]>
Commit | Line | Data |
---|---|---|
8e54aaed RD |
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 | |
1e9bafca RD |
163 | // 1 metapost keyword hightlighting |
164 | // 2+ metafun keyword hightlighting | |
8e54aaed RD |
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); |