青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-341  評論-2670  文章-0  trackbacks-0

    詞法分析器生成器終于做好了,因此我又畫了一個狀態機然后生成了一個詞法分析器,因此開始研究IDE的智能提示的技術了。智能提示的技術有幾個要點,第一個是無論怎么慢都不能妨礙你打字,第二個是崩潰了也不能讓IDE關掉,要重啟分析器。因此我做了一個小實驗。首先我將NativeX語言的著色器跟詞法分析器都做好了,因此我要做的事情就是在你打字的時候,用另外一個線程進行詞法分析,得到結果之后用一個框框來展示出光標所在的那個token:




    注意光標所在的位置是在方框的內部。為了實現這個過程,首先我們要一個安全的多線程機制。我們把詞法分析作為一個請求來看,在打字的過程中我們就不斷把請求發送到詞法分析器頭上,然后詞法分析器分析完了就會發個消息給窗口然后傳送結果。我們注意到如果打字太快導致來不及處理的話,可能會積累若干個請求,不過那些請求實際上只有最后一個需要被處理,之前的那些來不及處理的舊請求都會被忽略。反正我們的字已經打完了,詞法分析器就不需要分析那些我們還沒打完的字了。因此我們把它抽象一下:

    我們有一個請求的類,這個類需要的數據有輸入類型、輸出類型、計算方法以及傳送方法。為什么要傳送方法呢?因為計算是在另外一個線程完成的,因此在調用傳送方法的時候也是在另外一個線程完成的,所以我們得提供一個函數來接受分析后的結果,然后用一種安全的方法傳送到我們想要的地方去。因此我們就把這個過程分成了兩個類,一個處理多線程的問題的抽象類,和一個用來提供計算方法和傳送方法的子類:
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading;
 6 
 7 namespace CodeBoxControl
 8 {
 9     public abstract class CalculationNotifier<I, O> : IDisposable
10     {
11         private Thread workingThread = null;
12         private I analyzingInput = default(I);
13         private bool analyzingInputAvailable = false;
14         private Semaphore codeSemaphore = null;
15         private object locker = null;
16 
17         public CalculationNotifier()
18         {
19             this.locker = new object();
20             this.codeSemaphore = new Semaphore(01);
21             this.workingThread = new Thread(Run);
22             this.workingThread.Start();
23         }
24 
25         public void Analyze(I input)
26         {
27             bool needRelease = false;
28             lock (this.locker)
29             {
30                 if (!this.analyzingInputAvailable)
31                 {
32                     needRelease = true;
33                 }
34                 this.analyzingInputAvailable = true;
35                 this.analyzingInput = input;
36             }
37             if (needRelease)
38             {
39                 this.codeSemaphore.Release(1);
40             }
41         }
42 
43         public void Dispose()
44         {
45             this.workingThread.Abort();
46             this.codeSemaphore.Dispose();
47         }
48 
49         protected abstract O Calculate(I input);
50         protected abstract void Receive(O output);
51 
52         private void Run()
53         {
54             while (true)
55             {
56                 this.codeSemaphore.WaitOne();
57                 I input = default(I);
58                 lock (this.locker)
59                 {
60                     input = this.analyzingInput;
61                     this.analyzingInputAvailable = false;
62                 }
63                 O output = Calculate(input);
64                 Receive(output);
65             }
66         }
67     }
68 }
69 

    怎么使用它呢?我們只需要不斷地把數據發送給Analyze函數,那個函數就會自動替我們處理好跟同步相關的所有問題了,然后在另外一個線程調用分析函數和返回結果:
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using CodeBoxControl;
 6 using CodeBoxControl.CodeProvider;
 7 
 8 namespace CodeForm
 9 {
10     class NativeXAnalyzingResult
11     {
12         public List<CodeToken> Tokens { getset; }
13     }
14 
15     interface INativeXAnalyzingResultReceiver
16     {
17         void Receive(NativeXAnalyzingResult result);
18     }
19 
20     class NativeXCodeAnalyzer : CalculationNotifier<string, NativeXAnalyzingResult>
21     {
22         private NativeXTokenizer tokenizer = new NativeXTokenizer();
23         private INativeXAnalyzingResultReceiver receiver = null;
24 
25         public NativeXCodeAnalyzer(INativeXAnalyzingResultReceiver receiver)
26         {
27             this.receiver = receiver;
28         }
29 
30         protected override NativeXAnalyzingResult Calculate(string input)
31         {
32             NativeXAnalyzingResult result = new NativeXAnalyzingResult();
33             result.Tokens = this.tokenizer.Tokenize(input.ToCharArray());
34             return result;
35         }
36 
37         protected override void Receive(NativeXAnalyzingResult output)
38         {
39             this.receiver.Receive(output);
40         }
41     }
42 }
43 

    這個類就是用來負責做詞法分析的了。當然我們注意到此時接受數據的過程還是被抽象掉了,因為這個過程實際上應該讓插件去處理,因為插件才知道要怎么畫框。目前的控件支持兩個插件,一個是著色器,另一個是監視器。監視器負責監聽字符串的改變和插手繪圖的過程,我們可以看出這個插件是如何把詞法分析結果和畫框框聯系在一起的:
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using CodeBoxControl;
  6 using System.Windows.Forms;
  7 using CodeBoxControl.Core;
  8 using CodeBoxControl.CodeProvider;
  9 using System.Drawing;
 10 
 11 namespace CodeForm
 12 {
 13     class NativeXControlPanel
 14         : ITextEditorControlPanel
 15         , INativeXAnalyzingResultReceiver
 16         , IDisposable
 17     {
 18         private ITextEditorControlPanelCallBack callback = null;
 19         private NativeXAnalyzingResult analyzingResult = null;
 20         private NativeXCodeAnalyzer analyzer = null;
 21 
 22         private TextPosition grayStart = new TextPosition(00);
 23         private TextPosition grayEnd = new TextPosition(00);
 24 
 25         public int Width
 26         {
 27             get
 28             {
 29                 return 0;
 30             }
 31         }
 32 
 33         public void InstallCallBack(ITextEditorControlPanelCallBack callback)
 34         {
 35             this.analyzer = new NativeXCodeAnalyzer(this);
 36             this.callback = callback;
 37             this.callback.TextEditorBox.SelectionChanged += new EventHandler(TextEditorBox_SelectionChanged);
 38         }
 39 
 40         public void OnEdit(CodeBoxControl.Core.TextPosition start, CodeBoxControl.Core.TextPosition oldEnd, CodeBoxControl.Core.TextPosition newEnd)
 41         {
 42             this.analyzer.Analyze(this.callback.TextEditorBox.Text);
 43         }
 44 
 45         public bool NeedColorLineForDisplay(int lineIndex)
 46         {
 47             return this.grayStart != this.grayEnd && this.grayStart.row <= lineIndex && lineIndex <= this.grayEnd.row;
 48         }
 49 
 50         public void ColorLineForDisplay(int lineIndex, int[] colors)
 51         {
 52             TextLine<TextEditorBox.LineInfo> line = this.callback.TextEditorBox.TextProvider[lineIndex];
 53             int length = line.CharCount;
 54 
 55             int start = grayStart.row == lineIndex ? Math.Min(grayStart.col, length) : 0;
 56             int end = grayEnd.row == lineIndex ? Math.Min(grayEnd.col, length) : line.CharCount;
 57             for (int i = start; i < end; i++)
 58             {
 59                 colors[i] = NativeXColorizer.BlockPointColorId;
 60             }
 61         }
 62 
 63         public void DrawLineBackground(Graphics g, int lineIndex, Rectangle backgroundArea)
 64         {
 65         }
 66 
 67         public void DrawLineForeground(Graphics g, int lineIndex, Rectangle backgroundArea)
 68         {
 69             if (NeedColorLineForDisplay(lineIndex))
 70             {
 71                 TextLine<TextEditorBox.LineInfo> line = this.callback.TextEditorBox.TextProvider[lineIndex];
 72                 int length = line.CharCount;
 73                 int start = grayStart.row == lineIndex ? Math.Min(grayStart.col, length) : 0;
 74                 int end = grayEnd.row == lineIndex ? Math.Min(grayEnd.col, length) : line.CharCount;
 75 
 76                 int x1 = this.callback.TextEditorBox.TextPositionToViewPoint(new TextPosition(lineIndex, start)).X;
 77                 int x2 = this.callback.TextEditorBox.TextPositionToViewPoint(new TextPosition(lineIndex, end)).X;
 78                 g.DrawRectangle(Pens.Gray, x1, backgroundArea.Top, x2 - x1, backgroundArea.Height);
 79             }
 80         }
 81 
 82         public void DrawControlPanel(Graphics g, int lineIndex, Rectangle controlPanelArea)
 83         {
 84         }
 85 
 86         public void DrawControlPanelBackground(Graphics g, Rectangle backgroundArea)
 87         {
 88         }
 89 
 90         public void OnMouseDown(int lineIndex, Rectangle controlPanelArea, Point relativePosition, System.Windows.Forms.MouseButtons buttons)
 91         {
 92         }
 93 
 94         public void OnMouseMove(int lineIndex, Rectangle controlPanelArea, Point relativePosition, System.Windows.Forms.MouseButtons buttons)
 95         {
 96         }
 97 
 98         public void OnMouseUp(int lineIndex, Rectangle controlPanelArea, Point relativePosition, System.Windows.Forms.MouseButtons buttons)
 99         {
100         }
101 
102         public void Receive(NativeXAnalyzingResult result)
103         {
104             this.callback.TextEditorBox.Invoke(new MethodInvoker(() =>
105             {
106                 this.analyzingResult = result;
107                 UpdateBlock();
108             }));
109         }
110 
111         public void Dispose()
112         {
113             this.analyzer.Dispose();
114         }
115 
116         private void UpdateBlock()
117         {
118             NativeXAnalyzingResult result = this.analyzingResult;
119             TextPosition pos = this.callback.TextEditorBox.SelectionCaret;
120             if (result != null)
121             {
122                 foreach (CodeToken token in result.Tokens)
123                 {
124                     if (token.Start < pos && pos < token.End)
125                     {
126                         this.grayStart = token.Start;
127                         this.grayEnd = token.End;
128                         return;
129                     }
130                 }
131                 this.grayStart = new TextPosition(00);
132                 this.grayEnd = new TextPosition(00);
133             }
134         }
135 
136         private void TextEditorBox_SelectionChanged(object sender, EventArgs e)
137         {
138             UpdateBlock();
139         }
140     }
141 }
142 


    這里我們借助了System.Windows.Forms.Control.Invoke來將一整個閉包壓到了消息循環里面,然后消息循環來執行這個閉包,因此接收數據的過程就在UI線程上完成了。Invoke跟SendMessage其實是差不多的。我們還能看出這個插件的接口叫ControlPanel,所以是用來干預一切變化的。這里有Width屬性但是設置成0了,如果不是0的話就可以模仿VisualStudio左邊那個放斷點的控制欄了,這個在之前已經演示過了。

    到這里如何在非UI線程處理代碼的技術就介紹完了,現在讓我們來看著色器和詞法分析器的樣子哈。首先上著色器的狀態機:


    然后是詞法分析器的狀態機:


    至于他們生成的代碼,可以去Vczh Library++ 3.0這里看哈。

 

