]>
git.saurik.com Git - wxWidgets.git/blob - contrib/src/stc/scintilla/src/LexLua.cxx
fc9607e25d24300256ea201cd1bf598f47151378
1 // Scintilla source code edit control
3 ** Lexer for Lua language.
5 ** Written by Paul Winwood.
6 ** Folder by Alexey Yutkin.
7 ** Modified by Marcos E. Wurzius & Philippe Lhoste
21 #include "StyleContext.h"
23 #include "Scintilla.h"
26 #define SCE_LUA_LAST_STYLE SCE_LUA_WORD6
28 static inline bool IsAWordChar(const int ch
) {
29 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_');
32 inline bool IsAWordStart(const int ch
) {
33 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
36 inline bool isLuaOperator(char ch
) {
39 // '.' left out as it is used to make up numbers
40 if (ch
== '*' || ch
== '/' || ch
== '-' || ch
== '+' ||
41 ch
== '(' || ch
== ')' || ch
== '=' ||
42 ch
== '{' || ch
== '}' || ch
== '~' ||
43 ch
== '[' || ch
== ']' || ch
== ';' ||
44 ch
== '<' || ch
== '>' || ch
== ',' ||
45 ch
== '.' || ch
== '^' || ch
== '%' || ch
== ':')
50 static void ColouriseLuaDoc(
51 unsigned int startPos
,
54 WordList
*keywordlists
[],
57 WordList
&keywords
= *keywordlists
[0];
58 WordList
&keywords2
= *keywordlists
[1];
59 WordList
&keywords3
= *keywordlists
[2];
60 WordList
&keywords4
= *keywordlists
[3];
61 WordList
&keywords5
= *keywordlists
[4];
62 WordList
&keywords6
= *keywordlists
[5];
64 // Must initialize the literal string nesting level, if we are inside such a string.
65 int literalStringLevel
= 0;
66 if (initStyle
== SCE_LUA_LITERALSTRING
) {
67 literalStringLevel
= 1;
69 // We use states above the last one to indicate nesting level of literal strings
70 if (initStyle
> SCE_LUA_LAST_STYLE
) {
71 literalStringLevel
= initStyle
- SCE_LUA_LAST_STYLE
+ 1;
74 // Do not leak onto next line
75 if (initStyle
== SCE_LUA_STRINGEOL
) {
76 initStyle
= SCE_LUA_DEFAULT
;
79 StyleContext
sc(startPos
, length
, initStyle
, styler
);
80 if (startPos
== 0 && sc
.ch
== '#') {
81 sc
.SetState(SCE_LUA_COMMENTLINE
);
83 for (; sc
.More(); sc
.Forward()) {
84 if (sc
.atLineStart
&& (sc
.state
== SCE_LUA_STRING
)) {
85 // Prevent SCE_LUA_STRINGEOL from leaking back to previous line
86 sc
.SetState(SCE_LUA_STRING
);
89 // Handle string line continuation
90 if ((sc
.state
== SCE_LUA_STRING
|| sc
.state
== SCE_LUA_CHARACTER
) &&
92 if (sc
.chNext
== '\n' || sc
.chNext
== '\r') {
94 if (sc
.ch
== '\r' && sc
.chNext
== '\n') {
101 // Determine if the current state should terminate.
102 if (sc
.state
== SCE_LUA_OPERATOR
) {
103 sc
.SetState(SCE_LUA_DEFAULT
);
104 } else if (sc
.state
== SCE_LUA_NUMBER
) {
105 if (!IsAWordChar(sc
.ch
)) {
106 sc
.SetState(SCE_LUA_DEFAULT
);
108 } else if (sc
.state
== SCE_LUA_IDENTIFIER
) {
109 if (!IsAWordChar(sc
.ch
) || (sc
.ch
== '.')) {
111 sc
.GetCurrent(s
, sizeof(s
));
112 if (keywords
.InList(s
)) {
113 sc
.ChangeState(SCE_LUA_WORD
);
114 } else if (keywords2
.InList(s
)) {
115 sc
.ChangeState(SCE_LUA_WORD2
);
116 } else if (keywords3
.InList(s
)) {
117 sc
.ChangeState(SCE_LUA_WORD3
);
118 } else if (keywords4
.InList(s
)) {
119 sc
.ChangeState(SCE_LUA_WORD4
);
120 } else if (keywords5
.InList(s
)) {
121 sc
.ChangeState(SCE_LUA_WORD5
);
122 } else if (keywords6
.InList(s
)) {
123 sc
.ChangeState(SCE_LUA_WORD6
);
125 sc
.SetState(SCE_LUA_DEFAULT
);
127 } else if (sc
.state
== SCE_LUA_COMMENTLINE
) {
129 sc
.SetState(SCE_LUA_DEFAULT
);
131 } else if (sc
.state
== SCE_LUA_PREPROCESSOR
) {
133 sc
.SetState(SCE_LUA_DEFAULT
);
135 } else if (sc
.state
== SCE_LUA_STRING
) {
137 if (sc
.chNext
== '\"' || sc
.chNext
== '\'' || sc
.chNext
== '\\') {
140 } else if (sc
.ch
== '\"') {
141 sc
.ForwardSetState(SCE_LUA_DEFAULT
);
142 } else if (sc
.atLineEnd
) {
143 sc
.ChangeState(SCE_LUA_STRINGEOL
);
144 sc
.ForwardSetState(SCE_LUA_DEFAULT
);
146 } else if (sc
.state
== SCE_LUA_CHARACTER
) {
148 if (sc
.chNext
== '\"' || sc
.chNext
== '\'' || sc
.chNext
== '\\') {
151 } else if (sc
.ch
== '\'') {
152 sc
.ForwardSetState(SCE_LUA_DEFAULT
);
153 } else if (sc
.atLineEnd
) {
154 sc
.ChangeState(SCE_LUA_STRINGEOL
);
155 sc
.ForwardSetState(SCE_LUA_DEFAULT
);
157 } else if (sc
.state
== SCE_LUA_LITERALSTRING
|| sc
.state
> SCE_LUA_LAST_STYLE
) {
158 if (sc
.Match('[', '[')) {
159 literalStringLevel
++;
160 sc
.SetState(SCE_LUA_LAST_STYLE
+ literalStringLevel
- 1);
161 } else if (sc
.Match(']', ']') && literalStringLevel
> 0) {
162 literalStringLevel
--;
164 if (literalStringLevel
== 0) {
165 sc
.ForwardSetState(SCE_LUA_DEFAULT
);
166 } else if (literalStringLevel
== 1) {
167 sc
.ForwardSetState(SCE_LUA_LITERALSTRING
);
169 sc
.ForwardSetState(SCE_LUA_LAST_STYLE
+ literalStringLevel
- 1);
173 // Determine if a new state should be entered.
174 if (sc
.state
== SCE_LUA_DEFAULT
) {
175 if (IsADigit(sc
.ch
) || (sc
.ch
== '.' && IsADigit(sc
.chNext
))) {
176 sc
.SetState(SCE_LUA_NUMBER
);
177 } else if (IsAWordStart(sc
.ch
)) {
178 sc
.SetState(SCE_LUA_IDENTIFIER
);
179 } else if (sc
.Match('\"')) {
180 sc
.SetState(SCE_LUA_STRING
);
181 } else if (sc
.Match('\'')) {
182 sc
.SetState(SCE_LUA_CHARACTER
);
183 } else if (sc
.Match('[', '[')) {
184 literalStringLevel
= 1;
185 sc
.SetState(SCE_LUA_LITERALSTRING
);
187 } else if (sc
.Match('-', '-')) {
188 sc
.SetState(SCE_LUA_COMMENTLINE
);
190 } else if (sc
.Match('$') && sc
.atLineStart
) {
191 sc
.SetState(SCE_LUA_PREPROCESSOR
); // Obsolete since Lua 4.0, but still in old code
192 } else if (isLuaOperator(static_cast<char>(sc
.ch
))) {
193 sc
.SetState(SCE_LUA_OPERATOR
);
201 static void FoldLuaDoc(unsigned int startPos
, int length
, int /* initStyle */, WordList
*[],
203 unsigned int lengthDoc
= startPos
+ length
;
204 int visibleChars
= 0;
205 int lineCurrent
= styler
.GetLine(startPos
);
206 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
207 int levelCurrent
= levelPrev
;
208 char chNext
= styler
[startPos
];
209 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
210 int styleNext
= styler
.StyleAt(startPos
);
213 for (unsigned int i
= startPos
; i
< lengthDoc
; i
++) {
215 chNext
= styler
.SafeGetCharAt(i
+ 1);
216 int style
= styleNext
;
217 styleNext
= styler
.StyleAt(i
+ 1);
218 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
219 if (style
== SCE_LUA_WORD
) {
220 if (ch
== 'i' || ch
== 'd' || ch
== 'f' || ch
== 'e') {
221 for (unsigned int j
= 0; j
< 8; j
++) {
222 if (!iswordchar(styler
[i
+ j
])) {
225 s
[j
] = styler
[i
+ j
];
229 if ((strcmp(s
, "if") == 0) || (strcmp(s
, "do") == 0) || (strcmp(s
, "function") == 0)) {
232 if ((strcmp(s
, "end") == 0) || (strcmp(s
, "elseif") == 0)) {
236 } else if (style
== SCE_LUA_OPERATOR
) {
237 if (ch
== '{' || ch
== '(') {
239 } else if (ch
== '}' || ch
== ')') {
246 if (visibleChars
== 0 && foldCompact
) {
247 lev
|= SC_FOLDLEVELWHITEFLAG
;
249 if ((levelCurrent
> levelPrev
) && (visibleChars
> 0)) {
250 lev
|= SC_FOLDLEVELHEADERFLAG
;
252 if (lev
!= styler
.LevelAt(lineCurrent
)) {
253 styler
.SetLevel(lineCurrent
, lev
);
256 levelPrev
= levelCurrent
;
259 if (!isspacechar(ch
)) {
263 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
265 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
266 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
269 LexerModule
lmLua(SCLEX_LUA
, ColouriseLuaDoc
, "lua", FoldLuaDoc
);