OSDN Git Service

Commit DialogBox compile Okay
[tortoisegit/TortoiseGitJp.git] / ext / scintilla / src / LexVHDL.cxx
1 // Scintilla source code edit control\r
2 /** @file LexVHDL.cxx\r
3  ** Lexer for VHDL\r
4  ** Written by Phil Reid, \r
5  ** Based on:\r
6  **  - The Verilog Lexer by Avi Yegudin \r
7  **  - The Fortran Lexer by Chuan-jian Shen\r
8  **  - The C++ lexer by Neil Hodgson\r
9  **/\r
10 // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>\r
11 // The License.txt file describes the conditions under which this software may be distributed.\r
12 \r
13 #include <stdlib.h>\r
14 #include <string.h>\r
15 #include <ctype.h>\r
16 #include <stdio.h>\r
17 #include <stdarg.h>\r
18 \r
19 #include "Platform.h"\r
20 \r
21 #include "PropSet.h"\r
22 #include "Accessor.h"\r
23 #include "StyleContext.h"\r
24 #include "KeyWords.h"\r
25 #include "Scintilla.h"\r
26 #include "SciLexer.h"\r
27 \r
28 #ifdef SCI_NAMESPACE\r
29 using namespace Scintilla;\r
30 #endif\r
31 \r
32 static void ColouriseVHDLDoc(\r
33   unsigned int startPos,\r
34   int length,\r
35   int initStyle,\r
36   WordList *keywordlists[],\r
37   Accessor &styler);\r
38 \r
39 \r
40 /***************************************/\r
41 static inline bool IsAWordChar(const int ch) {\r
42   return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' );\r
43 }\r
44 \r
45 /***************************************/\r
46 static inline bool IsAWordStart(const int ch) {\r
47   return (ch < 0x80) && (isalnum(ch) || ch == '_');\r
48 }\r
49 \r
50 /***************************************/\r
51 inline bool IsABlank(unsigned int ch) {\r
52     return (ch == ' ') || (ch == 0x09) || (ch == 0x0b) ;\r
53 }\r
54 \r
55 /***************************************/\r
56 static void ColouriseVHDLDoc(\r
57   unsigned int startPos,\r
58   int length,\r
59   int initStyle,\r
60   WordList *keywordlists[],\r
61   Accessor &styler)\r
62 {\r
63   WordList &Keywords   = *keywordlists[0];\r
64   WordList &Operators  = *keywordlists[1];\r
65   WordList &Attributes = *keywordlists[2];\r
66   WordList &Functions  = *keywordlists[3];\r
67   WordList &Packages   = *keywordlists[4];\r
68   WordList &Types      = *keywordlists[5];\r
69   WordList &User       = *keywordlists[6];\r
70 \r
71   StyleContext sc(startPos, length, initStyle, styler);\r
72 \r
73   for (; sc.More(); sc.Forward())\r
74   {\r
75 \r
76     // Determine if the current state should terminate.\r
77     if (sc.state == SCE_VHDL_OPERATOR) {\r
78       sc.SetState(SCE_VHDL_DEFAULT);\r
79     } else if (sc.state == SCE_VHDL_NUMBER) {\r
80       if (!IsAWordChar(sc.ch) && (sc.ch != '#')) {\r
81         sc.SetState(SCE_VHDL_DEFAULT);\r
82       }\r
83     } else if (sc.state == SCE_VHDL_IDENTIFIER) {\r
84       if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {\r
85         char s[100];\r
86         sc.GetCurrentLowered(s, sizeof(s));\r
87         if (Keywords.InList(s)) {\r
88           sc.ChangeState(SCE_VHDL_KEYWORD);\r
89         } else if (Operators.InList(s)) {\r
90           sc.ChangeState(SCE_VHDL_STDOPERATOR);\r
91         } else if (Attributes.InList(s)) {\r
92           sc.ChangeState(SCE_VHDL_ATTRIBUTE);\r
93         } else if (Functions.InList(s)) {\r
94           sc.ChangeState(SCE_VHDL_STDFUNCTION);\r
95         } else if (Packages.InList(s)) {\r
96           sc.ChangeState(SCE_VHDL_STDPACKAGE);\r
97         } else if (Types.InList(s)) {\r
98           sc.ChangeState(SCE_VHDL_STDTYPE);\r
99         } else if (User.InList(s)) {\r
100           sc.ChangeState(SCE_VHDL_USERWORD);\r
101         }\r
102         sc.SetState(SCE_VHDL_DEFAULT);\r
103       }\r
104     } else if (sc.state == SCE_VHDL_COMMENT || sc.state == SCE_V_COMMENTLINEBANG) {\r
105       if (sc.atLineEnd) {\r
106         sc.SetState(SCE_VHDL_DEFAULT);\r
107       }\r
108     } else if (sc.state == SCE_VHDL_STRING) {\r
109       if (sc.ch == '\\') {\r
110         if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {\r
111           sc.Forward();\r
112         }\r
113       } else if (sc.ch == '\"') {\r
114         sc.ForwardSetState(SCE_VHDL_DEFAULT);\r
115       } else if (sc.atLineEnd) {\r
116         sc.ChangeState(SCE_V_STRINGEOL);\r
117         sc.ForwardSetState(SCE_VHDL_DEFAULT);\r
118       }\r
119     }\r
120 \r
121     // Determine if a new state should be entered.\r
122     if (sc.state == SCE_VHDL_DEFAULT) {\r
123       if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {\r
124         sc.SetState(SCE_VHDL_NUMBER);\r
125       } else if (IsAWordStart(sc.ch)) {\r
126         sc.SetState(SCE_VHDL_IDENTIFIER);\r
127       } else if (sc.Match('-', '-')) {\r
128         sc.SetState(SCE_VHDL_COMMENT);\r
129         sc.Forward(); \r
130       } else if (sc.Match('-', '-')) {\r
131         if (sc.Match("--!"))  // Nice to have a different comment style\r
132           sc.SetState(SCE_VHDL_COMMENTLINEBANG);\r
133         else\r
134           sc.SetState(SCE_VHDL_COMMENT);\r
135       } else if (sc.ch == '\"') {\r
136         sc.SetState(SCE_VHDL_STRING);\r
137       } else if (isoperator(static_cast<char>(sc.ch))) {\r
138         sc.SetState(SCE_VHDL_OPERATOR);\r
139       }\r
140     }\r
141   }\r
142   sc.Complete();\r
143 }\r
144 //=============================================================================\r
145 static bool IsCommentLine(int line, Accessor &styler) {\r
146         int pos = styler.LineStart(line);\r
147         int eol_pos = styler.LineStart(line + 1) - 1;\r
148         for (int i = pos; i < eol_pos; i++) {\r
149                 char ch = styler[i];\r
150                 char chNext = styler[i+1];\r
151                 if ((ch == '-') && (chNext == '-'))\r
152                         return true;\r
153                 else if (ch != ' ' && ch != '\t')\r
154                         return false;\r
155         }\r
156         return false;\r
157 }\r
158 \r
159 //=============================================================================\r
160 // Folding the code\r
161 static void FoldNoBoxVHDLDoc(\r
162   unsigned int startPos,\r
163   int length,\r
164   int initStyle,\r
165   Accessor &styler)\r
166 {\r
167   // Decided it would be smarter to have the lexer have all keywords included. Therefore I\r
168   // don't check if the style for the keywords that I use to adjust the levels.\r
169   char words[] =\r
170     "architecture begin case component else elsif end entity generate loop package process record then "\r
171     "procedure function when";\r
172   WordList keywords;\r
173   keywords.Set(words);\r
174 \r
175   bool foldComment      = styler.GetPropertyInt("fold.comment", 1) != 0;\r
176   bool foldCompact      = styler.GetPropertyInt("fold.compact", 1) != 0;\r
177   bool foldAtElse       = styler.GetPropertyInt("fold.at.else", 1) != 0;\r
178   bool foldAtBegin      = styler.GetPropertyInt("fold.at.Begin", 1) != 0;\r
179   bool foldAtParenthese = styler.GetPropertyInt("fold.at.Parenthese", 1) != 0;\r
180   //bool foldAtWhen       = styler.GetPropertyInt("fold.at.When", 1) != 0;  //< fold at when in case statements\r
181 \r
182   int  visibleChars     = 0;\r
183   unsigned int endPos   = startPos + length;\r
184 \r
185   int lineCurrent       = styler.GetLine(startPos);\r
186   int levelCurrent      = SC_FOLDLEVELBASE;\r
187   if(lineCurrent > 0)\r
188     levelCurrent        = styler.LevelAt(lineCurrent-1) >> 16;\r
189   //int levelMinCurrent   = levelCurrent;\r
190   int levelMinCurrentElse = levelCurrent;   //< Used for folding at 'else'\r
191   int levelMinCurrentBegin = levelCurrent;  //< Used for folding at 'begin'\r
192   int levelNext         = levelCurrent;\r
193 \r
194   /***************************************/\r
195   int lastStart         = 0;\r
196   char prevWord[32]     = "";\r
197 \r
198   /***************************************/\r
199   // Find prev word\r
200   // The logic for going up or down a level depends on a the previous keyword\r
201   // This code could be cleaned up.\r
202   int end = 0;\r
203   unsigned int j;\r
204   for(j = startPos; j>0; j--)\r
205   {\r
206     char ch       = styler.SafeGetCharAt(j);\r
207     char chPrev   = styler.SafeGetCharAt(j-1);\r
208     int style     = styler.StyleAt(j);\r
209     int stylePrev = styler.StyleAt(j-1);\r
210     if ((stylePrev != SCE_VHDL_COMMENT) && (stylePrev != SCE_VHDL_STRING))\r
211     {\r
212       if(IsAWordChar(chPrev) && !IsAWordChar(ch))\r
213       {\r
214         end = j-1;\r
215       }\r
216     }\r
217     if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING))\r
218     {\r
219       if(!IsAWordChar(chPrev) && IsAWordStart(ch) && (end != 0))\r
220       {\r
221         char s[32];\r
222         unsigned int k;\r
223         for(k=0; (k<31 ) && (k<end-j+1 ); k++) {\r
224           s[k] = static_cast<char>(tolower(styler[j+k]));\r
225         }\r
226         s[k] = '\0';\r
227 \r
228         if(keywords.InList(s)) {\r
229           strcpy(prevWord, s);\r
230           break;\r
231         }\r
232       }\r
233     }\r
234   }\r
235   for(j=j+strlen(prevWord); j<endPos; j++)\r
236   {\r
237     char ch       = styler.SafeGetCharAt(j);\r
238     int style     = styler.StyleAt(j);\r
239     if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING))\r
240     {\r
241       if((ch == ';') && (strcmp(prevWord, "end") == 0))\r
242       {\r
243         strcpy(prevWord, ";");\r
244       }\r
245     }\r
246   }\r
247 \r
248   char  chNext          = styler[startPos];\r
249   char  chPrev          = '\0';\r
250   char  chNextNonBlank;\r
251   int   styleNext       = styler.StyleAt(startPos);\r
252   int   style           = initStyle;\r
253   //Platform::DebugPrintf("Line[%04d] Prev[%20s] ************************* Level[%x]\n", lineCurrent+1, prevWord, levelCurrent);\r
254 \r
255   /***************************************/\r
256   for (unsigned int i = startPos; i < endPos; i++)\r
257   {\r
258     char ch         = chNext;\r
259     chNext          = styler.SafeGetCharAt(i + 1);\r
260     chPrev          = styler.SafeGetCharAt(i - 1);\r
261     chNextNonBlank  = chNext;\r
262     unsigned int j  = i+1;\r
263     while(IsABlank(chNextNonBlank) && j<endPos)\r
264     {\r
265       j ++ ;\r
266       chNextNonBlank = styler.SafeGetCharAt(j);\r
267     }\r
268     style           = styleNext;\r
269     styleNext       = styler.StyleAt(i + 1);\r
270     bool atEOL      = (ch == '\r' && chNext != '\n') || (ch == '\n');\r
271 \r
272                 if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) \r
273     {\r
274       if(!IsCommentLine(lineCurrent-1, styler) && IsCommentLine(lineCurrent+1, styler))\r
275       {\r
276         levelNext++;\r
277       } \r
278       else if(IsCommentLine(lineCurrent-1, styler) && !IsCommentLine(lineCurrent+1, styler))\r
279       {\r
280         levelNext--;\r
281       }\r
282     }\r
283 \r
284     if ((style == SCE_VHDL_OPERATOR) && foldAtParenthese)\r
285     {\r
286       if(ch == '(') {\r
287         levelNext++;\r
288       } else if (ch == ')') {\r
289         levelNext--;\r
290       }\r
291     }\r
292 \r
293     if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING))\r
294     {\r
295       if((ch == ';') && (strcmp(prevWord, "end") == 0))\r
296       {\r
297         strcpy(prevWord, ";");\r
298       }\r
299 \r
300       if(!IsAWordChar(chPrev) && IsAWordStart(ch))\r
301       {\r
302         lastStart = i;\r
303       }\r
304 \r
305       if(iswordchar(ch) && !iswordchar(chNext)) {\r
306         char s[32];\r
307         unsigned int k;\r
308         for(k=0; (k<31 ) && (k<i-lastStart+1 ); k++) {\r
309           s[k] = static_cast<char>(tolower(styler[lastStart+k]));\r
310         }\r
311         s[k] = '\0';\r
312 \r
313         if(keywords.InList(s))\r
314         {\r
315           if (\r
316             strcmp(s, "architecture") == 0  ||\r
317             strcmp(s, "case") == 0          ||\r
318             strcmp(s, "component") == 0     ||\r
319             strcmp(s, "entity") == 0        ||\r
320             strcmp(s, "generate") == 0      ||\r
321             strcmp(s, "loop") == 0          ||\r
322             strcmp(s, "package") ==0        ||\r
323             strcmp(s, "process") == 0       ||\r
324             strcmp(s, "record") == 0        ||\r
325             strcmp(s, "then") == 0)\r
326           {\r
327             if (strcmp(prevWord, "end") != 0)\r
328             {\r
329               if (levelMinCurrentElse > levelNext) {\r
330                 levelMinCurrentElse = levelNext;\r
331               }\r
332               levelNext++;\r
333             }\r
334           } else if (\r
335             strcmp(s, "procedure") == 0     ||\r
336             strcmp(s, "function") == 0)\r
337           {\r
338             if (strcmp(prevWord, "end") != 0) // check for "end procedure" etc.\r
339             { // This code checks to see if the procedure / function is a definition within a "package"\r
340               // rather than the actual code in the body.\r
341               int BracketLevel = 0;\r
342               for(int j=i+1; j<styler.Length(); j++)\r
343               {\r
344                 int LocalStyle = styler.StyleAt(j);\r
345                 char LocalCh = styler.SafeGetCharAt(j);\r
346                 if(LocalCh == '(') BracketLevel++;\r
347                 if(LocalCh == ')') BracketLevel--;\r
348                 if(\r
349                   (BracketLevel == 0) &&\r
350                   (LocalStyle != SCE_VHDL_COMMENT) &&\r
351                   (LocalStyle != SCE_VHDL_STRING) &&\r
352                   !iswordchar(styler.SafeGetCharAt(j-1)) &&\r
353                   styler.Match(j, "is") &&\r
354                   !iswordchar(styler.SafeGetCharAt(j+2)))\r
355                 {\r
356                   if (levelMinCurrentElse > levelNext) {\r
357                     levelMinCurrentElse = levelNext;\r
358                   }\r
359                   levelNext++;\r
360                   break;\r
361                 }\r
362                 if((BracketLevel == 0) && (LocalCh == ';'))\r
363                 {\r
364                   break;\r
365                 }\r
366               }\r
367             }\r
368 \r
369           } else if (strcmp(s, "end") == 0) {\r
370             levelNext--;\r
371           }  else if(strcmp(s, "elsif") == 0) { // elsif is followed by then so folding occurs correctly\r
372             levelNext--;\r
373           } else if (strcmp(s, "else") == 0) {\r
374             if(strcmp(prevWord, "when") != 0)  // ignore a <= x when y else z;\r
375             {\r
376               levelMinCurrentElse = levelNext - 1;  // VHDL else is all on its own so just dec. the min level\r
377             }\r
378           } else if(\r
379             ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "architecture") == 0)) ||\r
380             ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "function") == 0)) ||\r
381             ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "procedure") == 0)))\r
382           {\r
383             levelMinCurrentBegin = levelNext - 1;  \r
384           }\r
385           //Platform::DebugPrintf("Line[%04d] Prev[%20s] Cur[%20s] Level[%x]\n", lineCurrent+1, prevWord, s, levelCurrent);\r
386           strcpy(prevWord, s);\r
387         }\r
388       }\r
389     }\r
390     if (atEOL) {\r
391       int levelUse = levelCurrent;\r
392 \r
393       if (foldAtElse && (levelMinCurrentElse < levelUse)) {\r
394         levelUse = levelMinCurrentElse;\r
395       }\r
396       if (foldAtBegin && (levelMinCurrentBegin < levelUse)) {\r
397         levelUse = levelMinCurrentBegin;\r
398       }\r
399       int lev = levelUse | levelNext << 16;\r
400       if (visibleChars == 0 && foldCompact)\r
401         lev |= SC_FOLDLEVELWHITEFLAG;\r
402 \r
403       if (levelUse < levelNext)\r
404         lev |= SC_FOLDLEVELHEADERFLAG;\r
405       if (lev != styler.LevelAt(lineCurrent)) {\r
406         styler.SetLevel(lineCurrent, lev);\r
407       }\r
408       //Platform::DebugPrintf("Line[%04d] ---------------------------------------------------- Level[%x]\n", lineCurrent+1, levelCurrent);\r
409       lineCurrent++;\r
410       levelCurrent = levelNext;\r
411       //levelMinCurrent = levelCurrent;\r
412       levelMinCurrentElse = levelCurrent;\r
413       levelMinCurrentBegin = levelCurrent;\r
414       visibleChars = 0;\r
415     }\r
416     /***************************************/\r
417     if (!isspacechar(ch)) visibleChars++;\r
418   }\r
419 \r
420   /***************************************/\r
421 //  Platform::DebugPrintf("Line[%04d] ---------------------------------------------------- Level[%x]\n", lineCurrent+1, levelCurrent);\r
422 }\r
423 \r
424 //=============================================================================\r
425 static void FoldVHDLDoc(unsigned int startPos, int length, int initStyle, WordList *[],\r
426                        Accessor &styler) {\r
427   FoldNoBoxVHDLDoc(startPos, length, initStyle, styler);\r
428 }\r
429 \r
430 //=============================================================================\r
431 static const char * const VHDLWordLists[] = {\r
432             "Keywords",\r
433             "Operators",\r
434             "Attributes",\r
435             "Standard Functions",\r
436             "Standard Packages",\r
437             "Standard Types",\r
438             "User Words",\r
439             0,\r
440         };\r
441 \r
442 \r
443 LexerModule lmVHDL(SCLEX_VHDL, ColouriseVHDLDoc, "vhdl", FoldVHDLDoc, VHDLWordLists);\r
444 \r
445 \r
446 // Keyword:\r
447 //    access after alias all architecture array assert attribute begin block body buffer bus case component \r
448 //    configuration constant disconnect downto else elsif end entity exit file for function generate generic \r
449 //    group guarded if impure in inertial inout is label library linkage literal loop map new next null of \r
450 //    on open others out package port postponed procedure process pure range record register reject report \r
451 //    return select severity shared signal subtype then to transport type unaffected units until use variable \r
452 //    wait when while with\r
453 //\r
454 // Operators:\r
455 //    abs and mod nand nor not or rem rol ror sla sll sra srl xnor xor\r
456 //\r
457 // Attributes:\r
458 //    left right low high ascending image value pos val succ pred leftof rightof base range reverse_range \r
459 //    length delayed stable quiet transaction event active last_event last_active last_value driving \r
460 //    driving_value simple_name path_name instance_name\r
461 //\r
462 // Std Functions:\r
463 //    now readline read writeline write endfile resolved to_bit to_bitvector to_stdulogic to_stdlogicvector \r
464 //    to_stdulogicvector to_x01 to_x01z to_UX01 rising_edge falling_edge is_x shift_left shift_right rotate_left \r
465 //    rotate_right resize to_integer to_unsigned to_signed std_match to_01\r
466 //\r
467 // Std Packages:\r
468 //    std ieee work standard textio std_logic_1164 std_logic_arith std_logic_misc std_logic_signed \r
469 //    std_logic_textio std_logic_unsigned numeric_bit numeric_std math_complex math_real vital_primitives \r
470 //    vital_timing\r
471 //\r
472 // Std Types:\r
473 //    boolean bit character severity_level integer real time delay_length natural positive string bit_vector \r
474 //    file_open_kind file_open_status line text side width std_ulogic std_ulogic_vector std_logic \r
475 //    std_logic_vector X01 X01Z UX01 UX01Z unsigned signed\r
476 //\r
477 \r