]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexAVS.cxx
1 // Scintilla source code edit control
5 // Copyright 2012 by Bruno Barbieri <brunorex@gmail.com>
6 // Heavily based on LexPOV by Neil Hodgson
7 // The License.txt file describes the conditions under which this software may be distributed.
17 #include "Scintilla.h"
21 #include "LexAccessor.h"
23 #include "StyleContext.h"
24 #include "CharacterSet.h"
25 #include "LexerModule.h"
28 using namespace Scintilla
;
31 static inline bool IsAWordChar(const int ch
) {
32 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
35 static inline bool IsAWordStart(int ch
) {
36 return isalpha(ch
) || (ch
!= ' ' && ch
!= '\n' && ch
!= '(' && ch
!= '.' && ch
!= ',');
39 static inline bool IsANumberChar(int ch
) {
40 // Not exactly following number definition (several dots are seen as OK, etc.)
41 // but probably enough in most cases.
43 (isdigit(ch
) || ch
== '.' || ch
== '-' || ch
== '+');
46 static void ColouriseAvsDoc(
47 unsigned int startPos
,
50 WordList
*keywordlists
[],
53 WordList
&keywords
= *keywordlists
[0];
54 WordList
&filters
= *keywordlists
[1];
55 WordList
&plugins
= *keywordlists
[2];
56 WordList
&functions
= *keywordlists
[3];
57 WordList
&clipProperties
= *keywordlists
[4];
58 WordList
&userDefined
= *keywordlists
[5];
60 int currentLine
= styler
.GetLine(startPos
);
61 // Initialize the block comment nesting level, if we are inside such a comment.
62 int blockCommentLevel
= 0;
63 if (initStyle
== SCE_AVS_COMMENTBLOCK
|| initStyle
== SCE_AVS_COMMENTBLOCKN
) {
64 blockCommentLevel
= styler
.GetLineState(currentLine
- 1);
67 // Do not leak onto next line
68 if (initStyle
== SCE_AVS_COMMENTLINE
) {
69 initStyle
= SCE_AVS_DEFAULT
;
72 StyleContext
sc(startPos
, length
, initStyle
, styler
);
74 for (; sc
.More(); sc
.Forward()) {
76 // Update the line state, so it can be seen by next line
77 currentLine
= styler
.GetLine(sc
.currentPos
);
78 if (sc
.state
== SCE_AVS_COMMENTBLOCK
|| sc
.state
== SCE_AVS_COMMENTBLOCKN
) {
79 // Inside a block comment, we set the line state
80 styler
.SetLineState(currentLine
, blockCommentLevel
);
82 // Reset the line state
83 styler
.SetLineState(currentLine
, 0);
87 // Determine if the current state should terminate.
88 if (sc
.state
== SCE_AVS_OPERATOR
) {
89 sc
.SetState(SCE_AVS_DEFAULT
);
90 } else if (sc
.state
== SCE_AVS_NUMBER
) {
91 // We stop the number definition on non-numerical non-dot non-sign char
92 if (!IsANumberChar(sc
.ch
)) {
93 sc
.SetState(SCE_AVS_DEFAULT
);
95 } else if (sc
.state
== SCE_AVS_IDENTIFIER
) {
96 if (!IsAWordChar(sc
.ch
)) {
98 sc
.GetCurrentLowered(s
, sizeof(s
));
100 if (keywords
.InList(s
)) {
101 sc
.ChangeState(SCE_AVS_KEYWORD
);
102 } else if (filters
.InList(s
)) {
103 sc
.ChangeState(SCE_AVS_FILTER
);
104 } else if (plugins
.InList(s
)) {
105 sc
.ChangeState(SCE_AVS_PLUGIN
);
106 } else if (functions
.InList(s
)) {
107 sc
.ChangeState(SCE_AVS_FUNCTION
);
108 } else if (clipProperties
.InList(s
)) {
109 sc
.ChangeState(SCE_AVS_CLIPPROP
);
110 } else if (userDefined
.InList(s
)) {
111 sc
.ChangeState(SCE_AVS_USERDFN
);
113 sc
.SetState(SCE_AVS_DEFAULT
);
115 } else if (sc
.state
== SCE_AVS_COMMENTBLOCK
) {
116 if (sc
.Match('/', '*')) {
119 } else if (sc
.Match('*', '/') && blockCommentLevel
> 0) {
122 if (blockCommentLevel
== 0) {
123 sc
.ForwardSetState(SCE_AVS_DEFAULT
);
126 } else if (sc
.state
== SCE_AVS_COMMENTBLOCKN
) {
127 if (sc
.Match('[', '*')) {
130 } else if (sc
.Match('*', ']') && blockCommentLevel
> 0) {
133 if (blockCommentLevel
== 0) {
134 sc
.ForwardSetState(SCE_AVS_DEFAULT
);
137 } else if (sc
.state
== SCE_AVS_COMMENTLINE
) {
139 sc
.ForwardSetState(SCE_AVS_DEFAULT
);
141 } else if (sc
.state
== SCE_AVS_STRING
) {
143 sc
.ForwardSetState(SCE_AVS_DEFAULT
);
145 } else if (sc
.state
== SCE_AVS_TRIPLESTRING
) {
146 if (sc
.Match("\"\"\"")) {
149 sc
.ForwardSetState(SCE_AVS_DEFAULT
);
153 // Determine if a new state should be entered.
154 if (sc
.state
== SCE_AVS_DEFAULT
) {
155 if (IsADigit(sc
.ch
) || (sc
.ch
== '.' && IsADigit(sc
.chNext
))) {
156 sc
.SetState(SCE_AVS_NUMBER
);
157 } else if (IsADigit(sc
.ch
) || (sc
.ch
== ',' && IsADigit(sc
.chNext
))) {
159 sc
.SetState(SCE_AVS_NUMBER
);
160 } else if (sc
.Match('/', '*')) {
161 blockCommentLevel
= 1;
162 sc
.SetState(SCE_AVS_COMMENTBLOCK
);
163 sc
.Forward(); // Eat the * so it isn't used for the end of the comment
164 } else if (sc
.Match('[', '*')) {
165 blockCommentLevel
= 1;
166 sc
.SetState(SCE_AVS_COMMENTBLOCKN
);
167 sc
.Forward(); // Eat the * so it isn't used for the end of the comment
168 } else if (sc
.ch
== '#') {
169 sc
.SetState(SCE_AVS_COMMENTLINE
);
170 } else if (sc
.ch
== '\"') {
171 if (sc
.Match("\"\"\"")) {
172 sc
.SetState(SCE_AVS_TRIPLESTRING
);
174 sc
.SetState(SCE_AVS_STRING
);
176 } else if (isoperator(static_cast<char>(sc
.ch
))) {
177 sc
.SetState(SCE_AVS_OPERATOR
);
178 } else if (IsAWordStart(sc
.ch
)) {
179 sc
.SetState(SCE_AVS_IDENTIFIER
);
184 // End of file: complete any pending changeState
185 if (sc
.state
== SCE_AVS_IDENTIFIER
) {
186 if (!IsAWordChar(sc
.ch
)) {
188 sc
.GetCurrentLowered(s
, sizeof(s
));
190 if (keywords
.InList(s
)) {
191 sc
.ChangeState(SCE_AVS_KEYWORD
);
192 } else if (filters
.InList(s
)) {
193 sc
.ChangeState(SCE_AVS_FILTER
);
194 } else if (plugins
.InList(s
)) {
195 sc
.ChangeState(SCE_AVS_PLUGIN
);
196 } else if (functions
.InList(s
)) {
197 sc
.ChangeState(SCE_AVS_FUNCTION
);
198 } else if (clipProperties
.InList(s
)) {
199 sc
.ChangeState(SCE_AVS_CLIPPROP
);
200 } else if (userDefined
.InList(s
)) {
201 sc
.ChangeState(SCE_AVS_USERDFN
);
203 sc
.SetState(SCE_AVS_DEFAULT
);
210 static void FoldAvsDoc(
211 unsigned int startPos
,
217 bool foldComment
= styler
.GetPropertyInt("fold.comment") != 0;
218 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
219 unsigned int endPos
= startPos
+ length
;
220 int visibleChars
= 0;
221 int lineCurrent
= styler
.GetLine(startPos
);
222 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
223 int levelCurrent
= levelPrev
;
224 char chNext
= styler
[startPos
];
225 int styleNext
= styler
.StyleAt(startPos
);
226 int style
= initStyle
;
228 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
230 chNext
= styler
.SafeGetCharAt(i
+ 1);
231 int stylePrev
= style
;
233 styleNext
= styler
.StyleAt(i
+ 1);
234 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
235 if (foldComment
&& style
== SCE_AVS_COMMENTBLOCK
) {
236 if (stylePrev
!= SCE_AVS_COMMENTBLOCK
) {
238 } else if ((styleNext
!= SCE_AVS_COMMENTBLOCK
) && !atEOL
) {
239 // Comments don't end at end of line and the next character may be unstyled.
244 if (foldComment
&& style
== SCE_AVS_COMMENTBLOCKN
) {
245 if (stylePrev
!= SCE_AVS_COMMENTBLOCKN
) {
247 } else if ((styleNext
!= SCE_AVS_COMMENTBLOCKN
) && !atEOL
) {
248 // Comments don't end at end of line and the next character may be unstyled.
253 if (style
== SCE_AVS_OPERATOR
) {
256 } else if (ch
== '}') {
263 if (visibleChars
== 0 && foldCompact
)
264 lev
|= SC_FOLDLEVELWHITEFLAG
;
265 if ((levelCurrent
> levelPrev
) && (visibleChars
> 0))
266 lev
|= SC_FOLDLEVELHEADERFLAG
;
267 if (lev
!= styler
.LevelAt(lineCurrent
)) {
268 styler
.SetLevel(lineCurrent
, lev
);
271 levelPrev
= levelCurrent
;
275 if (!isspacechar(ch
))
278 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
279 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
280 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
283 static const char * const avsWordLists
[] = {
289 "User defined functions",
293 LexerModule
lmAVS(SCLEX_AVS
, ColouriseAvsDoc
, "avs", FoldAvsDoc
, avsWordLists
);