// Scintilla source code edit control /** @file LexLua.cxx ** Lexer for Lua language. ** ** Written by Paul Winwood. ** Folder by Alexey Yutkin. ** Modified by Marcos E. Wurzius & Philippe Lhoste **/ #include #include #include #include #include #include #include #include #include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" #include "StringCopy.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" #include "CharacterSet.h" #include "LexerModule.h" using namespace Lexilla; // Test for [=[ ... ]=] delimiters, returns 0 if it's only a [ or ], // return 1 for [[ or ]], returns >=2 for [=[ or ]=] and so on. // The maximum number of '=' characters allowed is 254. static int LongDelimCheck(StyleContext &sc) { int sep = 1; while (sc.GetRelative(sep) == '=' && sep < 0xFF) sep++; if (sc.GetRelative(sep) == sc.ch) return sep; return 0; } static void ColouriseLuaDoc( Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], Accessor &styler) { const WordList &keywords = *keywordlists[0]; const WordList &keywords2 = *keywordlists[1]; const WordList &keywords3 = *keywordlists[2]; const WordList &keywords4 = *keywordlists[3]; const WordList &keywords5 = *keywordlists[4]; const WordList &keywords6 = *keywordlists[5]; const WordList &keywords7 = *keywordlists[6]; const WordList &keywords8 = *keywordlists[7]; // Accepts accented characters CharacterSet setWordStart(CharacterSet::setAlpha, "_", true); CharacterSet setWord(CharacterSet::setAlphaNum, "_", true); // Not exactly following number definition (several dots are seen as OK, etc.) // but probably enough in most cases. [pP] is for hex floats. CharacterSet setNumber(CharacterSet::setDigits, ".-+abcdefpABCDEFP"); CharacterSet setExponent(CharacterSet::setNone, "eEpP"); CharacterSet setLuaOperator(CharacterSet::setNone, "*/-+()={}~[];<>,.^%:#&|"); CharacterSet setEscapeSkip(CharacterSet::setNone, "\"'\\"); Sci_Position currentLine = styler.GetLine(startPos); // Initialize long string [[ ... ]] or block comment --[[ ... ]], // if we are inside such a string. Block comment was introduced in Lua 5.0, // blocks with separators [=[ ... ]=] in Lua 5.1. // Continuation of a string (\z whitespace escaping) is controlled by stringWs. int sepCount = 0; int stringWs = 0; if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT || initStyle == SCE_LUA_STRING || initStyle == SCE_LUA_CHARACTER) { const int lineState = styler.GetLineState(currentLine - 1); sepCount = lineState & 0xFF; stringWs = lineState & 0x100; } // results of identifier/keyword matching Sci_Position idenPos = 0; Sci_Position idenWordPos = 0; int idenStyle = SCE_LUA_IDENTIFIER; bool foundGoto = false; // Do not leak onto next line if (initStyle == SCE_LUA_STRINGEOL || initStyle == SCE_LUA_COMMENTLINE || initStyle == SCE_LUA_PREPROCESSOR) { initStyle = SCE_LUA_DEFAULT; } StyleContext sc(startPos, length, initStyle, styler); if (startPos == 0 && sc.ch == '#' && sc.chNext == '!') { // shbang line: "#!" is a comment only if located at the start of the script sc.SetState(SCE_LUA_COMMENTLINE); } for (; sc.More(); sc.Forward()) { if (sc.atLineEnd) { // Update the line state, so it can be seen by next line currentLine = styler.GetLine(sc.currentPos); switch (sc.state) { case SCE_LUA_LITERALSTRING: case SCE_LUA_COMMENT: case SCE_LUA_STRING: case SCE_LUA_CHARACTER: // Inside a literal string, block comment or string, we set the line state styler.SetLineState(currentLine, stringWs | sepCount); break; default: // Reset the line state styler.SetLineState(currentLine, 0); break; } } if (sc.atLineStart && (sc.state == SCE_LUA_STRING)) { // Prevent SCE_LUA_STRINGEOL from leaking back to previous line sc.SetState(SCE_LUA_STRING); } // Handle string line continuation if ((sc.state == SCE_LUA_STRING || sc.state == SCE_LUA_CHARACTER) && sc.ch == '\\') { if (sc.chNext == '\n' || sc.chNext == '\r') { sc.Forward(); if (sc.ch == '\r' && sc.chNext == '\n') { sc.Forward(); } continue; } } // Determine if the current state should terminate. if (sc.state == SCE_LUA_OPERATOR) { if (sc.ch == ':' && sc.chPrev == ':') { // ::