开发自己的IDE(五)

开发自己的IDE(五)
    休息了大半个月,没写自己的代码了。国庆过了,再不为自己写写代码就有负罪感了。这篇文章所提到的所有工具的代码都可以在 Vczh Library++ 3.0的页面找到。 上一篇文章提到了一个状态机绘图工具,直到最近我终于把他的第一个部分给做好了。现在可以画图之后产生一个可以供 这里所描述的高亮控件所使用的着色器了。第一步我们要使用TokenizerBuilder绘制一个状态机:
开发自己的IDE(五)_第1张图片

    然后点击“Generate to Clipboard”按钮,就会要求你输入一个类名然后产生着色器插件的代码了。上面这个是一个简化过的C#代码着色状态机,其中Id有个星号代表不是所有走到这个状态的东西都可以叫Id(其实是关键字,懒得改了)。中括号里面的是颜色的名称。这些名称最终是要拿来生成代码的,所以必须是C#接受的可以拿来做变量名的东西,不过我也没检查,只管拼接字符串生成。

    我把生成后的代码贴在了CodeForm工程的CSharpTokenizer.Generated.cs里:

开发自己的IDE(五)_第2张图片

    第三步就是要自己建立一个CSharpColorizer.Configuration.cs了。C#的partial class真是伟大,简直就是为了代码生成而设计出来的。在这里我们看看生成后的CSharpColorizer.Generated.cs的代码:
  1  using  System;
  2  using  System.Collections.Generic;
  3  using  System.Linq;
  4  using  System.Text;
  5  using  CodeBoxControl;
  6  using  System.Drawing;
  7 
  8  namespace  CodeForm
  9  {
 10      partial  class  CSharpColorizer : ITextEditorColorizer
 11      {
 12           // public const int NormalColorId = 0;
 13           public   const   int  IdColorId  =  NormalColorId  +   1 ;
 14           public   const   int  StringColorId  =  NormalColorId  +   2 ;
 15           public   const   int  CommentColorId  =  NormalColorId  +   3 ;
 16 
 17           // private readonly Color HighlightColor = Color.FromArgb(173, 214, 255);
 18           // private readonly Color NormalColor = Color.FromArgb(0, 0, 0);
 19           // private readonly Color IdColor = Color.FromArgb(0, 0, 0);
 20           // private readonly Color StringColor = Color.FromArgb(0, 0, 0);
 21           // private readonly Color CommentColor = Color.FromArgb(0, 0, 0);
 22 
 23           private   const   int  StartState  =   0 ;
 24           private   const   int  NormalState  =   1 ;
 25           private   const   int  IdStateId  =   2 ;
 26           private   const   int  InStringStateId  =   3 ;
 27           private   const   int  InStringEscapingStateId  =   4 ;
 28           private   const   int  InCharStateId  =   5 ;
 29           private   const   int  InCharEscapingStateId  =   6 ;
 30           private   const   int  StringStateId  =   7 ;
 31           private   const   int  CommentStartStateId  =   8 ;
 32           private   const   int  SingleLineCommentStateId  =   9 ;
 33           private   const   int  InMultipleLineCommentStateId  =   10 ;
 34           private   const   int  InMultipleLineCommentWaitingToFinishStateId  =   11 ;
 35           private   const   int  MultipleLineCommentStateId  =   12 ;
 36 
 37           private  TextEditorColorItem[] colorItems  =   new  TextEditorColorItem[NormalColorId  +   4 ];
 38           private   int [] charset  =   new   int [ 65536 ];
 39           private   int [,] transitions  =   new   int [ 13 11 ];
 40           private   bool [] finalStates  =   new   bool [ 13 ];
 41           private   int [] stateColors  =   new   int [ 13 ];
 42 
 43           public  TextEditorColorItem[] ColorItems
 44          {
 45               get
 46              {
 47                   return   this .colorItems;
 48              }
 49          }
 50 
 51           public  CSharpColorizer()
 52          {
 53               this .colorItems[NormalColorId]  =   new  TextEditorColorItem()
 54              {
 55                  Text  =  NormalColor,
 56                  HighlightText  =  NormalColor,
 57                  Highlight  =  HighlightColor
 58              };
 59               this .colorItems[IdColorId]  =   new  TextEditorColorItem()
 60              {
 61                  Text  =  IdColor,
 62                  HighlightText  =  IdColor,
 63                  Highlight  =  HighlightColor
 64              };
 65               this .colorItems[StringColorId]  =   new  TextEditorColorItem()
 66              {
 67                  Text  =  StringColor,
 68                  HighlightText  =  StringColor,
 69                  Highlight  =  HighlightColor
 70              };
 71               this .colorItems[CommentColorId]  =   new  TextEditorColorItem()
 72              {
 73                  Text  =  CommentColor,
 74                  HighlightText  =  CommentColor,
 75                  Highlight  =  HighlightColor
 76              };
 77               //  You should write your own CreateAdditionalColors() implementation to add additional colors.
 78               //  You can modify the NormalColorId and put all additional colors ids before NormalColorId.
 79               //  It is recommended to use another partial class to store all customized code.
 80              CreateAdditionalColors();
 81              CreateStateMachine();
 82          }
 83           public   int  ColorizeLine( char [] items,  int  length,  int  initialState,  int [] colors)
 84          {
 85               int  state  =  initialState;
 86               int  itemStart  =   0 ;
 87               int  lastFinalState  =  StartState;
 88 
 89               for  ( int  i  =   0 ; i  <=  length; i ++ )
 90              {
 91                   if  (i  !=  length)
 92                  {
 93                      state  =  transitions[state, charset[items[i]]];
 94                       if  (state  ==  StartState)
 95                      {
 96                          state  =  transitions[state, charset[items[i]]];
 97                      }
 98                  }
 99                   else
100                  {
101                      lastFinalState  =  state;
102                  }
103 
104                   if  (i  ==  length  ||  lastFinalState  !=  state  &&  lastFinalState  !=  StartState)
105                  {
106                       int  color  =  stateColors[lastFinalState];
107                       switch  (lastFinalState)
108                      {
109                           case  IdStateId:
110                               //  You should write your own IsValidId implementation.
111                              color  =  IsValidId( new   string (items, itemStart, Math.Min(i, length)  -  itemStart))  ?  stateColors[lastFinalState] : NormalColorId;
112                               break ;
113                      }
114                       for  ( int  j  =  itemStart; j  <  i; j ++ )
115                      {
116                          colors[j]  =  color;
117                      }
118                      itemStart  =  i;
119                  }
120                  lastFinalState  =  finalStates[state]  ?  state : StartState;
121              }
122 
123               return  transitions[state, charset[ ' \n ' ]];
124          }
125 
126           private   void  CreateStateMachine()
127          {
128               for  ( int  i  =   0 ; i  <   10 ; i ++ )
129                  charset[i]  =   0 ;
130               for  ( int  i  =   10 ; i  <   11 ; i ++ )
131                  charset[i]  =   1 ;
132               for  ( int  i  =   11 ; i  <   34 ; i ++ )
133                  charset[i]  =   0 ;
134               for  ( int  i  =   34 ; i  <   35 ; i ++ )
135                  charset[i]  =   2 ;
136               for  ( int  i  =   35 ; i  <   36 ; i ++ )
137                  charset[i]  =   3 ;
138               for  ( int  i  =   36 ; i  <   39 ; i ++ )
139                  charset[i]  =   0 ;
140               for  ( int  i  =   39 ; i  <   40 ; i ++ )
141                  charset[i]  =   4 ;
142               for  ( int  i  =   40 ; i  <   42 ; i ++ )
143                  charset[i]  =   0 ;
144               for  ( int  i  =   42 ; i  <   43 ; i ++ )
145                  charset[i]  =   5 ;
146               for  ( int  i  =   43 ; i  <   47 ; i ++ )
147                  charset[i]  =   0 ;
148               for  ( int  i  =   47 ; i  <   48 ; i ++ )
149                  charset[i]  =   6 ;
150               for  ( int  i  =   48 ; i  <   58 ; i ++ )
151                  charset[i]  =   7 ;
152               for  ( int  i  =   58 ; i  <   65 ; i ++ )
153                  charset[i]  =   0 ;
154               for  ( int  i  =   65 ; i  <   91 ; i ++ )
155                  charset[i]  =   8 ;
156               for  ( int  i  =   91 ; i  <   92 ; i ++ )
157                  charset[i]  =   0 ;
158               for  ( int  i  =   92 ; i  <   93 ; i ++ )
159                  charset[i]  =   9 ;
160               for  ( int  i  =   93 ; i  <   95 ; i ++ )
161                  charset[i]  =   0 ;
162               for  ( int  i  =   95 ; i  <   96 ; i ++ )
163                  charset[i]  =   8 ;
164               for  ( int  i  =   96 ; i  <   97 ; i ++ )
165                  charset[i]  =   0 ;
166               for  ( int  i  =   97 ; i  <   123 ; i ++ )
167                  charset[i]  =   8 ;
168               for  ( int  i  =   123 ; i  <   65536 ; i ++ )
169                  charset[i]  =   0 ;
170 
171              finalStates[ 0 =   false ;
172              finalStates[ 1 =   true ;
173              finalStates[ 2 =   true ;
174              finalStates[ 3 =   false ;
175              finalStates[ 4 =   false ;
176              finalStates[ 5 =   false ;
177              finalStates[ 6 =   false ;
178              finalStates[ 7 =   true ;
179              finalStates[ 8 =   false ;
180              finalStates[ 9 =   true ;
181              finalStates[ 10 =   false ;
182              finalStates[ 11 =   false ;
183              finalStates[ 12 =   true ;
184 
185              stateColors[ 0 =  NormalColorId  +   0 ;
186              stateColors[ 1 =  NormalColorId  +   0 ;
187              stateColors[ 2 =  NormalColorId  +   1 ;
188              stateColors[ 3 =  NormalColorId  +   2 ;
189              stateColors[ 4 =  NormalColorId  +   2 ;
190              stateColors[ 5 =  NormalColorId  +   2 ;
191              stateColors[ 6 =  NormalColorId  +   2 ;
192              stateColors[ 7 =  NormalColorId  +   2 ;
193              stateColors[ 8 =  NormalColorId  +   0 ;
194              stateColors[ 9 =  NormalColorId  +   3 ;
195              stateColors[ 10 =  NormalColorId  +   3 ;
196              stateColors[ 11 =  NormalColorId  +   3 ;
197              stateColors[ 12 =  NormalColorId  +   3 ;
198 
199              transitions[ 0 0 =   1 ;
200              transitions[ 0 1 =   1 ;
201              transitions[ 0 2 =   3 ;
202              transitions[ 0 3 =   2 ;
203              transitions[ 0 4 =   5 ;
204              transitions[ 0 5 =   1 ;
205              transitions[ 0 6 =   8 ;
206              transitions[ 0 7 =   1 ;
207              transitions[ 0 8 =   2 ;
208              transitions[ 0 9 =   1 ;
209              transitions[ 0 10 =   1 ;
210              transitions[ 1 0 =   0 ;
211              transitions[ 1 1 =   0 ;
212              transitions[ 1 2 =   0 ;
213              transitions[ 1 3 =   0 ;
214              transitions[ 1 4 =   0 ;
215              transitions[ 1 5 =   0 ;
216              transitions[ 1 6 =   0 ;
217              transitions[ 1 7 =   0 ;
218              transitions[ 1 8 =   0 ;
219              transitions[ 1 9 =   0 ;
220              transitions[ 1 10 =   0 ;
221              transitions[ 2 0 =   0 ;
222              transitions[ 2 1 =   0 ;
223              transitions[ 2 2 =   0 ;
224              transitions[ 2 3 =   0 ;
225              transitions[ 2 4 =   0 ;
226              transitions[ 2 5 =   0 ;
227              transitions[ 2 6 =   0 ;
228              transitions[ 2 7 =   2 ;
229              transitions[ 2 8 =   2 ;
230              transitions[ 2 9 =   0 ;
231              transitions[ 2 10 =   0 ;
232              transitions[ 3 0 =   3 ;
233              transitions[ 3 1 =   0 ;
234              transitions[ 3 2 =   7 ;
235              transitions[ 3 3 =   3 ;
236              transitions[ 3 4 =   3 ;
237              transitions[ 3 5 =   3 ;
238              transitions[ 3 6 =   3 ;
239              transitions[ 3 7 =   3 ;
240              transitions[ 3 8 =   3 ;
241              transitions[ 3 9 =   4 ;
242              transitions[ 3 10 =   0 ;
243              transitions[ 4 0 =   3 ;
244              transitions[ 4 1 =   0 ;
245              transitions[ 4 2 =   3 ;
246              transitions[ 4 3 =   3 ;
247              transitions[ 4 4 =   3 ;
248              transitions[ 4 5 =   3 ;
249              transitions[ 4 6 =   3 ;
250              transitions[ 4 7 =   3 ;
251              transitions[ 4 8 =   3 ;
252              transitions[ 4 9 =   3 ;
253              transitions[ 4 10 =   0 ;
254              transitions[ 5 0 =   5 ;
255              transitions[ 5 1 =   0 ;
256              transitions[ 5 2 =   5 ;
257              transitions[ 5 3 =   5 ;
258              transitions[ 5 4 =   7 ;
259              transitions[ 5 5 =   5 ;
260              transitions[ 5 6 =   5 ;
261              transitions[ 5 7 =   5 ;
262              transitions[ 5 8 =   5 ;
263              transitions[ 5 9 =   6 ;
264              transitions[ 5 10 =   0 ;
265              transitions[ 6 0 =   5 ;
266              transitions[ 6 1 =   0 ;
267              transitions[ 6 2 =   5 ;
268              transitions[ 6 3 =   5 ;
269              transitions[ 6 4 =   5 ;
270              transitions[ 6 5 =   5 ;
271              transitions[ 6 6 =   5 ;
272              transitions[ 6 7 =   5 ;
273              transitions[ 6 8 =   5 ;
274              transitions[ 6 9 =   5 ;
275              transitions[ 6 10 =   0 ;
276              transitions[ 7 0 =   0 ;
277              transitions[ 7 1 =   0 ;
278              transitions[ 7 2 =   0 ;
279              transitions[ 7 3 =   0 ;
280              transitions[ 7 4 =   0 ;
281              transitions[ 7 5 =   0 ;
282              transitions[ 7 6 =   0 ;
283              transitions[ 7 7 =   0 ;
284              transitions[ 7 8 =   0 ;
285              transitions[ 7 9 =   0 ;
286              transitions[ 7 10 =   0 ;
287              transitions[ 8 0 =   1 ;
288              transitions[ 8 1 =   1 ;
289              transitions[ 8 2 =   1 ;
290              transitions[ 8 3 =   1 ;
291              transitions[ 8 4 =   1 ;
292              transitions[ 8 5 =   10 ;
293              transitions[ 8 6 =   9 ;
294              transitions[ 8 7 =   1 ;
295              transitions[ 8 8 =   1 ;
296              transitions[ 8 9 =   1 ;
297              transitions[ 8 10 =   1 ;
298              transitions[ 9 0 =   9 ;
299              transitions[ 9 1 =   0 ;
300              transitions[ 9 2 =   9 ;
301              transitions[ 9 3 =   9 ;
302              transitions[ 9 4 =   9 ;
303              transitions[ 9 5 =   9 ;
304              transitions[ 9 6 =   9 ;
305              transitions[ 9 7 =   9 ;
306              transitions[ 9 8 =   9 ;
307              transitions[ 9 9 =   9 ;
308              transitions[ 9 10 =   0 ;
309              transitions[ 10 0 =   10 ;
310              transitions[ 10 1 =   10 ;
311              transitions[ 10 2 =   10 ;
312              transitions[ 10 3 =   10 ;
313              transitions[ 10 4 =   10 ;
314              transitions[ 10 5 =   11 ;
315              transitions[ 10 6 =   0 ;
316              transitions[ 10 7 =   10 ;
317              transitions[ 10 8 =   10 ;
318              transitions[ 10 9 =   10 ;
319              transitions[ 10 10 =   0 ;
320              transitions[ 11 0 =   10 ;
321              transitions[ 11 1 =   10 ;
322              transitions[ 11 2 =   10 ;
323              transitions[ 11 3 =   10 ;
324              transitions[ 11 4 =   10 ;
325              transitions[ 11 5 =   10 ;
326              transitions[ 11 6 =   12 ;
327              transitions[ 11 7 =   10 ;
328              transitions[ 11 8 =   10 ;
329              transitions[ 11 9 =   10 ;
330              transitions[ 11 10 =   0 ;
331              transitions[ 12 0 =   0 ;
332              transitions[ 12 1 =   0 ;
333              transitions[ 12 2 =   0 ;
334              transitions[ 12 3 =   0 ;
335              transitions[ 12 4 =   0 ;
336              transitions[ 12 5 =   0 ;
337              transitions[ 12 6 =   0 ;
338              transitions[ 12 7 =   0 ;
339              transitions[ 12 8 =   0 ;
340              transitions[ 12 9 =   0 ;
341              transitions[ 12 10 =   0 ;
342          }
343      }
344  }
345 

    这是一个典型的状态机,里面定义了所有状态、颜色和对外可见的颜色标号。这里使用partial class是因为颜色是要你自己填写的,因此你可以看见我在代码的一开始注释掉了几行,所以他们就会出现在CSharpColorizer.Configuration.cs里:
  1  using  System;
  2  using  System.Collections.Generic;
  3  using  System.Linq;
  4  using  System.Text;
  5  using  CodeBoxControl;
  6  using  System.Drawing;
  7 
  8  namespace  CodeForm
  9  {
 10      partial  class  CSharpColorizer
 11      {
 12           public   const   int  BreakPointColorId  =   0 ;
 13           public   const   int  BlockPointColorId  =   1 ;
 14           public   const   int  NormalColorId  =   2 ;
 15 
 16           private   readonly  Color HighlightColor  =  Color.FromArgb( 173 214 255 );
 17           private   readonly  Color NormalColor  =  Color.FromArgb( 0 0 0 );
 18           private   readonly  Color IdColor  =  Color.FromArgb( 0 0 255 );
 19           private   readonly  Color StringColor  =  Color.FromArgb( 163 21 21 );
 20           private   readonly  Color CommentColor  =  Color.FromArgb( 0 128 0 );
 21 
 22           private   readonly  Color BreakPointColor  =  Color.FromArgb( 255 255 255 );
 23           private   readonly  Color BreakPointHighlightColor  =  Color.FromArgb( 123 119 166 );
 24           private   readonly  Color BlockPointColor  =  Color.Gray;
 25 
 26           private   void  CreateAdditionalColors()
 27          {
 28               this .colorItems[BreakPointColorId]  =   new  TextEditorColorItem()
 29              {
 30                  Text  =  BreakPointColor,
 31                  HighlightText  =  BreakPointColor,
 32                  Highlight  =  BreakPointHighlightColor
 33              };
 34               this .colorItems[BlockPointColorId]  =   new  TextEditorColorItem()
 35              {
 36                  Text  =  BlockPointColor,
 37                  HighlightText  =  BlockPointColor,
 38                  Highlight  =  HighlightColor
 39              };
 40          }
 41 
 42           private   bool  IsValidId( string  token)
 43          {
 44               return  token[ 0 ==   ' # '   ||  Array.BinarySearch(keywords, token)  >=   0 ;
 45          }
 46 
 47           private   static   string [] keywords  = {
 48               " abstract " ,
 49               " as " ,
 50               " base " ,
 51               " bool " ,
 52               " break " ,
 53               " byte " ,
 54               " case " ,
 55               " catch " ,
 56               " char " ,
 57               " checked " ,
 58               " class " ,
 59               " const " ,
 60               " continue " ,
 61               " decimal " ,
 62               " default " ,
 63               " delegate " ,
 64               " do " ,
 65               " double " ,
 66               " else " ,
 67               " enum " ,
 68               " event " ,
 69               " explicit " ,
 70               " extern " ,
 71               " false " ,
 72               " finally " ,
 73               " fixed " ,
 74               " float " ,
 75               " for " ,
 76               " foreach " ,
 77               " goto " ,
 78               " if " ,
 79               " implicit " ,
 80               " in " ,
 81               " int " ,
 82               " interface " ,
 83               " internal " ,
 84               " is " ,
 85               " lock " ,
 86               " long " ,
 87               " namespace " ,
 88               " new " ,
 89               " null " ,
 90               " object " ,
 91               " operator " ,
 92               " out " ,
 93               " override " ,
 94               " params " ,
 95               " private " ,
 96               " protected " ,
 97               " public " ,
 98               " readonly " ,
 99               " ref " ,
100               " return " ,
101               " sbyte " ,
102               " sealed " ,
103               " short " ,
104               " sizeof " ,
105               " stackalloc " ,
106               " static " ,
107               " string " ,
108               " struct " ,
109               " switch " ,
110               " this " ,
111               " throw " ,
112               " true " ,
113               " try " ,
114               " typeof " ,
115               " unit " ,
116               " ulong " ,
117               " unchecked " ,
118               " unsafe " ,
119               " ushort " ,
120               " using " ,
121               " virtual " ,
122               " void " ,
123               " volatile " ,
124               " while "
125          };
126      }
127  }
128 

    这个Configuration做了三件事情。第一、定义了额外的颜色。在这里我们修改了NormalColorId,这是系统颜色的第一个颜色序号。我们只需要修改了它,然后把自己的颜色加在它前面就行了。第二件事情是定义了什么是Id。我们在Id状态里打了个星号,那么生成的代码就会要求我们实现一个IsValidId函数。第三件事情就是我们指定了所有记号的真正的颜色。

    为什么要做成partial class呢?我们可以很容易看出来,每一次生成代码的时候,我们只需要修改namespace和类名以及注释掉NormalColorId和所有颜色的声明,就可以让我们的自定义部分得到保留。这无疑很方便我们对着色器进行修改。只需要修改一下状态机,生成一份代码,再做一点很小的改动就行了。

    最重要的是,这个着色器的性能跟 手写的基本一样优秀,因此从现在开始,我们开发一个上下文无关的着色器控件就基本不需要写代码了,只要是用Vczh Library++ 3.0实验库里面的TextEditorControl,再用这个TokenizerBuilder画个状态机生成个着色器的代码就搞定了,哇哈哈。下面要做的就是增强TokenizerBuilder,从状态机生成词法分析器了,然后就可以继续智能提示的实验了。

你可能感兴趣的:(开发自己的IDE(五))