]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexPOV.cxx
1 // Scintilla source code edit control
3 ** Lexer for POV-Ray SDL (Persistance of Vision Raytracer, Scene Description Language).
4 ** Written by Philippe Lhoste but this is mostly a derivative of LexCPP...
6 // Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
7 // The License.txt file describes the conditions under which this software may be distributed.
9 // Some points that distinguish from a simple C lexer:
10 // Identifiers start only by a character.
11 // No line continuation character.
12 // Strings are limited to 256 characters.
13 // Directives are similar to preprocessor commands,
14 // but we match directive keywords and colorize incorrect ones.
15 // Block comments can be nested (code stolen from my code in LexLua).
25 #include "Scintilla.h"
29 #include "LexAccessor.h"
31 #include "StyleContext.h"
32 #include "CharacterSet.h"
33 #include "LexerModule.h"
36 using namespace Scintilla
;
39 static inline bool IsAWordChar(int ch
) {
40 return ch
< 0x80 && (isalnum(ch
) || ch
== '_');
43 static inline bool IsAWordStart(int ch
) {
44 return ch
< 0x80 && isalpha(ch
);
47 static inline bool IsANumberChar(int ch
) {
48 // Not exactly following number definition (several dots are seen as OK, etc.)
49 // but probably enough in most cases.
51 (isdigit(ch
) || toupper(ch
) == 'E' ||
52 ch
== '.' || ch
== '-' || ch
== '+');
55 static void ColourisePovDoc(
56 unsigned int startPos
,
59 WordList
*keywordlists
[],
62 WordList
&keywords1
= *keywordlists
[0];
63 WordList
&keywords2
= *keywordlists
[1];
64 WordList
&keywords3
= *keywordlists
[2];
65 WordList
&keywords4
= *keywordlists
[3];
66 WordList
&keywords5
= *keywordlists
[4];
67 WordList
&keywords6
= *keywordlists
[5];
68 WordList
&keywords7
= *keywordlists
[6];
69 WordList
&keywords8
= *keywordlists
[7];
71 int currentLine
= styler
.GetLine(startPos
);
72 // Initialize the block comment /* */ nesting level, if we are inside such a comment.
73 int blockCommentLevel
= 0;
74 if (initStyle
== SCE_POV_COMMENT
) {
75 blockCommentLevel
= styler
.GetLineState(currentLine
- 1);
78 // Do not leak onto next line
79 if (initStyle
== SCE_POV_STRINGEOL
|| initStyle
== SCE_POV_COMMENTLINE
) {
80 initStyle
= SCE_POV_DEFAULT
;
85 StyleContext
sc(startPos
, length
, initStyle
, styler
);
87 for (; sc
.More(); sc
.Forward()) {
89 // Update the line state, so it can be seen by next line
90 currentLine
= styler
.GetLine(sc
.currentPos
);
91 if (sc
.state
== SCE_POV_COMMENT
) {
92 // Inside a block comment, we set the line state
93 styler
.SetLineState(currentLine
, blockCommentLevel
);
95 // Reset the line state
96 styler
.SetLineState(currentLine
, 0);
100 if (sc
.atLineStart
&& (sc
.state
== SCE_POV_STRING
)) {
101 // Prevent SCE_POV_STRINGEOL from leaking back to previous line
102 sc
.SetState(SCE_POV_STRING
);
105 // Determine if the current state should terminate.
106 if (sc
.state
== SCE_POV_OPERATOR
) {
107 sc
.SetState(SCE_POV_DEFAULT
);
108 } else if (sc
.state
== SCE_POV_NUMBER
) {
109 // We stop the number definition on non-numerical non-dot non-eE non-sign char
110 if (!IsANumberChar(sc
.ch
)) {
111 sc
.SetState(SCE_POV_DEFAULT
);
113 } else if (sc
.state
== SCE_POV_IDENTIFIER
) {
114 if (!IsAWordChar(sc
.ch
)) {
116 sc
.GetCurrent(s
, sizeof(s
));
117 if (keywords2
.InList(s
)) {
118 sc
.ChangeState(SCE_POV_WORD2
);
119 } else if (keywords3
.InList(s
)) {
120 sc
.ChangeState(SCE_POV_WORD3
);
121 } else if (keywords4
.InList(s
)) {
122 sc
.ChangeState(SCE_POV_WORD4
);
123 } else if (keywords5
.InList(s
)) {
124 sc
.ChangeState(SCE_POV_WORD5
);
125 } else if (keywords6
.InList(s
)) {
126 sc
.ChangeState(SCE_POV_WORD6
);
127 } else if (keywords7
.InList(s
)) {
128 sc
.ChangeState(SCE_POV_WORD7
);
129 } else if (keywords8
.InList(s
)) {
130 sc
.ChangeState(SCE_POV_WORD8
);
132 sc
.SetState(SCE_POV_DEFAULT
);
134 } else if (sc
.state
== SCE_POV_DIRECTIVE
) {
135 if (!IsAWordChar(sc
.ch
)) {
138 sc
.GetCurrent(s
, sizeof(s
));
140 // Skip # and whitespace between # and directive word
143 } while ((*p
== ' ' || *p
== '\t') && *p
!= '\0');
144 if (!keywords1
.InList(p
)) {
145 sc
.ChangeState(SCE_POV_BADDIRECTIVE
);
147 sc
.SetState(SCE_POV_DEFAULT
);
149 } else if (sc
.state
== SCE_POV_COMMENT
) {
150 if (sc
.Match('/', '*')) {
153 } else if (sc
.Match('*', '/') && blockCommentLevel
> 0) {
156 if (blockCommentLevel
== 0) {
157 sc
.ForwardSetState(SCE_POV_DEFAULT
);
160 } else if (sc
.state
== SCE_POV_COMMENTLINE
) {
162 sc
.ForwardSetState(SCE_POV_DEFAULT
);
164 } else if (sc
.state
== SCE_POV_STRING
) {
167 if (strchr("abfnrtuv0'\"", sc
.chNext
)) {
168 // Compound characters are counted as one.
169 // Note: for Unicode chars \u, we shouldn't count the next 4 digits...
172 } else if (sc
.ch
== '\"') {
173 sc
.ForwardSetState(SCE_POV_DEFAULT
);
174 } else if (sc
.atLineEnd
) {
175 sc
.ChangeState(SCE_POV_STRINGEOL
);
176 sc
.ForwardSetState(SCE_POV_DEFAULT
);
180 if (stringLen
> 256) {
181 // Strings are limited to 256 chars
182 sc
.SetState(SCE_POV_STRINGEOL
);
184 } else if (sc
.state
== SCE_POV_STRINGEOL
) {
186 if (sc
.chNext
== '\"' || sc
.chNext
== '\\') {
189 } else if (sc
.ch
== '\"') {
190 sc
.ForwardSetState(SCE_C_DEFAULT
);
191 } else if (sc
.atLineEnd
) {
192 sc
.ForwardSetState(SCE_POV_DEFAULT
);
196 // Determine if a new state should be entered.
197 if (sc
.state
== SCE_POV_DEFAULT
) {
198 if (IsADigit(sc
.ch
) || (sc
.ch
== '.' && IsADigit(sc
.chNext
))) {
199 sc
.SetState(SCE_POV_NUMBER
);
200 } else if (IsAWordStart(sc
.ch
)) {
201 sc
.SetState(SCE_POV_IDENTIFIER
);
202 } else if (sc
.Match('/', '*')) {
203 blockCommentLevel
= 1;
204 sc
.SetState(SCE_POV_COMMENT
);
205 sc
.Forward(); // Eat the * so it isn't used for the end of the comment
206 } else if (sc
.Match('/', '/')) {
207 sc
.SetState(SCE_POV_COMMENTLINE
);
208 } else if (sc
.ch
== '\"') {
209 sc
.SetState(SCE_POV_STRING
);
211 } else if (sc
.ch
== '#') {
212 sc
.SetState(SCE_POV_DIRECTIVE
);
213 // Skip whitespace between # and directive word
216 } while ((sc
.ch
== ' ' || sc
.ch
== '\t') && sc
.More());
218 sc
.SetState(SCE_POV_DEFAULT
);
220 } else if (isoperator(static_cast<char>(sc
.ch
))) {
221 sc
.SetState(SCE_POV_OPERATOR
);
228 static void FoldPovDoc(
229 unsigned int startPos
,
235 bool foldComment
= styler
.GetPropertyInt("fold.comment") != 0;
236 bool foldDirective
= styler
.GetPropertyInt("fold.directive") != 0;
237 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
238 unsigned int endPos
= startPos
+ length
;
239 int visibleChars
= 0;
240 int lineCurrent
= styler
.GetLine(startPos
);
241 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
242 int levelCurrent
= levelPrev
;
243 char chNext
= styler
[startPos
];
244 int styleNext
= styler
.StyleAt(startPos
);
245 int style
= initStyle
;
246 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
248 chNext
= styler
.SafeGetCharAt(i
+ 1);
249 int stylePrev
= style
;
251 styleNext
= styler
.StyleAt(i
+ 1);
252 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
253 if (foldComment
&& (style
== SCE_POV_COMMENT
)) {
254 if (stylePrev
!= SCE_POV_COMMENT
) {
256 } else if ((styleNext
!= SCE_POV_COMMENT
) && !atEOL
) {
257 // Comments don't end at end of line and the next character may be unstyled.
261 if (foldComment
&& (style
== SCE_POV_COMMENTLINE
)) {
262 if ((ch
== '/') && (chNext
== '/')) {
263 char chNext2
= styler
.SafeGetCharAt(i
+ 2);
264 if (chNext2
== '{') {
266 } else if (chNext2
== '}') {
271 if (foldDirective
&& (style
== SCE_POV_DIRECTIVE
)) {
274 while ((j
<endPos
) && IsASpaceOrTab(styler
.SafeGetCharAt(j
))) {
279 if (style
== SCE_POV_OPERATOR
) {
282 } else if (ch
== '}') {
288 if (visibleChars
== 0 && foldCompact
)
289 lev
|= SC_FOLDLEVELWHITEFLAG
;
290 if ((levelCurrent
> levelPrev
) && (visibleChars
> 0))
291 lev
|= SC_FOLDLEVELHEADERFLAG
;
292 if (lev
!= styler
.LevelAt(lineCurrent
)) {
293 styler
.SetLevel(lineCurrent
, lev
);
296 levelPrev
= levelCurrent
;
299 if (!isspacechar(ch
))
302 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
303 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
304 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
307 static const char * const povWordLists
[] = {
308 "Language directives",
309 "Objects & CSG & Appearance",
310 "Types & Modifiers & Items",
311 "Predefined Identifiers",
312 "Predefined Functions",
319 LexerModule
lmPOV(SCLEX_POV
, ColourisePovDoc
, "pov", FoldPovDoc
, povWordLists
);