1 // Scintilla source code edit control
2 /** @file LexMaxima.cxx
3 ** Lexer for Maxima (http://maxima.sourceforge.net).
4 ** Written by Gunter Königsmann based on the lisp lexer by Alexey Yutkin and Neil Hodgson .
5 **/
6 // Copyright 2018 by Gunter Königsmann <wxMaxima@physikbuch.de>
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 <stdio.h>
12 #include <stdarg.h>
13 #include <assert.h>
14 #include <ctype.h>
15
16 #include "ILexer.h"
17 #include "Scintilla.h"
18 #include "SciLexer.h"
19
20 #include "WordList.h"
21 #include "LexAccessor.h"
22 #include "Accessor.h"
23 #include "StyleContext.h"
24 #include "CharacterSet.h"
25 #include "LexerModule.h"
26 using namespace Scintilla;
27
isMaximaoperator(char ch)28 static inline bool isMaximaoperator(char ch) {
29 return (ch == '\'' || ch == '`' || ch == '(' ||
30 ch == ')' || ch == '[' || ch == ']' ||
31 ch == '{' || ch == '}' || ch == '!' ||
32 ch == '*' || ch == '/' || ch == '^' ||
33 ch == ',' || ch == ':' || ch == '+' ||
34 ch == '-');
35 }
36
ColouriseMaximaDoc(Sci_PositionU startPos,Sci_Position length,int lastStyle,WordList * [],Accessor & styler)37 static void ColouriseMaximaDoc(Sci_PositionU startPos, Sci_Position length, int lastStyle,
38 WordList *[],
39 Accessor &styler) {
40
41 styler.StartAt(startPos);
42
43 Sci_PositionU lengthDoc = startPos + length;
44 styler.StartSegment(startPos);
45
46 Sci_PositionU i = startPos;
47
48 // If we are in the middle of a comment we go back to its start before highlighting
49 if(lastStyle == SCE_MAXIMA_COMMENT)
50 {
51 while((i>0) &&
52 !((styler.SafeGetCharAt(i+1) == '*') && (styler.SafeGetCharAt(i) == '/')))
53 i--;
54 }
55
56 for (; i < lengthDoc; i++) {
57 char ch = styler.SafeGetCharAt(i);
58 char chNext = styler.SafeGetCharAt(i + 1);
59
60 if (styler.IsLeadByte(ch))
61 continue;
62
63 // Handle comments.
64 // Comments start with /* and end with */
65 if((ch == '/') && (chNext == '*'))
66 {
67 i++;i++;
68
69 chNext = styler.SafeGetCharAt(i);
70 for (; i < lengthDoc; i++)
71 {
72 ch = chNext;
73 chNext = styler.SafeGetCharAt(i + 1);
74 if((ch == '*') && (chNext == '/'))
75 {
76 i++;
77 i++;
78 break;
79 }
80 }
81 if(i > lengthDoc)
82 i = lengthDoc;
83 i--;
84 styler.ColourTo(i, SCE_MAXIMA_COMMENT);
85 continue;
86 }
87
88 // Handle Operators
89 if(isMaximaoperator(ch))
90 {
91 styler.ColourTo(i, SCE_MAXIMA_OPERATOR);
92 continue;
93 }
94
95 // Handle command endings.
96 if((ch == '$') || (ch == ';'))
97 {
98 styler.ColourTo(i, SCE_MAXIMA_COMMANDENDING);
99 continue;
100 }
101
102 // Handle numbers. Numbers always begin with a digit.
103 if(IsASCII(ch) && isdigit(ch))
104 {
105 i++;
106 for (; i < lengthDoc; i++)
107 {
108 ch = chNext;
109 chNext = styler.SafeGetCharAt(i + 1);
110
111 if(ch == '.')
112 continue;
113
114 // A "e" or similar can be followed by a "+" or a "-"
115 if(((ch == 'e') || (ch == 'b') || (ch == 'g') || (ch == 'f')) &&
116 ((chNext == '+') || (chNext == '-')))
117 {
118 i++;
119 chNext = styler.SafeGetCharAt(i + 1);
120 continue;
121 }
122
123 if(!IsASCII(ch) || !(isdigit(ch) || islower(ch) || isupper(ch)))
124 {
125 i--;
126 break;
127 }
128 }
129 styler.ColourTo(i, SCE_MAXIMA_NUMBER);
130 continue;
131 }
132
133 // Handle strings
134 if(ch == '\"')
135 {
136 i++;
137 for (; i < lengthDoc; i++)
138 {
139 ch = chNext;
140 chNext = styler.SafeGetCharAt(i + 1);
141 if(ch == '\\')
142 i++;
143 else
144 {
145 if(ch == '\"')
146 break;
147 }
148 }
149 styler.ColourTo(i, SCE_MAXIMA_STRING);
150 continue;
151 }
152
153 // Handle keywords. Maxima treats Non-ASCII chars as ordinary letters.
154 if(((!IsASCII(ch))) || isalpha(ch) || (ch == '_'))
155 {
156 char cmd[100];
157 int cmdidx = 0;
158 memset(cmd,0,100);
159 cmd[cmdidx++] = ch;
160 i++;
161 for (; i < lengthDoc; i++)
162 {
163 ch = chNext;
164 chNext = styler.SafeGetCharAt(i + 1);
165 if(ch == '\\')
166 {
167 if(cmdidx < 99)
168 cmd[cmdidx++] = ch;
169 i++;
170 if(cmdidx < 99)
171 cmd[cmdidx++] = ch;
172 continue;
173 }
174 if(isMaximaoperator(ch) || ((IsASCII(ch) && !isalpha(ch) && !isdigit(ch) && (ch != '_'))))
175 {
176 i--;
177 break;
178 }
179 if(cmdidx < 99)
180 cmd[cmdidx++] = ch;
181 }
182
183 // A few known keywords
184 if(
185 (strncmp(cmd,"if",99) == 0) ||
186 (strncmp(cmd,"then",99) == 0) ||
187 (strncmp(cmd,"else",99) == 0) ||
188 (strncmp(cmd,"thru",99) == 0) ||
189 (strncmp(cmd,"for",99) == 0) ||
190 (strncmp(cmd,"while",99) == 0) ||
191 (strncmp(cmd,"do",99) == 0)
192 )
193 {
194 styler.ColourTo(i, SCE_MAXIMA_COMMAND);
195 continue;
196 }
197
198 // All other keywords are functions if they are followed
199 // by an opening parenthesis
200 char nextNonwhitespace = ' ';
201 for (Sci_PositionU o = i + 1; o < lengthDoc; o++)
202 {
203 nextNonwhitespace = styler.SafeGetCharAt(o);
204 if(!IsASCII(nextNonwhitespace) || !isspacechar(nextNonwhitespace))
205 break;
206 }
207 if(nextNonwhitespace == '(')
208 {
209 styler.ColourTo(i, SCE_MAXIMA_COMMAND);
210 }
211 else
212 {
213 styler.ColourTo(i, SCE_MAXIMA_VARIABLE);
214 }
215 continue;
216 }
217
218 styler.ColourTo(i-1, SCE_MAXIMA_UNKNOWN);
219 }
220 }
221
222 LexerModule lmMaxima(SCLEX_MAXIMA, ColouriseMaximaDoc, "maxima", 0, 0);
223