scintilla: Update scintilla with changeset 3662:1d1c06df8a2f using gtk+3
[anjuta-extras.git] / plugins / scintilla / scintilla / LexGAP.cxx
blobfb30660986e8c3bd4c2b4851b9e29c611a78b7d4
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.
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdio.h>
12 #include <stdarg.h>
13 #include <assert.h>
14 #include <ctype.h>
16 #include "ILexer.h"
17 #include "Scintilla.h"
18 #include "SciLexer.h"
20 #include "WordList.h"
21 #include "LexAccessor.h"
22 #include "Accessor.h"
23 #include "StyleContext.h"
24 #include "CharacterSet.h"
25 #include "LexerModule.h"
27 #ifdef SCI_NAMESPACE
28 using namespace Scintilla;
29 #endif
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 == ':' )
38 return true;
39 return false;
42 static void GetRange(unsigned int start, unsigned int end, Accessor &styler, char *s, unsigned int len) {
43 unsigned int i = 0;
44 while ((i < end - start + 1) && (i < len-1)) {
45 s[i] = static_cast<char>(styler[start + i]);
46 i++;
48 s[i] = '\0';
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
72 if (sc.ch == '\\' ) {
73 if (sc.chNext == '\n' || sc.chNext == '\r') {
74 sc.Forward();
75 if (sc.ch == '\r' && sc.chNext == '\n') {
76 sc.Forward();
78 continue;
82 // Determine if the current state should terminate
83 switch (sc.state) {
84 case SCE_GAP_OPERATOR :
85 sc.SetState(SCE_GAP_DEFAULT);
86 break;
88 case SCE_GAP_NUMBER :
89 if (!IsADigit(sc.ch)) {
90 if (sc.ch == '\\') {
91 if (!sc.atLineEnd) {
92 if (!IsADigit(sc.chNext)) {
93 sc.Forward();
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);
102 break;
104 case SCE_GAP_IDENTIFIER :
105 if (!(iswordstart(static_cast<char>(sc.ch)) || sc.ch == '$')) {
106 if (sc.ch == '\\') sc.Forward();
107 else {
108 char s[1000];
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);
122 break;
124 case SCE_GAP_COMMENT :
125 if (sc.atLineEnd) {
126 sc.SetState(SCE_GAP_DEFAULT);
128 break;
130 case SCE_GAP_STRING:
131 if (sc.atLineEnd) {
132 sc.ChangeState(SCE_GAP_STRINGEOL);
133 } else if (sc.ch == '\\') {
134 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
135 sc.Forward();
137 } else if (sc.ch == '\"') {
138 sc.ForwardSetState(SCE_GAP_DEFAULT);
140 break;
142 case SCE_GAP_CHAR:
143 if (sc.atLineEnd) {
144 sc.ChangeState(SCE_GAP_STRINGEOL);
145 } else if (sc.ch == '\\') {
146 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
147 sc.Forward();
149 } else if (sc.ch == '\'') {
150 sc.ForwardSetState(SCE_GAP_DEFAULT);
152 break;
154 case SCE_GAP_STRINGEOL:
155 if (sc.atLineStart) {
156 sc.SetState(SCE_GAP_DEFAULT);
158 break;
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);
181 sc.Complete();
184 static int ClassifyFoldPointGAP(const char* s) {
185 int level = 0;
186 if (strcmp(s, "function") == 0 ||
187 strcmp(s, "do") == 0 ||
188 strcmp(s, "if") == 0 ||
189 strcmp(s, "repeat") == 0 ) {
190 level = 1;
191 } else if (strcmp(s, "end") == 0 ||
192 strcmp(s, "od") == 0 ||
193 strcmp(s, "fi") == 0 ||
194 strcmp(s, "until") == 0 ) {
195 level = -1;
197 return level;
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;
210 int lastStart = 0;
212 for (unsigned int i = startPos; i < endPos; i++) {
213 char ch = chNext;
214 chNext = styler.SafeGetCharAt(i + 1);
215 int stylePrev = style;
216 style = styleNext;
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.
222 lastStart = i;
225 if (stylePrev == SCE_GAP_KEYWORD) {
226 if(iswordchar(ch) && !iswordchar(chNext)) {
227 char s[100];
228 GetRange(lastStart, i, styler, s, sizeof(s));
229 levelCurrent += ClassifyFoldPointGAP(s);
233 if (atEOL) {
234 int lev = levelPrev;
235 if ((levelCurrent > levelPrev) && (visibleChars > 0))
236 lev |= SC_FOLDLEVELHEADERFLAG;
237 if (lev != styler.LevelAt(lineCurrent)) {
238 styler.SetLevel(lineCurrent, lev);
240 lineCurrent++;
241 levelPrev = levelCurrent;
242 visibleChars = 0;
245 if (!isspacechar(ch))
246 visibleChars++;
249 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
250 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
253 static const char * const GAPWordListDesc[] = {
254 "Keywords 1",
255 "Keywords 2",
256 "Keywords 3 (unused)",
257 "Keywords 4 (unused)",
261 LexerModule lmGAP(
262 SCLEX_GAP,
263 ColouriseGAPDoc,
264 "gap",
265 FoldGAPDoc,
266 GAPWordListDesc);