]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexMetapost.cxx
1 // Scintilla source code edit control
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 // Modified by instanton: July 10, 2007
7 // Folding based on keywordlists[]
9 // Copyright: 1998-2003 by Neil Hodgson <neilh@scintilla.org>
10 // The License.txt file describes the conditions under which this software may be distributed.
12 // This lexer is derived from the one written for the texwork environment (1999++) which in
13 // turn is inspired on texedit (1991++) which finds its roots in wdt (1986).
23 #include "Scintilla.h"
27 #include "LexAccessor.h"
29 #include "StyleContext.h"
30 #include "CharacterSet.h"
31 #include "LexerModule.h"
34 using namespace Scintilla
;
37 // val SCE_METAPOST_DEFAULT = 0
38 // val SCE_METAPOST_SPECIAL = 1
39 // val SCE_METAPOST_GROUP = 2
40 // val SCE_METAPOST_SYMBOL = 3
41 // val SCE_METAPOST_COMMAND = 4
42 // val SCE_METAPOST_TEXT = 5
44 // Definitions in SciTEGlobal.properties:
46 // Metapost Highlighting
49 // style.metapost.0=fore:#7F7F00
51 // style.metapost.1=fore:#007F7F
53 // style.metapost.2=fore:#880000
55 // style.metapost.3=fore:#7F7F00
57 // style.metapost.4=fore:#008800
59 // style.metapost.5=fore:#000000
61 // lexer.tex.comment.process=0
63 // Auxiliary functions:
65 static inline bool endOfLine(Accessor
&styler
, unsigned int i
) {
67 (styler
[i
] == '\n') || ((styler
[i
] == '\r') && (styler
.SafeGetCharAt(i
+ 1) != '\n')) ;
70 static inline bool isMETAPOSTcomment(int ch
) {
75 static inline bool isMETAPOSTone(int ch
) {
77 (ch
== '[') || (ch
== ']') || (ch
== '(') || (ch
== ')') ||
78 (ch
== ':') || (ch
== '=') || (ch
== '<') || (ch
== '>') ||
79 (ch
== '{') || (ch
== '}') || (ch
== '\'') || (ch
== '\"') ;
82 static inline bool isMETAPOSTtwo(int ch
) {
84 (ch
== ';') || (ch
== '$') || (ch
== '@') || (ch
== '#');
87 static inline bool isMETAPOSTthree(int ch
) {
89 (ch
== '.') || (ch
== '-') || (ch
== '+') || (ch
== '/') ||
90 (ch
== '*') || (ch
== ',') || (ch
== '|') || (ch
== '`') ||
91 (ch
== '!') || (ch
== '?') || (ch
== '^') || (ch
== '&') ||
95 static inline bool isMETAPOSTidentifier(int ch
) {
97 ((ch
>= 'a') && (ch
<= 'z')) || ((ch
>= 'A') && (ch
<= 'Z')) ||
101 static inline bool isMETAPOSTnumber(int ch
) {
103 (ch
>= '0') && (ch
<= '9') ;
106 static inline bool isMETAPOSTstring(int ch
) {
111 static inline bool isMETAPOSTcolon(int ch
) {
116 static inline bool isMETAPOSTequal(int ch
) {
121 static int CheckMETAPOSTInterface(
122 unsigned int startPos
,
125 int defaultInterface
) {
127 char lineBuffer
[1024] ;
128 unsigned int linePos
= 0 ;
130 // some day we can make something lexer.metapost.mapping=(none,0)(metapost,1)(mp,1)(metafun,2)...
132 if (styler
.SafeGetCharAt(0) == '%') {
133 for (unsigned int i
= 0; i
< startPos
+ length
; i
++) {
134 lineBuffer
[linePos
++] = styler
.SafeGetCharAt(i
) ;
135 if (endOfLine(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
136 lineBuffer
[linePos
] = '\0';
137 if (strstr(lineBuffer
, "interface=none")) {
139 } else if (strstr(lineBuffer
, "interface=metapost") || strstr(lineBuffer
, "interface=mp")) {
141 } else if (strstr(lineBuffer
, "interface=metafun")) {
143 } else if (styler
.SafeGetCharAt(1) == 'D' && strstr(lineBuffer
, "%D \\module")) {
144 // better would be to limit the search to just one line
147 return defaultInterface
;
153 return defaultInterface
;
156 static void ColouriseMETAPOSTDoc(
157 unsigned int startPos
,
160 WordList
*keywordlists
[],
163 styler
.StartAt(startPos
) ;
164 styler
.StartSegment(startPos
) ;
166 bool processComment
= styler
.GetPropertyInt("lexer.metapost.comment.process", 0) == 1 ;
167 int defaultInterface
= styler
.GetPropertyInt("lexer.metapost.interface.default", 1) ;
169 int currentInterface
= CheckMETAPOSTInterface(startPos
,length
,styler
,defaultInterface
) ;
171 // 0 no keyword highlighting
172 // 1 metapost keyword hightlighting
173 // 2+ metafun keyword hightlighting
175 int extraInterface
= 0 ;
177 if (currentInterface
!= 0) {
178 extraInterface
= currentInterface
;
181 WordList
&keywords
= *keywordlists
[0] ;
182 WordList
&keywords2
= *keywordlists
[extraInterface
-1] ;
184 StyleContext
sc(startPos
, length
, SCE_METAPOST_TEXT
, styler
) ;
189 bool inComment
= false ;
190 bool inString
= false ;
191 bool inClause
= false ;
193 bool going
= sc
.More() ; // needed because of a fuzzy end of file state
195 for (; going
; sc
.Forward()) {
197 if (! sc
.More()) { going
= false ; } // we need to go one behind the end of text
200 sc
.SetState(SCE_METAPOST_TEXT
) ;
206 sc
.SetState(SCE_METAPOST_TEXT
) ;
210 inString
= false ; // not correct but we want to stimulate one-lines
212 } else if (inString
) {
213 if (isMETAPOSTstring(sc
.ch
)) {
214 sc
.SetState(SCE_METAPOST_SPECIAL
) ;
215 sc
.ForwardSetState(SCE_METAPOST_TEXT
) ;
217 } else if (sc
.atLineEnd
) {
218 sc
.SetState(SCE_METAPOST_TEXT
) ;
222 inString
= false ; // not correct but we want to stimulate one-lines
225 if ((! isMETAPOSTidentifier(sc
.ch
)) && (sc
.LengthCurrent() > 0)) {
226 if (sc
.state
== SCE_METAPOST_COMMAND
) {
227 sc
.GetCurrent(key
, sizeof(key
)) ;
228 if ((strcmp(key
,"btex") == 0) || (strcmp(key
,"verbatimtex") == 0)) {
229 sc
.ChangeState(SCE_METAPOST_GROUP
) ;
232 if (strcmp(key
,"etex") == 0) {
233 sc
.ChangeState(SCE_METAPOST_GROUP
) ;
236 sc
.ChangeState(SCE_METAPOST_TEXT
) ;
239 if (keywords
&& keywords
.InList(key
)) {
240 sc
.ChangeState(SCE_METAPOST_COMMAND
) ;
241 } else if (keywords2
&& keywords2
.InList(key
)) {
242 sc
.ChangeState(SCE_METAPOST_EXTRA
) ;
244 sc
.ChangeState(SCE_METAPOST_TEXT
) ;
249 if (isMETAPOSTcomment(sc
.ch
)) {
251 sc
.SetState(SCE_METAPOST_SYMBOL
) ;
252 sc
.ForwardSetState(SCE_METAPOST_DEFAULT
) ;
253 inComment
= ! processComment
;
255 sc
.SetState(SCE_METAPOST_TEXT
) ;
257 } else if (isMETAPOSTstring(sc
.ch
)) {
259 sc
.SetState(SCE_METAPOST_SPECIAL
) ;
260 if (! isMETAPOSTstring(sc
.chNext
)) {
261 sc
.ForwardSetState(SCE_METAPOST_TEXT
) ;
265 sc
.SetState(SCE_METAPOST_TEXT
) ;
267 } else if (isMETAPOSTcolon(sc
.ch
)) {
269 if (! isMETAPOSTequal(sc
.chNext
)) {
270 sc
.SetState(SCE_METAPOST_COMMAND
) ;
273 sc
.SetState(SCE_METAPOST_SPECIAL
) ;
276 sc
.SetState(SCE_METAPOST_TEXT
) ;
278 } else if (isMETAPOSTone(sc
.ch
)) {
280 sc
.SetState(SCE_METAPOST_SPECIAL
) ;
282 sc
.SetState(SCE_METAPOST_TEXT
) ;
284 } else if (isMETAPOSTtwo(sc
.ch
)) {
286 sc
.SetState(SCE_METAPOST_GROUP
) ;
288 sc
.SetState(SCE_METAPOST_TEXT
) ;
290 } else if (isMETAPOSTthree(sc
.ch
)) {
292 sc
.SetState(SCE_METAPOST_SYMBOL
) ;
294 sc
.SetState(SCE_METAPOST_TEXT
) ;
296 } else if (isMETAPOSTidentifier(sc
.ch
)) {
297 if (sc
.state
!= SCE_METAPOST_COMMAND
) {
298 sc
.SetState(SCE_METAPOST_TEXT
) ;
299 sc
.ChangeState(SCE_METAPOST_COMMAND
) ;
301 } else if (isMETAPOSTnumber(sc
.ch
)) {
302 // rather redundant since for the moment we don't handle numbers
303 sc
.SetState(SCE_METAPOST_TEXT
) ;
304 } else if (sc
.atLineEnd
) {
305 sc
.SetState(SCE_METAPOST_TEXT
) ;
311 sc
.SetState(SCE_METAPOST_TEXT
) ;
321 // Hooks info the system:
323 static const char * const metapostWordListDesc
[] = {
329 static int classifyFoldPointMetapost(const char* s
,WordList
*keywordlists
[]) {
330 WordList
& keywordsStart
=*keywordlists
[3];
331 WordList
& keywordsStop1
=*keywordlists
[4];
333 if (keywordsStart
.InList(s
)) {return 1;}
334 else if (keywordsStop1
.InList(s
)) {return -1;}
339 static int ParseMetapostWord(unsigned int pos
, Accessor
&styler
, char *word
)
342 char ch
=styler
.SafeGetCharAt(pos
);
345 while(isMETAPOSTidentifier(ch
) && isalpha(ch
) && length
<100){
348 ch
=styler
.SafeGetCharAt(pos
+length
);
354 static void FoldMetapostDoc(unsigned int startPos
, int length
, int, WordList
*keywordlists
[], Accessor
&styler
)
356 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
357 unsigned int endPos
= startPos
+length
;
359 int lineCurrent
=styler
.GetLine(startPos
);
360 int levelPrev
=styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
361 int levelCurrent
=levelPrev
;
362 char chNext
=styler
[startPos
];
366 for (unsigned int i
=startPos
; i
< endPos
; i
++) {
368 chNext
=styler
.SafeGetCharAt(i
+1);
369 char chPrev
=styler
.SafeGetCharAt(i
-1);
370 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
372 if(i
==0 || chPrev
== '\r' || chPrev
=='\n'|| chPrev
==' '|| chPrev
=='(' || chPrev
=='$')
374 ParseMetapostWord(i
, styler
, buffer
);
375 levelCurrent
+= classifyFoldPointMetapost(buffer
,keywordlists
);
380 if (visibleChars
== 0 && foldCompact
)
381 lev
|= SC_FOLDLEVELWHITEFLAG
;
382 if ((levelCurrent
> levelPrev
) && (visibleChars
> 0))
383 lev
|= SC_FOLDLEVELHEADERFLAG
;
384 if (lev
!= styler
.LevelAt(lineCurrent
)) {
385 styler
.SetLevel(lineCurrent
, lev
);
388 levelPrev
= levelCurrent
;
392 if (!isspacechar(ch
))
395 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
396 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
397 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
402 LexerModule
lmMETAPOST(SCLEX_METAPOST
, ColouriseMETAPOSTDoc
, "metapost", FoldMetapostDoc
, metapostWordListDesc
);