posted on 2010-10-14 08:23 陳梓瀚(vczh) 閱讀(5879) 評論(6)  編輯 收藏 引用 所屬分類: 開發自己的IDE

評論:
# re: 開發自己的IDE(六)[未登錄] 2010-10-14 08:33 | Lyt
看一次流一次口水…  回復  更多評論
  
# re: 開發自己的IDE(六) 2010-10-14 16:51 | Pear
MB真帥氣。。MB真帥氣。。真帥氣。。  回復  更多評論
  
# re: 開發自己的IDE(六) 2010-10-16 07:57 | mm
好強大!!!  回復  更多評論
  
# re: 開發自己的IDE(六) 2010-10-17 08:45 | hhh2000
圖有點小,有些符號看不清楚……

對著色器狀態機的圖有點疑問:1、如果CharIn是指單個字符的話,好像少了一個狀態。2、StringIn指向自己的邊是非 \ 和 " 號嗎(圖看不清)?這好像不大對吧。還

有單雙引號一般只影響本行,加上一個行尾的狀態約束一下,這樣在引號不匹配的情況下看起來會好一些。
  回復  更多評論
  
# re: 開發自己的IDE(六) 2010-10-19 01:41 | 陳梓瀚(vczh)
@hhh2000
為了簡單,char我還是允許他擁有多個字符了,反正對于一個字符的狀態可以正確解析,而且這是用在IDE上面的,勢必跟編譯器會有一些小的區別

