]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexLua.cxx
63114a976dfaeb63a060b3b46579920e87e8d0ec
   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 
  20 #include "StyleContext.h" 
  22 #include "Scintilla.h" 
  26 using namespace Scintilla
; 
  29 // Extended to accept accented characters 
  30 static inline bool IsAWordChar(int ch
) { 
  32                (isalnum(ch
) || ch 
== '.' || ch 
== '_'); 
  35 static inline bool IsAWordStart(int ch
) { 
  37                (isalpha(ch
) || ch 
== '_'); 
  40 static inline bool IsANumberChar(int ch
) { 
  41         // Not exactly following number definition (several dots are seen as OK, etc.) 
  42         // but probably enough in most cases. 
  44                 (isdigit(ch
) || toupper(ch
) == 'E' || 
  45                 ch 
== '.' || ch 
== '-' || ch 
== '+' || 
  46                 (ch 
>= 'a' && ch 
<= 'f') || (ch 
>= 'A' && ch 
<= 'F')); 
  49 static inline bool IsLuaOperator(int ch
) { 
  50         if (ch 
>= 0x80 || isalnum(ch
)) { 
  53         // '.' left out as it is used to make up numbers 
  54         if (ch 
== '*' || ch 
== '/' || ch 
== '-' || ch 
== '+' || 
  55                 ch 
== '(' || ch 
== ')' || ch 
== '=' || 
  56                 ch 
== '{' || ch 
== '}' || ch 
== '~' || 
  57                 ch 
== '[' || ch 
== ']' || ch 
== ';' || 
  58                 ch 
== '<' || ch 
== '>' || ch 
== ',' || 
  59                 ch 
== '.' || ch 
== '^' || ch 
== '%' || ch 
== ':' || 
  66 // Test for [=[ ... ]=] delimiters, returns 0 if it's only a [ or ], 
  67 // return 1 for [[ or ]], returns >=2 for [=[ or ]=] and so on. 
  68 // The maximum number of '=' characters allowed is 254. 
  69 static int LongDelimCheck(StyleContext 
&sc
) { 
  71         while (sc
.GetRelative(sep
) == '=' && sep 
< 0xFF) 
  73         if (sc
.GetRelative(sep
) == sc
.ch
) 
  78 static void ColouriseLuaDoc( 
  79         unsigned int startPos
, 
  82         WordList 
*keywordlists
[], 
  85         WordList 
&keywords 
= *keywordlists
[0]; 
  86         WordList 
&keywords2 
= *keywordlists
[1]; 
  87         WordList 
&keywords3 
= *keywordlists
[2]; 
  88         WordList 
&keywords4 
= *keywordlists
[3]; 
  89         WordList 
&keywords5 
= *keywordlists
[4]; 
  90         WordList 
&keywords6 
= *keywordlists
[5]; 
  91         WordList 
&keywords7 
= *keywordlists
[6]; 
  92         WordList 
&keywords8 
= *keywordlists
[7]; 
  94         int currentLine 
= styler
.GetLine(startPos
); 
  95         // Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level, 
  96         // if we are inside such a string. Block comment was introduced in Lua 5.0, 
  97         // blocks with separators [=[ ... ]=] in Lua 5.1. 
 100         if (initStyle 
== SCE_LUA_LITERALSTRING 
|| initStyle 
== SCE_LUA_COMMENT
) { 
 101                 int lineState 
= styler
.GetLineState(currentLine 
- 1); 
 102                 nestLevel 
= lineState 
>> 8; 
 103                 sepCount 
= lineState 
& 0xFF; 
 106         // Do not leak onto next line 
 107         if (initStyle 
== SCE_LUA_STRINGEOL 
|| initStyle 
== SCE_LUA_COMMENTLINE 
|| initStyle 
== SCE_LUA_PREPROCESSOR
) { 
 108                 initStyle 
= SCE_LUA_DEFAULT
; 
 111         StyleContext 
sc(startPos
, length
, initStyle
, styler
); 
 112         if (startPos 
== 0 && sc
.ch 
== '#') { 
 113                 // shbang line: # is a comment only if first char of the script 
 114                 sc
.SetState(SCE_LUA_COMMENTLINE
); 
 116         for (; sc
.More(); sc
.Forward()) { 
 118                         // Update the line state, so it can be seen by next line 
 119                         currentLine 
= styler
.GetLine(sc
.currentPos
); 
 121                         case SCE_LUA_LITERALSTRING
: 
 122                         case SCE_LUA_COMMENT
: 
 123                                 // Inside a literal string or block comment, we set the line state 
 124                                 styler
.SetLineState(currentLine
, (nestLevel 
<< 8) | sepCount
); 
 127                                 // Reset the line state 
 128                                 styler
.SetLineState(currentLine
, 0); 
 132                 if (sc
.atLineStart 
&& (sc
.state 
== SCE_LUA_STRING
)) { 
 133                         // Prevent SCE_LUA_STRINGEOL from leaking back to previous line 
 134                         sc
.SetState(SCE_LUA_STRING
); 
 137                 // Handle string line continuation 
 138                 if ((sc
.state 
== SCE_LUA_STRING 
|| sc
.state 
== SCE_LUA_CHARACTER
) && 
 140                         if (sc
.chNext 
== '\n' || sc
.chNext 
== '\r') { 
 142                                 if (sc
.ch 
== '\r' && sc
.chNext 
== '\n') { 
 149                 // Determine if the current state should terminate. 
 150                 if (sc
.state 
== SCE_LUA_OPERATOR
) { 
 151                         sc
.SetState(SCE_LUA_DEFAULT
); 
 152                 } else if (sc
.state 
== SCE_LUA_NUMBER
) { 
 153                         // We stop the number definition on non-numerical non-dot non-eE non-sign non-hexdigit char 
 154                         if (!IsANumberChar(sc
.ch
)) { 
 155                                 sc
.SetState(SCE_LUA_DEFAULT
); 
 156                         } else if (sc
.ch 
== '-' || sc
.ch 
== '+') { 
 157                                 if (sc
.chPrev 
!= 'E' && sc
.chPrev 
!= 'e') 
 158                                         sc
.SetState(SCE_LUA_DEFAULT
); 
 160                 } else if (sc
.state 
== SCE_LUA_IDENTIFIER
) { 
 161                         if (!IsAWordChar(sc
.ch
) || sc
.Match('.', '.')) { 
 163                                 sc
.GetCurrent(s
, sizeof(s
)); 
 164                                 if (keywords
.InList(s
)) { 
 165                                         sc
.ChangeState(SCE_LUA_WORD
); 
 166                                 } else if (keywords2
.InList(s
)) { 
 167                                         sc
.ChangeState(SCE_LUA_WORD2
); 
 168                                 } else if (keywords3
.InList(s
)) { 
 169                                         sc
.ChangeState(SCE_LUA_WORD3
); 
 170                                 } else if (keywords4
.InList(s
)) { 
 171                                         sc
.ChangeState(SCE_LUA_WORD4
); 
 172                                 } else if (keywords5
.InList(s
)) { 
 173                                         sc
.ChangeState(SCE_LUA_WORD5
); 
 174                                 } else if (keywords6
.InList(s
)) { 
 175                                         sc
.ChangeState(SCE_LUA_WORD6
); 
 176                                 } else if (keywords7
.InList(s
)) { 
 177                                         sc
.ChangeState(SCE_LUA_WORD7
); 
 178                                 } else if (keywords8
.InList(s
)) { 
 179                                         sc
.ChangeState(SCE_LUA_WORD8
); 
 181                                 sc
.SetState(SCE_LUA_DEFAULT
); 
 183                 } else if (sc
.state 
== SCE_LUA_COMMENTLINE 
|| sc
.state 
== SCE_LUA_PREPROCESSOR
) { 
 185                                 sc
.ForwardSetState(SCE_LUA_DEFAULT
); 
 187                 } else if (sc
.state 
== SCE_LUA_STRING
) { 
 189                                 if (sc
.chNext 
== '\"' || sc
.chNext 
== '\'' || sc
.chNext 
== '\\') { 
 192                         } else if (sc
.ch 
== '\"') { 
 193                                 sc
.ForwardSetState(SCE_LUA_DEFAULT
); 
 194                         } else if (sc
.atLineEnd
) { 
 195                                 sc
.ChangeState(SCE_LUA_STRINGEOL
); 
 196                                 sc
.ForwardSetState(SCE_LUA_DEFAULT
); 
 198                 } else if (sc
.state 
== SCE_LUA_CHARACTER
) { 
 200                                 if (sc
.chNext 
== '\"' || sc
.chNext 
== '\'' || sc
.chNext 
== '\\') { 
 203                         } else if (sc
.ch 
== '\'') { 
 204                                 sc
.ForwardSetState(SCE_LUA_DEFAULT
); 
 205                         } else if (sc
.atLineEnd
) { 
 206                                 sc
.ChangeState(SCE_LUA_STRINGEOL
); 
 207                                 sc
.ForwardSetState(SCE_LUA_DEFAULT
); 
 209                 } else if (sc
.state 
== SCE_LUA_LITERALSTRING 
|| sc
.state 
== SCE_LUA_COMMENT
) { 
 211                                 int sep 
= LongDelimCheck(sc
); 
 212                                 if (sep 
== 1 && sepCount 
== 1) {    // [[-only allowed to nest 
 216                         } else if (sc
.ch 
== ']') { 
 217                                 int sep 
= LongDelimCheck(sc
); 
 218                                 if (sep 
== 1 && sepCount 
== 1) {    // un-nest with ]]-only 
 221                                         if (nestLevel 
== 0) { 
 222                                                 sc
.ForwardSetState(SCE_LUA_DEFAULT
); 
 224                                 } else if (sep 
> 1 && sep 
== sepCount
) {   // ]=]-style delim 
 226                                         sc
.ForwardSetState(SCE_LUA_DEFAULT
); 
 231                 // Determine if a new state should be entered. 
 232                 if (sc
.state 
== SCE_LUA_DEFAULT
) { 
 233                         if (IsADigit(sc
.ch
) || (sc
.ch 
== '.' && IsADigit(sc
.chNext
))) { 
 234                                 sc
.SetState(SCE_LUA_NUMBER
); 
 235                                 if (sc
.ch 
== '0' && toupper(sc
.chNext
) == 'X') { 
 238                         } else if (IsAWordStart(sc
.ch
)) { 
 239                                 sc
.SetState(SCE_LUA_IDENTIFIER
); 
 240                         } else if (sc
.ch 
== '\"') { 
 241                                 sc
.SetState(SCE_LUA_STRING
); 
 242                         } else if (sc
.ch 
== '\'') { 
 243                                 sc
.SetState(SCE_LUA_CHARACTER
); 
 244                         } else if (sc
.ch 
== '[') { 
 245                                 sepCount 
= LongDelimCheck(sc
); 
 247                                         sc
.SetState(SCE_LUA_OPERATOR
); 
 250                                         sc
.SetState(SCE_LUA_LITERALSTRING
); 
 251                                         sc
.Forward(sepCount
); 
 253                         } else if (sc
.Match('-', '-')) { 
 254                                 sc
.SetState(SCE_LUA_COMMENTLINE
); 
 255                                 if (sc
.Match("--[")) { 
 257                                         sepCount 
= LongDelimCheck(sc
); 
 260                                                 sc
.ChangeState(SCE_LUA_COMMENT
); 
 261                                                 sc
.Forward(sepCount
); 
 266                         } else if (sc
.atLineStart 
&& sc
.Match('$')) { 
 267                                 sc
.SetState(SCE_LUA_PREPROCESSOR
);      // Obsolete since Lua 4.0, but still in old code 
 268                         } else if (IsLuaOperator(static_cast<char>(sc
.ch
))) { 
 269                                 sc
.SetState(SCE_LUA_OPERATOR
); 
 276 static void FoldLuaDoc(unsigned int startPos
, int length
, int /* initStyle */, WordList 
*[], 
 278         unsigned int lengthDoc 
= startPos 
+ length
; 
 279         int visibleChars 
= 0; 
 280         int lineCurrent 
= styler
.GetLine(startPos
); 
 281         int levelPrev 
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
; 
 282         int levelCurrent 
= levelPrev
; 
 283         char chNext 
= styler
[startPos
]; 
 284         bool foldCompact 
= styler
.GetPropertyInt("fold.compact", 1) != 0; 
 285         int styleNext 
= styler
.StyleAt(startPos
); 
 288         for (unsigned int i 
= startPos
; i 
< lengthDoc
; i
++) { 
 290                 chNext 
= styler
.SafeGetCharAt(i 
+ 1); 
 291                 int style 
= styleNext
; 
 292                 styleNext 
= styler
.StyleAt(i 
+ 1); 
 293                 bool atEOL 
= (ch 
== '\r' && chNext 
!= '\n') || (ch 
== '\n'); 
 294                 if (style 
== SCE_LUA_WORD
) { 
 295                         if (ch 
== 'i' || ch 
== 'd' || ch 
== 'f' || ch 
== 'e' || ch 
== 'r' || ch 
== 'u') { 
 296                                 for (unsigned int j 
= 0; j 
< 8; j
++) { 
 297                                         if (!iswordchar(styler
[i 
+ j
])) { 
 300                                         s
[j
] = styler
[i 
+ j
]; 
 304                                 if ((strcmp(s
, "if") == 0) || (strcmp(s
, "do") == 0) || (strcmp(s
, "function") == 0) || (strcmp(s
, "repeat") == 0)) { 
 307                                 if ((strcmp(s
, "end") == 0) || (strcmp(s
, "elseif") == 0) || (strcmp(s
, "until") == 0)) { 
 311                 } else if (style 
== SCE_LUA_OPERATOR
) { 
 312                         if (ch 
== '{' || ch 
== '(') { 
 314                         } else if (ch 
== '}' || ch 
== ')') { 
 317                 } else if (style 
== SCE_LUA_LITERALSTRING 
|| style 
== SCE_LUA_COMMENT
) { 
 320                         } else if (ch 
== ']') { 
 327                         if (visibleChars 
== 0 && foldCompact
) { 
 328                                 lev 
|= SC_FOLDLEVELWHITEFLAG
; 
 330                         if ((levelCurrent 
> levelPrev
) && (visibleChars 
> 0)) { 
 331                                 lev 
|= SC_FOLDLEVELHEADERFLAG
; 
 333                         if (lev 
!= styler
.LevelAt(lineCurrent
)) { 
 334                                 styler
.SetLevel(lineCurrent
, lev
); 
 337                         levelPrev 
= levelCurrent
; 
 340                 if (!isspacechar(ch
)) { 
 344         // Fill in the real level of the next line, keeping the current flags as they will be filled in later 
 346         int flagsNext 
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
; 
 347         styler
.SetLevel(lineCurrent
, levelPrev 
| flagsNext
); 
 350 static const char * const luaWordListDesc
[] = { 
 353         "String, (table) & math functions", 
 354         "(coroutines), I/O & system facilities", 
 362 LexerModule 
lmLua(SCLEX_LUA
, ColouriseLuaDoc
, "lua", FoldLuaDoc
, luaWordListDesc
);