]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexGAP.cxx
Interface fixes for Phoenix
[wxWidgets.git] / src / stc / scintilla / src / LexGAP.cxx
1 // Scintilla source code edit control
2 /** @file LexGAP.cxx
3 ** Lexer for the GAP language. (The GAP System for Computational Discrete Algebra)
4 ** http://www.gap-system.org
5 **/
6 // Copyright 2007 by Istvan Szollosi ( szteven <at> gmail <dot> com )
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
24 #ifdef SCI_NAMESPACE
25 using namespace Scintilla;
26 #endif
27
28 static inline bool IsGAPOperator(char ch) {
29 if (isalnum(ch)) return false;
30 if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ||
31 ch == '^' || ch == ',' || ch == '!' || ch == '.' ||
32 ch == '=' || ch == '<' || ch == '>' || ch == '(' ||
33 ch == ')' || ch == ';' || ch == '[' || ch == ']' ||
34 ch == '{' || ch == '}' || ch == ':' )
35 return true;
36 return false;
37 }
38
39 static void GetRange(unsigned int start, unsigned int end, Accessor &styler, char *s, unsigned int len) {
40 unsigned int i = 0;
41 while ((i < end - start + 1) && (i < len-1)) {
42 s[i] = static_cast<char>(styler[start + i]);
43 i++;
44 }
45 s[i] = '\0';
46 }
47
48 static void ColouriseGAPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {
49
50 WordList &keywords1 = *keywordlists[0];
51 WordList &keywords2 = *keywordlists[1];
52 WordList &keywords3 = *keywordlists[2];
53 WordList &keywords4 = *keywordlists[3];
54
55 // Do not leak onto next line
56 if (initStyle == SCE_GAP_STRINGEOL) initStyle = SCE_GAP_DEFAULT;
57
58 StyleContext sc(startPos, length, initStyle, styler);
59
60 for (; sc.More(); sc.Forward()) {
61
62 // Prevent SCE_GAP_STRINGEOL from leaking back to previous line
63 if ( sc.atLineStart ) {
64 if (sc.state == SCE_GAP_STRING) sc.SetState(SCE_GAP_STRING);
65 if (sc.state == SCE_GAP_CHAR) sc.SetState(SCE_GAP_CHAR);
66 }
67
68 // Handle line continuation generically
69 if (sc.ch == '\\' ) {
70 if (sc.chNext == '\n' || sc.chNext == '\r') {
71 sc.Forward();
72 if (sc.ch == '\r' && sc.chNext == '\n') {
73 sc.Forward();
74 }
75 continue;
76 }
77 }
78
79 // Determine if the current state should terminate
80 switch (sc.state) {
81 case SCE_GAP_OPERATOR :
82 sc.SetState(SCE_GAP_DEFAULT);
83 break;
84
85 case SCE_GAP_NUMBER :
86 if (!IsADigit(sc.ch)) {
87 if (sc.ch == '\\') {
88 if (!sc.atLineEnd) {
89 if (!IsADigit(sc.chNext)) {
90 sc.Forward();
91 sc.ChangeState(SCE_GAP_IDENTIFIER);
92 }
93 }
94 } else if (isalpha(sc.ch) || sc.ch == '_') {
95 sc.ChangeState(SCE_GAP_IDENTIFIER);
96 }
97 else sc.SetState(SCE_GAP_DEFAULT);
98 }
99 break;
100
101 case SCE_GAP_IDENTIFIER :
102 if (!(iswordstart(static_cast<char>(sc.ch)) || sc.ch == '$')) {
103 if (sc.ch == '\\') sc.Forward();
104 else {
105 char s[1000];
106 sc.GetCurrent(s, sizeof(s));
107 if (keywords1.InList(s)) {
108 sc.ChangeState(SCE_GAP_KEYWORD);
109 } else if (keywords2.InList(s)) {
110 sc.ChangeState(SCE_GAP_KEYWORD2);
111 } else if (keywords3.InList(s)) {
112 sc.ChangeState(SCE_GAP_KEYWORD3);
113 } else if (keywords4.InList(s)) {
114 sc.ChangeState(SCE_GAP_KEYWORD4);
115 }
116 sc.SetState(SCE_GAP_DEFAULT);
117 }
118 }
119 break;
120
121 case SCE_GAP_COMMENT :
122 if (sc.atLineEnd) {
123 sc.SetState(SCE_GAP_DEFAULT);
124 }
125 break;
126
127 case SCE_GAP_STRING:
128 if (sc.atLineEnd) {
129 sc.ChangeState(SCE_GAP_STRINGEOL);
130 } else if (sc.ch == '\\') {
131 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
132 sc.Forward();
133 }
134 } else if (sc.ch == '\"') {
135 sc.ForwardSetState(SCE_GAP_DEFAULT);
136 }
137 break;
138
139 case SCE_GAP_CHAR:
140 if (sc.atLineEnd) {
141 sc.ChangeState(SCE_GAP_STRINGEOL);
142 } else if (sc.ch == '\\') {
143 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
144 sc.Forward();
145 }
146 } else if (sc.ch == '\'') {
147 sc.ForwardSetState(SCE_GAP_DEFAULT);
148 }
149 break;
150
151 case SCE_GAP_STRINGEOL:
152 if (sc.atLineStart) {
153 sc.SetState(SCE_GAP_DEFAULT);
154 }
155 break;
156 }
157
158 // Determine if a new state should be entered
159 if (sc.state == SCE_GAP_DEFAULT) {
160 if (IsGAPOperator(static_cast<char>(sc.ch))) {
161 sc.SetState(SCE_GAP_OPERATOR);
162 }
163 else if (IsADigit(sc.ch)) {
164 sc.SetState(SCE_GAP_NUMBER);
165 } else if (isalpha(sc.ch) || sc.ch == '_' || sc.ch == '\\' || sc.ch == '$' || sc.ch == '~') {
166 sc.SetState(SCE_GAP_IDENTIFIER);
167 if (sc.ch == '\\') sc.Forward();
168 } else if (sc.ch == '#') {
169 sc.SetState(SCE_GAP_COMMENT);
170 } else if (sc.ch == '\"') {
171 sc.SetState(SCE_GAP_STRING);
172 } else if (sc.ch == '\'') {
173 sc.SetState(SCE_GAP_CHAR);
174 }
175 }
176
177 }
178 sc.Complete();
179 }
180
181 static int ClassifyFoldPointGAP(const char* s) {
182 int level = 0;
183 if (strcmp(s, "function") == 0 ||
184 strcmp(s, "do") == 0 ||
185 strcmp(s, "if") == 0 ||
186 strcmp(s, "repeat") == 0 ) {
187 level = 1;
188 } else if (strcmp(s, "end") == 0 ||
189 strcmp(s, "od") == 0 ||
190 strcmp(s, "fi") == 0 ||
191 strcmp(s, "until") == 0 ) {
192 level = -1;
193 }
194 return level;
195 }
196
197 static void FoldGAPDoc( unsigned int startPos, int length, int initStyle, WordList** , Accessor &styler) {
198 unsigned int endPos = startPos + length;
199 int visibleChars = 0;
200 int lineCurrent = styler.GetLine(startPos);
201 int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
202 int levelCurrent = levelPrev;
203 char chNext = styler[startPos];
204 int styleNext = styler.StyleAt(startPos);
205 int style = initStyle;
206
207 int lastStart = 0;
208
209 for (unsigned int i = startPos; i < endPos; i++) {
210 char ch = chNext;
211 chNext = styler.SafeGetCharAt(i + 1);
212 int stylePrev = style;
213 style = styleNext;
214 styleNext = styler.StyleAt(i + 1);
215 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
216
217 if (stylePrev != SCE_GAP_KEYWORD && style == SCE_GAP_KEYWORD) {
218 // Store last word start point.
219 lastStart = i;
220 }
221
222 if (stylePrev == SCE_GAP_KEYWORD) {
223 if(iswordchar(ch) && !iswordchar(chNext)) {
224 char s[100];
225 GetRange(lastStart, i, styler, s, sizeof(s));
226 levelCurrent += ClassifyFoldPointGAP(s);
227 }
228 }
229
230 if (atEOL) {
231 int lev = levelPrev;
232 if ((levelCurrent > levelPrev) && (visibleChars > 0))
233 lev |= SC_FOLDLEVELHEADERFLAG;
234 if (lev != styler.LevelAt(lineCurrent)) {
235 styler.SetLevel(lineCurrent, lev);
236 }
237 lineCurrent++;
238 levelPrev = levelCurrent;
239 visibleChars = 0;
240 }
241
242 if (!isspacechar(ch))
243 visibleChars++;
244 }
245
246 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
247 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
248 }
249
250 static const char * const GAPWordListDesc[] = {
251 "Keywords 1",
252 "Keywords 2",
253 "Keywords 3 (unused)",
254 "Keywords 4 (unused)",
255 0
256 };
257
258 LexerModule lmGAP(
259 SCLEX_GAP,
260 ColouriseGAPDoc,
261 "gap",
262 FoldGAPDoc,
263 GAPWordListDesc);