StringIn那個東西是\.哈,也就是任意字符的意思。  回復  更多評論
  
# re: 開發自己的IDE(六) 2010-10-19 01:42 | 陳梓瀚(vczh)
@hhh2000
到了行末尾其實就是一個\n字符,只要你在狀態機上面把\n給排除了,自然就會只有一行了。  回復  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲欧美在线视频观看| 亚洲视频一区二区| 久久精品国产一区二区电影| 亚洲一区二区精品在线| 国产日韩综合一区二区性色av| 欧美一区二区三区免费观看| 午夜精品网站| 亚洲国产毛片完整版| 亚洲欧洲另类国产综合| 欧美网站在线| 久久久久久国产精品一区| 久久亚洲欧美国产精品乐播| 亚洲免费久久| 亚洲欧美另类在线| 亚洲茄子视频| 亚洲一区二区久久| 亚洲激情av在线| 中日韩美女免费视频网站在线观看| 国产精品亚洲人在线观看| 久久亚洲精选| 欧美日韩成人在线视频| 久久国产精品亚洲77777| 美日韩精品免费观看视频| 在线中文字幕不卡| 久久美女性网| 午夜免费日韩视频| 欧美韩日精品| 久久婷婷综合激情| 国产精品久久九九| 亚洲国产成人精品视频| 国产欧美va欧美不卡在线| 亚洲福利视频一区二区| 国产日本欧美一区二区三区| 亚洲国产一区视频| 国产婷婷一区二区| 夜夜嗨av色综合久久久综合网 | 亚洲特黄一级片| 亚洲第一区色| 亚洲人成人一区二区在线观看 | 免费短视频成人日韩| 欧美图区在线视频| 亚洲人午夜精品免费| 国产午夜精品久久久久久免费视| 亚洲精品综合精品自拍| 狠狠综合久久av一区二区小说 | 老司机精品导航| 中文国产成人精品| 国产精品视频不卡| 亚洲精品色婷婷福利天堂| 韩国av一区二区| 亚洲欧美伊人| 性做久久久久久久久| 欧美私人网站| 一本色道88久久加勒比精品 | 在线免费观看一区二区三区| 午夜精品久久久久久久| 亚洲女人小视频在线观看| 欧美日韩国产另类不卡| 亚洲国产三级| 一区二区高清视频在线观看| 欧美国产日韩一区二区三区| 欧美aⅴ99久久黑人专区| 国产一区免费视频| 久久国产精品久久久久久久久久| 欧美在线综合| 红桃视频欧美| 老巨人导航500精品| 免费永久网站黄欧美| 亚洲黄色精品| 欧美人成在线| 亚洲午夜av在线| 欧美中文字幕久久| 伊人夜夜躁av伊人久久| 久久综合亚洲社区| 亚洲日本国产| 欧美一级黄色网| 国产综合第一页| 蜜臀av一级做a爰片久久| 亚洲国产91| 亚洲在线1234| 精品91免费| 欧美护士18xxxxhd| 亚洲一区三区电影在线观看| 久久国产精品色婷婷| 亚洲国产成人在线| 欧美日韩国产高清| 欧美一级二级三级蜜桃| 亚洲第一精品久久忘忧草社区| 日韩视频在线播放| 国产精品v一区二区三区 | 亚洲精品影院| 久久国产夜色精品鲁鲁99| 激情懂色av一区av二区av| 欧美 日韩 国产在线| 亚洲午夜久久久久久久久电影院 | 蜜桃久久av一区| 一本久久综合| 黄色成人免费网站| 欧美日韩亚洲一区| 久久精品成人| 夜夜嗨av一区二区三区四季av | 亚洲精品中文字幕在线观看| 亚洲欧美一区二区精品久久久| 伊人久久成人| 欧美性天天影院| 免费成人黄色片| 性欧美暴力猛交69hd| 亚洲人成在线观看网站高清| 久久激情五月激情| 国产精品99久久久久久有的能看| 激情一区二区三区| 国产精品美女久久久久久久| 女女同性精品视频| 欧美一区二区三区免费视频| 亚洲另类视频| 亚洲国产小视频| 久久综合给合| 欧美一区二区三区免费观看视频| av成人老司机| 亚洲欧洲日产国码二区| 黄色成人91| 国产综合自拍| 国产欧美高清| 国产日韩高清一区二区三区在线| 欧美日韩不卡一区| 欧美激情视频给我| 免费亚洲一区二区| 久久综合999| 久久久久久久久久码影片| 欧美一级久久久久久久大片| 中文高清一区| 亚洲无玛一区| 亚洲一区二区少妇| 亚洲一级二级在线| 亚洲自拍三区| 亚洲欧美日韩综合国产aⅴ| 中日韩美女免费视频网站在线观看| 亚洲精品在线视频| 亚洲日本电影| 一本一本久久a久久精品牛牛影视| 亚洲欧洲视频在线| 亚洲日本va在线观看| 日韩午夜av在线| 一区二区三区四区国产| 一区二区精品国产| 亚洲深夜福利在线| 亚洲欧美一区二区三区极速播放| 亚洲一区二区综合| 欧美一区二区精美| 美女999久久久精品视频| 免费欧美电影| 欧美日韩在线直播| 国产精品一级| 韩国美女久久| 亚洲美女av黄| 亚洲曰本av电影| 久久九九国产| 亚洲第一黄网| 一区二区三区四区五区视频| 亚洲专区一区| 久久漫画官网| 欧美性开放视频| 国产女人精品视频| 亚洲国产美女久久久久 | 国产乱码精品1区2区3区| 国产日韩久久| 亚洲精品免费在线| 午夜精品久久久久久久99樱桃 | 亚洲一区在线观看免费观看电影高清| 亚洲欧美日本视频在线观看| 欧美制服第一页| 欧美精品国产| 国产一区二区三区成人欧美日韩在线观看 | 亚洲大胆人体在线| 中文日韩在线视频| 国产精品99久久久久久宅男 | 狠狠爱综合网| 亚洲午夜一二三区视频| 久久成人免费网| 亚洲区免费影片| 久久精品国产在热久久| 欧美激情中文字幕乱码免费| 国产日韩在线播放| 国产精品99久久99久久久二8| 久久久久久久综合| 一区二区精品在线| 女同性一区二区三区人了人一| 国产精品久久久一本精品| 亚洲国产成人av好男人在线观看| 亚洲一区在线直播| 欧美激情免费在线| 欧美专区18| 国产精品视频精品视频| 亚洲精品黄色| 麻豆成人在线播放| 午夜欧美精品| 国产精品久久一级| 一区二区三区久久| 亚洲精品国产精品国自产在线| 久久精品一级爱片|