]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexMetapost.cxx
Updated to Scintilla 1.67
[wxWidgets.git] / src / stc / scintilla / src / LexMetapost.cxx
1 // Scintilla source code edit control
2
3 // File: LexMetapost.cxx - general context conformant metapost coloring scheme
4 // Author: Hans Hagen - PRAGMA ADE - Hasselt NL - www.pragma-ade.com
5 // Version: September 28, 2003
6
7 // Copyright: 1998-2003 by Neil Hodgson <neilh@scintilla.org>
8 // The License.txt file describes the conditions under which this software may be distributed.
9
10 // This lexer is derived from the one written for the texwork environment (1999++) which in
11 // turn is inspired on texedit (1991++) which finds its roots in wdt (1986).
12
13 #include <stdlib.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <stdio.h>
17 #include <stdarg.h>
18
19 #include "Platform.h"
20
21 #include "PropSet.h"
22 #include "Accessor.h"
23 #include "KeyWords.h"
24 #include "Scintilla.h"
25 #include "SciLexer.h"
26 #include "StyleContext.h"
27
28 // val SCE_METAPOST_DEFAULT = 0
29 // val SCE_METAPOST_SPECIAL = 1
30 // val SCE_METAPOST_GROUP = 2
31 // val SCE_METAPOST_SYMBOL = 3
32 // val SCE_METAPOST_COMMAND = 4
33 // val SCE_METAPOST_TEXT = 5
34
35 // Definitions in SciTEGlobal.properties:
36 //
37 // Metapost Highlighting
38 //
39 // # Default
40 // style.metapost.0=fore:#7F7F00
41 // # Special
42 // style.metapost.1=fore:#007F7F
43 // # Group
44 // style.metapost.2=fore:#880000
45 // # Symbol
46 // style.metapost.3=fore:#7F7F00
47 // # Command
48 // style.metapost.4=fore:#008800
49 // # Text
50 // style.metapost.5=fore:#000000
51
52 // lexer.tex.comment.process=0
53
54 // Auxiliary functions:
55
56 static inline bool endOfLine(Accessor &styler, unsigned int i) {
57 return
58 (styler[i] == '\n') || ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')) ;
59 }
60
61 static inline bool isMETAPOSTcomment(int ch) {
62 return
63 (ch == '%') ;
64 }
65
66 static inline bool isMETAPOSTone(int ch) {
67 return
68 (ch == '[') || (ch == ']') || (ch == '(') || (ch == ')') ||
69 (ch == ':') || (ch == '=') || (ch == '<') || (ch == '>') ||
70 (ch == '{') || (ch == '}') || (ch == '\'') || (ch == '\"') ;
71 }
72
73 static inline bool isMETAPOSTtwo(int ch) {
74 return
75 (ch == ';') || (ch == '$') || (ch == '@') || (ch == '#');
76 }
77
78 static inline bool isMETAPOSTthree(int ch) {
79 return
80 (ch == '.') || (ch == '-') || (ch == '+') || (ch == '/') ||
81 (ch == '*') || (ch == ',') || (ch == '|') || (ch == '`') ||
82 (ch == '!') || (ch == '?') || (ch == '^') || (ch == '&') ||
83 (ch == '%') ;
84 }
85
86 static inline bool isMETAPOSTidentifier(int ch) {
87 return
88 ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ||
89 (ch == '_') ;
90 }
91
92 static inline bool isMETAPOSTnumber(int ch) {
93 return
94 (ch >= '0') && (ch <= '9') ;
95 }
96
97 static inline bool isMETAPOSTstring(int ch) {
98 return
99 (ch == '\"') ;
100 }
101
102 static inline bool isMETAPOSTcolon(int ch) {
103 return
104 (ch == ':') ;
105 }
106
107 static inline bool isMETAPOSTequal(int ch) {
108 return
109 (ch == '=') ;
110 }
111
112 static int CheckMETAPOSTInterface(
113 unsigned int startPos,
114 int length,
115 Accessor &styler,
116 int defaultInterface) {
117
118 char lineBuffer[1024] ;
119 unsigned int linePos = 0 ;
120
121 // some day we can make something lexer.metapost.mapping=(none,0)(metapost,1)(mp,1)(metafun,2)...
122
123 if (styler.SafeGetCharAt(0) == '%') {
124 for (unsigned int i = 0; i < startPos + length; i++) {
125 lineBuffer[linePos++] = styler.SafeGetCharAt(i) ;
126 if (endOfLine(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
127 lineBuffer[linePos] = '\0';
128 if (strstr(lineBuffer, "interface=none")) {
129 return 0 ;
130 } else if (strstr(lineBuffer, "interface=metapost") || strstr(lineBuffer, "interface=mp")) {
131 return 1 ;
132 } else if (strstr(lineBuffer, "interface=metafun")) {
133 return 2 ;
134 } else if (styler.SafeGetCharAt(1) == 'D' && strstr(lineBuffer, "%D \\module")) {
135 // better would be to limit the search to just one line
136 return 2 ;
137 } else {
138 return defaultInterface ;
139 }
140 }
141 }
142 }
143
144 return defaultInterface ;
145 }
146
147 static void ColouriseMETAPOSTDoc(
148 unsigned int startPos,
149 int length,
150 int,
151 WordList *keywordlists[],
152 Accessor &styler) {
153
154 styler.StartAt(startPos) ;
155 styler.StartSegment(startPos) ;
156
157 bool processComment = styler.GetPropertyInt("lexer.metapost.comment.process", 0) == 1 ;
158 int defaultInterface = styler.GetPropertyInt("lexer.metapost.interface.default", 1) ;
159
160 int currentInterface = CheckMETAPOSTInterface(startPos,length,styler,defaultInterface) ;
161
162 // 0 no keyword highlighting
163 // 1 metapost keyword hightlighting
164 // 2+ metafun keyword hightlighting
165
166 int extraInterface = 0 ;
167
168 if (currentInterface != 0) {
169 extraInterface = currentInterface ;
170 }
171
172 WordList &keywords = *keywordlists[0] ;
173 WordList &keywords2 = *keywordlists[extraInterface-1] ;
174
175 StyleContext sc(startPos, length, SCE_METAPOST_TEXT, styler) ;
176
177 char key[100] ;
178
179 bool inTeX = false ;
180 bool inComment = false ;
181 bool inString = false ;
182 bool inClause = false ;
183
184 bool going = sc.More() ; // needed because of a fuzzy end of file state
185
186 for (; going; sc.Forward()) {
187
188 if (! sc.More()) { going = false ; } // we need to go one behind the end of text
189
190 if (inClause) {
191 sc.SetState(SCE_METAPOST_TEXT) ;
192 inClause = false ;
193 }
194
195 if (inComment) {
196 if (sc.atLineEnd) {
197 sc.SetState(SCE_METAPOST_TEXT) ;
198 inTeX = false ;
199 inComment = false ;
200 inClause = false ;
201 inString = false ; // not correct but we want to stimulate one-lines
202 }
203 } else if (inString) {
204 if (isMETAPOSTstring(sc.ch)) {
205 sc.SetState(SCE_METAPOST_SPECIAL) ;
206 sc.ForwardSetState(SCE_METAPOST_TEXT) ;
207 inString = false ;
208 } else if (sc.atLineEnd) {
209 sc.SetState(SCE_METAPOST_TEXT) ;
210 inTeX = false ;
211 inComment = false ;
212 inClause = false ;
213 inString = false ; // not correct but we want to stimulate one-lines
214 }
215 } else {
216 if ((! isMETAPOSTidentifier(sc.ch)) && (sc.LengthCurrent() > 0)) {
217 if (sc.state == SCE_METAPOST_COMMAND) {
218 sc.GetCurrent(key, sizeof(key)) ;
219 if ((strcmp(key,"btex") == 0) || (strcmp(key,"verbatimtex") == 0)) {
220 sc.ChangeState(SCE_METAPOST_GROUP) ;
221 inTeX = true ;
222 } else if (inTeX) {
223 if (strcmp(key,"etex") == 0) {
224 sc.ChangeState(SCE_METAPOST_GROUP) ;
225 inTeX = false ;
226 } else {
227 sc.ChangeState(SCE_METAPOST_TEXT) ;
228 }
229 } else {
230 if (keywords && keywords.InList(key)) {
231 sc.ChangeState(SCE_METAPOST_COMMAND) ;
232 } else if (keywords2 && keywords2.InList(key)) {
233 sc.ChangeState(SCE_METAPOST_EXTRA) ;
234 } else {
235 sc.ChangeState(SCE_METAPOST_TEXT) ;
236 }
237 }
238 }
239 }
240 if (isMETAPOSTcomment(sc.ch)) {
241 if (! inTeX) {
242 sc.SetState(SCE_METAPOST_SYMBOL) ;
243 sc.ForwardSetState(SCE_METAPOST_DEFAULT) ;
244 inComment = ! processComment ;
245 } else {
246 sc.SetState(SCE_METAPOST_TEXT) ;
247 }
248 } else if (isMETAPOSTstring(sc.ch)) {
249 if (! inTeX) {
250 sc.SetState(SCE_METAPOST_SPECIAL) ;
251 if (! isMETAPOSTstring(sc.chNext)) {
252 sc.ForwardSetState(SCE_METAPOST_TEXT) ;
253 }
254 inString = true ;
255 } else {
256 sc.SetState(SCE_METAPOST_TEXT) ;
257 }
258 } else if (isMETAPOSTcolon(sc.ch)) {
259 if (! inTeX) {
260 if (! isMETAPOSTequal(sc.chNext)) {
261 sc.SetState(SCE_METAPOST_COMMAND) ;
262 inClause = true ;
263 } else {
264 sc.SetState(SCE_METAPOST_SPECIAL) ;
265 }
266 } else {
267 sc.SetState(SCE_METAPOST_TEXT) ;
268 }
269 } else if (isMETAPOSTone(sc.ch)) {
270 if (! inTeX) {
271 sc.SetState(SCE_METAPOST_SPECIAL) ;
272 } else {
273 sc.SetState(SCE_METAPOST_TEXT) ;
274 }
275 } else if (isMETAPOSTtwo(sc.ch)) {
276 if (! inTeX) {
277 sc.SetState(SCE_METAPOST_GROUP) ;
278 } else {
279 sc.SetState(SCE_METAPOST_TEXT) ;
280 }
281 } else if (isMETAPOSTthree(sc.ch)) {
282 if (! inTeX) {
283 sc.SetState(SCE_METAPOST_SYMBOL) ;
284 } else {
285 sc.SetState(SCE_METAPOST_TEXT) ;
286 }
287 } else if (isMETAPOSTidentifier(sc.ch)) {
288 if (sc.state != SCE_METAPOST_COMMAND) {
289 sc.SetState(SCE_METAPOST_TEXT) ;
290 sc.ChangeState(SCE_METAPOST_COMMAND) ;
291 }
292 } else if (isMETAPOSTnumber(sc.ch)) {
293 // rather redundant since for the moment we don't handle numbers
294 sc.SetState(SCE_METAPOST_TEXT) ;
295 } else if (sc.atLineEnd) {
296 sc.SetState(SCE_METAPOST_TEXT) ;
297 inTeX = false ;
298 inComment = false ;
299 inClause = false ;
300 inString = false ;
301 } else {
302 sc.SetState(SCE_METAPOST_TEXT) ;
303 }
304 }
305
306 }
307
308 sc.Complete();
309
310 }
311
312 // Hooks info the system:
313
314 static const char * const metapostWordListDesc[] = {
315 "MetaPost",
316 "MetaFun",
317 0
318 } ;
319
320 LexerModule lmMETAPOST(SCLEX_METAPOST, ColouriseMETAPOSTDoc, "metapost", 0, metapostWordListDesc);