]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexGAP.cxx
1 // Scintilla source code edit control
3 ** Lexer for the GAP language. (The GAP System for Computational Discrete Algebra)
4 ** http://www.gap-system.org
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.
17 #include "Scintilla.h"
21 #include "LexAccessor.h"
23 #include "StyleContext.h"
24 #include "CharacterSet.h"
25 #include "LexerModule.h"
28 using namespace Scintilla
;
31 static inline bool IsGAPOperator(char ch
) {
32 if (isascii(ch
) && isalnum(ch
)) return false;
33 if (ch
== '+' || ch
== '-' || ch
== '*' || ch
== '/' ||
34 ch
== '^' || ch
== ',' || ch
== '!' || ch
== '.' ||
35 ch
== '=' || ch
== '<' || ch
== '>' || ch
== '(' ||
36 ch
== ')' || ch
== ';' || ch
== '[' || ch
== ']' ||
37 ch
== '{' || ch
== '}' || ch
== ':' )
42 static void GetRange(unsigned int start
, unsigned int end
, Accessor
&styler
, char *s
, unsigned int len
) {
44 while ((i
< end
- start
+ 1) && (i
< len
-1)) {
45 s
[i
] = static_cast<char>(styler
[start
+ i
]);
51 static void ColouriseGAPDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[], Accessor
&styler
) {
53 WordList
&keywords1
= *keywordlists
[0];
54 WordList
&keywords2
= *keywordlists
[1];
55 WordList
&keywords3
= *keywordlists
[2];
56 WordList
&keywords4
= *keywordlists
[3];
58 // Do not leak onto next line
59 if (initStyle
== SCE_GAP_STRINGEOL
) initStyle
= SCE_GAP_DEFAULT
;
61 StyleContext
sc(startPos
, length
, initStyle
, styler
);
63 for (; sc
.More(); sc
.Forward()) {
65 // Prevent SCE_GAP_STRINGEOL from leaking back to previous line
66 if ( sc
.atLineStart
) {
67 if (sc
.state
== SCE_GAP_STRING
) sc
.SetState(SCE_GAP_STRING
);
68 if (sc
.state
== SCE_GAP_CHAR
) sc
.SetState(SCE_GAP_CHAR
);
71 // Handle line continuation generically
73 if (sc
.chNext
== '\n' || sc
.chNext
== '\r') {
75 if (sc
.ch
== '\r' && sc
.chNext
== '\n') {
82 // Determine if the current state should terminate
84 case SCE_GAP_OPERATOR
:
85 sc
.SetState(SCE_GAP_DEFAULT
);
89 if (!IsADigit(sc
.ch
)) {
92 if (!IsADigit(sc
.chNext
)) {
94 sc
.ChangeState(SCE_GAP_IDENTIFIER
);
97 } else if (isalpha(sc
.ch
) || sc
.ch
== '_') {
98 sc
.ChangeState(SCE_GAP_IDENTIFIER
);
100 else sc
.SetState(SCE_GAP_DEFAULT
);
104 case SCE_GAP_IDENTIFIER
:
105 if (!(iswordstart(static_cast<char>(sc
.ch
)) || sc
.ch
== '$')) {
106 if (sc
.ch
== '\\') sc
.Forward();
109 sc
.GetCurrent(s
, sizeof(s
));
110 if (keywords1
.InList(s
)) {
111 sc
.ChangeState(SCE_GAP_KEYWORD
);
112 } else if (keywords2
.InList(s
)) {
113 sc
.ChangeState(SCE_GAP_KEYWORD2
);
114 } else if (keywords3
.InList(s
)) {
115 sc
.ChangeState(SCE_GAP_KEYWORD3
);
116 } else if (keywords4
.InList(s
)) {
117 sc
.ChangeState(SCE_GAP_KEYWORD4
);
119 sc
.SetState(SCE_GAP_DEFAULT
);
124 case SCE_GAP_COMMENT
:
126 sc
.SetState(SCE_GAP_DEFAULT
);
132 sc
.ChangeState(SCE_GAP_STRINGEOL
);
133 } else if (sc
.ch
== '\\') {
134 if (sc
.chNext
== '\"' || sc
.chNext
== '\'' || sc
.chNext
== '\\') {
137 } else if (sc
.ch
== '\"') {
138 sc
.ForwardSetState(SCE_GAP_DEFAULT
);
144 sc
.ChangeState(SCE_GAP_STRINGEOL
);
145 } else if (sc
.ch
== '\\') {
146 if (sc
.chNext
== '\"' || sc
.chNext
== '\'' || sc
.chNext
== '\\') {
149 } else if (sc
.ch
== '\'') {
150 sc
.ForwardSetState(SCE_GAP_DEFAULT
);
154 case SCE_GAP_STRINGEOL
:
155 if (sc
.atLineStart
) {
156 sc
.SetState(SCE_GAP_DEFAULT
);
161 // Determine if a new state should be entered
162 if (sc
.state
== SCE_GAP_DEFAULT
) {
163 if (IsGAPOperator(static_cast<char>(sc
.ch
))) {
164 sc
.SetState(SCE_GAP_OPERATOR
);
166 else if (IsADigit(sc
.ch
)) {
167 sc
.SetState(SCE_GAP_NUMBER
);
168 } else if (isalpha(sc
.ch
) || sc
.ch
== '_' || sc
.ch
== '\\' || sc
.ch
== '$' || sc
.ch
== '~') {
169 sc
.SetState(SCE_GAP_IDENTIFIER
);
170 if (sc
.ch
== '\\') sc
.Forward();
171 } else if (sc
.ch
== '#') {
172 sc
.SetState(SCE_GAP_COMMENT
);
173 } else if (sc
.ch
== '\"') {
174 sc
.SetState(SCE_GAP_STRING
);
175 } else if (sc
.ch
== '\'') {
176 sc
.SetState(SCE_GAP_CHAR
);
184 static int ClassifyFoldPointGAP(const char* s
) {
186 if (strcmp(s
, "function") == 0 ||
187 strcmp(s
, "do") == 0 ||
188 strcmp(s
, "if") == 0 ||
189 strcmp(s
, "repeat") == 0 ) {
191 } else if (strcmp(s
, "end") == 0 ||
192 strcmp(s
, "od") == 0 ||
193 strcmp(s
, "fi") == 0 ||
194 strcmp(s
, "until") == 0 ) {
200 static void FoldGAPDoc( unsigned int startPos
, int length
, int initStyle
, WordList
** , Accessor
&styler
) {
201 unsigned int endPos
= startPos
+ length
;
202 int visibleChars
= 0;
203 int lineCurrent
= styler
.GetLine(startPos
);
204 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
205 int levelCurrent
= levelPrev
;
206 char chNext
= styler
[startPos
];
207 int styleNext
= styler
.StyleAt(startPos
);
208 int style
= initStyle
;
212 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
214 chNext
= styler
.SafeGetCharAt(i
+ 1);
215 int stylePrev
= style
;
217 styleNext
= styler
.StyleAt(i
+ 1);
218 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
220 if (stylePrev
!= SCE_GAP_KEYWORD
&& style
== SCE_GAP_KEYWORD
) {
221 // Store last word start point.
225 if (stylePrev
== SCE_GAP_KEYWORD
) {
226 if(iswordchar(ch
) && !iswordchar(chNext
)) {
228 GetRange(lastStart
, i
, styler
, s
, sizeof(s
));
229 levelCurrent
+= ClassifyFoldPointGAP(s
);
235 if ((levelCurrent
> levelPrev
) && (visibleChars
> 0))
236 lev
|= SC_FOLDLEVELHEADERFLAG
;
237 if (lev
!= styler
.LevelAt(lineCurrent
)) {
238 styler
.SetLevel(lineCurrent
, lev
);
241 levelPrev
= levelCurrent
;
245 if (!isspacechar(ch
))
249 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
250 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
253 static const char * const GAPWordListDesc
[] = {
256 "Keywords 3 (unused)",
257 "Keywords 4 (unused)",