]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexD.cxx
4 ** Copyright (c) 2006 by Waldemar Augustyn <waldemar@wdmsys.com>
6 // Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
7 // The License.txt file describes the conditions under which this software may be distributed.
19 #include "StyleContext.h"
21 #include "Scintilla.h"
25 using namespace Scintilla
;
28 /*/ Nested comments require keeping the value of the nesting level for every
29 position in the document. But since scintilla always styles line by line,
30 we only need to store one value per line. The non-negative number indicates
31 nesting level at the end of the line.
34 // We use custom qualifiers since it is not clear what D allows.
36 static bool IsWordStart(int ch) {
37 return isascii(ch) && (isalpha(ch) || ch == '_');
40 static bool IsWord(int ch) {
41 return isascii(ch) && (isalnum(ch) || ch == '_');
44 static bool IsDoxygen(int ch) {
45 if (isascii(ch) && islower(ch))
47 if (ch == '$' || ch == '@' || ch == '\\' ||
48 ch == '&' || ch == '#' || ch == '<' || ch == '>' ||
49 ch == '{' || ch == '}' || ch == '[' || ch == ']')
55 static void ColouriseDoc(unsigned int startPos, int length, int initStyle,
56 WordList *keywordlists[], Accessor &styler, bool caseSensitive) {
58 WordList &keywords = *keywordlists[0];
59 WordList &keywords2 = *keywordlists[1];
60 WordList &keywords3 = *keywordlists[2];
61 WordList &keywords4 = *keywordlists[3];
63 int styleBeforeDCKeyword = SCE_D_DEFAULT;
65 StyleContext sc(startPos, length, initStyle, styler);
67 int curLine = styler.GetLine(startPos);
68 int curNcLevel = curLine > 0? styler.GetLineState(curLine-1): 0;
70 for (; sc.More(); sc.Forward()) {
73 if (sc.state == SCE_D_STRING) {
74 // Prevent SCE_D_STRINGEOL from leaking back to previous line which
75 // ends with a line continuation by locking in the state upto this position.
76 sc.SetState(SCE_D_STRING);
78 curLine = styler.GetLine(sc.currentPos);
79 styler.SetLineState(curLine, curNcLevel);
82 // Handle line continuation generically.
84 if (sc.chNext == '\n' || sc.chNext == '\r') {
86 if (sc.ch == '\r' && sc.chNext == '\n') {
93 // Determine if the current state should terminate.
96 sc.SetState(SCE_D_DEFAULT);
99 // We accept almost anything because of hex. and number suffixes
100 if (!IsWord(sc.ch) && sc.ch != '.') {
101 sc.SetState(SCE_D_DEFAULT);
104 case SCE_D_IDENTIFIER:
105 if (!IsWord(sc.ch)) {
108 sc.GetCurrent(s, sizeof(s));
110 sc.GetCurrentLowered(s, sizeof(s));
112 if (keywords.InList(s)) {
113 sc.ChangeState(SCE_D_WORD);
114 } else if (keywords2.InList(s)) {
115 sc.ChangeState(SCE_D_WORD2);
116 } else if (keywords4.InList(s)) {
117 sc.ChangeState(SCE_D_TYPEDEF);
119 sc.SetState(SCE_D_DEFAULT);
123 if (sc.Match('*', '/')) {
125 sc.ForwardSetState(SCE_D_DEFAULT);
128 case SCE_D_COMMENTDOC:
129 if (sc.Match('*', '/')) {
131 sc.ForwardSetState(SCE_D_DEFAULT);
132 } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
133 // Verify that we have the conditions to mark a comment-doc-keyword
134 if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) {
135 styleBeforeDCKeyword = SCE_D_COMMENTDOC;
136 sc.SetState(SCE_D_COMMENTDOCKEYWORD);
140 case SCE_D_COMMENTLINE:
141 if (sc.atLineStart) {
142 sc.SetState(SCE_D_DEFAULT);
145 case SCE_D_COMMENTLINEDOC:
146 if (sc.atLineStart) {
147 sc.SetState(SCE_D_DEFAULT);
148 } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
149 // Verify that we have the conditions to mark a comment-doc-keyword
150 if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) {
151 styleBeforeDCKeyword = SCE_D_COMMENTLINEDOC;
152 sc.SetState(SCE_D_COMMENTDOCKEYWORD);
156 case SCE_D_COMMENTDOCKEYWORD:
157 if ((styleBeforeDCKeyword == SCE_D_COMMENTDOC) && sc.Match('*', '/')) {
158 sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR);
160 sc.ForwardSetState(SCE_D_DEFAULT);
161 } else if (!IsDoxygen(sc.ch)) {
164 sc.GetCurrent(s, sizeof(s));
166 sc.GetCurrentLowered(s, sizeof(s));
168 if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) {
169 sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR);
171 sc.SetState(styleBeforeDCKeyword);
174 case SCE_D_COMMENTNESTED:
175 if (sc.Match('+', '/')) {
178 curLine = styler.GetLine(sc.currentPos);
179 styler.SetLineState(curLine, curNcLevel);
181 if (curNcLevel == 0) {
182 sc.ForwardSetState(SCE_D_DEFAULT);
185 else if (sc.Match('/','+')) {
187 curLine = styler.GetLine(sc.currentPos);
188 styler.SetLineState(curLine, curNcLevel);
194 sc.ChangeState(SCE_D_STRINGEOL);
195 } else if (sc.ch == '\\') {
196 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
199 } else if (sc.ch == '\"') {
200 sc.ForwardSetState(SCE_D_DEFAULT);
203 case SCE_D_CHARACTER:
205 sc.ChangeState(SCE_D_STRINGEOL);
206 } else if (sc.ch == '\\') {
207 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
210 } else if (sc.ch == '\'') {
211 sc.ForwardSetState(SCE_D_DEFAULT);
214 case SCE_D_STRINGEOL:
215 if (sc.atLineStart) {
216 sc.SetState(SCE_D_DEFAULT);
221 // Determine if a new state should be entered.
222 if (sc.state == SCE_D_DEFAULT) {
223 if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
224 sc.SetState(SCE_D_NUMBER);
225 } else if (IsWordStart(sc.ch)) {
226 sc.SetState(SCE_D_IDENTIFIER);
227 } else if (sc.Match('/','+')) {
229 curLine = styler.GetLine(sc.currentPos);
230 styler.SetLineState(curLine, curNcLevel);
231 sc.SetState(SCE_D_COMMENTNESTED);
233 } else if (sc.Match('/', '*')) {
234 if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style
235 sc.SetState(SCE_D_COMMENTDOC);
237 sc.SetState(SCE_D_COMMENT);
239 sc.Forward(); // Eat the * so it isn't used for the end of the comment
240 } else if (sc.Match('/', '/')) {
241 if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!"))
242 // Support of Qt/Doxygen doc. style
243 sc.SetState(SCE_D_COMMENTLINEDOC);
245 sc.SetState(SCE_D_COMMENTLINE);
246 } else if (sc.ch == '\"') {
247 sc.SetState(SCE_D_STRING);
248 } else if (sc.ch == '\'') {
249 sc.SetState(SCE_D_CHARACTER);
250 } else if (isoperator(static_cast<char>(sc.ch))) {
251 sc.SetState(SCE_D_OPERATOR);
258 static bool IsStreamCommentStyle(int style) {
259 return style == SCE_D_COMMENT ||
260 style == SCE_D_COMMENTDOC ||
261 style == SCE_D_COMMENTDOCKEYWORD ||
262 style == SCE_D_COMMENTDOCKEYWORDERROR;
265 // Store both the current line's fold level and the next lines in the
266 // level store to make it easy to pick up with each increment
267 // and to make it possible to fiddle the current level for "} else {".
268 static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor &styler) {
269 bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
270 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
271 bool foldAtElse = styler.GetPropertyInt("lexer.d.fold.at.else",
272 styler.GetPropertyInt("fold.at.else", 0)) != 0;
273 unsigned int endPos = startPos + length;
274 int visibleChars = 0;
275 int lineCurrent = styler.GetLine(startPos);
276 int levelCurrent = SC_FOLDLEVELBASE;
278 levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
279 int levelMinCurrent = levelCurrent;
280 int levelNext = levelCurrent;
281 char chNext = styler[startPos];
282 int styleNext = styler.StyleAt(startPos);
283 int style = initStyle;
284 for (unsigned int i = startPos; i < endPos; i++) {
286 chNext = styler.SafeGetCharAt(i + 1);
287 int stylePrev = style;
289 styleNext = styler.StyleAt(i + 1);
290 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
291 if (foldComment && IsStreamCommentStyle(style)) {
292 if (!IsStreamCommentStyle(stylePrev)) {
294 } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
295 // Comments don't end at end of line and the next character may be unstyled.
299 if (style == SCE_D_OPERATOR) {
301 // Measure the minimum before a '{' to allow
302 // folding on "} else {"
303 if (levelMinCurrent > levelNext) {
304 levelMinCurrent = levelNext;
307 } else if (ch == '}') {
312 if (foldComment) { // Handle nested comments
314 nc = styler.GetLineState(lineCurrent);
315 nc -= lineCurrent>0? styler.GetLineState(lineCurrent-1): 0;
318 int levelUse = levelCurrent;
320 levelUse = levelMinCurrent;
322 int lev = levelUse | levelNext << 16;
323 if (visibleChars == 0 && foldCompact)
324 lev |= SC_FOLDLEVELWHITEFLAG;
325 if (levelUse < levelNext)
326 lev |= SC_FOLDLEVELHEADERFLAG;
327 if (lev != styler.LevelAt(lineCurrent)) {
328 styler.SetLevel(lineCurrent, lev);
331 levelCurrent = levelNext;
332 levelMinCurrent = levelCurrent;
340 static void FoldDDoc(unsigned int startPos, int length, int initStyle,
341 WordList *[], Accessor &styler) {
342 FoldDoc(startPos, length, initStyle, styler);
345 static const char * const dWordLists[] = {
346 "Primary keywords and identifiers",
347 "Secondary keywords and identifiers",
348 "Documentation comment keywords",
349 "Type definitions and aliases",
353 static void ColouriseDDoc(unsigned int startPos, int length,
354 int initStyle, WordList *keywordlists[], Accessor &styler) {
355 ColouriseDoc(startPos, length, initStyle, keywordlists, styler, true);
358 LexerModule lmD(SCLEX_D, ColouriseDDoc, "d", FoldDDoc, dWordLists);