Add an UI to enable/disable specific overlay handlers.
[TortoiseGit.git] / ext / scintilla / src / LexSpecman.cxx
blob4a7f4dd89e4fdb178ae4c658f1be0f02440b2a68
1 // Scintilla source code edit control
2 /** @file LexSpecman.cxx
3 ** Lexer for Specman E language.
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.
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ctype.h>
12 #include <stdio.h>
13 #include <stdarg.h>
15 #include "Platform.h"
17 #include "PropSet.h"
18 #include "Accessor.h"
19 #include "StyleContext.h"
20 #include "KeyWords.h"
21 #include "Scintilla.h"
22 #include "SciLexer.h"
24 #ifdef SCI_NAMESPACE
25 using namespace Scintilla;
26 #endif
28 static inline bool IsAWordChar(const int ch) {
29 return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\'');
32 static inline bool IsANumberChar(const int ch) {
33 return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '\'');
36 static inline bool IsAWordStart(const int ch) {
37 return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '`');
40 static void ColouriseSpecmanDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
41 Accessor &styler, bool caseSensitive) {
43 WordList &keywords = *keywordlists[0];
44 WordList &keywords2 = *keywordlists[1];
45 WordList &keywords3 = *keywordlists[2];
46 WordList &keywords4 = *keywordlists[3];
48 // Do not leak onto next line
49 if (initStyle == SCE_SN_STRINGEOL)
50 initStyle = SCE_SN_CODE;
52 int visibleChars = 0;
54 StyleContext sc(startPos, length, initStyle, styler);
56 for (; sc.More(); sc.Forward()) {
58 if (sc.atLineStart && (sc.state == SCE_SN_STRING)) {
59 // Prevent SCE_SN_STRINGEOL from leaking back to previous line
60 sc.SetState(SCE_SN_STRING);
63 // Handle line continuation generically.
64 if (sc.ch == '\\') {
65 if (sc.chNext == '\n' || sc.chNext == '\r') {
66 sc.Forward();
67 if (sc.ch == '\r' && sc.chNext == '\n') {
68 sc.Forward();
70 continue;
74 // Determine if the current state should terminate.
75 if (sc.state == SCE_SN_OPERATOR) {
76 sc.SetState(SCE_SN_CODE);
77 } else if (sc.state == SCE_SN_NUMBER) {
78 if (!IsANumberChar(sc.ch)) {
79 sc.SetState(SCE_SN_CODE);
81 } else if (sc.state == SCE_SN_IDENTIFIER) {
82 if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
83 char s[100];
84 if (caseSensitive) {
85 sc.GetCurrent(s, sizeof(s));
86 } else {
87 sc.GetCurrentLowered(s, sizeof(s));
89 if (keywords.InList(s)) {
90 sc.ChangeState(SCE_SN_WORD);
91 } else if (keywords2.InList(s)) {
92 sc.ChangeState(SCE_SN_WORD2);
93 } else if (keywords3.InList(s)) {
94 sc.ChangeState(SCE_SN_WORD3);
95 } else if (keywords4.InList(s)) {
96 sc.ChangeState(SCE_SN_USER);
98 sc.SetState(SCE_SN_CODE);
100 } else if (sc.state == SCE_SN_PREPROCESSOR) {
101 if (IsASpace(sc.ch)) {
102 sc.SetState(SCE_SN_CODE);
104 } else if (sc.state == SCE_SN_DEFAULT) {
105 if (sc.Match('<', '\'')) {
106 sc.Forward();
107 sc.ForwardSetState(SCE_SN_CODE);
109 } else if (sc.state == SCE_SN_COMMENTLINE || sc.state == SCE_SN_COMMENTLINEBANG) {
110 if (sc.atLineEnd) {
111 sc.SetState(SCE_SN_CODE);
112 visibleChars = 0;
114 } else if (sc.state == SCE_SN_STRING) {
115 if (sc.ch == '\\') {
116 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
117 sc.Forward();
119 } else if (sc.ch == '\"') {
120 sc.ForwardSetState(SCE_SN_CODE);
121 } else if (sc.atLineEnd) {
122 sc.ChangeState(SCE_SN_STRINGEOL);
123 sc.ForwardSetState(SCE_SN_CODE);
124 visibleChars = 0;
126 } else if (sc.state == SCE_SN_SIGNAL) {
127 if (sc.atLineEnd) {
128 sc.ChangeState(SCE_SN_STRINGEOL);
129 sc.ForwardSetState(SCE_SN_CODE);
130 visibleChars = 0;
131 } else if (sc.ch == '\\') {
132 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
133 sc.Forward();
135 } else if (sc.ch == '\'') {
136 sc.ForwardSetState(SCE_SN_CODE);
138 } else if (sc.state == SCE_SN_REGEXTAG) {
139 if (!IsADigit(sc.ch)) {
140 sc.SetState(SCE_SN_CODE);
144 // Determine if a new state should be entered.
145 if (sc.state == SCE_SN_CODE) {
146 if (sc.ch == '$' && IsADigit(sc.chNext)) {
147 sc.SetState(SCE_SN_REGEXTAG);
148 sc.Forward();
149 } else if (IsADigit(sc.ch)) {
150 sc.SetState(SCE_SN_NUMBER);
151 } else if (IsAWordStart(sc.ch)) {
152 sc.SetState(SCE_SN_IDENTIFIER);
153 } else if (sc.Match('\'', '>')) {
154 sc.SetState(SCE_SN_DEFAULT);
155 sc.Forward(); // Eat the * so it isn't used for the end of the comment
156 } else if (sc.Match('/', '/')) {
157 if (sc.Match("//!")) // Nice to have a different comment style
158 sc.SetState(SCE_SN_COMMENTLINEBANG);
159 else
160 sc.SetState(SCE_SN_COMMENTLINE);
161 } else if (sc.Match('-', '-')) {
162 if (sc.Match("--!")) // Nice to have a different comment style
163 sc.SetState(SCE_SN_COMMENTLINEBANG);
164 else
165 sc.SetState(SCE_SN_COMMENTLINE);
166 } else if (sc.ch == '\"') {
167 sc.SetState(SCE_SN_STRING);
168 } else if (sc.ch == '\'') {
169 sc.SetState(SCE_SN_SIGNAL);
170 } else if (sc.ch == '#' && visibleChars == 0) {
171 // Preprocessor commands are alone on their line
172 sc.SetState(SCE_SN_PREPROCESSOR);
173 // Skip whitespace between # and preprocessor word
174 do {
175 sc.Forward();
176 } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
177 if (sc.atLineEnd) {
178 sc.SetState(SCE_SN_CODE);
180 } else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@') {
181 sc.SetState(SCE_SN_OPERATOR);
185 if (sc.atLineEnd) {
186 // Reset states to begining of colourise so no surprises
187 // if different sets of lines lexed.
188 visibleChars = 0;
190 if (!IsASpace(sc.ch)) {
191 visibleChars++;
194 sc.Complete();
197 // Store both the current line's fold level and the next lines in the
198 // level store to make it easy to pick up with each increment
199 // and to make it possible to fiddle the current level for "} else {".
200 static void FoldNoBoxSpecmanDoc(unsigned int startPos, int length, int,
201 Accessor &styler) {
202 bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
203 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
204 bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
205 unsigned int endPos = startPos + length;
206 int visibleChars = 0;
207 int lineCurrent = styler.GetLine(startPos);
208 int levelCurrent = SC_FOLDLEVELBASE;
209 if (lineCurrent > 0)
210 levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
211 int levelMinCurrent = levelCurrent;
212 int levelNext = levelCurrent;
213 char chNext = styler[startPos];
214 int styleNext = styler.StyleAt(startPos);
215 int style;
216 for (unsigned int i = startPos; i < endPos; i++) {
217 char ch = chNext;
218 chNext = styler.SafeGetCharAt(i + 1);
219 //int stylePrev = style;
220 style = styleNext;
221 styleNext = styler.StyleAt(i + 1);
222 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
223 if (foldComment && (style == SCE_SN_COMMENTLINE)) {
224 if (((ch == '/') && (chNext == '/')) ||
225 ((ch == '-') && (chNext == '-'))) {
226 char chNext2 = styler.SafeGetCharAt(i + 2);
227 if (chNext2 == '{') {
228 levelNext++;
229 } else if (chNext2 == '}') {
230 levelNext--;
234 if (style == SCE_SN_OPERATOR) {
235 if (ch == '{') {
236 // Measure the minimum before a '{' to allow
237 // folding on "} else {"
238 if (levelMinCurrent > levelNext) {
239 levelMinCurrent = levelNext;
241 levelNext++;
242 } else if (ch == '}') {
243 levelNext--;
246 if (atEOL) {
247 int levelUse = levelCurrent;
248 if (foldAtElse) {
249 levelUse = levelMinCurrent;
251 int lev = levelUse | levelNext << 16;
252 if (visibleChars == 0 && foldCompact)
253 lev |= SC_FOLDLEVELWHITEFLAG;
254 if (levelUse < levelNext)
255 lev |= SC_FOLDLEVELHEADERFLAG;
256 if (lev != styler.LevelAt(lineCurrent)) {
257 styler.SetLevel(lineCurrent, lev);
259 lineCurrent++;
260 levelCurrent = levelNext;
261 levelMinCurrent = levelCurrent;
262 visibleChars = 0;
264 if (!isspacechar(ch))
265 visibleChars++;
269 static void FoldSpecmanDoc(unsigned int startPos, int length, int initStyle, WordList *[],
270 Accessor &styler) {
271 FoldNoBoxSpecmanDoc(startPos, length, initStyle, styler);
274 static const char * const specmanWordLists[] = {
275 "Primary keywords and identifiers",
276 "Secondary keywords and identifiers",
277 "Sequence keywords and identifiers",
278 "User defined keywords and identifiers",
279 "Unused",
283 static void ColouriseSpecmanDocSensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
284 Accessor &styler) {
285 ColouriseSpecmanDoc(startPos, length, initStyle, keywordlists, styler, true);
289 LexerModule lmSpecman(SCLEX_SPECMAN, ColouriseSpecmanDocSensitive, "specman", FoldSpecmanDoc, specmanWordLists);