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

隨筆-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>
            欧美 日韩 国产一区二区在线视频| 韩国视频理论视频久久| 亚洲一二三区在线观看| 91久久精品日日躁夜夜躁欧美 | 久久亚洲私人国产精品va媚药| 午夜精品视频网站| 久久久久久伊人| 欧美va日韩va| 国产精品激情偷乱一区二区∴| 国产精品美女www爽爽爽视频| 国产精品看片你懂得| 国产一区二区毛片| 亚洲精品麻豆| 亚洲一区二区在线看| 久久爱www.| 欧美激情2020午夜免费观看| 亚洲免费久久| 久久成人精品一区二区三区| 久久在线精品| 国产精品久久久对白| 狠狠色狠狠色综合系列| 99riav1国产精品视频| 亚洲欧美日韩中文视频| 美国成人直播| 一区二区三区成人| 久久久亚洲午夜电影| 国产精品国产三级国产普通话三级 | 日韩手机在线导航| 欧美在线视频不卡| 亚洲精品一线二线三线无人区| 午夜视频一区二区| 欧美日韩三级在线| 欧美承认网站| 国产精品自拍一区| 亚洲日本欧美天堂| 久久亚洲风情| 国产精品99久久久久久久久久久久| 久久久国产精品亚洲一区| 国产精品分类| 亚洲最新色图| 亚洲国产精品va| 久久久久久久一区二区三区| 国产精品素人视频| 一区二区三区四区五区在线| 亚洲电影欧美电影有声小说| 欧美在线综合| 国产精品一区二区你懂得| 亚洲深夜福利| 日韩视频免费| 欧美日韩国产限制| 一区二区动漫| 一本色道**综合亚洲精品蜜桃冫 | 久久久噜噜噜久久狠狠50岁| 欧美体内she精视频在线观看| 亚洲人成在线播放| 欧美激情综合| 欧美精品一区二区三区蜜臀 | 国产精品一区在线观看| 亚洲小说区图片区| 日韩午夜三级在线| 欧美日韩在线电影| 亚洲欧美日韩国产| 亚洲欧美日韩国产中文| 国产欧美一区二区精品秋霞影院| 性欧美激情精品| 亚洲欧美日韩国产成人精品影院| 国产精品永久入口久久久| 久久av一区二区三区漫画| 欧美中文日韩| 亚洲国产精品视频| 99riav国产精品| 国产精品第十页| 久久国产精品72免费观看| 久久精品噜噜噜成人av农村| 亚洲激情午夜| 一本色道**综合亚洲精品蜜桃冫| 国产精品卡一卡二卡三| 久久精品理论片| 免费看黄裸体一级大秀欧美| 夜夜嗨av一区二区三区免费区| 一区二区三区精品| 国产一区二区三区四区五区美女| 欧美不卡在线| 欧美日韩直播| 久久人人爽人人爽爽久久| 久久资源在线| 国产精品一区=区| 国产精品天美传媒入口| 精品va天堂亚洲国产| 麻豆成人在线播放| 欧美女同在线视频| 久久国产精品免费一区| 欧美电影专区| 久久av一区二区三区| 欧美v亚洲v综合ⅴ国产v| 亚洲欧美精品中文字幕在线| 久久精品国产综合精品| 一本色道久久综合亚洲精品高清| 欧美一区二区免费| 在线一区二区三区四区五区| 欧美在线二区| 亚洲一区观看| 蜜臀久久久99精品久久久久久| 亚洲欧美激情在线视频| 欧美1区2区| 午夜欧美精品| 欧美美女操人视频| 久久欧美肥婆一二区| 欧美新色视频| 亚洲欧洲精品成人久久奇米网| 国产亚洲一本大道中文在线| 日韩亚洲成人av在线| 91久久精品国产91久久性色| 欧美一区二区成人6969| 亚洲欧美日韩国产一区| 欧美黄色一区二区| 美女精品在线| 国产精品日本欧美一区二区三区| 欧美gay视频| 国产午夜精品美女视频明星a级| 亚洲欧洲精品一区二区| 亚洲国产精品一区二区三区| 欧美一区二区精品久久911| 亚洲欧美一区二区三区极速播放| 欧美成人免费全部观看天天性色| 久久久91精品国产| 国产精品永久| 亚洲自拍偷拍网址| 亚洲一级在线| 欧美日韩亚洲一区二区三区四区| 欧美黄色免费| 亚洲人成免费| 欧美二区乱c少妇| 亚洲电影第三页| 亚洲免费观看| 欧美日韩视频| 亚洲午夜羞羞片| 欧美亚洲网站| 国产亚洲一区二区在线观看 | 久久免费一区| 国产亚洲综合在线| 欧美在线免费视频| 免费欧美日韩| 亚洲片在线观看| 欧美+亚洲+精品+三区| 欧美黄色小视频| 亚洲免费观看高清完整版在线观看| 麻豆视频一区二区| 亚洲精品美女在线| 亚洲社区在线观看| 激情综合网激情| 久久露脸国产精品| 欧美成人亚洲成人| 亚洲日本在线观看| 欧美日韩精品在线播放| av成人免费在线观看| 午夜视频一区二区| 国内伊人久久久久久网站视频 | 亚洲精品一区在线| 欧美日韩精品一区二区在线播放| 亚洲最快最全在线视频| 性欧美xxxx大乳国产app| 韩日精品视频| 欧美精品在线播放| 香蕉久久夜色精品| 亚洲电影免费观看高清完整版在线观看 | 欧美一区91| 一区在线播放| 欧美日产一区二区三区在线观看| 亚洲午夜一级| 欧美大片免费久久精品三p | 欧美激情亚洲视频| 一区二区三区av| 蜜桃精品一区二区三区 | 在线精品福利| 欧美日韩一二三四五区| 欧美一区二区三区播放老司机| 亚洲成色最大综合在线| 麻豆91精品| 亚洲免费福利视频| 国产一区二区三区电影在线观看| 欧美成人激情视频免费观看| 亚洲一区二区在线观看视频| 欧美成人三级在线| 欧美一区二区三区四区夜夜大片 | 欧美成人亚洲成人| 亚洲免费人成在线视频观看| 欧美大片91| 久久精品99国产精品| 一区二区久久久久| 亚洲成色精品| 国产一区二区成人| 国产精品久久久久秋霞鲁丝| 欧美不卡视频一区发布| 欧美中文在线免费| 亚洲免费视频一区二区| 一本色道久久综合| 亚洲日本成人网| 欧美二区在线| 另类图片国产|