]> git.saurik.com Git - wxWidgets.git/blame - src/stc/scintilla/src/LexVerilog.cxx
Eliminated two unneeded arguments from wxPropertyGrid::DoDrawItems()
[wxWidgets.git] / src / stc / scintilla / src / LexVerilog.cxx
CommitLineData
591d01be
RD
1// Scintilla source code edit control
2/** @file LexVerilog.cxx
3 ** Lexer for Verilog.
4 ** Written by Avi Yegudin, based on C++ lexer by Neil Hodgson
5 **/
6// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
7// The License.txt file describes the conditions under which this software may be distributed.
8
9#include <stdlib.h>
10#include <string.h>
11#include <ctype.h>
12#include <stdio.h>
13#include <stdarg.h>
14
15#include "Platform.h"
16
17#include "PropSet.h"
18#include "Accessor.h"
19#include "StyleContext.h"
20#include "KeyWords.h"
21#include "Scintilla.h"
22#include "SciLexer.h"
23
7e0c58e9
RD
24#ifdef SCI_NAMESPACE
25using namespace Scintilla;
26#endif
27
591d01be
RD
28static inline bool IsAWordChar(const int ch) {
29 return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\'');
30}
31
32static inline bool IsAWordStart(const int ch) {
33 return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '$');
34}
35
36static void ColouriseVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
37 Accessor &styler) {
38
39 WordList &keywords = *keywordlists[0];
40 WordList &keywords2 = *keywordlists[1];
41 WordList &keywords3 = *keywordlists[2];
42 WordList &keywords4 = *keywordlists[3];
43
44 // Do not leak onto next line
45 if (initStyle == SCE_V_STRINGEOL)
46 initStyle = SCE_V_DEFAULT;
47
48 StyleContext sc(startPos, length, initStyle, styler);
49
50 for (; sc.More(); sc.Forward()) {
51
52 if (sc.atLineStart && (sc.state == SCE_V_STRING)) {
53 // Prevent SCE_V_STRINGEOL from leaking back to previous line
54 sc.SetState(SCE_V_STRING);
55 }
56
57 // Handle line continuation generically.
58 if (sc.ch == '\\') {
59 if (sc.chNext == '\n' || sc.chNext == '\r') {
60 sc.Forward();
61 if (sc.ch == '\r' && sc.chNext == '\n') {
62 sc.Forward();
63 }
64 continue;
65 }
66 }
67
68 // Determine if the current state should terminate.
69 if (sc.state == SCE_V_OPERATOR) {
70 sc.SetState(SCE_V_DEFAULT);
71 } else if (sc.state == SCE_V_NUMBER) {
72 if (!IsAWordChar(sc.ch)) {
73 sc.SetState(SCE_V_DEFAULT);
74 }
75 } else if (sc.state == SCE_V_IDENTIFIER) {
76 if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
77 char s[100];
78 sc.GetCurrent(s, sizeof(s));
79 if (keywords.InList(s)) {
80 sc.ChangeState(SCE_V_WORD);
81 } else if (keywords2.InList(s)) {
82 sc.ChangeState(SCE_V_WORD2);
83 } else if (keywords3.InList(s)) {
84 sc.ChangeState(SCE_V_WORD3);
85 } else if (keywords4.InList(s)) {
86 sc.ChangeState(SCE_V_USER);
87 }
88 sc.SetState(SCE_V_DEFAULT);
89 }
90 } else if (sc.state == SCE_V_PREPROCESSOR) {
91 if (!IsAWordChar(sc.ch)) {
92 sc.SetState(SCE_V_DEFAULT);
93 }
94 } else if (sc.state == SCE_V_COMMENT) {
95 if (sc.Match('*', '/')) {
96 sc.Forward();
97 sc.ForwardSetState(SCE_V_DEFAULT);
98 }
99 } else if (sc.state == SCE_V_COMMENTLINE || sc.state == SCE_V_COMMENTLINEBANG) {
100 if (sc.atLineEnd) {
101 sc.SetState(SCE_V_DEFAULT);
102 }
103 } else if (sc.state == SCE_V_STRING) {
104 if (sc.ch == '\\') {
105 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
106 sc.Forward();
107 }
108 } else if (sc.ch == '\"') {
109 sc.ForwardSetState(SCE_V_DEFAULT);
110 } else if (sc.atLineEnd) {
111 sc.ChangeState(SCE_V_STRINGEOL);
112 sc.ForwardSetState(SCE_V_DEFAULT);
113 }
114 }
115
116 // Determine if a new state should be entered.
117 if (sc.state == SCE_V_DEFAULT) {
118 if (IsADigit(sc.ch) || (sc.ch == '\'') || (sc.ch == '.' && IsADigit(sc.chNext))) {
119 sc.SetState(SCE_V_NUMBER);
120 } else if (IsAWordStart(sc.ch)) {
121 sc.SetState(SCE_V_IDENTIFIER);
122 } else if (sc.Match('/', '*')) {
123 sc.SetState(SCE_V_COMMENT);
124 sc.Forward(); // Eat the * so it isn't used for the end of the comment
125 } else if (sc.Match('/', '/')) {
126 if (sc.Match("//!")) // Nice to have a different comment style
127 sc.SetState(SCE_V_COMMENTLINEBANG);
128 else
129 sc.SetState(SCE_V_COMMENTLINE);
130 } else if (sc.ch == '\"') {
131 sc.SetState(SCE_V_STRING);
132 } else if (sc.ch == '`') {
133 sc.SetState(SCE_V_PREPROCESSOR);
134 // Skip whitespace between ` and preprocessor word
135 do {
136 sc.Forward();
137 } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
138 if (sc.atLineEnd) {
139 sc.SetState(SCE_V_DEFAULT);
140 }
141 } else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@' || sc.ch == '#') {
142 sc.SetState(SCE_V_OPERATOR);
143 }
144 }
145 }
146 sc.Complete();
147}
148
149static bool IsStreamCommentStyle(int style) {
150 return style == SCE_V_COMMENT;
151}
152
153// Store both the current line's fold level and the next lines in the
154// level store to make it easy to pick up with each increment
155// and to make it possible to fiddle the current level for "} else {".
156static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle,
157 Accessor &styler) {
158 bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
159 bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
160 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
161 bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
162 // Verilog specific folding options:
163 // fold_at_module -
164 // Generally used methodology in verilog code is
165 // one module per file, so folding at module definition is useless.
166 // fold_at_brace/parenthese -
167 // Folding of long port lists can be convenient.
168 bool foldAtModule = styler.GetPropertyInt("fold.verilog.flags", 0) != 0;
169 bool foldAtBrace = 1;
170 bool foldAtParenthese = 1;
171
172 unsigned int endPos = startPos + length;
173 int visibleChars = 0;
174 int lineCurrent = styler.GetLine(startPos);
175 int levelCurrent = SC_FOLDLEVELBASE;
176 if (lineCurrent > 0)
177 levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
178 int levelMinCurrent = levelCurrent;
179 int levelNext = levelCurrent;
180 char chNext = styler[startPos];
181 int styleNext = styler.StyleAt(startPos);
182 int style = initStyle;
183 for (unsigned int i = startPos; i < endPos; i++) {
184 char ch = chNext;
185 chNext = styler.SafeGetCharAt(i + 1);
186 int stylePrev = style;
187 style = styleNext;
188 styleNext = styler.StyleAt(i + 1);
189 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
190 if (foldComment && IsStreamCommentStyle(style)) {
191 if (!IsStreamCommentStyle(stylePrev)) {
192 levelNext++;
193 } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
194 // Comments don't end at end of line and the next character may be unstyled.
195 levelNext--;
196 }
197 }
198 if (foldComment && (style == SCE_V_COMMENTLINE)) {
199 if ((ch == '/') && (chNext == '/')) {
200 char chNext2 = styler.SafeGetCharAt(i + 2);
201 if (chNext2 == '{') {
202 levelNext++;
203 } else if (chNext2 == '}') {
204 levelNext--;
205 }
206 }
207 }
208 if (foldPreprocessor && (style == SCE_V_PREPROCESSOR)) {
209 if (ch == '`') {
210 unsigned int j = i + 1;
211 while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
212 j++;
213 }
214 if (styler.Match(j, "if")) {
215 levelNext++;
216 } else if (styler.Match(j, "end")) {
217 levelNext--;
218 }
219 }
220 }
221 if (style == SCE_V_OPERATOR) {
222 if (foldAtParenthese) {
223 if (ch == '(') {
224 levelNext++;
225 } else if (ch == ')') {
226 levelNext--;
227 }
228 }
229 }
230 if (style == SCE_V_OPERATOR) {
231 if (foldAtBrace) {
232 if (ch == '{') {
233 levelNext++;
234 } else if (ch == '}') {
235 levelNext--;
236 }
237 }
238 }
239 if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) {
240 unsigned int j = i;
241 if (styler.Match(j, "case") ||
242 styler.Match(j, "casex") ||
243 styler.Match(j, "casez") ||
244 styler.Match(j, "function") ||
245 styler.Match(j, "fork") ||
246 styler.Match(j, "table") ||
247 styler.Match(j, "task") ||
248 styler.Match(j, "specify") ||
249 styler.Match(j, "primitive") ||
250 styler.Match(j, "module") && foldAtModule ||
251 styler.Match(j, "begin")) {
252 levelNext++;
253 } else if (styler.Match(j, "endcase") ||
254 styler.Match(j, "endfunction") ||
255 styler.Match(j, "join") ||
256 styler.Match(j, "endtask") ||
257 styler.Match(j, "endtable") ||
258 styler.Match(j, "endspecify") ||
259 styler.Match(j, "endprimitive") ||
260 styler.Match(j, "endmodule") && foldAtModule ||
261 styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j+3))) {
262 levelNext--;
263 }
264 }
265 if (atEOL) {
266 int levelUse = levelCurrent;
267 if (foldAtElse) {
268 levelUse = levelMinCurrent;
269 }
270 int lev = levelUse | levelNext << 16;
271 if (visibleChars == 0 && foldCompact)
272 lev |= SC_FOLDLEVELWHITEFLAG;
273 if (levelUse < levelNext)
274 lev |= SC_FOLDLEVELHEADERFLAG;
275 if (lev != styler.LevelAt(lineCurrent)) {
276 styler.SetLevel(lineCurrent, lev);
277 }
278 lineCurrent++;
279 levelCurrent = levelNext;
280 levelMinCurrent = levelCurrent;
281 visibleChars = 0;
282 }
283 if (!isspacechar(ch))
284 visibleChars++;
285 }
286}
287
288static void FoldVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *[],
289 Accessor &styler) {
290 FoldNoBoxVerilogDoc(startPos, length, initStyle, styler);
291}
292
293static const char * const verilogWordLists[] = {
294 "Primary keywords and identifiers",
295 "Secondary keywords and identifiers",
296 "System Tasks",
297 "User defined tasks and identifiers",
298 "Unused",
299 0,
300 };
301
302
303LexerModule lmVerilog(SCLEX_VERILOG, ColouriseVerilogDoc, "verilog", FoldVerilogDoc, verilogWordLists);