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.
19
#include "StyleContext.h"
21
#include "Scintilla.h"
25
using namespace Scintilla;
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 == ':' )
39
static void GetRange(unsigned int start, unsigned int end, Accessor &styler, char *s, unsigned int len) {
41
while ((i < end - start + 1) && (i < len-1)) {
42
s[i] = static_cast<char>(styler[start + i]);
48
static void ColouriseGAPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {
50
WordList &keywords1 = *keywordlists[0];
51
WordList &keywords2 = *keywordlists[1];
52
WordList &keywords3 = *keywordlists[2];
53
WordList &keywords4 = *keywordlists[3];
55
// Do not leak onto next line
56
if (initStyle == SCE_GAP_STRINGEOL) initStyle = SCE_GAP_DEFAULT;
58
StyleContext sc(startPos, length, initStyle, styler);
60
for (; sc.More(); sc.Forward()) {
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);
68
// Handle line continuation generically
70
if (sc.chNext == '\n' || sc.chNext == '\r') {
72
if (sc.ch == '\r' && sc.chNext == '\n') {
79
// Determine if the current state should terminate
81
case SCE_GAP_OPERATOR :
82
sc.SetState(SCE_GAP_DEFAULT);
86
if (!IsADigit(sc.ch)) {
89
if (!IsADigit(sc.chNext)) {
91
sc.ChangeState(SCE_GAP_IDENTIFIER);
94
} else if (isalpha(sc.ch) || sc.ch == '_') {
95
sc.ChangeState(SCE_GAP_IDENTIFIER);
97
else sc.SetState(SCE_GAP_DEFAULT);
101
case SCE_GAP_IDENTIFIER :
102
if (!(iswordstart(static_cast<char>(sc.ch)) || sc.ch == '$')) {
103
if (sc.ch == '\\') sc.Forward();
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);
116
sc.SetState(SCE_GAP_DEFAULT);
121
case SCE_GAP_COMMENT :
123
sc.SetState(SCE_GAP_DEFAULT);
129
sc.ChangeState(SCE_GAP_STRINGEOL);
130
} else if (sc.ch == '\\') {
131
if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
134
} else if (sc.ch == '\"') {
135
sc.ForwardSetState(SCE_GAP_DEFAULT);
141
sc.ChangeState(SCE_GAP_STRINGEOL);
142
} else if (sc.ch == '\\') {
143
if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
146
} else if (sc.ch == '\'') {
147
sc.ForwardSetState(SCE_GAP_DEFAULT);
151
case SCE_GAP_STRINGEOL:
152
if (sc.atLineStart) {
153
sc.SetState(SCE_GAP_DEFAULT);
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);
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);
181
static int ClassifyFoldPointGAP(const char* s) {
183
if (strcmp(s, "function") == 0 ||
184
strcmp(s, "do") == 0 ||
185
strcmp(s, "if") == 0 ||
186
strcmp(s, "repeat") == 0 ) {
188
} else if (strcmp(s, "end") == 0 ||
189
strcmp(s, "od") == 0 ||
190
strcmp(s, "fi") == 0 ||
191
strcmp(s, "until") == 0 ) {
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;
209
for (unsigned int i = startPos; i < endPos; i++) {
211
chNext = styler.SafeGetCharAt(i + 1);
212
int stylePrev = style;
214
styleNext = styler.StyleAt(i + 1);
215
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
217
if (stylePrev != SCE_GAP_KEYWORD && style == SCE_GAP_KEYWORD) {
218
// Store last word start point.
222
if (stylePrev == SCE_GAP_KEYWORD) {
223
if(iswordchar(ch) && !iswordchar(chNext)) {
225
GetRange(lastStart, i, styler, s, sizeof(s));
226
levelCurrent += ClassifyFoldPointGAP(s);
232
if ((levelCurrent > levelPrev) && (visibleChars > 0))
233
lev |= SC_FOLDLEVELHEADERFLAG;
234
if (lev != styler.LevelAt(lineCurrent)) {
235
styler.SetLevel(lineCurrent, lev);
238
levelPrev = levelCurrent;
242
if (!isspacechar(ch))
246
int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
247
styler.SetLevel(lineCurrent, levelPrev | flagsNext);
250
static const char * const GAPWordListDesc[] = {
253
"Keywords 3 (unused)",
254
"Keywords 4 (unused)",