]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexVHDL.cxx
0feef951206a2ba4b33a2bce5b15b25fe22533d7
1 // Scintilla source code edit control
4 ** Written by Phil Reid,
6 ** - The Verilog Lexer by Avi Yegudin
7 ** - The Fortran Lexer by Chuan-jian Shen
8 ** - The C++ lexer by Neil Hodgson
10 // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
11 // The License.txt file describes the conditions under which this software may be distributed.
23 #include "StyleContext.h"
25 #include "Scintilla.h"
28 static void ColouriseVHDLDoc(
29 unsigned int startPos
,
32 WordList
*keywordlists
[],
36 /***************************************/
37 static inline bool IsAWordChar(const int ch
) {
38 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_' );
41 /***************************************/
42 static inline bool IsAWordStart(const int ch
) {
43 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
46 /***************************************/
47 inline bool IsABlank(unsigned int ch
) {
48 return (ch
== ' ') || (ch
== 0x09) || (ch
== 0x0b) ;
51 /***************************************/
52 static void ColouriseVHDLDoc(
53 unsigned int startPos
,
56 WordList
*keywordlists
[],
59 WordList
&Keywords
= *keywordlists
[0];
60 WordList
&Operators
= *keywordlists
[1];
61 WordList
&Attributes
= *keywordlists
[2];
62 WordList
&Functions
= *keywordlists
[3];
63 WordList
&Packages
= *keywordlists
[4];
64 WordList
&Types
= *keywordlists
[5];
65 WordList
&User
= *keywordlists
[6];
67 StyleContext
sc(startPos
, length
, initStyle
, styler
);
69 for (; sc
.More(); sc
.Forward())
72 // Determine if the current state should terminate.
73 if (sc
.state
== SCE_VHDL_OPERATOR
) {
74 sc
.SetState(SCE_VHDL_DEFAULT
);
75 } else if (sc
.state
== SCE_VHDL_NUMBER
) {
76 if (!IsAWordChar(sc
.ch
) && (sc
.ch
!= '#')) {
77 sc
.SetState(SCE_VHDL_DEFAULT
);
79 } else if (sc
.state
== SCE_VHDL_IDENTIFIER
) {
80 if (!IsAWordChar(sc
.ch
) || (sc
.ch
== '.')) {
82 sc
.GetCurrentLowered(s
, sizeof(s
));
83 if (Keywords
.InList(s
)) {
84 sc
.ChangeState(SCE_VHDL_KEYWORD
);
85 } else if (Operators
.InList(s
)) {
86 sc
.ChangeState(SCE_VHDL_STDOPERATOR
);
87 } else if (Attributes
.InList(s
)) {
88 sc
.ChangeState(SCE_VHDL_ATTRIBUTE
);
89 } else if (Functions
.InList(s
)) {
90 sc
.ChangeState(SCE_VHDL_STDFUNCTION
);
91 } else if (Packages
.InList(s
)) {
92 sc
.ChangeState(SCE_VHDL_STDPACKAGE
);
93 } else if (Types
.InList(s
)) {
94 sc
.ChangeState(SCE_VHDL_STDTYPE
);
95 } else if (User
.InList(s
)) {
96 sc
.ChangeState(SCE_VHDL_USERWORD
);
98 sc
.SetState(SCE_VHDL_DEFAULT
);
100 } else if (sc
.state
== SCE_VHDL_COMMENT
|| sc
.state
== SCE_V_COMMENTLINEBANG
) {
102 sc
.SetState(SCE_VHDL_DEFAULT
);
104 } else if (sc
.state
== SCE_VHDL_STRING
) {
106 if (sc
.chNext
== '\"' || sc
.chNext
== '\'' || sc
.chNext
== '\\') {
109 } else if (sc
.ch
== '\"') {
110 sc
.ForwardSetState(SCE_VHDL_DEFAULT
);
111 } else if (sc
.atLineEnd
) {
112 sc
.ChangeState(SCE_V_STRINGEOL
);
113 sc
.ForwardSetState(SCE_VHDL_DEFAULT
);
117 // Determine if a new state should be entered.
118 if (sc
.state
== SCE_VHDL_DEFAULT
) {
119 if (IsADigit(sc
.ch
) || (sc
.ch
== '.' && IsADigit(sc
.chNext
))) {
120 sc
.SetState(SCE_VHDL_NUMBER
);
121 } else if (IsAWordStart(sc
.ch
)) {
122 sc
.SetState(SCE_VHDL_IDENTIFIER
);
123 } else if (sc
.Match('-', '-')) {
124 sc
.SetState(SCE_VHDL_COMMENT
);
126 } else if (sc
.Match('-', '-')) {
127 if (sc
.Match("--!")) // Nice to have a different comment style
128 sc
.SetState(SCE_VHDL_COMMENTLINEBANG
);
130 sc
.SetState(SCE_VHDL_COMMENT
);
131 } else if (sc
.ch
== '\"') {
132 sc
.SetState(SCE_VHDL_STRING
);
133 } else if (isoperator(static_cast<char>(sc
.ch
))) {
134 sc
.SetState(SCE_VHDL_OPERATOR
);
140 //=============================================================================
141 static bool IsCommentLine(int line
, Accessor
&styler
) {
142 int pos
= styler
.LineStart(line
);
143 int eol_pos
= styler
.LineStart(line
+ 1) - 1;
144 for (int i
= pos
; i
< eol_pos
; i
++) {
146 char chNext
= styler
[i
+1];
147 if ((ch
== '-') && (chNext
== '-'))
149 else if (ch
!= ' ' && ch
!= '\t')
155 //=============================================================================
157 static void FoldNoBoxVHDLDoc(
158 unsigned int startPos
,
163 // Decided it would be smarter to have the lexer have all keywords included. Therefore I
164 // don't check if the style for the keywords that I use to adjust the levels.
166 "architecture begin case component else elsif end entity generate loop package process record then "
167 "procedure function when";
171 bool foldComment
= styler
.GetPropertyInt("fold.comment", 1) != 0;
172 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
173 bool foldAtElse
= styler
.GetPropertyInt("fold.at.else", 1) != 0;
174 bool foldAtBegin
= styler
.GetPropertyInt("fold.at.Begin", 1) != 0;
175 bool foldAtParenthese
= styler
.GetPropertyInt("fold.at.Parenthese", 1) != 0;
176 //bool foldAtWhen = styler.GetPropertyInt("fold.at.When", 1) != 0; //< fold at when in case statements
178 int visibleChars
= 0;
179 unsigned int endPos
= startPos
+ length
;
181 int lineCurrent
= styler
.GetLine(startPos
);
182 int levelCurrent
= SC_FOLDLEVELBASE
;
184 levelCurrent
= styler
.LevelAt(lineCurrent
-1) >> 16;
185 //int levelMinCurrent = levelCurrent;
186 int levelMinCurrentElse
= levelCurrent
; //< Used for folding at 'else'
187 int levelMinCurrentBegin
= levelCurrent
; //< Used for folding at 'begin'
188 int levelNext
= levelCurrent
;
190 /***************************************/
192 char prevWord
[32] = "";
194 /***************************************/
196 // The logic for going up or down a level depends on a the previous keyword
197 // This code could be cleaned up.
200 for(j
= startPos
; j
>0; j
--)
202 char ch
= styler
.SafeGetCharAt(j
);
203 char chPrev
= styler
.SafeGetCharAt(j
-1);
204 int style
= styler
.StyleAt(j
);
205 int stylePrev
= styler
.StyleAt(j
-1);
206 if ((stylePrev
!= SCE_VHDL_COMMENT
) && (stylePrev
!= SCE_VHDL_STRING
))
208 if(IsAWordChar(chPrev
) && !IsAWordChar(ch
))
213 if ((style
!= SCE_VHDL_COMMENT
) && (style
!= SCE_VHDL_STRING
))
215 if(!IsAWordChar(chPrev
) && IsAWordStart(ch
) && (end
!= 0))
219 for(k
=0; (k
<31 ) && (k
<end
-j
+1 ); k
++) {
220 s
[k
] = static_cast<char>(tolower(styler
[j
+k
]));
224 if(keywords
.InList(s
)) {
231 for(j
=j
+strlen(prevWord
); j
<endPos
; j
++)
233 char ch
= styler
.SafeGetCharAt(j
);
234 int style
= styler
.StyleAt(j
);
235 if ((style
!= SCE_VHDL_COMMENT
) && (style
!= SCE_VHDL_STRING
))
237 if((ch
== ';') && (strcmp(prevWord
, "end") == 0))
239 strcpy(prevWord
, ";");
244 char chNext
= styler
[startPos
];
247 int styleNext
= styler
.StyleAt(startPos
);
248 int style
= initStyle
;
249 //Platform::DebugPrintf("Line[%04d] Prev[%20s] ************************* Level[%x]\n", lineCurrent+1, prevWord, levelCurrent);
251 /***************************************/
252 for (unsigned int i
= startPos
; i
< endPos
; i
++)
255 chNext
= styler
.SafeGetCharAt(i
+ 1);
256 chPrev
= styler
.SafeGetCharAt(i
- 1);
257 chNextNonBlank
= chNext
;
258 unsigned int j
= i
+1;
259 while(IsABlank(chNextNonBlank
) && j
<endPos
)
262 chNextNonBlank
= styler
.SafeGetCharAt(j
);
265 styleNext
= styler
.StyleAt(i
+ 1);
266 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
268 if (foldComment
&& atEOL
&& IsCommentLine(lineCurrent
, styler
))
270 if(!IsCommentLine(lineCurrent
-1, styler
) && IsCommentLine(lineCurrent
+1, styler
))
274 else if(IsCommentLine(lineCurrent
-1, styler
) && !IsCommentLine(lineCurrent
+1, styler
))
280 if ((style
== SCE_VHDL_OPERATOR
) && foldAtParenthese
)
284 } else if (ch
== ')') {
289 if ((style
!= SCE_VHDL_COMMENT
) && (style
!= SCE_VHDL_STRING
))
291 if((ch
== ';') && (strcmp(prevWord
, "end") == 0))
293 strcpy(prevWord
, ";");
296 if(!IsAWordChar(chPrev
) && IsAWordStart(ch
))
301 if(iswordchar(ch
) && !iswordchar(chNext
)) {
304 for(k
=0; (k
<31 ) && (k
<i
-lastStart
+1 ); k
++) {
305 s
[k
] = static_cast<char>(tolower(styler
[lastStart
+k
]));
309 if(keywords
.InList(s
))
312 strcmp(s
, "architecture") == 0 ||
313 strcmp(s
, "case") == 0 ||
314 strcmp(s
, "component") == 0 ||
315 strcmp(s
, "entity") == 0 ||
316 strcmp(s
, "generate") == 0 ||
317 strcmp(s
, "loop") == 0 ||
318 strcmp(s
, "package") ==0 ||
319 strcmp(s
, "process") == 0 ||
320 strcmp(s
, "record") == 0 ||
321 strcmp(s
, "then") == 0)
323 if (strcmp(prevWord
, "end") != 0)
325 if (levelMinCurrentElse
> levelNext
) {
326 levelMinCurrentElse
= levelNext
;
331 strcmp(s
, "procedure") == 0 ||
332 strcmp(s
, "function") == 0)
334 if (strcmp(prevWord
, "end") != 0) // check for "end procedure" etc.
335 { // This code checks to see if the procedure / function is a definition within a "package"
336 // rather than the actual code in the body.
337 int BracketLevel
= 0;
338 for(int j
=i
+1; j
<styler
.Length(); j
++)
340 int LocalStyle
= styler
.StyleAt(j
);
341 char LocalCh
= styler
.SafeGetCharAt(j
);
342 if(LocalCh
== '(') BracketLevel
++;
343 if(LocalCh
== ')') BracketLevel
--;
345 (BracketLevel
== 0) &&
346 (LocalStyle
!= SCE_VHDL_COMMENT
) &&
347 (LocalStyle
!= SCE_VHDL_STRING
) &&
348 !iswordchar(styler
.SafeGetCharAt(j
-1)) &&
349 styler
.Match(j
, "is") &&
350 !iswordchar(styler
.SafeGetCharAt(j
+2)))
352 if (levelMinCurrentElse
> levelNext
) {
353 levelMinCurrentElse
= levelNext
;
358 if((BracketLevel
== 0) && (LocalCh
== ';'))
365 } else if (strcmp(s
, "end") == 0) {
367 } else if(strcmp(s
, "elsif") == 0) { // elsif is followed by then so folding occurs correctly
369 } else if (strcmp(s
, "else") == 0) {
370 if(strcmp(prevWord
, "when") != 0) // ignore a <= x when y else z;
372 levelMinCurrentElse
= levelNext
- 1; // VHDL else is all on its own so just dec. the min level
375 ((strcmp(s
, "begin") == 0) && (strcmp(prevWord
, "architecture") == 0)) ||
376 ((strcmp(s
, "begin") == 0) && (strcmp(prevWord
, "function") == 0)) ||
377 ((strcmp(s
, "begin") == 0) && (strcmp(prevWord
, "procedure") == 0)))
379 levelMinCurrentBegin
= levelNext
- 1;
381 //Platform::DebugPrintf("Line[%04d] Prev[%20s] Cur[%20s] Level[%x]\n", lineCurrent+1, prevWord, s, levelCurrent);
387 int levelUse
= levelCurrent
;
389 if (foldAtElse
&& (levelMinCurrentElse
< levelUse
)) {
390 levelUse
= levelMinCurrentElse
;
392 if (foldAtBegin
&& (levelMinCurrentBegin
< levelUse
)) {
393 levelUse
= levelMinCurrentBegin
;
395 int lev
= levelUse
| levelNext
<< 16;
396 if (visibleChars
== 0 && foldCompact
)
397 lev
|= SC_FOLDLEVELWHITEFLAG
;
399 if (levelUse
< levelNext
)
400 lev
|= SC_FOLDLEVELHEADERFLAG
;
401 if (lev
!= styler
.LevelAt(lineCurrent
)) {
402 styler
.SetLevel(lineCurrent
, lev
);
404 //Platform::DebugPrintf("Line[%04d] ---------------------------------------------------- Level[%x]\n", lineCurrent+1, levelCurrent);
406 levelCurrent
= levelNext
;
407 //levelMinCurrent = levelCurrent;
408 levelMinCurrentElse
= levelCurrent
;
409 levelMinCurrentBegin
= levelCurrent
;
412 /***************************************/
413 if (!isspacechar(ch
)) visibleChars
++;
416 /***************************************/
417 // Platform::DebugPrintf("Line[%04d] ---------------------------------------------------- Level[%x]\n", lineCurrent+1, levelCurrent);
420 //=============================================================================
421 static void FoldVHDLDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*[],
423 FoldNoBoxVHDLDoc(startPos
, length
, initStyle
, styler
);
426 //=============================================================================
427 static const char * const VHDLWordLists
[] = {
431 "Standard Functions",
439 LexerModule
lmVHDL(SCLEX_VHDL
, ColouriseVHDLDoc
, "vhdl", FoldVHDLDoc
, VHDLWordLists
);
443 // access after alias all architecture array assert attribute begin block body buffer bus case component
444 // configuration constant disconnect downto else elsif end entity exit file for function generate generic
445 // group guarded if impure in inertial inout is label library linkage literal loop map new next null of
446 // on open others out package port postponed procedure process pure range record register reject report
447 // return select severity shared signal subtype then to transport type unaffected units until use variable
448 // wait when while with
451 // abs and mod nand nor not or rem rol ror sla sll sra srl xnor xor
454 // left right low high ascending image value pos val succ pred leftof rightof base range reverse_range
455 // length delayed stable quiet transaction event active last_event last_active last_value driving
456 // driving_value simple_name path_name instance_name
459 // now readline read writeline write endfile resolved to_bit to_bitvector to_stdulogic to_stdlogicvector
460 // to_stdulogicvector to_x01 to_x01z to_UX01 rising_edge falling_edge is_x shift_left shift_right rotate_left
461 // rotate_right resize to_integer to_unsigned to_signed std_match to_01
464 // std ieee work standard textio std_logic_1164 std_logic_arith std_logic_misc std_logic_signed
465 // std_logic_textio std_logic_unsigned numeric_bit numeric_std math_complex math_real vital_primitives
469 // boolean bit character severity_level integer real time delay_length natural positive string bit_vector
470 // file_open_kind file_open_status line text side width std_ulogic std_ulogic_vector std_logic
471 // std_logic_vector X01 X01Z UX01 UX01Z unsigned signed