From fd7c21165bbc5200aa24ef89560a8bb40fd37255 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Tue, 13 Jul 2010 21:16:48 +1000 Subject: Moved lexers into lexers directory. --- lexers/LexAPDL.cxx | 256 ++++++ lexers/LexASY.cxx | 270 ++++++ lexers/LexAU3.cxx | 907 ++++++++++++++++++++ lexers/LexAVE.cxx | 228 +++++ lexers/LexAbaqus.cxx | 617 ++++++++++++++ lexers/LexAda.cxx | 525 ++++++++++++ lexers/LexAsm.cxx | 180 ++++ lexers/LexAsn1.cxx | 185 ++++ lexers/LexBaan.cxx | 193 +++++ lexers/LexBash.cxx | 521 +++++++++++ lexers/LexBasic.cxx | 373 ++++++++ lexers/LexBullant.cxx | 229 +++++ lexers/LexCLW.cxx | 679 +++++++++++++++ lexers/LexCOBOL.cxx | 368 ++++++++ lexers/LexCPP.cxx | 506 +++++++++++ lexers/LexCSS.cxx | 371 ++++++++ lexers/LexCaml.cxx | 449 ++++++++++ lexers/LexCmake.cxx | 457 ++++++++++ lexers/LexConf.cxx | 188 ++++ lexers/LexCrontab.cxx | 222 +++++ lexers/LexCsound.cxx | 210 +++++ lexers/LexD.cxx | 399 +++++++++ lexers/LexEScript.cxx | 273 ++++++ lexers/LexEiffel.cxx | 238 ++++++ lexers/LexErlang.cxx | 619 ++++++++++++++ lexers/LexFlagship.cxx | 352 ++++++++ lexers/LexForth.cxx | 176 ++++ lexers/LexFortran.cxx | 466 ++++++++++ lexers/LexGAP.cxx | 263 ++++++ lexers/LexGui4Cli.cxx | 313 +++++++ lexers/LexHTML.cxx | 2132 ++++++++++++++++++++++++++++++++++++++++++++++ lexers/LexHaskell.cxx | 275 ++++++ lexers/LexInno.cxx | 279 ++++++ lexers/LexKix.cxx | 126 +++ lexers/LexLisp.cxx | 282 ++++++ lexers/LexLout.cxx | 212 +++++ lexers/LexLua.cxx | 358 ++++++++ lexers/LexMMIXAL.cxx | 186 ++++ lexers/LexMPT.cxx | 188 ++++ lexers/LexMSSQL.cxx | 363 ++++++++ lexers/LexMagik.cxx | 445 ++++++++++ lexers/LexMarkdown.cxx | 412 +++++++++ lexers/LexMatlab.cxx | 236 +++++ lexers/LexMetapost.cxx | 399 +++++++++ lexers/LexMySQL.cxx | 518 +++++++++++ lexers/LexNimrod.cxx | 430 ++++++++++ lexers/LexNsis.cxx | 655 ++++++++++++++ lexers/LexOpal.cxx | 522 ++++++++++++ lexers/LexOthers.cxx | 1286 ++++++++++++++++++++++++++++ lexers/LexPB.cxx | 362 ++++++++ lexers/LexPLM.cxx | 198 +++++ lexers/LexPOV.cxx | 316 +++++++ lexers/LexPS.cxx | 347 ++++++++ lexers/LexPascal.cxx | 592 +++++++++++++ lexers/LexPerl.cxx | 1305 ++++++++++++++++++++++++++++ lexers/LexPowerPro.cxx | 600 +++++++++++++ lexers/LexPowerShell.cxx | 198 +++++ lexers/LexProgress.cxx | 279 ++++++ lexers/LexPython.cxx | 569 +++++++++++++ lexers/LexR.cxx | 213 +++++ lexers/LexRebol.cxx | 322 +++++++ lexers/LexRuby.cxx | 1715 +++++++++++++++++++++++++++++++++++++ lexers/LexSML.cxx | 221 +++++ lexers/LexSQL.cxx | 357 ++++++++ lexers/LexScriptol.cxx | 408 +++++++++ lexers/LexSmalltalk.cxx | 321 +++++++ lexers/LexSorcus.cxx | 205 +++++ lexers/LexSpecman.cxx | 289 +++++++ lexers/LexSpice.cxx | 226 +++++ lexers/LexTACL.cxx | 397 +++++++++ lexers/LexTADS3.cxx | 904 ++++++++++++++++++++ lexers/LexTAL.cxx | 396 +++++++++ lexers/LexTCL.cxx | 366 ++++++++ lexers/LexTeX.cxx | 494 +++++++++++ lexers/LexVB.cxx | 316 +++++++ lexers/LexVHDL.cxx | 476 +++++++++++ lexers/LexVerilog.cxx | 330 +++++++ lexers/LexYAML.cxx | 314 +++++++ src/LexAPDL.cxx | 256 ------ src/LexASY.cxx | 270 ------ src/LexAU3.cxx | 907 -------------------- src/LexAVE.cxx | 228 ----- src/LexAbaqus.cxx | 617 -------------- src/LexAda.cxx | 525 ------------ src/LexAsm.cxx | 180 ---- src/LexAsn1.cxx | 185 ---- src/LexBaan.cxx | 193 ----- src/LexBash.cxx | 521 ----------- src/LexBasic.cxx | 373 -------- src/LexBullant.cxx | 229 ----- src/LexCLW.cxx | 679 --------------- src/LexCOBOL.cxx | 368 -------- src/LexCPP.cxx | 506 ----------- src/LexCSS.cxx | 371 -------- src/LexCaml.cxx | 449 ---------- src/LexCmake.cxx | 457 ---------- src/LexConf.cxx | 188 ---- src/LexCrontab.cxx | 222 ----- src/LexCsound.cxx | 210 ----- src/LexD.cxx | 399 --------- src/LexEScript.cxx | 273 ------ src/LexEiffel.cxx | 238 ------ src/LexErlang.cxx | 619 -------------- src/LexFlagship.cxx | 352 -------- src/LexForth.cxx | 176 ---- src/LexFortran.cxx | 466 ---------- src/LexGAP.cxx | 263 ------ src/LexGui4Cli.cxx | 313 ------- src/LexHTML.cxx | 2132 ---------------------------------------------- src/LexHaskell.cxx | 275 ------ src/LexInno.cxx | 279 ------ src/LexKix.cxx | 126 --- src/LexLisp.cxx | 282 ------ src/LexLout.cxx | 212 ----- src/LexLua.cxx | 358 -------- src/LexMMIXAL.cxx | 186 ---- src/LexMPT.cxx | 188 ---- src/LexMSSQL.cxx | 363 -------- src/LexMagik.cxx | 445 ---------- src/LexMarkdown.cxx | 412 --------- src/LexMatlab.cxx | 236 ----- src/LexMetapost.cxx | 399 --------- src/LexMySQL.cxx | 518 ----------- src/LexNimrod.cxx | 430 ---------- src/LexNsis.cxx | 655 -------------- src/LexOpal.cxx | 522 ------------ src/LexOthers.cxx | 1286 ---------------------------- src/LexPB.cxx | 362 -------- src/LexPLM.cxx | 198 ----- src/LexPOV.cxx | 316 ------- src/LexPS.cxx | 347 -------- src/LexPascal.cxx | 592 ------------- src/LexPerl.cxx | 1305 ---------------------------- src/LexPowerPro.cxx | 600 ------------- src/LexPowerShell.cxx | 198 ----- src/LexProgress.cxx | 279 ------ src/LexPython.cxx | 569 ------------- src/LexR.cxx | 213 ----- src/LexRebol.cxx | 322 ------- src/LexRuby.cxx | 1715 ------------------------------------- src/LexSML.cxx | 221 ----- src/LexSQL.cxx | 357 -------- src/LexScriptol.cxx | 408 --------- src/LexSmalltalk.cxx | 321 ------- src/LexSorcus.cxx | 205 ----- src/LexSpecman.cxx | 289 ------- src/LexSpice.cxx | 226 ----- src/LexTACL.cxx | 397 --------- src/LexTADS3.cxx | 904 -------------------- src/LexTAL.cxx | 396 --------- src/LexTCL.cxx | 366 -------- src/LexTeX.cxx | 494 ----------- src/LexVB.cxx | 316 ------- src/LexVHDL.cxx | 476 ----------- src/LexVerilog.cxx | 330 ------- src/LexYAML.cxx | 314 ------- 156 files changed, 33373 insertions(+), 33373 deletions(-) create mode 100644 lexers/LexAPDL.cxx create mode 100644 lexers/LexASY.cxx create mode 100644 lexers/LexAU3.cxx create mode 100644 lexers/LexAVE.cxx create mode 100644 lexers/LexAbaqus.cxx create mode 100644 lexers/LexAda.cxx create mode 100644 lexers/LexAsm.cxx create mode 100644 lexers/LexAsn1.cxx create mode 100644 lexers/LexBaan.cxx create mode 100644 lexers/LexBash.cxx create mode 100644 lexers/LexBasic.cxx create mode 100644 lexers/LexBullant.cxx create mode 100644 lexers/LexCLW.cxx create mode 100644 lexers/LexCOBOL.cxx create mode 100644 lexers/LexCPP.cxx create mode 100644 lexers/LexCSS.cxx create mode 100644 lexers/LexCaml.cxx create mode 100644 lexers/LexCmake.cxx create mode 100644 lexers/LexConf.cxx create mode 100644 lexers/LexCrontab.cxx create mode 100644 lexers/LexCsound.cxx create mode 100644 lexers/LexD.cxx create mode 100644 lexers/LexEScript.cxx create mode 100644 lexers/LexEiffel.cxx create mode 100644 lexers/LexErlang.cxx create mode 100644 lexers/LexFlagship.cxx create mode 100644 lexers/LexForth.cxx create mode 100644 lexers/LexFortran.cxx create mode 100644 lexers/LexGAP.cxx create mode 100644 lexers/LexGui4Cli.cxx create mode 100644 lexers/LexHTML.cxx create mode 100644 lexers/LexHaskell.cxx create mode 100644 lexers/LexInno.cxx create mode 100644 lexers/LexKix.cxx create mode 100644 lexers/LexLisp.cxx create mode 100644 lexers/LexLout.cxx create mode 100644 lexers/LexLua.cxx create mode 100644 lexers/LexMMIXAL.cxx create mode 100644 lexers/LexMPT.cxx create mode 100644 lexers/LexMSSQL.cxx create mode 100644 lexers/LexMagik.cxx create mode 100644 lexers/LexMarkdown.cxx create mode 100644 lexers/LexMatlab.cxx create mode 100644 lexers/LexMetapost.cxx create mode 100644 lexers/LexMySQL.cxx create mode 100644 lexers/LexNimrod.cxx create mode 100644 lexers/LexNsis.cxx create mode 100644 lexers/LexOpal.cxx create mode 100644 lexers/LexOthers.cxx create mode 100644 lexers/LexPB.cxx create mode 100644 lexers/LexPLM.cxx create mode 100644 lexers/LexPOV.cxx create mode 100644 lexers/LexPS.cxx create mode 100644 lexers/LexPascal.cxx create mode 100644 lexers/LexPerl.cxx create mode 100644 lexers/LexPowerPro.cxx create mode 100644 lexers/LexPowerShell.cxx create mode 100644 lexers/LexProgress.cxx create mode 100644 lexers/LexPython.cxx create mode 100644 lexers/LexR.cxx create mode 100644 lexers/LexRebol.cxx create mode 100644 lexers/LexRuby.cxx create mode 100644 lexers/LexSML.cxx create mode 100644 lexers/LexSQL.cxx create mode 100644 lexers/LexScriptol.cxx create mode 100644 lexers/LexSmalltalk.cxx create mode 100644 lexers/LexSorcus.cxx create mode 100644 lexers/LexSpecman.cxx create mode 100644 lexers/LexSpice.cxx create mode 100644 lexers/LexTACL.cxx create mode 100644 lexers/LexTADS3.cxx create mode 100644 lexers/LexTAL.cxx create mode 100644 lexers/LexTCL.cxx create mode 100644 lexers/LexTeX.cxx create mode 100644 lexers/LexVB.cxx create mode 100644 lexers/LexVHDL.cxx create mode 100644 lexers/LexVerilog.cxx create mode 100644 lexers/LexYAML.cxx delete mode 100644 src/LexAPDL.cxx delete mode 100644 src/LexASY.cxx delete mode 100644 src/LexAU3.cxx delete mode 100644 src/LexAVE.cxx delete mode 100644 src/LexAbaqus.cxx delete mode 100644 src/LexAda.cxx delete mode 100644 src/LexAsm.cxx delete mode 100644 src/LexAsn1.cxx delete mode 100644 src/LexBaan.cxx delete mode 100644 src/LexBash.cxx delete mode 100644 src/LexBasic.cxx delete mode 100644 src/LexBullant.cxx delete mode 100644 src/LexCLW.cxx delete mode 100644 src/LexCOBOL.cxx delete mode 100644 src/LexCPP.cxx delete mode 100644 src/LexCSS.cxx delete mode 100644 src/LexCaml.cxx delete mode 100644 src/LexCmake.cxx delete mode 100644 src/LexConf.cxx delete mode 100644 src/LexCrontab.cxx delete mode 100644 src/LexCsound.cxx delete mode 100644 src/LexD.cxx delete mode 100644 src/LexEScript.cxx delete mode 100644 src/LexEiffel.cxx delete mode 100644 src/LexErlang.cxx delete mode 100644 src/LexFlagship.cxx delete mode 100644 src/LexForth.cxx delete mode 100644 src/LexFortran.cxx delete mode 100644 src/LexGAP.cxx delete mode 100644 src/LexGui4Cli.cxx delete mode 100644 src/LexHTML.cxx delete mode 100644 src/LexHaskell.cxx delete mode 100644 src/LexInno.cxx delete mode 100644 src/LexKix.cxx delete mode 100644 src/LexLisp.cxx delete mode 100644 src/LexLout.cxx delete mode 100644 src/LexLua.cxx delete mode 100644 src/LexMMIXAL.cxx delete mode 100644 src/LexMPT.cxx delete mode 100644 src/LexMSSQL.cxx delete mode 100644 src/LexMagik.cxx delete mode 100644 src/LexMarkdown.cxx delete mode 100644 src/LexMatlab.cxx delete mode 100644 src/LexMetapost.cxx delete mode 100644 src/LexMySQL.cxx delete mode 100644 src/LexNimrod.cxx delete mode 100644 src/LexNsis.cxx delete mode 100644 src/LexOpal.cxx delete mode 100644 src/LexOthers.cxx delete mode 100644 src/LexPB.cxx delete mode 100644 src/LexPLM.cxx delete mode 100644 src/LexPOV.cxx delete mode 100644 src/LexPS.cxx delete mode 100644 src/LexPascal.cxx delete mode 100644 src/LexPerl.cxx delete mode 100644 src/LexPowerPro.cxx delete mode 100644 src/LexPowerShell.cxx delete mode 100644 src/LexProgress.cxx delete mode 100644 src/LexPython.cxx delete mode 100644 src/LexR.cxx delete mode 100644 src/LexRebol.cxx delete mode 100644 src/LexRuby.cxx delete mode 100644 src/LexSML.cxx delete mode 100644 src/LexSQL.cxx delete mode 100644 src/LexScriptol.cxx delete mode 100644 src/LexSmalltalk.cxx delete mode 100644 src/LexSorcus.cxx delete mode 100644 src/LexSpecman.cxx delete mode 100644 src/LexSpice.cxx delete mode 100644 src/LexTACL.cxx delete mode 100644 src/LexTADS3.cxx delete mode 100644 src/LexTAL.cxx delete mode 100644 src/LexTCL.cxx delete mode 100644 src/LexTeX.cxx delete mode 100644 src/LexVB.cxx delete mode 100644 src/LexVHDL.cxx delete mode 100644 src/LexVerilog.cxx delete mode 100644 src/LexYAML.cxx diff --git a/lexers/LexAPDL.cxx b/lexers/LexAPDL.cxx new file mode 100644 index 000000000..7bf597b42 --- /dev/null +++ b/lexers/LexAPDL.cxx @@ -0,0 +1,256 @@ +// Scintilla source code edit control +/** @file LexAPDL.cxx + ** Lexer for APDL. Based on the lexer for Assembler by The Black Horus. + ** By Hadar Raz. + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80 && (isalnum(ch) || ch == '_')); +} + +static inline bool IsAnOperator(char ch) { + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || ch == '^' || + ch == '[' || ch == ']' || ch == '<' || ch == '&' || + ch == '>' || ch == ',' || ch == '|' || ch == '~' || + ch == '$' || ch == ':' || ch == '%') + return true; + return false; +} + +static void ColouriseAPDLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + int stringStart = ' '; + + WordList &processors = *keywordlists[0]; + WordList &commands = *keywordlists[1]; + WordList &slashcommands = *keywordlists[2]; + WordList &starcommands = *keywordlists[3]; + WordList &arguments = *keywordlists[4]; + WordList &functions = *keywordlists[5]; + + // Do not leak onto next line + initStyle = SCE_APDL_DEFAULT; + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + // Determine if the current state should terminate. + if (sc.state == SCE_APDL_NUMBER) { + if (!(IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') || + ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) { + sc.SetState(SCE_APDL_DEFAULT); + } + } else if (sc.state == SCE_APDL_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_APDL_DEFAULT); + } + } else if (sc.state == SCE_APDL_COMMENTBLOCK) { + if (sc.atLineEnd) { + if (sc.ch == '\r') { + sc.Forward(); + } + sc.ForwardSetState(SCE_APDL_DEFAULT); + } + } else if (sc.state == SCE_APDL_STRING) { + if (sc.atLineEnd) { + sc.SetState(SCE_APDL_DEFAULT); + } else if ((sc.ch == '\'' && stringStart == '\'') || (sc.ch == '\"' && stringStart == '\"')) { + sc.ForwardSetState(SCE_APDL_DEFAULT); + } + } else if (sc.state == SCE_APDL_WORD) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (processors.InList(s)) { + sc.ChangeState(SCE_APDL_PROCESSOR); + } else if (slashcommands.InList(s)) { + sc.ChangeState(SCE_APDL_SLASHCOMMAND); + } else if (starcommands.InList(s)) { + sc.ChangeState(SCE_APDL_STARCOMMAND); + } else if (commands.InList(s)) { + sc.ChangeState(SCE_APDL_COMMAND); + } else if (arguments.InList(s)) { + sc.ChangeState(SCE_APDL_ARGUMENT); + } else if (functions.InList(s)) { + sc.ChangeState(SCE_APDL_FUNCTION); + } + sc.SetState(SCE_APDL_DEFAULT); + } + } else if (sc.state == SCE_APDL_OPERATOR) { + if (!IsAnOperator(static_cast(sc.ch))) { + sc.SetState(SCE_APDL_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_APDL_DEFAULT) { + if (sc.ch == '!' && sc.chNext == '!') { + sc.SetState(SCE_APDL_COMMENTBLOCK); + } else if (sc.ch == '!') { + sc.SetState(SCE_APDL_COMMENT); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_APDL_NUMBER); + } else if (sc.ch == '\'' || sc.ch == '\"') { + sc.SetState(SCE_APDL_STRING); + stringStart = sc.ch; + } else if (IsAWordChar(sc.ch) || ((sc.ch == '*' || sc.ch == '/') && !isgraph(sc.chPrev))) { + sc.SetState(SCE_APDL_WORD); + } else if (IsAnOperator(static_cast(sc.ch))) { + sc.SetState(SCE_APDL_OPERATOR); + } + } + } + sc.Complete(); +} + +//------------------------------------------------------------------------------ +// 06-27-07 Sergio Lucato +// - Included code folding for Ansys APDL lexer +// - Copyied from LexBasic.cxx and modified for APDL +//------------------------------------------------------------------------------ + +/* Bits: + * 1 - whitespace + * 2 - operator + * 4 - identifier + * 8 - decimal digit + * 16 - hex digit + * 32 - bin digit + */ +static int character_classification[128] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 10, 6, + 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0 +}; + +static bool IsSpace(int c) { + return c < 128 && (character_classification[c] & 1); +} + +static bool IsIdentifier(int c) { + return c < 128 && (character_classification[c] & 4); +} + +static int LowerCase(int c) +{ + if (c >= 'A' && c <= 'Z') + return 'a' + c - 'A'; + return c; +} + +static int CheckAPDLFoldPoint(char const *token, int &level) { + if (!strcmp(token, "*if") || + !strcmp(token, "*do") || + !strcmp(token, "*dowhile") ) { + level |= SC_FOLDLEVELHEADERFLAG; + return 1; + } + if (!strcmp(token, "*endif") || + !strcmp(token, "*enddo") ) { + return -1; + } + return 0; +} + +static void FoldAPDLDoc(unsigned int startPos, int length, int, + WordList *[], Accessor &styler) { + + int line = styler.GetLine(startPos); + int level = styler.LevelAt(line); + int go = 0, done = 0; + int endPos = startPos + length; + char word[256]; + int wordlen = 0; + int i; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + // Scan for tokens at the start of the line (they may include + // whitespace, for tokens like "End Function" + for (i = startPos; i < endPos; i++) { + int c = styler.SafeGetCharAt(i); + if (!done && !go) { + if (wordlen) { // are we scanning a token already? + word[wordlen] = static_cast(LowerCase(c)); + if (!IsIdentifier(c)) { // done with token + word[wordlen] = '\0'; + go = CheckAPDLFoldPoint(word, level); + if (!go) { + // Treat any whitespace as single blank, for + // things like "End Function". + if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) { + word[wordlen] = ' '; + if (wordlen < 255) + wordlen++; + } + else // done with this line + done = 1; + } + } else if (wordlen < 255) { + wordlen++; + } + } else { // start scanning at first non-whitespace character + if (!IsSpace(c)) { + if (IsIdentifier(c)) { + word[0] = static_cast(LowerCase(c)); + wordlen = 1; + } else // done with this line + done = 1; + } + } + } + if (c == '\n') { // line end + if (!done && wordlen == 0 && foldCompact) // line was only space + level |= SC_FOLDLEVELWHITEFLAG; + if (level != styler.LevelAt(line)) + styler.SetLevel(line, level); + level += go; + line++; + // reset state + wordlen = 0; + level &= ~SC_FOLDLEVELHEADERFLAG; + level &= ~SC_FOLDLEVELWHITEFLAG; + go = 0; + done = 0; + } + } +} + +static const char * const apdlWordListDesc[] = { + "processors", + "commands", + "slashommands", + "starcommands", + "arguments", + "functions", + 0 +}; + +LexerModule lmAPDL(SCLEX_APDL, ColouriseAPDLDoc, "apdl", FoldAPDLDoc, apdlWordListDesc); diff --git a/lexers/LexASY.cxx b/lexers/LexASY.cxx new file mode 100644 index 000000000..5bf979fd3 --- /dev/null +++ b/lexers/LexASY.cxx @@ -0,0 +1,270 @@ +// Scintilla source code edit control +//Author: instanton (email: soft_share126com) +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "CharacterSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static void ColouriseAsyDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + + CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); + + int visibleChars = 0; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart) { + if (sc.state == SCE_ASY_STRING) { + sc.SetState(SCE_ASY_STRING); + } + visibleChars = 0; + } + + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } +// continuationLine = true; + continue; + } + } + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_ASY_OPERATOR: + sc.SetState(SCE_ASY_DEFAULT); + break; + case SCE_ASY_NUMBER: + if (!setWord.Contains(sc.ch)) { + sc.SetState(SCE_ASY_DEFAULT); + } + break; + case SCE_ASY_IDENTIFIER: + if (!setWord.Contains(sc.ch) || (sc.ch == '.')) { + char s[1000]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_ASY_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_ASY_WORD2); + } + sc.SetState(SCE_ASY_DEFAULT); + } + break; + case SCE_ASY_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_ASY_DEFAULT); + } + break; + case SCE_ASY_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_ASY_DEFAULT); + } + break; + case SCE_ASY_STRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_ASY_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_ASY_DEFAULT); + } + break; + case SCE_ASY_CHARACTER: + if (sc.atLineEnd) { + sc.ChangeState(SCE_ASY_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_ASY_DEFAULT); + } + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_ASY_DEFAULT) { + if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) { + sc.SetState(SCE_ASY_IDENTIFIER); + } else if (sc.Match('/', '*')) { + sc.SetState(SCE_ASY_COMMENT); + sc.Forward(); // + } else if (sc.Match('/', '/')) { + sc.SetState(SCE_ASY_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_ASY_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_ASY_CHARACTER); + } else if (sc.ch == '#' && visibleChars == 0) { + do { + sc.Forward(); + } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); + if (sc.atLineEnd) { + sc.SetState(SCE_ASY_DEFAULT); + } + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_ASY_OPERATOR); + } + } + + } + sc.Complete(); +} + +static bool IsAsyCommentStyle(int style) { + return style == SCE_ASY_COMMENT; +} + + +static inline bool isASYidentifier(int ch) { + return + ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ; +} + +static int ParseASYWord(unsigned int pos, Accessor &styler, char *word) +{ + int length=0; + char ch=styler.SafeGetCharAt(pos); + *word=0; + + while(isASYidentifier(ch) && length<100){ + word[length]=ch; + length++; + ch=styler.SafeGetCharAt(pos+length); + } + word[length]=0; + return length; +} + +static bool IsASYDrawingLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + + int startpos = pos; + char buffer[100]=""; + + while (startpos 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && IsAsyCommentStyle(style)) { + if (!IsAsyCommentStyle(stylePrev) && (stylePrev != SCE_ASY_COMMENTLINEDOC)) { + levelNext++; + } else if (!IsAsyCommentStyle(styleNext) && (styleNext != SCE_ASY_COMMENTLINEDOC) && !atEOL) { + levelNext--; + } + } + if (style == SCE_ASY_OPERATOR) { + if (ch == '{') { + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + + if (atEOL && IsASYDrawingLine(lineCurrent, styler)){ + if (lineCurrent==0 && IsASYDrawingLine(lineCurrent + 1, styler)) + levelNext++; + else if (lineCurrent!=0 && !IsASYDrawingLine(lineCurrent - 1, styler) + && IsASYDrawingLine(lineCurrent + 1, styler) + ) + levelNext++; + else if (lineCurrent!=0 && IsASYDrawingLine(lineCurrent - 1, styler) && + !IsASYDrawingLine(lineCurrent+1, styler)) + levelNext--; + } + + if (atEOL) { + int levelUse = levelCurrent; + if (foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + visibleChars = 0; + } + if (!IsASpace(ch)) + visibleChars++; + } +} + +static const char * const asyWordLists[] = { + "Primary keywords and identifiers", + "Secondary keywords and identifiers", + 0, + }; + +LexerModule lmASY(SCLEX_ASYMPTOTE, ColouriseAsyDoc, "asy", FoldAsyDoc, asyWordLists); diff --git a/lexers/LexAU3.cxx b/lexers/LexAU3.cxx new file mode 100644 index 000000000..cfff9279d --- /dev/null +++ b/lexers/LexAU3.cxx @@ -0,0 +1,907 @@ +// Scintilla source code edit control +// @file LexAU3.cxx +// Lexer for AutoIt3 http://www.hiddensoft.com/autoit3 +// by Jos van der Zande, jvdzande@yahoo.com +// +// Changes: +// March 28, 2004 - Added the standard Folding code +// April 21, 2004 - Added Preprosessor Table + Syntax Highlighting +// Fixed Number highlighting +// Changed default isoperator to IsAOperator to have a better match to AutoIt3 +// Fixed "#comments_start" -> "#comments-start" +// Fixed "#comments_end" -> "#comments-end" +// Fixed Sendkeys in Strings when not terminated with } +// Added support for Sendkey strings that have second parameter e.g. {UP 5} or {a down} +// April 26, 2004 - Fixed # pre-processor statement inside of comment block would invalidly change the color. +// Added logic for #include to treat the <> as string +// Added underscore to IsAOperator. +// May 17, 2004 - Changed the folding logic from indent to keyword folding. +// Added Folding logic for blocks of single-commentlines or commentblock. +// triggered by: fold.comment=1 +// Added Folding logic for preprocessor blocks triggered by fold.preprocessor=1 +// Added Special for #region - #endregion syntax highlight and folding. +// May 30, 2004 - Fixed issue with continuation lines on If statements. +// June 5, 2004 - Added comma to Operators for better readability. +// Added fold.compact support set with fold.compact=1 +// Changed folding inside of #cs-#ce. Default is no keyword folding inside comment blocks when fold.comment=1 +// it will now only happen when fold.comment=2. +// Sep 5, 2004 - Added logic to handle colourizing words on the last line. +// Typed Characters now show as "default" till they match any table. +// Oct 10, 2004 - Added logic to show Comments in "Special" directives. +// Nov 1, 2004 - Added better testing for Numbers supporting x and e notation. +// Nov 28, 2004 - Added logic to handle continuation lines for syntax highlighting. +// Jan 10, 2005 - Added Abbreviations Keyword used for expansion +// Mar 24, 2005 - Updated Abbreviations Keywords to fix when followed by Operator. +// Apr 18, 2005 - Updated #CE/#Comment-End logic to take a linecomment ";" into account +// - Added folding support for With...EndWith +// - Added support for a DOT in variable names +// - Fixed Underscore in CommentBlock +// May 23, 2005 - Fixed the SentKey lexing in case of a missing } +// Aug 11, 2005 - Fixed possible bug with s_save length > 100. +// Aug 23, 2005 - Added Switch/endswitch support to the folding logic. +// Sep 27, 2005 - Fixed the SentKey lexing logic in case of multiple sentkeys. +// Mar 12, 2006 - Fixed issue with <> coloring as String in stead of Operator in rare occasions. +// Apr 8, 2006 - Added support for AutoIt3 Standard UDF library (SCE_AU3_UDF) +// Mar 9, 2007 - Fixed bug with + following a String getting the wrong Color. +// Jun 20, 2007 - Fixed Commentblock issue when LF's are used as EOL. +// Jul 26, 2007 - Fixed #endregion undetected bug. +// +// Copyright for Scintilla: 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. +// Scintilla source code edit control + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsTypeCharacter(const int ch) +{ + return ch == '$'; +} +static inline bool IsAWordChar(const int ch) +{ + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordStart(const int ch) +{ + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$' || ch == '.'); +} + +static inline bool IsAOperator(char ch) { + if (isascii(ch) && isalnum(ch)) + return false; + if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || + ch == '&' || ch == '^' || ch == '=' || ch == '<' || ch == '>' || + ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == ',' ) + return true; + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetSendKey() filters the portion before and after a/multiple space(s) +// and return the first portion to be looked-up in the table +// also check if the second portion is valid... (up,down.on.off,toggle or a number) +/////////////////////////////////////////////////////////////////////////////// + +static int GetSendKey(const char *szLine, char *szKey) +{ + int nFlag = 0; + int nStartFound = 0; + int nKeyPos = 0; + int nSpecPos= 0; + int nSpecNum= 1; + int nPos = 0; + char cTemp; + char szSpecial[100]; + + // split the portion of the sendkey in the part before and after the spaces + while ( ( (cTemp = szLine[nPos]) != '\0')) + { + // skip leading Ctrl/Shift/Alt state + if (cTemp == '{') { + nStartFound = 1; + } + // + if (nStartFound == 1) { + if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space + { + nFlag = 1; + // Add } to the end of the first bit for table lookup later. + szKey[nKeyPos++] = '}'; + } + else if (cTemp == ' ') + { + // skip other spaces + } + else if (nFlag == 0) + { + // save first portion into var till space or } is hit + szKey[nKeyPos++] = cTemp; + } + else if ((nFlag == 1) && (cTemp != '}')) + { + // Save second portion into var... + szSpecial[nSpecPos++] = cTemp; + // check if Second portion is all numbers for repeat fuction + if (isdigit(cTemp) == false) {nSpecNum = 0;} + } + } + nPos++; // skip to next char + + } // End While + + + // Check if the second portion is either a number or one of these keywords + szKey[nKeyPos] = '\0'; + szSpecial[nSpecPos] = '\0'; + if (strcmp(szSpecial,"down")== 0 || strcmp(szSpecial,"up")== 0 || + strcmp(szSpecial,"on")== 0 || strcmp(szSpecial,"off")== 0 || + strcmp(szSpecial,"toggle")== 0 || nSpecNum == 1 ) + { + nFlag = 0; + } + else + { + nFlag = 1; + } + return nFlag; // 1 is bad, 0 is good + +} // GetSendKey() + +// +// Routine to check the last "none comment" character on a line to see if its a continuation +// +static bool IsContinuationLine(unsigned int szLine, Accessor &styler) +{ + int nsPos = styler.LineStart(szLine); + int nePos = styler.LineStart(szLine+1) - 2; + //int stylech = styler.StyleAt(nsPos); + while (nsPos < nePos) + { + //stylech = styler.StyleAt(nePos); + int stylech = styler.StyleAt(nsPos); + if (!(stylech == SCE_AU3_COMMENT)) { + char ch = styler.SafeGetCharAt(nePos); + if (!isspacechar(ch)) { + if (ch == '_') + return true; + else + return false; + } + } + nePos--; // skip to next char + } // End While + return false; +} // IsContinuationLine() + +// +// syntax highlighting logic +static void ColouriseAU3Doc(unsigned int startPos, + int length, int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; + WordList &keywords7 = *keywordlists[6]; + WordList &keywords8 = *keywordlists[7]; + // find the first previous line without continuation character at the end + int lineCurrent = styler.GetLine(startPos); + int s_startPos = startPos; + // When not inside a Block comment: find First line without _ + if (!(initStyle==SCE_AU3_COMMENTBLOCK)) { + while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || + (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); // get start position + initStyle = 0; // reset the start style to 0 + } + } + // Set the new length to include it from the start and set the start position + length = length + s_startPos - startPos; // correct the total length to process + styler.StartAt(startPos); + + StyleContext sc(startPos, length, initStyle, styler); + char si; // string indicator "=1 '=2 + char ni; // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 Enot=3 + char ci; // comment indicator 0=not linecomment(;) + char s_save[100]; + si=0; + ni=0; + ci=0; + //$$$ + for (; sc.More(); sc.Forward()) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + // ********************************************** + // save the total current word for eof processing + if (IsAWordChar(sc.ch) || sc.ch == '}') + { + strcpy(s_save,s); + int tp = strlen(s_save); + if (tp < 99) { + s_save[tp] = static_cast(tolower(sc.ch)); + s_save[tp+1] = '\0'; + } + } + // ********************************************** + // + switch (sc.state) + { + case SCE_AU3_COMMENTBLOCK: + { + //Reset at line end + if (sc.atLineEnd) { + ci=0; + if (strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0) { + if (sc.atLineEnd) + sc.SetState(SCE_AU3_DEFAULT); + else + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + break; + } + //skip rest of line when a ; is encountered + if (sc.chPrev == ';') { + ci=2; + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + // skip rest of the line + if (ci==2) + break; + // check when first character is detected on the line + if (ci==0) { + if (IsAWordStart(static_cast(sc.ch)) || IsAOperator(static_cast(sc.ch))) { + ci=1; + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + break; + } + if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && strcmp(s, "#comments") == 0))) { + if ((strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0)) + sc.SetState(SCE_AU3_COMMENT); // set to comment line for the rest of the line + else + ci=2; // line doesn't begin with #CE so skip the rest of the line + } + break; + } + case SCE_AU3_COMMENT: + { + if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} + break; + } + case SCE_AU3_OPERATOR: + { + // check if its a COMobject + if (sc.chPrev == '.' && IsAWordChar(sc.ch)) { + sc.SetState(SCE_AU3_COMOBJ); + } + else { + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_SPECIAL: + { + if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);} + if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} + break; + } + case SCE_AU3_KEYWORD: + { + if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && (strcmp(s, "#comments") == 0 || strcmp(s, "#include") == 0)))) + { + if (!IsTypeCharacter(sc.ch)) + { + if (strcmp(s, "#cs")== 0 || strcmp(s, "#comments-start")== 0 ) + { + sc.ChangeState(SCE_AU3_COMMENTBLOCK); + sc.SetState(SCE_AU3_COMMENTBLOCK); + break; + } + else if (keywords.InList(s)) { + sc.ChangeState(SCE_AU3_KEYWORD); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords2.InList(s)) { + sc.ChangeState(SCE_AU3_FUNCTION); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords3.InList(s)) { + sc.ChangeState(SCE_AU3_MACRO); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords5.InList(s)) { + sc.ChangeState(SCE_AU3_PREPROCESSOR); + sc.SetState(SCE_AU3_DEFAULT); + if (strcmp(s, "#include")== 0) + { + si = 3; // use to determine string start for #inlude <> + } + } + else if (keywords6.InList(s)) { + sc.ChangeState(SCE_AU3_SPECIAL); + sc.SetState(SCE_AU3_SPECIAL); + } + else if ((keywords7.InList(s)) && (!IsAOperator(static_cast(sc.ch)))) { + sc.ChangeState(SCE_AU3_EXPAND); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords8.InList(s)) { + sc.ChangeState(SCE_AU3_UDF); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (strcmp(s, "_") == 0) { + sc.ChangeState(SCE_AU3_OPERATOR); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (!IsAWordChar(sc.ch)) { + sc.ChangeState(SCE_AU3_DEFAULT); + sc.SetState(SCE_AU3_DEFAULT); + } + } + } + if (sc.atLineEnd) { + sc.SetState(SCE_AU3_DEFAULT);} + break; + } + case SCE_AU3_NUMBER: + { + // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 E-not=3 + // + // test for Hex notation + if (strcmp(s, "0") == 0 && (sc.ch == 'x' || sc.ch == 'X') && ni == 0) + { + ni = 2; + break; + } + // test for E notation + if (IsADigit(sc.chPrev) && (sc.ch == 'e' || sc.ch == 'E') && ni <= 1) + { + ni = 3; + break; + } + // Allow Hex characters inside hex numeric strings + if ((ni == 2) && + (sc.ch == 'a' || sc.ch == 'b' || sc.ch == 'c' || sc.ch == 'd' || sc.ch == 'e' || sc.ch == 'f' || + sc.ch == 'A' || sc.ch == 'B' || sc.ch == 'C' || sc.ch == 'D' || sc.ch == 'E' || sc.ch == 'F' )) + { + break; + } + // test for 1 dec point only + if (sc.ch == '.') + { + if (ni==0) + { + ni=1; + } + else + { + ni=9; + } + break; + } + // end of numeric string ? + if (!(IsADigit(sc.ch))) + { + if (ni==9) + { + sc.ChangeState(SCE_AU3_DEFAULT); + } + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_VARIABLE: + { + // Check if its a COMObject + if (sc.ch == '.' && !IsADigit(sc.chNext)) { + sc.SetState(SCE_AU3_OPERATOR); + } + else if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_COMOBJ: + { + if (!(IsAWordChar(sc.ch))) { + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_STRING: + { + // check for " to end a double qouted string or + // check for ' to end a single qouted string + if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'') || (si == 3 && sc.ch == '>')) + { + sc.ForwardSetState(SCE_AU3_DEFAULT); + si=0; + break; + } + if (sc.atLineEnd) + { + si=0; + // at line end and not found a continuation char then reset to default + int lineCurrent = styler.GetLine(sc.currentPos); + if (!IsContinuationLine(lineCurrent,styler)) + { + sc.SetState(SCE_AU3_DEFAULT); + break; + } + } + // find Sendkeys in a STRING + if (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ) { + sc.SetState(SCE_AU3_SENT);} + break; + } + + case SCE_AU3_SENT: + { + // Send key string ended + if (sc.chPrev == '}' && sc.ch != '}') + { + // set color to SENDKEY when valid sendkey .. else set back to regular string + char sk[100]; + // split {111 222} and return {111} and check if 222 is valid. + // if return code = 1 then invalid 222 so must be string + if (GetSendKey(s,sk)) + { + sc.ChangeState(SCE_AU3_STRING); + } + // if single char between {?} then its ok as sendkey for a single character + else if (strlen(sk) == 3) + { + sc.ChangeState(SCE_AU3_SENT); + } + // if sendkey {111} is in table then ok as sendkey + else if (keywords4.InList(sk)) + { + sc.ChangeState(SCE_AU3_SENT); + } + else + { + sc.ChangeState(SCE_AU3_STRING); + } + sc.SetState(SCE_AU3_STRING); + } + else + { + // check if the start is a valid SendKey start + int nPos = 0; + int nState = 1; + char cTemp; + while (!(nState == 2) && ((cTemp = s[nPos]) != '\0')) + { + if (cTemp == '{' && nState == 1) + { + nState = 2; + } + if (nState == 1 && !(cTemp == '+' || cTemp == '!' || cTemp == '^' || cTemp == '#' )) + { + nState = 0; + } + nPos++; + } + //Verify characters infront of { ... if not assume regular string + if (nState == 1 && (!(sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ))) { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_STRING); + } + // If invalid character found then assume its a regular string + if (nState == 0) { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_STRING); + } + } + // check if next portion is again a sendkey + if (sc.atLineEnd) + { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_DEFAULT); + si = 0; // reset string indicator + } + //* check in next characters following a sentkey are again a sent key + // Need this test incase of 2 sentkeys like {F1}{ENTER} but not detect {{} + if (sc.state == SCE_AU3_STRING && (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' )) { + sc.SetState(SCE_AU3_SENT);} + // check to see if the string ended... + // Sendkey string isn't complete but the string ended.... + if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'')) + { + sc.ChangeState(SCE_AU3_STRING); + sc.ForwardSetState(SCE_AU3_DEFAULT); + } + break; + } + } //switch (sc.state) + + // Determine if a new state should be entered: + + if (sc.state == SCE_AU3_DEFAULT) + { + if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);} + else if (sc.ch == '#') {sc.SetState(SCE_AU3_KEYWORD);} + else if (sc.ch == '$') {sc.SetState(SCE_AU3_VARIABLE);} + else if (sc.ch == '.' && !IsADigit(sc.chNext)) {sc.SetState(SCE_AU3_OPERATOR);} + else if (sc.ch == '@') {sc.SetState(SCE_AU3_KEYWORD);} + //else if (sc.ch == '_') {sc.SetState(SCE_AU3_KEYWORD);} + else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);} // string after #include + else if (sc.ch == '\"') { + sc.SetState(SCE_AU3_STRING); + si = 1; } + else if (sc.ch == '\'') { + sc.SetState(SCE_AU3_STRING); + si = 2; } + else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) + { + sc.SetState(SCE_AU3_NUMBER); + ni = 0; + } + else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_AU3_KEYWORD);} + else if (IsAOperator(static_cast(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);} + else if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} + } + } //for (; sc.More(); sc.Forward()) + + //************************************* + // Colourize the last word correctly + //************************************* + if (sc.state == SCE_AU3_KEYWORD) + { + if (strcmp(s_save, "#cs")== 0 || strcmp(s_save, "#comments-start")== 0 ) + { + sc.ChangeState(SCE_AU3_COMMENTBLOCK); + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + else if (keywords.InList(s_save)) { + sc.ChangeState(SCE_AU3_KEYWORD); + sc.SetState(SCE_AU3_KEYWORD); + } + else if (keywords2.InList(s_save)) { + sc.ChangeState(SCE_AU3_FUNCTION); + sc.SetState(SCE_AU3_FUNCTION); + } + else if (keywords3.InList(s_save)) { + sc.ChangeState(SCE_AU3_MACRO); + sc.SetState(SCE_AU3_MACRO); + } + else if (keywords5.InList(s_save)) { + sc.ChangeState(SCE_AU3_PREPROCESSOR); + sc.SetState(SCE_AU3_PREPROCESSOR); + } + else if (keywords6.InList(s_save)) { + sc.ChangeState(SCE_AU3_SPECIAL); + sc.SetState(SCE_AU3_SPECIAL); + } + else if (keywords7.InList(s_save) && sc.atLineEnd) { + sc.ChangeState(SCE_AU3_EXPAND); + sc.SetState(SCE_AU3_EXPAND); + } + else if (keywords8.InList(s_save)) { + sc.ChangeState(SCE_AU3_UDF); + sc.SetState(SCE_AU3_UDF); + } + else { + sc.ChangeState(SCE_AU3_DEFAULT); + sc.SetState(SCE_AU3_DEFAULT); + } + } + if (sc.state == SCE_AU3_SENT) + { + // Send key string ended + if (sc.chPrev == '}' && sc.ch != '}') + { + // set color to SENDKEY when valid sendkey .. else set back to regular string + char sk[100]; + // split {111 222} and return {111} and check if 222 is valid. + // if return code = 1 then invalid 222 so must be string + if (GetSendKey(s_save,sk)) + { + sc.ChangeState(SCE_AU3_STRING); + } + // if single char between {?} then its ok as sendkey for a single character + else if (strlen(sk) == 3) + { + sc.ChangeState(SCE_AU3_SENT); + } + // if sendkey {111} is in table then ok as sendkey + else if (keywords4.InList(sk)) + { + sc.ChangeState(SCE_AU3_SENT); + } + else + { + sc.ChangeState(SCE_AU3_STRING); + } + sc.SetState(SCE_AU3_STRING); + } + // check if next portion is again a sendkey + if (sc.atLineEnd) + { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_DEFAULT); + } + } + //************************************* + sc.Complete(); +} + +// +static bool IsStreamCommentStyle(int style) { + return style == SCE_AU3_COMMENT || style == SCE_AU3_COMMENTBLOCK; +} + +// +// Routine to find first none space on the current line and return its Style +// needed for comment lines not starting on pos 1 +static int GetStyleFirstWord(unsigned int szLine, Accessor &styler) +{ + int nsPos = styler.LineStart(szLine); + int nePos = styler.LineStart(szLine+1) - 1; + while (isspacechar(styler.SafeGetCharAt(nsPos)) && nsPos < nePos) + { + nsPos++; // skip to next char + + } // End While + return styler.StyleAt(nsPos); + +} // GetStyleFirstWord() + + +// +static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) +{ + int endPos = startPos + length; + // get settings from the config files for folding comments and preprocessor lines + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldInComment = styler.GetPropertyInt("fold.comment") == 2; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldpreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; + // Backtrack to previous line in case need to fix its fold status + int lineCurrent = styler.GetLine(startPos); + if (startPos > 0) { + if (lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + } + // vars for style of previous/current/next lines + int style = GetStyleFirstWord(lineCurrent,styler); + int stylePrev = 0; + // find the first previous line without continuation character at the end + while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || + (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + if (lineCurrent > 0) { + stylePrev = GetStyleFirstWord(lineCurrent-1,styler); + } + // vars for getting first word to check for keywords + bool FirstWordStart = false; + bool FirstWordEnd = false; + char szKeyword[11]=""; + int szKeywordlen = 0; + char szThen[5]=""; + int szThenlen = 0; + bool ThenFoundLast = false; + // var for indentlevel + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelNext = levelCurrent; + // + int visibleChars = 0; + char chNext = styler.SafeGetCharAt(startPos); + char chPrev = ' '; + // + for (int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + if (IsAWordChar(ch)) { + visibleChars++; + } + // get the syle for the current character neede to check in comment + int stylech = styler.StyleAt(i); + // get first word for the line for indent check max 9 characters + if (FirstWordStart && (!(FirstWordEnd))) { + if (!IsAWordChar(ch)) { + FirstWordEnd = true; + szKeyword[szKeywordlen] = '\0'; + } + else { + if (szKeywordlen < 10) { + szKeyword[szKeywordlen++] = static_cast(tolower(ch)); + } + } + } + // start the capture of the first word + if (!(FirstWordStart)) { + if (IsAWordChar(ch) || IsAWordStart(ch) || ch == ';') { + FirstWordStart = true; + szKeyword[szKeywordlen++] = static_cast(tolower(ch)); + } + } + // only process this logic when not in comment section + if (!(stylech == SCE_AU3_COMMENT)) { + if (ThenFoundLast) { + if (IsAWordChar(ch)) { + ThenFoundLast = false; + } + } + // find out if the word "then" is the last on a "if" line + if (FirstWordEnd && strcmp(szKeyword,"if") == 0) { + if (szThenlen == 4) { + szThen[0] = szThen[1]; + szThen[1] = szThen[2]; + szThen[2] = szThen[3]; + szThen[3] = static_cast(tolower(ch)); + if (strcmp(szThen,"then") == 0 ) { + ThenFoundLast = true; + } + } + else { + szThen[szThenlen++] = static_cast(tolower(ch)); + if (szThenlen == 5) { + szThen[4] = '\0'; + } + } + } + } + // End of Line found so process the information + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { + // ************************** + // Folding logic for Keywords + // ************************** + // if a keyword is found on the current line and the line doesn't end with _ (continuation) + // and we are not inside a commentblock. + if (szKeywordlen > 0 && (!(chPrev == '_')) && + ((!(IsStreamCommentStyle(style)) || foldInComment)) ) { + szKeyword[szKeywordlen] = '\0'; + // only fold "if" last keyword is "then" (else its a one line if) + if (strcmp(szKeyword,"if") == 0 && ThenFoundLast) { + levelNext++; + } + // create new fold for these words + if (strcmp(szKeyword,"do") == 0 || strcmp(szKeyword,"for") == 0 || + strcmp(szKeyword,"func") == 0 || strcmp(szKeyword,"while") == 0|| + strcmp(szKeyword,"with") == 0 || strcmp(szKeyword,"#region") == 0 ) { + levelNext++; + } + // create double Fold for select&switch because Case will subtract one of the current level + if (strcmp(szKeyword,"select") == 0 || strcmp(szKeyword,"switch") == 0) { + levelNext++; + levelNext++; + } + // end the fold for these words before the current line + if (strcmp(szKeyword,"endfunc") == 0 || strcmp(szKeyword,"endif") == 0 || + strcmp(szKeyword,"next") == 0 || strcmp(szKeyword,"until") == 0 || + strcmp(szKeyword,"endwith") == 0 ||strcmp(szKeyword,"wend") == 0){ + levelNext--; + levelCurrent--; + } + // end the fold for these words before the current line and Start new fold + if (strcmp(szKeyword,"case") == 0 || strcmp(szKeyword,"else") == 0 || + strcmp(szKeyword,"elseif") == 0 ) { + levelCurrent--; + } + // end the double fold for this word before the current line + if (strcmp(szKeyword,"endselect") == 0 || strcmp(szKeyword,"endswitch") == 0 ) { + levelNext--; + levelNext--; + levelCurrent--; + levelCurrent--; + } + // end the fold for these words on the current line + if (strcmp(szKeyword,"#endregion") == 0 ) { + levelNext--; + } + } + // Preprocessor and Comment folding + int styleNext = GetStyleFirstWord(lineCurrent + 1,styler); + // ************************************* + // Folding logic for preprocessor blocks + // ************************************* + // process preprosessor line + if (foldpreprocessor && style == SCE_AU3_PREPROCESSOR) { + if (!(stylePrev == SCE_AU3_PREPROCESSOR) && (styleNext == SCE_AU3_PREPROCESSOR)) { + levelNext++; + } + // fold till the last line for normal comment lines + else if (stylePrev == SCE_AU3_PREPROCESSOR && !(styleNext == SCE_AU3_PREPROCESSOR)) { + levelNext--; + } + } + // ********************************* + // Folding logic for Comment blocks + // ********************************* + if (foldComment && IsStreamCommentStyle(style)) { + // Start of a comment block + if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) { + levelNext++; + } + // fold till the last line for normal comment lines + else if (IsStreamCommentStyle(stylePrev) + && !(styleNext == SCE_AU3_COMMENT) + && stylePrev == SCE_AU3_COMMENT + && style == SCE_AU3_COMMENT) { + levelNext--; + } + // fold till the one but last line for Blockcomment lines + else if (IsStreamCommentStyle(stylePrev) + && !(styleNext == SCE_AU3_COMMENTBLOCK) + && style == SCE_AU3_COMMENTBLOCK) { + levelNext--; + levelCurrent--; + } + } + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + // reset values for the next line + lineCurrent++; + stylePrev = style; + style = styleNext; + levelCurrent = levelNext; + visibleChars = 0; + // if the last character is an Underscore then don't reset since the line continues on the next line. + if (!(chPrev == '_')) { + szKeywordlen = 0; + szThenlen = 0; + FirstWordStart = false; + FirstWordEnd = false; + ThenFoundLast = false; + } + } + // save the last processed character + if (!isspacechar(ch)) { + chPrev = ch; + visibleChars++; + } + } +} + + +// + +static const char * const AU3WordLists[] = { + "#autoit keywords", + "#autoit functions", + "#autoit macros", + "#autoit Sent keys", + "#autoit Pre-processors", + "#autoit Special", + "#autoit Expand", + "#autoit UDF", + 0 +}; +LexerModule lmAU3(SCLEX_AU3, ColouriseAU3Doc, "au3", FoldAU3Doc , AU3WordLists); diff --git a/lexers/LexAVE.cxx b/lexers/LexAVE.cxx new file mode 100644 index 000000000..09b393343 --- /dev/null +++ b/lexers/LexAVE.cxx @@ -0,0 +1,228 @@ +// SciTE - Scintilla based Text Editor +/** @file LexAVE.cxx + ** Lexer for Avenue. + ** + ** Written by Alexey Yutkin . + **/ +// Copyright 1998-2002 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); +} +static inline bool IsEnumChar(const int ch) { + return (ch < 0x80) && (isalnum(ch)|| ch == '_'); +} +static inline bool IsANumberChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' ); +} + +inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +inline bool isAveOperator(char ch) { + if (isascii(ch) && isalnum(ch)) + return false; + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || + ch == '{' || ch == '}' || + ch == '[' || ch == ']' || ch == ';' || + ch == '<' || ch == '>' || ch == ',' || + ch == '.' ) + return true; + return false; +} + +static void ColouriseAveDoc( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; + + // Do not leak onto next line + if (initStyle == SCE_AVE_STRINGEOL) { + initStyle = SCE_AVE_DEFAULT; + } + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + if (sc.atLineEnd) { + // Update the line state, so it can be seen by next line + int currentLine = styler.GetLine(sc.currentPos); + styler.SetLineState(currentLine, 0); + } + if (sc.atLineStart && (sc.state == SCE_AVE_STRING)) { + // Prevent SCE_AVE_STRINGEOL from leaking back to previous line + sc.SetState(SCE_AVE_STRING); + } + + + // Determine if the current state should terminate. + if (sc.state == SCE_AVE_OPERATOR) { + sc.SetState(SCE_AVE_DEFAULT); + } else if (sc.state == SCE_AVE_NUMBER) { + if (!IsANumberChar(sc.ch)) { + sc.SetState(SCE_AVE_DEFAULT); + } + } else if (sc.state == SCE_AVE_ENUM) { + if (!IsEnumChar(sc.ch)) { + sc.SetState(SCE_AVE_DEFAULT); + } + } else if (sc.state == SCE_AVE_IDENTIFIER) { + if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { + char s[100]; + //sc.GetCurrent(s, sizeof(s)); + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_AVE_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_AVE_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_AVE_WORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_AVE_WORD4); + } else if (keywords5.InList(s)) { + sc.ChangeState(SCE_AVE_WORD5); + } else if (keywords6.InList(s)) { + sc.ChangeState(SCE_AVE_WORD6); + } + sc.SetState(SCE_AVE_DEFAULT); + } + } else if (sc.state == SCE_AVE_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_AVE_DEFAULT); + } + } else if (sc.state == SCE_AVE_STRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_AVE_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_AVE_STRINGEOL); + sc.ForwardSetState(SCE_AVE_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_AVE_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_AVE_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_AVE_IDENTIFIER); + } else if (sc.Match('\"')) { + sc.SetState(SCE_AVE_STRING); + } else if (sc.Match('\'')) { + sc.SetState(SCE_AVE_COMMENT); + sc.Forward(); + } else if (isAveOperator(static_cast(sc.ch))) { + sc.SetState(SCE_AVE_OPERATOR); + } else if (sc.Match('#')) { + sc.SetState(SCE_AVE_ENUM); + sc.Forward(); + } + } + } + sc.Complete(); +} + +static void FoldAveDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[], + Accessor &styler) { + unsigned int lengthDoc = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = static_cast(tolower(styler[startPos])); + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + int styleNext = styler.StyleAt(startPos); + char s[10]; + + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = static_cast(tolower(chNext)); + chNext = static_cast(tolower(styler.SafeGetCharAt(i + 1))); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (style == SCE_AVE_WORD) { + if (ch == 't' || ch == 'f' || ch == 'w' || ch == 'e') { + for (unsigned int j = 0; j < 6; j++) { + if (!iswordchar(styler[i + j])) { + break; + } + s[j] = static_cast(tolower(styler[i + j])); + s[j + 1] = '\0'; + } + + if ((strcmp(s, "then") == 0) || (strcmp(s, "for") == 0) || (strcmp(s, "while") == 0)) { + levelCurrent++; + } + if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0)) { + // Normally "elseif" and "then" will be on the same line and will cancel + // each other out. // As implemented, this does not support fold.at.else. + levelCurrent--; + } + } + } else if (style == SCE_AVE_OPERATOR) { + if (ch == '{' || ch == '(') { + levelCurrent++; + } else if (ch == '}' || ch == ')') { + levelCurrent--; + } + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) { + lev |= SC_FOLDLEVELWHITEFLAG; + } + if ((levelCurrent > levelPrev) && (visibleChars > 0)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) { + visibleChars++; + } + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +LexerModule lmAVE(SCLEX_AVE, ColouriseAveDoc, "ave", FoldAveDoc); + diff --git a/lexers/LexAbaqus.cxx b/lexers/LexAbaqus.cxx new file mode 100644 index 000000000..10e8b76b1 --- /dev/null +++ b/lexers/LexAbaqus.cxx @@ -0,0 +1,617 @@ +// Scintilla source code edit control +/** @file LexABAQUS.cxx + ** Lexer for ABAQUS. Based on the lexer for APDL by Hadar Raz. + ** By Sergio Lucato. + ** Sort of completely rewritten by Gertjan Kloosterman + **/ +// The License.txt file describes the conditions under which this software may be distributed. + +// Code folding copyied and modified from LexBasic.cxx + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80 && (isalnum(ch) || (ch == '_'))); +} + +static inline bool IsAKeywordChar(const int ch) { + return (ch < 0x80 && (isalnum(ch) || (ch == '_') || (ch == ' '))); +} + +static inline bool IsASetChar(const int ch) { + return (ch < 0x80 && (isalnum(ch) || (ch == '_') || (ch == '.') || (ch == '-'))); +} + +static inline bool IsAnOperator(char ch) { + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || ch == '^' || + ch == '[' || ch == ']' || ch == '<' || ch == '&' || + ch == '>' || ch == ',' || ch == '|' || ch == '~' || + ch == '$' || ch == ':' || ch == '%') + return true; + return false; +} + +static void ColouriseABAQUSDoc(unsigned int startPos, int length, int initStyle, WordList*[] /* *keywordlists[] */, + Accessor &styler) { + enum localState { KW_LINE_KW, KW_LINE_COMMA, KW_LINE_PAR, KW_LINE_EQ, KW_LINE_VAL, \ + DAT_LINE_VAL, DAT_LINE_COMMA,\ + COMMENT_LINE,\ + ST_ERROR, LINE_END } state ; + + // Do not leak onto next line + state = LINE_END ; + initStyle = SCE_ABAQUS_DEFAULT; + StyleContext sc(startPos, length, initStyle, styler); + + // Things are actually quite simple + // we have commentlines + // keywordlines and datalines + // On a data line there will only be colouring of numbers + // a keyword line is constructed as + // *word,[ paramname[=paramvalue]]* + // if the line ends with a , the keyword line continues onto the new line + + for (; sc.More(); sc.Forward()) { + switch ( state ) { + case KW_LINE_KW : + if ( sc.atLineEnd ) { + // finished the line in keyword state, switch to LINE_END + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } else if ( IsAKeywordChar(sc.ch) ) { + // nothing changes + state = KW_LINE_KW ; + } else if ( sc.ch == ',' ) { + // Well well we say a comma, arguments *MUST* follow + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = KW_LINE_COMMA ; + } else { + // Flag an error + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + // Done with processing + break ; + case KW_LINE_COMMA : + // acomma on a keywordline was seen + if ( IsAKeywordChar(sc.ch)) { + sc.SetState(SCE_ABAQUS_ARGUMENT) ; + state = KW_LINE_PAR ; + } else if ( sc.atLineEnd || (sc.ch == ',') ) { + // we remain in keyword mode + state = KW_LINE_COMMA ; + } else if ( sc.ch == ' ' ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = KW_LINE_COMMA ; + } else { + // Anything else constitutes an error + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case KW_LINE_PAR : + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } else if ( IsAKeywordChar(sc.ch) || (sc.ch == '-') ) { + // remain in this state + state = KW_LINE_PAR ; + } else if ( sc.ch == ',' ) { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = KW_LINE_COMMA ; + } else if ( sc.ch == '=' ) { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = KW_LINE_EQ ; + } else { + // Anything else constitutes an error + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case KW_LINE_EQ : + if ( sc.ch == ' ' ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + // remain in this state + state = KW_LINE_EQ ; + } else if ( IsADigit(sc.ch) || (sc.ch == '-') || (sc.ch == '.' && IsADigit(sc.chNext)) ) { + sc.SetState(SCE_ABAQUS_NUMBER) ; + state = KW_LINE_VAL ; + } else if ( IsAKeywordChar(sc.ch) ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = KW_LINE_VAL ; + } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) { + sc.SetState(SCE_ABAQUS_STRING) ; + state = KW_LINE_VAL ; + } else { + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case KW_LINE_VAL : + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } else if ( IsASetChar(sc.ch) && (sc.state == SCE_ABAQUS_DEFAULT) ) { + // nothing changes + state = KW_LINE_VAL ; + } else if (( (IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') || + ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) && + (sc.state == SCE_ABAQUS_NUMBER)) { + // remain in number mode + state = KW_LINE_VAL ; + } else if (sc.state == SCE_ABAQUS_STRING) { + // accept everything until a closing quote + if ( sc.ch == '\'' || sc.ch == '\"' ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = KW_LINE_VAL ; + } + } else if ( sc.ch == ',' ) { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = KW_LINE_COMMA ; + } else { + // anything else is an error + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case DAT_LINE_VAL : + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } else if ( IsASetChar(sc.ch) && (sc.state == SCE_ABAQUS_DEFAULT) ) { + // nothing changes + state = DAT_LINE_VAL ; + } else if (( (IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') || + ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) && + (sc.state == SCE_ABAQUS_NUMBER)) { + // remain in number mode + state = DAT_LINE_VAL ; + } else if (sc.state == SCE_ABAQUS_STRING) { + // accept everything until a closing quote + if ( sc.ch == '\'' || sc.ch == '\"' ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = DAT_LINE_VAL ; + } + } else if ( sc.ch == ',' ) { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = DAT_LINE_COMMA ; + } else { + // anything else is an error + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case DAT_LINE_COMMA : + // a comma on a data line was seen + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } else if ( sc.ch == ' ' ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = DAT_LINE_COMMA ; + } else if (sc.ch == ',') { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = DAT_LINE_COMMA ; + } else if ( IsADigit(sc.ch) || (sc.ch == '-')|| (sc.ch == '.' && IsADigit(sc.chNext)) ) { + sc.SetState(SCE_ABAQUS_NUMBER) ; + state = DAT_LINE_VAL ; + } else if ( IsAKeywordChar(sc.ch) ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = DAT_LINE_VAL ; + } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) { + sc.SetState(SCE_ABAQUS_STRING) ; + state = DAT_LINE_VAL ; + } else { + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + break ; + case COMMENT_LINE : + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } + break ; + case ST_ERROR : + if ( sc.atLineEnd ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = LINE_END ; + } + break ; + case LINE_END : + if ( sc.atLineEnd || sc.ch == ' ' ) { + // nothing changes + state = LINE_END ; + } else if ( sc.ch == '*' ) { + if ( sc.chNext == '*' ) { + state = COMMENT_LINE ; + sc.SetState(SCE_ABAQUS_COMMENT) ; + } else { + state = KW_LINE_KW ; + sc.SetState(SCE_ABAQUS_STARCOMMAND) ; + } + } else { + // it must be a data line, things are as if we are in DAT_LINE_COMMA + if ( sc.ch == ',' ) { + sc.SetState(SCE_ABAQUS_OPERATOR) ; + state = DAT_LINE_COMMA ; + } else if ( IsADigit(sc.ch) || (sc.ch == '-')|| (sc.ch == '.' && IsADigit(sc.chNext)) ) { + sc.SetState(SCE_ABAQUS_NUMBER) ; + state = DAT_LINE_VAL ; + } else if ( IsAKeywordChar(sc.ch) ) { + sc.SetState(SCE_ABAQUS_DEFAULT) ; + state = DAT_LINE_VAL ; + } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) { + sc.SetState(SCE_ABAQUS_STRING) ; + state = DAT_LINE_VAL ; + } else { + sc.SetState(SCE_ABAQUS_PROCESSOR) ; + state = ST_ERROR ; + } + } + break ; + } + } + sc.Complete(); +} + +//------------------------------------------------------------------------------ +// This copyied and modified from LexBasic.cxx +//------------------------------------------------------------------------------ + +/* Bits: + * 1 - whitespace + * 2 - operator + * 4 - identifier + * 8 - decimal digit + * 16 - hex digit + * 32 - bin digit + */ +static int character_classification[128] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 10, 6, + 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0 +}; + +static bool IsSpace(int c) { + return c < 128 && (character_classification[c] & 1); +} + +static bool IsIdentifier(int c) { + return c < 128 && (character_classification[c] & 4); +} + +static int LowerCase(int c) +{ + if (c >= 'A' && c <= 'Z') + return 'a' + c - 'A'; + return c; +} + +static int LineEnd(int line, Accessor &styler) +{ + const int docLines = styler.GetLine(styler.Length() - 1); // Available last line + int eol_pos ; + // if the line is the last line, the eol_pos is styler.Length() + // eol will contain a new line, or a virtual new line + if ( docLines == line ) + eol_pos = styler.Length() ; + else + eol_pos = styler.LineStart(line + 1) - 1; + return eol_pos ; +} + +static int LineStart(int line, Accessor &styler) +{ + return styler.LineStart(line) ; +} + +// LineType +// +// bits determines the line type +// 1 : data line +// 2 : only whitespace +// 3 : data line with only whitespace +// 4 : keyword line +// 5 : block open keyword line +// 6 : block close keyword line +// 7 : keyword line in error +// 8 : comment line +static int LineType(int line, Accessor &styler) { + int pos = LineStart(line, styler) ; + int eol_pos = LineEnd(line, styler) ; + + int c ; + char ch = ' '; + + int i = pos ; + while ( i < eol_pos ) { + c = styler.SafeGetCharAt(i); + ch = static_cast(LowerCase(c)); + // We can say something as soon as no whitespace + // was encountered + if ( !IsSpace(c) ) + break ; + i++ ; + } + + if ( i >= eol_pos ) { + // This is a whitespace line, currently + // classifies as data line + return 3 ; + } + + if ( ch != '*' ) { + // This is a data line + return 1 ; + } + + if ( i == eol_pos - 1 ) { + // Only a single *, error but make keyword line + return 4+3 ; + } + + // This means we can have a second character + // if that is also a * this means a comment + // otherwise it is a keyword. + c = styler.SafeGetCharAt(i+1); + ch = static_cast(LowerCase(c)); + if ( ch == '*' ) { + return 8 ; + } + + // At this point we know this is a keyword line + // the character at position i is a * + // it is not a comment line + char word[256] ; + int wlen = 0; + + word[wlen] = '*' ; + wlen++ ; + + i++ ; + while ( (i < eol_pos) && (wlen < 255) ) { + c = styler.SafeGetCharAt(i); + ch = static_cast(LowerCase(c)); + + if ( (!IsSpace(c)) && (!IsIdentifier(c)) ) + break ; + + if ( IsIdentifier(c) ) { + word[wlen] = ch ; + wlen++ ; + } + + i++ ; + } + + word[wlen] = 0 ; + + // Make a comparison + if ( !strcmp(word, "*step") || + !strcmp(word, "*part") || + !strcmp(word, "*instance") || + !strcmp(word, "*assembly")) { + return 4+1 ; + } + + if ( !strcmp(word, "*endstep") || + !strcmp(word, "*endpart") || + !strcmp(word, "*endinstance") || + !strcmp(word, "*endassembly")) { + return 4+2 ; + } + + return 4 ; +} + +static void SafeSetLevel(int line, int level, Accessor &styler) +{ + if ( line < 0 ) + return ; + + int mask = ((~SC_FOLDLEVELHEADERFLAG) | (~SC_FOLDLEVELWHITEFLAG)); + + if ( (level & mask) < 0 ) + return ; + + if ( styler.LevelAt(line) != level ) + styler.SetLevel(line, level) ; +} + +static void FoldABAQUSDoc(unsigned int startPos, int length, int, +WordList *[], Accessor &styler) { + int startLine = styler.GetLine(startPos) ; + int endLine = styler.GetLine(startPos+length-1) ; + + // bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + // We want to deal with all the cases + // To know the correct indentlevel, we need to look back to the + // previous command line indentation level + // order of formatting keyline datalines commentlines + int beginData = -1 ; + int beginComment = -1 ; + int prvKeyLine = startLine ; + int prvKeyLineTp = 0 ; + + // Scan until we find the previous keyword line + // this will give us the level reference that we need + while ( prvKeyLine > 0 ) { + prvKeyLine-- ; + prvKeyLineTp = LineType(prvKeyLine, styler) ; + if ( prvKeyLineTp & 4 ) + break ; + } + + // Determine the base line level of all lines following + // the previous keyword + // new keyword lines are placed on this level + //if ( prvKeyLineTp & 4 ) { + int level = styler.LevelAt(prvKeyLine) & ~SC_FOLDLEVELHEADERFLAG ; + //} + + // uncomment line below if weird behaviour continues + prvKeyLine = -1 ; + + // Now start scanning over the lines. + for ( int line = startLine; line <= endLine; line++ ) { + int lineType = LineType(line, styler) ; + + // Check for comment line + if ( lineType == 8 ) { + if ( beginComment < 0 ) { + beginComment = line ; + } + } + + // Check for data line + if ( (lineType == 1) || (lineType == 3) ) { + if ( beginData < 0 ) { + if ( beginComment >= 0 ) { + beginData = beginComment ; + } else { + beginData = line ; + } + } + beginComment = -1 ; + } + + // Check for keywordline. + // As soon as a keyword line is encountered, we can set the + // levels of everything from the previous keyword line to this one + if ( lineType & 4 ) { + // this is a keyword, we can now place the previous keyword + // all its data lines and the remainder + + // Write comments and data line + if ( beginComment < 0 ) { + beginComment = line ; + } + + if ( beginData < 0 ) { + beginData = beginComment ; + if ( prvKeyLineTp != 5 ) + SafeSetLevel(prvKeyLine, level, styler) ; + else + SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; + } else { + SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; + } + + int datLevel = level + 1 ; + if ( !(prvKeyLineTp & 4) ) { + datLevel = level ; + } + + for ( int ll = beginData; ll < beginComment; ll++ ) + SafeSetLevel(ll, datLevel, styler) ; + + // The keyword we just found is going to be written at another level + // if we have a type 5 and type 6 + if ( prvKeyLineTp == 5 ) { + level += 1 ; + } + + if ( prvKeyLineTp == 6 ) { + level -= 1 ; + if ( level < 0 ) { + level = 0 ; + } + } + + for ( int lll = beginComment; lll < line; lll++ ) + SafeSetLevel(lll, level, styler) ; + + // wrap and reset + beginComment = -1 ; + beginData = -1 ; + prvKeyLine = line ; + prvKeyLineTp = lineType ; + } + + } + + if ( beginComment < 0 ) { + beginComment = endLine + 1 ; + } else { + // We need to find out whether this comment block is followed by + // a data line or a keyword line + const int docLines = styler.GetLine(styler.Length() - 1); + + for ( int line = endLine + 1; line <= docLines; line++ ) { + int lineType = LineType(line, styler) ; + + if ( lineType != 8 ) { + if ( !(lineType & 4) ) { + beginComment = endLine + 1 ; + } + break ; + } + } + } + + if ( beginData < 0 ) { + beginData = beginComment ; + if ( prvKeyLineTp != 5 ) + SafeSetLevel(prvKeyLine, level, styler) ; + else + SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; + } else { + SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; + } + + int datLevel = level + 1 ; + if ( !(prvKeyLineTp & 4) ) { + datLevel = level ; + } + + for ( int ll = beginData; ll < beginComment; ll++ ) + SafeSetLevel(ll, datLevel, styler) ; + + if ( prvKeyLineTp == 5 ) { + level += 1 ; + } + + if ( prvKeyLineTp == 6 ) { + level -= 1 ; + } + for ( int m = beginComment; m <= endLine; m++ ) + SafeSetLevel(m, level, styler) ; +} + +static const char * const abaqusWordListDesc[] = { + "processors", + "commands", + "slashommands", + "starcommands", + "arguments", + "functions", + 0 +}; + +LexerModule lmAbaqus(SCLEX_ABAQUS, ColouriseABAQUSDoc, "abaqus", FoldABAQUSDoc, abaqusWordListDesc); diff --git a/lexers/LexAda.cxx b/lexers/LexAda.cxx new file mode 100644 index 000000000..654bfbeba --- /dev/null +++ b/lexers/LexAda.cxx @@ -0,0 +1,525 @@ +// Scintilla source code edit control +/** @file LexAda.cxx + ** Lexer for Ada 95 + **/ +// Copyright 2002 by Sergey Koshcheyev +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include + +#include + +#include "Platform.h" + +#include "Accessor.h" +#include "StyleContext.h" +#include "PropSet.h" +#include "KeyWords.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +/* + * Interface + */ + +static void ColouriseDocument( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler); + +static const char * const adaWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmAda(SCLEX_ADA, ColouriseDocument, "ada", NULL, adaWordListDesc); + +/* + * Implementation + */ + +// Functions that have apostropheStartsAttribute as a parameter set it according to whether +// an apostrophe encountered after processing the current token will start an attribute or +// a character literal. +static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL); +static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute); +static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute); + +static inline bool IsDelimiterCharacter(int ch); +static inline bool IsNumberStartCharacter(int ch); +static inline bool IsNumberCharacter(int ch); +static inline bool IsSeparatorOrDelimiterCharacter(int ch); +static bool IsValidIdentifier(const std::string& identifier); +static bool IsValidNumber(const std::string& number); +static inline bool IsWordStartCharacter(int ch); +static inline bool IsWordCharacter(int ch); + +static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = true; + + sc.SetState(SCE_ADA_CHARACTER); + + // Skip the apostrophe and one more character (so that '' is shown as non-terminated and ''' + // is handled correctly) + sc.Forward(); + sc.Forward(); + + ColouriseContext(sc, '\'', SCE_ADA_CHARACTEREOL); +} + +static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL) { + while (!sc.atLineEnd && !sc.Match(chEnd)) { + sc.Forward(); + } + + if (!sc.atLineEnd) { + sc.ForwardSetState(SCE_ADA_DEFAULT); + } else { + sc.ChangeState(stateEOL); + } +} + +static void ColouriseComment(StyleContext& sc, bool& /*apostropheStartsAttribute*/) { + // Apostrophe meaning is not changed, but the parameter is present for uniformity + + sc.SetState(SCE_ADA_COMMENTLINE); + + while (!sc.atLineEnd) { + sc.Forward(); + } +} + +static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = sc.Match (')'); + sc.SetState(SCE_ADA_DELIMITER); + sc.ForwardSetState(SCE_ADA_DEFAULT); +} + +static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = false; + + sc.SetState(SCE_ADA_LABEL); + + // Skip "<<" + sc.Forward(); + sc.Forward(); + + std::string identifier; + + while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) { + identifier += static_cast(tolower(sc.ch)); + sc.Forward(); + } + + // Skip ">>" + if (sc.Match('>', '>')) { + sc.Forward(); + sc.Forward(); + } else { + sc.ChangeState(SCE_ADA_ILLEGAL); + } + + // If the name is an invalid identifier or a keyword, then make it invalid label + if (!IsValidIdentifier(identifier) || keywords.InList(identifier.c_str())) { + sc.ChangeState(SCE_ADA_ILLEGAL); + } + + sc.SetState(SCE_ADA_DEFAULT); + +} + +static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = true; + + std::string number; + sc.SetState(SCE_ADA_NUMBER); + + // Get all characters up to a delimiter or a separator, including points, but excluding + // double points (ranges). + while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) { + number += static_cast(sc.ch); + sc.Forward(); + } + + // Special case: exponent with sign + if ((sc.chPrev == 'e' || sc.chPrev == 'E') && + (sc.ch == '+' || sc.ch == '-')) { + number += static_cast(sc.ch); + sc.Forward (); + + while (!IsSeparatorOrDelimiterCharacter(sc.ch)) { + number += static_cast(sc.ch); + sc.Forward(); + } + } + + if (!IsValidNumber(number)) { + sc.ChangeState(SCE_ADA_ILLEGAL); + } + + sc.SetState(SCE_ADA_DEFAULT); +} + +static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = true; + + sc.SetState(SCE_ADA_STRING); + sc.Forward(); + + ColouriseContext(sc, '"', SCE_ADA_STRINGEOL); +} + +static void ColouriseWhiteSpace(StyleContext& sc, bool& /*apostropheStartsAttribute*/) { + // Apostrophe meaning is not changed, but the parameter is present for uniformity + sc.SetState(SCE_ADA_DEFAULT); + sc.ForwardSetState(SCE_ADA_DEFAULT); +} + +static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = true; + sc.SetState(SCE_ADA_IDENTIFIER); + + std::string word; + + while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) { + word += static_cast(tolower(sc.ch)); + sc.Forward(); + } + + if (!IsValidIdentifier(word)) { + sc.ChangeState(SCE_ADA_ILLEGAL); + + } else if (keywords.InList(word.c_str())) { + sc.ChangeState(SCE_ADA_WORD); + + if (word != "all") { + apostropheStartsAttribute = false; + } + } + + sc.SetState(SCE_ADA_DEFAULT); +} + +// +// ColouriseDocument +// + +static void ColouriseDocument( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + WordList &keywords = *keywordlists[0]; + + StyleContext sc(startPos, length, initStyle, styler); + + int lineCurrent = styler.GetLine(startPos); + bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0; + + while (sc.More()) { + if (sc.atLineEnd) { + // Go to the next line + sc.Forward(); + lineCurrent++; + + // Remember the line state for future incremental lexing + styler.SetLineState(lineCurrent, apostropheStartsAttribute); + + // Don't continue any styles on the next line + sc.SetState(SCE_ADA_DEFAULT); + } + + // Comments + if (sc.Match('-', '-')) { + ColouriseComment(sc, apostropheStartsAttribute); + + // Strings + } else if (sc.Match('"')) { + ColouriseString(sc, apostropheStartsAttribute); + + // Characters + } else if (sc.Match('\'') && !apostropheStartsAttribute) { + ColouriseCharacter(sc, apostropheStartsAttribute); + + // Labels + } else if (sc.Match('<', '<')) { + ColouriseLabel(sc, keywords, apostropheStartsAttribute); + + // Whitespace + } else if (IsASpace(sc.ch)) { + ColouriseWhiteSpace(sc, apostropheStartsAttribute); + + // Delimiters + } else if (IsDelimiterCharacter(sc.ch)) { + ColouriseDelimiter(sc, apostropheStartsAttribute); + + // Numbers + } else if (IsADigit(sc.ch) || sc.ch == '#') { + ColouriseNumber(sc, apostropheStartsAttribute); + + // Keywords or identifiers + } else { + ColouriseWord(sc, keywords, apostropheStartsAttribute); + } + } + + sc.Complete(); +} + +static inline bool IsDelimiterCharacter(int ch) { + switch (ch) { + case '&': + case '\'': + case '(': + case ')': + case '*': + case '+': + case ',': + case '-': + case '.': + case '/': + case ':': + case ';': + case '<': + case '=': + case '>': + case '|': + return true; + default: + return false; + } +} + +static inline bool IsNumberCharacter(int ch) { + return IsNumberStartCharacter(ch) || + ch == '_' || + ch == '.' || + ch == '#' || + (ch >= 'a' && ch <= 'f') || + (ch >= 'A' && ch <= 'F'); +} + +static inline bool IsNumberStartCharacter(int ch) { + return IsADigit(ch); +} + +static inline bool IsSeparatorOrDelimiterCharacter(int ch) { + return IsASpace(ch) || IsDelimiterCharacter(ch); +} + +static bool IsValidIdentifier(const std::string& identifier) { + // First character can't be '_', so initialize the flag to true + bool lastWasUnderscore = true; + + size_t length = identifier.length(); + + // Zero-length identifiers are not valid (these can occur inside labels) + if (length == 0) { + return false; + } + + // Check for valid character at the start + if (!IsWordStartCharacter(identifier[0])) { + return false; + } + + // Check for only valid characters and no double underscores + for (size_t i = 0; i < length; i++) { + if (!IsWordCharacter(identifier[i]) || + (identifier[i] == '_' && lastWasUnderscore)) { + return false; + } + lastWasUnderscore = identifier[i] == '_'; + } + + // Check for underscore at the end + if (lastWasUnderscore == true) { + return false; + } + + // All checks passed + return true; +} + +static bool IsValidNumber(const std::string& number) { + size_t hashPos = number.find("#"); + bool seenDot = false; + + size_t i = 0; + size_t length = number.length(); + + if (length == 0) + return false; // Just in case + + // Decimal number + if (hashPos == std::string::npos) { + bool canBeSpecial = false; + + for (; i < length; i++) { + if (number[i] == '_') { + if (!canBeSpecial) { + return false; + } + canBeSpecial = false; + } else if (number[i] == '.') { + if (!canBeSpecial || seenDot) { + return false; + } + canBeSpecial = false; + seenDot = true; + } else if (IsADigit(number[i])) { + canBeSpecial = true; + } else { + break; + } + } + + if (!canBeSpecial) + return false; + } else { + // Based number + bool canBeSpecial = false; + int base = 0; + + // Parse base + for (; i < length; i++) { + int ch = number[i]; + if (ch == '_') { + if (!canBeSpecial) + return false; + canBeSpecial = false; + } else if (IsADigit(ch)) { + base = base * 10 + (ch - '0'); + if (base > 16) + return false; + canBeSpecial = true; + } else if (ch == '#' && canBeSpecial) { + break; + } else { + return false; + } + } + + if (base < 2) + return false; + if (i == length) + return false; + + i++; // Skip over '#' + + // Parse number + canBeSpecial = false; + + for (; i < length; i++) { + int ch = tolower(number[i]); + + if (ch == '_') { + if (!canBeSpecial) { + return false; + } + canBeSpecial = false; + + } else if (ch == '.') { + if (!canBeSpecial || seenDot) { + return false; + } + canBeSpecial = false; + seenDot = true; + + } else if (IsADigit(ch)) { + if (ch - '0' >= base) { + return false; + } + canBeSpecial = true; + + } else if (ch >= 'a' && ch <= 'f') { + if (ch - 'a' + 10 >= base) { + return false; + } + canBeSpecial = true; + + } else if (ch == '#' && canBeSpecial) { + break; + + } else { + return false; + } + } + + if (i == length) { + return false; + } + + i++; + } + + // Exponent (optional) + if (i < length) { + if (number[i] != 'e' && number[i] != 'E') + return false; + + i++; // Move past 'E' + + if (i == length) { + return false; + } + + if (number[i] == '+') + i++; + else if (number[i] == '-') { + if (seenDot) { + i++; + } else { + return false; // Integer literals should not have negative exponents + } + } + + if (i == length) { + return false; + } + + bool canBeSpecial = false; + + for (; i < length; i++) { + if (number[i] == '_') { + if (!canBeSpecial) { + return false; + } + canBeSpecial = false; + } else if (IsADigit(number[i])) { + canBeSpecial = true; + } else { + return false; + } + } + + if (!canBeSpecial) + return false; + } + + // if i == length, number was parsed successfully. + return i == length; +} + +static inline bool IsWordCharacter(int ch) { + return IsWordStartCharacter(ch) || IsADigit(ch); +} + +static inline bool IsWordStartCharacter(int ch) { + return (isascii(ch) && isalpha(ch)) || ch == '_'; +} diff --git a/lexers/LexAsm.cxx b/lexers/LexAsm.cxx new file mode 100644 index 000000000..17c938420 --- /dev/null +++ b/lexers/LexAsm.cxx @@ -0,0 +1,180 @@ +// Scintilla source code edit control +/** @file LexAsm.cxx + ** Lexer for Assembler, just for the MASM syntax + ** Written by The Black Horus + ** Enhancements and NASM stuff by Kein-Hong Man, 2003-10 + ** SCE_ASM_COMMENTBLOCK and SCE_ASM_CHARACTER are for future GNU as colouring + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || + ch == '_' || ch == '?'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' || + ch == '%' || ch == '@' || ch == '$' || ch == '?'); +} + +static inline bool IsAsmOperator(const int ch) { + if ((ch < 0x80) && (isalnum(ch))) + return false; + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || ch == '^' || + ch == '[' || ch == ']' || ch == '<' || ch == '&' || + ch == '>' || ch == ',' || ch == '|' || ch == '~' || + ch == '%' || ch == ':') + return true; + return false; +} + +static void ColouriseAsmDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &cpuInstruction = *keywordlists[0]; + WordList &mathInstruction = *keywordlists[1]; + WordList ®isters = *keywordlists[2]; + WordList &directive = *keywordlists[3]; + WordList &directiveOperand = *keywordlists[4]; + WordList &extInstruction = *keywordlists[5]; + + // Do not leak onto next line + if (initStyle == SCE_ASM_STRINGEOL) + initStyle = SCE_ASM_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) + { + + // Prevent SCE_ASM_STRINGEOL from leaking back to previous line + if (sc.atLineStart && (sc.state == SCE_ASM_STRING)) { + sc.SetState(SCE_ASM_STRING); + } else if (sc.atLineStart && (sc.state == SCE_ASM_CHARACTER)) { + sc.SetState(SCE_ASM_CHARACTER); + } + + // Handle line continuation generically. + if (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_ASM_OPERATOR) { + if (!IsAsmOperator(sc.ch)) { + sc.SetState(SCE_ASM_DEFAULT); + } + }else if (sc.state == SCE_ASM_NUMBER) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_IDENTIFIER) { + if (!IsAWordChar(sc.ch) ) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + + if (cpuInstruction.InList(s)) { + sc.ChangeState(SCE_ASM_CPUINSTRUCTION); + } else if (mathInstruction.InList(s)) { + sc.ChangeState(SCE_ASM_MATHINSTRUCTION); + } else if (registers.InList(s)) { + sc.ChangeState(SCE_ASM_REGISTER); + } else if (directive.InList(s)) { + sc.ChangeState(SCE_ASM_DIRECTIVE); + } else if (directiveOperand.InList(s)) { + sc.ChangeState(SCE_ASM_DIRECTIVEOPERAND); + } else if (extInstruction.InList(s)) { + sc.ChangeState(SCE_ASM_EXTINSTRUCTION); + } + sc.SetState(SCE_ASM_DEFAULT); + } + } + else if (sc.state == SCE_ASM_COMMENT ) { + if (sc.atLineEnd) { + sc.SetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_STRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_ASM_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_ASM_STRINGEOL); + sc.ForwardSetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_CHARACTER) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_ASM_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_ASM_STRINGEOL); + sc.ForwardSetState(SCE_ASM_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_ASM_DEFAULT) { + if (sc.ch == ';'){ + sc.SetState(SCE_ASM_COMMENT); + } else if (isascii(sc.ch) && (isdigit(sc.ch) || (sc.ch == '.' && isascii(sc.chNext) && isdigit(sc.chNext)))) { + sc.SetState(SCE_ASM_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_ASM_IDENTIFIER); + } else if (sc.ch == '\"') { + sc.SetState(SCE_ASM_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_ASM_CHARACTER); + } else if (IsAsmOperator(sc.ch)) { + sc.SetState(SCE_ASM_OPERATOR); + } + } + + } + sc.Complete(); +} + +static const char * const asmWordListDesc[] = { + "CPU instructions", + "FPU instructions", + "Registers", + "Directives", + "Directive operands", + "Extended instructions", + 0 +}; + +LexerModule lmAsm(SCLEX_ASM, ColouriseAsmDoc, "asm", 0, asmWordListDesc); + diff --git a/lexers/LexAsn1.cxx b/lexers/LexAsn1.cxx new file mode 100644 index 000000000..36f1d5dc2 --- /dev/null +++ b/lexers/LexAsn1.cxx @@ -0,0 +1,185 @@ +// Scintilla source code edit control +/** @file LexAsn1.cxx + ** Lexer for ASN.1 + **/ +// Copyright 2004 by Herr Pfarrer rpfarrer yahoo de +// Last Updated: 20/07/2004 +// The License.txt file describes the conditions under which this software may be distributed. +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// Some char test functions +static bool isAsn1Number(int ch) +{ + return (ch >= '0' && ch <= '9'); +} + +static bool isAsn1Letter(int ch) +{ + return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); +} + +static bool isAsn1Char(int ch) +{ + return (ch == '-' ) || isAsn1Number(ch) || isAsn1Letter (ch); +} + +// +// Function determining the color of a given code portion +// Based on a "state" +// +static void ColouriseAsn1Doc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[], Accessor &styler) +{ + // The keywords + WordList &Keywords = *keywordLists[0]; + WordList &Attributes = *keywordLists[1]; + WordList &Descriptors = *keywordLists[2]; + WordList &Types = *keywordLists[3]; + + // Parse the whole buffer character by character using StyleContext + StyleContext sc(startPos, length, initStyle, styler); + for (; sc.More(); sc.Forward()) + { + // The state engine + switch (sc.state) + { + case SCE_ASN1_DEFAULT: // Plain characters +asn1_default: + if (sc.ch == '-' && sc.chNext == '-') + // A comment begins here + sc.SetState(SCE_ASN1_COMMENT); + else if (sc.ch == '"') + // A string begins here + sc.SetState(SCE_ASN1_STRING); + else if (isAsn1Number (sc.ch)) + // A number starts here (identifier should start with a letter in ASN.1) + sc.SetState(SCE_ASN1_SCALAR); + else if (isAsn1Char (sc.ch)) + // An identifier starts here (identifier always start with a letter) + sc.SetState(SCE_ASN1_IDENTIFIER); + else if (sc.ch == ':') + // A ::= operator starts here + sc.SetState(SCE_ASN1_OPERATOR); + break; + case SCE_ASN1_COMMENT: // A comment + if (sc.ch == '\r' || sc.ch == '\n') + // A comment ends here + sc.SetState(SCE_ASN1_DEFAULT); + break; + case SCE_ASN1_IDENTIFIER: // An identifier (keyword, attribute, descriptor or type) + if (!isAsn1Char (sc.ch)) + { + // The end of identifier is here: we can look for it in lists by now and change its state + char s[100]; + sc.GetCurrent(s, sizeof(s)); + if (Keywords.InList(s)) + // It's a keyword, change its state + sc.ChangeState(SCE_ASN1_KEYWORD); + else if (Attributes.InList(s)) + // It's an attribute, change its state + sc.ChangeState(SCE_ASN1_ATTRIBUTE); + else if (Descriptors.InList(s)) + // It's a descriptor, change its state + sc.ChangeState(SCE_ASN1_DESCRIPTOR); + else if (Types.InList(s)) + // It's a type, change its state + sc.ChangeState(SCE_ASN1_TYPE); + + // Set to default now + sc.SetState(SCE_ASN1_DEFAULT); + } + break; + case SCE_ASN1_STRING: // A string delimited by "" + if (sc.ch == '"') + { + // A string ends here + sc.ForwardSetState(SCE_ASN1_DEFAULT); + + // To correctly manage a char sticking to the string quote + goto asn1_default; + } + break; + case SCE_ASN1_SCALAR: // A plain number + if (!isAsn1Number (sc.ch)) + // A number ends here + sc.SetState(SCE_ASN1_DEFAULT); + break; + case SCE_ASN1_OPERATOR: // The affectation operator ::= and wath follows (eg: ::= { org 6 } OID or ::= 12 trap) + if (sc.ch == '{') + { + // An OID definition starts here: enter the sub loop + for (; sc.More(); sc.Forward()) + { + if (isAsn1Number (sc.ch) && (!isAsn1Char (sc.chPrev) || isAsn1Number (sc.chPrev))) + // The OID number is highlighted + sc.SetState(SCE_ASN1_OID); + else if (isAsn1Char (sc.ch)) + // The OID parent identifier is plain + sc.SetState(SCE_ASN1_IDENTIFIER); + else + sc.SetState(SCE_ASN1_DEFAULT); + + if (sc.ch == '}') + // Here ends the OID and the operator sub loop: go back to main loop + break; + } + } + else if (isAsn1Number (sc.ch)) + { + // A trap number definition starts here: enter the sub loop + for (; sc.More(); sc.Forward()) + { + if (isAsn1Number (sc.ch)) + // The trap number is highlighted + sc.SetState(SCE_ASN1_OID); + else + { + // The number ends here: go back to main loop + sc.SetState(SCE_ASN1_DEFAULT); + break; + } + } + } + else if (sc.ch != ':' && sc.ch != '=' && sc.ch != ' ') + // The operator doesn't imply an OID definition nor a trap, back to main loop + goto asn1_default; // To be sure to handle actually the state change + break; + } + } + sc.Complete(); +} + +static void FoldAsn1Doc(unsigned int, int, int, WordList *[], Accessor &styler) +{ + // No folding enabled, no reason to continue... + if( styler.GetPropertyInt("fold") == 0 ) + return; + + // No folding implemented: doesn't make sense for ASN.1 +} + +static const char * const asn1WordLists[] = { + "Keywords", + "Attributes", + "Descriptors", + "Types", + 0, }; + + +LexerModule lmAns1(SCLEX_ASN1, ColouriseAsn1Doc, "asn1", FoldAsn1Doc, asn1WordLists); diff --git a/lexers/LexBaan.cxx b/lexers/LexBaan.cxx new file mode 100644 index 000000000..a6847db71 --- /dev/null +++ b/lexers/LexBaan.cxx @@ -0,0 +1,193 @@ +// Scintilla source code edit control +/** @file LexBaan.cxx + ** Lexer for Baan. + ** Based heavily on LexCPP.cxx + **/ +// Copyright 2001- by Vamsi Potluru & Praveen Ambekar +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '$' || ch == ':'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static void ColouriseBaanDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; + + if (initStyle == SCE_BAAN_STRINGEOL) // Does not leak onto next line + initStyle = SCE_BAAN_DEFAULT; + + int visibleChars = 0; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.state == SCE_BAAN_OPERATOR) { + sc.SetState(SCE_BAAN_DEFAULT); + } else if (sc.state == SCE_BAAN_NUMBER) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_BAAN_DEFAULT); + } + } else if (sc.state == SCE_BAAN_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_BAAN_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_BAAN_WORD2); + } + sc.SetState(SCE_BAAN_DEFAULT); + } + } else if (sc.state == SCE_BAAN_PREPROCESSOR) { + if (stylingWithinPreprocessor) { + if (IsASpace(sc.ch)) { + sc.SetState(SCE_BAAN_DEFAULT); + } + } else { + if (sc.atLineEnd && (sc.chNext != '^')) { + sc.SetState(SCE_BAAN_DEFAULT); + } + } + } else if (sc.state == SCE_BAAN_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_BAAN_DEFAULT); + } + } else if (sc.state == SCE_BAAN_COMMENTDOC) { + if (sc.MatchIgnoreCase("enddllusage")) { + for (unsigned int i = 0; i < 10; i++){ + sc.Forward(); + } + sc.ForwardSetState(SCE_BAAN_DEFAULT); + } + } else if (sc.state == SCE_BAAN_STRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_BAAN_DEFAULT); + } else if ((sc.atLineEnd) && (sc.chNext != '^')) { + sc.ChangeState(SCE_BAAN_STRINGEOL); + sc.ForwardSetState(SCE_C_DEFAULT); + visibleChars = 0; + } + } + + if (sc.state == SCE_BAAN_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_BAAN_NUMBER); + } else if (sc.MatchIgnoreCase("dllusage")){ + sc.SetState(SCE_BAAN_COMMENTDOC); + do { + sc.Forward(); + } while ((!sc.atLineEnd) && sc.More()); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_BAAN_IDENTIFIER); + } else if (sc.Match('|')){ + sc.SetState(SCE_BAAN_COMMENT); + } else if (sc.ch == '\"') { + sc.SetState(SCE_BAAN_STRING); + } else if (sc.ch == '#' && visibleChars == 0) { + // Preprocessor commands are alone on their line + sc.SetState(SCE_BAAN_PREPROCESSOR); + // Skip whitespace between # and preprocessor word + do { + sc.Forward(); + } while (IsASpace(sc.ch) && sc.More()); + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_BAAN_OPERATOR); + } + } + if (sc.atLineEnd) { + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + } + if (!IsASpace(sc.ch)) { + visibleChars++; + } + } + sc.Complete(); +} + +static void FoldBaanDoc(unsigned int startPos, int length, int initStyle, WordList *[], + Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && + (style == SCE_BAAN_COMMENT || style == SCE_BAAN_COMMENTDOC)) { + if (style != stylePrev) { + levelCurrent++; + } else if ((style != styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + if (style == SCE_BAAN_OPERATOR) { + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +LexerModule lmBaan(SCLEX_BAAN, ColouriseBaanDoc, "baan", FoldBaanDoc); diff --git a/lexers/LexBash.cxx b/lexers/LexBash.cxx new file mode 100644 index 000000000..1f97e4829 --- /dev/null +++ b/lexers/LexBash.cxx @@ -0,0 +1,521 @@ +// Scintilla source code edit control +/** @file LexBash.cxx + ** Lexer for Bash. + **/ +// Copyright 2004-2008 by Neil Hodgson +// Adapted from LexPerl by Kein-Hong Man 2004 +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "CharacterSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#define HERE_DELIM_MAX 256 + +// define this if you want 'invalid octals' to be marked as errors +// usually, this is not a good idea, permissive lexing is better +#undef PEDANTIC_OCTAL + +#define BASH_BASE_ERROR 65 +#define BASH_BASE_DECIMAL 66 +#define BASH_BASE_HEX 67 +#ifdef PEDANTIC_OCTAL +#define BASH_BASE_OCTAL 68 +#define BASH_BASE_OCTAL_ERROR 69 +#endif + +static inline int translateBashDigit(int ch) { + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } else if (ch >= 'a' && ch <= 'z') { + return ch - 'a' + 10; + } else if (ch >= 'A' && ch <= 'Z') { + return ch - 'A' + 36; + } else if (ch == '@') { + return 62; + } else if (ch == '_') { + return 63; + } + return BASH_BASE_ERROR; +} + +static inline int getBashNumberBase(char *s) { + int i = 0; + int base = 0; + while (*s) { + base = base * 10 + (*s++ - '0'); + i++; + } + if (base > 64 || i > 2) { + return BASH_BASE_ERROR; + } + return base; +} + +static int opposite(int ch) { + if (ch == '(') return ')'; + if (ch == '[') return ']'; + if (ch == '{') return '}'; + if (ch == '<') return '>'; + return ch; +} + +static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + + CharacterSet setWordStart(CharacterSet::setAlpha, "_"); + // note that [+-] are often parts of identifiers in shell scripts + CharacterSet setWord(CharacterSet::setAlphaNum, "._+-"); + CharacterSet setBashOperator(CharacterSet::setNone, "^&\\%()-+=|{}[]:;>,*/(ch); + Delimiter[DelimiterLength] = '\0'; + } + ~HereDocCls() { + delete []Delimiter; + } + }; + HereDocCls HereDoc; + + class QuoteCls { // Class to manage quote pairs (simplified vs LexPerl) + public: + int Count; + int Up, Down; + QuoteCls() { + Count = 0; + Up = '\0'; + Down = '\0'; + } + void Open(int u) { + Count++; + Up = u; + Down = opposite(Up); + } + void Start(int u) { + Count = 0; + Open(u); + } + }; + QuoteCls Quote; + + int numBase = 0; + int digit; + unsigned int endPos = startPos + length; + + // Backtrack to beginning of style if required... + // If in a long distance lexical state, backtrack to find quote characters + if (initStyle == SCE_SH_HERE_Q) { + while ((startPos > 1) && (styler.StyleAt(startPos) != SCE_SH_HERE_DELIM)) { + startPos--; + } + startPos = styler.LineStart(styler.GetLine(startPos)); + initStyle = styler.StyleAt(startPos - 1); + } + // Bash strings can be multi-line with embedded newlines, so backtrack. + // Bash numbers have additional state during lexing, so backtrack too. + if (initStyle == SCE_SH_STRING + || initStyle == SCE_SH_BACKTICKS + || initStyle == SCE_SH_CHARACTER + || initStyle == SCE_SH_NUMBER + || initStyle == SCE_SH_IDENTIFIER + || initStyle == SCE_SH_COMMENTLINE) { + while ((startPos > 1) && (styler.StyleAt(startPos - 1) == initStyle)) { + startPos--; + } + initStyle = SCE_SH_DEFAULT; + } + + StyleContext sc(startPos, endPos - startPos, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_SH_OPERATOR: + sc.SetState(SCE_SH_DEFAULT); + break; + case SCE_SH_WORD: + // "." never used in Bash variable names but used in file names + if (!setWord.Contains(sc.ch)) { + char s[1000]; + sc.GetCurrent(s, sizeof(s)); + if (s[0] != '-' && // for file operators + !keywords.InList(s)) { + sc.ChangeState(SCE_SH_IDENTIFIER); + } + sc.SetState(SCE_SH_DEFAULT); + } + break; + case SCE_SH_IDENTIFIER: + if (sc.chPrev == '\\') { // for escaped chars + sc.ForwardSetState(SCE_SH_DEFAULT); + } else if (!setWord.Contains(sc.ch)) { + sc.SetState(SCE_SH_DEFAULT); + } + break; + case SCE_SH_NUMBER: + digit = translateBashDigit(sc.ch); + if (numBase == BASH_BASE_DECIMAL) { + if (sc.ch == '#') { + char s[10]; + sc.GetCurrent(s, sizeof(s)); + numBase = getBashNumberBase(s); + if (numBase != BASH_BASE_ERROR) + break; + } else if (IsADigit(sc.ch)) + break; + } else if (numBase == BASH_BASE_HEX) { + if (IsADigit(sc.ch, 16)) + break; +#ifdef PEDANTIC_OCTAL + } else if (numBase == BASH_BASE_OCTAL || + numBase == BASH_BASE_OCTAL_ERROR) { + if (digit <= 7) + break; + if (digit <= 9) { + numBase = BASH_BASE_OCTAL_ERROR; + break; + } +#endif + } else if (numBase == BASH_BASE_ERROR) { + if (digit <= 9) + break; + } else { // DD#DDDD number style handling + if (digit != BASH_BASE_ERROR) { + if (numBase <= 36) { + // case-insensitive if base<=36 + if (digit >= 36) digit -= 26; + } + if (digit < numBase) + break; + if (digit <= 9) { + numBase = BASH_BASE_ERROR; + break; + } + } + } + // fallthrough when number is at an end or error + if (numBase == BASH_BASE_ERROR +#ifdef PEDANTIC_OCTAL + || numBase == BASH_BASE_OCTAL_ERROR +#endif + ) { + sc.ChangeState(SCE_SH_ERROR); + } + sc.SetState(SCE_SH_DEFAULT); + break; + case SCE_SH_COMMENTLINE: + if (sc.atLineEnd && sc.chPrev != '\\') { + sc.SetState(SCE_SH_DEFAULT); + } + break; + case SCE_SH_HERE_DELIM: + // From Bash info: + // --------------- + // Specifier format is: <<[-]WORD + // Optional '-' is for removal of leading tabs from here-doc. + // Whitespace acceptable after <<[-] operator + // + if (HereDoc.State == 0) { // '<<' encountered + HereDoc.Quote = sc.chNext; + HereDoc.Quoted = false; + HereDoc.DelimiterLength = 0; + HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; + if (sc.chNext == '\'' || sc.chNext == '\"') { // a quoted here-doc delimiter (' or ") + sc.Forward(); + HereDoc.Quoted = true; + HereDoc.State = 1; + } else if (!HereDoc.Indent && sc.chNext == '-') { // <<- indent case + HereDoc.Indent = true; + } else if (setHereDoc.Contains(sc.chNext)) { + // an unquoted here-doc delimiter, no special handling + // TODO check what exactly bash considers part of the delim + HereDoc.State = 1; + } else if (sc.chNext == '<') { // HERE string <<< + sc.Forward(); + sc.ForwardSetState(SCE_SH_DEFAULT); + } else if (IsASpace(sc.chNext)) { + // eat whitespace + } else if (setLeftShift.Contains(sc.chNext)) { + // left shift << or <<= operator cases + sc.ChangeState(SCE_SH_OPERATOR); + sc.ForwardSetState(SCE_SH_DEFAULT); + } else { + // symbols terminates; deprecated zero-length delimiter + HereDoc.State = 1; + } + } else if (HereDoc.State == 1) { // collect the delimiter + if (setHereDoc2.Contains(sc.ch) || sc.chPrev == '\\') { + HereDoc.Append(sc.ch); + } else if (HereDoc.Quoted && sc.ch == HereDoc.Quote) { // closing quote => end of delimiter + sc.ForwardSetState(SCE_SH_DEFAULT); + } else if (sc.ch == '\\') { + // skip escape prefix + } else { + sc.SetState(SCE_SH_DEFAULT); + } + if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) { // force blowup + sc.SetState(SCE_SH_ERROR); + HereDoc.State = 0; + } + } + break; + case SCE_SH_HERE_Q: + // HereDoc.State == 2 + if (sc.atLineStart) { + sc.SetState(SCE_SH_HERE_Q); + int prefixws = 0; + while (IsASpace(sc.ch) && !sc.atLineEnd) { // whitespace prefix + sc.Forward(); + prefixws++; + } + if (prefixws > 0) + sc.SetState(SCE_SH_HERE_Q); + while (!sc.atLineEnd) { + sc.Forward(); + } + char s[HERE_DELIM_MAX]; + sc.GetCurrent(s, sizeof(s)); + if (sc.LengthCurrent() == 0) + break; + if (s[strlen(s) - 1] == '\r') + s[strlen(s) - 1] = '\0'; + if (strcmp(HereDoc.Delimiter, s) == 0) { + if ((prefixws > 0 && HereDoc.Indent) || // indentation rule + (prefixws == 0 && !HereDoc.Indent)) { + sc.SetState(SCE_SH_DEFAULT); + break; + } + } + } + break; + case SCE_SH_SCALAR: // variable names + if (!setParam.Contains(sc.ch)) { + if (sc.LengthCurrent() == 1) { + // Special variable: $(, $_ etc. + sc.ForwardSetState(SCE_SH_DEFAULT); + } else { + sc.SetState(SCE_SH_DEFAULT); + } + } + break; + case SCE_SH_STRING: // delimited styles + case SCE_SH_CHARACTER: + case SCE_SH_BACKTICKS: + case SCE_SH_PARAM: + if (sc.ch == '\\' && Quote.Up != '\\') { + sc.Forward(); + } else if (sc.ch == Quote.Down) { + Quote.Count--; + if (Quote.Count == 0) { + sc.ForwardSetState(SCE_SH_DEFAULT); + } + } else if (sc.ch == Quote.Up) { + Quote.Count++; + } + break; + } + + // Must check end of HereDoc state 1 before default state is handled + if (HereDoc.State == 1 && sc.atLineEnd) { + // Begin of here-doc (the line after the here-doc delimiter): + // Lexically, the here-doc starts from the next line after the >>, but the + // first line of here-doc seem to follow the style of the last EOL sequence + HereDoc.State = 2; + if (HereDoc.Quoted) { + if (sc.state == SCE_SH_HERE_DELIM) { + // Missing quote at end of string! We are stricter than bash. + // Colour here-doc anyway while marking this bit as an error. + sc.ChangeState(SCE_SH_ERROR); + } + // HereDoc.Quote always == '\'' + } + sc.SetState(SCE_SH_HERE_Q); + } + + // Determine if a new state should be entered. + if (sc.state == SCE_SH_DEFAULT) { + if (sc.ch == '\\') { // escaped character + sc.SetState(SCE_SH_IDENTIFIER); + } else if (IsADigit(sc.ch)) { + sc.SetState(SCE_SH_NUMBER); + numBase = BASH_BASE_DECIMAL; + if (sc.ch == '0') { // hex,octal + if (sc.chNext == 'x' || sc.chNext == 'X') { + numBase = BASH_BASE_HEX; + sc.Forward(); + } else if (IsADigit(sc.chNext)) { +#ifdef PEDANTIC_OCTAL + numBase = BASH_BASE_OCTAL; +#else + numBase = BASH_BASE_HEX; +#endif + } + } + } else if (setWordStart.Contains(sc.ch)) { + sc.SetState(SCE_SH_WORD); + } else if (sc.ch == '#') { + sc.SetState(SCE_SH_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_SH_STRING); + Quote.Start(sc.ch); + } else if (sc.ch == '\'') { + sc.SetState(SCE_SH_CHARACTER); + Quote.Start(sc.ch); + } else if (sc.ch == '`') { + sc.SetState(SCE_SH_BACKTICKS); + Quote.Start(sc.ch); + } else if (sc.ch == '$') { + sc.SetState(SCE_SH_SCALAR); + sc.Forward(); + if (sc.ch == '{') { + sc.ChangeState(SCE_SH_PARAM); + } else if (sc.ch == '\'') { + sc.ChangeState(SCE_SH_CHARACTER); + } else if (sc.ch == '"') { + sc.ChangeState(SCE_SH_STRING); + } else if (sc.ch == '(' || sc.ch == '`') { + sc.ChangeState(SCE_SH_BACKTICKS); + if (sc.chNext == '(') { // $(( is lexed as operator + sc.ChangeState(SCE_SH_OPERATOR); + } + } else { + continue; // scalar has no delimiter pair + } + // fallthrough, open delim for $[{'"(`] + Quote.Start(sc.ch); + } else if (sc.Match('<', '<')) { + sc.SetState(SCE_SH_HERE_DELIM); + HereDoc.State = 0; + HereDoc.Indent = false; + } else if (sc.ch == '-' && // one-char file test operators + setSingleCharOp.Contains(sc.chNext) && + !setWord.Contains(sc.GetRelative(2)) && + IsASpace(sc.chPrev)) { + sc.SetState(SCE_SH_WORD); + sc.Forward(); + } else if (setBashOperator.Contains(sc.ch)) { + sc.SetState(SCE_SH_OPERATOR); + } + } + } + sc.Complete(); +} + +static bool IsCommentLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eol_pos; i++) { + char ch = styler[i]; + if (ch == '#') + return true; + else if (ch != ' ' && ch != '\t') + return false; + } + return false; +} + +static void FoldBashDoc(unsigned int startPos, int length, int, WordList *[], + Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + // Comment folding + if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) + { + if (!IsCommentLine(lineCurrent - 1, styler) + && IsCommentLine(lineCurrent + 1, styler)) + levelCurrent++; + else if (IsCommentLine(lineCurrent - 1, styler) + && !IsCommentLine(lineCurrent + 1, styler)) + levelCurrent--; + } + if (style == SCE_SH_OPERATOR) { + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const bashWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmBash(SCLEX_BASH, ColouriseBashDoc, "bash", FoldBashDoc, bashWordListDesc); diff --git a/lexers/LexBasic.cxx b/lexers/LexBasic.cxx new file mode 100644 index 000000000..1c5d7b425 --- /dev/null +++ b/lexers/LexBasic.cxx @@ -0,0 +1,373 @@ +// Scintilla source code edit control +/** @file LexBasic.cxx + ** Lexer for BlitzBasic and PureBasic. + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +// This tries to be a unified Lexer/Folder for all the BlitzBasic/BlitzMax/PurBasic basics +// and derivatives. Once they diverge enough, might want to split it into multiple +// lexers for more code clearity. +// +// Mail me (elias users sf net) for any bugs. + +// Folding only works for simple things like functions or types. + +// You may want to have a look at my ctags lexer as well, if you additionally to coloring +// and folding need to extract things like label tags in your editor. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +/* Bits: + * 1 - whitespace + * 2 - operator + * 4 - identifier + * 8 - decimal digit + * 16 - hex digit + * 32 - bin digit + */ +static int character_classification[128] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 2, + 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4, + 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0 +}; + +static bool IsSpace(int c) { + return c < 128 && (character_classification[c] & 1); +} + +static bool IsOperator(int c) { + return c < 128 && (character_classification[c] & 2); +} + +static bool IsIdentifier(int c) { + return c < 128 && (character_classification[c] & 4); +} + +static bool IsDigit(int c) { + return c < 128 && (character_classification[c] & 8); +} + +static bool IsHexDigit(int c) { + return c < 128 && (character_classification[c] & 16); +} + +static bool IsBinDigit(int c) { + return c < 128 && (character_classification[c] & 32); +} + +static int LowerCase(int c) +{ + if (c >= 'A' && c <= 'Z') + return 'a' + c - 'A'; + return c; +} + +static void ColouriseBasicDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler, char comment_char) { + bool wasfirst = true, isfirst = true; // true if first token in a line + styler.StartAt(startPos); + + StyleContext sc(startPos, length, initStyle, styler); + + // Can't use sc.More() here else we miss the last character + for (; ; sc.Forward()) { + if (sc.state == SCE_B_IDENTIFIER) { + if (!IsIdentifier(sc.ch)) { + // Labels + if (wasfirst && sc.Match(':')) { + sc.ChangeState(SCE_B_LABEL); + sc.ForwardSetState(SCE_B_DEFAULT); + } else { + char s[100]; + int kstates[4] = { + SCE_B_KEYWORD, + SCE_B_KEYWORD2, + SCE_B_KEYWORD3, + SCE_B_KEYWORD4, + }; + sc.GetCurrentLowered(s, sizeof(s)); + for (int i = 0; i < 4; i++) { + if (keywordlists[i]->InList(s)) { + sc.ChangeState(kstates[i]); + } + } + // Types, must set them as operator else they will be + // matched as number/constant + if (sc.Match('.') || sc.Match('$') || sc.Match('%') || + sc.Match('#')) { + sc.SetState(SCE_B_OPERATOR); + } else { + sc.SetState(SCE_B_DEFAULT); + } + } + } + } else if (sc.state == SCE_B_OPERATOR) { + if (!IsOperator(sc.ch) || sc.Match('#')) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_LABEL) { + if (!IsIdentifier(sc.ch)) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_CONSTANT) { + if (!IsIdentifier(sc.ch)) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_NUMBER) { + if (!IsDigit(sc.ch)) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_HEXNUMBER) { + if (!IsHexDigit(sc.ch)) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_BINNUMBER) { + if (!IsBinDigit(sc.ch)) + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_STRING) { + if (sc.ch == '"') { + sc.ForwardSetState(SCE_B_DEFAULT); + } + if (sc.atLineEnd) { + sc.ChangeState(SCE_B_ERROR); + sc.SetState(SCE_B_DEFAULT); + } + } else if (sc.state == SCE_B_COMMENT || sc.state == SCE_B_PREPROCESSOR) { + if (sc.atLineEnd) { + sc.SetState(SCE_B_DEFAULT); + } + } + + if (sc.atLineStart) + isfirst = true; + + if (sc.state == SCE_B_DEFAULT || sc.state == SCE_B_ERROR) { + if (isfirst && sc.Match('.')) { + sc.SetState(SCE_B_LABEL); + } else if (isfirst && sc.Match('#')) { + wasfirst = isfirst; + sc.SetState(SCE_B_IDENTIFIER); + } else if (sc.Match(comment_char)) { + // Hack to make deprecated QBASIC '$Include show + // up in freebasic with SCE_B_PREPROCESSOR. + if (comment_char == '\'' && sc.Match(comment_char, '$')) + sc.SetState(SCE_B_PREPROCESSOR); + else + sc.SetState(SCE_B_COMMENT); + } else if (sc.Match('"')) { + sc.SetState(SCE_B_STRING); + } else if (IsDigit(sc.ch)) { + sc.SetState(SCE_B_NUMBER); + } else if (sc.Match('$')) { + sc.SetState(SCE_B_HEXNUMBER); + } else if (sc.Match('%')) { + sc.SetState(SCE_B_BINNUMBER); + } else if (sc.Match('#')) { + sc.SetState(SCE_B_CONSTANT); + } else if (IsOperator(sc.ch)) { + sc.SetState(SCE_B_OPERATOR); + } else if (IsIdentifier(sc.ch)) { + wasfirst = isfirst; + sc.SetState(SCE_B_IDENTIFIER); + } else if (!IsSpace(sc.ch)) { + sc.SetState(SCE_B_ERROR); + } + } + + if (!IsSpace(sc.ch)) + isfirst = false; + + if (!sc.More()) + break; + } + sc.Complete(); +} + +static int CheckBlitzFoldPoint(char const *token, int &level) { + if (!strcmp(token, "function") || + !strcmp(token, "type")) { + level |= SC_FOLDLEVELHEADERFLAG; + return 1; + } + if (!strcmp(token, "end function") || + !strcmp(token, "end type")) { + return -1; + } + return 0; +} + +static int CheckPureFoldPoint(char const *token, int &level) { + if (!strcmp(token, "procedure") || + !strcmp(token, "enumeration") || + !strcmp(token, "interface") || + !strcmp(token, "structure")) { + level |= SC_FOLDLEVELHEADERFLAG; + return 1; + } + if (!strcmp(token, "endprocedure") || + !strcmp(token, "endenumeration") || + !strcmp(token, "endinterface") || + !strcmp(token, "endstructure")) { + return -1; + } + return 0; +} + +static int CheckFreeFoldPoint(char const *token, int &level) { + if (!strcmp(token, "function") || + !strcmp(token, "sub") || + !strcmp(token, "type")) { + level |= SC_FOLDLEVELHEADERFLAG; + return 1; + } + if (!strcmp(token, "end function") || + !strcmp(token, "end sub") || + !strcmp(token, "end type")) { + return -1; + } + return 0; +} + +static void FoldBasicDoc(unsigned int startPos, int length, + Accessor &styler, int (*CheckFoldPoint)(char const *, int &)) { + int line = styler.GetLine(startPos); + int level = styler.LevelAt(line); + int go = 0, done = 0; + int endPos = startPos + length; + char word[256]; + int wordlen = 0; + int i; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + // Scan for tokens at the start of the line (they may include + // whitespace, for tokens like "End Function" + for (i = startPos; i < endPos; i++) { + int c = styler.SafeGetCharAt(i); + if (!done && !go) { + if (wordlen) { // are we scanning a token already? + word[wordlen] = static_cast(LowerCase(c)); + if (!IsIdentifier(c)) { // done with token + word[wordlen] = '\0'; + go = CheckFoldPoint(word, level); + if (!go) { + // Treat any whitespace as single blank, for + // things like "End Function". + if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) { + word[wordlen] = ' '; + if (wordlen < 255) + wordlen++; + } + else // done with this line + done = 1; + } + } else if (wordlen < 255) { + wordlen++; + } + } else { // start scanning at first non-whitespace character + if (!IsSpace(c)) { + if (IsIdentifier(c)) { + word[0] = static_cast(LowerCase(c)); + wordlen = 1; + } else // done with this line + done = 1; + } + } + } + if (c == '\n') { // line end + if (!done && wordlen == 0 && foldCompact) // line was only space + level |= SC_FOLDLEVELWHITEFLAG; + if (level != styler.LevelAt(line)) + styler.SetLevel(line, level); + level += go; + line++; + // reset state + wordlen = 0; + level &= ~SC_FOLDLEVELHEADERFLAG; + level &= ~SC_FOLDLEVELWHITEFLAG; + go = 0; + done = 0; + } + } +} + +static void ColouriseBlitzBasicDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, ';'); +} + +static void ColourisePureBasicDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, ';'); +} + +static void ColouriseFreeBasicDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, '\''); +} + +static void FoldBlitzBasicDoc(unsigned int startPos, int length, int, + WordList *[], Accessor &styler) { + FoldBasicDoc(startPos, length, styler, CheckBlitzFoldPoint); +} + +static void FoldPureBasicDoc(unsigned int startPos, int length, int, + WordList *[], Accessor &styler) { + FoldBasicDoc(startPos, length, styler, CheckPureFoldPoint); +} + +static void FoldFreeBasicDoc(unsigned int startPos, int length, int, + WordList *[], Accessor &styler) { + FoldBasicDoc(startPos, length, styler, CheckFreeFoldPoint); +} + +static const char * const blitzbasicWordListDesc[] = { + "BlitzBasic Keywords", + "user1", + "user2", + "user3", + 0 +}; + +static const char * const purebasicWordListDesc[] = { + "PureBasic Keywords", + "PureBasic PreProcessor Keywords", + "user defined 1", + "user defined 2", + 0 +}; + +static const char * const freebasicWordListDesc[] = { + "FreeBasic Keywords", + "FreeBasic PreProcessor Keywords", + "user defined 1", + "user defined 2", + 0 +}; + +LexerModule lmBlitzBasic(SCLEX_BLITZBASIC, ColouriseBlitzBasicDoc, "blitzbasic", + FoldBlitzBasicDoc, blitzbasicWordListDesc); + +LexerModule lmPureBasic(SCLEX_PUREBASIC, ColourisePureBasicDoc, "purebasic", + FoldPureBasicDoc, purebasicWordListDesc); + +LexerModule lmFreeBasic(SCLEX_FREEBASIC, ColouriseFreeBasicDoc, "freebasic", + FoldFreeBasicDoc, freebasicWordListDesc); + diff --git a/lexers/LexBullant.cxx b/lexers/LexBullant.cxx new file mode 100644 index 000000000..28e2e7543 --- /dev/null +++ b/lexers/LexBullant.cxx @@ -0,0 +1,229 @@ +// SciTE - Scintilla based Text Editor +// LexBullant.cxx - lexer for Bullant + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static int classifyWordBullant(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { + char s[100]; + s[0] = '\0'; + for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) { + s[i] = static_cast(tolower(styler[start + i])); + s[i + 1] = '\0'; + } + int lev= 0; + char chAttr = SCE_C_IDENTIFIER; + if (isdigit(s[0]) || (s[0] == '.')){ + chAttr = SCE_C_NUMBER; + } + else { + if (keywords.InList(s)) { + chAttr = SCE_C_WORD; + if (strcmp(s, "end") == 0) + lev = -1; + else if (strcmp(s, "method") == 0 || + strcmp(s, "case") == 0 || + strcmp(s, "class") == 0 || + strcmp(s, "debug") == 0 || + strcmp(s, "test") == 0 || + strcmp(s, "if") == 0 || + strcmp(s, "lock") == 0 || + strcmp(s, "transaction") == 0 || + strcmp(s, "trap") == 0 || + strcmp(s, "until") == 0 || + strcmp(s, "while") == 0) + lev = 1; + } + } + styler.ColourTo(end, chAttr); + return lev; +} + +static void ColouriseBullantDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + WordList &keywords = *keywordlists[0]; + + styler.StartAt(startPos); + + bool fold = styler.GetPropertyInt("fold") != 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + + int state = initStyle; + if (state == SCE_C_STRINGEOL) // Does not leak onto next line + state = SCE_C_DEFAULT; + char chPrev = ' '; + char chNext = styler[startPos]; + unsigned int lengthDoc = startPos + length; + int visibleChars = 0; + styler.StartSegment(startPos); + int endFoundThisLine = 0; + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // End of line + endFoundThisLine = 0; + if (state == SCE_C_STRINGEOL) { + styler.ColourTo(i, state); + state = SCE_C_DEFAULT; + } + if (fold) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + styler.SetLevel(lineCurrent, lev); + lineCurrent++; + levelPrev = levelCurrent; + } + visibleChars = 0; + +/* int indentBlock = GetLineIndentation(lineCurrent); + if (blockChange==1){ + lineCurrent++; + int pos=SetLineIndentation(lineCurrent, indentBlock + indentSize); + } else if (blockChange==-1) { + indentBlock -= indentSize; + if (indentBlock < 0) + indentBlock = 0; + SetLineIndentation(lineCurrent, indentBlock); + lineCurrent++; + } + blockChange=0; +*/ } + if (!(isascii(ch) && isspace(ch))) + visibleChars++; + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + chPrev = ' '; + i += 1; + continue; + } + + if (state == SCE_C_DEFAULT) { + if (iswordstart(ch)) { + styler.ColourTo(i-1, state); + state = SCE_C_IDENTIFIER; + } else if (ch == '@' && chNext == 'o') { + if ((styler.SafeGetCharAt(i+2) =='f') && (styler.SafeGetCharAt(i+3) == 'f')) { + styler.ColourTo(i-1, state); + state = SCE_C_COMMENT; + } + } else if (ch == '#') { + styler.ColourTo(i-1, state); + state = SCE_C_COMMENTLINE; + } else if (ch == '\"') { + styler.ColourTo(i-1, state); + state = SCE_C_STRING; + } else if (ch == '\'') { + styler.ColourTo(i-1, state); + state = SCE_C_CHARACTER; + } else if (isoperator(ch)) { + styler.ColourTo(i-1, state); + styler.ColourTo(i, SCE_C_OPERATOR); + } + } else if (state == SCE_C_IDENTIFIER) { + if (!iswordchar(ch)) { + int levelChange = classifyWordBullant(styler.GetStartSegment(), i - 1, keywords, styler); + state = SCE_C_DEFAULT; + chNext = styler.SafeGetCharAt(i + 1); + if (ch == '#') { + state = SCE_C_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_C_STRING; + } else if (ch == '\'') { + state = SCE_C_CHARACTER; + } else if (isoperator(ch)) { + styler.ColourTo(i, SCE_C_OPERATOR); + } + if (endFoundThisLine == 0) + levelCurrent+=levelChange; + if (levelChange == -1) + endFoundThisLine=1; + } + } else if (state == SCE_C_COMMENT) { + if (ch == '@' && chNext == 'o') { + if (styler.SafeGetCharAt(i+2) == 'n') { + styler.ColourTo(i+2, state); + state = SCE_C_DEFAULT; + i+=2; + } + } + } else if (state == SCE_C_COMMENTLINE) { + if (ch == '\r' || ch == '\n') { + endFoundThisLine = 0; + styler.ColourTo(i-1, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_STRING) { + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + } + } else if (ch == '\"') { + styler.ColourTo(i, state); + state = SCE_C_DEFAULT; + } else if (chNext == '\r' || chNext == '\n') { + endFoundThisLine = 0; + styler.ColourTo(i-1, SCE_C_STRINGEOL); + state = SCE_C_STRINGEOL; + } + } else if (state == SCE_C_CHARACTER) { + if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) { + endFoundThisLine = 0; + styler.ColourTo(i-1, SCE_C_STRINGEOL); + state = SCE_C_STRINGEOL; + } else if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + } + } else if (ch == '\'') { + styler.ColourTo(i, state); + state = SCE_C_DEFAULT; + } + } + chPrev = ch; + } + styler.ColourTo(lengthDoc - 1, state); + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + if (fold) { + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + //styler.SetLevel(lineCurrent, levelCurrent | flagsNext); + styler.SetLevel(lineCurrent, levelPrev | flagsNext); + + } +} + +static const char * const bullantWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmBullant(SCLEX_BULLANT, ColouriseBullantDoc, "bullant", 0, bullantWordListDesc); diff --git a/lexers/LexCLW.cxx b/lexers/LexCLW.cxx new file mode 100644 index 000000000..624ef0f2b --- /dev/null +++ b/lexers/LexCLW.cxx @@ -0,0 +1,679 @@ +// Scintilla source code edit control +/** @file LexClw.cxx + ** Lexer for Clarion. + ** 2004/12/17 Updated Lexer + **/ +// Copyright 2003-2004 by Ron Schofield +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// Is an end of line character +inline bool IsEOL(const int ch) { + + return(ch == '\n'); +} + +// Convert character to uppercase +static char CharacterUpper(char chChar) { + + if (chChar < 'a' || chChar > 'z') { + return(chChar); + } + else { + return(static_cast(chChar - 'a' + 'A')); + } +} + +// Convert string to uppercase +static void StringUpper(char *szString) { + + while (*szString) { + *szString = CharacterUpper(*szString); + szString++; + } +} + +// Is a label start character +inline bool IsALabelStart(const int iChar) { + + return(isalpha(iChar) || iChar == '_'); +} + +// Is a label character +inline bool IsALabelCharacter(const int iChar) { + + return(isalnum(iChar) || iChar == '_' || iChar == ':'); +} + +// Is the character is a ! and the the next character is not a ! +inline bool IsACommentStart(const int iChar) { + + return(iChar == '!'); +} + +// Is the character a Clarion hex character (ABCDEF) +inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) { + + // Case insensitive. + if (!bCaseSensitive) { + if (strchr("ABCDEFabcdef", iChar) != NULL) { + return(true); + } + } + // Case sensitive + else { + if (strchr("ABCDEF", iChar) != NULL) { + return(true); + } + } + return(false); +} + +// Is the character a Clarion base character (B=Binary, O=Octal, H=Hex) +inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) { + + // Case insensitive. + if (!bCaseSensitive) { + // If character is a numeric base character + if (strchr("BOHboh", iChar) != NULL) { + return(true); + } + } + // Case sensitive + else { + // If character is a numeric base character + if (strchr("BOH", iChar) != NULL) { + return(true); + } + } + return(false); +} + +// Set the correct numeric constant state +inline bool SetNumericConstantState(StyleContext &scDoc) { + + int iPoints = 0; // Point counter + char cNumericString[512]; // Numeric string buffer + + // Buffer the current numberic string + scDoc.GetCurrent(cNumericString, sizeof(cNumericString)); + // Loop through the string until end of string (NULL termination) + for (int iIndex = 0; cNumericString[iIndex] != '\0'; iIndex++) { + // Depending on the character + switch (cNumericString[iIndex]) { + // Is a . (point) + case '.' : + // Increment point counter + iPoints++; + break; + default : + break; + } + } + // If points found (can be more than one for improper formatted number + if (iPoints > 0) { + return(true); + } + // Else no points found + else { + return(false); + } +} + +// Get the next word in uppercase from the current position (keyword lookahead) +inline bool GetNextWordUpper(Accessor &styler, unsigned int uiStartPos, int iLength, char *cWord) { + + unsigned int iIndex = 0; // Buffer Index + + // Loop through the remaining string from the current position + for (int iOffset = uiStartPos; iOffset < iLength; iOffset++) { + // Get the character from the buffer using the offset + char cCharacter = styler[iOffset]; + if (IsEOL(cCharacter)) { + break; + } + // If the character is alphabet character + if (isalpha(cCharacter)) { + // Add UPPERCASE character to the word buffer + cWord[iIndex++] = CharacterUpper(cCharacter); + } + } + // Add null termination + cWord[iIndex] = '\0'; + // If no word was found + if (iIndex == 0) { + // Return failure + return(false); + } + // Else word was found + else { + // Return success + return(true); + } +} + +// Clarion Language Colouring Procedure +static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) { + + int iParenthesesLevel = 0; // Parenthese Level + int iColumn1Label = false; // Label starts in Column 1 + + WordList &wlClarionKeywords = *wlKeywords[0]; // Clarion Keywords + WordList &wlCompilerDirectives = *wlKeywords[1]; // Compiler Directives + WordList &wlRuntimeExpressions = *wlKeywords[2]; // Runtime Expressions + WordList &wlBuiltInProcsFuncs = *wlKeywords[3]; // Builtin Procedures and Functions + WordList &wlStructsDataTypes = *wlKeywords[4]; // Structures and Data Types + WordList &wlAttributes = *wlKeywords[5]; // Procedure Attributes + WordList &wlStandardEquates = *wlKeywords[6]; // Standard Equates + WordList &wlLabelReservedWords = *wlKeywords[7]; // Clarion Reserved Keywords (Labels) + WordList &wlProcLabelReservedWords = *wlKeywords[8]; // Clarion Reserved Keywords (Procedure Labels) + + const char wlProcReservedKeywordList[] = + "PROCEDURE FUNCTION"; + WordList wlProcReservedKeywords; + wlProcReservedKeywords.Set(wlProcReservedKeywordList); + + const char wlCompilerKeywordList[] = + "COMPILE OMIT"; + WordList wlCompilerKeywords; + wlCompilerKeywords.Set(wlCompilerKeywordList); + + const char wlLegacyStatementsList[] = + "BOF EOF FUNCTION POINTER SHARE"; + WordList wlLegacyStatements; + wlLegacyStatements.Set(wlLegacyStatementsList); + + StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler); + + // lex source code + for (; scDoc.More(); scDoc.Forward()) + { + // + // Determine if the current state should terminate. + // + + // Label State Handling + if (scDoc.state == SCE_CLW_LABEL) { + // If the character is not a valid label + if (!IsALabelCharacter(scDoc.ch)) { + // If the character is a . (dot syntax) + if (scDoc.ch == '.') { + // Turn off column 1 label flag as label now cannot be reserved work + iColumn1Label = false; + // Uncolour the . (dot) to default state, move forward one character, + // and change back to the label state. + scDoc.SetState(SCE_CLW_DEFAULT); + scDoc.Forward(); + scDoc.SetState(SCE_CLW_LABEL); + } + // Else check label + else { + char cLabel[512]; // Label buffer + // Buffer the current label string + scDoc.GetCurrent(cLabel,sizeof(cLabel)); + // If case insensitive, convert string to UPPERCASE to match passed keywords. + if (!bCaseSensitive) { + StringUpper(cLabel); + } + // Else if UPPERCASE label string is in the Clarion compiler keyword list + if (wlCompilerKeywords.InList(cLabel) && iColumn1Label){ + // change the label to error state + scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); + } + // Else if UPPERCASE label string is in the Clarion reserved keyword list + else if (wlLabelReservedWords.InList(cLabel) && iColumn1Label){ + // change the label to error state + scDoc.ChangeState(SCE_CLW_ERROR); + } + // Else if UPPERCASE label string is + else if (wlProcLabelReservedWords.InList(cLabel) && iColumn1Label) { + char cWord[512]; // Word buffer + // Get the next word from the current position + if (GetNextWordUpper(accStyler,scDoc.currentPos,uiStartPos+iLength,cWord)) { + // If the next word is a procedure reserved word + if (wlProcReservedKeywords.InList(cWord)) { + // Change the label to error state + scDoc.ChangeState(SCE_CLW_ERROR); + } + } + } + // Else if label string is in the compiler directive keyword list + else if (wlCompilerDirectives.InList(cLabel)) { + // change the state to compiler directive state + scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); + } + // Terminate the label state and set to default state + scDoc.SetState(SCE_CLW_DEFAULT); + } + } + } + // Keyword State Handling + else if (scDoc.state == SCE_CLW_KEYWORD) { + // If character is : (colon) + if (scDoc.ch == ':') { + char cEquate[512]; // Equate buffer + // Move forward to include : (colon) in buffer + scDoc.Forward(); + // Buffer the equate string + scDoc.GetCurrent(cEquate,sizeof(cEquate)); + // If case insensitive, convert string to UPPERCASE to match passed keywords. + if (!bCaseSensitive) { + StringUpper(cEquate); + } + // If statement string is in the equate list + if (wlStandardEquates.InList(cEquate)) { + // Change to equate state + scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE); + } + } + // If the character is not a valid label character + else if (!IsALabelCharacter(scDoc.ch)) { + char cStatement[512]; // Statement buffer + // Buffer the statement string + scDoc.GetCurrent(cStatement,sizeof(cStatement)); + // If case insensitive, convert string to UPPERCASE to match passed keywords. + if (!bCaseSensitive) { + StringUpper(cStatement); + } + // If statement string is in the Clarion keyword list + if (wlClarionKeywords.InList(cStatement)) { + // Change the statement string to the Clarion keyword state + scDoc.ChangeState(SCE_CLW_KEYWORD); + } + // Else if statement string is in the compiler directive keyword list + else if (wlCompilerDirectives.InList(cStatement)) { + // Change the statement string to the compiler directive state + scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); + } + // Else if statement string is in the runtime expressions keyword list + else if (wlRuntimeExpressions.InList(cStatement)) { + // Change the statement string to the runtime expressions state + scDoc.ChangeState(SCE_CLW_RUNTIME_EXPRESSIONS); + } + // Else if statement string is in the builtin procedures and functions keyword list + else if (wlBuiltInProcsFuncs.InList(cStatement)) { + // Change the statement string to the builtin procedures and functions state + scDoc.ChangeState(SCE_CLW_BUILTIN_PROCEDURES_FUNCTION); + } + // Else if statement string is in the tructures and data types keyword list + else if (wlStructsDataTypes.InList(cStatement)) { + // Change the statement string to the structures and data types state + scDoc.ChangeState(SCE_CLW_STRUCTURE_DATA_TYPE); + } + // Else if statement string is in the procedure attribute keyword list + else if (wlAttributes.InList(cStatement)) { + // Change the statement string to the procedure attribute state + scDoc.ChangeState(SCE_CLW_ATTRIBUTE); + } + // Else if statement string is in the standard equate keyword list + else if (wlStandardEquates.InList(cStatement)) { + // Change the statement string to the standard equate state + scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE); + } + // Else if statement string is in the deprecated or legacy keyword list + else if (wlLegacyStatements.InList(cStatement)) { + // Change the statement string to the standard equate state + scDoc.ChangeState(SCE_CLW_DEPRECATED); + } + // Else the statement string doesn't match any work list + else { + // Change the statement string to the default state + scDoc.ChangeState(SCE_CLW_DEFAULT); + } + // Terminate the keyword state and set to default state + scDoc.SetState(SCE_CLW_DEFAULT); + } + } + // String State Handling + else if (scDoc.state == SCE_CLW_STRING) { + // If the character is an ' (single quote) + if (scDoc.ch == '\'') { + // Set the state to default and move forward colouring + // the ' (single quote) as default state + // terminating the string state + scDoc.SetState(SCE_CLW_DEFAULT); + scDoc.Forward(); + } + // If the next character is an ' (single quote) + if (scDoc.chNext == '\'') { + // Move forward one character and set to default state + // colouring the next ' (single quote) as default state + // terminating the string state + scDoc.ForwardSetState(SCE_CLW_DEFAULT); + scDoc.Forward(); + } + } + // Picture String State Handling + else if (scDoc.state == SCE_CLW_PICTURE_STRING) { + // If the character is an ( (open parenthese) + if (scDoc.ch == '(') { + // Increment the parenthese level + iParenthesesLevel++; + } + // Else if the character is a ) (close parenthese) + else if (scDoc.ch == ')') { + // If the parenthese level is set to zero + // parentheses matched + if (!iParenthesesLevel) { + scDoc.SetState(SCE_CLW_DEFAULT); + } + // Else parenthese level is greater than zero + // still looking for matching parentheses + else { + // Decrement the parenthese level + iParenthesesLevel--; + } + } + } + // Standard Equate State Handling + else if (scDoc.state == SCE_CLW_STANDARD_EQUATE) { + if (!isalnum(scDoc.ch)) { + scDoc.SetState(SCE_CLW_DEFAULT); + } + } + // Integer Constant State Handling + else if (scDoc.state == SCE_CLW_INTEGER_CONSTANT) { + // If the character is not a digit (0-9) + // or character is not a hexidecimal character (A-F) + // or character is not a . (point) + // or character is not a numberic base character (B,O,H) + if (!(isdigit(scDoc.ch) + || IsAHexCharacter(scDoc.ch, bCaseSensitive) + || scDoc.ch == '.' + || IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) { + // If the number was a real + if (SetNumericConstantState(scDoc)) { + // Colour the matched string to the real constant state + scDoc.ChangeState(SCE_CLW_REAL_CONSTANT); + } + // Else the number was an integer + else { + // Colour the matched string to an integer constant state + scDoc.ChangeState(SCE_CLW_INTEGER_CONSTANT); + } + // Terminate the integer constant state and set to default state + scDoc.SetState(SCE_CLW_DEFAULT); + } + } + + // + // Determine if a new state should be entered. + // + + // Beginning of Line Handling + if (scDoc.atLineStart) { + // Reset the column 1 label flag + iColumn1Label = false; + // If column 1 character is a label start character + if (IsALabelStart(scDoc.ch)) { + // Label character is found in column 1 + // so set column 1 label flag and clear last column 1 label + iColumn1Label = true; + // Set the state to label + scDoc.SetState(SCE_CLW_LABEL); + } + // else if character is a space or tab + else if (IsASpace(scDoc.ch)){ + // Set to default state + scDoc.SetState(SCE_CLW_DEFAULT); + } + // else if comment start (!) or is an * (asterisk) + else if (IsACommentStart(scDoc.ch) || scDoc.ch == '*' ) { + // then set the state to comment. + scDoc.SetState(SCE_CLW_COMMENT); + } + // else the character is a ? (question mark) + else if (scDoc.ch == '?') { + // Change to the compiler directive state, move forward, + // colouring the ? (question mark), change back to default state. + scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); + scDoc.Forward(); + scDoc.SetState(SCE_CLW_DEFAULT); + } + // else an invalid character in column 1 + else { + // Set to error state + scDoc.SetState(SCE_CLW_ERROR); + } + } + // End of Line Handling + else if (scDoc.atLineEnd) { + // Reset to the default state at the end of each line. + scDoc.SetState(SCE_CLW_DEFAULT); + } + // Default Handling + else { + // If in default state + if (scDoc.state == SCE_CLW_DEFAULT) { + // If is a letter could be a possible statement + if (isalpha(scDoc.ch)) { + // Set the state to Clarion Keyword and verify later + scDoc.SetState(SCE_CLW_KEYWORD); + } + // else is a number + else if (isdigit(scDoc.ch)) { + // Set the state to Integer Constant and verify later + scDoc.SetState(SCE_CLW_INTEGER_CONSTANT); + } + // else if the start of a comment or a | (line continuation) + else if (IsACommentStart(scDoc.ch) || scDoc.ch == '|') { + // then set the state to comment. + scDoc.SetState(SCE_CLW_COMMENT); + } + // else if the character is a ' (single quote) + else if (scDoc.ch == '\'') { + // If the character is also a ' (single quote) + // Embedded Apostrophe + if (scDoc.chNext == '\'') { + // Move forward colouring it as default state + scDoc.ForwardSetState(SCE_CLW_DEFAULT); + } + else { + // move to the next character and then set the state to comment. + scDoc.ForwardSetState(SCE_CLW_STRING); + } + } + // else the character is an @ (ampersand) + else if (scDoc.ch == '@') { + // Case insensitive. + if (!bCaseSensitive) { + // If character is a valid picture token character + if (strchr("DEKNPSTdeknpst", scDoc.chNext) != NULL) { + // Set to the picture string state + scDoc.SetState(SCE_CLW_PICTURE_STRING); + } + } + // Case sensitive + else { + // If character is a valid picture token character + if (strchr("DEKNPST", scDoc.chNext) != NULL) { + // Set the picture string state + scDoc.SetState(SCE_CLW_PICTURE_STRING); + } + } + } + } + } + } + // lexing complete + scDoc.Complete(); +} + +// Clarion Language Case Sensitive Colouring Procedure +static void ColouriseClarionDocSensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) { + + ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true); +} + +// Clarion Language Case Insensitive Colouring Procedure +static void ColouriseClarionDocInsensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) { + + ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false); +} + +// Fill Buffer + +static void FillBuffer(unsigned int uiStart, unsigned int uiEnd, Accessor &accStyler, char *szBuffer, unsigned int uiLength) { + + unsigned int uiPos = 0; + + while ((uiPos < uiEnd - uiStart + 1) && (uiPos < uiLength-1)) { + szBuffer[uiPos] = static_cast(toupper(accStyler[uiStart + uiPos])); + uiPos++; + } + szBuffer[uiPos] = '\0'; +} + +// Classify Clarion Fold Point + +static int ClassifyClarionFoldPoint(int iLevel, const char* szString) { + + if (!(isdigit(szString[0]) || (szString[0] == '.'))) { + if (strcmp(szString, "PROCEDURE") == 0) { + // iLevel = SC_FOLDLEVELBASE + 1; + } + else if (strcmp(szString, "MAP") == 0 || + strcmp(szString,"ACCEPT") == 0 || + strcmp(szString,"BEGIN") == 0 || + strcmp(szString,"CASE") == 0 || + strcmp(szString,"EXECUTE") == 0 || + strcmp(szString,"IF") == 0 || + strcmp(szString,"ITEMIZE") == 0 || + strcmp(szString,"INTERFACE") == 0 || + strcmp(szString,"JOIN") == 0 || + strcmp(szString,"LOOP") == 0 || + strcmp(szString,"MODULE") == 0 || + strcmp(szString,"RECORD") == 0) { + iLevel++; + } + else if (strcmp(szString, "APPLICATION") == 0 || + strcmp(szString, "CLASS") == 0 || + strcmp(szString, "DETAIL") == 0 || + strcmp(szString, "FILE") == 0 || + strcmp(szString, "FOOTER") == 0 || + strcmp(szString, "FORM") == 0 || + strcmp(szString, "GROUP") == 0 || + strcmp(szString, "HEADER") == 0 || + strcmp(szString, "INTERFACE") == 0 || + strcmp(szString, "MENU") == 0 || + strcmp(szString, "MENUBAR") == 0 || + strcmp(szString, "OLE") == 0 || + strcmp(szString, "OPTION") == 0 || + strcmp(szString, "QUEUE") == 0 || + strcmp(szString, "REPORT") == 0 || + strcmp(szString, "SHEET") == 0 || + strcmp(szString, "TAB") == 0 || + strcmp(szString, "TOOLBAR") == 0 || + strcmp(szString, "VIEW") == 0 || + strcmp(szString, "WINDOW") == 0) { + iLevel++; + } + else if (strcmp(szString, "END") == 0 || + strcmp(szString, "UNTIL") == 0 || + strcmp(szString, "WHILE") == 0) { + iLevel--; + } + } + return(iLevel); +} + +// Clarion Language Folding Procedure +static void FoldClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *[], Accessor &accStyler) { + + unsigned int uiEndPos = uiStartPos + iLength; + int iLineCurrent = accStyler.GetLine(uiStartPos); + int iLevelPrev = accStyler.LevelAt(iLineCurrent) & SC_FOLDLEVELNUMBERMASK; + int iLevelCurrent = iLevelPrev; + char chNext = accStyler[uiStartPos]; + int iStyle = iInitStyle; + int iStyleNext = accStyler.StyleAt(uiStartPos); + int iVisibleChars = 0; + int iLastStart = 0; + + for (unsigned int uiPos = uiStartPos; uiPos < uiEndPos; uiPos++) { + + char chChar = chNext; + chNext = accStyler.SafeGetCharAt(uiPos + 1); + int iStylePrev = iStyle; + iStyle = iStyleNext; + iStyleNext = accStyler.StyleAt(uiPos + 1); + bool bEOL = (chChar == '\r' && chNext != '\n') || (chChar == '\n'); + + if (iStylePrev == SCE_CLW_DEFAULT) { + if (iStyle == SCE_CLW_KEYWORD || iStyle == SCE_CLW_STRUCTURE_DATA_TYPE) { + // Store last word start point. + iLastStart = uiPos; + } + } + + if (iStylePrev == SCE_CLW_KEYWORD || iStylePrev == SCE_CLW_STRUCTURE_DATA_TYPE) { + if(iswordchar(chChar) && !iswordchar(chNext)) { + char chBuffer[100]; + FillBuffer(iLastStart, uiPos, accStyler, chBuffer, sizeof(chBuffer)); + iLevelCurrent = ClassifyClarionFoldPoint(iLevelCurrent,chBuffer); + // if ((iLevelCurrent == SC_FOLDLEVELBASE + 1) && iLineCurrent > 1) { + // accStyler.SetLevel(iLineCurrent-1,SC_FOLDLEVELBASE); + // iLevelPrev = SC_FOLDLEVELBASE; + // } + } + } + + if (bEOL) { + int iLevel = iLevelPrev; + if ((iLevelCurrent > iLevelPrev) && (iVisibleChars > 0)) + iLevel |= SC_FOLDLEVELHEADERFLAG; + if (iLevel != accStyler.LevelAt(iLineCurrent)) { + accStyler.SetLevel(iLineCurrent,iLevel); + } + iLineCurrent++; + iLevelPrev = iLevelCurrent; + iVisibleChars = 0; + } + + if (!isspacechar(chChar)) + iVisibleChars++; + } + + // Fill in the real level of the next line, keeping the current flags + // as they will be filled in later. + int iFlagsNext = accStyler.LevelAt(iLineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + accStyler.SetLevel(iLineCurrent, iLevelPrev | iFlagsNext); +} + +// Word List Descriptions +static const char * const rgWordListDescriptions[] = { + "Clarion Keywords", + "Compiler Directives", + "Built-in Procedures and Functions", + "Runtime Expressions", + "Structure and Data Types", + "Attributes", + "Standard Equates", + "Reserved Words (Labels)", + "Reserved Words (Procedure Labels)", + 0, +}; + +// Case Sensitive Clarion Language Lexer +LexerModule lmClw(SCLEX_CLW, ColouriseClarionDocSensitive, "clarion", FoldClarionDoc, rgWordListDescriptions); + +// Case Insensitive Clarion Language Lexer +LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClarionDocInsensitive, "clarionnocase", FoldClarionDoc, rgWordListDescriptions); diff --git a/lexers/LexCOBOL.cxx b/lexers/LexCOBOL.cxx new file mode 100644 index 000000000..05bf1d973 --- /dev/null +++ b/lexers/LexCOBOL.cxx @@ -0,0 +1,368 @@ +// Scintilla source code edit control +/** @file LexCOBOL.cxx + ** Lexer for COBOL + ** Based on LexPascal.cxx + ** Written by Laurent le Tynevez + ** Updated by Simon Steele September 2002 + ** Updated by Mathias Rauen May 2003 (Delphi adjustments) + ** Updated by Rod Falck, Aug 2006 Converted to COBOL + **/ + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "StyleContext.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#define IN_DIVISION 0x01 +#define IN_DECLARATIVES 0x02 +#define IN_SECTION 0x04 +#define IN_PARAGRAPH 0x08 +#define IN_FLAGS 0xF +#define NOT_HEADER 0x10 + +inline bool isCOBOLoperator(char ch) + { + return isoperator(ch); + } + +inline bool isCOBOLwordchar(char ch) + { + return isascii(ch) && (isalnum(ch) || ch == '-'); + + } + +inline bool isCOBOLwordstart(char ch) + { + return isascii(ch) && isalnum(ch); + } + +static int CountBits(int nBits) + { + int count = 0; + for (int i = 0; i < 32; ++i) + { + count += nBits & 1; + nBits >>= 1; + } + return count; + } + +static void getRange(unsigned int start, + unsigned int end, + Accessor &styler, + char *s, + unsigned int len) { + unsigned int i = 0; + while ((i < end - start + 1) && (i < len-1)) { + s[i] = static_cast(tolower(styler[start + i])); + i++; + } + s[i] = '\0'; +} + +static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr) { + styler.ColourTo(end, attr); +} + + +static int classifyWordCOBOL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, int nContainment, bool *bAarea) { + int ret = 0; + + WordList& a_keywords = *keywordlists[0]; + WordList& b_keywords = *keywordlists[1]; + WordList& c_keywords = *keywordlists[2]; + + char s[100]; + getRange(start, end, styler, s, sizeof(s)); + + char chAttr = SCE_C_IDENTIFIER; + if (isdigit(s[0]) || (s[0] == '.') || (s[0] == 'v')) { + chAttr = SCE_C_NUMBER; + char *p = s + 1; + while (*p) { + if ((!isdigit(*p) && (*p) != 'v') && isCOBOLwordchar(*p)) { + chAttr = SCE_C_IDENTIFIER; + break; + } + ++p; + } + } + else { + if (a_keywords.InList(s)) { + chAttr = SCE_C_WORD; + } + else if (b_keywords.InList(s)) { + chAttr = SCE_C_WORD2; + } + else if (c_keywords.InList(s)) { + chAttr = SCE_C_UUID; + } + } + if (*bAarea) { + if (strcmp(s, "division") == 0) { + ret = IN_DIVISION; + // we've determined the containment, anything else is just ignored for those purposes + *bAarea = false; + } else if (strcmp(s, "declaratives") == 0) { + ret = IN_DIVISION | IN_DECLARATIVES; + if (nContainment & IN_DECLARATIVES) + ret |= NOT_HEADER | IN_SECTION; + // we've determined the containment, anything else is just ignored for those purposes + *bAarea = false; + } else if (strcmp(s, "section") == 0) { + ret = (nContainment &~ IN_PARAGRAPH) | IN_SECTION; + // we've determined the containment, anything else is just ignored for those purposes + *bAarea = false; + } else if (strcmp(s, "end") == 0 && (nContainment & IN_DECLARATIVES)) { + ret = IN_DIVISION | IN_DECLARATIVES | IN_SECTION | NOT_HEADER; + } else { + ret = nContainment | IN_PARAGRAPH; + } + } + ColourTo(styler, end, chAttr); + return ret; +} + +static void ColouriseCOBOLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + styler.StartAt(startPos); + + int state = initStyle; + if (state == SCE_C_CHARACTER) // Does not leak onto next line + state = SCE_C_DEFAULT; + char chPrev = ' '; + char chNext = styler[startPos]; + unsigned int lengthDoc = startPos + length; + + int nContainment; + + int currentLine = styler.GetLine(startPos); + if (currentLine > 0) { + styler.SetLineState(currentLine, styler.GetLineState(currentLine-1)); + nContainment = styler.GetLineState(currentLine); + nContainment &= ~NOT_HEADER; + } else { + styler.SetLineState(currentLine, 0); + nContainment = 0; + } + + styler.StartSegment(startPos); + bool bNewLine = true; + bool bAarea = !isspacechar(chNext); + int column = 0; + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + + chNext = styler.SafeGetCharAt(i + 1); + + ++column; + + if (bNewLine) { + column = 0; + } + if (column <= 1 && !bAarea) { + bAarea = !isspacechar(ch); + } + bool bSetNewLine = false; + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // End of line + if (state == SCE_C_CHARACTER) { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + styler.SetLineState(currentLine, nContainment); + currentLine++; + bSetNewLine = true; + if (nContainment & NOT_HEADER) + nContainment &= ~(NOT_HEADER | IN_DECLARATIVES | IN_SECTION); + } + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + chPrev = ' '; + i += 1; + continue; + } + + if (state == SCE_C_DEFAULT) { + if (isCOBOLwordstart(ch) || (ch == '$' && isascii(chNext) && isalpha(chNext))) { + ColourTo(styler, i-1, state); + state = SCE_C_IDENTIFIER; + } else if (column == 0 && ch == '*' && chNext != '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTLINE; + } else if (column == 0 && ch == '/' && chNext != '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTLINE; + } else if (column == 0 && ch == '*' && chNext == '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTDOC; + } else if (column == 0 && ch == '/' && chNext == '*') { + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTDOC; + } else if (ch == '"') { + ColourTo(styler, i-1, state); + state = SCE_C_STRING; + } else if (ch == '\'') { + ColourTo(styler, i-1, state); + state = SCE_C_CHARACTER; + } else if (ch == '?' && column == 0) { + ColourTo(styler, i-1, state); + state = SCE_C_PREPROCESSOR; + } else if (isCOBOLoperator(ch)) { + ColourTo(styler, i-1, state); + ColourTo(styler, i, SCE_C_OPERATOR); + } + } else if (state == SCE_C_IDENTIFIER) { + if (!isCOBOLwordchar(ch)) { + int lStateChange = classifyWordCOBOL(styler.GetStartSegment(), i - 1, keywordlists, styler, nContainment, &bAarea); + + if(lStateChange != 0) { + styler.SetLineState(currentLine, lStateChange); + nContainment = lStateChange; + } + + state = SCE_C_DEFAULT; + chNext = styler.SafeGetCharAt(i + 1); + if (ch == '"') { + state = SCE_C_STRING; + } else if (ch == '\'') { + state = SCE_C_CHARACTER; + } else if (isCOBOLoperator(ch)) { + ColourTo(styler, i, SCE_C_OPERATOR); + } + } + } else { + if (state == SCE_C_PREPROCESSOR) { + if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) { + ColourTo(styler, i-1, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENT) { + if (ch == '\r' || ch == '\n') { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENTDOC) { + if (ch == '\r' || ch == '\n') { + if (((i > styler.GetStartSegment() + 2) || ( + (initStyle == SCE_C_COMMENTDOC) && + (styler.GetStartSegment() == static_cast(startPos))))) { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + } + } else if (state == SCE_C_COMMENTLINE) { + if (ch == '\r' || ch == '\n') { + ColourTo(styler, i-1, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_STRING) { + if (ch == '"') { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_CHARACTER) { + if (ch == '\'') { + ColourTo(styler, i, state); + state = SCE_C_DEFAULT; + } + } + } + chPrev = ch; + bNewLine = bSetNewLine; + if (bNewLine) + { + bAarea = false; + } + } + ColourTo(styler, lengthDoc - 1, state); +} + +static void FoldCOBOLDoc(unsigned int startPos, int length, int, WordList *[], + Accessor &styler) { + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) & SC_FOLDLEVELNUMBERMASK : 0xFFF; + char chNext = styler[startPos]; + + bool bNewLine = true; + bool bAarea = !isspacechar(chNext); + int column = 0; + bool bComment = false; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + ++column; + + if (bNewLine) { + column = 0; + bComment = (ch == '*' || ch == '/' || ch == '?'); + } + if (column <= 1 && !bAarea) { + bAarea = !isspacechar(ch); + } + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (atEOL) { + int nContainment = styler.GetLineState(lineCurrent); + int lev = CountBits(nContainment & IN_FLAGS) | SC_FOLDLEVELBASE; + if (bAarea && !bComment) + --lev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((bAarea) && (visibleChars > 0) && !(nContainment & NOT_HEADER) && !bComment) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + if ((lev & SC_FOLDLEVELNUMBERMASK) <= (levelPrev & SC_FOLDLEVELNUMBERMASK)) { + // this level is at the same level or less than the previous line + // therefore these is nothing for the previous header to collapse, so remove the header + styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG); + } + levelPrev = lev; + visibleChars = 0; + bAarea = false; + bNewLine = true; + lineCurrent++; + } else { + bNewLine = false; + } + + + if (!isspacechar(ch)) + visibleChars++; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const COBOLWordListDesc[] = { + "A Keywords", + "B Keywords", + "Extended Keywords", + 0 +}; + +LexerModule lmCOBOL(SCLEX_COBOL, ColouriseCOBOLDoc, "COBOL", FoldCOBOLDoc, COBOLWordListDesc); diff --git a/lexers/LexCPP.cxx b/lexers/LexCPP.cxx new file mode 100644 index 000000000..8a9395e17 --- /dev/null +++ b/lexers/LexCPP.cxx @@ -0,0 +1,506 @@ +// Scintilla source code edit control +/** @file LexCPP.cxx + ** Lexer for C++, C, Java, and JavaScript. + **/ +// Copyright 1998-2005 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "CharacterSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static bool IsSpaceEquiv(int state) { + return (state <= SCE_C_COMMENTDOC) || + // including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE + (state == SCE_C_COMMENTLINEDOC) || (state == SCE_C_COMMENTDOCKEYWORD) || + (state == SCE_C_COMMENTDOCKEYWORDERROR); +} + +// Preconditions: sc.currentPos points to a character after '+' or '-'. +// The test for pos reaching 0 should be redundant, +// and is in only for safety measures. +// Limitation: this code will give the incorrect answer for code like +// a = b+++/ptn/... +// Putting a space between the '++' post-inc operator and the '+' binary op +// fixes this, and is highly recommended for readability anyway. +static bool FollowsPostfixOperator(StyleContext &sc, Accessor &styler) { + int pos = (int) sc.currentPos; + while (--pos > 0) { + char ch = styler[pos]; + if (ch == '+' || ch == '-') { + return styler[pos - 1] == ch; + } + } + return false; +} + +static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler, bool caseSensitive) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + + // property styling.within.preprocessor + // For C++ code, determines whether all preprocessor code is styled in the preprocessor style (0, the default) + // or only from the initial # to the end of the command word(1). + bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; + + CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-"); + CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-"); + + CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); + + CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); + + // property lexer.cpp.allow.dollars + // Set to 0 to disallow the '$' character in identifiers with the cpp lexer. + if (styler.GetPropertyInt("lexer.cpp.allow.dollars", 1) != 0) { + setWordStart.Add('$'); + setWord.Add('$'); + } + + int chPrevNonWhite = ' '; + int visibleChars = 0; + bool lastWordWasUUID = false; + int styleBeforeDCKeyword = SCE_C_DEFAULT; + bool continuationLine = false; + bool isIncludePreprocessor = false; + + if (initStyle == SCE_C_PREPROCESSOR) { + // Set continuationLine if last character of previous line is '\' + int lineCurrent = styler.GetLine(startPos); + if (lineCurrent > 0) { + int chBack = styler.SafeGetCharAt(startPos-1, 0); + int chBack2 = styler.SafeGetCharAt(startPos-2, 0); + int lineEndChar = '!'; + if (chBack2 == '\r' && chBack == '\n') { + lineEndChar = styler.SafeGetCharAt(startPos-3, 0); + } else if (chBack == '\n' || chBack == '\r') { + lineEndChar = chBack2; + } + continuationLine = lineEndChar == '\\'; + } + } + + // look back to set chPrevNonWhite properly for better regex colouring + if (startPos > 0) { + int back = startPos; + while (--back && IsSpaceEquiv(styler.StyleAt(back))) + ; + if (styler.StyleAt(back) == SCE_C_OPERATOR) { + chPrevNonWhite = styler.SafeGetCharAt(back); + } + } + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart) { + if (sc.state == SCE_C_STRING) { + // Prevent SCE_C_STRINGEOL from leaking back to previous line which + // ends with a line continuation by locking in the state upto this position. + sc.SetState(SCE_C_STRING); + } + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + lastWordWasUUID = false; + isIncludePreprocessor = false; + } + + // Handle line continuation generically. + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continuationLine = true; + continue; + } + } + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_C_OPERATOR: + sc.SetState(SCE_C_DEFAULT); + break; + case SCE_C_NUMBER: + // We accept almost anything because of hex. and number suffixes + if (!setWord.Contains(sc.ch)) { + sc.SetState(SCE_C_DEFAULT); + } + break; + case SCE_C_IDENTIFIER: + if (!setWord.Contains(sc.ch) || (sc.ch == '.')) { + char s[1000]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (keywords.InList(s)) { + lastWordWasUUID = strcmp(s, "uuid") == 0; + sc.ChangeState(SCE_C_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_C_WORD2); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_C_GLOBALCLASS); + } + sc.SetState(SCE_C_DEFAULT); + } + break; + case SCE_C_PREPROCESSOR: + if (sc.atLineStart && !continuationLine) { + sc.SetState(SCE_C_DEFAULT); + } else if (stylingWithinPreprocessor) { + if (IsASpace(sc.ch)) { + sc.SetState(SCE_C_DEFAULT); + } + } else { + if (sc.Match('/', '*') || sc.Match('/', '/')) { + sc.SetState(SCE_C_DEFAULT); + } + } + break; + case SCE_C_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT); + } + break; + case SCE_C_COMMENTDOC: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_C_COMMENTDOC; + sc.SetState(SCE_C_COMMENTDOCKEYWORD); + } + } + break; + case SCE_C_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } + break; + case SCE_C_COMMENTLINEDOC: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC; + sc.SetState(SCE_C_COMMENTDOCKEYWORD); + } + } + break; + case SCE_C_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT); + } else if (!setDoxygen.Contains(sc.ch)) { + char s[100]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); + } + sc.SetState(styleBeforeDCKeyword); + } + break; + case SCE_C_STRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_C_STRINGEOL); + } else if (isIncludePreprocessor) { + if (sc.ch == '>') { + sc.ForwardSetState(SCE_C_DEFAULT); + isIncludePreprocessor = false; + } + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_C_DEFAULT); + } + break; + case SCE_C_CHARACTER: + if (sc.atLineEnd) { + sc.ChangeState(SCE_C_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_C_DEFAULT); + } + break; + case SCE_C_REGEX: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } else if (sc.ch == '/') { + sc.Forward(); + while ((sc.ch < 0x80) && islower(sc.ch)) + sc.Forward(); // gobble regex flags + sc.SetState(SCE_C_DEFAULT); + } else if (sc.ch == '\\') { + // Gobble up the quoted character + if (sc.chNext == '\\' || sc.chNext == '/') { + sc.Forward(); + } + } + break; + case SCE_C_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } + break; + case SCE_C_VERBATIM: + if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_C_DEFAULT); + } + } + break; + case SCE_C_UUID: + if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { + sc.SetState(SCE_C_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_C_DEFAULT) { + if (sc.Match('@', '\"')) { + sc.SetState(SCE_C_VERBATIM); + sc.Forward(); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + if (lastWordWasUUID) { + sc.SetState(SCE_C_UUID); + lastWordWasUUID = false; + } else { + sc.SetState(SCE_C_NUMBER); + } + } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) { + if (lastWordWasUUID) { + sc.SetState(SCE_C_UUID); + lastWordWasUUID = false; + } else { + sc.SetState(SCE_C_IDENTIFIER); + } + } else if (sc.Match('/', '*')) { + if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style + sc.SetState(SCE_C_COMMENTDOC); + } else { + sc.SetState(SCE_C_COMMENT); + } + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!")) + // Support of Qt/Doxygen doc. style + sc.SetState(SCE_C_COMMENTLINEDOC); + else + sc.SetState(SCE_C_COMMENTLINE); + } else if (sc.ch == '/' && setOKBeforeRE.Contains(chPrevNonWhite) && + (!setCouldBePostOp.Contains(chPrevNonWhite) || !FollowsPostfixOperator(sc, styler))) { + sc.SetState(SCE_C_REGEX); // JavaScript's RegEx + } else if (sc.ch == '\"') { + sc.SetState(SCE_C_STRING); + isIncludePreprocessor = false; // ensure that '>' won't end the string + } else if (isIncludePreprocessor && sc.ch == '<') { + sc.SetState(SCE_C_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_C_CHARACTER); + } else if (sc.ch == '#' && visibleChars == 0) { + // Preprocessor commands are alone on their line + sc.SetState(SCE_C_PREPROCESSOR); + // Skip whitespace between # and preprocessor word + do { + sc.Forward(); + } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); + if (sc.atLineEnd) { + sc.SetState(SCE_C_DEFAULT); + } else if (sc.Match("include")) { + isIncludePreprocessor = true; + } + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_C_OPERATOR); + } + } + + if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) { + chPrevNonWhite = sc.ch; + visibleChars++; + } + continuationLine = false; + } + sc.Complete(); +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_C_COMMENT || + style == SCE_C_COMMENTDOC || + style == SCE_C_COMMENTDOCKEYWORD || + style == SCE_C_COMMENTDOCKEYWORDERROR; +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "} else {". +static void FoldCppDoc(unsigned int startPos, int length, int initStyle, + WordList *[], Accessor &styler) { + + // property fold.comment + // This option enables folding multi-line comments and explicit fold points when using the C++ lexer. + // Explicit fold points allows adding extra folding by placing a //{ comment at the start and a //} + // at the end of a section that should fold. + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + + // property fold.preprocessor + // This option enables folding preprocessor directives when using the C++ lexer. + // Includes C#'s explicit #region and #endregion folding directives. + bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; + + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + + // property fold.at.else + // This option enables C++ folding on a "} else {" line of an if statement. + bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_C_COMMENTLINEDOC)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_C_COMMENTLINEDOC) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (foldComment && (style == SCE_C_COMMENTLINE)) { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelNext++; + } else if (chNext2 == '}') { + levelNext--; + } + } + } + if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { + if (ch == '#') { + unsigned int j = i + 1; + while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { + j++; + } + if (styler.Match(j, "region") || styler.Match(j, "if")) { + levelNext++; + } else if (styler.Match(j, "end")) { + levelNext--; + } + } + } + if (style == SCE_C_OPERATOR) { + if (ch == '{') { + // Measure the minimum before a '{' to allow + // folding on "} else {" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + if (!IsASpace(ch)) + visibleChars++; + if (atEOL || (i == endPos-1)) { + int levelUse = levelCurrent; + if (foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + if (atEOL && (i == static_cast(styler.Length()-1))) { + // There is an empty line at end of file so give it same level and empty + styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); + } + visibleChars = 0; + } + } +} + +static const char *const cppWordLists[] = { + "Primary keywords and identifiers", + "Secondary keywords and identifiers", + "Documentation comment keywords", + "Unused", + "Global classes and typedefs", + 0, +}; + +static void ColouriseCppDocSensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + ColouriseCppDoc(startPos, length, initStyle, keywordlists, styler, true); +} + +static void ColouriseCppDocInsensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + ColouriseCppDoc(startPos, length, initStyle, keywordlists, styler, false); +} + +LexerModule lmCPP(SCLEX_CPP, ColouriseCppDocSensitive, "cpp", FoldCppDoc, cppWordLists); +LexerModule lmCPPNoCase(SCLEX_CPPNOCASE, ColouriseCppDocInsensitive, "cppnocase", FoldCppDoc, cppWordLists); diff --git a/lexers/LexCSS.cxx b/lexers/LexCSS.cxx new file mode 100644 index 000000000..f63103de3 --- /dev/null +++ b/lexers/LexCSS.cxx @@ -0,0 +1,371 @@ +// Scintilla source code edit control +/** @file LexCSS.cxx + ** Lexer for Cascading Style Sheets + ** Written by Jakub Vrána + ** Improved by Philippe Lhoste (CSS2) + **/ +// Copyright 1998-2002 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + + +static inline bool IsAWordChar(const unsigned int ch) { + /* FIXME: + * The CSS spec allows "ISO 10646 characters U+00A1 and higher" to be treated as word chars. + * Unfortunately, we are only getting string bytes here, and not full unicode characters. We cannot guarantee + * that our byte is between U+0080 - U+00A0 (to return false), so we have to allow all characters U+0080 and higher + */ + return ch >= 0x80 || isalnum(ch) || ch == '-' || ch == '_'; +} + +inline bool IsCssOperator(const int ch) { + if (!((ch < 0x80) && isalnum(ch)) && + (ch == '{' || ch == '}' || ch == ':' || ch == ',' || ch == ';' || + ch == '.' || ch == '#' || ch == '!' || ch == '@' || + /* CSS2 */ + ch == '*' || ch == '>' || ch == '+' || ch == '=' || ch == '~' || ch == '|' || + ch == '[' || ch == ']' || ch == '(' || ch == ')')) { + return true; + } + return false; +} + +static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { + WordList &css1Props = *keywordlists[0]; + WordList &pseudoClasses = *keywordlists[1]; + WordList &css2Props = *keywordlists[2]; + WordList &css3Props = *keywordlists[3]; + WordList &pseudoElements = *keywordlists[4]; + WordList &exProps = *keywordlists[5]; + WordList &exPseudoClasses = *keywordlists[6]; + WordList &exPseudoElements = *keywordlists[7]; + + StyleContext sc(startPos, length, initStyle, styler); + + int lastState = -1; // before operator + int lastStateC = -1; // before comment + int lastStateS = -1; // before single-quoted/double-quoted string + int op = ' '; // last operator + int opPrev = ' '; // last operator + + for (; sc.More(); sc.Forward()) { + if (sc.state == SCE_CSS_COMMENT && sc.Match('*', '/')) { + if (lastStateC == -1) { + // backtrack to get last state: + // comments are like whitespace, so we must return to the previous state + unsigned int i = startPos; + for (; i > 0; i--) { + if ((lastStateC = styler.StyleAt(i-1)) != SCE_CSS_COMMENT) { + if (lastStateC == SCE_CSS_OPERATOR) { + op = styler.SafeGetCharAt(i-1); + opPrev = styler.SafeGetCharAt(i-2); + while (--i) { + lastState = styler.StyleAt(i-1); + if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT) + break; + } + if (i == 0) + lastState = SCE_CSS_DEFAULT; + } + break; + } + } + if (i == 0) + lastStateC = SCE_CSS_DEFAULT; + } + sc.Forward(); + sc.ForwardSetState(lastStateC); + } + + if (sc.state == SCE_CSS_COMMENT) + continue; + + if (sc.state == SCE_CSS_DOUBLESTRING || sc.state == SCE_CSS_SINGLESTRING) { + if (sc.ch != (sc.state == SCE_CSS_DOUBLESTRING ? '\"' : '\'')) + continue; + unsigned int i = sc.currentPos; + while (i && styler[i-1] == '\\') + i--; + if ((sc.currentPos - i) % 2 == 1) + continue; + sc.ForwardSetState(lastStateS); + } + + if (sc.state == SCE_CSS_OPERATOR) { + if (op == ' ') { + unsigned int i = startPos; + op = styler.SafeGetCharAt(i-1); + opPrev = styler.SafeGetCharAt(i-2); + while (--i) { + lastState = styler.StyleAt(i-1); + if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT) + break; + } + } + switch (op) { + case '@': + if (lastState == SCE_CSS_DEFAULT) + sc.SetState(SCE_CSS_DIRECTIVE); + break; + case '>': + case '+': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) + sc.SetState(SCE_CSS_DEFAULT); + break; + case '[': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) + sc.SetState(SCE_CSS_ATTRIBUTE); + break; + case ']': + if (lastState == SCE_CSS_ATTRIBUTE) + sc.SetState(SCE_CSS_TAG); + break; + case '{': + if (lastState == SCE_CSS_MEDIA) + sc.SetState(SCE_CSS_DEFAULT); + else if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DIRECTIVE) + sc.SetState(SCE_CSS_IDENTIFIER); + break; + case '}': + if (lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT || + lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2 || lastState == SCE_CSS_IDENTIFIER3) + sc.SetState(SCE_CSS_DEFAULT); + break; + case '(': + if (lastState == SCE_CSS_PSEUDOCLASS) + sc.SetState(SCE_CSS_TAG); + else if (lastState == SCE_CSS_EXTENDED_PSEUDOCLASS) + sc.SetState(SCE_CSS_EXTENDED_PSEUDOCLASS); + break; + case ')': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS || + lastState == SCE_CSS_PSEUDOELEMENT || lastState == SCE_CSS_EXTENDED_PSEUDOELEMENT) + sc.SetState(SCE_CSS_TAG); + break; + case ':': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS || + lastState == SCE_CSS_PSEUDOELEMENT || lastState == SCE_CSS_EXTENDED_PSEUDOELEMENT) + sc.SetState(SCE_CSS_PSEUDOCLASS); + else if (lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2 || + lastState == SCE_CSS_IDENTIFIER3 || lastState == SCE_CSS_EXTENDED_IDENTIFIER || + lastState == SCE_CSS_UNKNOWN_IDENTIFIER) + sc.SetState(SCE_CSS_VALUE); + break; + case '.': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) + sc.SetState(SCE_CSS_CLASS); + break; + case '#': + if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || + lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) + sc.SetState(SCE_CSS_ID); + break; + case ',': + case '|': + case '~': + if (lastState == SCE_CSS_TAG) + sc.SetState(SCE_CSS_DEFAULT); + break; + case ';': + if (lastState == SCE_CSS_DIRECTIVE) + sc.SetState(SCE_CSS_DEFAULT); + else if (lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT) + sc.SetState(SCE_CSS_IDENTIFIER); + break; + case '!': + if (lastState == SCE_CSS_VALUE) + sc.SetState(SCE_CSS_IMPORTANT); + break; + } + } + + if (IsAWordChar(sc.ch)) { + if (sc.state == SCE_CSS_DEFAULT) + sc.SetState(SCE_CSS_TAG); + continue; + } + + if (sc.ch == '*' && sc.state == SCE_CSS_DEFAULT) { + sc.SetState(SCE_CSS_TAG); + continue; + } + + if (IsAWordChar(sc.chPrev) && ( + sc.state == SCE_CSS_IDENTIFIER || sc.state == SCE_CSS_IDENTIFIER2 || + sc.state == SCE_CSS_IDENTIFIER3 || sc.state == SCE_CSS_EXTENDED_IDENTIFIER || + sc.state == SCE_CSS_UNKNOWN_IDENTIFIER || + sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT || + sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT || + sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS || + sc.state == SCE_CSS_IMPORTANT || + sc.state == SCE_CSS_DIRECTIVE + )) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + char *s2 = s; + while (*s2 && !IsAWordChar(*s2)) + s2++; + switch (sc.state) { + case SCE_CSS_IDENTIFIER: + case SCE_CSS_IDENTIFIER2: + case SCE_CSS_IDENTIFIER3: + case SCE_CSS_EXTENDED_IDENTIFIER: + case SCE_CSS_UNKNOWN_IDENTIFIER: + if (css1Props.InList(s2)) + sc.ChangeState(SCE_CSS_IDENTIFIER); + else if (css2Props.InList(s2)) + sc.ChangeState(SCE_CSS_IDENTIFIER2); + else if (css3Props.InList(s2)) + sc.ChangeState(SCE_CSS_IDENTIFIER3); + else if (exProps.InList(s2)) + sc.ChangeState(SCE_CSS_EXTENDED_IDENTIFIER); + else + sc.ChangeState(SCE_CSS_UNKNOWN_IDENTIFIER); + break; + case SCE_CSS_PSEUDOCLASS: + case SCE_CSS_PSEUDOELEMENT: + case SCE_CSS_EXTENDED_PSEUDOCLASS: + case SCE_CSS_EXTENDED_PSEUDOELEMENT: + case SCE_CSS_UNKNOWN_PSEUDOCLASS: + if (op == ':' && opPrev != ':' && pseudoClasses.InList(s2)) + sc.ChangeState(SCE_CSS_PSEUDOCLASS); + else if (opPrev == ':' && pseudoElements.InList(s2)) + sc.ChangeState(SCE_CSS_PSEUDOELEMENT); + else if ((op == ':' || (op == '(' && lastState == SCE_CSS_EXTENDED_PSEUDOCLASS)) && opPrev != ':' && exPseudoClasses.InList(s2)) + sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOCLASS); + else if (opPrev == ':' && exPseudoElements.InList(s2)) + sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOELEMENT); + else + sc.ChangeState(SCE_CSS_UNKNOWN_PSEUDOCLASS); + break; + case SCE_CSS_IMPORTANT: + if (strcmp(s2, "important") != 0) + sc.ChangeState(SCE_CSS_VALUE); + break; + case SCE_CSS_DIRECTIVE: + if (op == '@' && strcmp(s2, "media") == 0) + sc.ChangeState(SCE_CSS_MEDIA); + break; + } + } + + if (sc.ch != '.' && sc.ch != ':' && sc.ch != '#' && ( + sc.state == SCE_CSS_CLASS || sc.state == SCE_CSS_ID || + (sc.ch != '(' && sc.ch != ')' && ( /* This line of the condition makes it possible to extend pseudo-classes with parentheses */ + sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT || + sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT || + sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS + )) + )) + sc.SetState(SCE_CSS_TAG); + + if (sc.Match('/', '*')) { + lastStateC = sc.state; + sc.SetState(SCE_CSS_COMMENT); + sc.Forward(); + } else if ((sc.state == SCE_CSS_VALUE || sc.state == SCE_CSS_ATTRIBUTE) + && (sc.ch == '\"' || sc.ch == '\'')) { + lastStateS = sc.state; + sc.SetState((sc.ch == '\"' ? SCE_CSS_DOUBLESTRING : SCE_CSS_SINGLESTRING)); + } else if (IsCssOperator(sc.ch) + && (sc.state != SCE_CSS_ATTRIBUTE || sc.ch == ']') + && (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!') + && ((sc.state != SCE_CSS_DIRECTIVE && sc.state != SCE_CSS_MEDIA) || sc.ch == ';' || sc.ch == '{') + ) { + if (sc.state != SCE_CSS_OPERATOR) + lastState = sc.state; + sc.SetState(SCE_CSS_OPERATOR); + op = sc.ch; + opPrev = sc.chPrev; + } + } + + sc.Complete(); +} + +static void FoldCSSDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + bool inComment = (styler.StyleAt(startPos-1) == SCE_CSS_COMMENT); + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styler.StyleAt(i); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment) { + if (!inComment && (style == SCE_CSS_COMMENT)) + levelCurrent++; + else if (inComment && (style != SCE_CSS_COMMENT)) + levelCurrent--; + inComment = (style == SCE_CSS_COMMENT); + } + if (style == SCE_CSS_OPERATOR) { + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const cssWordListDesc[] = { + "CSS1 Properties", + "Pseudo-classes", + "CSS2 Properties", + "CSS3 Properties", + "Pseudo-elements", + "Browser-Specific CSS Properties", + "Browser-Specific Pseudo-classes", + "Browser-Specific Pseudo-elements", + 0 +}; + +LexerModule lmCss(SCLEX_CSS, ColouriseCssDoc, "css", FoldCSSDoc, cssWordListDesc); diff --git a/lexers/LexCaml.cxx b/lexers/LexCaml.cxx new file mode 100644 index 000000000..ca1b65f38 --- /dev/null +++ b/lexers/LexCaml.cxx @@ -0,0 +1,449 @@ +// Scintilla source code edit control +/** @file LexCaml.cxx + ** Lexer for Objective Caml. + **/ +// Copyright 2005-2009 by Robert Roessler +// The License.txt file describes the conditions under which this software may be distributed. +/* Release History + 20050204 Initial release. + 20050205 Quick compiler standards/"cleanliness" adjustment. + 20050206 Added cast for IsLeadByte(). + 20050209 Changes to "external" build support. + 20050306 Fix for 1st-char-in-doc "corner" case. + 20050502 Fix for [harmless] one-past-the-end coloring. + 20050515 Refined numeric token recognition logic. + 20051125 Added 2nd "optional" keywords class. + 20051129 Support "magic" (read-only) comments for RCaml. + 20051204 Swtich to using StyleContext infrastructure. + 20090629 Add full Standard ML '97 support. +*/ + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "PropSetSimple.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +// Since the Microsoft __iscsym[f] funcs are not ANSI... +inline int iscaml(int c) {return isalnum(c) || c == '_';} +inline int iscamlf(int c) {return isalpha(c) || c == '_';} + +static const int baseT[24] = { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A - L */ + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,16 /* M - X */ +}; + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#ifdef BUILD_AS_EXTERNAL_LEXER +/* + (actually seems to work!) +*/ +#include "WindowAccessor.h" +#include "ExternalLexer.h" + +#if PLAT_WIN +#include +#endif + +static void ColouriseCamlDoc( + unsigned int startPos, int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler); + +static void FoldCamlDoc( + unsigned int startPos, int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler); + +static void InternalLexOrFold(int lexOrFold, unsigned int startPos, int length, + int initStyle, char *words[], WindowID window, char *props); + +static const char* LexerName = "caml"; + +#ifdef TRACE +void Platform::DebugPrintf(const char *format, ...) { + char buffer[2000]; + va_list pArguments; + va_start(pArguments, format); + vsprintf(buffer,format,pArguments); + va_end(pArguments); + Platform::DebugDisplay(buffer); +} +#else +void Platform::DebugPrintf(const char *, ...) { +} +#endif + +bool Platform::IsDBCSLeadByte(int codePage, char ch) { + return ::IsDBCSLeadByteEx(codePage, ch) != 0; +} + +long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam, long lParam) { + return ::SendMessage(reinterpret_cast(w), msg, wParam, lParam); +} + +long Platform::SendScintillaPointer(WindowID w, unsigned int msg, unsigned long wParam, void *lParam) { + return ::SendMessage(reinterpret_cast(w), msg, wParam, + reinterpret_cast(lParam)); +} + +void EXT_LEXER_DECL Fold(unsigned int lexer, unsigned int startPos, int length, + int initStyle, char *words[], WindowID window, char *props) +{ + // below useless evaluation(s) to supress "not used" warnings + lexer; + // build expected data structures and do the Fold + InternalLexOrFold(1, startPos, length, initStyle, words, window, props); + +} + +int EXT_LEXER_DECL GetLexerCount() +{ + return 1; // just us [Objective] Caml lexers here! +} + +void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength) +{ + // below useless evaluation(s) to supress "not used" warnings + Index; + // return as much of our lexer name as will fit (what's up with Index?) + if (buflength > 0) { + buflength--; + int n = strlen(LexerName); + if (n > buflength) + n = buflength; + memcpy(name, LexerName, n), name[n] = '\0'; + } +} + +void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, + int initStyle, char *words[], WindowID window, char *props) +{ + // below useless evaluation(s) to supress "not used" warnings + lexer; + // build expected data structures and do the Lex + InternalLexOrFold(0, startPos, length, initStyle, words, window, props); +} + +static void InternalLexOrFold(int foldOrLex, unsigned int startPos, int length, + int initStyle, char *words[], WindowID window, char *props) +{ + // create and initialize a WindowAccessor (including contained PropSet) + PropSetSimple ps; + ps.SetMultiple(props); + WindowAccessor wa(window, ps); + // create and initialize WordList(s) + int nWL = 0; + for (; words[nWL]; nWL++) ; // count # of WordList PTRs needed + WordList** wl = new WordList* [nWL + 1];// alloc WordList PTRs + int i = 0; + for (; i < nWL; i++) { + wl[i] = new WordList(); // (works or THROWS bad_alloc EXCEPTION) + wl[i]->Set(words[i]); + } + wl[i] = 0; + // call our "internal" folder/lexer (... then do Flush!) + if (foldOrLex) + FoldCamlDoc(startPos, length, initStyle, wl, wa); + else + ColouriseCamlDoc(startPos, length, initStyle, wl, wa); + wa.Flush(); + // clean up before leaving + for (i = nWL - 1; i >= 0; i--) + delete wl[i]; + delete [] wl; +} + +static +#endif /* BUILD_AS_EXTERNAL_LEXER */ + +void ColouriseCamlDoc( + unsigned int startPos, int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) +{ + // initialize styler + StyleContext sc(startPos, length, initStyle, styler); + + int chBase = 0, chToken = 0, chLit = 0; + WordList& keywords = *keywordlists[0]; + WordList& keywords2 = *keywordlists[1]; + WordList& keywords3 = *keywordlists[2]; + const bool isSML = keywords.InList("andalso"); + const int useMagic = styler.GetPropertyInt("lexer.caml.magic", 0); + + // set up [initial] state info (terminating states that shouldn't "bleed") + const int state_ = sc.state & 0x0f; + if (state_ <= SCE_CAML_CHAR + || (isSML && state_ == SCE_CAML_STRING)) + sc.state = SCE_CAML_DEFAULT; + int nesting = (state_ >= SCE_CAML_COMMENT)? (state_ - SCE_CAML_COMMENT): 0; + + // foreach char in range... + while (sc.More()) { + // set up [per-char] state info + int state2 = -1; // (ASSUME no state change) + int chColor = sc.currentPos - 1;// (ASSUME standard coloring range) + bool advance = true; // (ASSUME scanner "eats" 1 char) + + // step state machine + switch (sc.state & 0x0f) { + case SCE_CAML_DEFAULT: + chToken = sc.currentPos; // save [possible] token start (JIC) + // it's wide open; what do we have? + if (iscamlf(sc.ch)) + state2 = SCE_CAML_IDENTIFIER; + else if (!isSML && sc.Match('`') && iscamlf(sc.chNext)) + state2 = SCE_CAML_TAGNAME; + else if (!isSML && sc.Match('#') && isdigit(sc.chNext)) + state2 = SCE_CAML_LINENUM; + else if (isdigit(sc.ch)) { + // it's a number, assume base 10 + state2 = SCE_CAML_NUMBER, chBase = 10; + if (sc.Match('0')) { + // there MAY be a base specified... + const char* baseC = "bBoOxX"; + if (isSML) { + if (sc.chNext == 'w') + sc.Forward(); // (consume SML "word" indicator) + baseC = "x"; + } + // ... change to specified base AS REQUIRED + if (strchr(baseC, sc.chNext)) + chBase = baseT[tolower(sc.chNext) - 'a'], sc.Forward(); + } + } else if (!isSML && sc.Match('\'')) // (Caml char literal?) + state2 = SCE_CAML_CHAR, chLit = 0; + else if (isSML && sc.Match('#', '"')) // (SML char literal?) + state2 = SCE_CAML_CHAR, sc.Forward(); + else if (sc.Match('"')) + state2 = SCE_CAML_STRING; + else if (sc.Match('(', '*')) + state2 = SCE_CAML_COMMENT, sc.Forward(), sc.ch = ' '; // (*)... + else if (strchr("!?~" /* Caml "prefix-symbol" */ + "=<>@^|&+-*/$%" /* Caml "infix-symbol" */ + "()[]{};,:.#", sc.ch) // Caml "bracket" or ;,:.# + // SML "extra" ident chars + || (isSML && (sc.Match('\\') || sc.Match('`')))) + state2 = SCE_CAML_OPERATOR; + break; + + case SCE_CAML_IDENTIFIER: + // [try to] interpret as [additional] identifier char + if (!(iscaml(sc.ch) || sc.Match('\''))) { + const int n = sc.currentPos - chToken; + if (n < 24) { + // length is believable as keyword, [re-]construct token + char t[24]; + for (int i = -n; i < 0; i++) + t[n + i] = static_cast(sc.GetRelative(i)); + t[n] = '\0'; + // special-case "_" token as KEYWORD + if ((n == 1 && sc.chPrev == '_') || keywords.InList(t)) + sc.ChangeState(SCE_CAML_KEYWORD); + else if (keywords2.InList(t)) + sc.ChangeState(SCE_CAML_KEYWORD2); + else if (keywords3.InList(t)) + sc.ChangeState(SCE_CAML_KEYWORD3); + } + state2 = SCE_CAML_DEFAULT, advance = false; + } + break; + + case SCE_CAML_TAGNAME: + // [try to] interpret as [additional] tagname char + if (!(iscaml(sc.ch) || sc.Match('\''))) + state2 = SCE_CAML_DEFAULT, advance = false; + break; + + /*case SCE_CAML_KEYWORD: + case SCE_CAML_KEYWORD2: + case SCE_CAML_KEYWORD3: + // [try to] interpret as [additional] keyword char + if (!iscaml(ch)) + state2 = SCE_CAML_DEFAULT, advance = false; + break;*/ + + case SCE_CAML_LINENUM: + // [try to] interpret as [additional] linenum directive char + if (!isdigit(sc.ch)) + state2 = SCE_CAML_DEFAULT, advance = false; + break; + + case SCE_CAML_OPERATOR: { + // [try to] interpret as [additional] operator char + const char* o = 0; + if (iscaml(sc.ch) || isspace(sc.ch) // ident or whitespace + || (o = strchr(")]};,\'\"#", sc.ch),o) // "termination" chars + || (!isSML && sc.Match('`')) // Caml extra term char + || (!strchr("!$%&*+-./:<=>?@^|~", sc.ch)// "operator" chars + // SML extra ident chars + && !(isSML && (sc.Match('\\') || sc.Match('`'))))) { + // check for INCLUSIVE termination + if (o && strchr(")]};,", sc.ch)) { + if ((sc.Match(')') && sc.chPrev == '(') + || (sc.Match(']') && sc.chPrev == '[')) + // special-case "()" and "[]" tokens as KEYWORDS + sc.ChangeState(SCE_CAML_KEYWORD); + chColor++; + } else + advance = false; + state2 = SCE_CAML_DEFAULT; + } + break; + } + + case SCE_CAML_NUMBER: + // [try to] interpret as [additional] numeric literal char + if ((!isSML && sc.Match('_')) || IsADigit(sc.ch, chBase)) + break; + // how about an integer suffix? + if (!isSML && (sc.Match('l') || sc.Match('L') || sc.Match('n')) + && (sc.chPrev == '_' || IsADigit(sc.chPrev, chBase))) + break; + // or a floating-point literal? + if (chBase == 10) { + // with a decimal point? + if (sc.Match('.') + && ((!isSML && sc.chPrev == '_') + || IsADigit(sc.chPrev, chBase))) + break; + // with an exponent? (I) + if ((sc.Match('e') || sc.Match('E')) + && ((!isSML && (sc.chPrev == '.' || sc.chPrev == '_')) + || IsADigit(sc.chPrev, chBase))) + break; + // with an exponent? (II) + if (((!isSML && (sc.Match('+') || sc.Match('-'))) + || (isSML && sc.Match('~'))) + && (sc.chPrev == 'e' || sc.chPrev == 'E')) + break; + } + // it looks like we have run out of number + state2 = SCE_CAML_DEFAULT, advance = false; + break; + + case SCE_CAML_CHAR: + if (!isSML) { + // [try to] interpret as [additional] char literal char + if (sc.Match('\\')) { + chLit = 1; // (definitely IS a char literal) + if (sc.chPrev == '\\') + sc.ch = ' '; // (...\\') + // should we be terminating - one way or another? + } else if ((sc.Match('\'') && sc.chPrev != '\\') + || sc.atLineEnd) { + state2 = SCE_CAML_DEFAULT; + if (sc.Match('\'')) + chColor++; + else + sc.ChangeState(SCE_CAML_IDENTIFIER); + // ... maybe a char literal, maybe not + } else if (chLit < 1 && sc.currentPos - chToken >= 2) + sc.ChangeState(SCE_CAML_IDENTIFIER), advance = false; + break; + }/* else + // fall through for SML char literal (handle like string) */ + + case SCE_CAML_STRING: + // [try to] interpret as [additional] [SML char/] string literal char + if (isSML && sc.Match('\\') && sc.chPrev != '\\' && isspace(sc.chNext)) + state2 = SCE_CAML_WHITE; + else if (sc.Match('\\') && sc.chPrev == '\\') + sc.ch = ' '; // (...\\") + // should we be terminating - one way or another? + else if ((sc.Match('"') && sc.chPrev != '\\') + || (isSML && sc.atLineEnd)) { + state2 = SCE_CAML_DEFAULT; + if (sc.Match('"')) + chColor++; + } + break; + + case SCE_CAML_WHITE: + // [try to] interpret as [additional] SML embedded whitespace char + if (sc.Match('\\')) { + // style this puppy NOW... + state2 = SCE_CAML_STRING, sc.ch = ' ' /* (...\") */, chColor++, + styler.ColourTo(chColor, SCE_CAML_WHITE), styler.Flush(); + // ... then backtrack to determine original SML literal type + int p = chColor - 2; + for (; p >= 0 && styler.StyleAt(p) == SCE_CAML_WHITE; p--) ; + if (p >= 0) + state2 = static_cast(styler.StyleAt(p)); + // take care of state change NOW + sc.ChangeState(state2), state2 = -1; + } + break; + + case SCE_CAML_COMMENT: + case SCE_CAML_COMMENT1: + case SCE_CAML_COMMENT2: + case SCE_CAML_COMMENT3: + // we're IN a comment - does this start a NESTED comment? + if (sc.Match('(', '*')) + state2 = sc.state + 1, chToken = sc.currentPos, + sc.Forward(), sc.ch = ' ' /* (*)... */, nesting++; + // [try to] interpret as [additional] comment char + else if (sc.Match(')') && sc.chPrev == '*') { + if (nesting) + state2 = (sc.state & 0x0f) - 1, chToken = 0, nesting--; + else + state2 = SCE_CAML_DEFAULT; + chColor++; + // enable "magic" (read-only) comment AS REQUIRED + } else if (useMagic && sc.currentPos - chToken == 4 + && sc.Match('c') && sc.chPrev == 'r' && sc.GetRelative(-2) == '@') + sc.state |= 0x10; // (switch to read-only comment style) + break; + } + + // handle state change and char coloring AS REQUIRED + if (state2 >= 0) + styler.ColourTo(chColor, sc.state), sc.ChangeState(state2); + // move to next char UNLESS re-scanning current char + if (advance) + sc.Forward(); + } + + // do any required terminal char coloring (JIC) + sc.Complete(); +} + +#ifdef BUILD_AS_EXTERNAL_LEXER +static +#endif /* BUILD_AS_EXTERNAL_LEXER */ +void FoldCamlDoc( + unsigned int, int, + int, + WordList *[], + Accessor &) +{ +} + +static const char * const camlWordListDesc[] = { + "Keywords", // primary Objective Caml keywords + "Keywords2", // "optional" keywords (typically from Pervasives) + "Keywords3", // "optional" keywords (typically typenames) + 0 +}; + +#ifndef BUILD_AS_EXTERNAL_LEXER +LexerModule lmCaml(SCLEX_CAML, ColouriseCamlDoc, "caml", FoldCamlDoc, camlWordListDesc); +#endif /* BUILD_AS_EXTERNAL_LEXER */ diff --git a/lexers/LexCmake.cxx b/lexers/LexCmake.cxx new file mode 100644 index 000000000..1f51f474e --- /dev/null +++ b/lexers/LexCmake.cxx @@ -0,0 +1,457 @@ +// Scintilla source code edit control +/** @file LexCmake.cxx + ** Lexer for Cmake + **/ +// Copyright 2007 by Cristian Adam +// based on the NSIS lexer +// The License.txt file describes the conditions under which this software may be distributed. +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "CharClassify.h" +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static bool isCmakeNumber(char ch) +{ + return(ch >= '0' && ch <= '9'); +} + +static bool isCmakeChar(char ch) +{ + return(ch == '.' ) || (ch == '_' ) || isCmakeNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); +} + +static bool isCmakeLetter(char ch) +{ + return(ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); +} + +static bool CmakeNextLineHasElse(unsigned int start, unsigned int end, Accessor &styler) +{ + int nNextLine = -1; + for ( unsigned int i = start; i < end; i++ ) { + char cNext = styler.SafeGetCharAt( i ); + if ( cNext == '\n' ) { + nNextLine = i+1; + break; + } + } + + if ( nNextLine == -1 ) // We never foudn the next line... + return false; + + for ( unsigned int firstChar = nNextLine; firstChar < end; firstChar++ ) { + char cNext = styler.SafeGetCharAt( firstChar ); + if ( cNext == ' ' ) + continue; + if ( cNext == '\t' ) + continue; + if ( styler.Match(firstChar, "ELSE") || styler.Match(firstChar, "else")) + return true; + break; + } + + return false; +} + +static int calculateFoldCmake(unsigned int start, unsigned int end, int foldlevel, Accessor &styler, bool bElse) +{ + // If the word is too long, it is not what we are looking for + if ( end - start > 20 ) + return foldlevel; + + int newFoldlevel = foldlevel; + + char s[20]; // The key word we are looking for has atmost 13 characters + for (unsigned int i = 0; i < end - start + 1 && i < 19; i++) { + s[i] = static_cast( styler[ start + i ] ); + s[i + 1] = '\0'; + } + + if ( CompareCaseInsensitive(s, "IF") == 0 || CompareCaseInsensitive(s, "WHILE") == 0 + || CompareCaseInsensitive(s, "MACRO") == 0 || CompareCaseInsensitive(s, "FOREACH") == 0 + || CompareCaseInsensitive(s, "ELSEIF") == 0 ) + newFoldlevel++; + else if ( CompareCaseInsensitive(s, "ENDIF") == 0 || CompareCaseInsensitive(s, "ENDWHILE") == 0 + || CompareCaseInsensitive(s, "ENDMACRO") == 0 || CompareCaseInsensitive(s, "ENDFOREACH") == 0) + newFoldlevel--; + else if ( bElse && CompareCaseInsensitive(s, "ELSEIF") == 0 ) + newFoldlevel++; + else if ( bElse && CompareCaseInsensitive(s, "ELSE") == 0 ) + newFoldlevel++; + + return newFoldlevel; +} + +static int classifyWordCmake(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler ) +{ + char word[100] = {0}; + char lowercaseWord[100] = {0}; + + WordList &Commands = *keywordLists[0]; + WordList &Parameters = *keywordLists[1]; + WordList &UserDefined = *keywordLists[2]; + + for (unsigned int i = 0; i < end - start + 1 && i < 99; i++) { + word[i] = static_cast( styler[ start + i ] ); + lowercaseWord[i] = static_cast(tolower(word[i])); + } + + // Check for special words... + if ( CompareCaseInsensitive(word, "MACRO") == 0 || CompareCaseInsensitive(word, "ENDMACRO") == 0 ) + return SCE_CMAKE_MACRODEF; + + if ( CompareCaseInsensitive(word, "IF") == 0 || CompareCaseInsensitive(word, "ENDIF") == 0 ) + return SCE_CMAKE_IFDEFINEDEF; + + if ( CompareCaseInsensitive(word, "ELSEIF") == 0 || CompareCaseInsensitive(word, "ELSE") == 0 ) + return SCE_CMAKE_IFDEFINEDEF; + + if ( CompareCaseInsensitive(word, "WHILE") == 0 || CompareCaseInsensitive(word, "ENDWHILE") == 0) + return SCE_CMAKE_WHILEDEF; + + if ( CompareCaseInsensitive(word, "FOREACH") == 0 || CompareCaseInsensitive(word, "ENDFOREACH") == 0) + return SCE_CMAKE_FOREACHDEF; + + if ( Commands.InList(lowercaseWord) ) + return SCE_CMAKE_COMMANDS; + + if ( Parameters.InList(word) ) + return SCE_CMAKE_PARAMETERS; + + + if ( UserDefined.InList(word) ) + return SCE_CMAKE_USERDEFINED; + + if ( strlen(word) > 3 ) { + if ( word[1] == '{' && word[strlen(word)-1] == '}' ) + return SCE_CMAKE_VARIABLE; + } + + // To check for numbers + if ( isCmakeNumber( word[0] ) ) { + bool bHasSimpleCmakeNumber = true; + for (unsigned int j = 1; j < end - start + 1 && j < 99; j++) { + if ( !isCmakeNumber( word[j] ) ) { + bHasSimpleCmakeNumber = false; + break; + } + } + + if ( bHasSimpleCmakeNumber ) + return SCE_CMAKE_NUMBER; + } + + return SCE_CMAKE_DEFAULT; +} + +static void ColouriseCmakeDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) +{ + int state = SCE_CMAKE_DEFAULT; + if ( startPos > 0 ) + state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox + + styler.StartAt( startPos ); + styler.GetLine( startPos ); + + unsigned int nLengthDoc = startPos + length; + styler.StartSegment( startPos ); + + char cCurrChar; + bool bVarInString = false; + bool bClassicVarInString = false; + + unsigned int i; + for ( i = startPos; i < nLengthDoc; i++ ) { + cCurrChar = styler.SafeGetCharAt( i ); + char cNextChar = styler.SafeGetCharAt(i+1); + + switch (state) { + case SCE_CMAKE_DEFAULT: + if ( cCurrChar == '#' ) { // we have a comment line + styler.ColourTo(i-1, state ); + state = SCE_CMAKE_COMMENT; + break; + } + if ( cCurrChar == '"' ) { + styler.ColourTo(i-1, state ); + state = SCE_CMAKE_STRINGDQ; + bVarInString = false; + bClassicVarInString = false; + break; + } + if ( cCurrChar == '\'' ) { + styler.ColourTo(i-1, state ); + state = SCE_CMAKE_STRINGRQ; + bVarInString = false; + bClassicVarInString = false; + break; + } + if ( cCurrChar == '`' ) { + styler.ColourTo(i-1, state ); + state = SCE_CMAKE_STRINGLQ; + bVarInString = false; + bClassicVarInString = false; + break; + } + + // CMake Variable + if ( cCurrChar == '$' || isCmakeChar(cCurrChar)) { + styler.ColourTo(i-1,state); + state = SCE_CMAKE_VARIABLE; + + // If it is a number, we must check and set style here first... + if ( isCmakeNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) ) + styler.ColourTo( i, SCE_CMAKE_NUMBER); + + break; + } + + break; + case SCE_CMAKE_COMMENT: + if ( cNextChar == '\n' || cNextChar == '\r' ) { + // Special case: + if ( cCurrChar == '\\' ) { + styler.ColourTo(i-2,state); + styler.ColourTo(i,SCE_CMAKE_DEFAULT); + } + else { + styler.ColourTo(i,state); + state = SCE_CMAKE_DEFAULT; + } + } + break; + case SCE_CMAKE_STRINGDQ: + case SCE_CMAKE_STRINGLQ: + case SCE_CMAKE_STRINGRQ: + + if ( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' ) + break; // Ignore the next character, even if it is a quote of some sort + + if ( cCurrChar == '"' && state == SCE_CMAKE_STRINGDQ ) { + styler.ColourTo(i,state); + state = SCE_CMAKE_DEFAULT; + break; + } + + if ( cCurrChar == '`' && state == SCE_CMAKE_STRINGLQ ) { + styler.ColourTo(i,state); + state = SCE_CMAKE_DEFAULT; + break; + } + + if ( cCurrChar == '\'' && state == SCE_CMAKE_STRINGRQ ) { + styler.ColourTo(i,state); + state = SCE_CMAKE_DEFAULT; + break; + } + + if ( cNextChar == '\r' || cNextChar == '\n' ) { + int nCurLine = styler.GetLine(i+1); + int nBack = i; + // We need to check if the previous line has a \ in it... + bool bNextLine = false; + + while ( nBack > 0 ) { + if ( styler.GetLine(nBack) != nCurLine ) + break; + + char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here + + if ( cTemp == '\\' ) { + bNextLine = true; + break; + } + if ( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' ) + break; + + nBack--; + } + + if ( bNextLine ) { + styler.ColourTo(i+1,state); + } + if ( bNextLine == false ) { + styler.ColourTo(i,state); + state = SCE_CMAKE_DEFAULT; + } + } + break; + + case SCE_CMAKE_VARIABLE: + + // CMake Variable: + if ( cCurrChar == '$' ) + state = SCE_CMAKE_DEFAULT; + else if ( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) ) + state = SCE_CMAKE_DEFAULT; + else if ( (isCmakeChar(cCurrChar) && !isCmakeChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' ) { + state = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler ); + styler.ColourTo( i, state); + state = SCE_CMAKE_DEFAULT; + } + else if ( !isCmakeChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' ) { + if ( classifyWordCmake( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_CMAKE_NUMBER ) + styler.ColourTo( i-1, SCE_CMAKE_NUMBER ); + + state = SCE_CMAKE_DEFAULT; + + if ( cCurrChar == '"' ) { + state = SCE_CMAKE_STRINGDQ; + bVarInString = false; + bClassicVarInString = false; + } + else if ( cCurrChar == '`' ) { + state = SCE_CMAKE_STRINGLQ; + bVarInString = false; + bClassicVarInString = false; + } + else if ( cCurrChar == '\'' ) { + state = SCE_CMAKE_STRINGRQ; + bVarInString = false; + bClassicVarInString = false; + } + else if ( cCurrChar == '#' ) { + state = SCE_CMAKE_COMMENT; + } + } + break; + } + + if ( state == SCE_CMAKE_COMMENT) { + styler.ColourTo(i,state); + } + else if ( state == SCE_CMAKE_STRINGDQ || state == SCE_CMAKE_STRINGLQ || state == SCE_CMAKE_STRINGRQ ) { + bool bIngoreNextDollarSign = false; + + if ( bVarInString && cCurrChar == '$' ) { + bVarInString = false; + bIngoreNextDollarSign = true; + } + else if ( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) ) { + styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR); + bVarInString = false; + bIngoreNextDollarSign = false; + } + + else if ( bVarInString && !isCmakeChar(cNextChar) ) { + int nWordState = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler); + if ( nWordState == SCE_CMAKE_VARIABLE ) + styler.ColourTo( i, SCE_CMAKE_STRINGVAR); + bVarInString = false; + } + // Covers "${TEST}..." + else if ( bClassicVarInString && cNextChar == '}' ) { + styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR); + bClassicVarInString = false; + } + + // Start of var in string + if ( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' ) { + styler.ColourTo( i-1, state); + bClassicVarInString = true; + bVarInString = false; + } + else if ( !bIngoreNextDollarSign && cCurrChar == '$' ) { + styler.ColourTo( i-1, state); + bVarInString = true; + bClassicVarInString = false; + } + } + } + + // Colourise remaining document + styler.ColourTo(nLengthDoc-1,state); +} + +static void FoldCmakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) +{ + // No folding enabled, no reason to continue... + if ( styler.GetPropertyInt("fold") == 0 ) + return; + + bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1; + + int lineCurrent = styler.GetLine(startPos); + unsigned int safeStartPos = styler.LineStart( lineCurrent ); + + bool bArg1 = true; + int nWordStart = -1; + + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelNext = levelCurrent; + + for (unsigned int i = safeStartPos; i < startPos + length; i++) { + char chCurr = styler.SafeGetCharAt(i); + + if ( bArg1 ) { + if ( nWordStart == -1 && (isCmakeLetter(chCurr)) ) { + nWordStart = i; + } + else if ( isCmakeLetter(chCurr) == false && nWordStart > -1 ) { + int newLevel = calculateFoldCmake( nWordStart, i-1, levelNext, styler, foldAtElse); + + if ( newLevel == levelNext ) { + if ( foldAtElse ) { + if ( CmakeNextLineHasElse(i, startPos + length, styler) ) + levelNext--; + } + } + else + levelNext = newLevel; + bArg1 = false; + } + } + + if ( chCurr == '\n' ) { + if ( bArg1 && foldAtElse) { + if ( CmakeNextLineHasElse(i, startPos + length, styler) ) + levelNext--; + } + + // If we are on a new line... + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (levelUse < levelNext ) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) + styler.SetLevel(lineCurrent, lev); + + lineCurrent++; + levelCurrent = levelNext; + bArg1 = true; // New line, lets look at first argument again + nWordStart = -1; + } + } + + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) + styler.SetLevel(lineCurrent, lev); +} + +static const char * const cmakeWordLists[] = { + "Commands", + "Parameters", + "UserDefined", + 0, + 0,}; + +LexerModule lmCmake(SCLEX_CMAKE, ColouriseCmakeDoc, "cmake", FoldCmakeDoc, cmakeWordLists); diff --git a/lexers/LexConf.cxx b/lexers/LexConf.cxx new file mode 100644 index 000000000..7b066af7b --- /dev/null +++ b/lexers/LexConf.cxx @@ -0,0 +1,188 @@ +// Scintilla source code edit control +/** @file LexConf.cxx + ** Lexer for Apache Configuration Files. + ** + ** First working version contributed by Ahmad Zawawi on October 28, 2000. + ** i created this lexer because i needed something pretty when dealing + ** when Apache Configuration files... + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static void ColouriseConfDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) +{ + int state = SCE_CONF_DEFAULT; + char chNext = styler[startPos]; + int lengthDoc = startPos + length; + // create a buffer large enough to take the largest chunk... + char *buffer = new char[length]; + int bufferCount = 0; + + // this assumes that we have 2 keyword list in conf.properties + WordList &directives = *keywordLists[0]; + WordList ¶ms = *keywordLists[1]; + + // go through all provided text segment + // using the hand-written state machine shown below + styler.StartAt(startPos); + styler.StartSegment(startPos); + for (int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + i++; + continue; + } + switch(state) { + case SCE_CONF_DEFAULT: + if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') { + // whitespace is simply ignored here... + styler.ColourTo(i,SCE_CONF_DEFAULT); + break; + } else if( ch == '#' ) { + // signals the start of a comment... + state = SCE_CONF_COMMENT; + styler.ColourTo(i,SCE_CONF_COMMENT); + } else if( ch == '.' /*|| ch == '/'*/) { + // signals the start of a file... + state = SCE_CONF_EXTENSION; + styler.ColourTo(i,SCE_CONF_EXTENSION); + } else if( ch == '"') { + state = SCE_CONF_STRING; + styler.ColourTo(i,SCE_CONF_STRING); + } else if( isascii(ch) && ispunct(ch) ) { + // signals an operator... + // no state jump necessary for this + // simple case... + styler.ColourTo(i,SCE_CONF_OPERATOR); + } else if( isascii(ch) && isalpha(ch) ) { + // signals the start of an identifier + bufferCount = 0; + buffer[bufferCount++] = static_cast(tolower(ch)); + state = SCE_CONF_IDENTIFIER; + } else if( isascii(ch) && isdigit(ch) ) { + // signals the start of a number + bufferCount = 0; + buffer[bufferCount++] = ch; + //styler.ColourTo(i,SCE_CONF_NUMBER); + state = SCE_CONF_NUMBER; + } else { + // style it the default style.. + styler.ColourTo(i,SCE_CONF_DEFAULT); + } + break; + + case SCE_CONF_COMMENT: + // if we find a newline here, + // we simply go to default state + // else continue to work on it... + if( ch == '\n' || ch == '\r' ) { + state = SCE_CONF_DEFAULT; + } else { + styler.ColourTo(i,SCE_CONF_COMMENT); + } + break; + + case SCE_CONF_EXTENSION: + // if we find a non-alphanumeric char, + // we simply go to default state + // else we're still dealing with an extension... + if( (isascii(ch) && isalnum(ch)) || (ch == '_') || + (ch == '-') || (ch == '$') || + (ch == '/') || (ch == '.') || (ch == '*') ) + { + styler.ColourTo(i,SCE_CONF_EXTENSION); + } else { + state = SCE_CONF_DEFAULT; + chNext = styler[i--]; + } + break; + + case SCE_CONF_STRING: + // if we find the end of a string char, we simply go to default state + // else we're still dealing with an string... + if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') || (ch == '\n') || (ch == '\r') ) { + state = SCE_CONF_DEFAULT; + } + styler.ColourTo(i,SCE_CONF_STRING); + break; + + case SCE_CONF_IDENTIFIER: + // stay in CONF_IDENTIFIER state until we find a non-alphanumeric + if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') || (ch == '$') || (ch == '.') || (ch == '*')) { + buffer[bufferCount++] = static_cast(tolower(ch)); + } else { + state = SCE_CONF_DEFAULT; + buffer[bufferCount] = '\0'; + + // check if the buffer contains a keyword, and highlight it if it is a keyword... + if(directives.InList(buffer)) { + styler.ColourTo(i-1,SCE_CONF_DIRECTIVE ); + } else if(params.InList(buffer)) { + styler.ColourTo(i-1,SCE_CONF_PARAMETER ); + } else if(strchr(buffer,'/') || strchr(buffer,'.')) { + styler.ColourTo(i-1,SCE_CONF_EXTENSION); + } else { + styler.ColourTo(i-1,SCE_CONF_DEFAULT); + } + + // push back the faulty character + chNext = styler[i--]; + + } + break; + + case SCE_CONF_NUMBER: + // stay in CONF_NUMBER state until we find a non-numeric + if( (isascii(ch) && isdigit(ch)) || ch == '.') { + buffer[bufferCount++] = ch; + } else { + state = SCE_CONF_DEFAULT; + buffer[bufferCount] = '\0'; + + // Colourize here... + if( strchr(buffer,'.') ) { + // it is an IP address... + styler.ColourTo(i-1,SCE_CONF_IP); + } else { + // normal number + styler.ColourTo(i-1,SCE_CONF_NUMBER); + } + + // push back a character + chNext = styler[i--]; + } + break; + + } + } + delete []buffer; +} + +static const char * const confWordListDesc[] = { + "Directives", + "Parameters", + 0 +}; + +LexerModule lmConf(SCLEX_CONF, ColouriseConfDoc, "conf", 0, confWordListDesc); diff --git a/lexers/LexCrontab.cxx b/lexers/LexCrontab.cxx new file mode 100644 index 000000000..f6c4d42f1 --- /dev/null +++ b/lexers/LexCrontab.cxx @@ -0,0 +1,222 @@ +// Scintilla source code edit control +/** @file LexCrontab.cxx + ** Lexer to use with extended crontab files used by a powerful + ** Windows scheduler/event monitor/automation manager nnCron. + ** (http://nemtsev.eserv.ru/) + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static void ColouriseNncrontabDoc(unsigned int startPos, int length, int, WordList +*keywordLists[], Accessor &styler) +{ + int state = SCE_NNCRONTAB_DEFAULT; + char chNext = styler[startPos]; + int lengthDoc = startPos + length; + // create a buffer large enough to take the largest chunk... + char *buffer = new char[length]; + int bufferCount = 0; + // used when highliting environment variables inside quoted string: + bool insideString = false; + + // this assumes that we have 3 keyword list in conf.properties + WordList §ion = *keywordLists[0]; + WordList &keyword = *keywordLists[1]; + WordList &modifier = *keywordLists[2]; + + // go through all provided text segment + // using the hand-written state machine shown below + styler.StartAt(startPos); + styler.StartSegment(startPos); + for (int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + i++; + continue; + } + switch(state) { + case SCE_NNCRONTAB_DEFAULT: + if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') { + // whitespace is simply ignored here... + styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT); + break; + } else if( ch == '#' && styler.SafeGetCharAt(i+1) == '(') { + // signals the start of a task... + state = SCE_NNCRONTAB_TASK; + styler.ColourTo(i,SCE_NNCRONTAB_TASK); + } + else if( ch == '\\' && (styler.SafeGetCharAt(i+1) == ' ' || + styler.SafeGetCharAt(i+1) == '\t')) { + // signals the start of an extended comment... + state = SCE_NNCRONTAB_COMMENT; + styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); + } else if( ch == '#' ) { + // signals the start of a plain comment... + state = SCE_NNCRONTAB_COMMENT; + styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); + } else if( ch == ')' && styler.SafeGetCharAt(i+1) == '#') { + // signals the end of a task... + state = SCE_NNCRONTAB_TASK; + styler.ColourTo(i,SCE_NNCRONTAB_TASK); + } else if( ch == '"') { + state = SCE_NNCRONTAB_STRING; + styler.ColourTo(i,SCE_NNCRONTAB_STRING); + } else if( ch == '%') { + // signals environment variables + state = SCE_NNCRONTAB_ENVIRONMENT; + styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); + } else if( ch == '<' && styler.SafeGetCharAt(i+1) == '%') { + // signals environment variables + state = SCE_NNCRONTAB_ENVIRONMENT; + styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); + } else if( ch == '*' ) { + // signals an asterisk + // no state jump necessary for this simple case... + styler.ColourTo(i,SCE_NNCRONTAB_ASTERISK); + } else if( (isascii(ch) && isalpha(ch)) || ch == '<' ) { + // signals the start of an identifier + bufferCount = 0; + buffer[bufferCount++] = ch; + state = SCE_NNCRONTAB_IDENTIFIER; + } else if( isascii(ch) && isdigit(ch) ) { + // signals the start of a number + bufferCount = 0; + buffer[bufferCount++] = ch; + state = SCE_NNCRONTAB_NUMBER; + } else { + // style it the default style.. + styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT); + } + break; + + case SCE_NNCRONTAB_COMMENT: + // if we find a newline here, + // we simply go to default state + // else continue to work on it... + if( ch == '\n' || ch == '\r' ) { + state = SCE_NNCRONTAB_DEFAULT; + } else { + styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); + } + break; + + case SCE_NNCRONTAB_TASK: + // if we find a newline here, + // we simply go to default state + // else continue to work on it... + if( ch == '\n' || ch == '\r' ) { + state = SCE_NNCRONTAB_DEFAULT; + } else { + styler.ColourTo(i,SCE_NNCRONTAB_TASK); + } + break; + + case SCE_NNCRONTAB_STRING: + if( ch == '%' ) { + state = SCE_NNCRONTAB_ENVIRONMENT; + insideString = true; + styler.ColourTo(i-1,SCE_NNCRONTAB_STRING); + break; + } + // if we find the end of a string char, we simply go to default state + // else we're still dealing with an string... + if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') || + (ch == '\n') || (ch == '\r') ) { + state = SCE_NNCRONTAB_DEFAULT; + } + styler.ColourTo(i,SCE_NNCRONTAB_STRING); + break; + + case SCE_NNCRONTAB_ENVIRONMENT: + // if we find the end of a string char, we simply go to default state + // else we're still dealing with an string... + if( ch == '%' && insideString ) { + state = SCE_NNCRONTAB_STRING; + insideString = false; + break; + } + if( (ch == '%' && styler.SafeGetCharAt(i-1)!='\\') + || (ch == '\n') || (ch == '\r') || (ch == '>') ) { + state = SCE_NNCRONTAB_DEFAULT; + styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); + break; + } + styler.ColourTo(i+1,SCE_NNCRONTAB_ENVIRONMENT); + break; + + case SCE_NNCRONTAB_IDENTIFIER: + // stay in CONF_IDENTIFIER state until we find a non-alphanumeric + if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') || + (ch == '$') || (ch == '.') || (ch == '<') || (ch == '>') || + (ch == '@') ) { + buffer[bufferCount++] = ch; + } else { + state = SCE_NNCRONTAB_DEFAULT; + buffer[bufferCount] = '\0'; + + // check if the buffer contains a keyword, + // and highlight it if it is a keyword... + if(section.InList(buffer)) { + styler.ColourTo(i,SCE_NNCRONTAB_SECTION ); + } else if(keyword.InList(buffer)) { + styler.ColourTo(i-1,SCE_NNCRONTAB_KEYWORD ); + } // else if(strchr(buffer,'/') || strchr(buffer,'.')) { + // styler.ColourTo(i-1,SCE_NNCRONTAB_EXTENSION); + // } + else if(modifier.InList(buffer)) { + styler.ColourTo(i-1,SCE_NNCRONTAB_MODIFIER ); + } else { + styler.ColourTo(i-1,SCE_NNCRONTAB_DEFAULT); + } + // push back the faulty character + chNext = styler[i--]; + } + break; + + case SCE_NNCRONTAB_NUMBER: + // stay in CONF_NUMBER state until we find a non-numeric + if( isascii(ch) && isdigit(ch) /* || ch == '.' */ ) { + buffer[bufferCount++] = ch; + } else { + state = SCE_NNCRONTAB_DEFAULT; + buffer[bufferCount] = '\0'; + // Colourize here... (normal number) + styler.ColourTo(i-1,SCE_NNCRONTAB_NUMBER); + // push back a character + chNext = styler[i--]; + } + break; + } + } + delete []buffer; +} + +static const char * const cronWordListDesc[] = { + "Section keywords and Forth words", + "nnCrontab keywords", + "Modifiers", + 0 +}; + +LexerModule lmNncrontab(SCLEX_NNCRONTAB, ColouriseNncrontabDoc, "nncrontab", 0, cronWordListDesc); diff --git a/lexers/LexCsound.cxx b/lexers/LexCsound.cxx new file mode 100644 index 000000000..3aa2eb897 --- /dev/null +++ b/lexers/LexCsound.cxx @@ -0,0 +1,210 @@ +// Scintilla source code edit control +/** @file LexCsound.cxx + ** Lexer for Csound (Orchestra & Score) + ** Written by Georg Ritter - + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || + ch == '_' || ch == '?'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' || + ch == '%' || ch == '@' || ch == '$' || ch == '?'); +} + +static inline bool IsCsoundOperator(char ch) { + if (isascii(ch) && isalnum(ch)) + return false; + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || ch == '^' || + ch == '[' || ch == ']' || ch == '<' || ch == '&' || + ch == '>' || ch == ',' || ch == '|' || ch == '~' || + ch == '%' || ch == ':') + return true; + return false; +} + +static void ColouriseCsoundDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &opcode = *keywordlists[0]; + WordList &headerStmt = *keywordlists[1]; + WordList &otherKeyword = *keywordlists[2]; + + // Do not leak onto next line + if (initStyle == SCE_CSOUND_STRINGEOL) + initStyle = SCE_CSOUND_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) + { + // Handle line continuation generically. + if (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_CSOUND_OPERATOR) { + if (!IsCsoundOperator(static_cast(sc.ch))) { + sc.SetState(SCE_CSOUND_DEFAULT); + } + }else if (sc.state == SCE_CSOUND_NUMBER) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_CSOUND_DEFAULT); + } + } else if (sc.state == SCE_CSOUND_IDENTIFIER) { + if (!IsAWordChar(sc.ch) ) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + + if (opcode.InList(s)) { + sc.ChangeState(SCE_CSOUND_OPCODE); + } else if (headerStmt.InList(s)) { + sc.ChangeState(SCE_CSOUND_HEADERSTMT); + } else if (otherKeyword.InList(s)) { + sc.ChangeState(SCE_CSOUND_USERKEYWORD); + } else if (s[0] == 'p') { + sc.ChangeState(SCE_CSOUND_PARAM); + } else if (s[0] == 'a') { + sc.ChangeState(SCE_CSOUND_ARATE_VAR); + } else if (s[0] == 'k') { + sc.ChangeState(SCE_CSOUND_KRATE_VAR); + } else if (s[0] == 'i') { // covers both i-rate variables and i-statements + sc.ChangeState(SCE_CSOUND_IRATE_VAR); + } else if (s[0] == 'g') { + sc.ChangeState(SCE_CSOUND_GLOBAL_VAR); + } + sc.SetState(SCE_CSOUND_DEFAULT); + } + } + else if (sc.state == SCE_CSOUND_COMMENT ) { + if (sc.atLineEnd) { + sc.SetState(SCE_CSOUND_DEFAULT); + } + } + else if ((sc.state == SCE_CSOUND_ARATE_VAR) || + (sc.state == SCE_CSOUND_KRATE_VAR) || + (sc.state == SCE_CSOUND_IRATE_VAR)) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_CSOUND_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_CSOUND_DEFAULT) { + if (sc.ch == ';'){ + sc.SetState(SCE_CSOUND_COMMENT); + } else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) { + sc.SetState(SCE_CSOUND_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_CSOUND_IDENTIFIER); + } else if (IsCsoundOperator(static_cast(sc.ch))) { + sc.SetState(SCE_CSOUND_OPERATOR); + } else if (sc.ch == 'p') { + sc.SetState(SCE_CSOUND_PARAM); + } else if (sc.ch == 'a') { + sc.SetState(SCE_CSOUND_ARATE_VAR); + } else if (sc.ch == 'k') { + sc.SetState(SCE_CSOUND_KRATE_VAR); + } else if (sc.ch == 'i') { // covers both i-rate variables and i-statements + sc.SetState(SCE_CSOUND_IRATE_VAR); + } else if (sc.ch == 'g') { + sc.SetState(SCE_CSOUND_GLOBAL_VAR); + } + } + } + sc.Complete(); +} + +static void FoldCsoundInstruments(unsigned int startPos, int length, int /* initStyle */, WordList *[], + Accessor &styler) { + unsigned int lengthDoc = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int stylePrev = 0; + int styleNext = styler.StyleAt(startPos); + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if ((stylePrev != SCE_CSOUND_OPCODE) && (style == SCE_CSOUND_OPCODE)) { + char s[20]; + unsigned int j = 0; + while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) { + s[j] = styler[i + j]; + j++; + } + s[j] = '\0'; + + if (strcmp(s, "instr") == 0) + levelCurrent++; + if (strcmp(s, "endin") == 0) + levelCurrent--; + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + stylePrev = style; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + + +static const char * const csoundWordListDesc[] = { + "Opcodes", + "Header Statements", + "User keywords", + 0 +}; + +LexerModule lmCsound(SCLEX_CSOUND, ColouriseCsoundDoc, "csound", FoldCsoundInstruments, csoundWordListDesc); diff --git a/lexers/LexD.cxx b/lexers/LexD.cxx new file mode 100644 index 000000000..4c4bcb343 --- /dev/null +++ b/lexers/LexD.cxx @@ -0,0 +1,399 @@ +/** @file LexD.cxx + ** Lexer for D. + ** + ** Copyright (c) 2006 by Waldemar Augustyn + **/ +// Copyright 1998-2005 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +/* Nested comments require keeping the value of the nesting level for every + position in the document. But since scintilla always styles line by line, + we only need to store one value per line. The non-negative number indicates + nesting level at the end of the line. +*/ + +// Underscore, letter, digit and universal alphas from C99 Appendix D. + +static bool IsWordStart(int ch) { + return (isascii(ch) && (isalpha(ch) || ch == '_')) || !isascii(ch); +} + +static bool IsWord(int ch) { + return (isascii(ch) && (isalnum(ch) || ch == '_')) || !isascii(ch); +} + +static bool IsDoxygen(int ch) { + if (isascii(ch) && islower(ch)) + return true; + if (ch == '$' || ch == '@' || ch == '\\' || + ch == '&' || ch == '#' || ch == '<' || ch == '>' || + ch == '{' || ch == '}' || ch == '[' || ch == ']') + return true; + return false; +} + +static bool IsStringSuffix(int ch) { + return ch == 'c' || ch == 'w' || ch == 'd'; +} + + +static void ColouriseDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler, bool caseSensitive) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; //doxygen + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; + WordList &keywords7 = *keywordlists[6]; + + int styleBeforeDCKeyword = SCE_D_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + int curLine = styler.GetLine(startPos); + int curNcLevel = curLine > 0? styler.GetLineState(curLine-1): 0; + bool numFloat = false; // Float literals have '+' and '-' signs + bool numHex = false; + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart) { + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curNcLevel); + } + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_D_OPERATOR: + sc.SetState(SCE_D_DEFAULT); + break; + case SCE_D_NUMBER: + // We accept almost anything because of hex. and number suffixes + if (isascii(sc.ch) && (isalnum(sc.ch) || sc.ch == '_')) { + continue; + } else if (sc.ch == '.' && sc.chNext != '.' && !numFloat) { + // Don't parse 0..2 as number. + numFloat=true; + continue; + } else if ( ( sc.ch == '-' || sc.ch == '+' ) && ( /*sign and*/ + ( !numHex && ( sc.chPrev == 'e' || sc.chPrev == 'E' ) ) || /*decimal or*/ + ( sc.chPrev == 'p' || sc.chPrev == 'P' ) ) ) { /*hex*/ + // Parse exponent sign in float literals: 2e+10 0x2e+10 + continue; + } else { + sc.SetState(SCE_D_DEFAULT); + } + break; + case SCE_D_IDENTIFIER: + if (!IsWord(sc.ch)) { + char s[1000]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (keywords.InList(s)) { + sc.ChangeState(SCE_D_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_D_WORD2); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_D_TYPEDEF); + } else if (keywords5.InList(s)) { + sc.ChangeState(SCE_D_WORD5); + } else if (keywords6.InList(s)) { + sc.ChangeState(SCE_D_WORD6); + } else if (keywords7.InList(s)) { + sc.ChangeState(SCE_D_WORD7); + } + sc.SetState(SCE_D_DEFAULT); + } + break; + case SCE_D_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } + break; + case SCE_D_COMMENTDOC: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_D_COMMENTDOC; + sc.SetState(SCE_D_COMMENTDOCKEYWORD); + } + } + break; + case SCE_D_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_D_DEFAULT); + } + break; + case SCE_D_COMMENTLINEDOC: + if (sc.atLineStart) { + sc.SetState(SCE_D_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_D_COMMENTLINEDOC; + sc.SetState(SCE_D_COMMENTDOCKEYWORD); + } + } + break; + case SCE_D_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_D_COMMENTDOC) && sc.Match('*', '/')) { + sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } else if (!IsDoxygen(sc.ch)) { + char s[100]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { + sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR); + } + sc.SetState(styleBeforeDCKeyword); + } + break; + case SCE_D_COMMENTNESTED: + if (sc.Match('+', '/')) { + if (curNcLevel > 0) + curNcLevel -= 1; + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curNcLevel); + sc.Forward(); + if (curNcLevel == 0) { + sc.ForwardSetState(SCE_D_DEFAULT); + } + } else if (sc.Match('/','+')) { + curNcLevel += 1; + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curNcLevel); + sc.Forward(); + } + break; + case SCE_D_STRING: + if (sc.ch == '\\') { + if (sc.chNext == '"' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '"') { + if(IsStringSuffix(sc.chNext)) + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } + break; + case SCE_D_CHARACTER: + if (sc.atLineEnd) { + sc.ChangeState(SCE_D_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + // Char has no suffixes + sc.ForwardSetState(SCE_D_DEFAULT); + } + break; + case SCE_D_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_D_DEFAULT); + } + break; + case SCE_D_STRINGB: + if (sc.ch == '`') { + if(IsStringSuffix(sc.chNext)) + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } + break; + case SCE_D_STRINGR: + if (sc.ch == '"') { + if(IsStringSuffix(sc.chNext)) + sc.Forward(); + sc.ForwardSetState(SCE_D_DEFAULT); + } + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_D_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_D_NUMBER); + numFloat = sc.ch == '.'; + // Remember hex literal + numHex = sc.ch == '0' && ( sc.chNext == 'x' || sc.chNext == 'X' ); + } else if ( (sc.ch == 'r' || sc.ch == 'x' || sc.ch == 'q') + && sc.chNext == '"' ) { + // Limited support for hex and delimited strings: parse as r"" + sc.SetState(SCE_D_STRINGR); + sc.Forward(); + } else if (IsWordStart(sc.ch) || sc.ch == '$') { + sc.SetState(SCE_D_IDENTIFIER); + } else if (sc.Match('/','+')) { + curNcLevel += 1; + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curNcLevel); + sc.SetState(SCE_D_COMMENTNESTED); + sc.Forward(); + } else if (sc.Match('/', '*')) { + if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style + sc.SetState(SCE_D_COMMENTDOC); + } else { + sc.SetState(SCE_D_COMMENT); + } + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!")) + // Support of Qt/Doxygen doc. style + sc.SetState(SCE_D_COMMENTLINEDOC); + else + sc.SetState(SCE_D_COMMENTLINE); + } else if (sc.ch == '"') { + sc.SetState(SCE_D_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_D_CHARACTER); + } else if (sc.ch == '`') { + sc.SetState(SCE_D_STRINGB); + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_D_OPERATOR); + if (sc.ch == '.' && sc.chNext == '.') sc.Forward(); // Range operator + } + } + } + sc.Complete(); +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_D_COMMENT || + style == SCE_D_COMMENTDOC || + style == SCE_D_COMMENTDOCKEYWORD || + style == SCE_D_COMMENTDOCKEYWORDERROR; +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "} else {". +static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + + // property lexer.d.fold.at.else + // This option enables D folding on a "} else {" line of an if statement. + bool foldAtElse = styler.GetPropertyInt("lexer.d.fold.at.else", + styler.GetPropertyInt("fold.at.else", 0)) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (style == SCE_D_OPERATOR) { + if (ch == '{') { + // Measure the minimum before a '{' to allow + // folding on "} else {" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + if (atEOL) { + if (foldComment) { // Handle nested comments + int nc; + nc = styler.GetLineState(lineCurrent); + nc -= lineCurrent>0? styler.GetLineState(lineCurrent-1): 0; + levelNext += nc; + } + int levelUse = levelCurrent; + if (foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + visibleChars = 0; + } + if (!IsASpace(ch)) + visibleChars++; + } +} + +static void FoldDDoc(unsigned int startPos, int length, int initStyle, + WordList *[], Accessor &styler) { + FoldDoc(startPos, length, initStyle, styler); +} + +static const char * const dWordLists[] = { + "Primary keywords and identifiers", + "Secondary keywords and identifiers", + "Documentation comment keywords", + "Type definitions and aliases", + "Keywords 5", + "Keywords 6", + "Keywords 7", + 0, + }; + +static void ColouriseDDoc(unsigned int startPos, int length, + int initStyle, WordList *keywordlists[], Accessor &styler) { + ColouriseDoc(startPos, length, initStyle, keywordlists, styler, true); +} + +LexerModule lmD(SCLEX_D, ColouriseDDoc, "d", FoldDDoc, dWordLists); diff --git a/lexers/LexEScript.cxx b/lexers/LexEScript.cxx new file mode 100644 index 000000000..295aaec53 --- /dev/null +++ b/lexers/LexEScript.cxx @@ -0,0 +1,273 @@ +// Scintilla source code edit control +/** @file LexESCRIPT.cxx + ** Lexer for ESCRIPT + **/ +// Copyright 2003 by Patrizio Bekerle (patrizio@bekerle.com) + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + + + +static void ColouriseESCRIPTDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + + // Do not leak onto next line + /*if (initStyle == SCE_ESCRIPT_STRINGEOL) + initStyle = SCE_ESCRIPT_DEFAULT;*/ + + StyleContext sc(startPos, length, initStyle, styler); + + bool caseSensitive = styler.GetPropertyInt("escript.case.sensitive", 0) != 0; + + for (; sc.More(); sc.Forward()) { + + /*if (sc.atLineStart && (sc.state == SCE_ESCRIPT_STRING)) { + // Prevent SCE_ESCRIPT_STRINGEOL from leaking back to previous line + sc.SetState(SCE_ESCRIPT_STRING); + }*/ + + // Handle line continuation generically. + if (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_ESCRIPT_OPERATOR || sc.state == SCE_ESCRIPT_BRACE) { + sc.SetState(SCE_ESCRIPT_DEFAULT); + } else if (sc.state == SCE_ESCRIPT_NUMBER) { + if (!IsADigit(sc.ch) || sc.ch != '.') { + sc.SetState(SCE_ESCRIPT_DEFAULT); + } + } else if (sc.state == SCE_ESCRIPT_IDENTIFIER) { + if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { + char s[100]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + +// sc.GetCurrentLowered(s, sizeof(s)); + + if (keywords.InList(s)) { + sc.ChangeState(SCE_ESCRIPT_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_ESCRIPT_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_ESCRIPT_WORD3); + // sc.state = SCE_ESCRIPT_IDENTIFIER; + } + sc.SetState(SCE_ESCRIPT_DEFAULT); + } + } else if (sc.state == SCE_ESCRIPT_COMMENT) { + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_ESCRIPT_DEFAULT); + } + } else if (sc.state == SCE_ESCRIPT_COMMENTDOC) { + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_ESCRIPT_DEFAULT); + } + } else if (sc.state == SCE_ESCRIPT_COMMENTLINE) { + if (sc.atLineEnd) { + sc.SetState(SCE_ESCRIPT_DEFAULT); + } + } else if (sc.state == SCE_ESCRIPT_STRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_ESCRIPT_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_ESCRIPT_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_ESCRIPT_NUMBER); + } else if (IsAWordStart(sc.ch) || (sc.ch == '#')) { + sc.SetState(SCE_ESCRIPT_IDENTIFIER); + } else if (sc.Match('/', '*')) { + sc.SetState(SCE_ESCRIPT_COMMENT); + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + sc.SetState(SCE_ESCRIPT_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_ESCRIPT_STRING); + //} else if (isoperator(static_cast(sc.ch))) { + } else if (sc.ch == '+' || sc.ch == '-' || sc.ch == '*' || sc.ch == '/' || sc.ch == '=' || sc.ch == '<' || sc.ch == '>' || sc.ch == '&' || sc.ch == '|' || sc.ch == '!' || sc.ch == '?' || sc.ch == ':') { + sc.SetState(SCE_ESCRIPT_OPERATOR); + } else if (sc.ch == '{' || sc.ch == '}') { + sc.SetState(SCE_ESCRIPT_BRACE); + } + } + + } + sc.Complete(); +} + + +static int classifyFoldPointESCRIPT(const char* s, const char* prevWord) { + int lev = 0; + if (strcmp(prevWord, "end") == 0) return lev; + if ((strcmp(prevWord, "else") == 0 && strcmp(s, "if") == 0) || strcmp(s, "elseif") == 0) + return -1; + + if (strcmp(s, "for") == 0 || strcmp(s, "foreach") == 0 + || strcmp(s, "program") == 0 || strcmp(s, "function") == 0 + || strcmp(s, "while") == 0 || strcmp(s, "case") == 0 + || strcmp(s, "if") == 0 ) { + lev = 1; + } else if ( strcmp(s, "endfor") == 0 || strcmp(s, "endforeach") == 0 + || strcmp(s, "endprogram") == 0 || strcmp(s, "endfunction") == 0 + || strcmp(s, "endwhile") == 0 || strcmp(s, "endcase") == 0 + || strcmp(s, "endif") == 0 ) { + lev = -1; + } + + return lev; +} + + +static bool IsStreamCommentStyle(int style) { + return style == SCE_ESCRIPT_COMMENT || + style == SCE_ESCRIPT_COMMENTDOC || + style == SCE_ESCRIPT_COMMENTLINE; +} + +static void FoldESCRIPTDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { + //~ bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + // Do not know how to fold the comment at the moment. + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldComment = true; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + + int lastStart = 0; + char prevWord[32] = ""; + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + + if (foldComment && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelCurrent++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + + if (foldComment && (style == SCE_ESCRIPT_COMMENTLINE)) { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelCurrent++; + } else if (chNext2 == '}') { + levelCurrent--; + } + } + } + + if (stylePrev == SCE_ESCRIPT_DEFAULT && style == SCE_ESCRIPT_WORD3) + { + // Store last word start point. + lastStart = i; + } + + if (style == SCE_ESCRIPT_WORD3) { + if(iswordchar(ch) && !iswordchar(chNext)) { + char s[32]; + unsigned int j; + for(j = 0; ( j < 31 ) && ( j < i-lastStart+1 ); j++) { + s[j] = static_cast(tolower(styler[lastStart + j])); + } + s[j] = '\0'; + levelCurrent += classifyFoldPointESCRIPT(s, prevWord); + strcpy(prevWord, s); + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + strcpy(prevWord, ""); + } + + if (!isspacechar(ch)) + visibleChars++; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + + + +static const char * const ESCRIPTWordLists[] = { + "Primary keywords and identifiers", + "Intrinsic functions", + "Extended and user defined functions", + 0, +}; + +LexerModule lmESCRIPT(SCLEX_ESCRIPT, ColouriseESCRIPTDoc, "escript", FoldESCRIPTDoc, ESCRIPTWordLists); diff --git a/lexers/LexEiffel.cxx b/lexers/LexEiffel.cxx new file mode 100644 index 000000000..03dea5e73 --- /dev/null +++ b/lexers/LexEiffel.cxx @@ -0,0 +1,238 @@ +// Scintilla source code edit control +/** @file LexEiffel.cxx + ** Lexer for Eiffel. + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool isEiffelOperator(unsigned int ch) { + // '.' left out as it is used to make up numbers + return ch == '*' || ch == '/' || ch == '\\' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || + ch == '{' || ch == '}' || ch == '~' || + ch == '[' || ch == ']' || ch == ';' || + ch == '<' || ch == '>' || ch == ',' || + ch == '.' || ch == '^' || ch == '%' || ch == ':' || + ch == '!' || ch == '@' || ch == '?'; +} + +static inline bool IsAWordChar(unsigned int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordStart(unsigned int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static void ColouriseEiffelDoc(unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.state == SCE_EIFFEL_STRINGEOL) { + if (sc.ch != '\r' && sc.ch != '\n') { + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } else if (sc.state == SCE_EIFFEL_OPERATOR) { + sc.SetState(SCE_EIFFEL_DEFAULT); + } else if (sc.state == SCE_EIFFEL_WORD) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (!keywords.InList(s)) { + sc.ChangeState(SCE_EIFFEL_IDENTIFIER); + } + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } else if (sc.state == SCE_EIFFEL_NUMBER) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } else if (sc.state == SCE_EIFFEL_COMMENTLINE) { + if (sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } else if (sc.state == SCE_EIFFEL_STRING) { + if (sc.ch == '%') { + sc.Forward(); + } else if (sc.ch == '\"') { + sc.Forward(); + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } else if (sc.state == SCE_EIFFEL_CHARACTER) { + if (sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_EIFFEL_STRINGEOL); + } else if (sc.ch == '%') { + sc.Forward(); + } else if (sc.ch == '\'') { + sc.Forward(); + sc.SetState(SCE_EIFFEL_DEFAULT); + } + } + + if (sc.state == SCE_EIFFEL_DEFAULT) { + if (sc.ch == '-' && sc.chNext == '-') { + sc.SetState(SCE_EIFFEL_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_EIFFEL_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_EIFFEL_CHARACTER); + } else if (IsADigit(sc.ch) || (sc.ch == '.')) { + sc.SetState(SCE_EIFFEL_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_EIFFEL_WORD); + } else if (isEiffelOperator(sc.ch)) { + sc.SetState(SCE_EIFFEL_OPERATOR); + } + } + } + sc.Complete(); +} + +static bool IsEiffelComment(Accessor &styler, int pos, int len) { + return len>1 && styler[pos]=='-' && styler[pos+1]=='-'; +} + +static void FoldEiffelDocIndent(unsigned int startPos, int length, int, + WordList *[], Accessor &styler) { + int lengthDoc = startPos + length; + + // Backtrack to previous line in case need to fix its fold status + int lineCurrent = styler.GetLine(startPos); + if (startPos > 0) { + if (lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + } + int spaceFlags = 0; + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsEiffelComment); + char chNext = styler[startPos]; + for (int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) { + int lev = indentCurrent; + int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsEiffelComment); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + // Only non whitespace lines can be headers + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { + // Line after is blank so check the next - maybe should continue further? + int spaceFlags2 = 0; + int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsEiffelComment); + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + } + } + indentCurrent = indentNext; + styler.SetLevel(lineCurrent, lev); + lineCurrent++; + } + } +} + +static void FoldEiffelDocKeyWords(unsigned int startPos, int length, int /* initStyle */, WordList *[], + Accessor &styler) { + unsigned int lengthDoc = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int stylePrev = 0; + int styleNext = styler.StyleAt(startPos); + // lastDeferred should be determined by looking back to last keyword in case + // the "deferred" is on a line before "class" + bool lastDeferred = false; + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if ((stylePrev != SCE_EIFFEL_WORD) && (style == SCE_EIFFEL_WORD)) { + char s[20]; + unsigned int j = 0; + while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) { + s[j] = styler[i + j]; + j++; + } + s[j] = '\0'; + + if ( + (strcmp(s, "check") == 0) || + (strcmp(s, "debug") == 0) || + (strcmp(s, "deferred") == 0) || + (strcmp(s, "do") == 0) || + (strcmp(s, "from") == 0) || + (strcmp(s, "if") == 0) || + (strcmp(s, "inspect") == 0) || + (strcmp(s, "once") == 0) + ) + levelCurrent++; + if (!lastDeferred && (strcmp(s, "class") == 0)) + levelCurrent++; + if (strcmp(s, "end") == 0) + levelCurrent--; + lastDeferred = strcmp(s, "deferred") == 0; + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + stylePrev = style; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const eiffelWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmEiffel(SCLEX_EIFFEL, ColouriseEiffelDoc, "eiffel", FoldEiffelDocIndent, eiffelWordListDesc); +LexerModule lmEiffelkw(SCLEX_EIFFELKW, ColouriseEiffelDoc, "eiffelkw", FoldEiffelDocKeyWords, eiffelWordListDesc); diff --git a/lexers/LexErlang.cxx b/lexers/LexErlang.cxx new file mode 100644 index 000000000..45577bda4 --- /dev/null +++ b/lexers/LexErlang.cxx @@ -0,0 +1,619 @@ +// Scintilla source code edit control +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. +/** @file LexErlang.cxx + ** Lexer for Erlang. + ** Enhanced by Etienne 'Lenain' Girondel (lenaing@gmail.com) + ** Originally wrote by Peter-Henry Mander, + ** based on Matlab lexer by José Fonseca. + **/ + +#include +#include +#include +#include +#include + +#include "Platform.h" +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static int is_radix(int radix, int ch) { + int digit; + + if (36 < radix || 2 > radix) + return 0; + + if (isdigit(ch)) { + digit = ch - '0'; + } else if (isalnum(ch)) { + digit = toupper(ch) - 'A' + 10; + } else { + return 0; + } + + return (digit < radix); +} + +typedef enum { + STATE_NULL, + COMMENT, + COMMENT_FUNCTION, + COMMENT_MODULE, + COMMENT_DOC, + COMMENT_DOC_MACRO, + ATOM_UNQUOTED, + ATOM_QUOTED, + NODE_NAME_UNQUOTED, + NODE_NAME_QUOTED, + MACRO_START, + MACRO_UNQUOTED, + MACRO_QUOTED, + RECORD_START, + RECORD_UNQUOTED, + RECORD_QUOTED, + NUMERAL_START, + NUMERAL_BASE_VALUE, + NUMERAL_FLOAT, + NUMERAL_EXPONENT, + PREPROCESSOR +} atom_parse_state_t; + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (ch != ' ') && (isalnum(ch) || ch == '_'); +} + +static void ColouriseErlangDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + StyleContext sc(startPos, length, initStyle, styler); + WordList &reservedWords = *keywordlists[0]; + WordList &erlangBIFs = *keywordlists[1]; + WordList &erlangPreproc = *keywordlists[2]; + WordList &erlangModulesAtt = *keywordlists[3]; + WordList &erlangDoc = *keywordlists[4]; + WordList &erlangDocMacro = *keywordlists[5]; + int radix_digits = 0; + int exponent_digits = 0; + atom_parse_state_t parse_state = STATE_NULL; + atom_parse_state_t old_parse_state = STATE_NULL; + bool to_late_to_comment = false; + char cur[100]; + int old_style = SCE_ERLANG_DEFAULT; + + styler.StartAt(startPos); + + for (; sc.More(); sc.Forward()) { + int style = SCE_ERLANG_DEFAULT; + if (STATE_NULL != parse_state) { + + switch (parse_state) { + + case STATE_NULL : sc.SetState(SCE_ERLANG_DEFAULT); break; + + /* COMMENTS ------------------------------------------------------*/ + case COMMENT : { + if (sc.ch != '%') { + to_late_to_comment = true; + } else if (!to_late_to_comment && sc.ch == '%') { + // Switch to comment level 2 (Function) + sc.ChangeState(SCE_ERLANG_COMMENT_FUNCTION); + old_style = SCE_ERLANG_COMMENT_FUNCTION; + parse_state = COMMENT_FUNCTION; + sc.Forward(); + } + } + // V--- Falling through! + case COMMENT_FUNCTION : { + if (sc.ch != '%') { + to_late_to_comment = true; + } else if (!to_late_to_comment && sc.ch == '%') { + // Switch to comment level 3 (Module) + sc.ChangeState(SCE_ERLANG_COMMENT_MODULE); + old_style = SCE_ERLANG_COMMENT_MODULE; + parse_state = COMMENT_MODULE; + sc.Forward(); + } + } + // V--- Falling through! + case COMMENT_MODULE : { + if (parse_state != COMMENT) { + // Search for comment documentation + if (sc.chNext == '@') { + old_parse_state = parse_state; + parse_state = ('{' == sc.ch) + ? COMMENT_DOC_MACRO + : COMMENT_DOC; + sc.ForwardSetState(sc.state); + } + } + + // All comments types fall here. + if (sc.atLineEnd) { + to_late_to_comment = false; + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case COMMENT_DOC : + // V--- Falling through! + case COMMENT_DOC_MACRO : { + + if (!isalnum(sc.ch)) { + // Try to match documentation comment + sc.GetCurrent(cur, sizeof(cur)); + + if (parse_state == COMMENT_DOC_MACRO + && erlangDocMacro.InList(cur)) { + sc.ChangeState(SCE_ERLANG_COMMENT_DOC_MACRO); + while (sc.ch != '}' && !sc.atLineEnd) + sc.Forward(); + } else if (erlangDoc.InList(cur)) { + sc.ChangeState(SCE_ERLANG_COMMENT_DOC); + } else { + sc.ChangeState(old_style); + } + + // Switch back to old state + sc.SetState(old_style); + parse_state = old_parse_state; + } + + if (sc.atLineEnd) { + to_late_to_comment = false; + sc.ChangeState(old_style); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* -------------------------------------------------------------- */ + /* Atoms ---------------------------------------------------------*/ + case ATOM_UNQUOTED : { + if ('@' == sc.ch){ + parse_state = NODE_NAME_UNQUOTED; + } else if (sc.ch == ':') { + // Searching for module name + if (sc.chNext == ' ') { + // error + sc.ChangeState(SCE_ERLANG_UNKNOWN); + parse_state = STATE_NULL; + } else { + sc.Forward(); + if (isalnum(sc.ch)) { + sc.GetCurrent(cur, sizeof(cur)); + sc.ChangeState(SCE_ERLANG_MODULES); + sc.SetState(SCE_ERLANG_MODULES); + } + } + } else if (!IsAWordChar(sc.ch)) { + + sc.GetCurrent(cur, sizeof(cur)); + if (reservedWords.InList(cur)) { + style = SCE_ERLANG_KEYWORD; + } else if (erlangBIFs.InList(cur) + && strcmp(cur,"erlang:")){ + style = SCE_ERLANG_BIFS; + } else if (sc.ch == '(' || '/' == sc.ch){ + style = SCE_ERLANG_FUNCTION_NAME; + } else { + style = SCE_ERLANG_ATOM; + } + + sc.ChangeState(style); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + + } break; + + case ATOM_QUOTED : { + if ( '@' == sc.ch ){ + parse_state = NODE_NAME_QUOTED; + } else if ('\'' == sc.ch && '\\' != sc.chPrev) { + sc.ChangeState(SCE_ERLANG_ATOM); + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* -------------------------------------------------------------- */ + /* Node names ----------------------------------------------------*/ + case NODE_NAME_UNQUOTED : { + if ('@' == sc.ch) { + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } else if (!IsAWordChar(sc.ch)) { + sc.ChangeState(SCE_ERLANG_NODE_NAME); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case NODE_NAME_QUOTED : { + if ('@' == sc.ch) { + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } else if ('\'' == sc.ch && '\\' != sc.chPrev) { + sc.ChangeState(SCE_ERLANG_NODE_NAME_QUOTED); + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* -------------------------------------------------------------- */ + /* Records -------------------------------------------------------*/ + case RECORD_START : { + if ('\'' == sc.ch) { + parse_state = RECORD_QUOTED; + } else if (isalpha(sc.ch) && islower(sc.ch)) { + parse_state = RECORD_UNQUOTED; + } else { // error + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case RECORD_UNQUOTED : { + if (!IsAWordChar(sc.ch)) { + sc.ChangeState(SCE_ERLANG_RECORD); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case RECORD_QUOTED : { + if ('\'' == sc.ch && '\\' != sc.chPrev) { + sc.ChangeState(SCE_ERLANG_RECORD_QUOTED); + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* -------------------------------------------------------------- */ + /* Macros --------------------------------------------------------*/ + case MACRO_START : { + if ('\'' == sc.ch) { + parse_state = MACRO_QUOTED; + } else if (isalpha(sc.ch)) { + parse_state = MACRO_UNQUOTED; + } else { // error + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case MACRO_UNQUOTED : { + if (!IsAWordChar(sc.ch)) { + sc.ChangeState(SCE_ERLANG_MACRO); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + case MACRO_QUOTED : { + if ('\'' == sc.ch && '\\' != sc.chPrev) { + sc.ChangeState(SCE_ERLANG_MACRO_QUOTED); + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* -------------------------------------------------------------- */ + /* Numerics ------------------------------------------------------*/ + /* Simple integer */ + case NUMERAL_START : { + if (isdigit(sc.ch)) { + radix_digits *= 10; + radix_digits += sc.ch - '0'; // Assuming ASCII here! + } else if ('#' == sc.ch) { + if (2 > radix_digits || 36 < radix_digits) { + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } else { + parse_state = NUMERAL_BASE_VALUE; + } + } else if ('.' == sc.ch && isdigit(sc.chNext)) { + radix_digits = 0; + parse_state = NUMERAL_FLOAT; + } else if ('e' == sc.ch || 'E' == sc.ch) { + exponent_digits = 0; + parse_state = NUMERAL_EXPONENT; + } else { + radix_digits = 0; + sc.ChangeState(SCE_ERLANG_NUMBER); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* Integer in other base than 10 (x#yyy) */ + case NUMERAL_BASE_VALUE : { + if (!is_radix(radix_digits,sc.ch)) { + radix_digits = 0; + + if (!isalnum(sc.ch)) + sc.ChangeState(SCE_ERLANG_NUMBER); + + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* Float (x.yyy) */ + case NUMERAL_FLOAT : { + if ('e' == sc.ch || 'E' == sc.ch) { + exponent_digits = 0; + parse_state = NUMERAL_EXPONENT; + } else if (!isdigit(sc.ch)) { + sc.ChangeState(SCE_ERLANG_NUMBER); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + /* Exponent, either integer or float (xEyy, x.yyEzzz) */ + case NUMERAL_EXPONENT : { + if (('-' == sc.ch || '+' == sc.ch) + && (isdigit(sc.chNext))) { + sc.Forward(); + } else if (!isdigit(sc.ch)) { + if (0 < exponent_digits) + sc.ChangeState(SCE_ERLANG_NUMBER); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } else { + ++exponent_digits; + } + } break; + + /* -------------------------------------------------------------- */ + /* Preprocessor --------------------------------------------------*/ + case PREPROCESSOR : { + if (!IsAWordChar(sc.ch)) { + + sc.GetCurrent(cur, sizeof(cur)); + if (erlangPreproc.InList(cur)) { + style = SCE_ERLANG_PREPROC; + } else if (erlangModulesAtt.InList(cur)) { + style = SCE_ERLANG_MODULES_ATT; + } + + sc.ChangeState(style); + sc.SetState(SCE_ERLANG_DEFAULT); + parse_state = STATE_NULL; + } + } break; + + } + + } /* End of : STATE_NULL != parse_state */ + else + { + switch (sc.state) { + case SCE_ERLANG_VARIABLE : { + if (!IsAWordChar(sc.ch)) + sc.SetState(SCE_ERLANG_DEFAULT); + } break; + case SCE_ERLANG_STRING : { + if (sc.ch == '\"' && sc.chPrev != '\\') + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + } break; + case SCE_ERLANG_COMMENT : { + if (sc.atLineEnd) + sc.SetState(SCE_ERLANG_DEFAULT); + } break; + case SCE_ERLANG_CHARACTER : { + if (sc.chPrev == '\\') { + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + } else if (sc.ch != '\\') { + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + } + } break; + case SCE_ERLANG_OPERATOR : { + if (sc.chPrev == '.') { + if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' + || sc.ch == '^') { + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_ERLANG_DEFAULT); + } else { + sc.SetState(SCE_ERLANG_DEFAULT); + } + } else { + sc.SetState(SCE_ERLANG_DEFAULT); + } + } break; + } + } + + if (sc.state == SCE_ERLANG_DEFAULT) { + bool no_new_state = false; + + switch (sc.ch) { + case '\"' : sc.SetState(SCE_ERLANG_STRING); break; + case '$' : sc.SetState(SCE_ERLANG_CHARACTER); break; + case '%' : { + parse_state = COMMENT; + sc.SetState(SCE_ERLANG_COMMENT); + } break; + case '#' : { + parse_state = RECORD_START; + sc.SetState(SCE_ERLANG_UNKNOWN); + } break; + case '?' : { + parse_state = MACRO_START; + sc.SetState(SCE_ERLANG_UNKNOWN); + } break; + case '\'' : { + parse_state = ATOM_QUOTED; + sc.SetState(SCE_ERLANG_UNKNOWN); + } break; + case '+' : + case '-' : { + if (IsADigit(sc.chNext)) { + parse_state = NUMERAL_START; + radix_digits = 0; + sc.SetState(SCE_ERLANG_UNKNOWN); + } else if (sc.ch != '+') { + parse_state = PREPROCESSOR; + sc.SetState(SCE_ERLANG_UNKNOWN); + } + } break; + default : no_new_state = true; + } + + if (no_new_state) { + if (isdigit(sc.ch)) { + parse_state = NUMERAL_START; + radix_digits = sc.ch - '0'; + sc.SetState(SCE_ERLANG_UNKNOWN); + } else if (isupper(sc.ch) || '_' == sc.ch) { + sc.SetState(SCE_ERLANG_VARIABLE); + } else if (isalpha(sc.ch)) { + parse_state = ATOM_UNQUOTED; + sc.SetState(SCE_ERLANG_UNKNOWN); + } else if (isoperator(static_cast(sc.ch)) + || sc.ch == '\\') { + sc.SetState(SCE_ERLANG_OPERATOR); + } + } + } + + } + sc.Complete(); +} + +static int ClassifyErlangFoldPoint( + Accessor &styler, + int styleNext, + int keyword_start +) { + int lev = 0; + if (styler.Match(keyword_start,"case") + || ( + styler.Match(keyword_start,"fun") + && (SCE_ERLANG_FUNCTION_NAME != styleNext) + ) + || styler.Match(keyword_start,"if") + || styler.Match(keyword_start,"query") + || styler.Match(keyword_start,"receive") + ) { + ++lev; + } else if (styler.Match(keyword_start,"end")) { + --lev; + } + + return lev; +} + +static void FoldErlangDoc( + unsigned int startPos, int length, int initStyle, + WordList** /*keywordlists*/, Accessor &styler +) { + unsigned int endPos = startPos + length; + int currentLine = styler.GetLine(startPos); + int lev; + int previousLevel = styler.LevelAt(currentLine) & SC_FOLDLEVELNUMBERMASK; + int currentLevel = previousLevel; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + int stylePrev; + int keyword_start = 0; + char ch; + char chNext = styler.SafeGetCharAt(startPos); + bool atEOL; + + for (unsigned int i = startPos; i < endPos; i++) { + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + // Get styles + stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + atEOL = ((ch == '\r') && (chNext != '\n')) || (ch == '\n'); + + if (stylePrev != SCE_ERLANG_KEYWORD + && style == SCE_ERLANG_KEYWORD) { + keyword_start = i; + } + + // Fold on keywords + if (stylePrev == SCE_ERLANG_KEYWORD + && style != SCE_ERLANG_KEYWORD + && style != SCE_ERLANG_ATOM + ) { + currentLevel += ClassifyErlangFoldPoint(styler, + styleNext, + keyword_start); + } + + // Fold on comments + if (style == SCE_ERLANG_COMMENT + || style == SCE_ERLANG_COMMENT_MODULE + || style == SCE_ERLANG_COMMENT_FUNCTION) { + + if (ch == '%' && chNext == '{') { + currentLevel++; + } else if (ch == '%' && chNext == '}') { + currentLevel--; + } + } + + // Fold on braces + if (style == SCE_ERLANG_OPERATOR) { + if (ch == '{' || ch == '(' || ch == '[') { + currentLevel++; + } else if (ch == '}' || ch == ')' || ch == ']') { + currentLevel--; + } + } + + + if (atEOL) { + lev = previousLevel; + + if (currentLevel > previousLevel) + lev |= SC_FOLDLEVELHEADERFLAG; + + if (lev != styler.LevelAt(currentLine)) + styler.SetLevel(currentLine, lev); + + currentLine++; + previousLevel = currentLevel; + } + + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + styler.SetLevel(currentLine, + previousLevel + | (styler.LevelAt(currentLine) & ~SC_FOLDLEVELNUMBERMASK)); +} + +static const char * const erlangWordListDesc[] = { + "Erlang Reserved words", + "Erlang BIFs", + "Erlang Preprocessor", + "Erlang Module Attributes", + "Erlang Documentation", + "Erlang Documentation Macro", + 0 +}; + +LexerModule lmErlang( + SCLEX_ERLANG, + ColouriseErlangDoc, + "erlang", + FoldErlangDoc, + erlangWordListDesc); diff --git a/lexers/LexFlagship.cxx b/lexers/LexFlagship.cxx new file mode 100644 index 000000000..e3a8b9f25 --- /dev/null +++ b/lexers/LexFlagship.cxx @@ -0,0 +1,352 @@ +// Scintilla source code edit control +/** @file LexFlagShip.cxx + ** Lexer for Harbour and FlagShip. + ** (Syntactically compatible to other xBase dialects, like Clipper, dBase, Clip, FoxPro etc.) + **/ +// Copyright 2005 by Randy Butler +// Copyright 2010 by Xavi (Harbour) +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "CharacterSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// Extended to accept accented characters +static inline bool IsAWordChar(int ch) +{ + return ch >= 0x80 || + (isalnum(ch) || ch == '_'); +} + +static void ColouriseFlagShipDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) +{ + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + + // property lexer.flagship.styling.within.preprocessor + // For Harbour code, determines whether all preprocessor code is styled in the preprocessor style (0) or only from the + // initial # to the end of the command word(1, the default). It also determines how to present text, dump, and disabled code. + bool stylingWithinPreprocessor = styler.GetPropertyInt("lexer.flagship.styling.within.preprocessor", 1) != 0; + + CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); + + int visibleChars = 0; + int closeStringChar = 0; + int styleBeforeDCKeyword = SCE_FS_DEFAULT; + bool bEnableCode = initStyle < SCE_FS_DISABLEDCODE; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_FS_OPERATOR: + case SCE_FS_OPERATOR_C: + case SCE_FS_WORDOPERATOR: + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + break; + case SCE_FS_IDENTIFIER: + case SCE_FS_IDENTIFIER_C: + if (!IsAWordChar(sc.ch)) { + char s[64]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD : SCE_FS_KEYWORD_C); + } else if (keywords2.InList(s)) { + sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD2 : SCE_FS_KEYWORD2_C); + } else if (bEnableCode && keywords3.InList(s)) { + sc.ChangeState(SCE_FS_KEYWORD3); + } else if (bEnableCode && keywords4.InList(s)) { + sc.ChangeState(SCE_FS_KEYWORD4); + }// Else, it is really an identifier... + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_NUMBER: + if (!IsAWordChar(sc.ch) && !(sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_FS_DEFAULT); + } + break; + case SCE_FS_NUMBER_C: + if (!IsAWordChar(sc.ch) && sc.ch != '.') { + sc.SetState(SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_CONSTANT: + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_FS_DEFAULT); + } + break; + case SCE_FS_STRING: + case SCE_FS_STRING_C: + if (sc.ch == closeStringChar) { + sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.atLineEnd) { + sc.ChangeState(bEnableCode ? SCE_FS_STRINGEOL : SCE_FS_STRINGEOL_C); + } + break; + case SCE_FS_STRINGEOL: + case SCE_FS_STRINGEOL_C: + if (sc.atLineStart) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_COMMENTDOC: + case SCE_FS_COMMENTDOC_C: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C; + sc.SetState(SCE_FS_COMMENTDOCKEYWORD); + } + } + break; + case SCE_FS_COMMENT: + case SCE_FS_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_FS_DEFAULT); + } + break; + case SCE_FS_COMMENTLINEDOC: + case SCE_FS_COMMENTLINEDOC_C: + if (sc.atLineStart) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C; + sc.SetState(SCE_FS_COMMENTDOCKEYWORD); + } + } + break; + case SCE_FS_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_FS_COMMENTDOC || styleBeforeDCKeyword == SCE_FS_COMMENTDOC_C) && + sc.Match('*', '/')) { + sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (!setDoxygen.Contains(sc.ch)) { + char s[64]; + sc.GetCurrentLowered(s, sizeof(s)); + if (!IsASpace(sc.ch) || !keywords5.InList(s + 1)) { + sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR); + } + sc.SetState(styleBeforeDCKeyword); + } + break; + case SCE_FS_PREPROCESSOR: + case SCE_FS_PREPROCESSOR_C: + if (sc.atLineEnd) { + if (!(sc.chPrev == ';' || sc.GetRelative(-2) == ';')) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + } else if (stylingWithinPreprocessor) { + if (IsASpaceOrTab(sc.ch)) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + } else if (sc.Match('/', '*') || sc.Match('/', '/') || sc.Match('&', '&')) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_DISABLEDCODE: + if (sc.ch == '#' && visibleChars == 0) { + sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C); + do { // Skip whitespace between # and preprocessor word + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.MatchIgnoreCase("pragma")) { + sc.Forward(6); + do { // Skip more whitespace until keyword + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) { + bEnableCode = true; + sc.SetState(SCE_FS_DISABLEDCODE); + sc.Forward(sc.ch == '_' ? 8 : 6); + sc.ForwardSetState(SCE_FS_DEFAULT); + } else { + sc.ChangeState(SCE_FS_DISABLEDCODE); + } + } else { + sc.ChangeState(SCE_FS_DISABLEDCODE); + } + } + break; + case SCE_FS_DATE: + if (sc.ch == '}') { + sc.ForwardSetState(SCE_FS_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_FS_STRINGEOL); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_FS_DEFAULT || sc.state == SCE_FS_DEFAULT_C) { + if (bEnableCode && + (sc.MatchIgnoreCase(".and.") || sc.MatchIgnoreCase(".not."))) { + sc.SetState(SCE_FS_WORDOPERATOR); + sc.Forward(4); + } else if (bEnableCode && sc.MatchIgnoreCase(".or.")) { + sc.SetState(SCE_FS_WORDOPERATOR); + sc.Forward(3); + } else if (bEnableCode && + (sc.MatchIgnoreCase(".t.") || sc.MatchIgnoreCase(".f.") || + (!IsAWordChar(sc.GetRelative(3)) && sc.MatchIgnoreCase("nil")))) { + sc.SetState(SCE_FS_CONSTANT); + sc.Forward(2); + } else if (sc.Match('/', '*')) { + sc.SetState(bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C); + sc.Forward(); + } else if (bEnableCode && sc.Match('&', '&')) { + sc.SetState(SCE_FS_COMMENTLINE); + sc.Forward(); + } else if (sc.Match('/', '/')) { + sc.SetState(bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C); + sc.Forward(); + } else if (bEnableCode && sc.ch == '*' && visibleChars == 0) { + sc.SetState(SCE_FS_COMMENT); + } else if (sc.ch == '\"' || sc.ch == '\'') { + sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C); + closeStringChar = sc.ch; + } else if (closeStringChar == '>' && sc.ch == '<') { + sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C); + } else if (sc.ch == '#' && visibleChars == 0) { + sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C); + do { // Skip whitespace between # and preprocessor word + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.atLineEnd) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.MatchIgnoreCase("include")) { + if (stylingWithinPreprocessor) { + closeStringChar = '>'; + } + } else if (sc.MatchIgnoreCase("pragma")) { + sc.Forward(6); + do { // Skip more whitespace until keyword + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.MatchIgnoreCase("begindump") || sc.MatchIgnoreCase("__cstream")) { + bEnableCode = false; + if (stylingWithinPreprocessor) { + sc.SetState(SCE_FS_DISABLEDCODE); + sc.Forward(8); + sc.ForwardSetState(SCE_FS_DEFAULT_C); + } else { + sc.SetState(SCE_FS_DISABLEDCODE); + } + } else if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) { + bEnableCode = true; + sc.SetState(SCE_FS_DISABLEDCODE); + sc.Forward(sc.ch == '_' ? 8 : 6); + sc.ForwardSetState(SCE_FS_DEFAULT); + } + } + } else if (bEnableCode && sc.ch == '{') { + int p = 0; + int chSeek; + unsigned int endPos(startPos + length); + do { // Skip whitespace + chSeek = sc.GetRelative(++p); + } while (IsASpaceOrTab(chSeek) && (sc.currentPos + p < endPos)); + if (chSeek == '^') { + sc.SetState(SCE_FS_DATE); + } else { + sc.SetState(SCE_FS_OPERATOR); + } + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(bEnableCode ? SCE_FS_NUMBER : SCE_FS_NUMBER_C); + } else if (IsAWordChar(sc.ch)) { + sc.SetState(bEnableCode ? SCE_FS_IDENTIFIER : SCE_FS_IDENTIFIER_C); + } else if (isoperator(static_cast(sc.ch)) || (bEnableCode && sc.ch == '@')) { + sc.SetState(bEnableCode ? SCE_FS_OPERATOR : SCE_FS_OPERATOR_C); + } + } + + if (sc.atLineEnd) { + visibleChars = 0; + closeStringChar = 0; + } + if (!IsASpace(sc.ch)) { + visibleChars++; + } + } + sc.Complete(); +} + +static void FoldFlagShipDoc(unsigned int startPos, int length, int, + WordList *[], Accessor &styler) +{ + + int endPos = startPos + length; + + // Backtrack to previous line in case need to fix its fold status + int lineCurrent = styler.GetLine(startPos); + if (startPos > 0 && lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + int spaceFlags = 0; + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags); + char chNext = styler[startPos]; + for (int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos-1)) { + int lev = indentCurrent; + int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { + int spaceFlags2 = 0; + int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2); + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + } + } + indentCurrent = indentNext; + styler.SetLevel(lineCurrent, lev); + lineCurrent++; + } + } +} + +static const char * const FSWordListDesc[] = { + "Keywords Commands", + "Std Library Functions", + "Procedure, return, exit", + "Class (oop)", + "Doxygen keywords", + 0 +}; + +LexerModule lmFlagShip(SCLEX_FLAGSHIP, ColouriseFlagShipDoc, "flagship", FoldFlagShipDoc, FSWordListDesc); diff --git a/lexers/LexForth.cxx b/lexers/LexForth.cxx new file mode 100644 index 000000000..e52543fa5 --- /dev/null +++ b/lexers/LexForth.cxx @@ -0,0 +1,176 @@ +// Scintilla source code edit control +/** @file LexForth.cxx + ** Lexer for FORTH + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || + ch == '_' || ch == '?' || ch == '"' || ch == '@' || + ch == '!' || ch == '[' || ch == ']' || ch == '/' || + ch == '+' || ch == '-' || ch == '*' || ch == '<' || + ch == '>' || ch == '=' || ch == ';' || ch == '(' || + ch == ')' ); +} + +static inline bool IsAWordStart(int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.'); +} + +static inline bool IsANumChar(int ch) { + return (ch < 0x80) && (isxdigit(ch) || ch == '.' || ch == 'e' || ch == 'E' ); +} + +static inline bool IsASpaceChar(int ch) { + return (ch < 0x80) && isspace(ch); +} + +static void ColouriseForthDoc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[], + Accessor &styler) { + + WordList &control = *keywordLists[0]; + WordList &keyword = *keywordLists[1]; + WordList &defword = *keywordLists[2]; + WordList &preword1 = *keywordLists[3]; + WordList &preword2 = *keywordLists[4]; + WordList &strings = *keywordLists[5]; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) + { + // Determine if the current state should terminate. + if (sc.state == SCE_FORTH_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_FORTH_DEFAULT); + } + }else if (sc.state == SCE_FORTH_COMMENT_ML) { + if (sc.ch == ')') { + sc.ForwardSetState(SCE_FORTH_DEFAULT); + } + }else if (sc.state == SCE_FORTH_IDENTIFIER || sc.state == SCE_FORTH_NUMBER) { + // handle numbers here too, because what we thought was a number might + // turn out to be a keyword e.g. 2DUP + if (IsASpaceChar(sc.ch) ) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + int newState = sc.state == SCE_FORTH_NUMBER ? SCE_FORTH_NUMBER : SCE_FORTH_DEFAULT; + if (control.InList(s)) { + sc.ChangeState(SCE_FORTH_CONTROL); + } else if (keyword.InList(s)) { + sc.ChangeState(SCE_FORTH_KEYWORD); + } else if (defword.InList(s)) { + sc.ChangeState(SCE_FORTH_DEFWORD); + } else if (preword1.InList(s)) { + sc.ChangeState(SCE_FORTH_PREWORD1); + } else if (preword2.InList(s)) { + sc.ChangeState(SCE_FORTH_PREWORD2); + } else if (strings.InList(s)) { + sc.ChangeState(SCE_FORTH_STRING); + newState = SCE_FORTH_STRING; + } + sc.SetState(newState); + } + if (sc.state == SCE_FORTH_NUMBER) { + if (IsASpaceChar(sc.ch)) { + sc.SetState(SCE_FORTH_DEFAULT); + } else if (!IsANumChar(sc.ch)) { + sc.ChangeState(SCE_FORTH_IDENTIFIER); + } + } + }else if (sc.state == SCE_FORTH_STRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_FORTH_DEFAULT); + } + }else if (sc.state == SCE_FORTH_LOCALE) { + if (sc.ch == '}') { + sc.ForwardSetState(SCE_FORTH_DEFAULT); + } + }else if (sc.state == SCE_FORTH_DEFWORD) { + if (IsASpaceChar(sc.ch)) { + sc.SetState(SCE_FORTH_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_FORTH_DEFAULT) { + if (sc.ch == '\\'){ + sc.SetState(SCE_FORTH_COMMENT); + } else if (sc.ch == '(' && + (sc.atLineStart || IsASpaceChar(sc.chPrev)) && + (sc.atLineEnd || IsASpaceChar(sc.chNext))) { + sc.SetState(SCE_FORTH_COMMENT_ML); + } else if ( (sc.ch == '$' && (isascii(sc.chNext) && isxdigit(sc.chNext))) ) { + // number starting with $ is a hex number + sc.SetState(SCE_FORTH_NUMBER); + while(sc.More() && isascii(sc.chNext) && isxdigit(sc.chNext)) + sc.Forward(); + } else if ( (sc.ch == '%' && (isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))) ) { + // number starting with % is binary + sc.SetState(SCE_FORTH_NUMBER); + while(sc.More() && isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1')) + sc.Forward(); + } else if ( isascii(sc.ch) && + (isxdigit(sc.ch) || ((sc.ch == '.' || sc.ch == '-') && isascii(sc.chNext) && isxdigit(sc.chNext)) ) + ){ + sc.SetState(SCE_FORTH_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_FORTH_IDENTIFIER); + } else if (sc.ch == '{') { + sc.SetState(SCE_FORTH_LOCALE); + } else if (sc.ch == ':' && isascii(sc.chNext) && isspace(sc.chNext)) { + // highlight word definitions e.g. : GCD ( n n -- n ) ..... ; + // ^ ^^^ + sc.SetState(SCE_FORTH_DEFWORD); + while(sc.More() && isascii(sc.chNext) && isspace(sc.chNext)) + sc.Forward(); + } else if (sc.ch == ';' && + (sc.atLineStart || IsASpaceChar(sc.chPrev)) && + (sc.atLineEnd || IsASpaceChar(sc.chNext)) ) { + // mark the ';' that ends a word + sc.SetState(SCE_FORTH_DEFWORD); + sc.ForwardSetState(SCE_FORTH_DEFAULT); + } + } + + } + sc.Complete(); +} + +static void FoldForthDoc(unsigned int, int, int, WordList *[], + Accessor &) { +} + +static const char * const forthWordLists[] = { + "control keywords", + "keywords", + "definition words", + "prewords with one argument", + "prewords with two arguments", + "string definition keywords", + 0, + }; + +LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth", FoldForthDoc, forthWordLists); + + diff --git a/lexers/LexFortran.cxx b/lexers/LexFortran.cxx new file mode 100644 index 000000000..0b3f2777c --- /dev/null +++ b/lexers/LexFortran.cxx @@ -0,0 +1,466 @@ +// Scintilla source code edit control +/** @file LexFortran.cxx + ** Lexer for Fortran. + ** Writen by Chuan-jian Shen, Last changed Sep. 2003 + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. +/***************************************/ +#include +#include +#include +#include +#include +/***************************************/ +#include "Platform.h" +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +/***********************************************/ +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '%'); +} +/**********************************************/ +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch)); +} +/***************************************/ +inline bool IsABlank(unsigned int ch) { + return (ch == ' ') || (ch == 0x09) || (ch == 0x0b) ; +} +/***************************************/ +inline bool IsALineEnd(char ch) { + return ((ch == '\n') || (ch == '\r')) ; +} +/***************************************/ +unsigned int GetContinuedPos(unsigned int pos, Accessor &styler) { + while (!IsALineEnd(styler.SafeGetCharAt(pos++))) continue; + if (styler.SafeGetCharAt(pos) == '\n') pos++; + while (IsABlank(styler.SafeGetCharAt(pos++))) continue; + char chCur = styler.SafeGetCharAt(pos); + if (chCur == '&') { + while (IsABlank(styler.SafeGetCharAt(++pos))) continue; + return pos; + } else { + return pos; + } +} +/***************************************/ +static void ColouriseFortranDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler, bool isFixFormat) { + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + /***************************************/ + int posLineStart = 0, numNonBlank = 0, prevState = 0; + int endPos = startPos + length; + /***************************************/ + // backtrack to the nearest keyword + while ((startPos > 1) && (styler.StyleAt(startPos) != SCE_F_WORD)) { + startPos--; + } + startPos = styler.LineStart(styler.GetLine(startPos)); + initStyle = styler.StyleAt(startPos - 1); + StyleContext sc(startPos, endPos-startPos, initStyle, styler); + /***************************************/ + for (; sc.More(); sc.Forward()) { + // remember the start position of the line + if (sc.atLineStart) { + posLineStart = sc.currentPos; + numNonBlank = 0; + sc.SetState(SCE_F_DEFAULT); + } + if (!IsASpaceOrTab(sc.ch)) numNonBlank ++; + /***********************************************/ + // Handle the fix format generically + int toLineStart = sc.currentPos - posLineStart; + if (isFixFormat && (toLineStart < 6 || toLineStart > 72)) { + if ((toLineStart == 0 && (tolower(sc.ch) == 'c' || sc.ch == '*')) || sc.ch == '!') { + if (sc.MatchIgnoreCase("cdec$") || sc.MatchIgnoreCase("*dec$") || sc.MatchIgnoreCase("!dec$") || + sc.MatchIgnoreCase("cdir$") || sc.MatchIgnoreCase("*dir$") || sc.MatchIgnoreCase("!dir$") || + sc.MatchIgnoreCase("cms$") || sc.MatchIgnoreCase("*ms$") || sc.MatchIgnoreCase("!ms$") || + sc.chNext == '$') { + sc.SetState(SCE_F_PREPROCESSOR); + } else { + sc.SetState(SCE_F_COMMENT); + } + + while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end + } else if (toLineStart > 72) { + sc.SetState(SCE_F_COMMENT); + while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end + } else if (toLineStart < 5) { + if (IsADigit(sc.ch)) + sc.SetState(SCE_F_LABEL); + else + sc.SetState(SCE_F_DEFAULT); + } else if (toLineStart == 5) { + if (!IsASpace(sc.ch) && sc.ch != '0') { + sc.SetState(SCE_F_CONTINUATION); + sc.ForwardSetState(prevState); + } else + sc.SetState(SCE_F_DEFAULT); + } + continue; + } + /***************************************/ + // Handle line continuation generically. + if (!isFixFormat && sc.ch == '&') { + char chTemp = ' '; + int j = 1; + while (IsABlank(chTemp) && j<132) { + chTemp = static_cast(sc.GetRelative(j)); + j++; + } + if (chTemp == '!') { + sc.SetState(SCE_F_CONTINUATION); + if (sc.chNext == '!') sc.ForwardSetState(SCE_F_COMMENT); + } else if (chTemp == '\r' || chTemp == '\n') { + int currentState = sc.state; + sc.SetState(SCE_F_CONTINUATION); + sc.ForwardSetState(SCE_F_DEFAULT); + while (IsASpace(sc.ch) && sc.More()) sc.Forward(); + if (sc.ch == '&') { + sc.SetState(SCE_F_CONTINUATION); + sc.Forward(); + } + sc.SetState(currentState); + } + } + /***************************************/ + // Determine if the current state should terminate. + if (sc.state == SCE_F_OPERATOR) { + sc.SetState(SCE_F_DEFAULT); + } else if (sc.state == SCE_F_NUMBER) { + if (!(IsAWordChar(sc.ch) || sc.ch=='\'' || sc.ch=='\"' || sc.ch=='.')) { + sc.SetState(SCE_F_DEFAULT); + } + } else if (sc.state == SCE_F_IDENTIFIER) { + if (!IsAWordChar(sc.ch) || (sc.ch == '%')) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_F_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_F_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_F_WORD3); + } + sc.SetState(SCE_F_DEFAULT); + } + } else if (sc.state == SCE_F_COMMENT || sc.state == SCE_F_PREPROCESSOR) { + if (sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_F_DEFAULT); + } + } else if (sc.state == SCE_F_STRING1) { + prevState = sc.state; + if (sc.ch == '\'') { + if (sc.chNext == '\'') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_F_DEFAULT); + prevState = SCE_F_DEFAULT; + } + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_F_STRINGEOL); + sc.ForwardSetState(SCE_F_DEFAULT); + } + } else if (sc.state == SCE_F_STRING2) { + prevState = sc.state; + if (sc.atLineEnd) { + sc.ChangeState(SCE_F_STRINGEOL); + sc.ForwardSetState(SCE_F_DEFAULT); + } else if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_F_DEFAULT); + prevState = SCE_F_DEFAULT; + } + } + } else if (sc.state == SCE_F_OPERATOR2) { + if (sc.ch == '.') { + sc.ForwardSetState(SCE_F_DEFAULT); + } + } else if (sc.state == SCE_F_CONTINUATION) { + sc.SetState(SCE_F_DEFAULT); + } else if (sc.state == SCE_F_LABEL) { + if (!IsADigit(sc.ch)) { + sc.SetState(SCE_F_DEFAULT); + } else { + if (isFixFormat && sc.currentPos-posLineStart > 4) + sc.SetState(SCE_F_DEFAULT); + else if (numNonBlank > 5) + sc.SetState(SCE_F_DEFAULT); + } + } + /***************************************/ + // Determine if a new state should be entered. + if (sc.state == SCE_F_DEFAULT) { + if (sc.ch == '!') { + if (sc.MatchIgnoreCase("!dec$") || sc.MatchIgnoreCase("!dir$") || + sc.MatchIgnoreCase("!ms$") || sc.chNext == '$') { + sc.SetState(SCE_F_PREPROCESSOR); + } else { + sc.SetState(SCE_F_COMMENT); + } + } else if ((!isFixFormat) && IsADigit(sc.ch) && numNonBlank == 1) { + sc.SetState(SCE_F_LABEL); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_F_NUMBER); + } else if ((tolower(sc.ch) == 'b' || tolower(sc.ch) == 'o' || + tolower(sc.ch) == 'z') && (sc.chNext == '\"' || sc.chNext == '\'')) { + sc.SetState(SCE_F_NUMBER); + sc.Forward(); + } else if (sc.ch == '.' && isalpha(sc.chNext)) { + sc.SetState(SCE_F_OPERATOR2); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_F_IDENTIFIER); + } else if (sc.ch == '\"') { + sc.SetState(SCE_F_STRING2); + } else if (sc.ch == '\'') { + sc.SetState(SCE_F_STRING1); + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_F_OPERATOR); + } + } + } + sc.Complete(); +} +/***************************************/ +// To determine the folding level depending on keywords +static int classifyFoldPointFortran(const char* s, const char* prevWord, const char chNextNonBlank) { + int lev = 0; + if ((strcmp(prevWord, "else") == 0 && strcmp(s, "if") == 0) || strcmp(s, "elseif") == 0) + return -1; + if (strcmp(s, "associate") == 0 || strcmp(s, "block") == 0 + || strcmp(s, "blockdata") == 0 || strcmp(s, "select") == 0 + || strcmp(s, "do") == 0 || strcmp(s, "enum") ==0 + || strcmp(s, "function") == 0 || strcmp(s, "interface") == 0 + || strcmp(s, "module") == 0 || strcmp(s, "program") == 0 + || strcmp(s, "subroutine") == 0 || strcmp(s, "then") == 0 + || (strcmp(s, "type") == 0 && chNextNonBlank != '(') ){ + if (strcmp(prevWord, "end") == 0) + lev = 0; + else + lev = 1; + } else if ((strcmp(s, "end") == 0 && chNextNonBlank != '=') + || strcmp(s, "endassociate") == 0 || strcmp(s, "endblock") == 0 + || strcmp(s, "endblockdata") == 0 || strcmp(s, "endselect") == 0 + || strcmp(s, "enddo") == 0 || strcmp(s, "endenum") ==0 + || strcmp(s, "endif") == 0 || strcmp(s, "endforall") == 0 + || strcmp(s, "endfunction") == 0 || strcmp(s, "endinterface") == 0 + || strcmp(s, "endmodule") == 0 || strcmp(s, "endprogram") == 0 + || strcmp(s, "endsubroutine") == 0 || strcmp(s, "endtype") == 0 + || strcmp(s, "endwhere") == 0 + || strcmp(s, "procedure") == 0 ) { // Take care of the module procedure statement + lev = -1; + } else if (strcmp(prevWord, "end") == 0 && strcmp(s, "if") == 0){ // end if + lev = 0; + } + return lev; +} +// Folding the code +static void FoldFortranDoc(unsigned int startPos, int length, int initStyle, + Accessor &styler, bool isFixFormat) { + // + // bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + // Do not know how to fold the comment at the moment. + // + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + char chNextNonBlank; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + /***************************************/ + int lastStart = 0; + char prevWord[32] = ""; + char Label[6] = ""; + // Variables for do label folding. + static int doLabels[100]; + static int posLabel=-1; + /***************************************/ + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + chNextNonBlank = chNext; + unsigned int j=i+1; + while(IsABlank(chNextNonBlank) && j(tolower(styler[lastStart+k])); + } + s[k] = '\0'; + // Handle the forall and where statement and structure. + if (strcmp(s, "forall") == 0 || strcmp(s, "where") == 0) { + if (strcmp(prevWord, "end") != 0) { + j = i + 1; + char chBrace = '(', chSeek = ')', ch1 = styler.SafeGetCharAt(j); + // Find the position of the first ( + while (ch1 != chBrace && j -1) { + levelCurrent--; + posLabel--; + } + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + strcpy(prevWord, ""); + } + /***************************************/ + if (!isspacechar(ch)) visibleChars++; + } + /***************************************/ + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} +/***************************************/ +static const char * const FortranWordLists[] = { + "Primary keywords and identifiers", + "Intrinsic functions", + "Extended and user defined functions", + 0, +}; +/***************************************/ +static void ColouriseFortranDocFreeFormat(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + ColouriseFortranDoc(startPos, length, initStyle, keywordlists, styler, false); +} +/***************************************/ +static void ColouriseFortranDocFixFormat(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + ColouriseFortranDoc(startPos, length, initStyle, keywordlists, styler, true); +} +/***************************************/ +static void FoldFortranDocFreeFormat(unsigned int startPos, int length, int initStyle, + WordList *[], Accessor &styler) { + FoldFortranDoc(startPos, length, initStyle,styler, false); +} +/***************************************/ +static void FoldFortranDocFixFormat(unsigned int startPos, int length, int initStyle, + WordList *[], Accessor &styler) { + FoldFortranDoc(startPos, length, initStyle,styler, true); +} +/***************************************/ +LexerModule lmFortran(SCLEX_FORTRAN, ColouriseFortranDocFreeFormat, "fortran", FoldFortranDocFreeFormat, FortranWordLists); +LexerModule lmF77(SCLEX_F77, ColouriseFortranDocFixFormat, "f77", FoldFortranDocFixFormat, FortranWordLists); diff --git a/lexers/LexGAP.cxx b/lexers/LexGAP.cxx new file mode 100644 index 000000000..fb6e739bd --- /dev/null +++ b/lexers/LexGAP.cxx @@ -0,0 +1,263 @@ +// Scintilla source code edit control +/** @file LexGAP.cxx + ** Lexer for the GAP language. (The GAP System for Computational Discrete Algebra) + ** http://www.gap-system.org + **/ +// Copyright 2007 by Istvan Szollosi ( szteven gmail com ) +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsGAPOperator(char ch) { + if (isascii(ch) && isalnum(ch)) return false; + if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || + ch == '^' || ch == ',' || ch == '!' || ch == '.' || + ch == '=' || ch == '<' || ch == '>' || ch == '(' || + ch == ')' || ch == ';' || ch == '[' || ch == ']' || + ch == '{' || ch == '}' || ch == ':' ) + return true; + return false; +} + +static void GetRange(unsigned int start, unsigned int end, Accessor &styler, char *s, unsigned int len) { + unsigned int i = 0; + while ((i < end - start + 1) && (i < len-1)) { + s[i] = static_cast(styler[start + i]); + i++; + } + s[i] = '\0'; +} + +static void ColouriseGAPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { + + WordList &keywords1 = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + + // Do not leak onto next line + if (initStyle == SCE_GAP_STRINGEOL) initStyle = SCE_GAP_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + // Prevent SCE_GAP_STRINGEOL from leaking back to previous line + if ( sc.atLineStart ) { + if (sc.state == SCE_GAP_STRING) sc.SetState(SCE_GAP_STRING); + if (sc.state == SCE_GAP_CHAR) sc.SetState(SCE_GAP_CHAR); + } + + // Handle line continuation generically + if (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 + switch (sc.state) { + case SCE_GAP_OPERATOR : + sc.SetState(SCE_GAP_DEFAULT); + break; + + case SCE_GAP_NUMBER : + if (!IsADigit(sc.ch)) { + if (sc.ch == '\\') { + if (!sc.atLineEnd) { + if (!IsADigit(sc.chNext)) { + sc.Forward(); + sc.ChangeState(SCE_GAP_IDENTIFIER); + } + } + } else if (isalpha(sc.ch) || sc.ch == '_') { + sc.ChangeState(SCE_GAP_IDENTIFIER); + } + else sc.SetState(SCE_GAP_DEFAULT); + } + break; + + case SCE_GAP_IDENTIFIER : + if (!(iswordstart(static_cast(sc.ch)) || sc.ch == '$')) { + if (sc.ch == '\\') sc.Forward(); + else { + char s[1000]; + sc.GetCurrent(s, sizeof(s)); + if (keywords1.InList(s)) { + sc.ChangeState(SCE_GAP_KEYWORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_GAP_KEYWORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_GAP_KEYWORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_GAP_KEYWORD4); + } + sc.SetState(SCE_GAP_DEFAULT); + } + } + break; + + case SCE_GAP_COMMENT : + if (sc.atLineEnd) { + sc.SetState(SCE_GAP_DEFAULT); + } + break; + + case SCE_GAP_STRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_GAP_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_GAP_DEFAULT); + } + break; + + case SCE_GAP_CHAR: + if (sc.atLineEnd) { + sc.ChangeState(SCE_GAP_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_GAP_DEFAULT); + } + break; + + case SCE_GAP_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_GAP_DEFAULT); + } + break; + } + + // Determine if a new state should be entered + if (sc.state == SCE_GAP_DEFAULT) { + if (IsGAPOperator(static_cast(sc.ch))) { + sc.SetState(SCE_GAP_OPERATOR); + } + else if (IsADigit(sc.ch)) { + sc.SetState(SCE_GAP_NUMBER); + } else if (isalpha(sc.ch) || sc.ch == '_' || sc.ch == '\\' || sc.ch == '$' || sc.ch == '~') { + sc.SetState(SCE_GAP_IDENTIFIER); + if (sc.ch == '\\') sc.Forward(); + } else if (sc.ch == '#') { + sc.SetState(SCE_GAP_COMMENT); + } else if (sc.ch == '\"') { + sc.SetState(SCE_GAP_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_GAP_CHAR); + } + } + + } + sc.Complete(); +} + +static int ClassifyFoldPointGAP(const char* s) { + int level = 0; + if (strcmp(s, "function") == 0 || + strcmp(s, "do") == 0 || + strcmp(s, "if") == 0 || + strcmp(s, "repeat") == 0 ) { + level = 1; + } else if (strcmp(s, "end") == 0 || + strcmp(s, "od") == 0 || + strcmp(s, "fi") == 0 || + strcmp(s, "until") == 0 ) { + level = -1; + } + return level; +} + +static void FoldGAPDoc( unsigned int startPos, int length, int initStyle, WordList** , Accessor &styler) { + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + + int lastStart = 0; + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (stylePrev != SCE_GAP_KEYWORD && style == SCE_GAP_KEYWORD) { + // Store last word start point. + lastStart = i; + } + + if (stylePrev == SCE_GAP_KEYWORD) { + if(iswordchar(ch) && !iswordchar(chNext)) { + char s[100]; + GetRange(lastStart, i, styler, s, sizeof(s)); + levelCurrent += ClassifyFoldPointGAP(s); + } + } + + if (atEOL) { + int lev = levelPrev; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + + if (!isspacechar(ch)) + visibleChars++; + } + + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const GAPWordListDesc[] = { + "Keywords 1", + "Keywords 2", + "Keywords 3 (unused)", + "Keywords 4 (unused)", + 0 +}; + +LexerModule lmGAP( + SCLEX_GAP, + ColouriseGAPDoc, + "gap", + FoldGAPDoc, + GAPWordListDesc); diff --git a/lexers/LexGui4Cli.cxx b/lexers/LexGui4Cli.cxx new file mode 100644 index 000000000..1c92de72e --- /dev/null +++ b/lexers/LexGui4Cli.cxx @@ -0,0 +1,313 @@ +// Scintilla source code edit control +// Copyright 1998-2002 by Neil Hodgson +/* +This is the Lexer for Gui4Cli, included in SciLexer.dll +- by d. Keletsekis, 2/10/2003 + +To add to SciLexer.dll: +1. Add the values below to INCLUDE\Scintilla.iface +2. Run the include/HFacer.py script +3. Run the src/lexGen.py script + +val SCE_GC_DEFAULT=0 +val SCE_GC_COMMENTLINE=1 +val SCE_GC_COMMENTBLOCK=2 +val SCE_GC_GLOBAL=3 +val SCE_GC_EVENT=4 +val SCE_GC_ATTRIBUTE=5 +val SCE_GC_CONTROL=6 +val SCE_GC_COMMAND=7 +val SCE_GC_STRING=8 +val SCE_GC_OPERATOR=9 +*/ + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#define debug Platform::DebugPrintf + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch =='\\'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.'); +} + +inline bool isGCOperator(int ch) +{ if (isalnum(ch)) + return false; + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || ch == '%' || + ch == '[' || ch == ']' || ch == '<' || ch == '>' || + ch == ',' || ch == ';' || ch == ':') + return true; + return false; +} + +#define isSpace(x) ((x)==' ' || (x)=='\t') +#define isNL(x) ((x)=='\n' || (x)=='\r') +#define isSpaceOrNL(x) (isSpace(x) || isNL(x)) +#define BUFFSIZE 500 +#define isFoldPoint(x) ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024) + +static void colorFirstWord(WordList *keywordlists[], Accessor &styler, + StyleContext *sc, char *buff, int length, int) +{ + int c = 0; + while (sc->More() && isSpaceOrNL(sc->ch)) + { sc->Forward(); + } + styler.ColourTo(sc->currentPos - 1, sc->state); + + if (!IsAWordChar(sc->ch)) // comment, marker, etc.. + return; + + while (sc->More() && !isSpaceOrNL(sc->ch) && (c < length-1) && !isGCOperator(sc->ch)) + { buff[c] = static_cast(sc->ch); + ++c; sc->Forward(); + } + buff[c] = '\0'; + char *p = buff; + while (*p) // capitalize.. + { if (islower(*p)) *p = static_cast(toupper(*p)); + ++p; + } + + WordList &kGlobal = *keywordlists[0]; // keyword lists set by the user + WordList &kEvent = *keywordlists[1]; + WordList &kAttribute = *keywordlists[2]; + WordList &kControl = *keywordlists[3]; + WordList &kCommand = *keywordlists[4]; + + int state = 0; + // int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK; + // debug ("line = %d, level = %d", line, level); + + if (kGlobal.InList(buff)) state = SCE_GC_GLOBAL; + else if (kAttribute.InList(buff)) state = SCE_GC_ATTRIBUTE; + else if (kControl.InList(buff)) state = SCE_GC_CONTROL; + else if (kCommand.InList(buff)) state = SCE_GC_COMMAND; + else if (kEvent.InList(buff)) state = SCE_GC_EVENT; + + if (state) + { sc->ChangeState(state); + styler.ColourTo(sc->currentPos - 1, sc->state); + sc->ChangeState(SCE_GC_DEFAULT); + } + else + { sc->ChangeState(SCE_GC_DEFAULT); + styler.ColourTo(sc->currentPos - 1, sc->state); + } +} + +// Main colorizing function called by Scintilla +static void +ColouriseGui4CliDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) +{ + styler.StartAt(startPos); + + int quotestart = 0, oldstate, currentline = styler.GetLine(startPos); + styler.StartSegment(startPos); + bool noforward; + char buff[BUFFSIZE+1]; // buffer for command name + + StyleContext sc(startPos, length, initStyle, styler); + buff[0] = '\0'; // cbuff = 0; + + if (sc.state != SCE_GC_COMMENTBLOCK) // colorize 1st word.. + colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); + + while (sc.More()) + { noforward = 0; + + switch (sc.ch) + { + case '/': + if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_STRING) + break; + if (sc.chNext == '/') // line comment + { sc.SetState (SCE_GC_COMMENTLINE); + sc.Forward(); + styler.ColourTo(sc.currentPos, sc.state); + } + else if (sc.chNext == '*') // block comment + { sc.SetState(SCE_GC_COMMENTBLOCK); + sc.Forward(); + styler.ColourTo(sc.currentPos, sc.state); + } + else + styler.ColourTo(sc.currentPos, sc.state); + break; + + case '*': // end of comment block, or operator.. + if (sc.state == SCE_GC_STRING) + break; + if (sc.state == SCE_GC_COMMENTBLOCK && sc.chNext == '/') + { sc.Forward(); + styler.ColourTo(sc.currentPos, sc.state); + sc.ChangeState (SCE_GC_DEFAULT); + } + else + styler.ColourTo(sc.currentPos, sc.state); + break; + + case '\'': case '\"': // strings.. + if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_COMMENTLINE) + break; + if (sc.state == SCE_GC_STRING) + { if (sc.ch == quotestart) // match same quote char.. + { styler.ColourTo(sc.currentPos, sc.state); + sc.ChangeState(SCE_GC_DEFAULT); + quotestart = 0; + } } + else + { styler.ColourTo(sc.currentPos - 1, sc.state); + sc.ChangeState(SCE_GC_STRING); + quotestart = sc.ch; + } + break; + + case ';': // end of commandline character + if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE && + sc.state != SCE_GC_STRING) + { + styler.ColourTo(sc.currentPos - 1, sc.state); + styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); + sc.ChangeState(SCE_GC_DEFAULT); + sc.Forward(); + colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); + noforward = 1; // don't move forward - already positioned at next char.. + } + break; + + case '+': case '-': case '=': case '!': // operators.. + case '<': case '>': case '&': case '|': case '$': + if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE && + sc.state != SCE_GC_STRING) + { + styler.ColourTo(sc.currentPos - 1, sc.state); + styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); + sc.ChangeState(SCE_GC_DEFAULT); + } + break; + + case '\\': // escape - same as operator, but also mark in strings.. + if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE) + { + oldstate = sc.state; + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(); // mark also the next char.. + styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); + sc.ChangeState(oldstate); + } + break; + + case '\n': case '\r': + ++currentline; + if (sc.state == SCE_GC_COMMENTLINE) + { styler.ColourTo(sc.currentPos, sc.state); + sc.ChangeState (SCE_GC_DEFAULT); + } + else if (sc.state != SCE_GC_COMMENTBLOCK) + { colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); + noforward = 1; // don't move forward - already positioned at next char.. + } + break; + +// case ' ': case '\t': +// default : + } + + if (!noforward) sc.Forward(); + + } + sc.Complete(); +} + +// Main folding function called by Scintilla - (based on props (.ini) files function) +static void FoldGui4Cli(unsigned int startPos, int length, int, + WordList *[], Accessor &styler) +{ + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + bool headerPoint = false; + + for (unsigned int i = startPos; i < endPos; i++) + { + char ch = chNext; + chNext = styler[i+1]; + + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (style == SCE_GC_EVENT || style == SCE_GC_GLOBAL) + { headerPoint = true; // fold at events and globals + } + + if (atEOL) + { int lev = SC_FOLDLEVELBASE+1; + + if (headerPoint) + lev = SC_FOLDLEVELBASE; + + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + + if (headerPoint) + lev |= SC_FOLDLEVELHEADERFLAG; + + if (lev != styler.LevelAt(lineCurrent)) // set level, if not already correct + { styler.SetLevel(lineCurrent, lev); + } + + lineCurrent++; // re-initialize our flags + visibleChars = 0; + headerPoint = false; + } + + if (!(isspacechar(ch))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK))) + visibleChars++; + } + + int lev = headerPoint ? SC_FOLDLEVELBASE : SC_FOLDLEVELBASE+1; + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, lev | flagsNext); +} + +// I have no idea what these are for.. probably accessible by some message. +static const char * const gui4cliWordListDesc[] = { + "Globals", "Events", "Attributes", "Control", "Commands", + 0 +}; + +// Declare language & pass our function pointers to Scintilla +LexerModule lmGui4Cli(SCLEX_GUI4CLI, ColouriseGui4CliDoc, "gui4cli", FoldGui4Cli, gui4cliWordListDesc); + +#undef debug + diff --git a/lexers/LexHTML.cxx b/lexers/LexHTML.cxx new file mode 100644 index 000000000..ed9db9763 --- /dev/null +++ b/lexers/LexHTML.cxx @@ -0,0 +1,2132 @@ +// Scintilla source code edit control +/** @file LexHTML.cxx + ** Lexer for HTML. + **/ +// Copyright 1998-2005 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "CharacterSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#define SCE_HA_JS (SCE_HJA_START - SCE_HJ_START) +#define SCE_HA_VBS (SCE_HBA_START - SCE_HB_START) +#define SCE_HA_PYTHON (SCE_HPA_START - SCE_HP_START) + +enum script_type { eScriptNone = 0, eScriptJS, eScriptVBS, eScriptPython, eScriptPHP, eScriptXML, eScriptSGML, eScriptSGMLblock, eScriptComment }; +enum script_mode { eHtml = 0, eNonHtmlScript, eNonHtmlPreProc, eNonHtmlScriptPreProc }; + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +inline bool IsOperator(int ch) { + if (isascii(ch) && isalnum(ch)) + return false; + // '.' left out as it is used to make up numbers + if (ch == '%' || ch == '^' || ch == '&' || ch == '*' || + ch == '(' || ch == ')' || ch == '-' || ch == '+' || + ch == '=' || ch == '|' || ch == '{' || ch == '}' || + ch == '[' || ch == ']' || ch == ':' || ch == ';' || + ch == '<' || ch == '>' || ch == ',' || ch == '/' || + ch == '?' || ch == '!' || ch == '.' || ch == '~') + return true; + return false; +} + +static inline int MakeLowerCase(int ch) { + if (ch < 'A' || ch > 'Z') + return ch; + else + return ch - 'A' + 'a'; +} + +static void GetTextSegment(Accessor &styler, unsigned int start, unsigned int end, char *s, size_t len) { + size_t i = 0; + for (; (i < end - start + 1) && (i < len-1); i++) { + s[i] = static_cast(MakeLowerCase(styler[start + i])); + } + s[i] = '\0'; +} + +static const char *GetNextWord(Accessor &styler, unsigned int start, char *s, size_t sLen) { + + size_t i = 0; + for (; i < sLen-1; i++) { + char ch = static_cast(styler.SafeGetCharAt(start + i)); + if ((i == 0) && !IsAWordStart(ch)) + break; + if ((i > 0) && !IsAWordChar(ch)) + break; + s[i] = ch; + } + s[i] = '\0'; + + return s; +} + +static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start, unsigned int end, script_type prevValue) { + char s[100]; + GetTextSegment(styler, start, end, s, sizeof(s)); + //Platform::DebugPrintf("Scripting indicator [%s]\n", s); + if (strstr(s, "src")) // External script + return eScriptNone; + if (strstr(s, "vbs")) + return eScriptVBS; + if (strstr(s, "pyth")) + return eScriptPython; + if (strstr(s, "javas")) + return eScriptJS; + if (strstr(s, "jscr")) + return eScriptJS; + if (strstr(s, "php")) + return eScriptPHP; + if (strstr(s, "xml")) { + const char *xml = strstr(s, "xml"); + for (const char *t=s; t= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) { + return eScriptPython; + } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) { + return eScriptVBS; + } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) { + return eScriptJS; + } else if ((state >= SCE_HPHP_DEFAULT) && (state <= SCE_HPHP_COMMENTLINE)) { + return eScriptPHP; + } else if ((state >= SCE_H_SGML_DEFAULT) && (state < SCE_H_SGML_BLOCK_DEFAULT)) { + return eScriptSGML; + } else if (state == SCE_H_SGML_BLOCK_DEFAULT) { + return eScriptSGMLblock; + } else { + return eScriptNone; + } +} + +static int statePrintForState(int state, script_mode inScriptType) { + int StateToPrint = state; + + if (state >= SCE_HJ_START) { + if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) { + StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_PYTHON); + } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) { + StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_VBS); + } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) { + StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_JS); + } + } + + return StateToPrint; +} + +static int stateForPrintState(int StateToPrint) { + int state; + + if ((StateToPrint >= SCE_HPA_START) && (StateToPrint <= SCE_HPA_IDENTIFIER)) { + state = StateToPrint - SCE_HA_PYTHON; + } else if ((StateToPrint >= SCE_HBA_START) && (StateToPrint <= SCE_HBA_STRINGEOL)) { + state = StateToPrint - SCE_HA_VBS; + } else if ((StateToPrint >= SCE_HJA_START) && (StateToPrint <= SCE_HJA_REGEX)) { + state = StateToPrint - SCE_HA_JS; + } else { + state = StateToPrint; + } + + return state; +} + +static inline bool IsNumber(unsigned int start, Accessor &styler) { + return IsADigit(styler[start]) || (styler[start] == '.') || + (styler[start] == '-') || (styler[start] == '#'); +} + +static inline bool isStringState(int state) { + bool bResult; + + switch (state) { + case SCE_HJ_DOUBLESTRING: + case SCE_HJ_SINGLESTRING: + case SCE_HJA_DOUBLESTRING: + case SCE_HJA_SINGLESTRING: + case SCE_HB_STRING: + case SCE_HBA_STRING: + case SCE_HP_STRING: + case SCE_HP_CHARACTER: + case SCE_HP_TRIPLE: + case SCE_HP_TRIPLEDOUBLE: + case SCE_HPA_STRING: + case SCE_HPA_CHARACTER: + case SCE_HPA_TRIPLE: + case SCE_HPA_TRIPLEDOUBLE: + case SCE_HPHP_HSTRING: + case SCE_HPHP_SIMPLESTRING: + case SCE_HPHP_HSTRING_VARIABLE: + case SCE_HPHP_COMPLEX_VARIABLE: + bResult = true; + break; + default : + bResult = false; + break; + } + return bResult; +} + +static inline bool stateAllowsTermination(int state) { + bool allowTermination = !isStringState(state); + if (allowTermination) { + switch (state) { + case SCE_HB_COMMENTLINE: + case SCE_HPHP_COMMENT: + case SCE_HP_COMMENTLINE: + case SCE_HPA_COMMENTLINE: + allowTermination = false; + } + } + return allowTermination; +} + +// not really well done, since it's only comments that should lex the %> and <% +static inline bool isCommentASPState(int state) { + bool bResult; + + switch (state) { + case SCE_HJ_COMMENT: + case SCE_HJ_COMMENTLINE: + case SCE_HJ_COMMENTDOC: + case SCE_HB_COMMENTLINE: + case SCE_HP_COMMENTLINE: + case SCE_HPHP_COMMENT: + case SCE_HPHP_COMMENTLINE: + bResult = true; + break; + default : + bResult = false; + break; + } + return bResult; +} + +static void classifyAttribHTML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { + bool wordIsNumber = IsNumber(start, styler); + char chAttr = SCE_H_ATTRIBUTEUNKNOWN; + if (wordIsNumber) { + chAttr = SCE_H_NUMBER; + } else { + char s[100]; + GetTextSegment(styler, start, end, s, sizeof(s)); + if (keywords.InList(s)) + chAttr = SCE_H_ATTRIBUTE; + } + if ((chAttr == SCE_H_ATTRIBUTEUNKNOWN) && !keywords) + // No keywords -> all are known + chAttr = SCE_H_ATTRIBUTE; + styler.ColourTo(end, chAttr); +} + +static int classifyTagHTML(unsigned int start, unsigned int end, + WordList &keywords, Accessor &styler, bool &tagDontFold, + bool caseSensitive, bool isXml, bool allowScripts) { + char s[30 + 2]; + // Copy after the '<' + unsigned int i = 0; + for (unsigned int cPos = start; cPos <= end && i < 30; cPos++) { + char ch = styler[cPos]; + if ((ch != '<') && (ch != '/')) { + s[i++] = caseSensitive ? ch : static_cast(MakeLowerCase(ch)); + } + } + + //The following is only a quick hack, to see if this whole thing would work + //we first need the tagname with a trailing space... + s[i] = ' '; + s[i+1] = '\0'; + + // if the current language is XML, I can fold any tag + // if the current language is HTML, I don't want to fold certain tags (input, meta, etc.) + //...to find it in the list of no-container-tags + tagDontFold = (!isXml) && (NULL != strstr("meta link img area br hr input ", s)); + + //now we can remove the trailing space + s[i] = '\0'; + + // No keywords -> all are known + char chAttr = SCE_H_TAGUNKNOWN; + if (s[0] == '!') { + chAttr = SCE_H_SGML_DEFAULT; + } else if (!keywords || keywords.InList(s)) { + chAttr = SCE_H_TAG; + } + styler.ColourTo(end, chAttr); + if (chAttr == SCE_H_TAG) { + if (allowScripts && 0 == strcmp(s, "script")) { + // check to see if this is a self-closing tag by sniffing ahead + bool isSelfClose = false; + for (unsigned int cPos = end; cPos <= end + 100; cPos++) { + char ch = styler.SafeGetCharAt(cPos, '\0'); + if (ch == '\0' || ch == '>') + break; + else if (ch == '/' && styler.SafeGetCharAt(cPos + 1, '\0') == '>') { + isSelfClose = true; + break; + } + } + + // do not enter a script state if the tag self-closed + if (!isSelfClose) + chAttr = SCE_H_SCRIPT; + } else if (!isXml && 0 == strcmp(s, "comment")) { + chAttr = SCE_H_COMMENT; + } + } + return chAttr; +} + +static void classifyWordHTJS(unsigned int start, unsigned int end, + WordList &keywords, Accessor &styler, script_mode inScriptType) { + char chAttr = SCE_HJ_WORD; + bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.'); + if (wordIsNumber) + chAttr = SCE_HJ_NUMBER; + else { + char s[30 + 1]; + unsigned int i = 0; + for (; i < end - start + 1 && i < 30; i++) { + s[i] = styler[start + i]; + } + s[i] = '\0'; + if (keywords.InList(s)) + chAttr = SCE_HJ_KEYWORD; + } + styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); +} + +static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, script_mode inScriptType) { + char chAttr = SCE_HB_IDENTIFIER; + bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.'); + if (wordIsNumber) + chAttr = SCE_HB_NUMBER; + else { + char s[100]; + GetTextSegment(styler, start, end, s, sizeof(s)); + if (keywords.InList(s)) { + chAttr = SCE_HB_WORD; + if (strcmp(s, "rem") == 0) + chAttr = SCE_HB_COMMENTLINE; + } + } + styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); + if (chAttr == SCE_HB_COMMENTLINE) + return SCE_HB_COMMENTLINE; + else + return SCE_HB_DEFAULT; +} + +static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord, script_mode inScriptType) { + bool wordIsNumber = IsADigit(styler[start]); + char s[30 + 1]; + unsigned int i = 0; + for (; i < end - start + 1 && i < 30; i++) { + s[i] = styler[start + i]; + } + s[i] = '\0'; + char chAttr = SCE_HP_IDENTIFIER; + if (0 == strcmp(prevWord, "class")) + chAttr = SCE_HP_CLASSNAME; + else if (0 == strcmp(prevWord, "def")) + chAttr = SCE_HP_DEFNAME; + else if (wordIsNumber) + chAttr = SCE_HP_NUMBER; + else if (keywords.InList(s)) + chAttr = SCE_HP_WORD; + styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); + strcpy(prevWord, s); +} + +// Update the word colour to default or keyword +// Called when in a PHP word +static void classifyWordHTPHP(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { + char chAttr = SCE_HPHP_DEFAULT; + bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.' && start+1 <= end && IsADigit(styler[start+1])); + if (wordIsNumber) + chAttr = SCE_HPHP_NUMBER; + else { + char s[100]; + GetTextSegment(styler, start, end, s, sizeof(s)); + if (keywords.InList(s)) + chAttr = SCE_HPHP_WORD; + } + styler.ColourTo(end, chAttr); +} + +static bool isWordHSGML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { + char s[30 + 1]; + unsigned int i = 0; + for (; i < end - start + 1 && i < 30; i++) { + s[i] = styler[start + i]; + } + s[i] = '\0'; + return keywords.InList(s); +} + +static bool isWordCdata(unsigned int start, unsigned int end, Accessor &styler) { + char s[30 + 1]; + unsigned int i = 0; + for (; i < end - start + 1 && i < 30; i++) { + s[i] = styler[start + i]; + } + s[i] = '\0'; + return (0 == strcmp(s, "[CDATA[")); +} + +// Return the first state to reach when entering a scripting language +static int StateForScript(script_type scriptLanguage) { + int Result; + switch (scriptLanguage) { + case eScriptVBS: + Result = SCE_HB_START; + break; + case eScriptPython: + Result = SCE_HP_START; + break; + case eScriptPHP: + Result = SCE_HPHP_DEFAULT; + break; + case eScriptXML: + Result = SCE_H_TAGUNKNOWN; + break; + case eScriptSGML: + Result = SCE_H_SGML_DEFAULT; + break; + case eScriptComment: + Result = SCE_H_COMMENT; + break; + default : + Result = SCE_HJ_START; + break; + } + return Result; +} + +static inline bool ishtmlwordchar(int ch) { + return !isascii(ch) || + (isalnum(ch) || ch == '.' || ch == '-' || ch == '_' || ch == ':' || ch == '!' || ch == '#'); +} + +static inline bool issgmlwordchar(int ch) { + return !isascii(ch) || + (isalnum(ch) || ch == '.' || ch == '_' || ch == ':' || ch == '!' || ch == '#' || ch == '['); +} + +static inline bool IsPhpWordStart(int ch) { + return (isascii(ch) && (isalpha(ch) || (ch == '_'))) || (ch >= 0x7f); +} + +static inline bool IsPhpWordChar(int ch) { + return IsADigit(ch) || IsPhpWordStart(ch); +} + +static bool InTagState(int state) { + return state == SCE_H_TAG || state == SCE_H_TAGUNKNOWN || + state == SCE_H_SCRIPT || + state == SCE_H_ATTRIBUTE || state == SCE_H_ATTRIBUTEUNKNOWN || + state == SCE_H_NUMBER || state == SCE_H_OTHER || + state == SCE_H_DOUBLESTRING || state == SCE_H_SINGLESTRING; +} + +static bool IsCommentState(const int state) { + return state == SCE_H_COMMENT || state == SCE_H_SGML_COMMENT; +} + +static bool IsScriptCommentState(const int state) { + return state == SCE_HJ_COMMENT || state == SCE_HJ_COMMENTLINE || state == SCE_HJA_COMMENT || + state == SCE_HJA_COMMENTLINE || state == SCE_HB_COMMENTLINE || state == SCE_HBA_COMMENTLINE; +} + +static bool isLineEnd(int ch) { + return ch == '\r' || ch == '\n'; +} + +static bool isOKBeforeRE(int ch) { + return (ch == '(') || (ch == '=') || (ch == ','); +} + +static bool isMakoBlockEnd(const int ch, const int chNext, const char *blockType) { + if (strlen(blockType) == 0) { + return ((ch == '%') && (chNext == '>')); + } else if ((0 == strcmp(blockType, "inherit")) || + (0 == strcmp(blockType, "namespace")) || + (0 == strcmp(blockType, "include")) || + (0 == strcmp(blockType, "page"))) { + return ((ch == '/') && (chNext == '>')); + } else if (0 == strcmp(blockType, "%")) { + return isLineEnd(ch); + } else if (0 == strcmp(blockType, "{")) { + return ch == '}'; + } else { + return (ch == '>'); + } +} + +static bool isDjangoBlockEnd(const int ch, const int chNext, const char *blockType) { + if (strlen(blockType) == 0) { + return 0; + } else if (0 == strcmp(blockType, "%")) { + return ((ch == '%') && (chNext == '}')); + } else if (0 == strcmp(blockType, "{")) { + return ((ch == '}') && (chNext == '}')); + } else { + return 0; + } +} + +static bool isPHPStringState(int state) { + return + (state == SCE_HPHP_HSTRING) || + (state == SCE_HPHP_SIMPLESTRING) || + (state == SCE_HPHP_HSTRING_VARIABLE) || + (state == SCE_HPHP_COMPLEX_VARIABLE); +} + +static int FindPhpStringDelimiter(char *phpStringDelimiter, const int phpStringDelimiterSize, int i, const int lengthDoc, Accessor &styler, bool &isSimpleString) { + int j; + const int beginning = i - 1; + bool isValidSimpleString = false; + + while (i < lengthDoc && (styler[i] == ' ' || styler[i] == '\t')) + i++; + + char ch = styler.SafeGetCharAt(i); + const char chNext = styler.SafeGetCharAt(i + 1); + if (!IsPhpWordStart(ch)) { + if (ch == '\'' && IsPhpWordStart(chNext)) { + i++; + ch = chNext; + isSimpleString = true; + } else { + phpStringDelimiter[0] = '\0'; + return beginning; + } + } + phpStringDelimiter[0] = ch; + i++; + + for (j = i; j < lengthDoc && !isLineEnd(styler[j]); j++) { + if (!IsPhpWordChar(styler[j])) { + if (isSimpleString && (styler[j] == '\'') && isLineEnd(styler.SafeGetCharAt(j + 1))) { + isValidSimpleString = true; + j++; + break; + } else { + phpStringDelimiter[0] = '\0'; + return beginning; + } + } + if (j - i < phpStringDelimiterSize - 2) + phpStringDelimiter[j-i+1] = styler[j]; + else + i++; + } + if (isSimpleString && !isValidSimpleString) { + phpStringDelimiter[0] = '\0'; + return beginning; + } + phpStringDelimiter[j-i+1 - (isSimpleString ? 1 : 0)] = '\0'; + return j - 1; +} + +static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler, bool isXml) { + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; // SGML (DTD) keywords + + // Lexer for HTML requires more lexical states (8 bits worth) than most lexers + styler.StartAt(startPos, static_cast(STYLE_MAX)); + char prevWord[200]; + prevWord[0] = '\0'; + char phpStringDelimiter[200]; // PHP is not limited in length, we are + phpStringDelimiter[0] = '\0'; + int StateToPrint = initStyle; + int state = stateForPrintState(StateToPrint); + char makoBlockType[200]; + makoBlockType[0] = '\0'; + char djangoBlockType[2]; + djangoBlockType[0] = '\0'; + + // If inside a tag, it may be a script tag, so reread from the start to ensure any language tags are seen + if (InTagState(state)) { + while ((startPos > 0) && (InTagState(styler.StyleAt(startPos - 1)))) { + startPos--; + length++; + } + state = SCE_H_DEFAULT; + } + // String can be heredoc, must find a delimiter first. Reread from beginning of line containing the string, to get the correct lineState + if (isPHPStringState(state)) { + while (startPos > 0 && (isPHPStringState(state) || !isLineEnd(styler[startPos - 1]))) { + startPos--; + length++; + state = styler.StyleAt(startPos); + } + if (startPos == 0) + state = SCE_H_DEFAULT; + } + styler.StartAt(startPos, static_cast(STYLE_MAX)); + + int lineCurrent = styler.GetLine(startPos); + int lineState; + if (lineCurrent > 0) { + lineState = styler.GetLineState(lineCurrent); + } else { + // Default client and ASP scripting language is JavaScript + lineState = eScriptJS << 8; + + // property asp.default.language + // Script in ASP code is initially assumed to be in JavaScript. + // To change this to VBScript set asp.default.language to 2. Python is 3. + lineState |= styler.GetPropertyInt("asp.default.language", eScriptJS) << 4; + } + script_mode inScriptType = script_mode((lineState >> 0) & 0x03); // 2 bits of scripting mode + bool tagOpened = (lineState >> 2) & 0x01; // 1 bit to know if we are in an opened tag + bool tagClosing = (lineState >> 3) & 0x01; // 1 bit to know if we are in a closing tag + bool tagDontFold = false; //some HTML tags should not be folded + script_type aspScript = script_type((lineState >> 4) & 0x0F); // 4 bits of script name + script_type clientScript = script_type((lineState >> 8) & 0x0F); // 4 bits of script name + int beforePreProc = (lineState >> 12) & 0xFF; // 8 bits of state + + script_type scriptLanguage = ScriptOfState(state); + // If eNonHtmlScript coincides with SCE_H_COMMENT, assume eScriptComment + if (inScriptType == eNonHtmlScript && state == SCE_H_COMMENT) { + scriptLanguage = eScriptComment; + } + script_type beforeLanguage = ScriptOfState(beforePreProc); + + // property fold.html + // Folding is turned on or off for HTML and XML files with this option. + // The fold option must also be on for folding to occur. + const bool foldHTML = styler.GetPropertyInt("fold.html", 0) != 0; + + const bool fold = foldHTML && styler.GetPropertyInt("fold", 0); + + // property fold.html.preprocessor + // Folding is turned on or off for scripts embedded in HTML files with this option. + // The default is on. + const bool foldHTMLPreprocessor = foldHTML && styler.GetPropertyInt("fold.html.preprocessor", 1); + + const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + + // property fold.hypertext.comment + // Allow folding for comments in scripts embedded in HTML. + // The default is off. + const bool foldComment = fold && styler.GetPropertyInt("fold.hypertext.comment", 0) != 0; + + // property fold.hypertext.heredoc + // Allow folding for heredocs in scripts embedded in HTML. + // The default is off. + const bool foldHeredoc = fold && styler.GetPropertyInt("fold.hypertext.heredoc", 0) != 0; + + // property html.tags.case.sensitive + // For XML and HTML, setting this property to 1 will make tags match in a case + // sensitive way which is the expected behaviour for XML and XHTML. + const bool caseSensitive = styler.GetPropertyInt("html.tags.case.sensitive", 0) != 0; + + // property lexer.xml.allow.scripts + // Set to 0 to disable scripts in XML. + const bool allowScripts = styler.GetPropertyInt("lexer.xml.allow.scripts", 1) != 0; + + // property lexer.html.mako + // Set to 1 to enable the mako template language. + const bool isMako = styler.GetPropertyInt("lexer.html.mako", 0) != 0; + + // property lexer.html.django + // Set to 1 to enable the django template language. + const bool isDjango = styler.GetPropertyInt("lexer.html.django", 0) != 0; + + const CharacterSet setHTMLWord(CharacterSet::setAlphaNum, ".-_:!#", 0x80, true); + const CharacterSet setTagContinue(CharacterSet::setAlphaNum, ".-_:!#[", 0x80, true); + const CharacterSet setAttributeContinue(CharacterSet::setAlphaNum, ".-_:!#/", 0x80, true); + + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + int visibleChars = 0; + int lineStartVisibleChars = 0; + + int chPrev = ' '; + int ch = ' '; + int chPrevNonWhite = ' '; + // look back to set chPrevNonWhite properly for better regex colouring + if (scriptLanguage == eScriptJS && startPos > 0) { + int back = startPos; + int style = 0; + while (--back) { + style = styler.StyleAt(back); + if (style < SCE_HJ_DEFAULT || style > SCE_HJ_COMMENTDOC) + // includes SCE_HJ_COMMENT & SCE_HJ_COMMENTLINE + break; + } + if (style == SCE_HJ_SYMBOLS) { + chPrevNonWhite = static_cast(styler.SafeGetCharAt(back)); + } + } + + styler.StartSegment(startPos); + const int lengthDoc = startPos + length; + for (int i = startPos; i < lengthDoc; i++) { + const int chPrev2 = chPrev; + chPrev = ch; + if (!IsASpace(ch) && state != SCE_HJ_COMMENT && + state != SCE_HJ_COMMENTLINE && state != SCE_HJ_COMMENTDOC) + chPrevNonWhite = ch; + ch = static_cast(styler[i]); + int chNext = static_cast(styler.SafeGetCharAt(i + 1)); + const int chNext2 = static_cast(styler.SafeGetCharAt(i + 2)); + + // Handle DBCS codepages + if (styler.IsLeadByte(static_cast(ch))) { + chPrev = ' '; + i += 1; + continue; + } + + if ((!IsASpace(ch) || !foldCompact) && fold) + visibleChars++; + if (!IsASpace(ch)) + lineStartVisibleChars++; + + // decide what is the current state to print (depending of the script tag) + StateToPrint = statePrintForState(state, inScriptType); + + // handle script folding + if (fold) { + switch (scriptLanguage) { + case eScriptJS: + case eScriptPHP: + //not currently supported case eScriptVBS: + + if ((state != SCE_HPHP_COMMENT) && (state != SCE_HPHP_COMMENTLINE) && (state != SCE_HJ_COMMENT) && (state != SCE_HJ_COMMENTLINE) && (state != SCE_HJ_COMMENTDOC) && (!isStringState(state))) { + //Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle); + //if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) { + if ((ch == '{') || (ch == '}') || (foldComment && (ch == '/') && (chNext == '*'))) { + levelCurrent += ((ch == '{') || (ch == '/')) ? 1 : -1; + } + } else if (((state == SCE_HPHP_COMMENT) || (state == SCE_HJ_COMMENT)) && foldComment && (ch == '*') && (chNext == '/')) { + levelCurrent--; + } + break; + case eScriptPython: + if (state != SCE_HP_COMMENTLINE) { + if ((ch == ':') && ((chNext == '\n') || (chNext == '\r' && chNext2 == '\n'))) { + levelCurrent++; + } else if ((ch == '\n') && !((chNext == '\r') && (chNext2 == '\n')) && (chNext != '\n')) { + // check if the number of tabs is lower than the level + int Findlevel = (levelCurrent & ~SC_FOLDLEVELBASE) * 8; + for (int j = 0; Findlevel > 0; j++) { + char chTmp = styler.SafeGetCharAt(i + j + 1); + if (chTmp == '\t') { + Findlevel -= 8; + } else if (chTmp == ' ') { + Findlevel--; + } else { + break; + } + } + + if (Findlevel > 0) { + levelCurrent -= Findlevel / 8; + if (Findlevel % 8) + levelCurrent--; + } + } + } + break; + default: + break; + } + } + + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // New line -> record any line state onto /next/ line + if (fold) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + + styler.SetLevel(lineCurrent, lev); + visibleChars = 0; + levelPrev = levelCurrent; + } + lineCurrent++; + lineStartVisibleChars = 0; + styler.SetLineState(lineCurrent, + ((inScriptType & 0x03) << 0) | + ((tagOpened & 0x01) << 2) | + ((tagClosing & 0x01) << 3) | + ((aspScript & 0x0F) << 4) | + ((clientScript & 0x0F) << 8) | + ((beforePreProc & 0xFF) << 12)); + } + + // Allow falling through to mako handling code if newline is going to end a block + if (((ch == '\r' && chNext != '\n') || (ch == '\n')) && + (!isMako || (0 != strcmp(makoBlockType, "%")))) { + } + + // generic end of script processing + else if ((inScriptType == eNonHtmlScript) && (ch == '<') && (chNext == '/')) { + // Check if it's the end of the script tag (or any other HTML tag) + switch (state) { + // in these cases, you can embed HTML tags (to confirm !!!!!!!!!!!!!!!!!!!!!!) + case SCE_H_DOUBLESTRING: + case SCE_H_SINGLESTRING: + case SCE_HJ_COMMENT: + case SCE_HJ_COMMENTDOC: + //case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide + // the end of script marker from some JS interpreters. + case SCE_HB_COMMENTLINE: + case SCE_HBA_COMMENTLINE: + case SCE_HJ_DOUBLESTRING: + case SCE_HJ_SINGLESTRING: + case SCE_HJ_REGEX: + case SCE_HB_STRING: + case SCE_HBA_STRING: + case SCE_HP_STRING: + case SCE_HP_TRIPLE: + case SCE_HP_TRIPLEDOUBLE: + case SCE_HPHP_HSTRING: + case SCE_HPHP_SIMPLESTRING: + case SCE_HPHP_COMMENT: + case SCE_HPHP_COMMENTLINE: + break; + default : + // check if the closing tag is a script tag + if (const char *tag = + state == SCE_HJ_COMMENTLINE || isXml ? "script" : + state == SCE_H_COMMENT ? "comment" : 0) { + int j = i + 2; + int chr; + do { + chr = static_cast(*tag++); + } while (chr != 0 && chr == MakeLowerCase(styler.SafeGetCharAt(j++))); + if (chr != 0) break; + } + // closing tag of the script (it's a closing HTML tag anyway) + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_TAGUNKNOWN; + inScriptType = eHtml; + scriptLanguage = eScriptNone; + clientScript = eScriptJS; + i += 2; + visibleChars += 2; + tagClosing = true; + continue; + } + } + + ///////////////////////////////////// + // handle the start of PHP pre-processor = Non-HTML + else if ((state != SCE_H_ASPAT) && + !isPHPStringState(state) && + (state != SCE_HPHP_COMMENT) && + (state != SCE_HPHP_COMMENTLINE) && + (ch == '<') && + (chNext == '?') && + !IsScriptCommentState(state) ) { + scriptLanguage = segIsScriptingIndicator(styler, i + 2, i + 6, eScriptPHP); + if (scriptLanguage != eScriptPHP && isStringState(state)) continue; + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + i++; + visibleChars++; + i += PrintScriptingIndicatorOffset(styler, styler.GetStartSegment() + 2, i + 6); + if (scriptLanguage == eScriptXML) + styler.ColourTo(i, SCE_H_XMLSTART); + else + styler.ColourTo(i, SCE_H_QUESTION); + state = StateForScript(scriptLanguage); + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + // Fold whole script, but not if the XML first tag (all XML-like tags in this case) + if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) { + levelCurrent++; + } + // should be better + ch = static_cast(styler.SafeGetCharAt(i)); + continue; + } + + // handle the start Mako template Python code + else if (isMako && scriptLanguage == eScriptNone && ((ch == '<' && chNext == '%') || + (lineStartVisibleChars == 1 && ch == '%') || + (ch == '$' && chNext == '{') || + (ch == '<' && chNext == '/' && chNext2 == '%'))) { + if (ch == '%') + strcpy(makoBlockType, "%"); + else if (ch == '$') + strcpy(makoBlockType, "{"); + else if (chNext == '/') + GetNextWord(styler, i+3, makoBlockType, sizeof(makoBlockType)); + else + GetNextWord(styler, i+2, makoBlockType, sizeof(makoBlockType)); + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + + if (chNext == '/') { + i += 2; + visibleChars += 2; + } else if (ch != '%') { + i++; + visibleChars++; + } + state = SCE_HP_START; + scriptLanguage = eScriptPython; + styler.ColourTo(i, SCE_H_ASP); + if (foldHTMLPreprocessor && ch == '<') + levelCurrent++; + + if (ch != '%' && ch != '$') { + i += strlen(makoBlockType); + visibleChars += strlen(makoBlockType); + if (keywords4.InList(makoBlockType)) + styler.ColourTo(i, SCE_HP_WORD); + else + styler.ColourTo(i, SCE_H_TAGUNKNOWN); + } + + ch = static_cast(styler.SafeGetCharAt(i)); + continue; + } + + // handle the start Django template code + else if (isDjango && scriptLanguage != eScriptPython && (ch == '{' && (chNext == '%' || chNext == '{'))) { + if (chNext == '%') + strcpy(djangoBlockType, "%"); + else + strcpy(djangoBlockType, "{"); + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + + i += 1; + visibleChars += 1; + state = SCE_HP_START; + beforeLanguage = scriptLanguage; + scriptLanguage = eScriptPython; + styler.ColourTo(i, SCE_H_ASP); + if (foldHTMLPreprocessor && chNext == '%') + levelCurrent++; + + ch = static_cast(styler.SafeGetCharAt(i)); + continue; + } + + // handle the start of ASP pre-processor = Non-HTML + else if (!isMako && !isDjango && !isCommentASPState(state) && (ch == '<') && (chNext == '%') && !isPHPStringState(state)) { + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + + if (chNext2 == '@') { + i += 2; // place as if it was the second next char treated + visibleChars += 2; + state = SCE_H_ASPAT; + } else if ((chNext2 == '-') && (styler.SafeGetCharAt(i + 3) == '-')) { + styler.ColourTo(i + 3, SCE_H_ASP); + state = SCE_H_XCCOMMENT; + scriptLanguage = eScriptVBS; + continue; + } else { + if (chNext2 == '=') { + i += 2; // place as if it was the second next char treated + visibleChars += 2; + } else { + i++; // place as if it was the next char treated + visibleChars++; + } + + state = StateForScript(aspScript); + } + scriptLanguage = eScriptVBS; + styler.ColourTo(i, SCE_H_ASP); + // fold whole script + if (foldHTMLPreprocessor) + levelCurrent++; + // should be better + ch = static_cast(styler.SafeGetCharAt(i)); + continue; + } + + ///////////////////////////////////// + // handle the start of SGML language (DTD) + else if (((scriptLanguage == eScriptNone) || (scriptLanguage == eScriptXML)) && + (chPrev == '<') && + (ch == '!') && + (StateToPrint != SCE_H_CDATA) && + (!IsCommentState(StateToPrint)) && + (!IsScriptCommentState(StateToPrint)) ) { + beforePreProc = state; + styler.ColourTo(i - 2, StateToPrint); + if ((chNext == '-') && (chNext2 == '-')) { + state = SCE_H_COMMENT; // wait for a pending command + styler.ColourTo(i + 2, SCE_H_COMMENT); + i += 2; // follow styling after the -- + } else if (isWordCdata(i + 1, i + 7, styler)) { + state = SCE_H_CDATA; + } else { + styler.ColourTo(i, SCE_H_SGML_DEFAULT); // ') { + i++; + visibleChars++; + } + if (0 != strcmp(makoBlockType, "%")) { + styler.ColourTo(i, SCE_H_ASP); + } + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + if (foldHTMLPreprocessor && ch != '\n' && ch != '\r') { + levelCurrent--; + } + scriptLanguage = eScriptNone; + continue; + } + + // handle the end of Django template code + else if (isDjango && + ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && + (scriptLanguage != eScriptNone) && stateAllowsTermination(state) && + isDjangoBlockEnd(ch, chNext, djangoBlockType)) { + if (state == SCE_H_ASPAT) { + aspScript = segIsScriptingIndicator(styler, + styler.GetStartSegment(), i - 1, aspScript); + } + if (state == SCE_HP_WORD) { + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType); + } else { + styler.ColourTo(i - 1, StateToPrint); + } + i += 1; + visibleChars += 1; + styler.ColourTo(i, SCE_H_ASP); + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + if (foldHTMLPreprocessor) { + levelCurrent--; + } + scriptLanguage = beforeLanguage; + continue; + } + + // handle the end of a pre-processor = Non-HTML + else if ((!isMako && !isDjango && ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && + (((scriptLanguage != eScriptNone) && stateAllowsTermination(state))) && + (((ch == '%') || (ch == '?')) && (chNext == '>'))) || + ((scriptLanguage == eScriptSGML) && (ch == '>') && (state != SCE_H_SGML_COMMENT))) { + if (state == SCE_H_ASPAT) { + aspScript = segIsScriptingIndicator(styler, + styler.GetStartSegment(), i - 1, aspScript); + } + // Bounce out of any ASP mode + switch (state) { + case SCE_HJ_WORD: + classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType); + break; + case SCE_HB_WORD: + classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType); + break; + case SCE_HP_WORD: + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType); + break; + case SCE_HPHP_WORD: + classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler); + break; + case SCE_H_XCCOMMENT: + styler.ColourTo(i - 1, state); + break; + default : + styler.ColourTo(i - 1, StateToPrint); + break; + } + if (scriptLanguage != eScriptSGML) { + i++; + visibleChars++; + } + if (ch == '%') + styler.ColourTo(i, SCE_H_ASP); + else if (scriptLanguage == eScriptXML) + styler.ColourTo(i, SCE_H_XMLEND); + else if (scriptLanguage == eScriptSGML) + styler.ColourTo(i, SCE_H_SGML_DEFAULT); + else + styler.ColourTo(i, SCE_H_QUESTION); + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + // Unfold all scripting languages, except for XML tag + if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) { + levelCurrent--; + } + scriptLanguage = eScriptNone; + continue; + } + ///////////////////////////////////// + + switch (state) { + case SCE_H_DEFAULT: + if (ch == '<') { + // in HTML, fold on tag open and unfold on tag close + tagOpened = true; + tagClosing = (chNext == '/'); + styler.ColourTo(i - 1, StateToPrint); + if (chNext != '!') + state = SCE_H_TAGUNKNOWN; + } else if (ch == '&') { + styler.ColourTo(i - 1, SCE_H_DEFAULT); + state = SCE_H_ENTITY; + } + break; + case SCE_H_SGML_DEFAULT: + case SCE_H_SGML_BLOCK_DEFAULT: +// if (scriptLanguage == eScriptSGMLblock) +// StateToPrint = SCE_H_SGML_BLOCK_DEFAULT; + + if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_DOUBLESTRING; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_SIMPLESTRING; + } else if ((ch == '-') && (chPrev == '-')) { + if (static_cast(styler.GetStartSegment()) <= (i - 2)) { + styler.ColourTo(i - 2, StateToPrint); + } + state = SCE_H_SGML_COMMENT; + } else if (isascii(ch) && isalpha(ch) && (chPrev == '%')) { + styler.ColourTo(i - 2, StateToPrint); + state = SCE_H_SGML_ENTITY; + } else if (ch == '#') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_SPECIAL; + } else if (ch == '[') { + styler.ColourTo(i - 1, StateToPrint); + scriptLanguage = eScriptSGMLblock; + state = SCE_H_SGML_BLOCK_DEFAULT; + } else if (ch == ']') { + if (scriptLanguage == eScriptSGMLblock) { + styler.ColourTo(i, StateToPrint); + scriptLanguage = eScriptSGML; + } else { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, SCE_H_SGML_ERROR); + } + state = SCE_H_SGML_DEFAULT; + } else if (scriptLanguage == eScriptSGMLblock) { + if ((ch == '!') && (chPrev == '<')) { + styler.ColourTo(i - 2, StateToPrint); + styler.ColourTo(i, SCE_H_SGML_DEFAULT); + state = SCE_H_SGML_COMMAND; + } else if (ch == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, SCE_H_SGML_DEFAULT); + } + } + break; + case SCE_H_SGML_COMMAND: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i - 2, StateToPrint); + state = SCE_H_SGML_COMMENT; + } else if (!issgmlwordchar(ch)) { + if (isWordHSGML(styler.GetStartSegment(), i - 1, keywords6, styler)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_1ST_PARAM; + } else { + state = SCE_H_SGML_ERROR; + } + } + break; + case SCE_H_SGML_1ST_PARAM: + // wait for the beginning of the word + if ((ch == '-') && (chPrev == '-')) { + if (scriptLanguage == eScriptSGMLblock) { + styler.ColourTo(i - 2, SCE_H_SGML_BLOCK_DEFAULT); + } else { + styler.ColourTo(i - 2, SCE_H_SGML_DEFAULT); + } + state = SCE_H_SGML_1ST_PARAM_COMMENT; + } else if (issgmlwordchar(ch)) { + if (scriptLanguage == eScriptSGMLblock) { + styler.ColourTo(i - 1, SCE_H_SGML_BLOCK_DEFAULT); + } else { + styler.ColourTo(i - 1, SCE_H_SGML_DEFAULT); + } + // find the length of the word + int size = 1; + while (setHTMLWord.Contains(static_cast(styler.SafeGetCharAt(i + size)))) + size++; + styler.ColourTo(i + size - 1, StateToPrint); + i += size - 1; + visibleChars += size - 1; + ch = static_cast(styler.SafeGetCharAt(i)); + if (scriptLanguage == eScriptSGMLblock) { + state = SCE_H_SGML_BLOCK_DEFAULT; + } else { + state = SCE_H_SGML_DEFAULT; + } + continue; + } + break; + case SCE_H_SGML_ERROR: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i - 2, StateToPrint); + state = SCE_H_SGML_COMMENT; + } + case SCE_H_SGML_DOUBLESTRING: + if (ch == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_SGML_SIMPLESTRING: + if (ch == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_SGML_COMMENT: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_CDATA: + if ((chPrev2 == ']') && (chPrev == ']') && (ch == '>')) { + styler.ColourTo(i, StateToPrint); + state = SCE_H_DEFAULT; + levelCurrent--; + } + break; + case SCE_H_COMMENT: + if ((scriptLanguage != eScriptComment) && (chPrev2 == '-') && (chPrev == '-') && (ch == '>')) { + styler.ColourTo(i, StateToPrint); + state = SCE_H_DEFAULT; + levelCurrent--; + } + break; + case SCE_H_SGML_1ST_PARAM_COMMENT: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i, SCE_H_SGML_COMMENT); + state = SCE_H_SGML_1ST_PARAM; + } + break; + case SCE_H_SGML_SPECIAL: + if (!(isascii(ch) && isupper(ch))) { + styler.ColourTo(i - 1, StateToPrint); + if (isalnum(ch)) { + state = SCE_H_SGML_ERROR; + } else { + state = SCE_H_SGML_DEFAULT; + } + } + break; + case SCE_H_SGML_ENTITY: + if (ch == ';') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } else if (!(isascii(ch) && isalnum(ch)) && ch != '-' && ch != '.') { + styler.ColourTo(i, SCE_H_SGML_ERROR); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_ENTITY: + if (ch == ';') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_DEFAULT; + } + if (ch != '#' && !(isascii(ch) && isalnum(ch)) // Should check that '#' follows '&', but it is unlikely anyway... + && ch != '.' && ch != '-' && ch != '_' && ch != ':') { // valid in XML + if (!isascii(ch)) // Possibly start of a multibyte character so don't allow this byte to be in entity style + styler.ColourTo(i-1, SCE_H_TAGUNKNOWN); + else + styler.ColourTo(i, SCE_H_TAGUNKNOWN); + state = SCE_H_DEFAULT; + } + break; + case SCE_H_TAGUNKNOWN: + if (!setTagContinue.Contains(ch) && !((ch == '/') && (chPrev == '<'))) { + int eClass = classifyTagHTML(styler.GetStartSegment(), + i - 1, keywords, styler, tagDontFold, caseSensitive, isXml, allowScripts); + if (eClass == SCE_H_SCRIPT || eClass == SCE_H_COMMENT) { + if (!tagClosing) { + inScriptType = eNonHtmlScript; + scriptLanguage = eClass == SCE_H_SCRIPT ? clientScript : eScriptComment; + } else { + scriptLanguage = eScriptNone; + } + eClass = SCE_H_TAG; + } + if (ch == '>') { + styler.ColourTo(i, eClass); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!tagDontFold) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else if (ch == '/' && chNext == '>') { + if (eClass == SCE_H_TAGUNKNOWN) { + styler.ColourTo(i + 1, SCE_H_TAGUNKNOWN); + } else { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i + 1, SCE_H_TAGEND); + } + i++; + ch = chNext; + state = SCE_H_DEFAULT; + tagOpened = false; + } else { + if (eClass != SCE_H_TAGUNKNOWN) { + if (eClass == SCE_H_SGML_DEFAULT) { + state = SCE_H_SGML_DEFAULT; + } else { + state = SCE_H_OTHER; + } + } + } + } + break; + case SCE_H_ATTRIBUTE: + if (!setAttributeContinue.Contains(ch)) { + if (inScriptType == eNonHtmlScript) { + int scriptLanguagePrev = scriptLanguage; + clientScript = segIsScriptingIndicator(styler, styler.GetStartSegment(), i - 1, scriptLanguage); + scriptLanguage = clientScript; + if ((scriptLanguagePrev != scriptLanguage) && (scriptLanguage == eScriptNone)) + inScriptType = eHtml; + } + classifyAttribHTML(styler.GetStartSegment(), i - 1, keywords, styler); + if (ch == '>') { + styler.ColourTo(i, SCE_H_TAG); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!tagDontFold) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else if (ch == '=') { + styler.ColourTo(i, SCE_H_OTHER); + state = SCE_H_VALUE; + } else { + state = SCE_H_OTHER; + } + } + break; + case SCE_H_OTHER: + if (ch == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, SCE_H_TAG); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!tagDontFold) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_DOUBLESTRING; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SINGLESTRING; + } else if (ch == '=') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_VALUE; + } else if (ch == '/' && chNext == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i + 1, SCE_H_TAGEND); + i++; + ch = chNext; + state = SCE_H_DEFAULT; + tagOpened = false; + } else if (ch == '?' && chNext == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i + 1, SCE_H_XMLEND); + i++; + ch = chNext; + state = SCE_H_DEFAULT; + } else if (setHTMLWord.Contains(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_ATTRIBUTE; + } + break; + case SCE_H_DOUBLESTRING: + if (ch == '\"') { + if (inScriptType == eNonHtmlScript) { + scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage); + } + styler.ColourTo(i, SCE_H_DOUBLESTRING); + state = SCE_H_OTHER; + } + break; + case SCE_H_SINGLESTRING: + if (ch == '\'') { + if (inScriptType == eNonHtmlScript) { + scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage); + } + styler.ColourTo(i, SCE_H_SINGLESTRING); + state = SCE_H_OTHER; + } + break; + case SCE_H_VALUE: + if (!setHTMLWord.Contains(ch)) { + if (ch == '\"' && chPrev == '=') { + // Should really test for being first character + state = SCE_H_DOUBLESTRING; + } else if (ch == '\'' && chPrev == '=') { + state = SCE_H_SINGLESTRING; + } else { + if (IsNumber(styler.GetStartSegment(), styler)) { + styler.ColourTo(i - 1, SCE_H_NUMBER); + } else { + styler.ColourTo(i - 1, StateToPrint); + } + if (ch == '>') { + styler.ColourTo(i, SCE_H_TAG); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!tagDontFold) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else { + state = SCE_H_OTHER; + } + } + } + break; + case SCE_HJ_DEFAULT: + case SCE_HJ_START: + case SCE_HJ_SYMBOLS: + if (IsAWordStart(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_WORD; + } else if (ch == '/' && chNext == '*') { + styler.ColourTo(i - 1, StateToPrint); + if (chNext2 == '*') + state = SCE_HJ_COMMENTDOC; + else + state = SCE_HJ_COMMENT; + } else if (ch == '/' && chNext == '/') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + } else if (ch == '/' && isOKBeforeRE(chPrevNonWhite)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_REGEX; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_DOUBLESTRING; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_SINGLESTRING; + } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && + styler.SafeGetCharAt(i + 3) == '-') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + i += 2; + } else if (IsOperator(ch)) { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); + state = SCE_HJ_DEFAULT; + } else if ((ch == ' ') || (ch == '\t')) { + if (state == SCE_HJ_START) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_DEFAULT; + } + } + break; + case SCE_HJ_WORD: + if (!IsAWordChar(ch)) { + classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType); + //styler.ColourTo(i - 1, eHTJSKeyword); + state = SCE_HJ_DEFAULT; + if (ch == '/' && chNext == '*') { + if (chNext2 == '*') + state = SCE_HJ_COMMENTDOC; + else + state = SCE_HJ_COMMENT; + } else if (ch == '/' && chNext == '/') { + state = SCE_HJ_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_HJ_DOUBLESTRING; + } else if (ch == '\'') { + state = SCE_HJ_SINGLESTRING; + } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + i += 2; + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); + state = SCE_HJ_DEFAULT; + } + } + break; + case SCE_HJ_COMMENT: + case SCE_HJ_COMMENTDOC: + if (ch == '/' && chPrev == '*') { + styler.ColourTo(i, StateToPrint); + state = SCE_HJ_DEFAULT; + ch = ' '; + } + break; + case SCE_HJ_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, statePrintForState(SCE_HJ_COMMENTLINE, inScriptType)); + state = SCE_HJ_DEFAULT; + ch = ' '; + } + break; + case SCE_HJ_DOUBLESTRING: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + } + } else if (ch == '\"') { + styler.ColourTo(i, statePrintForState(SCE_HJ_DOUBLESTRING, inScriptType)); + state = SCE_HJ_DEFAULT; + } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + i += 2; + } else if (isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_STRINGEOL; + } + break; + case SCE_HJ_SINGLESTRING: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + } + } else if (ch == '\'') { + styler.ColourTo(i, statePrintForState(SCE_HJ_SINGLESTRING, inScriptType)); + state = SCE_HJ_DEFAULT; + } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + i += 2; + } else if (isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_STRINGEOL; + } + break; + case SCE_HJ_STRINGEOL: + if (!isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_DEFAULT; + } else if (!isLineEnd(chNext)) { + styler.ColourTo(i, StateToPrint); + state = SCE_HJ_DEFAULT; + } + break; + case SCE_HJ_REGEX: + if (ch == '\r' || ch == '\n' || ch == '/') { + if (ch == '/') { + while (isascii(chNext) && islower(chNext)) { // gobble regex flags + i++; + ch = chNext; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } + } + styler.ColourTo(i, StateToPrint); + state = SCE_HJ_DEFAULT; + } else if (ch == '\\') { + // Gobble up the quoted character + if (chNext == '\\' || chNext == '/') { + i++; + ch = chNext; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } + } + break; + case SCE_HB_DEFAULT: + case SCE_HB_START: + if (IsAWordStart(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_WORD; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_COMMENTLINE; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_STRING; + } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && + styler.SafeGetCharAt(i + 3) == '-') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_COMMENTLINE; + } else if (IsOperator(ch)) { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType)); + state = SCE_HB_DEFAULT; + } else if ((ch == ' ') || (ch == '\t')) { + if (state == SCE_HB_START) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_DEFAULT; + } + } + break; + case SCE_HB_WORD: + if (!IsAWordChar(ch)) { + state = classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType); + if (state == SCE_HB_DEFAULT) { + if (ch == '\"') { + state = SCE_HB_STRING; + } else if (ch == '\'') { + state = SCE_HB_COMMENTLINE; + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType)); + state = SCE_HB_DEFAULT; + } + } + } + break; + case SCE_HB_STRING: + if (ch == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_HB_DEFAULT; + } else if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_STRINGEOL; + } + break; + case SCE_HB_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_DEFAULT; + } + break; + case SCE_HB_STRINGEOL: + if (!isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_DEFAULT; + } else if (!isLineEnd(chNext)) { + styler.ColourTo(i, StateToPrint); + state = SCE_HB_DEFAULT; + } + break; + case SCE_HP_DEFAULT: + case SCE_HP_START: + if (IsAWordStart(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_WORD; + } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && + styler.SafeGetCharAt(i + 3) == '-') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_COMMENTLINE; + } else if (ch == '#') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_COMMENTLINE; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + if (chNext == '\"' && chNext2 == '\"') { + i += 2; + state = SCE_HP_TRIPLEDOUBLE; + ch = ' '; + chPrev = ' '; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } else { + // state = statePrintForState(SCE_HP_STRING,inScriptType); + state = SCE_HP_STRING; + } + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + if (chNext == '\'' && chNext2 == '\'') { + i += 2; + state = SCE_HP_TRIPLE; + ch = ' '; + chPrev = ' '; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } else { + state = SCE_HP_CHARACTER; + } + } else if (IsOperator(ch)) { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType)); + } else if ((ch == ' ') || (ch == '\t')) { + if (state == SCE_HP_START) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_DEFAULT; + } + } + break; + case SCE_HP_WORD: + if (!IsAWordChar(ch)) { + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType); + state = SCE_HP_DEFAULT; + if (ch == '#') { + state = SCE_HP_COMMENTLINE; + } else if (ch == '\"') { + if (chNext == '\"' && chNext2 == '\"') { + i += 2; + state = SCE_HP_TRIPLEDOUBLE; + ch = ' '; + chPrev = ' '; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } else { + state = SCE_HP_STRING; + } + } else if (ch == '\'') { + if (chNext == '\'' && chNext2 == '\'') { + i += 2; + state = SCE_HP_TRIPLE; + ch = ' '; + chPrev = ' '; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } else { + state = SCE_HP_CHARACTER; + } + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType)); + } + } + break; + case SCE_HP_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_STRING: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } + } else if (ch == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_CHARACTER: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } + } else if (ch == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_TRIPLE: + if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_TRIPLEDOUBLE: + if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + ///////////// start - PHP state handling + case SCE_HPHP_WORD: + if (!IsAWordChar(ch)) { + classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler); + if (ch == '/' && chNext == '*') { + i++; + state = SCE_HPHP_COMMENT; + } else if (ch == '/' && chNext == '/') { + i++; + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '#') { + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_HPHP_HSTRING; + strcpy(phpStringDelimiter, "\""); + } else if (styler.Match(i, "<<<")) { + bool isSimpleString = false; + i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString); + if (strlen(phpStringDelimiter)) { + state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING); + if (foldHeredoc) levelCurrent++; + } + } else if (ch == '\'') { + state = SCE_HPHP_SIMPLESTRING; + strcpy(phpStringDelimiter, "\'"); + } else if (ch == '$' && IsPhpWordStart(chNext)) { + state = SCE_HPHP_VARIABLE; + } else if (IsOperator(ch)) { + state = SCE_HPHP_OPERATOR; + } else { + state = SCE_HPHP_DEFAULT; + } + } + break; + case SCE_HPHP_NUMBER: + // recognize bases 8,10 or 16 integers OR floating-point numbers + if (!IsADigit(ch) + && strchr(".xXabcdefABCDEF", ch) == NULL + && ((ch != '-' && ch != '+') || (chPrev != 'e' && chPrev != 'E'))) { + styler.ColourTo(i - 1, SCE_HPHP_NUMBER); + if (IsOperator(ch)) + state = SCE_HPHP_OPERATOR; + else + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_VARIABLE: + if (!IsPhpWordChar(chNext)) { + styler.ColourTo(i, SCE_HPHP_VARIABLE); + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_COMMENT: + if (ch == '/' && chPrev == '*') { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_HSTRING: + if (ch == '\\' && (phpStringDelimiter[0] == '\"' || chNext == '$' || chNext == '{')) { + // skip the next char + i++; + } else if (((ch == '{' && chNext == '$') || (ch == '$' && chNext == '{')) + && IsPhpWordStart(chNext2)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HPHP_COMPLEX_VARIABLE; + } else if (ch == '$' && IsPhpWordStart(chNext)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HPHP_HSTRING_VARIABLE; + } else if (styler.Match(i, phpStringDelimiter)) { + if (phpStringDelimiter[0] == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + } else if (isLineEnd(chPrev)) { + const int psdLength = strlen(phpStringDelimiter); + const char chAfterPsd = styler.SafeGetCharAt(i + psdLength); + const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1); + if (isLineEnd(chAfterPsd) || + (chAfterPsd == ';' && isLineEnd(chAfterPsd2))) { + i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1; + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + if (foldHeredoc) levelCurrent--; + } + } + } + break; + case SCE_HPHP_SIMPLESTRING: + if (phpStringDelimiter[0] == '\'') { + if (ch == '\\') { + // skip the next char + i++; + } else if (ch == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + } + } else if (isLineEnd(chPrev) && styler.Match(i, phpStringDelimiter)) { + const int psdLength = strlen(phpStringDelimiter); + const char chAfterPsd = styler.SafeGetCharAt(i + psdLength); + const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1); + if (isLineEnd(chAfterPsd) || + (chAfterPsd == ';' && isLineEnd(chAfterPsd2))) { + i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1; + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + if (foldHeredoc) levelCurrent--; + } + } + break; + case SCE_HPHP_HSTRING_VARIABLE: + if (!IsPhpWordChar(chNext)) { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_HSTRING; + } + break; + case SCE_HPHP_COMPLEX_VARIABLE: + if (ch == '}') { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_HSTRING; + } + break; + case SCE_HPHP_OPERATOR: + case SCE_HPHP_DEFAULT: + styler.ColourTo(i - 1, StateToPrint); + if (IsADigit(ch) || (ch == '.' && IsADigit(chNext))) { + state = SCE_HPHP_NUMBER; + } else if (IsAWordStart(ch)) { + state = SCE_HPHP_WORD; + } else if (ch == '/' && chNext == '*') { + i++; + state = SCE_HPHP_COMMENT; + } else if (ch == '/' && chNext == '/') { + i++; + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '#') { + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_HPHP_HSTRING; + strcpy(phpStringDelimiter, "\""); + } else if (styler.Match(i, "<<<")) { + bool isSimpleString = false; + i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString); + if (strlen(phpStringDelimiter)) { + state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING); + if (foldHeredoc) levelCurrent++; + } + } else if (ch == '\'') { + state = SCE_HPHP_SIMPLESTRING; + strcpy(phpStringDelimiter, "\'"); + } else if (ch == '$' && IsPhpWordStart(chNext)) { + state = SCE_HPHP_VARIABLE; + } else if (IsOperator(ch)) { + state = SCE_HPHP_OPERATOR; + } else if ((state == SCE_HPHP_OPERATOR) && (IsASpace(ch))) { + state = SCE_HPHP_DEFAULT; + } + break; + ///////////// end - PHP state handling + } + + // Some of the above terminated their lexeme but since the same character starts + // the same class again, only reenter if non empty segment. + + bool nonEmptySegment = i >= static_cast(styler.GetStartSegment()); + if (state == SCE_HB_DEFAULT) { // One of the above succeeded + if ((ch == '\"') && (nonEmptySegment)) { + state = SCE_HB_STRING; + } else if (ch == '\'') { + state = SCE_HB_COMMENTLINE; + } else if (IsAWordStart(ch)) { + state = SCE_HB_WORD; + } else if (IsOperator(ch)) { + styler.ColourTo(i, SCE_HB_DEFAULT); + } + } else if (state == SCE_HBA_DEFAULT) { // One of the above succeeded + if ((ch == '\"') && (nonEmptySegment)) { + state = SCE_HBA_STRING; + } else if (ch == '\'') { + state = SCE_HBA_COMMENTLINE; + } else if (IsAWordStart(ch)) { + state = SCE_HBA_WORD; + } else if (IsOperator(ch)) { + styler.ColourTo(i, SCE_HBA_DEFAULT); + } + } else if (state == SCE_HJ_DEFAULT) { // One of the above succeeded + if (ch == '/' && chNext == '*') { + if (styler.SafeGetCharAt(i + 2) == '*') + state = SCE_HJ_COMMENTDOC; + else + state = SCE_HJ_COMMENT; + } else if (ch == '/' && chNext == '/') { + state = SCE_HJ_COMMENTLINE; + } else if ((ch == '\"') && (nonEmptySegment)) { + state = SCE_HJ_DOUBLESTRING; + } else if ((ch == '\'') && (nonEmptySegment)) { + state = SCE_HJ_SINGLESTRING; + } else if (IsAWordStart(ch)) { + state = SCE_HJ_WORD; + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); + } + } + } + + switch (state) { + case SCE_HJ_WORD: + classifyWordHTJS(styler.GetStartSegment(), lengthDoc - 1, keywords2, styler, inScriptType); + break; + case SCE_HB_WORD: + classifyWordHTVB(styler.GetStartSegment(), lengthDoc - 1, keywords3, styler, inScriptType); + break; + case SCE_HP_WORD: + classifyWordHTPy(styler.GetStartSegment(), lengthDoc - 1, keywords4, styler, prevWord, inScriptType); + break; + case SCE_HPHP_WORD: + classifyWordHTPHP(styler.GetStartSegment(), lengthDoc - 1, keywords5, styler); + break; + default: + StateToPrint = statePrintForState(state, inScriptType); + styler.ColourTo(lengthDoc - 1, StateToPrint); + break; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + if (fold) { + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); + } +} + +static void ColouriseXMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + // Passing in true because we're lexing XML + ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, true); +} + +static void ColouriseHTMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + // Passing in false because we're notlexing XML + ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, false); +} + +static void ColourisePHPScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + if (startPos == 0) + initStyle = SCE_HPHP_DEFAULT; + ColouriseHTMLDoc(startPos, length, initStyle, keywordlists, styler); +} + +static const char * const htmlWordListDesc[] = { + "HTML elements and attributes", + "JavaScript keywords", + "VBScript keywords", + "Python keywords", + "PHP keywords", + "SGML and DTD keywords", + 0, +}; + +static const char * const phpscriptWordListDesc[] = { + "", //Unused + "", //Unused + "", //Unused + "", //Unused + "PHP keywords", + "", //Unused + 0, +}; + +LexerModule lmHTML(SCLEX_HTML, ColouriseHTMLDoc, "hypertext", 0, htmlWordListDesc, 8); +LexerModule lmXML(SCLEX_XML, ColouriseXMLDoc, "xml", 0, htmlWordListDesc, 8); +LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc, 8); diff --git a/lexers/LexHaskell.cxx b/lexers/LexHaskell.cxx new file mode 100644 index 000000000..b528f3f0e --- /dev/null +++ b/lexers/LexHaskell.cxx @@ -0,0 +1,275 @@ +/****************************************************************** + * LexHaskell.cxx + * + * A haskell lexer for the scintilla code control. + * Some stuff "lended" from LexPython.cxx and LexCPP.cxx. + * External lexer stuff inspired from the caml external lexer. + * + * Written by Tobias Engvall - tumm at dtek dot chalmers dot se + * + * + * TODO: + * * Implement a folder :) + * * Nice Character-lexing (stuff inside '\''), LexPython has + * this. + * + * + *****************************************************************/ + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "PropSetSimple.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#ifdef BUILD_AS_EXTERNAL_LEXER + +#include "ExternalLexer.h" +#include "WindowAccessor.h" + +#define BUILD_EXTERNAL_LEXER 0 + +#endif + +// Max level of nested comments +#define SCE_HA_COMMENTMAX SCE_HA_COMMENTBLOCK3 + + +enum kwType { kwOther, kwClass, kwData, kwInstance, kwImport, kwModule, kwType}; + +static inline bool IsNewline(const int ch) { + return (ch == '\n' || ch == '\r'); +} + +static inline bool IsWhitespace(const int ch) { + return ( ch == ' ' + || ch == '\t' + || IsNewline(ch) ); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''); +} + +static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + + int kwLast = kwOther; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + // Check for state end + // Operator + if (sc.state == SCE_HA_OPERATOR) { + kwLast = kwOther; + sc.SetState(SCE_HA_DEFAULT); + } + // String + else if (sc.state == SCE_HA_STRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_HA_DEFAULT); + } else if (sc.ch == '\\') { + sc.Forward(); + } + } + // Char + else if (sc.state == SCE_HA_CHARACTER) { + if (sc.ch == '\'') { + sc.ForwardSetState(SCE_HA_DEFAULT); + } else if (sc.ch == '\\') { + sc.Forward(); + } + } + // Number + else if (sc.state == SCE_HA_NUMBER) { + if (!IsADigit(sc.ch)) { + sc.SetState(SCE_HA_DEFAULT); + } + } + // Types, constructors, etc. + else if (sc.state == SCE_HA_CAPITAL) { + if (!IsAWordChar(sc.ch) || sc.ch == '.') { + sc.SetState(SCE_HA_DEFAULT); + } + } + // Identifier + else if (sc.state == SCE_HA_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + int style = SCE_HA_IDENTIFIER; + if ((kwLast == kwImport) || (strcmp(s,"qualified") == 0) || (strcmp(s,"as") == 0)) { + style = SCE_HA_IMPORT; + } else if (keywords.InList(s)) { + style = SCE_HA_KEYWORD; + } else if (kwLast == kwData) { + style = SCE_HA_DATA; + } else if (kwLast == kwClass) { + style = SCE_HA_CLASS; + } else if (kwLast == kwModule) { + style = SCE_HA_MODULE; + } else if (isupper(s[0])) { + style = SCE_HA_CAPITAL; + } + sc.ChangeState(style); + sc.SetState(SCE_HA_DEFAULT); + if (style == SCE_HA_KEYWORD) { + if (0 == strcmp(s, "class")) + kwLast = kwClass; + else if (0 == strcmp(s, "data")) + kwLast = kwData; + else if (0 == strcmp(s, "instance")) + kwLast = kwInstance; + else if (0 == strcmp(s, "import")) + kwLast = kwImport; + else if (0 == strcmp(s, "module")) + kwLast = kwModule; + else + kwLast = kwOther; + } else if (style == SCE_HA_CLASS || style == SCE_HA_IMPORT || + style == SCE_HA_MODULE || style == SCE_HA_CAPITAL || + style == SCE_HA_DATA || style == SCE_HA_INSTANCE) { + kwLast = kwOther; + } + } + } + // Comments + // Oneliner + else if (sc.state == SCE_HA_COMMENTLINE) { + if (IsNewline(sc.ch)) + sc.SetState(SCE_HA_DEFAULT); + } + // Nested + else if (sc.state >= SCE_HA_COMMENTBLOCK) { + if (sc.Match("{-")) { + if (sc.state < SCE_HA_COMMENTMAX) + sc.SetState(sc.state + 1); + } + else if (sc.Match("-}")) { + sc.Forward(); + if (sc.state == SCE_HA_COMMENTBLOCK) + sc.ForwardSetState(SCE_HA_DEFAULT); + else + sc.ForwardSetState(sc.state - 1); + } + } + // New state? + if (sc.state == SCE_HA_DEFAULT) { + // Digit + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_HA_NUMBER); + if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) { // Match anything starting with "0x" or "0X", too + sc.Forward(1); + } + } + // Comment line + else if (sc.Match("--")) { + sc.SetState(SCE_HA_COMMENTLINE); + // Comment block + } + else if (sc.Match("{-")) { + sc.SetState(SCE_HA_COMMENTBLOCK); + } + // String + else if (sc.Match('\"')) { + sc.SetState(SCE_HA_STRING); + } + // Character + else if (sc.Match('\'')) { + sc.SetState(SCE_HA_CHARACTER); + } + // Stringstart + else if (sc.Match('\"')) { + sc.SetState(SCE_HA_STRING); + } + // Operator + else if (isascii(sc.ch) && isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_HA_OPERATOR); + } + // Keyword + else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_HA_IDENTIFIER); + } + + } + } + sc.Complete(); +} + +// External stuff - used for dynamic-loading, not implemented in wxStyledTextCtrl yet. +// Inspired by the caml external lexer - Credits to Robert Roessler - http://www.rftp.com +#ifdef BUILD_EXTERNAL_LEXER +static const char* LexerName = "haskell"; + +void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, int initStyle, + char *words[], WindowID window, char *props) +{ + PropSetSimple ps; + ps.SetMultiple(props); + WindowAccessor wa(window, ps); + + int nWL = 0; + for (; words[nWL]; nWL++) ; + WordList** wl = new WordList* [nWL + 1]; + int i = 0; + for (; iSet(words[i]); + } + wl[i] = 0; + + ColorizeHaskellDoc(startPos, length, initStyle, wl, wa); + wa.Flush(); + for (i=nWL-1;i>=0;i--) + delete wl[i]; + delete [] wl; +} + +void EXT_LEXER_DECL Fold (unsigned int lexer, unsigned int startPos, int length, int initStyle, + char *words[], WindowID window, char *props) +{ + +} + +int EXT_LEXER_DECL GetLexerCount() +{ + return 1; +} + +void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength) +{ + if (buflength > 0) { + buflength--; + int n = strlen(LexerName); + if (n > buflength) + n = buflength; + memcpy(name, LexerName, n), name[n] = '\0'; + } +} +#endif + +LexerModule lmHaskell(SCLEX_HASKELL, ColorizeHaskellDoc, "haskell"); + diff --git a/lexers/LexInno.cxx b/lexers/LexInno.cxx new file mode 100644 index 000000000..6d1102c65 --- /dev/null +++ b/lexers/LexInno.cxx @@ -0,0 +1,279 @@ +// Scintilla source code edit control +/** @file LexInno.cxx + ** Lexer for Inno Setup scripts. + **/ +// Written by Friedrich Vedder , using code from LexOthers.cxx. +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "CharClassify.h" +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) { + int state = SCE_INNO_DEFAULT; + char chPrev; + char ch = 0; + char chNext = styler[startPos]; + int lengthDoc = startPos + length; + char *buffer = new char[length]; + int bufferCount = 0; + bool isBOL, isEOL, isWS, isBOLWS = 0; + bool isCode = false; + bool isCStyleComment = false; + + WordList §ionKeywords = *keywordLists[0]; + WordList &standardKeywords = *keywordLists[1]; + WordList ¶meterKeywords = *keywordLists[2]; + WordList &preprocessorKeywords = *keywordLists[3]; + WordList &pascalKeywords = *keywordLists[4]; + WordList &userKeywords = *keywordLists[5]; + + // Go through all provided text segment + // using the hand-written state machine shown below + styler.StartAt(startPos); + styler.StartSegment(startPos); + for (int i = startPos; i < lengthDoc; i++) { + chPrev = ch; + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + i++; + continue; + } + + isBOL = (chPrev == 0) || (chPrev == '\n') || (chPrev == '\r' && ch != '\n'); + isBOLWS = (isBOL) ? 1 : (isBOLWS && (chPrev == ' ' || chPrev == '\t')); + isEOL = (ch == '\n' || ch == '\r'); + isWS = (ch == ' ' || ch == '\t'); + + switch(state) { + case SCE_INNO_DEFAULT: + if (!isCode && ch == ';' && isBOLWS) { + // Start of a comment + state = SCE_INNO_COMMENT; + } else if (ch == '[' && isBOLWS) { + // Start of a section name + bufferCount = 0; + state = SCE_INNO_SECTION; + } else if (ch == '#' && isBOLWS) { + // Start of a preprocessor directive + state = SCE_INNO_PREPROC; + } else if (!isCode && ch == '{' && chNext != '{' && chPrev != '{') { + // Start of an inline expansion + state = SCE_INNO_INLINE_EXPANSION; + } else if (isCode && (ch == '{' || (ch == '(' && chNext == '*'))) { + // Start of a Pascal comment + state = SCE_INNO_COMMENT_PASCAL; + isCStyleComment = false; + } else if (isCode && ch == '/' && chNext == '/') { + // Apparently, C-style comments are legal, too + state = SCE_INNO_COMMENT_PASCAL; + isCStyleComment = true; + } else if (ch == '"') { + // Start of a double-quote string + state = SCE_INNO_STRING_DOUBLE; + } else if (ch == '\'') { + // Start of a single-quote string + state = SCE_INNO_STRING_SINGLE; + } else if (isascii(ch) && (isalpha(ch) || (ch == '_'))) { + // Start of an identifier + bufferCount = 0; + buffer[bufferCount++] = static_cast(tolower(ch)); + state = SCE_INNO_IDENTIFIER; + } else { + // Style it the default style + styler.ColourTo(i,SCE_INNO_DEFAULT); + } + break; + + case SCE_INNO_COMMENT: + if (isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_COMMENT); + } + break; + + case SCE_INNO_IDENTIFIER: + if (isascii(ch) && (isalnum(ch) || (ch == '_'))) { + buffer[bufferCount++] = static_cast(tolower(ch)); + } else { + state = SCE_INNO_DEFAULT; + buffer[bufferCount] = '\0'; + + // Check if the buffer contains a keyword + if (!isCode && standardKeywords.InList(buffer)) { + styler.ColourTo(i-1,SCE_INNO_KEYWORD); + } else if (!isCode && parameterKeywords.InList(buffer)) { + styler.ColourTo(i-1,SCE_INNO_PARAMETER); + } else if (isCode && pascalKeywords.InList(buffer)) { + styler.ColourTo(i-1,SCE_INNO_KEYWORD_PASCAL); + } else if (!isCode && userKeywords.InList(buffer)) { + styler.ColourTo(i-1,SCE_INNO_KEYWORD_USER); + } else { + styler.ColourTo(i-1,SCE_INNO_DEFAULT); + } + + // Push back the faulty character + chNext = styler[i--]; + ch = chPrev; + } + break; + + case SCE_INNO_SECTION: + if (ch == ']') { + state = SCE_INNO_DEFAULT; + buffer[bufferCount] = '\0'; + + // Check if the buffer contains a section name + if (sectionKeywords.InList(buffer)) { + styler.ColourTo(i,SCE_INNO_SECTION); + isCode = !CompareCaseInsensitive(buffer, "code"); + } else { + styler.ColourTo(i,SCE_INNO_DEFAULT); + } + } else if (isascii(ch) && (isalnum(ch) || (ch == '_'))) { + buffer[bufferCount++] = static_cast(tolower(ch)); + } else { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_DEFAULT); + } + break; + + case SCE_INNO_PREPROC: + if (isWS || isEOL) { + if (isascii(chPrev) && isalpha(chPrev)) { + state = SCE_INNO_DEFAULT; + buffer[bufferCount] = '\0'; + + // Check if the buffer contains a preprocessor directive + if (preprocessorKeywords.InList(buffer)) { + styler.ColourTo(i-1,SCE_INNO_PREPROC); + } else { + styler.ColourTo(i-1,SCE_INNO_DEFAULT); + } + + // Push back the faulty character + chNext = styler[i--]; + ch = chPrev; + } + } else if (isascii(ch) && isalpha(ch)) { + if (chPrev == '#' || chPrev == ' ' || chPrev == '\t') + bufferCount = 0; + buffer[bufferCount++] = static_cast(tolower(ch)); + } + break; + + case SCE_INNO_STRING_DOUBLE: + if (ch == '"' || isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_STRING_DOUBLE); + } + break; + + case SCE_INNO_STRING_SINGLE: + if (ch == '\'' || isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_STRING_SINGLE); + } + break; + + case SCE_INNO_INLINE_EXPANSION: + if (ch == '}') { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_INLINE_EXPANSION); + } else if (isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_DEFAULT); + } + break; + + case SCE_INNO_COMMENT_PASCAL: + if (isCStyleComment) { + if (isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL); + } + } else { + if (ch == '}' || (ch == ')' && chPrev == '*')) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL); + } else if (isEOL) { + state = SCE_INNO_DEFAULT; + styler.ColourTo(i,SCE_INNO_DEFAULT); + } + } + break; + + } + } + delete []buffer; +} + +static const char * const innoWordListDesc[] = { + "Sections", + "Keywords", + "Parameters", + "Preprocessor directives", + "Pascal keywords", + "User defined keywords", + 0 +}; + +static void FoldInnoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + unsigned int endPos = startPos + length; + char chNext = styler[startPos]; + + int lineCurrent = styler.GetLine(startPos); + + bool sectionFlag = false; + int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) : SC_FOLDLEVELBASE; + int level; + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler[i+1]; + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + int style = styler.StyleAt(i); + + if (style == SCE_INNO_SECTION) + sectionFlag = true; + + if (atEOL || i == endPos - 1) { + if (sectionFlag) { + level = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; + if (level == levelPrev) + styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG); + } else { + level = levelPrev & SC_FOLDLEVELNUMBERMASK; + if (levelPrev & SC_FOLDLEVELHEADERFLAG) + level++; + } + + styler.SetLevel(lineCurrent, level); + + levelPrev = level; + lineCurrent++; + sectionFlag = false; + } + } +} + +LexerModule lmInno(SCLEX_INNOSETUP, ColouriseInnoDoc, "inno", FoldInnoDoc, innoWordListDesc); diff --git a/lexers/LexKix.cxx b/lexers/LexKix.cxx new file mode 100644 index 000000000..06e7c1791 --- /dev/null +++ b/lexers/LexKix.cxx @@ -0,0 +1,126 @@ +// Scintilla source code edit control +/** @file LexKix.cxx + ** Lexer for KIX-Scripts. + **/ +// Copyright 2004 by Manfred Becker +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// Extended to accept accented characters +static inline bool IsAWordChar(int ch) { + return ch >= 0x80 || isalnum(ch) || ch == '_'; +} + +static inline bool IsOperator(const int ch) { + return (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '&' || ch == '|' || ch == '<' || ch == '>' || ch == '='); +} + +static void ColouriseKixDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; +// WordList &keywords4 = *keywordlists[3]; + + styler.StartAt(startPos); + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.state == SCE_KIX_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_STRING1) { + // This is a doubles quotes string + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_STRING2) { + // This is a single quote string + if (sc.ch == '\'') { + sc.ForwardSetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_NUMBER) { + if (!IsADigit(sc.ch)) { + sc.SetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_VAR) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_MACRO) { + if (!IsAWordChar(sc.ch) && !IsADigit(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + + if (!keywords3.InList(&s[1])) { + sc.ChangeState(SCE_KIX_DEFAULT); + } + sc.SetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_OPERATOR) { + if (!IsOperator(sc.ch)) { + sc.SetState(SCE_KIX_DEFAULT); + } + } else if (sc.state == SCE_KIX_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + + if (keywords.InList(s)) { + sc.ChangeState(SCE_KIX_KEYWORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_KIX_FUNCTIONS); + } + sc.SetState(SCE_KIX_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_KIX_DEFAULT) { + if (sc.ch == ';') { + sc.SetState(SCE_KIX_COMMENT); + } else if (sc.ch == '\"') { + sc.SetState(SCE_KIX_STRING1); + } else if (sc.ch == '\'') { + sc.SetState(SCE_KIX_STRING2); + } else if (sc.ch == '$') { + sc.SetState(SCE_KIX_VAR); + } else if (sc.ch == '@') { + sc.SetState(SCE_KIX_MACRO); + } else if (IsADigit(sc.ch) || ((sc.ch == '.' || sc.ch == '&') && IsADigit(sc.chNext))) { + sc.SetState(SCE_KIX_NUMBER); + } else if (IsOperator(sc.ch)) { + sc.SetState(SCE_KIX_OPERATOR); + } else if (IsAWordChar(sc.ch)) { + sc.SetState(SCE_KIX_IDENTIFIER); + } + } + } + sc.Complete(); +} + + +LexerModule lmKix(SCLEX_KIX, ColouriseKixDoc, "kix"); + diff --git a/lexers/LexLisp.cxx b/lexers/LexLisp.cxx new file mode 100644 index 000000000..ad5535f14 --- /dev/null +++ b/lexers/LexLisp.cxx @@ -0,0 +1,282 @@ +// Scintilla source code edit control +/** @file LexLisp.cxx + ** Lexer for Lisp. + ** Written by Alexey Yutkin. + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "StyleContext.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#define SCE_LISP_CHARACTER 29 +#define SCE_LISP_MACRO 30 +#define SCE_LISP_MACRO_DISPATCH 31 + +static inline bool isLispoperator(char ch) { + if (isascii(ch) && isalnum(ch)) + return false; + if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}') + return true; + return false; +} + +static inline bool isLispwordstart(char ch) { + return isascii(ch) && ch != ';' && !isspacechar(ch) && !isLispoperator(ch) && + ch != '\n' && ch != '\r' && ch != '\"'; +} + + +static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, WordList &keywords_kw, Accessor &styler) { + PLATFORM_ASSERT(end >= start); + char s[100]; + unsigned int i; + bool digit_flag = true; + for (i = 0; (i < end - start + 1) && (i < 99); i++) { + s[i] = styler[start + i]; + s[i + 1] = '\0'; + if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false; + } + char chAttr = SCE_LISP_IDENTIFIER; + + if(digit_flag) chAttr = SCE_LISP_NUMBER; + else { + if (keywords.InList(s)) { + chAttr = SCE_LISP_KEYWORD; + } else if (keywords_kw.InList(s)) { + chAttr = SCE_LISP_KEYWORD_KW; + } else if ((s[0] == '*' && s[i-1] == '*') || + (s[0] == '+' && s[i-1] == '+')) { + chAttr = SCE_LISP_SPECIAL; + } + } + styler.ColourTo(end, chAttr); + return; +} + + +static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords_kw = *keywordlists[1]; + + styler.StartAt(startPos); + + int state = initStyle, radix = -1; + char chNext = styler[startPos]; + unsigned int lengthDoc = startPos + length; + styler.StartSegment(startPos); + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + i += 1; + continue; + } + + if (state == SCE_LISP_DEFAULT) { + if (ch == '#') { + styler.ColourTo(i - 1, state); + radix = -1; + state = SCE_LISP_MACRO_DISPATCH; + } else if (ch == ':' && isLispwordstart(chNext)) { + styler.ColourTo(i - 1, state); + state = SCE_LISP_SYMBOL; + } else if (isLispwordstart(ch)) { + styler.ColourTo(i - 1, state); + state = SCE_LISP_IDENTIFIER; + } + else if (ch == ';') { + styler.ColourTo(i - 1, state); + state = SCE_LISP_COMMENT; + } + else if (isLispoperator(ch) || ch=='\'') { + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_LISP_OPERATOR); + if (ch=='\'' && isLispwordstart(chNext)) { + state = SCE_LISP_SYMBOL; + } + } + else if (ch == '\"') { + styler.ColourTo(i - 1, state); + state = SCE_LISP_STRING; + } + } else if (state == SCE_LISP_IDENTIFIER || state == SCE_LISP_SYMBOL) { + if (!isLispwordstart(ch)) { + if (state == SCE_LISP_IDENTIFIER) { + classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler); + } else { + styler.ColourTo(i - 1, state); + } + state = SCE_LISP_DEFAULT; + } /*else*/ + if (isLispoperator(ch) || ch=='\'') { + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_LISP_OPERATOR); + if (ch=='\'' && isLispwordstart(chNext)) { + state = SCE_LISP_SYMBOL; + } + } + } else if (state == SCE_LISP_MACRO_DISPATCH) { + if (!(isascii(ch) && isdigit(ch))) { + if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) { + state = SCE_LISP_DEFAULT; + } else { + switch (ch) { + case '|': state = SCE_LISP_MULTI_COMMENT; break; + case 'o': + case 'O': radix = 8; state = SCE_LISP_MACRO; break; + case 'x': + case 'X': radix = 16; state = SCE_LISP_MACRO; break; + case 'b': + case 'B': radix = 2; state = SCE_LISP_MACRO; break; + case '\\': state = SCE_LISP_CHARACTER; break; + case ':': + case '-': + case '+': state = SCE_LISP_MACRO; break; + case '\'': if (isLispwordstart(chNext)) { + state = SCE_LISP_SPECIAL; + } else { + styler.ColourTo(i - 1, SCE_LISP_DEFAULT); + styler.ColourTo(i, SCE_LISP_OPERATOR); + state = SCE_LISP_DEFAULT; + } + break; + default: if (isLispoperator(ch)) { + styler.ColourTo(i - 1, SCE_LISP_DEFAULT); + styler.ColourTo(i, SCE_LISP_OPERATOR); + } + state = SCE_LISP_DEFAULT; + break; + } + } + } + } else if (state == SCE_LISP_MACRO) { + if (isLispwordstart(ch) && (radix == -1 || IsADigit(ch, radix))) { + state = SCE_LISP_SPECIAL; + } else { + state = SCE_LISP_DEFAULT; + } + } else if (state == SCE_LISP_CHARACTER) { + if (isLispoperator(ch)) { + styler.ColourTo(i, SCE_LISP_SPECIAL); + state = SCE_LISP_DEFAULT; + } else if (isLispwordstart(ch)) { + styler.ColourTo(i, SCE_LISP_SPECIAL); + state = SCE_LISP_SPECIAL; + } else { + state = SCE_LISP_DEFAULT; + } + } else if (state == SCE_LISP_SPECIAL) { + if (!isLispwordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) { + styler.ColourTo(i - 1, state); + state = SCE_LISP_DEFAULT; + } + if (isLispoperator(ch) || ch=='\'') { + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_LISP_OPERATOR); + if (ch=='\'' && isLispwordstart(chNext)) { + state = SCE_LISP_SYMBOL; + } + } + } else { + if (state == SCE_LISP_COMMENT) { + if (atEOL) { + styler.ColourTo(i - 1, state); + state = SCE_LISP_DEFAULT; + } + } else if (state == SCE_LISP_MULTI_COMMENT) { + if (ch == '|' && chNext == '#') { + i++; + chNext = styler.SafeGetCharAt(i + 1); + styler.ColourTo(i, state); + state = SCE_LISP_DEFAULT; + } + } else if (state == SCE_LISP_STRING) { + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + chNext = styler.SafeGetCharAt(i + 1); + } + } else if (ch == '\"') { + styler.ColourTo(i, state); + state = SCE_LISP_DEFAULT; + } + } + } + + } + styler.ColourTo(lengthDoc - 1, state); +} + +static void FoldLispDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[], + Accessor &styler) { + unsigned int lengthDoc = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (style == SCE_LISP_OPERATOR) { + if (ch == '(' || ch == '[' || ch == '{') { + levelCurrent++; + } else if (ch == ')' || ch == ']' || ch == '}') { + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const lispWordListDesc[] = { + "Functions and special operators", + "Keywords", + 0 +}; + +LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc); diff --git a/lexers/LexLout.cxx b/lexers/LexLout.cxx new file mode 100644 index 000000000..492e4ed6d --- /dev/null +++ b/lexers/LexLout.cxx @@ -0,0 +1,212 @@ +// Scintilla source code edit control +/** @file LexLout.cxx + ** Lexer for the Basser Lout (>= version 3) typesetting language + **/ +// Copyright 2003 by Kein-Hong Man +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalpha(ch) || ch == '@' || ch == '_'); +} + +static inline bool IsAnOther(const int ch) { + return (ch < 0x80) && (ch == '{' || ch == '}' || + ch == '!' || ch == '$' || ch == '%' || ch == '&' || ch == '\'' || + ch == '(' || ch == ')' || ch == '*' || ch == '+' || ch == ',' || + ch == '-' || ch == '.' || ch == '/' || ch == ':' || ch == ';' || + ch == '<' || ch == '=' || ch == '>' || ch == '?' || ch == '[' || + ch == ']' || ch == '^' || ch == '`' || ch == '|' || ch == '~'); +} + +static void ColouriseLoutDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + + int visibleChars = 0; + int firstWordInLine = 0; + int leadingAtSign = 0; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart && (sc.state == SCE_LOUT_STRING)) { + // Prevent SCE_LOUT_STRINGEOL from leaking back to previous line + sc.SetState(SCE_LOUT_STRING); + } + + // Determine if the current state should terminate. + if (sc.state == SCE_LOUT_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_LOUT_DEFAULT); + visibleChars = 0; + } + } else if (sc.state == SCE_LOUT_NUMBER) { + if (!IsADigit(sc.ch) && sc.ch != '.') { + sc.SetState(SCE_LOUT_DEFAULT); + } + } else if (sc.state == SCE_LOUT_STRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_LOUT_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_LOUT_STRINGEOL); + sc.ForwardSetState(SCE_LOUT_DEFAULT); + visibleChars = 0; + } + } else if (sc.state == SCE_LOUT_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + + if (leadingAtSign) { + if (keywords.InList(s)) { + sc.ChangeState(SCE_LOUT_WORD); + } else { + sc.ChangeState(SCE_LOUT_WORD4); + } + } else if (firstWordInLine && keywords3.InList(s)) { + sc.ChangeState(SCE_LOUT_WORD3); + } + sc.SetState(SCE_LOUT_DEFAULT); + } + } else if (sc.state == SCE_LOUT_OPERATOR) { + if (!IsAnOther(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + + if (keywords2.InList(s)) { + sc.ChangeState(SCE_LOUT_WORD2); + } + sc.SetState(SCE_LOUT_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_LOUT_DEFAULT) { + if (sc.ch == '#') { + sc.SetState(SCE_LOUT_COMMENT); + } else if (sc.ch == '\"') { + sc.SetState(SCE_LOUT_STRING); + } else if (IsADigit(sc.ch) || + (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_LOUT_NUMBER); + } else if (IsAWordChar(sc.ch)) { + firstWordInLine = (visibleChars == 0); + leadingAtSign = (sc.ch == '@'); + sc.SetState(SCE_LOUT_IDENTIFIER); + } else if (IsAnOther(sc.ch)) { + sc.SetState(SCE_LOUT_OPERATOR); + } + } + + if (sc.atLineEnd) { + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + } + if (!IsASpace(sc.ch)) { + visibleChars++; + } + } + sc.Complete(); +} + +static void FoldLoutDoc(unsigned int startPos, int length, int, WordList *[], + Accessor &styler) { + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + int styleNext = styler.StyleAt(startPos); + char s[10]; + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (style == SCE_LOUT_WORD) { + if (ch == '@') { + for (unsigned int j = 0; j < 8; j++) { + if (!IsAWordChar(styler[i + j])) { + break; + } + s[j] = styler[i + j]; + s[j + 1] = '\0'; + } + if (strcmp(s, "@Begin") == 0) { + levelCurrent++; + } else if (strcmp(s, "@End") == 0) { + levelCurrent--; + } + } + } else if (style == SCE_LOUT_OPERATOR) { + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) { + lev |= SC_FOLDLEVELWHITEFLAG; + } + if ((levelCurrent > levelPrev) && (visibleChars > 0)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const loutWordLists[] = { + "Predefined identifiers", + "Predefined delimiters", + "Predefined keywords", + 0, + }; + +LexerModule lmLout(SCLEX_LOUT, ColouriseLoutDoc, "lout", FoldLoutDoc, loutWordLists); diff --git a/lexers/LexLua.cxx b/lexers/LexLua.cxx new file mode 100644 index 000000000..a1e579f26 --- /dev/null +++ b/lexers/LexLua.cxx @@ -0,0 +1,358 @@ +// 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 "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "CharacterSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// 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( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; + WordList &keywords7 = *keywordlists[6]; + WordList &keywords8 = *keywordlists[7]; + + // Accepts accented characters + CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); + // Not exactly following number definition (several dots are seen as OK, etc.) + // but probably enough in most cases. + CharacterSet setNumber(CharacterSet::setDigits, ".-+abcdefABCDEF"); + CharacterSet setLuaOperator(CharacterSet::setNone, "*/-+()={}~[];<>,.^%:#"); + CharacterSet setEscapeSkip(CharacterSet::setNone, "\"'\\"); + + int currentLine = styler.GetLine(startPos); + // Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level, + // if we are inside such a string. Block comment was introduced in Lua 5.0, + // blocks with separators [=[ ... ]=] in Lua 5.1. + int nestLevel = 0; + int sepCount = 0; + if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT) { + int lineState = styler.GetLineState(currentLine - 1); + nestLevel = lineState >> 8; + sepCount = lineState & 0xFF; + } + + // 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 == '#') { + // shbang line: # is a comment only if first char 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: + // Inside a literal string or block comment, we set the line state + styler.SetLineState(currentLine, (nestLevel << 8) | 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) { + sc.SetState(SCE_LUA_DEFAULT); + } else if (sc.state == SCE_LUA_NUMBER) { + // We stop the number definition on non-numerical non-dot non-eE non-sign non-hexdigit char + if (!setNumber.Contains(sc.ch)) { + sc.SetState(SCE_LUA_DEFAULT); + } else if (sc.ch == '-' || sc.ch == '+') { + if (sc.chPrev != 'E' && sc.chPrev != 'e') + sc.SetState(SCE_LUA_DEFAULT); + } + } else if (sc.state == SCE_LUA_IDENTIFIER) { + if (!setWord.Contains(sc.ch) || sc.Match('.', '.')) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_LUA_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_LUA_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_LUA_WORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_LUA_WORD4); + } else if (keywords5.InList(s)) { + sc.ChangeState(SCE_LUA_WORD5); + } else if (keywords6.InList(s)) { + sc.ChangeState(SCE_LUA_WORD6); + } else if (keywords7.InList(s)) { + sc.ChangeState(SCE_LUA_WORD7); + } else if (keywords8.InList(s)) { + sc.ChangeState(SCE_LUA_WORD8); + } + sc.SetState(SCE_LUA_DEFAULT); + } + } else if (sc.state == SCE_LUA_COMMENTLINE || sc.state == SCE_LUA_PREPROCESSOR) { + if (sc.atLineEnd) { + sc.ForwardSetState(SCE_LUA_DEFAULT); + } + } else if (sc.state == SCE_LUA_STRING) { + if (sc.ch == '\\') { + if (setEscapeSkip.Contains(sc.chNext)) { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_LUA_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_LUA_STRINGEOL); + sc.ForwardSetState(SCE_LUA_DEFAULT); + } + } else if (sc.state == SCE_LUA_CHARACTER) { + if (sc.ch == '\\') { + if (setEscapeSkip.Contains(sc.chNext)) { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_LUA_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_LUA_STRINGEOL); + sc.ForwardSetState(SCE_LUA_DEFAULT); + } + } else if (sc.state == SCE_LUA_LITERALSTRING || sc.state == SCE_LUA_COMMENT) { + if (sc.ch == '[') { + int sep = LongDelimCheck(sc); + if (sep == 1 && sepCount == 1) { // [[-only allowed to nest + nestLevel++; + sc.Forward(); + } + } else if (sc.ch == ']') { + int sep = LongDelimCheck(sc); + if (sep == 1 && sepCount == 1) { // un-nest with ]]-only + nestLevel--; + sc.Forward(); + if (nestLevel == 0) { + sc.ForwardSetState(SCE_LUA_DEFAULT); + } + } else if (sep > 1 && sep == sepCount) { // ]=]-style delim + sc.Forward(sep); + sc.ForwardSetState(SCE_LUA_DEFAULT); + } + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_LUA_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_LUA_NUMBER); + if (sc.ch == '0' && toupper(sc.chNext) == 'X') { + sc.Forward(); + } + } else if (setWordStart.Contains(sc.ch)) { + sc.SetState(SCE_LUA_IDENTIFIER); + } else if (sc.ch == '\"') { + sc.SetState(SCE_LUA_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_LUA_CHARACTER); + } else if (sc.ch == '[') { + sepCount = LongDelimCheck(sc); + if (sepCount == 0) { + sc.SetState(SCE_LUA_OPERATOR); + } else { + nestLevel = 1; + sc.SetState(SCE_LUA_LITERALSTRING); + sc.Forward(sepCount); + } + } else if (sc.Match('-', '-')) { + sc.SetState(SCE_LUA_COMMENTLINE); + if (sc.Match("--[")) { + sc.Forward(2); + sepCount = LongDelimCheck(sc); + if (sepCount > 0) { + nestLevel = 1; + sc.ChangeState(SCE_LUA_COMMENT); + sc.Forward(sepCount); + } + } else { + sc.Forward(); + } + } else if (sc.atLineStart && sc.Match('$')) { + sc.SetState(SCE_LUA_PREPROCESSOR); // Obsolete since Lua 4.0, but still in old code + } else if (setLuaOperator.Contains(sc.ch)) { + sc.SetState(SCE_LUA_OPERATOR); + } + } + } + + if (setWord.Contains(sc.chPrev)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_LUA_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_LUA_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_LUA_WORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_LUA_WORD4); + } else if (keywords5.InList(s)) { + sc.ChangeState(SCE_LUA_WORD5); + } else if (keywords6.InList(s)) { + sc.ChangeState(SCE_LUA_WORD6); + } else if (keywords7.InList(s)) { + sc.ChangeState(SCE_LUA_WORD7); + } else if (keywords8.InList(s)) { + sc.ChangeState(SCE_LUA_WORD8); + } + } + + sc.Complete(); +} + +static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[], + Accessor &styler) { + unsigned int lengthDoc = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + int styleNext = styler.StyleAt(startPos); + char s[10]; + + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (style == SCE_LUA_WORD) { + if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e' || ch == 'r' || ch == 'u') { + for (unsigned int j = 0; j < 8; j++) { + if (!iswordchar(styler[i + j])) { + break; + } + s[j] = styler[i + j]; + s[j + 1] = '\0'; + } + + if ((strcmp(s, "if") == 0) || (strcmp(s, "do") == 0) || (strcmp(s, "function") == 0) || (strcmp(s, "repeat") == 0)) { + levelCurrent++; + } + if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0) || (strcmp(s, "until") == 0)) { + levelCurrent--; + } + } + } else if (style == SCE_LUA_OPERATOR) { + if (ch == '{' || ch == '(') { + levelCurrent++; + } else if (ch == '}' || ch == ')') { + levelCurrent--; + } + } else if (style == SCE_LUA_LITERALSTRING || style == SCE_LUA_COMMENT) { + if (ch == '[') { + levelCurrent++; + } else if (ch == ']') { + levelCurrent--; + } + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) { + lev |= SC_FOLDLEVELWHITEFLAG; + } + if ((levelCurrent > levelPrev) && (visibleChars > 0)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) { + visibleChars++; + } + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const luaWordListDesc[] = { + "Keywords", + "Basic functions", + "String, (table) & math functions", + "(coroutines), I/O & system facilities", + "user1", + "user2", + "user3", + "user4", + 0 +}; + +LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc, luaWordListDesc); diff --git a/lexers/LexMMIXAL.cxx b/lexers/LexMMIXAL.cxx new file mode 100644 index 000000000..369929998 --- /dev/null +++ b/lexers/LexMMIXAL.cxx @@ -0,0 +1,186 @@ +// Scintilla source code edit control +/** @file LexMMIXAL.cxx + ** Lexer for MMIX Assembler Language. + ** Written by Christoph Hösler + ** For information about MMIX visit http://www-cs-faculty.stanford.edu/~knuth/mmix.html + **/ +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == ':' || ch == '_'); +} + +inline bool isMMIXALOperator(char ch) { + if (isascii(ch) && isalnum(ch)) + return false; + if (ch == '+' || ch == '-' || ch == '|' || ch == '^' || + ch == '*' || ch == '/' || ch == '/' || + ch == '%' || ch == '<' || ch == '>' || ch == '&' || + ch == '~' || ch == '$' || + ch == ',' || ch == '(' || ch == ')' || + ch == '[' || ch == ']') + return true; + return false; +} + +static void ColouriseMMIXALDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &opcodes = *keywordlists[0]; + WordList &special_register = *keywordlists[1]; + WordList &predef_symbols = *keywordlists[2]; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) + { + // No EOL continuation + if (sc.atLineStart) { + if (sc.ch == '@' && sc.chNext == 'i') { + sc.SetState(SCE_MMIXAL_INCLUDE); + } else { + sc.SetState(SCE_MMIXAL_LEADWS); + } + } + + // Check if first non whitespace character in line is alphanumeric + if (sc.state == SCE_MMIXAL_LEADWS && !isspace(sc.ch)) { // LEADWS + if(!IsAWordChar(sc.ch)) { + sc.SetState(SCE_MMIXAL_COMMENT); + } else { + if(sc.atLineStart) { + sc.SetState(SCE_MMIXAL_LABEL); + } else { + sc.SetState(SCE_MMIXAL_OPCODE_PRE); + } + } + } + + // Determine if the current state should terminate. + if (sc.state == SCE_MMIXAL_OPERATOR) { // OPERATOR + sc.SetState(SCE_MMIXAL_OPERANDS); + } else if (sc.state == SCE_MMIXAL_NUMBER) { // NUMBER + if (!isdigit(sc.ch)) { + if (IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + sc.ChangeState(SCE_MMIXAL_REF); + sc.SetState(SCE_MMIXAL_REF); + } else { + sc.SetState(SCE_MMIXAL_OPERANDS); + } + } + } else if (sc.state == SCE_MMIXAL_LABEL) { // LABEL + if (!IsAWordChar(sc.ch) ) { + sc.SetState(SCE_MMIXAL_OPCODE_PRE); + } + } else if (sc.state == SCE_MMIXAL_REF) { // REF + if (!IsAWordChar(sc.ch) ) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + if (*s == ':') { // ignore base prefix for match + for (size_t i = 0; i != sizeof(s); ++i) { + *(s+i) = *(s+i+1); + } + } + if (special_register.InList(s)) { + sc.ChangeState(SCE_MMIXAL_REGISTER); + } else if (predef_symbols.InList(s)) { + sc.ChangeState(SCE_MMIXAL_SYMBOL); + } + sc.SetState(SCE_MMIXAL_OPERANDS); + } + } else if (sc.state == SCE_MMIXAL_OPCODE_PRE) { // OPCODE_PRE + if (!isspace(sc.ch)) { + sc.SetState(SCE_MMIXAL_OPCODE); + } + } else if (sc.state == SCE_MMIXAL_OPCODE) { // OPCODE + if (!IsAWordChar(sc.ch) ) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + if (opcodes.InList(s)) { + sc.ChangeState(SCE_MMIXAL_OPCODE_VALID); + } else { + sc.ChangeState(SCE_MMIXAL_OPCODE_UNKNOWN); + } + sc.SetState(SCE_MMIXAL_OPCODE_POST); + } + } else if (sc.state == SCE_MMIXAL_STRING) { // STRING + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_MMIXAL_OPERANDS); + } else if (sc.atLineEnd) { + sc.ForwardSetState(SCE_MMIXAL_OPERANDS); + } + } else if (sc.state == SCE_MMIXAL_CHAR) { // CHAR + if (sc.ch == '\'') { + sc.ForwardSetState(SCE_MMIXAL_OPERANDS); + } else if (sc.atLineEnd) { + sc.ForwardSetState(SCE_MMIXAL_OPERANDS); + } + } else if (sc.state == SCE_MMIXAL_REGISTER) { // REGISTER + if (!isdigit(sc.ch)) { + sc.SetState(SCE_MMIXAL_OPERANDS); + } + } else if (sc.state == SCE_MMIXAL_HEX) { // HEX + if (!isxdigit(sc.ch)) { + sc.SetState(SCE_MMIXAL_OPERANDS); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_MMIXAL_OPCODE_POST || // OPCODE_POST + sc.state == SCE_MMIXAL_OPERANDS) { // OPERANDS + if (sc.state == SCE_MMIXAL_OPERANDS && isspace(sc.ch)) { + if (!sc.atLineEnd) { + sc.SetState(SCE_MMIXAL_COMMENT); + } + } else if (isdigit(sc.ch)) { + sc.SetState(SCE_MMIXAL_NUMBER); + } else if (IsAWordChar(sc.ch) || sc.Match('@')) { + sc.SetState(SCE_MMIXAL_REF); + } else if (sc.Match('\"')) { + sc.SetState(SCE_MMIXAL_STRING); + } else if (sc.Match('\'')) { + sc.SetState(SCE_MMIXAL_CHAR); + } else if (sc.Match('$')) { + sc.SetState(SCE_MMIXAL_REGISTER); + } else if (sc.Match('#')) { + sc.SetState(SCE_MMIXAL_HEX); + } else if (isMMIXALOperator(static_cast(sc.ch))) { + sc.SetState(SCE_MMIXAL_OPERATOR); + } + } + } + sc.Complete(); +} + +static const char * const MMIXALWordListDesc[] = { + "Operation Codes", + "Special Register", + "Predefined Symbols", + 0 +}; + +LexerModule lmMMIXAL(SCLEX_MMIXAL, ColouriseMMIXALDoc, "mmixal", 0, MMIXALWordListDesc); + diff --git a/lexers/LexMPT.cxx b/lexers/LexMPT.cxx new file mode 100644 index 000000000..a69fe5464 --- /dev/null +++ b/lexers/LexMPT.cxx @@ -0,0 +1,188 @@ +// Scintilla source code edit control +/** @file LexMPT.cxx + ** Lexer for MPT specific files. Based on LexOthers.cxx + ** LOT = the text log file created by the MPT application while running a test program + ** Other MPT specific files to be added later. + **/ +// Copyright 2003 by Marius Gheorghe +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include + +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static int GetLotLineState(std::string &line) { + if (line.length()) { + // Most of the time the first non-blank character in line determines that line's type + // Now finds the first non-blank character + unsigned i; // Declares counter here to make it persistent after the for loop + for (i = 0; i < line.length(); ++i) { + if (!(isascii(line[i]) && isspace(line[i]))) + break; + } + + // Checks if it was a blank line + if (i == line.length()) + return SCE_LOT_DEFAULT; + + switch (line[i]) { + case '*': // Fail measurement + return SCE_LOT_FAIL; + + case '+': // Header + case '|': // Header + return SCE_LOT_HEADER; + + case ':': // Set test limits + return SCE_LOT_SET; + + case '-': // Section break + return SCE_LOT_BREAK; + + default: // Any other line + // Checks for message at the end of lot file + if (line.find("PASSED") != std::string::npos) { + return SCE_LOT_PASS; + } + else if (line.find("FAILED") != std::string::npos) { + return SCE_LOT_FAIL; + } + else if (line.find("ABORTED") != std::string::npos) { + return SCE_LOT_ABORT; + } + else { + return i ? SCE_LOT_PASS : SCE_LOT_DEFAULT; + } + } + } + else { + return SCE_LOT_DEFAULT; + } +} + +static void ColourizeLotDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + styler.StartAt(startPos); + styler.StartSegment(startPos); + bool atLineStart = true;// Arms the 'at line start' flag + char chNext = styler.SafeGetCharAt(startPos); + std::string line(""); + line.reserve(256); // Lot lines are less than 256 chars long most of the time. This should avoid reallocations + + // Styles LOT document + unsigned int i; // Declared here because it's used after the for loop + for (i = startPos; i < startPos + length; ++i) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + line += ch; + atLineStart = false; + + // LOT files are only used on the Win32 platform, thus EOL == CR+LF + // Searches for the end of line + if (ch == '\r' && chNext == '\n') { + line += chNext; // Gets the '\n' + ++i; // Advances past the '\n' + chNext = styler.SafeGetCharAt(i + 1); // Gets character of next line + styler.ColourTo(i, GetLotLineState(line)); + line = ""; + atLineStart = true; // Arms flag for next line + } + } + + // Last line may not have a line ending + if (!atLineStart) { + styler.ColourTo(i - 1, GetLotLineState(line)); + } +} + +// Folds an MPT LOT file: the blocks that can be folded are: +// sections (headed by a set line) +// passes (contiguous pass results within a section) +// fails (contiguous fail results within a section) +static void FoldLotDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + bool foldCompact = styler.GetPropertyInt("fold.compact", 0) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + + char chNext = styler.SafeGetCharAt(startPos); + int style = SCE_LOT_DEFAULT; + int styleNext = styler.StyleAt(startPos); + int lev = SC_FOLDLEVELBASE; + + // Gets style of previous line if not at the beginning of the document + if (startPos > 1) + style = styler.StyleAt(startPos - 2); + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if (ch == '\r' && chNext == '\n') { + // TO DO: + // Should really get the state of the previous line from the styler + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 2); + + switch (style) { +/* + case SCE_LOT_SET: + lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; + break; +*/ + case SCE_LOT_FAIL: +/* + if (stylePrev != SCE_LOT_FAIL) + lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; + else + lev = SC_FOLDLEVELBASE + 1; +*/ + lev = SC_FOLDLEVELBASE; + break; + + default: + if (lineCurrent == 0 || stylePrev == SCE_LOT_FAIL) + lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; + else + lev = SC_FOLDLEVELBASE + 1; + + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + break; + } + + if (lev != styler.LevelAt(lineCurrent)) + styler.SetLevel(lineCurrent, lev); + + lineCurrent++; + visibleChars = 0; + } + + if (!isspacechar(ch)) + visibleChars++; + } + + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, lev | flagsNext); +} + +static const char * const emptyWordListDesc[] = { + 0 +}; + +LexerModule lmLot(SCLEX_LOT, ColourizeLotDoc, "lot", FoldLotDoc, emptyWordListDesc); diff --git a/lexers/LexMSSQL.cxx b/lexers/LexMSSQL.cxx new file mode 100644 index 000000000..4a3f3bed8 --- /dev/null +++ b/lexers/LexMSSQL.cxx @@ -0,0 +1,363 @@ +// Scintilla source code edit control +/** @file LexMSSQL.cxx + ** Lexer for MSSQL. + **/ +// By Filip Yaghob +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#define KW_MSSQL_STATEMENTS 0 +#define KW_MSSQL_DATA_TYPES 1 +#define KW_MSSQL_SYSTEM_TABLES 2 +#define KW_MSSQL_GLOBAL_VARIABLES 3 +#define KW_MSSQL_FUNCTIONS 4 +#define KW_MSSQL_STORED_PROCEDURES 5 +#define KW_MSSQL_OPERATORS 6 + +static bool isMSSQLOperator(char ch) { + if (isascii(ch) && isalnum(ch)) + return false; + // '.' left out as it is used to make up numbers + if (ch == '%' || ch == '^' || ch == '&' || ch == '*' || + ch == '-' || ch == '+' || ch == '=' || ch == '|' || + ch == '<' || ch == '>' || ch == '/' || + ch == '!' || ch == '~' || ch == '(' || ch == ')' || + ch == ',') + return true; + return false; +} + +static char classifyWordSQL(unsigned int start, + unsigned int end, + WordList *keywordlists[], + Accessor &styler, + unsigned int actualState, + unsigned int prevState) { + char s[256]; + bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.'); + + WordList &kwStatements = *keywordlists[KW_MSSQL_STATEMENTS]; + WordList &kwDataTypes = *keywordlists[KW_MSSQL_DATA_TYPES]; + WordList &kwSystemTables = *keywordlists[KW_MSSQL_SYSTEM_TABLES]; + WordList &kwGlobalVariables = *keywordlists[KW_MSSQL_GLOBAL_VARIABLES]; + WordList &kwFunctions = *keywordlists[KW_MSSQL_FUNCTIONS]; + WordList &kwStoredProcedures = *keywordlists[KW_MSSQL_STORED_PROCEDURES]; + WordList &kwOperators = *keywordlists[KW_MSSQL_OPERATORS]; + + for (unsigned int i = 0; i < end - start + 1 && i < 128; i++) { + s[i] = static_cast(tolower(styler[start + i])); + s[i + 1] = '\0'; + } + char chAttr = SCE_MSSQL_IDENTIFIER; + + if (actualState == SCE_MSSQL_GLOBAL_VARIABLE) { + + if (kwGlobalVariables.InList(&s[2])) + chAttr = SCE_MSSQL_GLOBAL_VARIABLE; + + } else if (wordIsNumber) { + chAttr = SCE_MSSQL_NUMBER; + + } else if (prevState == SCE_MSSQL_DEFAULT_PREF_DATATYPE) { + // Look first in datatypes + if (kwDataTypes.InList(s)) + chAttr = SCE_MSSQL_DATATYPE; + else if (kwOperators.InList(s)) + chAttr = SCE_MSSQL_OPERATOR; + else if (kwStatements.InList(s)) + chAttr = SCE_MSSQL_STATEMENT; + else if (kwSystemTables.InList(s)) + chAttr = SCE_MSSQL_SYSTABLE; + else if (kwFunctions.InList(s)) + chAttr = SCE_MSSQL_FUNCTION; + else if (kwStoredProcedures.InList(s)) + chAttr = SCE_MSSQL_STORED_PROCEDURE; + + } else { + if (kwOperators.InList(s)) + chAttr = SCE_MSSQL_OPERATOR; + else if (kwStatements.InList(s)) + chAttr = SCE_MSSQL_STATEMENT; + else if (kwSystemTables.InList(s)) + chAttr = SCE_MSSQL_SYSTABLE; + else if (kwFunctions.InList(s)) + chAttr = SCE_MSSQL_FUNCTION; + else if (kwStoredProcedures.InList(s)) + chAttr = SCE_MSSQL_STORED_PROCEDURE; + else if (kwDataTypes.InList(s)) + chAttr = SCE_MSSQL_DATATYPE; + } + + styler.ColourTo(end, chAttr); + + return chAttr; +} + +static void ColouriseMSSQLDoc(unsigned int startPos, int length, + int initStyle, WordList *keywordlists[], Accessor &styler) { + + + styler.StartAt(startPos); + + bool fold = styler.GetPropertyInt("fold") != 0; + int lineCurrent = styler.GetLine(startPos); + int spaceFlags = 0; + + int state = initStyle; + int prevState = initStyle; + char chPrev = ' '; + char chNext = styler[startPos]; + styler.StartSegment(startPos); + unsigned int lengthDoc = startPos + length; + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags); + int lev = indentCurrent; + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + // Only non whitespace lines can be headers + int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags); + if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + } + if (fold) { + styler.SetLevel(lineCurrent, lev); + } + } + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + chPrev = ' '; + i += 1; + continue; + } + + // When the last char isn't part of the state (have to deal with it too)... + if ( (state == SCE_MSSQL_IDENTIFIER) || + (state == SCE_MSSQL_STORED_PROCEDURE) || + (state == SCE_MSSQL_DATATYPE) || + //~ (state == SCE_MSSQL_COLUMN_NAME) || + (state == SCE_MSSQL_FUNCTION) || + //~ (state == SCE_MSSQL_GLOBAL_VARIABLE) || + (state == SCE_MSSQL_VARIABLE)) { + if (!iswordchar(ch)) { + int stateTmp; + + if ((state == SCE_MSSQL_VARIABLE) || (state == SCE_MSSQL_COLUMN_NAME)) { + styler.ColourTo(i - 1, state); + stateTmp = state; + } else + stateTmp = classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState); + + prevState = state; + + if (stateTmp == SCE_MSSQL_IDENTIFIER || stateTmp == SCE_MSSQL_VARIABLE) + state = SCE_MSSQL_DEFAULT_PREF_DATATYPE; + else + state = SCE_MSSQL_DEFAULT; + } + } else if (state == SCE_MSSQL_LINE_COMMENT) { + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, state); + prevState = state; + state = SCE_MSSQL_DEFAULT; + } + } else if (state == SCE_MSSQL_GLOBAL_VARIABLE) { + if ((ch != '@') && !iswordchar(ch)) { + classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState); + prevState = state; + state = SCE_MSSQL_DEFAULT; + } + } + + // If is the default or one of the above succeeded + if (state == SCE_MSSQL_DEFAULT || state == SCE_MSSQL_DEFAULT_PREF_DATATYPE) { + if (iswordstart(ch)) { + styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); + prevState = state; + state = SCE_MSSQL_IDENTIFIER; + } else if (ch == '/' && chNext == '*') { + styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); + prevState = state; + state = SCE_MSSQL_COMMENT; + } else if (ch == '-' && chNext == '-') { + styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); + prevState = state; + state = SCE_MSSQL_LINE_COMMENT; + } else if (ch == '\'') { + styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); + prevState = state; + state = SCE_MSSQL_STRING; + } else if (ch == '"') { + styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); + prevState = state; + state = SCE_MSSQL_COLUMN_NAME; + } else if (ch == '[') { + styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); + prevState = state; + state = SCE_MSSQL_COLUMN_NAME_2; + } else if (isMSSQLOperator(ch)) { + styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); + styler.ColourTo(i, SCE_MSSQL_OPERATOR); + //~ style = SCE_MSSQL_DEFAULT; + prevState = state; + state = SCE_MSSQL_DEFAULT; + } else if (ch == '@') { + styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); + prevState = state; + if (chNext == '@') { + state = SCE_MSSQL_GLOBAL_VARIABLE; +// i += 2; + } else + state = SCE_MSSQL_VARIABLE; + } + + + // When the last char is part of the state... + } else if (state == SCE_MSSQL_COMMENT) { + if (ch == '/' && chPrev == '*') { + if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_MSSQL_COMMENT) && + (styler.GetStartSegment() == startPos)))) { + styler.ColourTo(i, state); + //~ state = SCE_MSSQL_COMMENT; + prevState = state; + state = SCE_MSSQL_DEFAULT; + } + } + } else if (state == SCE_MSSQL_STRING) { + if (ch == '\'') { + if ( chNext == '\'' ) { + i++; + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + } else { + styler.ColourTo(i, state); + prevState = state; + state = SCE_MSSQL_DEFAULT; + //i++; + } + //ch = chNext; + //chNext = styler.SafeGetCharAt(i + 1); + } + } else if (state == SCE_MSSQL_COLUMN_NAME) { + if (ch == '"') { + if (chNext == '"') { + i++; + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + } else { + styler.ColourTo(i, state); + prevState = state; + state = SCE_MSSQL_DEFAULT_PREF_DATATYPE; + //i++; + } + } + } else if (state == SCE_MSSQL_COLUMN_NAME_2) { + if (ch == ']') { + styler.ColourTo(i, state); + prevState = state; + state = SCE_MSSQL_DEFAULT_PREF_DATATYPE; + //i++; + } + } + + chPrev = ch; + } + styler.ColourTo(lengthDoc - 1, state); +} + +static void FoldMSSQLDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + bool inComment = (styler.StyleAt(startPos-1) == SCE_MSSQL_COMMENT); + char s[10]; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styler.StyleAt(i); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + // Comment folding + if (foldComment) { + if (!inComment && (style == SCE_MSSQL_COMMENT)) + levelCurrent++; + else if (inComment && (style != SCE_MSSQL_COMMENT)) + levelCurrent--; + inComment = (style == SCE_MSSQL_COMMENT); + } + if (style == SCE_MSSQL_STATEMENT) { + // Folding between begin or case and end + if (ch == 'b' || ch == 'B' || ch == 'c' || ch == 'C' || ch == 'e' || ch == 'E') { + for (unsigned int j = 0; j < 5; j++) { + if (!iswordchar(styler[i + j])) { + break; + } + s[j] = static_cast(tolower(styler[i + j])); + s[j + 1] = '\0'; + } + if ((strcmp(s, "begin") == 0) || (strcmp(s, "case") == 0)) { + levelCurrent++; + } + if (strcmp(s, "end") == 0) { + levelCurrent--; + } + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const sqlWordListDesc[] = { + "Statements", + "Data Types", + "System tables", + "Global variables", + "Functions", + "System Stored Procedures", + "Operators", + 0, +}; + +LexerModule lmMSSQL(SCLEX_MSSQL, ColouriseMSSQLDoc, "mssql", FoldMSSQLDoc, sqlWordListDesc); diff --git a/lexers/LexMagik.cxx b/lexers/LexMagik.cxx new file mode 100644 index 000000000..c6f6585b3 --- /dev/null +++ b/lexers/LexMagik.cxx @@ -0,0 +1,445 @@ +// Scintilla source code edit control +/** + * @file LexMagik.cxx + * Lexer for GE(r) Smallworld(tm) MagikSF + */ +// Copyright 1998-2005 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +/** + * Is it a core character (C isalpha(), exclamation and question mark) + * + * \param ch The character + * \return True if ch is a character, False otherwise + */ +static inline bool IsAlphaCore(int ch) { + return (isalpha(ch) || ch == '!' || ch == '?'); +} + +/** + * Is it a character (IsAlphaCore() and underscore) + * + * \param ch The character + * \return True if ch is a character, False otherwise + */ +static inline bool IsAlpha(int ch) { + return (IsAlphaCore(ch) || ch == '_'); +} + +/** + * Is it a symbolic character (IsAlpha() and colon) + * + * \param ch The character + * \return True if ch is a character, False otherwise + */ +static inline bool IsAlphaSym(int ch) { + return (IsAlpha(ch) || ch == ':'); +} + +/** + * Is it a numerical character (IsAlpha() and 0 - 9) + * + * \param ch The character + * \return True if ch is a character, False otherwise + */ +static inline bool IsAlNum(int ch) { + return ((ch >= '0' && ch <= '9') || IsAlpha(ch)); +} + +/** + * Is it a symbolic numerical character (IsAlNum() and colon) + * + * \param ch The character + * \return True if ch is a character, False otherwise + */ +static inline bool IsAlNumSym(int ch) { + return (IsAlNum(ch) || ch == ':'); +} + +/** + * The lexer function + * + * \param startPos Where to start scanning + * \param length Where to scan to + * \param initStyle The style at the initial point, not used in this folder + * \param keywordslists The keywordslists, currently, number 5 is used + * \param styler The styler + */ +static void ColouriseMagikDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + styler.StartAt(startPos); + + WordList &keywords = *keywordlists[0]; + WordList &pragmatics = *keywordlists[1]; + WordList &containers = *keywordlists[2]; + WordList &flow = *keywordlists[3]; + WordList &characters = *keywordlists[4]; + + StyleContext sc(startPos, length, initStyle, styler); + + + for (; sc.More(); sc.Forward()) { + + repeat: + + if(sc.ch == '#') { + if (sc.chNext == '#') sc.SetState(SCE_MAGIK_HYPER_COMMENT); + else sc.SetState(SCE_MAGIK_COMMENT); + for(; sc.More() && !(sc.atLineEnd); sc.Forward()); + sc.SetState(SCE_MAGIK_DEFAULT); + goto repeat; + } + + if(sc.ch == '"') { + sc.SetState(SCE_MAGIK_STRING); + + if(sc.More()) + { + sc.Forward(); + for(; sc.More() && sc.ch != '"'; sc.Forward()); + } + + sc.ForwardSetState(SCE_MAGIK_DEFAULT); + goto repeat; + } + + // The default state + if(sc.state == SCE_MAGIK_DEFAULT) { + + // A certain keyword has been detected + if (sc.ch == '_' && ( + sc.currentPos == 0 || !IsAlNum(sc.chPrev))) { + char keyword[50]; + memset(keyword, '\0', 50); + + for( + int scanPosition = 0; + scanPosition < 50; + scanPosition++) { + char keywordChar = static_cast( + tolower(styler.SafeGetCharAt( + scanPosition + + static_cast(sc.currentPos+1), ' '))); + if(IsAlpha(keywordChar)) { + keyword[scanPosition] = keywordChar; + } else { + break; + } + } + + // It is a pragma + if(pragmatics.InList(keyword)) { + sc.SetState(SCE_MAGIK_PRAGMA); + } + + // it is a normal keyword like _local, _self, etc. + else if(keywords.InList(keyword)) { + sc.SetState(SCE_MAGIK_KEYWORD); + } + + // It is a container keyword, such as _method, _proc, etc. + else if(containers.InList(keyword)) { + sc.SetState(SCE_MAGIK_CONTAINER); + } + + // It is a flow keyword, such as _for, _if, _try, etc. + else if(flow.InList(keyword)) { + sc.SetState(SCE_MAGIK_FLOW); + } + + // Interpret as unknown keyword + else { + sc.SetState(SCE_MAGIK_UNKNOWN_KEYWORD); + } + } + + // Symbolic expression + else if(sc.ch == ':' && !IsAlNum(sc.chPrev)) { + sc.SetState(SCE_MAGIK_SYMBOL); + bool firstTrip = true; + for(sc.Forward(); sc.More(); sc.Forward()) { + if(firstTrip && IsAlphaSym(sc.ch)); + else if(!firstTrip && IsAlNumSym(sc.ch)); + else if(sc.ch == '|') { + for(sc.Forward(); + sc.More() && sc.ch != '|'; + sc.Forward()); + } + else break; + + firstTrip = false; + } + sc.SetState(SCE_MAGIK_DEFAULT); + goto repeat; + } + + // Identifier (label) expression + else if(sc.ch == '@') { + sc.SetState(SCE_MAGIK_IDENTIFIER); + bool firstTrip = true; + for(sc.Forward(); sc.More(); sc.Forward()) { + if(firstTrip && IsAlphaCore(sc.ch)) { + firstTrip = false; + } + else if(!firstTrip && IsAlpha(sc.ch)); + else break; + } + sc.SetState(SCE_MAGIK_DEFAULT); + goto repeat; + } + + // Start of a character + else if(sc.ch == '%') { + sc.SetState(SCE_MAGIK_CHARACTER); + sc.Forward(); + char keyword[50]; + memset(keyword, '\0', 50); + + for( + int scanPosition = 0; + scanPosition < 50; + scanPosition++) { + char keywordChar = static_cast( + tolower(styler.SafeGetCharAt( + scanPosition + + static_cast(sc.currentPos), ' '))); + if(IsAlpha(keywordChar)) { + keyword[scanPosition] = keywordChar; + } else { + break; + } + } + + if(characters.InList(keyword)) { + sc.Forward(strlen(keyword)); + } else { + sc.Forward(); + } + + sc.SetState(SCE_MAGIK_DEFAULT); + goto repeat; + } + + // Operators + else if( + sc.ch == '>' || + sc.ch == '<' || + sc.ch == '.' || + sc.ch == ',' || + sc.ch == '+' || + sc.ch == '-' || + sc.ch == '/' || + sc.ch == '*' || + sc.ch == '~' || + sc.ch == '$' || + sc.ch == '=') { + sc.SetState(SCE_MAGIK_OPERATOR); + } + + // Braces + else if(sc.ch == '(' || sc.ch == ')') { + sc.SetState(SCE_MAGIK_BRACE_BLOCK); + } + + // Brackets + else if(sc.ch == '{' || sc.ch == '}') { + sc.SetState(SCE_MAGIK_BRACKET_BLOCK); + } + + // Square Brackets + else if(sc.ch == '[' || sc.ch == ']') { + sc.SetState(SCE_MAGIK_SQBRACKET_BLOCK); + } + + + } + + // It is an operator + else if( + sc.state == SCE_MAGIK_OPERATOR || + sc.state == SCE_MAGIK_BRACE_BLOCK || + sc.state == SCE_MAGIK_BRACKET_BLOCK || + sc.state == SCE_MAGIK_SQBRACKET_BLOCK) { + sc.SetState(SCE_MAGIK_DEFAULT); + goto repeat; + } + + // It is the pragma state + else if(sc.state == SCE_MAGIK_PRAGMA) { + if(!IsAlpha(sc.ch)) { + sc.SetState(SCE_MAGIK_DEFAULT); + goto repeat; + } + } + + // It is the keyword state + else if( + sc.state == SCE_MAGIK_KEYWORD || + sc.state == SCE_MAGIK_CONTAINER || + sc.state == SCE_MAGIK_FLOW || + sc.state == SCE_MAGIK_UNKNOWN_KEYWORD) { + if(!IsAlpha(sc.ch)) { + sc.SetState(SCE_MAGIK_DEFAULT); + goto repeat; + } + } + } + + sc.Complete(); +} + +/** + * The word list description + */ +static const char * const magikWordListDesc[] = { + "Accessors (local, global, self, super, thisthread)", + "Pragmatic (pragma, private)", + "Containers (method, block, proc)", + "Flow (if, then, elif, else)", + "Characters (space, tab, newline, return)", + "Fold Containers (method, proc, block, if, loop)", + 0}; + +/** + * This function detects keywords which are able to have a body. Note that it + * uses the Fold Containers word description, not the containers description. It + * only works when the style at that particular position is set on Containers + * or Flow (number 3 or 4). + * + * \param keywordslist The list of keywords that are scanned, they should only + * contain the start keywords, not the end keywords + * \param The actual keyword + * \return 1 if it is a folding start-keyword, -1 if it is a folding end-keyword + * 0 otherwise + */ +static inline int IsFoldingContainer(WordList &keywordslist, char * keyword) { + if( + strlen(keyword) > 3 && + keyword[0] == 'e' && keyword[1] == 'n' && keyword[2] == 'd') { + if (keywordslist.InList(keyword + 3)) { + return -1; + } + + } else { + if(keywordslist.InList(keyword)) { + return 1; + } + } + + return 0; +} + +/** + * The folding function + * + * \param startPos Where to start scanning + * \param length Where to scan to + * \param keywordslists The keywordslists, currently, number 5 is used + * \param styler The styler + */ +static void FoldMagikDoc(unsigned int startPos, int length, int, + WordList *keywordslists[], Accessor &styler) { + + bool compact = styler.GetPropertyInt("fold.compact") != 0; + + WordList &foldingElements = *keywordslists[5]; + int endPos = startPos + length; + int line = styler.GetLine(startPos); + int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK; + int flags = styler.LevelAt(line) & ~SC_FOLDLEVELNUMBERMASK; + + for( + int currentPos = startPos; + currentPos < endPos; + currentPos++) { + char currentState = styler.StyleAt(currentPos); + char c = styler.SafeGetCharAt(currentPos, ' '); + int prevLine = styler.GetLine(currentPos - 1); + line = styler.GetLine(currentPos); + + // Default situation + if(prevLine < line) { + styler.SetLevel(line, (level|flags) & ~SC_FOLDLEVELHEADERFLAG); + flags = styler.LevelAt(line) & ~SC_FOLDLEVELNUMBERMASK; + } + + if( + ( + currentState == SCE_MAGIK_CONTAINER || + currentState == SCE_MAGIK_FLOW + ) && + c == '_') { + + char keyword[50]; + memset(keyword, '\0', 50); + + for( + int scanPosition = 0; + scanPosition < 50; + scanPosition++) { + char keywordChar = static_cast( + tolower(styler.SafeGetCharAt( + scanPosition + + currentPos + 1, ' '))); + if(IsAlpha(keywordChar)) { + keyword[scanPosition] = keywordChar; + } else { + break; + } + } + + if(IsFoldingContainer(foldingElements, keyword) > 0) { + styler.SetLevel( + line, + styler.LevelAt(line) | SC_FOLDLEVELHEADERFLAG); + level++; + } else if(IsFoldingContainer(foldingElements, keyword) < 0) { + styler.SetLevel(line, styler.LevelAt(line)); + level--; + } + } + + if( + compact && ( + currentState == SCE_MAGIK_BRACE_BLOCK || + currentState == SCE_MAGIK_BRACKET_BLOCK || + currentState == SCE_MAGIK_SQBRACKET_BLOCK)) { + if(c == '{' || c == '[' || c == '(') { + styler.SetLevel( + line, + styler.LevelAt(line) | SC_FOLDLEVELHEADERFLAG); + level++; + } else if(c == '}' || c == ']' || c == ')') { + styler.SetLevel(line, styler.LevelAt(line)); + level--; + } + } + } + +} + +/** + * Injecting the module + */ +LexerModule lmMagikSF( + SCLEX_MAGIK, ColouriseMagikDoc, "magiksf", FoldMagikDoc, magikWordListDesc); + diff --git a/lexers/LexMarkdown.cxx b/lexers/LexMarkdown.cxx new file mode 100644 index 000000000..f7fc48f40 --- /dev/null +++ b/lexers/LexMarkdown.cxx @@ -0,0 +1,412 @@ +/****************************************************************** + * LexMarkdown.cxx + * + * A simple Markdown lexer for scintilla. + * + * Includes highlighting for some extra features from the + * Pandoc implementation; strikeout, using '#.' as a default + * ordered list item marker, and delimited code blocks. + * + * Limitations: + * + * Standard indented code blocks are not highlighted at all, + * as it would conflict with other indentation schemes. Use + * delimited code blocks for blanket highlighting of an + * entire code block. Embedded HTML is not highlighted either. + * Blanket HTML highlighting has issues, because some Markdown + * implementations allow Markdown markup inside of the HTML. Also, + * there is a following blank line issue that can't be ignored, + * explained in the next paragraph. Embedded HTML and code + * blocks would be better supported with language specific + * highlighting. + * + * The highlighting aims to accurately reflect correct syntax, + * but a few restrictions are relaxed. Delimited code blocks are + * highlighted, even if the line following the code block is not blank. + * Requiring a blank line after a block, breaks the highlighting + * in certain cases, because of the way Scintilla ends up calling + * the lexer. + * + * Written by Jon Strait - jstrait@moonloop.net + * + * The License.txt file describes the conditions under which this + * software may be distributed. + * + *****************************************************************/ + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsNewline(const int ch) { + return (ch == '\n' || ch == '\r'); +} + +// True if can follow ch down to the end with possibly trailing whitespace +static bool FollowToLineEnd(const int ch, const int state, const unsigned int endPos, StyleContext &sc) { + unsigned int i = 0; + while (sc.GetRelative(++i) == ch) + ; + // Skip over whitespace + while (IsASpaceOrTab(sc.GetRelative(i)) && sc.currentPos + i < endPos) + ++i; + if (IsNewline(sc.GetRelative(i)) || sc.currentPos + i == endPos) { + sc.Forward(i); + sc.ChangeState(state); + sc.SetState(SCE_MARKDOWN_LINE_BEGIN); + return true; + } + else return false; +} + +// Set the state on text section from current to length characters, +// then set the rest until the newline to default, except for any characters matching token +static void SetStateAndZoom(const int state, const int length, const int token, StyleContext &sc) { + sc.SetState(state); + sc.Forward(length); + sc.SetState(SCE_MARKDOWN_DEFAULT); + sc.Forward(); + bool started = false; + while (sc.More() && !IsNewline(sc.ch)) { + if (sc.ch == token && !started) { + sc.SetState(state); + started = true; + } + else if (sc.ch != token) { + sc.SetState(SCE_MARKDOWN_DEFAULT); + started = false; + } + sc.Forward(); + } + sc.SetState(SCE_MARKDOWN_LINE_BEGIN); +} + +// Does the previous line have more than spaces and tabs? +static bool HasPrevLineContent(StyleContext &sc) { + int i = 0; + // Go back to the previous newline + while ((--i + sc.currentPos) && !IsNewline(sc.GetRelative(i))) + ; + while (--i + sc.currentPos) { + if (IsNewline(sc.GetRelative(i))) + break; + if (!IsASpaceOrTab(sc.GetRelative(i))) + return true; + } + return false; +} + +static bool IsValidHrule(const unsigned int endPos, StyleContext &sc) { + int c, count = 1; + unsigned int i = 0; + while (++i) { + c = sc.GetRelative(i); + if (c == sc.ch) + ++count; + // hit a terminating character + else if (!IsASpaceOrTab(c) || sc.currentPos + i == endPos) { + // Are we a valid HRULE + if ((IsNewline(c) || sc.currentPos + i == endPos) && + count >= 3 && !HasPrevLineContent(sc)) { + sc.SetState(SCE_MARKDOWN_HRULE); + sc.Forward(i); + sc.SetState(SCE_MARKDOWN_LINE_BEGIN); + return true; + } + else { + sc.SetState(SCE_MARKDOWN_DEFAULT); + return false; + } + } + } + return false; +} + +static void ColorizeMarkdownDoc(unsigned int startPos, int length, int initStyle, + WordList **, Accessor &styler) { + unsigned int endPos = startPos + length; + int precharCount = 0; + // Don't advance on a new loop iteration and retry at the same position. + // Useful in the corner case of having to start at the beginning file position + // in the default state. + bool freezeCursor = false; + + StyleContext sc(startPos, length, initStyle, styler); + + while (sc.More()) { + // Skip past escaped characters + if (sc.ch == '\\') { + sc.Forward(); + continue; + } + + // A blockquotes resets the line semantics + if (sc.state == SCE_MARKDOWN_BLOCKQUOTE) + sc.SetState(SCE_MARKDOWN_LINE_BEGIN); + + // Conditional state-based actions + if (sc.state == SCE_MARKDOWN_CODE2) { + if (sc.Match("``") && sc.GetRelative(-2) != ' ') { + sc.Forward(2); + sc.SetState(SCE_MARKDOWN_DEFAULT); + } + } + else if (sc.state == SCE_MARKDOWN_CODE) { + if (sc.ch == '`' && sc.chPrev != ' ') + sc.ForwardSetState(SCE_MARKDOWN_DEFAULT); + } + /* De-activated because it gets in the way of other valid indentation + * schemes, for example multiple paragraphs inside a list item. + // Code block + else if (sc.state == SCE_MARKDOWN_CODEBK) { + bool d = true; + if (IsNewline(sc.ch)) { + if (sc.chNext != '\t') { + for (int c = 1; c < 5; ++c) { + if (sc.GetRelative(c) != ' ') + d = false; + } + } + } + else if (sc.atLineStart) { + if (sc.ch != '\t' ) { + for (int i = 0; i < 4; ++i) { + if (sc.GetRelative(i) != ' ') + d = false; + } + } + } + if (!d) + sc.SetState(SCE_MARKDOWN_LINE_BEGIN); + } + */ + // Strong + else if (sc.state == SCE_MARKDOWN_STRONG1) { + if (sc.Match("**") && sc.chPrev != ' ') { + sc.Forward(2); + sc.SetState(SCE_MARKDOWN_DEFAULT); + } + } + else if (sc.state == SCE_MARKDOWN_STRONG2) { + if (sc.Match("__") && sc.chPrev != ' ') { + sc.Forward(2); + sc.SetState(SCE_MARKDOWN_DEFAULT); + } + } + // Emphasis + else if (sc.state == SCE_MARKDOWN_EM1) { + if (sc.ch == '*' && sc.chPrev != ' ') + sc.ForwardSetState(SCE_MARKDOWN_DEFAULT); + } + else if (sc.state == SCE_MARKDOWN_EM2) { + if (sc.ch == '_' && sc.chPrev != ' ') + sc.ForwardSetState(SCE_MARKDOWN_DEFAULT); + } + else if (sc.state == SCE_MARKDOWN_CODEBK) { + if (sc.atLineStart && sc.Match("~~~")) { + int i = 1; + while (!IsNewline(sc.GetRelative(i)) && sc.currentPos + i < endPos) + i++; + sc.Forward(i); + sc.SetState(SCE_MARKDOWN_DEFAULT); + } + } + else if (sc.state == SCE_MARKDOWN_STRIKEOUT) { + if (sc.Match("~~") && sc.chPrev != ' ') { + sc.Forward(2); + sc.SetState(SCE_MARKDOWN_DEFAULT); + } + } + else if (sc.state == SCE_MARKDOWN_LINE_BEGIN) { + // Header + if (sc.Match("######")) + SetStateAndZoom(SCE_MARKDOWN_HEADER6, 6, '#', sc); + else if (sc.Match("#####")) + SetStateAndZoom(SCE_MARKDOWN_HEADER5, 5, '#', sc); + else if (sc.Match("####")) + SetStateAndZoom(SCE_MARKDOWN_HEADER4, 4, '#', sc); + else if (sc.Match("###")) + SetStateAndZoom(SCE_MARKDOWN_HEADER3, 3, '#', sc); + else if (sc.Match("##")) + SetStateAndZoom(SCE_MARKDOWN_HEADER2, 2, '#', sc); + else if (sc.Match("#")) { + // Catch the special case of an unordered list + if (sc.chNext == '.' && IsASpaceOrTab(sc.GetRelative(2))) { + precharCount = 0; + sc.SetState(SCE_MARKDOWN_PRECHAR); + } + else + SetStateAndZoom(SCE_MARKDOWN_HEADER1, 1, '#', sc); + } + // Code block + else if (sc.Match("~~~")) { + if (!HasPrevLineContent(sc)) + sc.SetState(SCE_MARKDOWN_CODEBK); + else + sc.SetState(SCE_MARKDOWN_DEFAULT); + } + else if (sc.ch == '=') { + if (HasPrevLineContent(sc) && FollowToLineEnd('=', SCE_MARKDOWN_HEADER1, endPos, sc)) + ; + else + sc.SetState(SCE_MARKDOWN_DEFAULT); + } + else if (sc.ch == '-') { + if (HasPrevLineContent(sc) && FollowToLineEnd('-', SCE_MARKDOWN_HEADER2, endPos, sc)) + ; + else { + precharCount = 0; + sc.SetState(SCE_MARKDOWN_PRECHAR); + } + } + else if (IsNewline(sc.ch)) + sc.SetState(SCE_MARKDOWN_LINE_BEGIN); + else { + precharCount = 0; + sc.SetState(SCE_MARKDOWN_PRECHAR); + } + } + + // The header lasts until the newline + else if (sc.state == SCE_MARKDOWN_HEADER1 || sc.state == SCE_MARKDOWN_HEADER2 || + sc.state == SCE_MARKDOWN_HEADER3 || sc.state == SCE_MARKDOWN_HEADER4 || + sc.state == SCE_MARKDOWN_HEADER5 || sc.state == SCE_MARKDOWN_HEADER6) { + if (IsNewline(sc.ch)) + sc.SetState(SCE_MARKDOWN_LINE_BEGIN); + } + + // New state only within the initial whitespace + if (sc.state == SCE_MARKDOWN_PRECHAR) { + // Blockquote + if (sc.ch == '>' && precharCount < 5) + sc.SetState(SCE_MARKDOWN_BLOCKQUOTE); + /* + // Begin of code block + else if (!HasPrevLineContent(sc) && (sc.chPrev == '\t' || precharCount >= 4)) + sc.SetState(SCE_MARKDOWN_CODEBK); + */ + // HRule - Total of three or more hyphens, asterisks, or underscores + // on a line by themselves + else if ((sc.ch == '-' || sc.ch == '*' || sc.ch == '_') && IsValidHrule(endPos, sc)) + ; + // Unordered list + else if ((sc.ch == '-' || sc.ch == '*' || sc.ch == '+') && IsASpaceOrTab(sc.chNext)) { + sc.SetState(SCE_MARKDOWN_ULIST_ITEM); + sc.ForwardSetState(SCE_MARKDOWN_DEFAULT); + } + // Ordered list + else if (IsADigit(sc.ch)) { + int digitCount = 0; + while (IsADigit(sc.GetRelative(++digitCount))) + ; + if (sc.GetRelative(digitCount) == '.' && + IsASpaceOrTab(sc.GetRelative(digitCount + 1))) { + sc.SetState(SCE_MARKDOWN_OLIST_ITEM); + sc.Forward(digitCount + 1); + sc.SetState(SCE_MARKDOWN_DEFAULT); + } + } + // Alternate Ordered list + else if (sc.ch == '#' && sc.chNext == '.' && IsASpaceOrTab(sc.GetRelative(2))) { + sc.SetState(SCE_MARKDOWN_OLIST_ITEM); + sc.Forward(2); + sc.SetState(SCE_MARKDOWN_DEFAULT); + } + else if (sc.ch != ' ' || precharCount > 2) + sc.SetState(SCE_MARKDOWN_DEFAULT); + else + ++precharCount; + } + + // New state anywhere in doc + if (sc.state == SCE_MARKDOWN_DEFAULT) { + if (sc.atLineStart && sc.ch == '#') { + sc.SetState(SCE_MARKDOWN_LINE_BEGIN); + freezeCursor = true; + } + // Links and Images + if (sc.Match("![") || sc.ch == '[') { + int i = 0, j = 0, k = 0; + int len = endPos - sc.currentPos; + while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\')) + ; + if (sc.GetRelative(i) == ']') { + j = i; + if (sc.GetRelative(++i) == '(') { + while (i < len && (sc.GetRelative(++i) != ')' || sc.GetRelative(i - 1) == '\\')) + ; + if (sc.GetRelative(i) == ')') + k = i; + } + else if (sc.GetRelative(i) == '[' || sc.GetRelative(++i) == '[') { + while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\')) + ; + if (sc.GetRelative(i) == ']') + k = i; + } + } + // At least a link text + if (j) { + sc.SetState(SCE_MARKDOWN_LINK); + sc.Forward(j); + // Also has a URL or reference portion + if (k) + sc.Forward(k - j); + sc.ForwardSetState(SCE_MARKDOWN_DEFAULT); + } + } + // Code - also a special case for alternate inside spacing + if (sc.Match("``") && sc.GetRelative(3) != ' ') { + sc.SetState(SCE_MARKDOWN_CODE2); + sc.Forward(); + } + else if (sc.ch == '`' && sc.chNext != ' ') { + sc.SetState(SCE_MARKDOWN_CODE); + } + // Strong + else if (sc.Match("**") && sc.GetRelative(2) != ' ') { + sc.SetState(SCE_MARKDOWN_STRONG1); + sc.Forward(); + } + else if (sc.Match("__") && sc.GetRelative(2) != ' ') { + sc.SetState(SCE_MARKDOWN_STRONG2); + sc.Forward(); + } + // Emphasis + else if (sc.ch == '*' && sc.chNext != ' ') + sc.SetState(SCE_MARKDOWN_EM1); + else if (sc.ch == '_' && sc.chNext != ' ') + sc.SetState(SCE_MARKDOWN_EM2); + // Strikeout + else if (sc.Match("~~") && sc.GetRelative(2) != ' ') { + sc.SetState(SCE_MARKDOWN_STRIKEOUT); + sc.Forward(); + } + // Beginning of line + else if (IsNewline(sc.ch)) + sc.SetState(SCE_MARKDOWN_LINE_BEGIN); + } + // Advance if not holding back the cursor for this iteration. + if (!freezeCursor) + sc.Forward(); + freezeCursor = false; + } + sc.Complete(); +} + +LexerModule lmMarkdown(SCLEX_MARKDOWN, ColorizeMarkdownDoc, "markdown"); diff --git a/lexers/LexMatlab.cxx b/lexers/LexMatlab.cxx new file mode 100644 index 000000000..4e467bd2f --- /dev/null +++ b/lexers/LexMatlab.cxx @@ -0,0 +1,236 @@ +// Scintilla source code edit control +/** @file LexMatlab.cxx + ** Lexer for Matlab. + ** Written by José Fonseca + ** + ** Changes by Christoph Dalitz 2003/12/04: + ** - added support for Octave + ** - Strings can now be included both in single or double quotes + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static bool IsMatlabCommentChar(int c) { + return (c == '%') ; +} + +static bool IsOctaveCommentChar(int c) { + return (c == '%' || c == '#') ; +} + +static bool IsMatlabComment(Accessor &styler, int pos, int len) { + return len > 0 && IsMatlabCommentChar(styler[pos]) ; +} + +static bool IsOctaveComment(Accessor &styler, int pos, int len) { + return len > 0 && IsOctaveCommentChar(styler[pos]) ; +} + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static void ColouriseMatlabOctaveDoc( + unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler, + bool (*IsCommentChar)(int)) { + + WordList &keywords = *keywordlists[0]; + + styler.StartAt(startPos); + + bool transpose = false; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.state == SCE_MATLAB_OPERATOR) { + if (sc.chPrev == '.') { + if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' || sc.ch == '^') { + sc.ForwardSetState(SCE_MATLAB_DEFAULT); + transpose = false; + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_MATLAB_DEFAULT); + transpose = true; + } else { + sc.SetState(SCE_MATLAB_DEFAULT); + } + } else { + sc.SetState(SCE_MATLAB_DEFAULT); + } + } else if (sc.state == SCE_MATLAB_KEYWORD) { + if (!isalnum(sc.ch) && sc.ch != '_') { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.SetState(SCE_MATLAB_DEFAULT); + transpose = false; + } else { + sc.ChangeState(SCE_MATLAB_IDENTIFIER); + sc.SetState(SCE_MATLAB_DEFAULT); + transpose = true; + } + } + } else if (sc.state == SCE_MATLAB_NUMBER) { + if (!isdigit(sc.ch) && sc.ch != '.' + && !(sc.ch == 'e' || sc.ch == 'E') + && !((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E'))) { + sc.SetState(SCE_MATLAB_DEFAULT); + transpose = true; + } + } else if (sc.state == SCE_MATLAB_STRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_MATLAB_DEFAULT); + } + } else if (sc.state == SCE_MATLAB_DOUBLEQUOTESTRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_MATLAB_DEFAULT); + } + } else if (sc.state == SCE_MATLAB_COMMENT || sc.state == SCE_MATLAB_COMMAND) { + if (sc.atLineEnd) { + sc.SetState(SCE_MATLAB_DEFAULT); + transpose = false; + } + } + + if (sc.state == SCE_MATLAB_DEFAULT) { + if (IsCommentChar(sc.ch)) { + sc.SetState(SCE_MATLAB_COMMENT); + } else if (sc.ch == '!' && sc.chNext != '=' ) { + sc.SetState(SCE_MATLAB_COMMAND); + } else if (sc.ch == '\'') { + if (transpose) { + sc.SetState(SCE_MATLAB_OPERATOR); + } else { + sc.SetState(SCE_MATLAB_STRING); + } + } else if (sc.ch == '"') { + sc.SetState(SCE_MATLAB_DOUBLEQUOTESTRING); + } else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) { + sc.SetState(SCE_MATLAB_NUMBER); + } else if (isalpha(sc.ch)) { + sc.SetState(SCE_MATLAB_KEYWORD); + } else if (isoperator(static_cast(sc.ch)) || sc.ch == '@' || sc.ch == '\\') { + if (sc.ch == ')' || sc.ch == ']') { + transpose = true; + } else { + transpose = false; + } + sc.SetState(SCE_MATLAB_OPERATOR); + } else { + transpose = false; + } + } + } + sc.Complete(); +} + +static void ColouriseMatlabDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + ColouriseMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsMatlabCommentChar); +} + +static void ColouriseOctaveDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + ColouriseMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsOctaveCommentChar); +} + +static void FoldMatlabOctaveDoc(unsigned int startPos, int length, int, + WordList *[], Accessor &styler, + bool (*IsComment)(Accessor&, int, int)) { + + int endPos = startPos + length; + + // Backtrack to previous line in case need to fix its fold status + int lineCurrent = styler.GetLine(startPos); + if (startPos > 0) { + if (lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + } + int spaceFlags = 0; + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsComment); + char chNext = styler[startPos]; + for (int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { + int lev = indentCurrent; + int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsComment); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + // Only non whitespace lines can be headers + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { + // Line after is blank so check the next - maybe should continue further? + int spaceFlags2 = 0; + int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsComment); + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + } + } + indentCurrent = indentNext; + styler.SetLevel(lineCurrent, lev); + lineCurrent++; + } + } +} + +static void FoldMatlabDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + FoldMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsMatlabComment); +} + +static void FoldOctaveDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + FoldMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsOctaveComment); +} + +static const char * const matlabWordListDesc[] = { + "Keywords", + 0 +}; + +static const char * const octaveWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmMatlab(SCLEX_MATLAB, ColouriseMatlabDoc, "matlab", FoldMatlabDoc, matlabWordListDesc); + +LexerModule lmOctave(SCLEX_OCTAVE, ColouriseOctaveDoc, "octave", FoldOctaveDoc, octaveWordListDesc); diff --git a/lexers/LexMetapost.cxx b/lexers/LexMetapost.cxx new file mode 100644 index 000000000..6afc9d826 --- /dev/null +++ b/lexers/LexMetapost.cxx @@ -0,0 +1,399 @@ +// Scintilla source code edit control + +// File: LexMetapost.cxx - general context conformant metapost coloring scheme +// Author: Hans Hagen - PRAGMA ADE - Hasselt NL - www.pragma-ade.com +// Version: September 28, 2003 +// Modified by instanton: July 10, 2007 +// Folding based on keywordlists[] + +// Copyright: 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +// This lexer is derived from the one written for the texwork environment (1999++) which in +// turn is inspired on texedit (1991++) which finds its roots in wdt (1986). + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "StyleContext.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// val SCE_METAPOST_DEFAULT = 0 +// val SCE_METAPOST_SPECIAL = 1 +// val SCE_METAPOST_GROUP = 2 +// val SCE_METAPOST_SYMBOL = 3 +// val SCE_METAPOST_COMMAND = 4 +// val SCE_METAPOST_TEXT = 5 + +// Definitions in SciTEGlobal.properties: +// +// Metapost Highlighting +// +// # Default +// style.metapost.0=fore:#7F7F00 +// # Special +// style.metapost.1=fore:#007F7F +// # Group +// style.metapost.2=fore:#880000 +// # Symbol +// style.metapost.3=fore:#7F7F00 +// # Command +// style.metapost.4=fore:#008800 +// # Text +// style.metapost.5=fore:#000000 + +// lexer.tex.comment.process=0 + +// Auxiliary functions: + +static inline bool endOfLine(Accessor &styler, unsigned int i) { + return + (styler[i] == '\n') || ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')) ; +} + +static inline bool isMETAPOSTcomment(int ch) { + return + (ch == '%') ; +} + +static inline bool isMETAPOSTone(int ch) { + return + (ch == '[') || (ch == ']') || (ch == '(') || (ch == ')') || + (ch == ':') || (ch == '=') || (ch == '<') || (ch == '>') || + (ch == '{') || (ch == '}') || (ch == '\'') || (ch == '\"') ; +} + +static inline bool isMETAPOSTtwo(int ch) { + return + (ch == ';') || (ch == '$') || (ch == '@') || (ch == '#'); +} + +static inline bool isMETAPOSTthree(int ch) { + return + (ch == '.') || (ch == '-') || (ch == '+') || (ch == '/') || + (ch == '*') || (ch == ',') || (ch == '|') || (ch == '`') || + (ch == '!') || (ch == '?') || (ch == '^') || (ch == '&') || + (ch == '%') ; +} + +static inline bool isMETAPOSTidentifier(int ch) { + return + ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) || + (ch == '_') ; +} + +static inline bool isMETAPOSTnumber(int ch) { + return + (ch >= '0') && (ch <= '9') ; +} + +static inline bool isMETAPOSTstring(int ch) { + return + (ch == '\"') ; +} + +static inline bool isMETAPOSTcolon(int ch) { + return + (ch == ':') ; +} + +static inline bool isMETAPOSTequal(int ch) { + return + (ch == '=') ; +} + +static int CheckMETAPOSTInterface( + unsigned int startPos, + int length, + Accessor &styler, + int defaultInterface) { + + char lineBuffer[1024] ; + unsigned int linePos = 0 ; + + // some day we can make something lexer.metapost.mapping=(none,0)(metapost,1)(mp,1)(metafun,2)... + + if (styler.SafeGetCharAt(0) == '%') { + for (unsigned int i = 0; i < startPos + length; i++) { + lineBuffer[linePos++] = styler.SafeGetCharAt(i) ; + if (endOfLine(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { + lineBuffer[linePos] = '\0'; + if (strstr(lineBuffer, "interface=none")) { + return 0 ; + } else if (strstr(lineBuffer, "interface=metapost") || strstr(lineBuffer, "interface=mp")) { + return 1 ; + } else if (strstr(lineBuffer, "interface=metafun")) { + return 2 ; + } else if (styler.SafeGetCharAt(1) == 'D' && strstr(lineBuffer, "%D \\module")) { + // better would be to limit the search to just one line + return 2 ; + } else { + return defaultInterface ; + } + } + } + } + + return defaultInterface ; +} + +static void ColouriseMETAPOSTDoc( + unsigned int startPos, + int length, + int, + WordList *keywordlists[], + Accessor &styler) { + + styler.StartAt(startPos) ; + styler.StartSegment(startPos) ; + + bool processComment = styler.GetPropertyInt("lexer.metapost.comment.process", 0) == 1 ; + int defaultInterface = styler.GetPropertyInt("lexer.metapost.interface.default", 1) ; + + int currentInterface = CheckMETAPOSTInterface(startPos,length,styler,defaultInterface) ; + + // 0 no keyword highlighting + // 1 metapost keyword hightlighting + // 2+ metafun keyword hightlighting + + int extraInterface = 0 ; + + if (currentInterface != 0) { + extraInterface = currentInterface ; + } + + WordList &keywords = *keywordlists[0] ; + WordList &keywords2 = *keywordlists[extraInterface-1] ; + + StyleContext sc(startPos, length, SCE_METAPOST_TEXT, styler) ; + + char key[100] ; + + bool inTeX = false ; + bool inComment = false ; + bool inString = false ; + bool inClause = false ; + + bool going = sc.More() ; // needed because of a fuzzy end of file state + + for (; going; sc.Forward()) { + + if (! sc.More()) { going = false ; } // we need to go one behind the end of text + + if (inClause) { + sc.SetState(SCE_METAPOST_TEXT) ; + inClause = false ; + } + + if (inComment) { + if (sc.atLineEnd) { + sc.SetState(SCE_METAPOST_TEXT) ; + inTeX = false ; + inComment = false ; + inClause = false ; + inString = false ; // not correct but we want to stimulate one-lines + } + } else if (inString) { + if (isMETAPOSTstring(sc.ch)) { + sc.SetState(SCE_METAPOST_SPECIAL) ; + sc.ForwardSetState(SCE_METAPOST_TEXT) ; + inString = false ; + } else if (sc.atLineEnd) { + sc.SetState(SCE_METAPOST_TEXT) ; + inTeX = false ; + inComment = false ; + inClause = false ; + inString = false ; // not correct but we want to stimulate one-lines + } + } else { + if ((! isMETAPOSTidentifier(sc.ch)) && (sc.LengthCurrent() > 0)) { + if (sc.state == SCE_METAPOST_COMMAND) { + sc.GetCurrent(key, sizeof(key)) ; + if ((strcmp(key,"btex") == 0) || (strcmp(key,"verbatimtex") == 0)) { + sc.ChangeState(SCE_METAPOST_GROUP) ; + inTeX = true ; + } else if (inTeX) { + if (strcmp(key,"etex") == 0) { + sc.ChangeState(SCE_METAPOST_GROUP) ; + inTeX = false ; + } else { + sc.ChangeState(SCE_METAPOST_TEXT) ; + } + } else { + if (keywords && keywords.InList(key)) { + sc.ChangeState(SCE_METAPOST_COMMAND) ; + } else if (keywords2 && keywords2.InList(key)) { + sc.ChangeState(SCE_METAPOST_EXTRA) ; + } else { + sc.ChangeState(SCE_METAPOST_TEXT) ; + } + } + } + } + if (isMETAPOSTcomment(sc.ch)) { + if (! inTeX) { + sc.SetState(SCE_METAPOST_SYMBOL) ; + sc.ForwardSetState(SCE_METAPOST_DEFAULT) ; + inComment = ! processComment ; + } else { + sc.SetState(SCE_METAPOST_TEXT) ; + } + } else if (isMETAPOSTstring(sc.ch)) { + if (! inTeX) { + sc.SetState(SCE_METAPOST_SPECIAL) ; + if (! isMETAPOSTstring(sc.chNext)) { + sc.ForwardSetState(SCE_METAPOST_TEXT) ; + } + inString = true ; + } else { + sc.SetState(SCE_METAPOST_TEXT) ; + } + } else if (isMETAPOSTcolon(sc.ch)) { + if (! inTeX) { + if (! isMETAPOSTequal(sc.chNext)) { + sc.SetState(SCE_METAPOST_COMMAND) ; + inClause = true ; + } else { + sc.SetState(SCE_METAPOST_SPECIAL) ; + } + } else { + sc.SetState(SCE_METAPOST_TEXT) ; + } + } else if (isMETAPOSTone(sc.ch)) { + if (! inTeX) { + sc.SetState(SCE_METAPOST_SPECIAL) ; + } else { + sc.SetState(SCE_METAPOST_TEXT) ; + } + } else if (isMETAPOSTtwo(sc.ch)) { + if (! inTeX) { + sc.SetState(SCE_METAPOST_GROUP) ; + } else { + sc.SetState(SCE_METAPOST_TEXT) ; + } + } else if (isMETAPOSTthree(sc.ch)) { + if (! inTeX) { + sc.SetState(SCE_METAPOST_SYMBOL) ; + } else { + sc.SetState(SCE_METAPOST_TEXT) ; + } + } else if (isMETAPOSTidentifier(sc.ch)) { + if (sc.state != SCE_METAPOST_COMMAND) { + sc.SetState(SCE_METAPOST_TEXT) ; + sc.ChangeState(SCE_METAPOST_COMMAND) ; + } + } else if (isMETAPOSTnumber(sc.ch)) { + // rather redundant since for the moment we don't handle numbers + sc.SetState(SCE_METAPOST_TEXT) ; + } else if (sc.atLineEnd) { + sc.SetState(SCE_METAPOST_TEXT) ; + inTeX = false ; + inComment = false ; + inClause = false ; + inString = false ; + } else { + sc.SetState(SCE_METAPOST_TEXT) ; + } + } + + } + + sc.Complete(); + +} + +// Hooks info the system: + +static const char * const metapostWordListDesc[] = { + "MetaPost", + "MetaFun", + 0 +} ; + +static int classifyFoldPointMetapost(const char* s,WordList *keywordlists[]) { + WordList& keywordsStart=*keywordlists[3]; + WordList& keywordsStop1=*keywordlists[4]; + + if (keywordsStart.InList(s)) {return 1;} + else if (keywordsStop1.InList(s)) {return -1;} + return 0; + +} + +static int ParseMetapostWord(unsigned int pos, Accessor &styler, char *word) +{ + int length=0; + char ch=styler.SafeGetCharAt(pos); + *word=0; + + while(isMETAPOSTidentifier(ch) && isalpha(ch) && length<100){ + word[length]=ch; + length++; + ch=styler.SafeGetCharAt(pos+length); + } + word[length]=0; + return length; +} + +static void FoldMetapostDoc(unsigned int startPos, int length, int, WordList *keywordlists[], Accessor &styler) +{ + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos+length; + int visibleChars=0; + int lineCurrent=styler.GetLine(startPos); + int levelPrev=styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent=levelPrev; + char chNext=styler[startPos]; + + char buffer[100]=""; + + for (unsigned int i=startPos; i < endPos; i++) { + char ch=chNext; + chNext=styler.SafeGetCharAt(i+1); + char chPrev=styler.SafeGetCharAt(i-1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if(i==0 || chPrev == '\r' || chPrev=='\n'|| chPrev==' '|| chPrev=='(' || chPrev=='$') + { + ParseMetapostWord(i, styler, buffer); + levelCurrent += classifyFoldPointMetapost(buffer,keywordlists); + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); + +} + + +LexerModule lmMETAPOST(SCLEX_METAPOST, ColouriseMETAPOSTDoc, "metapost", FoldMetapostDoc, metapostWordListDesc); diff --git a/lexers/LexMySQL.cxx b/lexers/LexMySQL.cxx new file mode 100644 index 000000000..e8496ceea --- /dev/null +++ b/lexers/LexMySQL.cxx @@ -0,0 +1,518 @@ +/** + * Scintilla source code edit control + * @file LexMySQL.cxx + * Lexer for MySQL + * + * Improved by Mike Lischke + * Adopted from LexSQL.cxx by Anders Karlsson + * Original work by Neil Hodgson + * Copyright 1998-2005 by Neil Hodgson + * The License.txt file describes the conditions under which this software may be distributed. + */ + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordStart(int ch) { + return (ch < 0x80) && (isalpha(ch) || ch == '_'); +} + +static inline bool IsADoxygenChar(int ch) { + return (islower(ch) || ch == '$' || ch == '@' || + ch == '\\' || ch == '&' || ch == '<' || + ch == '>' || ch == '#' || ch == '{' || + ch == '}' || ch == '[' || ch == ']'); +} + +static inline bool IsANumberChar(int ch) { + // Not exactly following number definition (several dots are seen as OK, etc.) + // but probably enough in most cases. + return (ch < 0x80) && + (isdigit(ch) || toupper(ch) == 'E' || + ch == '.' || ch == '-' || ch == '+'); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Check if the current content context represent a keyword and set the context state if so. + */ +static void CheckForKeyword(StyleContext& sc, WordList* keywordlists[]) +{ + int length = sc.LengthCurrent() + 1; // +1 for the next char + char* s = new char[length]; + sc.GetCurrentLowered(s, length); + if (keywordlists[0]->InList(s)) + sc.ChangeState(SCE_MYSQL_MAJORKEYWORD); + else + if (keywordlists[1]->InList(s)) + sc.ChangeState(SCE_MYSQL_KEYWORD); + else + if (keywordlists[2]->InList(s)) + sc.ChangeState(SCE_MYSQL_DATABASEOBJECT); + else + if (keywordlists[3]->InList(s)) + sc.ChangeState(SCE_MYSQL_FUNCTION); + else + if (keywordlists[5]->InList(s)) + sc.ChangeState(SCE_MYSQL_PROCEDUREKEYWORD); + else + if (keywordlists[6]->InList(s)) + sc.ChangeState(SCE_MYSQL_USER1); + else + if (keywordlists[7]->InList(s)) + sc.ChangeState(SCE_MYSQL_USER2); + else + if (keywordlists[8]->InList(s)) + sc.ChangeState(SCE_MYSQL_USER3); + delete [] s; +} + +//-------------------------------------------------------------------------------------------------- + +static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) +{ + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) + { + // Determine if the current state should terminate. + switch (sc.state) + { + case SCE_MYSQL_OPERATOR: + sc.SetState(SCE_MYSQL_DEFAULT); + break; + case SCE_MYSQL_NUMBER: + // We stop the number definition on non-numerical non-dot non-eE non-sign char. + if (!IsANumberChar(sc.ch)) + sc.SetState(SCE_MYSQL_DEFAULT); + break; + case SCE_MYSQL_IDENTIFIER: + // Switch from identifier to keyword state and open a new state for the new char. + if (!IsAWordChar(sc.ch)) + { + CheckForKeyword(sc, keywordlists); + + // Additional check for function keywords needed. + // A function name must be followed by an opening parenthesis. + if (sc.state == SCE_MYSQL_FUNCTION && sc.ch != '(') + sc.ChangeState(SCE_MYSQL_DEFAULT); + + sc.SetState(SCE_MYSQL_DEFAULT); + } + break; + case SCE_MYSQL_VARIABLE: + if (!IsAWordChar(sc.ch)) + sc.SetState(SCE_MYSQL_DEFAULT); + break; + case SCE_MYSQL_SYSTEMVARIABLE: + if (!IsAWordChar(sc.ch)) + { + int length = sc.LengthCurrent() + 1; + char* s = new char[length]; + sc.GetCurrentLowered(s, length); + + // Check for known system variables here. + if (keywordlists[4]->InList(&s[2])) + sc.ChangeState(SCE_MYSQL_KNOWNSYSTEMVARIABLE); + delete [] s; + + sc.SetState(SCE_MYSQL_DEFAULT); + } + break; + case SCE_MYSQL_QUOTEDIDENTIFIER: + if (sc.ch == '`') + { + if (sc.chNext == '`') + sc.Forward(); // Ignore it + else + sc.ForwardSetState(SCE_MYSQL_DEFAULT); + } + break; + case SCE_MYSQL_COMMENT: + case SCE_MYSQL_HIDDENCOMMAND: + if (sc.Match('*', '/')) + { + sc.Forward(); + sc.ForwardSetState(SCE_MYSQL_DEFAULT); + } + break; + case SCE_MYSQL_COMMENTLINE: + if (sc.atLineStart) + sc.SetState(SCE_MYSQL_DEFAULT); + break; + case SCE_MYSQL_SQSTRING: + if (sc.ch == '\\') + sc.Forward(); // Escape sequence + else + if (sc.ch == '\'') + { + // End of single quoted string reached? + if (sc.chNext == '\'') + sc.Forward(); + else + sc.ForwardSetState(SCE_MYSQL_DEFAULT); + } + break; + case SCE_MYSQL_DQSTRING: + if (sc.ch == '\\') + sc.Forward(); // Escape sequence + else + if (sc.ch == '\"') + { + // End of single quoted string reached? + if (sc.chNext == '\"') + sc.Forward(); + else + sc.ForwardSetState(SCE_MYSQL_DEFAULT); + } + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_MYSQL_DEFAULT) + { + switch (sc.ch) + { + case '@': + if (sc.chNext == '@') + { + sc.SetState(SCE_MYSQL_SYSTEMVARIABLE); + sc.Forward(2); // Skip past @@. + } + else + if (IsAWordStart(sc.ch)) + { + sc.SetState(SCE_MYSQL_VARIABLE); + sc.Forward(); // Skip past @. + } + else + sc.SetState(SCE_MYSQL_OPERATOR); + break; + case '`': + sc.SetState(SCE_MYSQL_QUOTEDIDENTIFIER); + break; + case '#': + sc.SetState(SCE_MYSQL_COMMENTLINE); + break; + case '\'': + sc.SetState(SCE_MYSQL_SQSTRING); + break; + case '\"': + sc.SetState(SCE_MYSQL_DQSTRING); + break; + default: + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) + sc.SetState(SCE_MYSQL_NUMBER); + else + if (IsAWordStart(sc.ch)) + sc.SetState(SCE_MYSQL_IDENTIFIER); + else + if (sc.Match('/', '*')) + { + sc.SetState(SCE_MYSQL_COMMENT); + + // Skip comment introducer and check for hidden command. + sc.Forward(2); + if (sc.ch == '!') + { + sc.ChangeState(SCE_MYSQL_HIDDENCOMMAND); + sc.Forward(); + } + } + else + if (sc.Match("--")) + { + // Special MySQL single line comment. + sc.SetState(SCE_MYSQL_COMMENTLINE); + sc.Forward(2); + + // Check the third character too. It must be a space or EOL. + if (sc.ch != ' ' && sc.ch != '\n' && sc.ch != '\r') + sc.ChangeState(SCE_MYSQL_OPERATOR); + } + else + if (isoperator(static_cast(sc.ch))) + sc.SetState(SCE_MYSQL_OPERATOR); + } + } + } + + // Do a final check for keywords if we currently have an identifier, to highlight them + // also at the end of a line. + if (sc.state == SCE_MYSQL_IDENTIFIER) + { + CheckForKeyword(sc, keywordlists); + + // Additional check for function keywords needed. + // A function name must be followed by an opening parenthesis. + if (sc.state == SCE_MYSQL_FUNCTION && sc.ch != '(') + sc.ChangeState(SCE_MYSQL_DEFAULT); + } + + sc.Complete(); +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Helper function to determine if we have a foldable comment currently. + */ +static bool IsStreamCommentStyle(int style) +{ + return style == SCE_MYSQL_COMMENT; +} + +//-------------------------------------------------------------------------------------------------- + +/** + * Code copied from StyleContext and modified to work here. Should go into Accessor as a + * companion to Match()... + */ +bool MatchIgnoreCase(Accessor &styler, int currentPos, const char *s) +{ + for (int n = 0; *s; n++) + { + if (*s != tolower(styler.SafeGetCharAt(currentPos + n))) + return false; + s++; + } + return true; +} + +//-------------------------------------------------------------------------------------------------- + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment. +static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) +{ + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldOnlyBegin = styler.GetPropertyInt("fold.sql.only.begin", 0) != 0; + + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16; + int levelNext = levelCurrent; + + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + + bool endFound = false; + bool whenFound = false; + bool elseFound = false; + + char nextChar = styler.SafeGetCharAt(startPos); + for (unsigned int i = startPos; length > 0; i++, length--) + { + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + + char currentChar = nextChar; + nextChar = styler.SafeGetCharAt(i + 1); + bool atEOL = (currentChar == '\r' && nextChar != '\n') || (currentChar == '\n'); + + switch (style) + { + case SCE_MYSQL_COMMENT: + if (foldComment) + { + // Multiline comment style /* .. */. + if (IsStreamCommentStyle(style)) + { + // Increase level if we just start a foldable comment. + if (!IsStreamCommentStyle(stylePrev)) + levelNext++; + else + // If we are in the middle of a foldable comment check if it ends now. + // Don't end at the line end, though. + if (!IsStreamCommentStyle(styleNext) && !atEOL) + levelNext--; + } + } + break; + case SCE_MYSQL_COMMENTLINE: + if (foldComment) + { + // Not really a standard, but we add support for single line comments + // with special curly braces syntax as foldable comments too. + // MySQL needs -- comments to be followed by space or control char + if (styler.Match(i, "--")) + { + char chNext2 = styler.SafeGetCharAt(i + 2); + char chNext3 = styler.SafeGetCharAt(i + 3); + if (chNext2 == '{' || chNext3 == '{') + levelNext++; + else + if (chNext2 == '}' || chNext3 == '}') + levelNext--; + } + } + break; + case SCE_MYSQL_HIDDENCOMMAND: + if (style != stylePrev) + levelNext++; + else + if (style != styleNext) + levelNext--; + break; + case SCE_MYSQL_OPERATOR: + if (currentChar == '(') + levelNext++; + else + if (currentChar == ')') + levelNext--; + break; + case SCE_MYSQL_MAJORKEYWORD: + case SCE_MYSQL_KEYWORD: + case SCE_MYSQL_FUNCTION: + case SCE_MYSQL_PROCEDUREKEYWORD: + // Reserved and other keywords. + if (style != stylePrev) + { + bool beginFound = MatchIgnoreCase(styler, i, "begin"); + bool ifFound = MatchIgnoreCase(styler, i, "if"); + bool thenFound = MatchIgnoreCase(styler, i, "then"); + bool whileFound = MatchIgnoreCase(styler, i, "while"); + bool loopFound = MatchIgnoreCase(styler, i, "loop"); + bool repeatFound = MatchIgnoreCase(styler, i, "repeat"); + + if (!foldOnlyBegin && endFound && (ifFound || whileFound || loopFound)) + { + endFound = false; + levelNext--; + if (levelNext < SC_FOLDLEVELBASE) + levelNext = SC_FOLDLEVELBASE; + + // Note that "else" is special here. It may or may not be followed by an "if .. then", + // but in any case the level stays the same. When followed by an "if .. then" the level + // will be increased later, if not, then at eol. + } + else + if (!foldOnlyBegin && MatchIgnoreCase(styler, i, "else")) + { + levelNext--; + elseFound = true; + } + else + if (!foldOnlyBegin && thenFound) + { + if (whenFound) + whenFound = false; + else + levelNext++; + } + else + if (ifFound) + elseFound = false; + else + if (MatchIgnoreCase(styler, i, "when")) + whenFound = true; + else + { + if (beginFound) + levelNext++; + else + if (!foldOnlyBegin && (loopFound || repeatFound || whileFound)) + { + if (endFound) + endFound = false; + else + levelNext++; + } + else + if (MatchIgnoreCase(styler, i, "end")) + { + // Multiple "end" in a row are counted multiple times! + if (endFound) + { + levelNext--; + if (levelNext < SC_FOLDLEVELBASE) + levelNext = SC_FOLDLEVELBASE; + } + endFound = true; + whenFound = false; + } + } + } + break; + } + + // Handle the case of a trailing end without an if / while etc, as in the case of a begin. + if (endFound) + { + endFound = false; + levelNext--; + if (levelNext < SC_FOLDLEVELBASE) + levelNext = SC_FOLDLEVELBASE; + } + + if (atEOL) + { + if (elseFound) + { + levelNext++; + elseFound = false; + } + + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) + styler.SetLevel(lineCurrent, lev); + + lineCurrent++; + levelCurrent = levelNext; + visibleChars = 0; + endFound = false; + whenFound = false; + } + + if (!isspacechar(currentChar)) + visibleChars++; + } +} + +//-------------------------------------------------------------------------------------------------- + +static const char * const mysqlWordListDesc[] = { + "Major Keywords", + "Keywords", + "Database Objects", + "Functions", + "System Variables", + "Procedure keywords", + "User Keywords 1", + "User Keywords 2", + "User Keywords 3", + 0 +}; + +LexerModule lmMySQL(SCLEX_MYSQL, ColouriseMySQLDoc, "mysql", FoldMySQLDoc, mysqlWordListDesc); diff --git a/lexers/LexNimrod.cxx b/lexers/LexNimrod.cxx new file mode 100644 index 000000000..8c4d04360 --- /dev/null +++ b/lexers/LexNimrod.cxx @@ -0,0 +1,430 @@ +// Scintilla source code edit control +// Nimrod lexer +// (c) 2009 Andreas Rumpf +/** @file LexNimrod.cxx + ** Lexer for Nimrod. + **/ +// Copyright 1998-2002 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(int ch) { + return (ch >= 0x80) || isalnum(ch) || ch == '_'; +} + +static int tillEndOfTripleQuote(Accessor &styler, int pos, int max) { + /* search for """ */ + for (;;) { + if (styler.SafeGetCharAt(pos, '\0') == '\0') return pos; + if (pos >= max) return pos; + if (styler.Match(pos, "\"\"\"")) { + return pos + 2; + } + pos++; + } +} + +#define CR 13 /* use both because Scite allows changing the line ending */ +#define LF 10 + +static bool inline isNewLine(int ch) { + return ch == CR || ch == LF; +} + +static int scanString(Accessor &styler, int pos, int max, bool rawMode) { + for (;;) { + if (pos >= max) return pos; + char ch = styler.SafeGetCharAt(pos, '\0'); + if (ch == CR || ch == LF || ch == '\0') return pos; + if (ch == '"') return pos; + if (ch == '\\' && !rawMode) { + pos += 2; + } else { + pos++; + } + } +} + +static int scanChar(Accessor &styler, int pos, int max) { + for (;;) { + if (pos >= max) return pos; + char ch = styler.SafeGetCharAt(pos, '\0'); + if (ch == CR || ch == LF || ch == '\0') return pos; + if (ch == '\'' && !isalnum(styler.SafeGetCharAt(pos+1, '\0')) ) + return pos; + if (ch == '\\') { + pos += 2; + } else { + pos++; + } + } +} + +static int scanIdent(Accessor &styler, int pos, WordList &keywords) { + char buf[100]; /* copy to lowercase and ignore underscores */ + int i = 0; + + for (;;) { + char ch = styler.SafeGetCharAt(pos, '\0'); + if (!IsAWordChar(ch)) break; + if (ch != '_' && i < ((int)sizeof(buf))-1) { + buf[i] = static_cast(tolower(ch)); + i++; + } + pos++; + } + buf[i] = '\0'; + /* look for keyword */ + if (keywords.InList(buf)) { + styler.ColourTo(pos-1, SCE_P_WORD); + } else { + styler.ColourTo(pos-1, SCE_P_IDENTIFIER); + } + return pos; +} + +static int scanNumber(Accessor &styler, int pos) { + char ch, ch2; + ch = styler.SafeGetCharAt(pos, '\0'); + ch2 = styler.SafeGetCharAt(pos+1, '\0'); + if (ch == '0' && (ch2 == 'b' || ch2 == 'B')) { + /* binary number: */ + pos += 2; + for (;;) { + ch = styler.SafeGetCharAt(pos, '\0'); + if (ch == '_' || (ch >= '0' && ch <= '1')) ++pos; + else break; + } + } else if (ch == '0' && + (ch2 == 'o' || ch2 == 'O' || ch2 == 'c' || ch2 == 'C')) { + /* octal number: */ + pos += 2; + for (;;) { + ch = styler.SafeGetCharAt(pos, '\0'); + if (ch == '_' || (ch >= '0' && ch <= '7')) ++pos; + else break; + } + } else if (ch == '0' && (ch2 == 'x' || ch2 == 'X')) { + /* hexadecimal number: */ + pos += 2; + for (;;) { + ch = styler.SafeGetCharAt(pos, '\0'); + if (ch == '_' || (ch >= '0' && ch <= '9') + || (ch >= 'a' && ch <= 'f') + || (ch >= 'A' && ch <= 'F')) ++pos; + else break; + } + } else { + // skip decimal part: + for (;;) { + ch = styler.SafeGetCharAt(pos, '\0'); + if (ch == '_' || (ch >= '0' && ch <= '9')) ++pos; + else break; + } + ch2 = styler.SafeGetCharAt(pos+1, '\0'); + if (ch == '.' && ch2 >= '0' && ch2 <= '9') { + ++pos; // skip '.' + for (;;) { + ch = styler.SafeGetCharAt(pos, '\0'); + if (ch == '_' || (ch >= '0' && ch <= '9')) ++pos; + else break; + } + } + if (ch == 'e' || ch == 'E') { + ++pos; + ch = styler.SafeGetCharAt(pos, '\0'); + if (ch == '-' || ch == '+') ++pos; + for (;;) { + ch = styler.SafeGetCharAt(pos, '\0'); + if (ch == '_' || (ch >= '0' && ch <= '9')) ++pos; + else break; + } + } + } + if (ch == '\'') { + /* a type suffix: */ + pos++; + for (;;) { + ch = styler.SafeGetCharAt(pos); + if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') + || (ch >= 'a' && ch <= 'z') || ch == '_') ++pos; + else break; + } + } + styler.ColourTo(pos-1, SCE_P_NUMBER); + return pos; +} + +/* rewritten from scratch, because I couldn't get rid of the bugs... + (A character based approach sucks!) +*/ +static void ColouriseNimrodDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + int pos = startPos; + int max = startPos + length; + char ch; + WordList &keywords = *keywordlists[0]; + + styler.StartAt(startPos); + styler.StartSegment(startPos); + + switch (initStyle) { + /* check where we are: */ + case SCE_P_TRIPLEDOUBLE: + pos = tillEndOfTripleQuote(styler, pos, max); + styler.ColourTo(pos, SCE_P_TRIPLEDOUBLE); + pos++; + break; + default: /* nothing to do: */ + break; + } + while (pos < max) { + ch = styler.SafeGetCharAt(pos, '\0'); + switch (ch) { + case '\0': return; + case '#': { + bool doccomment = (styler.SafeGetCharAt(pos+1) == '#'); + while (pos < max && !isNewLine(styler.SafeGetCharAt(pos, LF))) pos++; + if (doccomment) + styler.ColourTo(pos, SCE_C_COMMENTLINEDOC); + else + styler.ColourTo(pos, SCE_P_COMMENTLINE); + } break; + case 'r': case 'R': { + if (styler.SafeGetCharAt(pos+1) == '"') { + pos = scanString(styler, pos+2, max, true); + styler.ColourTo(pos, SCE_P_STRING); + pos++; + } else { + pos = scanIdent(styler, pos, keywords); + } + } break; + case '"': + if (styler.Match(pos+1, "\"\"")) { + pos = tillEndOfTripleQuote(styler, pos+3, max); + styler.ColourTo(pos, SCE_P_TRIPLEDOUBLE); + } else { + pos = scanString(styler, pos+1, max, false); + styler.ColourTo(pos, SCE_P_STRING); + } + pos++; + break; + case '\'': + pos = scanChar(styler, pos+1, max); + styler.ColourTo(pos, SCE_P_CHARACTER); + pos++; + break; + default: // identifers, numbers, operators, whitespace + if (ch >= '0' && ch <= '9') { + pos = scanNumber(styler, pos); + } else if (IsAWordChar(ch)) { + pos = scanIdent(styler, pos, keywords); + } else if (ch == '`') { + pos++; + while (pos < max) { + ch = styler.SafeGetCharAt(pos, LF); + if (ch == '`') { + ++pos; + break; + } + if (ch == CR || ch == LF) break; + ++pos; + } + styler.ColourTo(pos, SCE_P_IDENTIFIER); + } else if (strchr("()[]{}:=;-\\/&%$!+<>|^?,.*~@", ch)) { + styler.ColourTo(pos, SCE_P_OPERATOR); + pos++; + } else { + styler.ColourTo(pos, SCE_P_DEFAULT); + pos++; + } + break; + } + } +} + +static bool IsCommentLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eol_pos; i++) { + char ch = styler[i]; + if (ch == '#') + return true; + else if (ch != ' ' && ch != '\t') + return false; + } + return false; +} + +static bool IsQuoteLine(int line, Accessor &styler) { + int style = styler.StyleAt(styler.LineStart(line)) & 31; + return ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE)); +} + + +static void FoldNimrodDoc(unsigned int startPos, int length, + int /*initStyle - unused*/, + WordList *[], Accessor &styler) { + const int maxPos = startPos + length; + const int maxLines = styler.GetLine(maxPos - 1); // Requested last line + const int docLines = styler.GetLine(styler.Length() - 1); // Available last line + const bool foldComment = styler.GetPropertyInt("fold.comment.nimrod") != 0; + const bool foldQuotes = styler.GetPropertyInt("fold.quotes.nimrod") != 0; + + // Backtrack to previous non-blank line so we can determine indent level + // for any white space lines (needed esp. within triple quoted strings) + // and so we can fix any preceding fold level (which is why we go back + // at least one line in all cases) + int spaceFlags = 0; + int lineCurrent = styler.GetLine(startPos); + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); + while (lineCurrent > 0) { + lineCurrent--; + indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) && + (!IsCommentLine(lineCurrent, styler)) && + (!IsQuoteLine(lineCurrent, styler))) + break; + } + int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + + // Set up initial loop state + startPos = styler.LineStart(lineCurrent); + int prev_state = SCE_P_DEFAULT & 31; + if (lineCurrent >= 1) + prev_state = styler.StyleAt(startPos - 1) & 31; + int prevQuote = foldQuotes && ((prev_state == SCE_P_TRIPLE) || + (prev_state == SCE_P_TRIPLEDOUBLE)); + int prevComment = 0; + if (lineCurrent >= 1) + prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler); + + // Process all characters to end of requested range or end of any triple quote + // or comment that hangs over the end of the range. Cap processing in all cases + // to end of document (in case of unclosed quote or comment at end). + while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || + prevQuote || prevComment)) { + + // Gather info + int lev = indentCurrent; + int lineNext = lineCurrent + 1; + int indentNext = indentCurrent; + int quote = false; + if (lineNext <= docLines) { + // Information about next line is only available if not at end of document + indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); + int style = styler.StyleAt(styler.LineStart(lineNext)) & 31; + quote = foldQuotes && ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE)); + } + const int quote_start = (quote && !prevQuote); + const int quote_continue = (quote && prevQuote); + const int comment = foldComment && IsCommentLine(lineCurrent, styler); + const int comment_start = (comment && !prevComment && (lineNext <= docLines) && + IsCommentLine(lineNext, styler) && + (lev > SC_FOLDLEVELBASE)); + const int comment_continue = (comment && prevComment); + if ((!quote || !prevQuote) && !comment) + indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + if (quote) + indentNext = indentCurrentLevel; + if (indentNext & SC_FOLDLEVELWHITEFLAG) + indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel; + + if (quote_start) { + // Place fold point at start of triple quoted string + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (quote_continue || prevQuote) { + // Add level to rest of lines in the string + lev = lev + 1; + } else if (comment_start) { + // Place fold point at start of a block of comments + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (comment_continue) { + // Add level to rest of lines in the block + lev = lev + 1; + } + + // Skip past any blank lines for next indent level info; we skip also + // comments (all comments, not just those starting in column 0) + // which effectively folds them into surrounding code rather + // than screwing up folding. + + while (!quote && + (lineNext < docLines) && + ((indentNext & SC_FOLDLEVELWHITEFLAG) || + (lineNext <= docLines && IsCommentLine(lineNext, styler)))) { + + lineNext++; + indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); + } + + const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK; + const int levelBeforeComments = + Platform::Maximum(indentCurrentLevel,levelAfterComments); + + // Now set all the indent levels on the lines we skipped + // Do this from end to start. Once we encounter one line + // which is indented more than the line after the end of + // the comment-block, use the level of the block before + + int skipLine = lineNext; + int skipLevel = levelAfterComments; + + while (--skipLine > lineCurrent) { + int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL); + + if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments) + skipLevel = levelBeforeComments; + + int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG; + + styler.SetLevel(skipLine, skipLevel | whiteFlag); + } + + // Set fold header on non-quote/non-comment line + if (!quote && !comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG) ) { + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < + (indentNext & SC_FOLDLEVELNUMBERMASK)) + lev |= SC_FOLDLEVELHEADERFLAG; + } + + // Keep track of triple quote and block comment state of previous line + prevQuote = quote; + prevComment = comment_start || comment_continue; + + // Set fold level for this line and move to next line + styler.SetLevel(lineCurrent, lev); + indentCurrent = indentNext; + lineCurrent = lineNext; + } + + // NOTE: Cannot set level of last line here because indentCurrent doesn't have + // header flag set; the loop above is crafted to take care of this case! + //styler.SetLevel(lineCurrent, indentCurrent); +} + +static const char * const nimrodWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmNimrod(SCLEX_NIMROD, ColouriseNimrodDoc, "nimrod", FoldNimrodDoc, + nimrodWordListDesc); diff --git a/lexers/LexNsis.cxx b/lexers/LexNsis.cxx new file mode 100644 index 000000000..43ddc4706 --- /dev/null +++ b/lexers/LexNsis.cxx @@ -0,0 +1,655 @@ +// Scintilla source code edit control +/** @file LexNsis.cxx + ** Lexer for NSIS + **/ +// Copyright 2003 - 2005 by Angelo Mandato +// Last Updated: 03/13/2005 +// The License.txt file describes the conditions under which this software may be distributed. +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "CharClassify.h" +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +/* +// located in SciLexer.h +#define SCLEX_NSIS 43 + +#define SCE_NSIS_DEFAULT 0 +#define SCE_NSIS_COMMENT 1 +#define SCE_NSIS_STRINGDQ 2 +#define SCE_NSIS_STRINGLQ 3 +#define SCE_NSIS_STRINGRQ 4 +#define SCE_NSIS_FUNCTION 5 +#define SCE_NSIS_VARIABLE 6 +#define SCE_NSIS_LABEL 7 +#define SCE_NSIS_USERDEFINED 8 +#define SCE_NSIS_SECTIONDEF 9 +#define SCE_NSIS_SUBSECTIONDEF 10 +#define SCE_NSIS_IFDEFINEDEF 11 +#define SCE_NSIS_MACRODEF 12 +#define SCE_NSIS_STRINGVAR 13 +#define SCE_NSIS_NUMBER 14 +// ADDED for Scintilla v1.63 +#define SCE_NSIS_SECTIONGROUP 15 +#define SCE_NSIS_PAGEEX 16 +#define SCE_NSIS_FUNCTIONDEF 17 +#define SCE_NSIS_COMMENTBOX 18 +*/ + +static bool isNsisNumber(char ch) +{ + return (ch >= '0' && ch <= '9'); +} + +static bool isNsisChar(char ch) +{ + return (ch == '.' ) || (ch == '_' ) || isNsisNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); +} + +static bool isNsisLetter(char ch) +{ + return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); +} + +static bool NsisNextLineHasElse(unsigned int start, unsigned int end, Accessor &styler) +{ + int nNextLine = -1; + for( unsigned int i = start; i < end; i++ ) + { + char cNext = styler.SafeGetCharAt( i ); + if( cNext == '\n' ) + { + nNextLine = i+1; + break; + } + } + + if( nNextLine == -1 ) // We never found the next line... + return false; + + for( unsigned int firstChar = nNextLine; firstChar < end; firstChar++ ) + { + char cNext = styler.SafeGetCharAt( firstChar ); + if( cNext == ' ' ) + continue; + if( cNext == '\t' ) + continue; + if( cNext == '!' ) + { + if( styler.Match(firstChar, "!else") ) + return true; + } + break; + } + + return false; +} + +static int NsisCmp( const char *s1, const char *s2, bool bIgnoreCase ) +{ + if( bIgnoreCase ) + return CompareCaseInsensitive( s1, s2); + + return strcmp( s1, s2 ); +} + +static int calculateFoldNsis(unsigned int start, unsigned int end, int foldlevel, Accessor &styler, bool bElse, bool foldUtilityCmd ) +{ + int style = styler.StyleAt(end); + + // If the word is too long, it is not what we are looking for + if( end - start > 20 ) + return foldlevel; + + if( foldUtilityCmd ) + { + // Check the style at this point, if it is not valid, then return zero + if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF && + style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_IFDEFINEDEF && + style != SCE_NSIS_MACRODEF && style != SCE_NSIS_SECTIONGROUP && + style != SCE_NSIS_PAGEEX ) + return foldlevel; + } + else + { + if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF && + style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_SECTIONGROUP && + style != SCE_NSIS_PAGEEX ) + return foldlevel; + } + + int newFoldlevel = foldlevel; + bool bIgnoreCase = false; + if( styler.GetPropertyInt("nsis.ignorecase") == 1 ) + bIgnoreCase = true; + + char s[20]; // The key word we are looking for has atmost 13 characters + for (unsigned int i = 0; i < end - start + 1 && i < 19; i++) + { + s[i] = static_cast( styler[ start + i ] ); + s[i + 1] = '\0'; + } + + if( s[0] == '!' ) + { + if( NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifmacrodef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifmacrondef", bIgnoreCase ) == 0 || NsisCmp(s, "!if", bIgnoreCase ) == 0 || NsisCmp(s, "!macro", bIgnoreCase ) == 0 ) + newFoldlevel++; + else if( NsisCmp(s, "!endif", bIgnoreCase) == 0 || NsisCmp(s, "!macroend", bIgnoreCase ) == 0 ) + newFoldlevel--; + else if( bElse && NsisCmp(s, "!else", bIgnoreCase) == 0 ) + newFoldlevel++; + } + else + { + if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionGroup", bIgnoreCase ) == 0 || NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "SubSection", bIgnoreCase ) == 0 || NsisCmp(s, "PageEx", bIgnoreCase ) == 0 ) + newFoldlevel++; + else if( NsisCmp(s, "SectionGroupEnd", bIgnoreCase ) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "PageExEnd", bIgnoreCase ) == 0 ) + newFoldlevel--; + } + + return newFoldlevel; +} + +static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler ) +{ + bool bIgnoreCase = false; + if( styler.GetPropertyInt("nsis.ignorecase") == 1 ) + bIgnoreCase = true; + + bool bUserVars = false; + if( styler.GetPropertyInt("nsis.uservars") == 1 ) + bUserVars = true; + + char s[100]; + + WordList &Functions = *keywordLists[0]; + WordList &Variables = *keywordLists[1]; + WordList &Lables = *keywordLists[2]; + WordList &UserDefined = *keywordLists[3]; + + for (unsigned int i = 0; i < end - start + 1 && i < 99; i++) + { + if( bIgnoreCase ) + s[i] = static_cast( tolower(styler[ start + i ] ) ); + else + s[i] = static_cast( styler[ start + i ] ); + s[i + 1] = '\0'; + } + + // Check for special words... + if( NsisCmp(s, "!macro", bIgnoreCase ) == 0 || NsisCmp(s, "!macroend", bIgnoreCase) == 0 ) // Covers !macro and !macroend + return SCE_NSIS_MACRODEF; + + if( NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!endif", bIgnoreCase) == 0 ) // Covers !ifdef, !ifndef and !endif + return SCE_NSIS_IFDEFINEDEF; + + if( NsisCmp(s, "!if", bIgnoreCase ) == 0 || NsisCmp(s, "!else", bIgnoreCase ) == 0 ) // Covers !if and else + return SCE_NSIS_IFDEFINEDEF; + + if (NsisCmp(s, "!ifmacrodef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifmacrondef", bIgnoreCase ) == 0 ) // Covers !ifmacrodef and !ifnmacrodef + return SCE_NSIS_IFDEFINEDEF; + + if( NsisCmp(s, "SectionGroup", bIgnoreCase) == 0 || NsisCmp(s, "SectionGroupEnd", bIgnoreCase) == 0 ) // Covers SectionGroup and SectionGroupEnd + return SCE_NSIS_SECTIONGROUP; + + if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase) == 0 ) // Covers Section and SectionEnd + return SCE_NSIS_SECTIONDEF; + + if( NsisCmp(s, "SubSection", bIgnoreCase) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase) == 0 ) // Covers SubSection and SubSectionEnd + return SCE_NSIS_SUBSECTIONDEF; + + if( NsisCmp(s, "PageEx", bIgnoreCase) == 0 || NsisCmp(s, "PageExEnd", bIgnoreCase) == 0 ) // Covers PageEx and PageExEnd + return SCE_NSIS_PAGEEX; + + if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 ) // Covers Function and FunctionEnd + return SCE_NSIS_FUNCTIONDEF; + + if ( Functions.InList(s) ) + return SCE_NSIS_FUNCTION; + + if ( Variables.InList(s) ) + return SCE_NSIS_VARIABLE; + + if ( Lables.InList(s) ) + return SCE_NSIS_LABEL; + + if( UserDefined.InList(s) ) + return SCE_NSIS_USERDEFINED; + + if( strlen(s) > 3 ) + { + if( s[1] == '{' && s[strlen(s)-1] == '}' ) + return SCE_NSIS_VARIABLE; + } + + // See if the variable is a user defined variable + if( s[0] == '$' && bUserVars ) + { + bool bHasSimpleNsisChars = true; + for (unsigned int j = 1; j < end - start + 1 && j < 99; j++) + { + if( !isNsisChar( s[j] ) ) + { + bHasSimpleNsisChars = false; + break; + } + } + + if( bHasSimpleNsisChars ) + return SCE_NSIS_VARIABLE; + } + + // To check for numbers + if( isNsisNumber( s[0] ) ) + { + bool bHasSimpleNsisNumber = true; + for (unsigned int j = 1; j < end - start + 1 && j < 99; j++) + { + if( !isNsisNumber( s[j] ) ) + { + bHasSimpleNsisNumber = false; + break; + } + } + + if( bHasSimpleNsisNumber ) + return SCE_NSIS_NUMBER; + } + + return SCE_NSIS_DEFAULT; +} + +static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) +{ + int state = SCE_NSIS_DEFAULT; + if( startPos > 0 ) + state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox + + styler.StartAt( startPos ); + styler.GetLine( startPos ); + + unsigned int nLengthDoc = startPos + length; + styler.StartSegment( startPos ); + + char cCurrChar; + bool bVarInString = false; + bool bClassicVarInString = false; + + unsigned int i; + for( i = startPos; i < nLengthDoc; i++ ) + { + cCurrChar = styler.SafeGetCharAt( i ); + char cNextChar = styler.SafeGetCharAt(i+1); + + switch(state) + { + case SCE_NSIS_DEFAULT: + if( cCurrChar == ';' || cCurrChar == '#' ) // we have a comment line + { + styler.ColourTo(i-1, state ); + state = SCE_NSIS_COMMENT; + break; + } + if( cCurrChar == '"' ) + { + styler.ColourTo(i-1, state ); + state = SCE_NSIS_STRINGDQ; + bVarInString = false; + bClassicVarInString = false; + break; + } + if( cCurrChar == '\'' ) + { + styler.ColourTo(i-1, state ); + state = SCE_NSIS_STRINGRQ; + bVarInString = false; + bClassicVarInString = false; + break; + } + if( cCurrChar == '`' ) + { + styler.ColourTo(i-1, state ); + state = SCE_NSIS_STRINGLQ; + bVarInString = false; + bClassicVarInString = false; + break; + } + + // NSIS KeyWord,Function, Variable, UserDefined: + if( cCurrChar == '$' || isNsisChar(cCurrChar) || cCurrChar == '!' ) + { + styler.ColourTo(i-1,state); + state = SCE_NSIS_FUNCTION; + + // If it is a number, we must check and set style here first... + if( isNsisNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) ) + styler.ColourTo( i, SCE_NSIS_NUMBER); + + break; + } + + if( cCurrChar == '/' && cNextChar == '*' ) + { + styler.ColourTo(i-1,state); + state = SCE_NSIS_COMMENTBOX; + break; + } + + break; + case SCE_NSIS_COMMENT: + if( cNextChar == '\n' || cNextChar == '\r' ) + { + // Special case: + if( cCurrChar == '\\' ) + { + styler.ColourTo(i-2,state); + styler.ColourTo(i,SCE_NSIS_DEFAULT); + } + else + { + styler.ColourTo(i,state); + state = SCE_NSIS_DEFAULT; + } + } + break; + case SCE_NSIS_STRINGDQ: + case SCE_NSIS_STRINGLQ: + case SCE_NSIS_STRINGRQ: + + if( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' ) + break; // Ignore the next character, even if it is a quote of some sort + + if( cCurrChar == '"' && state == SCE_NSIS_STRINGDQ ) + { + styler.ColourTo(i,state); + state = SCE_NSIS_DEFAULT; + break; + } + + if( cCurrChar == '`' && state == SCE_NSIS_STRINGLQ ) + { + styler.ColourTo(i,state); + state = SCE_NSIS_DEFAULT; + break; + } + + if( cCurrChar == '\'' && state == SCE_NSIS_STRINGRQ ) + { + styler.ColourTo(i,state); + state = SCE_NSIS_DEFAULT; + break; + } + + if( cNextChar == '\r' || cNextChar == '\n' ) + { + int nCurLine = styler.GetLine(i+1); + int nBack = i; + // We need to check if the previous line has a \ in it... + bool bNextLine = false; + + while( nBack > 0 ) + { + if( styler.GetLine(nBack) != nCurLine ) + break; + + char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here + + if( cTemp == '\\' ) + { + bNextLine = true; + break; + } + if( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' ) + break; + + nBack--; + } + + if( bNextLine ) + { + styler.ColourTo(i+1,state); + } + if( bNextLine == false ) + { + styler.ColourTo(i,state); + state = SCE_NSIS_DEFAULT; + } + } + break; + + case SCE_NSIS_FUNCTION: + + // NSIS KeyWord: + if( cCurrChar == '$' ) + state = SCE_NSIS_DEFAULT; + else if( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) ) + state = SCE_NSIS_DEFAULT; + else if( (isNsisChar(cCurrChar) && !isNsisChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' ) + { + state = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler ); + styler.ColourTo( i, state); + state = SCE_NSIS_DEFAULT; + } + else if( !isNsisChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' ) + { + if( classifyWordNsis( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_NSIS_NUMBER ) + styler.ColourTo( i-1, SCE_NSIS_NUMBER ); + + state = SCE_NSIS_DEFAULT; + + if( cCurrChar == '"' ) + { + state = SCE_NSIS_STRINGDQ; + bVarInString = false; + bClassicVarInString = false; + } + else if( cCurrChar == '`' ) + { + state = SCE_NSIS_STRINGLQ; + bVarInString = false; + bClassicVarInString = false; + } + else if( cCurrChar == '\'' ) + { + state = SCE_NSIS_STRINGRQ; + bVarInString = false; + bClassicVarInString = false; + } + else if( cCurrChar == '#' || cCurrChar == ';' ) + { + state = SCE_NSIS_COMMENT; + } + } + break; + case SCE_NSIS_COMMENTBOX: + + if( styler.SafeGetCharAt(i-1) == '*' && cCurrChar == '/' ) + { + styler.ColourTo(i,state); + state = SCE_NSIS_DEFAULT; + } + break; + } + + if( state == SCE_NSIS_COMMENT || state == SCE_NSIS_COMMENTBOX ) + { + styler.ColourTo(i,state); + } + else if( state == SCE_NSIS_STRINGDQ || state == SCE_NSIS_STRINGLQ || state == SCE_NSIS_STRINGRQ ) + { + bool bIngoreNextDollarSign = false; + bool bUserVars = false; + if( styler.GetPropertyInt("nsis.uservars") == 1 ) + bUserVars = true; + + if( bVarInString && cCurrChar == '$' ) + { + bVarInString = false; + bIngoreNextDollarSign = true; + } + else if( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) ) + { + styler.ColourTo( i+1, SCE_NSIS_STRINGVAR); + bVarInString = false; + bIngoreNextDollarSign = false; + } + + // Covers "$INSTDIR and user vars like $MYVAR" + else if( bVarInString && !isNsisChar(cNextChar) ) + { + int nWordState = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler); + if( nWordState == SCE_NSIS_VARIABLE ) + styler.ColourTo( i, SCE_NSIS_STRINGVAR); + else if( bUserVars ) + styler.ColourTo( i, SCE_NSIS_STRINGVAR); + bVarInString = false; + } + // Covers "${TEST}..." + else if( bClassicVarInString && cNextChar == '}' ) + { + styler.ColourTo( i+1, SCE_NSIS_STRINGVAR); + bClassicVarInString = false; + } + + // Start of var in string + if( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' ) + { + styler.ColourTo( i-1, state); + bClassicVarInString = true; + bVarInString = false; + } + else if( !bIngoreNextDollarSign && cCurrChar == '$' ) + { + styler.ColourTo( i-1, state); + bVarInString = true; + bClassicVarInString = false; + } + } + } + + // Colourise remaining document + styler.ColourTo(nLengthDoc-1,state); +} + +static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) +{ + // No folding enabled, no reason to continue... + if( styler.GetPropertyInt("fold") == 0 ) + return; + + bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1; + bool foldUtilityCmd = styler.GetPropertyInt("nsis.foldutilcmd", 1) == 1; + bool blockComment = false; + + int lineCurrent = styler.GetLine(startPos); + unsigned int safeStartPos = styler.LineStart( lineCurrent ); + + bool bArg1 = true; + int nWordStart = -1; + + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelNext = levelCurrent; + int style = styler.StyleAt(safeStartPos); + if( style == SCE_NSIS_COMMENTBOX ) + { + if( styler.SafeGetCharAt(safeStartPos) == '/' && styler.SafeGetCharAt(safeStartPos+1) == '*' ) + levelNext++; + blockComment = true; + } + + for (unsigned int i = safeStartPos; i < startPos + length; i++) + { + char chCurr = styler.SafeGetCharAt(i); + style = styler.StyleAt(i); + if( blockComment && style != SCE_NSIS_COMMENTBOX ) + { + levelNext--; + blockComment = false; + } + else if( !blockComment && style == SCE_NSIS_COMMENTBOX ) + { + levelNext++; + blockComment = true; + } + + if( bArg1 && !blockComment) + { + if( nWordStart == -1 && (isNsisLetter(chCurr) || chCurr == '!') ) + { + nWordStart = i; + } + else if( isNsisLetter(chCurr) == false && nWordStart > -1 ) + { + int newLevel = calculateFoldNsis( nWordStart, i-1, levelNext, styler, foldAtElse, foldUtilityCmd ); + + if( newLevel == levelNext ) + { + if( foldAtElse && foldUtilityCmd ) + { + if( NsisNextLineHasElse(i, startPos + length, styler) ) + levelNext--; + } + } + else + levelNext = newLevel; + bArg1 = false; + } + } + + if( chCurr == '\n' ) + { + if( bArg1 && foldAtElse && foldUtilityCmd && !blockComment ) + { + if( NsisNextLineHasElse(i, startPos + length, styler) ) + levelNext--; + } + + // If we are on a new line... + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (levelUse < levelNext ) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) + styler.SetLevel(lineCurrent, lev); + + lineCurrent++; + levelCurrent = levelNext; + bArg1 = true; // New line, lets look at first argument again + nWordStart = -1; + } + } + + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) + styler.SetLevel(lineCurrent, lev); +} + +static const char * const nsisWordLists[] = { + "Functions", + "Variables", + "Lables", + "UserDefined", + 0, }; + + +LexerModule lmNsis(SCLEX_NSIS, ColouriseNsisDoc, "nsis", FoldNsisDoc, nsisWordLists); + diff --git a/lexers/LexOpal.cxx b/lexers/LexOpal.cxx new file mode 100644 index 000000000..46cf43f7c --- /dev/null +++ b/lexers/LexOpal.cxx @@ -0,0 +1,522 @@ +// Scintilla source code edit control +/** @file LexOpal.cxx + ** Lexer for OPAL (functional language similar to Haskell) + ** Written by Sebastian Pipping + **/ + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "StyleContext.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +inline static void getRange( unsigned int start, unsigned int end, Accessor & styler, char * s, unsigned int len ) +{ + unsigned int i = 0; + while( ( i < end - start + 1 ) && ( i < len - 1 ) ) + { + s[i] = static_cast( styler[ start + i ] ); + i++; + } + s[ i ] = '\0'; +} + +inline bool HandleString( unsigned int & cur, unsigned int one_too_much, Accessor & styler ) +{ + char ch; + + // Wait for string to close + bool even_backslash_count = true; // Without gaps in between + cur++; // Skip initial quote + for( ; ; ) + { + if( cur >= one_too_much ) + { + styler.ColourTo( cur - 1, SCE_OPAL_STRING ); + return false; // STOP + } + + ch = styler.SafeGetCharAt( cur ); + if( ( ch == '\015' ) || ( ch == '\012' ) ) // Deny multi-line strings + { + styler.ColourTo( cur - 1, SCE_OPAL_STRING ); + styler.StartSegment( cur ); + return true; + } + else + { + if( even_backslash_count ) + { + if( ch == '"' ) + { + styler.ColourTo( cur, SCE_OPAL_STRING ); + cur++; + if( cur >= one_too_much ) + { + return false; // STOP + } + else + { + styler.StartSegment( cur ); + return true; + } + } + else if( ch == '\\' ) + { + even_backslash_count = false; + } + } + else + { + even_backslash_count = true; + } + } + + cur++; + } +} + +inline bool HandleCommentBlock( unsigned int & cur, unsigned int one_too_much, Accessor & styler, bool could_fail ) +{ + char ch; + + if( could_fail ) + { + cur++; + if( cur >= one_too_much ) + { + styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); + return false; // STOP + } + + ch = styler.SafeGetCharAt( cur ); + if( ch != '*' ) + { + styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); + styler.StartSegment( cur ); + return true; + } + } + + // Wait for comment close + cur++; + bool star_found = false; + for( ; ; ) + { + if( cur >= one_too_much ) + { + styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_BLOCK ); + return false; // STOP + } + + ch = styler.SafeGetCharAt( cur ); + if( star_found ) + { + if( ch == '/' ) + { + styler.ColourTo( cur, SCE_OPAL_COMMENT_BLOCK ); + cur++; + if( cur >= one_too_much ) + { + return false; // STOP + } + else + { + styler.StartSegment( cur ); + return true; + } + } + else if( ch != '*' ) + { + star_found = false; + } + } + else if( ch == '*' ) + { + star_found = true; + } + cur++; + } +} + +inline bool HandleCommentLine( unsigned int & cur, unsigned int one_too_much, Accessor & styler, bool could_fail ) +{ + char ch; + + if( could_fail ) + { + cur++; + if( cur >= one_too_much ) + { + styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); + return false; // STOP + } + + ch = styler.SafeGetCharAt( cur ); + if( ch != '-' ) + { + styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); + styler.StartSegment( cur ); + return true; + } + + cur++; + if( cur >= one_too_much ) + { + styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); + return false; // STOP + } + + ch = styler.SafeGetCharAt( cur ); + if( ( ch != ' ' ) && ( ch != '\t' ) ) + { + styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); + styler.StartSegment( cur ); + return true; + } + } + + // Wait for end of line + bool fifteen_found = false; + + for( ; ; ) + { + cur++; + + if( cur >= one_too_much ) + { + styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE ); + return false; // STOP + } + + ch = styler.SafeGetCharAt( cur ); + if( fifteen_found ) + { +/* + if( ch == '\012' ) + { + // One newline on Windows (015, 012) + } + else + { + // One newline on MAC (015) and another char + } +*/ + cur--; + styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE ); + styler.StartSegment( cur ); + return true; + } + else + { + if( ch == '\015' ) + { + fifteen_found = true; + } + else if( ch == '\012' ) + { + // One newline on Linux (012) + styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE ); + styler.StartSegment( cur ); + return true; + } + } + } +} + +inline bool HandlePar( unsigned int & cur, Accessor & styler ) +{ + styler.ColourTo( cur, SCE_OPAL_PAR ); + + cur++; + + styler.StartSegment( cur ); + return true; +} + +inline bool HandleSpace( unsigned int & cur, unsigned int one_too_much, Accessor & styler ) +{ + char ch; + + cur++; + for( ; ; ) + { + if( cur >= one_too_much ) + { + styler.ColourTo( cur - 1, SCE_OPAL_SPACE ); + return false; + } + + ch = styler.SafeGetCharAt( cur ); + switch( ch ) + { + case ' ': + case '\t': + case '\015': + case '\012': + cur++; + break; + + default: + styler.ColourTo( cur - 1, SCE_OPAL_SPACE ); + styler.StartSegment( cur ); + return true; + } + } +} + +inline bool HandleInteger( unsigned int & cur, unsigned int one_too_much, Accessor & styler ) +{ + char ch; + + for( ; ; ) + { + cur++; + if( cur >= one_too_much ) + { + styler.ColourTo( cur - 1, SCE_OPAL_INTEGER ); + return false; // STOP + } + + ch = styler.SafeGetCharAt( cur ); + if( !( isascii( ch ) && isdigit( ch ) ) ) + { + styler.ColourTo( cur - 1, SCE_OPAL_INTEGER ); + styler.StartSegment( cur ); + return true; + } + } +} + +inline bool HandleWord( unsigned int & cur, unsigned int one_too_much, Accessor & styler, WordList * keywordlists[] ) +{ + char ch; + const unsigned int beg = cur; + + cur++; + for( ; ; ) + { + ch = styler.SafeGetCharAt( cur ); + if( ( ch != '_' ) && ( ch != '-' ) && + !( isascii( ch ) && ( islower( ch ) || isupper( ch ) || isdigit( ch ) ) ) ) break; + + cur++; + if( cur >= one_too_much ) + { + break; + } + } + + const int ide_len = cur - beg + 1; + char * ide = new char[ ide_len ]; + getRange( beg, cur, styler, ide, ide_len ); + + WordList & keywords = *keywordlists[ 0 ]; + WordList & classwords = *keywordlists[ 1 ]; + + if( keywords.InList( ide ) ) // Keyword + { + delete [] ide; + + styler.ColourTo( cur - 1, SCE_OPAL_KEYWORD ); + if( cur >= one_too_much ) + { + return false; // STOP + } + else + { + styler.StartSegment( cur ); + return true; + } + } + else if( classwords.InList( ide ) ) // Sort + { + delete [] ide; + + styler.ColourTo( cur - 1, SCE_OPAL_SORT ); + if( cur >= one_too_much ) + { + return false; // STOP + } + else + { + styler.StartSegment( cur ); + return true; + } + } + else if( !strcmp( ide, "true" ) || !strcmp( ide, "false" ) ) // Bool const + { + delete [] ide; + + styler.ColourTo( cur - 1, SCE_OPAL_BOOL_CONST ); + if( cur >= one_too_much ) + { + return false; // STOP + } + else + { + styler.StartSegment( cur ); + return true; + } + } + else // Unknown keyword + { + delete [] ide; + + styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); + if( cur >= one_too_much ) + { + return false; // STOP + } + else + { + styler.StartSegment( cur ); + return true; + } + } + +} + +inline bool HandleSkip( unsigned int & cur, unsigned int one_too_much, Accessor & styler ) +{ + cur++; + styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); + if( cur >= one_too_much ) + { + return false; // STOP + } + else + { + styler.StartSegment( cur ); + return true; + } +} + +static void ColouriseOpalDoc( unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor & styler ) +{ + styler.StartAt( startPos ); + styler.StartSegment( startPos ); + + unsigned int & cur = startPos; + const unsigned int one_too_much = startPos + length; + + int state = initStyle; + + for( ; ; ) + { + switch( state ) + { + case SCE_OPAL_KEYWORD: + case SCE_OPAL_SORT: + if( !HandleWord( cur, one_too_much, styler, keywordlists ) ) return; + state = SCE_OPAL_DEFAULT; + break; + + case SCE_OPAL_INTEGER: + if( !HandleInteger( cur, one_too_much, styler ) ) return; + state = SCE_OPAL_DEFAULT; + break; + + case SCE_OPAL_COMMENT_BLOCK: + if( !HandleCommentBlock( cur, one_too_much, styler, false ) ) return; + state = SCE_OPAL_DEFAULT; + break; + + case SCE_OPAL_COMMENT_LINE: + if( !HandleCommentLine( cur, one_too_much, styler, false ) ) return; + state = SCE_OPAL_DEFAULT; + break; + + case SCE_OPAL_STRING: + if( !HandleString( cur, one_too_much, styler ) ) return; + state = SCE_OPAL_DEFAULT; + break; + + default: // SCE_OPAL_DEFAULT: + { + char ch = styler.SafeGetCharAt( cur ); + + switch( ch ) + { + // String + case '"': + if( !HandleString( cur, one_too_much, styler ) ) return; + break; + + // Comment block + case '/': + if( !HandleCommentBlock( cur, one_too_much, styler, true ) ) return; + break; + + // Comment line + case '-': + if( !HandleCommentLine( cur, one_too_much, styler, true ) ) return; + break; + + // Par + case '(': + case ')': + case '[': + case ']': + case '{': + case '}': + if( !HandlePar( cur, styler ) ) return; + break; + + // Whitespace + case ' ': + case '\t': + case '\015': + case '\012': + if( !HandleSpace( cur, one_too_much, styler ) ) return; + break; + + default: + { + // Integer + if( isascii( ch ) && isdigit( ch ) ) + { + if( !HandleInteger( cur, one_too_much, styler ) ) return; + } + + // Keyword + else if( isascii( ch ) && ( islower( ch ) || isupper( ch ) ) ) + { + if( !HandleWord( cur, one_too_much, styler, keywordlists ) ) return; + + } + + // Skip + else + { + if( !HandleSkip( cur, one_too_much, styler ) ) return; + } + } + } + + break; + } + } + } +} + +static const char * const opalWordListDesc[] = { + "Keywords", + "Sorts", + 0 +}; + +LexerModule lmOpal(SCLEX_OPAL, ColouriseOpalDoc, "opal", NULL, opalWordListDesc); diff --git a/lexers/LexOthers.cxx b/lexers/LexOthers.cxx new file mode 100644 index 000000000..c8f6ca977 --- /dev/null +++ b/lexers/LexOthers.cxx @@ -0,0 +1,1286 @@ +// Scintilla source code edit control +/** @file LexOthers.cxx + ** Lexers for batch files, diff results, properties files, make files and error lists. + ** Also lexer for LaTeX documents. + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "CharClassify.h" +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static bool strstart(const char *haystack, const char *needle) { + return strncmp(haystack, needle, strlen(needle)) == 0; +} + +static bool Is0To9(char ch) { + return (ch >= '0') && (ch <= '9'); +} + +static bool Is1To9(char ch) { + return (ch >= '1') && (ch <= '9'); +} + +static bool IsAlphabetic(int ch) { + return isascii(ch) && isalpha(ch); +} + +static inline bool AtEOL(Accessor &styler, unsigned int i) { + return (styler[i] == '\n') || + ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); +} + +// Tests for BATCH Operators +static bool IsBOperator(char ch) { + return (ch == '=') || (ch == '+') || (ch == '>') || (ch == '<') || + (ch == '|') || (ch == '?') || (ch == '*'); +} + +// Tests for BATCH Separators +static bool IsBSeparator(char ch) { + return (ch == '\\') || (ch == '.') || (ch == ';') || + (ch == '\"') || (ch == '\'') || (ch == '/') || (ch == ')'); +} + +static void ColouriseBatchLine( + char *lineBuffer, + unsigned int lengthLine, + unsigned int startLine, + unsigned int endPos, + WordList *keywordlists[], + Accessor &styler) { + + unsigned int offset = 0; // Line Buffer Offset + unsigned int cmdLoc; // External Command / Program Location + char wordBuffer[81]; // Word Buffer - large to catch long paths + unsigned int wbl; // Word Buffer Length + unsigned int wbo; // Word Buffer Offset - also Special Keyword Buffer Length + WordList &keywords = *keywordlists[0]; // Internal Commands + WordList &keywords2 = *keywordlists[1]; // External Commands (optional) + + // CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords + // Toggling Regular Keyword Checking off improves readability + // Other Regular Keywords and External Commands / Programs might also benefit from toggling + // Need a more robust algorithm to properly toggle Regular Keyword Checking + bool continueProcessing = true; // Used to toggle Regular Keyword Checking + // Special Keywords are those that allow certain characters without whitespace after the command + // Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path= + // Special Keyword Buffer used to determine if the first n characters is a Keyword + char sKeywordBuffer[10]; // Special Keyword Buffer + bool sKeywordFound; // Exit Special Keyword for-loop if found + + // Skip initial spaces + while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { + offset++; + } + // Colorize Default Text + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + // Set External Command / Program Location + cmdLoc = offset; + + // Check for Fake Label (Comment) or Real Label - return if found + if (lineBuffer[offset] == ':') { + if (lineBuffer[offset + 1] == ':') { + // Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm + styler.ColourTo(endPos, SCE_BAT_COMMENT); + } else { + // Colorize Real Label + styler.ColourTo(endPos, SCE_BAT_LABEL); + } + return; + // Check for Drive Change (Drive Change is internal command) - return if found + } else if ((IsAlphabetic(lineBuffer[offset])) && + (lineBuffer[offset + 1] == ':') && + ((isspacechar(lineBuffer[offset + 2])) || + (((lineBuffer[offset + 2] == '\\')) && + (isspacechar(lineBuffer[offset + 3]))))) { + // Colorize Regular Keyword + styler.ColourTo(endPos, SCE_BAT_WORD); + return; + } + + // Check for Hide Command (@ECHO OFF/ON) + if (lineBuffer[offset] == '@') { + styler.ColourTo(startLine + offset, SCE_BAT_HIDE); + offset++; + } + // Skip next spaces + while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { + offset++; + } + + // Read remainder of line word-at-a-time or remainder-of-word-at-a-time + while (offset < lengthLine) { + if (offset > startLine) { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + } + // Copy word from Line Buffer into Word Buffer + wbl = 0; + for (; offset < lengthLine && wbl < 80 && + !isspacechar(lineBuffer[offset]); wbl++, offset++) { + wordBuffer[wbl] = static_cast(tolower(lineBuffer[offset])); + } + wordBuffer[wbl] = '\0'; + wbo = 0; + + // Check for Comment - return if found + if (CompareCaseInsensitive(wordBuffer, "rem") == 0) { + styler.ColourTo(endPos, SCE_BAT_COMMENT); + return; + } + // Check for Separator + if (IsBSeparator(wordBuffer[0])) { + // Check for External Command / Program + if ((cmdLoc == offset - wbl) && + ((wordBuffer[0] == ':') || + (wordBuffer[0] == '\\') || + (wordBuffer[0] == '.'))) { + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + // Colorize External Command / Program + if (!keywords2) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else if (keywords2.InList(wordBuffer)) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else { + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + } + // Reset External Command / Program Location + cmdLoc = offset; + } else { + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + // Colorize Default Text + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + } + // Check for Regular Keyword in list + } else if ((keywords.InList(wordBuffer)) && + (continueProcessing)) { + // ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking + if ((CompareCaseInsensitive(wordBuffer, "echo") == 0) || + (CompareCaseInsensitive(wordBuffer, "goto") == 0) || + (CompareCaseInsensitive(wordBuffer, "prompt") == 0) || + (CompareCaseInsensitive(wordBuffer, "set") == 0)) { + continueProcessing = false; + } + // Identify External Command / Program Location for ERRORLEVEL, and EXIST + if ((CompareCaseInsensitive(wordBuffer, "errorlevel") == 0) || + (CompareCaseInsensitive(wordBuffer, "exist") == 0)) { + // Reset External Command / Program Location + cmdLoc = offset; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Skip comparison + while ((cmdLoc < lengthLine) && + (!isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Identify External Command / Program Location for CALL, DO, LOADHIGH and LH + } else if ((CompareCaseInsensitive(wordBuffer, "call") == 0) || + (CompareCaseInsensitive(wordBuffer, "do") == 0) || + (CompareCaseInsensitive(wordBuffer, "loadhigh") == 0) || + (CompareCaseInsensitive(wordBuffer, "lh") == 0)) { + // Reset External Command / Program Location + cmdLoc = offset; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + } + // Colorize Regular keyword + styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD); + // No need to Reset Offset + // Check for Special Keyword in list, External Command / Program, or Default Text + } else if ((wordBuffer[0] != '%') && + (wordBuffer[0] != '!') && + (!IsBOperator(wordBuffer[0])) && + (continueProcessing)) { + // Check for Special Keyword + // Affected Commands are in Length range 2-6 + // Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected + sKeywordFound = false; + for (unsigned int keywordLength = 2; keywordLength < wbl && keywordLength < 7 && !sKeywordFound; keywordLength++) { + wbo = 0; + // Copy Keyword Length from Word Buffer into Special Keyword Buffer + for (; wbo < keywordLength; wbo++) { + sKeywordBuffer[wbo] = static_cast(wordBuffer[wbo]); + } + sKeywordBuffer[wbo] = '\0'; + // Check for Special Keyword in list + if ((keywords.InList(sKeywordBuffer)) && + ((IsBOperator(wordBuffer[wbo])) || + (IsBSeparator(wordBuffer[wbo])))) { + sKeywordFound = true; + // ECHO requires no further Regular Keyword Checking + if (CompareCaseInsensitive(sKeywordBuffer, "echo") == 0) { + continueProcessing = false; + } + // Colorize Special Keyword as Regular Keyword + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_WORD); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + } + // Check for External Command / Program or Default Text + if (!sKeywordFound) { + wbo = 0; + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + // Read up to %, Operator or Separator + while ((wbo < wbl) && + (wordBuffer[wbo] != '%') && + (wordBuffer[wbo] != '!') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo]))) { + wbo++; + } + // Reset External Command / Program Location + cmdLoc = offset - (wbl - wbo); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + // CHOICE requires no further Regular Keyword Checking + if (CompareCaseInsensitive(wordBuffer, "choice") == 0) { + continueProcessing = false; + } + // Check for START (and its switches) - What follows is External Command \ Program + if (CompareCaseInsensitive(wordBuffer, "start") == 0) { + // Reset External Command / Program Location + cmdLoc = offset; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Reset External Command / Program Location if command switch detected + if (lineBuffer[cmdLoc] == '/') { + // Skip command switch + while ((cmdLoc < lengthLine) && + (!isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + } + } + // Colorize External Command / Program + if (!keywords2) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else if (keywords2.InList(wordBuffer)) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else { + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + } + // No need to Reset Offset + // Check for Default Text + } else { + // Read up to %, Operator or Separator + while ((wbo < wbl) && + (wordBuffer[wbo] != '%') && + (wordBuffer[wbo] != '!') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo]))) { + wbo++; + } + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + } + // Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a) + } else if (wordBuffer[0] == '%') { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); + wbo++; + // Search to end of word for second % (can be a long path) + while ((wbo < wbl) && + (wordBuffer[wbo] != '%') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo]))) { + wbo++; + } + // Check for Argument (%n) or (%*) + if (((Is0To9(wordBuffer[1])) || (wordBuffer[1] == '*')) && + (wordBuffer[wbo] != '%')) { + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - 2); + } + // Colorize Argument + styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - 2); + // Check for Expanded Argument (%~...) / Variable (%%~...) + } else if (((wbl > 1) && (wordBuffer[1] == '~')) || + ((wbl > 2) && (wordBuffer[1] == '%') && (wordBuffer[2] == '~'))) { + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - wbo); + } + // Colorize Expanded Argument / Variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + // Check for Environment Variable (%x...%) + } else if ((wordBuffer[1] != '%') && + (wordBuffer[wbo] == '%')) { + wbo++; + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - wbo); + } + // Colorize Environment Variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + // Check for Local Variable (%%a) + } else if ( + (wbl > 2) && + (wordBuffer[1] == '%') && + (wordBuffer[2] != '%') && + (!IsBOperator(wordBuffer[2])) && + (!IsBSeparator(wordBuffer[2]))) { + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - 3); + } + // Colorize Local Variable + styler.ColourTo(startLine + offset - 1 - (wbl - 3), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - 3); + } + // Check for Environment Variable (!x...!) + } else if (wordBuffer[0] == '!') { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); + wbo++; + // Search to end of word for second ! (can be a long path) + while ((wbo < wbl) && + (wordBuffer[wbo] != '!') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo]))) { + wbo++; + } + if (wordBuffer[wbo] == '!') { + wbo++; + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - wbo); + } + // Colorize Environment Variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + // Check for Operator + } else if (IsBOperator(wordBuffer[0])) { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); + // Check for Comparison Operator + if ((wordBuffer[0] == '=') && (wordBuffer[1] == '=')) { + // Identify External Command / Program Location for IF + cmdLoc = offset; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Colorize Comparison Operator + styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_OPERATOR); + // Reset Offset to re-process remainder of word + offset -= (wbl - 2); + // Check for Pipe Operator + } else if (wordBuffer[0] == '|') { + // Reset External Command / Program Location + cmdLoc = offset - wbl + 1; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Colorize Pipe Operator + styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + // Check for Other Operator + } else { + // Check for > Operator + if (wordBuffer[0] == '>') { + // Turn Keyword and External Command / Program checking back on + continueProcessing = true; + } + // Colorize Other Operator + styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + } + // Check for Default Text + } else { + // Read up to %, Operator or Separator + while ((wbo < wbl) && + (wordBuffer[wbo] != '%') && + (wordBuffer[wbo] != '!') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo]))) { + wbo++; + } + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + // Skip next spaces - nothing happens if Offset was Reset + while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { + offset++; + } + } + // Colorize Default Text for remainder of line - currently not lexed + styler.ColourTo(endPos, SCE_BAT_DEFAULT); +} + +static void ColouriseBatchDoc( + unsigned int startPos, + int length, + int /*initStyle*/, + WordList *keywordlists[], + Accessor &styler) { + + char lineBuffer[1024]; + + styler.StartAt(startPos); + styler.StartSegment(startPos); + unsigned int linePos = 0; + unsigned int startLine = startPos; + for (unsigned int i = startPos; i < startPos + length; i++) { + lineBuffer[linePos++] = styler[i]; + if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { + // End of line (or of line buffer) met, colourise it + lineBuffer[linePos] = '\0'; + ColouriseBatchLine(lineBuffer, linePos, startLine, i, keywordlists, styler); + linePos = 0; + startLine = i + 1; + } + } + if (linePos > 0) { // Last line does not have ending characters + lineBuffer[linePos] = '\0'; + ColouriseBatchLine(lineBuffer, linePos, startLine, startPos + length - 1, + keywordlists, styler); + } +} + +static void ColouriseDiffLine(char *lineBuffer, int endLine, Accessor &styler) { + // It is needed to remember the current state to recognize starting + // comment lines before the first "diff " or "--- ". If a real + // difference starts then each line starting with ' ' is a whitespace + // otherwise it is considered a comment (Only in..., Binary file...) + if (0 == strncmp(lineBuffer, "diff ", 5)) { + styler.ColourTo(endLine, SCE_DIFF_COMMAND); + } else if (0 == strncmp(lineBuffer, "Index: ", 7)) { // For subversion's diff + styler.ColourTo(endLine, SCE_DIFF_COMMAND); + } else if (0 == strncmp(lineBuffer, "---", 3)) { + // In a context diff, --- appears in both the header and the position markers + if (lineBuffer[3] == ' ' && atoi(lineBuffer + 4) && !strchr(lineBuffer, '/')) + styler.ColourTo(endLine, SCE_DIFF_POSITION); + else if (lineBuffer[3] == '\r' || lineBuffer[3] == '\n') + styler.ColourTo(endLine, SCE_DIFF_POSITION); + else + styler.ColourTo(endLine, SCE_DIFF_HEADER); + } else if (0 == strncmp(lineBuffer, "+++ ", 4)) { + // I don't know of any diff where "+++ " is a position marker, but for + // consistency, do the same as with "--- " and "*** ". + if (atoi(lineBuffer+4) && !strchr(lineBuffer, '/')) + styler.ColourTo(endLine, SCE_DIFF_POSITION); + else + styler.ColourTo(endLine, SCE_DIFF_HEADER); + } else if (0 == strncmp(lineBuffer, "====", 4)) { // For p4's diff + styler.ColourTo(endLine, SCE_DIFF_HEADER); + } else if (0 == strncmp(lineBuffer, "***", 3)) { + // In a context diff, *** appears in both the header and the position markers. + // Also ******** is a chunk header, but here it's treated as part of the + // position marker since there is no separate style for a chunk header. + if (lineBuffer[3] == ' ' && atoi(lineBuffer+4) && !strchr(lineBuffer, '/')) + styler.ColourTo(endLine, SCE_DIFF_POSITION); + else if (lineBuffer[3] == '*') + styler.ColourTo(endLine, SCE_DIFF_POSITION); + else + styler.ColourTo(endLine, SCE_DIFF_HEADER); + } else if (0 == strncmp(lineBuffer, "? ", 2)) { // For difflib + styler.ColourTo(endLine, SCE_DIFF_HEADER); + } else if (lineBuffer[0] == '@') { + styler.ColourTo(endLine, SCE_DIFF_POSITION); + } else if (lineBuffer[0] >= '0' && lineBuffer[0] <= '9') { + styler.ColourTo(endLine, SCE_DIFF_POSITION); + } else if (lineBuffer[0] == '-' || lineBuffer[0] == '<') { + styler.ColourTo(endLine, SCE_DIFF_DELETED); + } else if (lineBuffer[0] == '+' || lineBuffer[0] == '>') { + styler.ColourTo(endLine, SCE_DIFF_ADDED); + } else if (lineBuffer[0] == '!') { + styler.ColourTo(endLine, SCE_DIFF_CHANGED); + } else if (lineBuffer[0] != ' ') { + styler.ColourTo(endLine, SCE_DIFF_COMMENT); + } else { + styler.ColourTo(endLine, SCE_DIFF_DEFAULT); + } +} + +static void ColouriseDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + char lineBuffer[1024]; + styler.StartAt(startPos); + styler.StartSegment(startPos); + unsigned int linePos = 0; + for (unsigned int i = startPos; i < startPos + length; i++) { + lineBuffer[linePos++] = styler[i]; + if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { + // End of line (or of line buffer) met, colourise it + lineBuffer[linePos] = '\0'; + ColouriseDiffLine(lineBuffer, i, styler); + linePos = 0; + } + } + if (linePos > 0) { // Last line does not have ending characters + ColouriseDiffLine(lineBuffer, startPos + length - 1, styler); + } +} + +static void FoldDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + int curLine = styler.GetLine(startPos); + int curLineStart = styler.LineStart(curLine); + int prevLevel = curLine > 0 ? styler.LevelAt(curLine - 1) : SC_FOLDLEVELBASE; + int nextLevel; + + do { + int lineType = styler.StyleAt(curLineStart); + if (lineType == SCE_DIFF_COMMAND) + nextLevel = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; + else if (lineType == SCE_DIFF_HEADER) + nextLevel = (SC_FOLDLEVELBASE + 1) | SC_FOLDLEVELHEADERFLAG; + else if (lineType == SCE_DIFF_POSITION && styler[curLineStart] != '-') + nextLevel = (SC_FOLDLEVELBASE + 2) | SC_FOLDLEVELHEADERFLAG; + else if (prevLevel & SC_FOLDLEVELHEADERFLAG) + nextLevel = (prevLevel & SC_FOLDLEVELNUMBERMASK) + 1; + else + nextLevel = prevLevel; + + if ((nextLevel & SC_FOLDLEVELHEADERFLAG) && (nextLevel == prevLevel)) + styler.SetLevel(curLine-1, prevLevel & ~SC_FOLDLEVELHEADERFLAG); + + styler.SetLevel(curLine, nextLevel); + prevLevel = nextLevel; + + curLineStart = styler.LineStart(++curLine); + } while (static_cast(startPos) + length > curLineStart); +} + +static void ColourisePoLine( + char *lineBuffer, + unsigned int lengthLine, + unsigned int startLine, + unsigned int endPos, + Accessor &styler) { + + unsigned int i = 0; + static unsigned int state = SCE_PO_DEFAULT; + unsigned int state_start = SCE_PO_DEFAULT; + + while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces + i++; + if (i < lengthLine) { + if (lineBuffer[i] == '#') { + // check if the comment contains any flags ("#, ") and + // then whether the flags contain "fuzzy" + if (strstart(lineBuffer, "#, ") && strstr(lineBuffer, "fuzzy")) + styler.ColourTo(endPos, SCE_PO_FUZZY); + else + styler.ColourTo(endPos, SCE_PO_COMMENT); + } else { + if (lineBuffer[0] == '"') { + // line continuation, use previous style + styler.ColourTo(endPos, state); + return; + // this implicitly also matches "msgid_plural" + } else if (strstart(lineBuffer, "msgid")) { + state_start = SCE_PO_MSGID; + state = SCE_PO_MSGID_TEXT; + } else if (strstart(lineBuffer, "msgstr")) { + state_start = SCE_PO_MSGSTR; + state = SCE_PO_MSGSTR_TEXT; + } else if (strstart(lineBuffer, "msgctxt")) { + state_start = SCE_PO_MSGCTXT; + state = SCE_PO_MSGCTXT_TEXT; + } + if (state_start != SCE_PO_DEFAULT) { + // find the next space + while ((i < lengthLine) && ! isspacechar(lineBuffer[i])) + i++; + styler.ColourTo(startLine + i - 1, state_start); + styler.ColourTo(startLine + i, SCE_PO_DEFAULT); + styler.ColourTo(endPos, state); + } + } + } else { + styler.ColourTo(endPos, SCE_PO_DEFAULT); + } +} + +static void ColourisePoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + char lineBuffer[1024]; + styler.StartAt(startPos); + styler.StartSegment(startPos); + unsigned int linePos = 0; + unsigned int startLine = startPos; + for (unsigned int i = startPos; i < startPos + length; i++) { + lineBuffer[linePos++] = styler[i]; + if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { + // End of line (or of line buffer) met, colourise it + lineBuffer[linePos] = '\0'; + ColourisePoLine(lineBuffer, linePos, startLine, i, styler); + linePos = 0; + startLine = i + 1; + } + } + if (linePos > 0) { // Last line does not have ending characters + ColourisePoLine(lineBuffer, linePos, startLine, startPos + length - 1, styler); + } +} + +static inline bool isassignchar(unsigned char ch) { + return (ch == '=') || (ch == ':'); +} + +static void ColourisePropsLine( + char *lineBuffer, + unsigned int lengthLine, + unsigned int startLine, + unsigned int endPos, + Accessor &styler, + bool allowInitialSpaces) { + + unsigned int i = 0; + if (allowInitialSpaces) { + while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces + i++; + } else { + if (isspacechar(lineBuffer[i])) // don't allow initial spaces + i = lengthLine; + } + + if (i < lengthLine) { + if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') { + styler.ColourTo(endPos, SCE_PROPS_COMMENT); + } else if (lineBuffer[i] == '[') { + styler.ColourTo(endPos, SCE_PROPS_SECTION); + } else if (lineBuffer[i] == '@') { + styler.ColourTo(startLine + i, SCE_PROPS_DEFVAL); + if (isassignchar(lineBuffer[i++])) + styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT); + styler.ColourTo(endPos, SCE_PROPS_DEFAULT); + } else { + // Search for the '=' character + while ((i < lengthLine) && !isassignchar(lineBuffer[i])) + i++; + if ((i < lengthLine) && isassignchar(lineBuffer[i])) { + styler.ColourTo(startLine + i - 1, SCE_PROPS_KEY); + styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT); + styler.ColourTo(endPos, SCE_PROPS_DEFAULT); + } else { + styler.ColourTo(endPos, SCE_PROPS_DEFAULT); + } + } + } else { + styler.ColourTo(endPos, SCE_PROPS_DEFAULT); + } +} + +static void ColourisePropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + char lineBuffer[1024]; + styler.StartAt(startPos); + styler.StartSegment(startPos); + unsigned int linePos = 0; + unsigned int startLine = startPos; + + // property lexer.props.allow.initial.spaces + // For properties files, set to 0 to style all lines that start with whitespace in the default style. + // This is not suitable for SciTE .properties files which use indentation for flow control but + // can be used for RFC2822 text where indentation is used for continuation lines. + bool allowInitialSpaces = styler.GetPropertyInt("lexer.props.allow.initial.spaces", 1) != 0; + + for (unsigned int i = startPos; i < startPos + length; i++) { + lineBuffer[linePos++] = styler[i]; + if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { + // End of line (or of line buffer) met, colourise it + lineBuffer[linePos] = '\0'; + ColourisePropsLine(lineBuffer, linePos, startLine, i, styler, allowInitialSpaces); + linePos = 0; + startLine = i + 1; + } + } + if (linePos > 0) { // Last line does not have ending characters + ColourisePropsLine(lineBuffer, linePos, startLine, startPos + length - 1, styler, allowInitialSpaces); + } +} + +// adaption by ksc, using the "} else {" trick of 1.53 +// 030721 +static void FoldPropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + bool headerPoint = false; + int lev; + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler[i+1]; + + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (style == SCE_PROPS_SECTION) { + headerPoint = true; + } + + if (atEOL) { + lev = SC_FOLDLEVELBASE; + + if (lineCurrent > 0) { + int levelPrevious = styler.LevelAt(lineCurrent - 1); + + if (levelPrevious & SC_FOLDLEVELHEADERFLAG) { + lev = SC_FOLDLEVELBASE + 1; + } else { + lev = levelPrevious & SC_FOLDLEVELNUMBERMASK; + } + } + + if (headerPoint) { + lev = SC_FOLDLEVELBASE; + } + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + + if (headerPoint) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + + lineCurrent++; + visibleChars = 0; + headerPoint = false; + } + if (!isspacechar(ch)) + visibleChars++; + } + + if (lineCurrent > 0) { + int levelPrevious = styler.LevelAt(lineCurrent - 1); + if (levelPrevious & SC_FOLDLEVELHEADERFLAG) { + lev = SC_FOLDLEVELBASE + 1; + } else { + lev = levelPrevious & SC_FOLDLEVELNUMBERMASK; + } + } else { + lev = SC_FOLDLEVELBASE; + } + int flagsNext = styler.LevelAt(lineCurrent); + styler.SetLevel(lineCurrent, lev | (flagsNext & ~SC_FOLDLEVELNUMBERMASK)); +} + +static void ColouriseMakeLine( + char *lineBuffer, + unsigned int lengthLine, + unsigned int startLine, + unsigned int endPos, + Accessor &styler) { + + unsigned int i = 0; + int lastNonSpace = -1; + unsigned int state = SCE_MAKE_DEFAULT; + bool bSpecial = false; + + // check for a tab character in column 0 indicating a command + bool bCommand = false; + if ((lengthLine > 0) && (lineBuffer[0] == '\t')) + bCommand = true; + + // Skip initial spaces + while ((i < lengthLine) && isspacechar(lineBuffer[i])) { + i++; + } + if (lineBuffer[i] == '#') { // Comment + styler.ColourTo(endPos, SCE_MAKE_COMMENT); + return; + } + if (lineBuffer[i] == '!') { // Special directive + styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR); + return; + } + while (i < lengthLine) { + if (lineBuffer[i] == '$' && lineBuffer[i + 1] == '(') { + styler.ColourTo(startLine + i - 1, state); + state = SCE_MAKE_IDENTIFIER; + } else if (state == SCE_MAKE_IDENTIFIER && lineBuffer[i] == ')') { + styler.ColourTo(startLine + i, state); + state = SCE_MAKE_DEFAULT; + } + + // skip identifier and target styling if this is a command line + if (!bSpecial && !bCommand) { + if (lineBuffer[i] == ':') { + if (((i + 1) < lengthLine) && (lineBuffer[i + 1] == '=')) { + // it's a ':=', so style as an identifier + if (lastNonSpace >= 0) + styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER); + styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); + styler.ColourTo(startLine + i + 1, SCE_MAKE_OPERATOR); + } else { + // We should check that no colouring was made since the beginning of the line, + // to avoid colouring stuff like /OUT:file + if (lastNonSpace >= 0) + styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_TARGET); + styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); + styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR); + } + bSpecial = true; // Only react to the first ':' of the line + state = SCE_MAKE_DEFAULT; + } else if (lineBuffer[i] == '=') { + if (lastNonSpace >= 0) + styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER); + styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); + styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR); + bSpecial = true; // Only react to the first '=' of the line + state = SCE_MAKE_DEFAULT; + } + } + if (!isspacechar(lineBuffer[i])) { + lastNonSpace = i; + } + i++; + } + if (state == SCE_MAKE_IDENTIFIER) { + styler.ColourTo(endPos, SCE_MAKE_IDEOL); // Error, variable reference not ended + } else { + styler.ColourTo(endPos, SCE_MAKE_DEFAULT); + } +} + +static void ColouriseMakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + char lineBuffer[1024]; + styler.StartAt(startPos); + styler.StartSegment(startPos); + unsigned int linePos = 0; + unsigned int startLine = startPos; + for (unsigned int i = startPos; i < startPos + length; i++) { + lineBuffer[linePos++] = styler[i]; + if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { + // End of line (or of line buffer) met, colourise it + lineBuffer[linePos] = '\0'; + ColouriseMakeLine(lineBuffer, linePos, startLine, i, styler); + linePos = 0; + startLine = i + 1; + } + } + if (linePos > 0) { // Last line does not have ending characters + ColouriseMakeLine(lineBuffer, linePos, startLine, startPos + length - 1, styler); + } +} + +static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLine, int &startValue) { + if (lineBuffer[0] == '>') { + // Command or return status + return SCE_ERR_CMD; + } else if (lineBuffer[0] == '<') { + // Diff removal, but not interested. Trapped to avoid hitting CTAG cases. + return SCE_ERR_DEFAULT; + } else if (lineBuffer[0] == '!') { + return SCE_ERR_DIFF_CHANGED; + } else if (lineBuffer[0] == '+') { + if (strstart(lineBuffer, "+++ ")) { + return SCE_ERR_DIFF_MESSAGE; + } else { + return SCE_ERR_DIFF_ADDITION; + } + } else if (lineBuffer[0] == '-') { + if (strstart(lineBuffer, "--- ")) { + return SCE_ERR_DIFF_MESSAGE; + } else { + return SCE_ERR_DIFF_DELETION; + } + } else if (strstart(lineBuffer, "cf90-")) { + // Absoft Pro Fortran 90/95 v8.2 error and/or warning message + return SCE_ERR_ABSF; + } else if (strstart(lineBuffer, "fortcom:")) { + // Intel Fortran Compiler v8.0 error/warning message + return SCE_ERR_IFORT; + } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) { + return SCE_ERR_PYTHON; + } else if (strstr(lineBuffer, " in ") && strstr(lineBuffer, " on line ")) { + return SCE_ERR_PHP; + } else if ((strstart(lineBuffer, "Error ") || + strstart(lineBuffer, "Warning ")) && + strstr(lineBuffer, " at (") && + strstr(lineBuffer, ") : ") && + (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) { + // Intel Fortran Compiler error/warning message + return SCE_ERR_IFC; + } else if (strstart(lineBuffer, "Error ")) { + // Borland error message + return SCE_ERR_BORLAND; + } else if (strstart(lineBuffer, "Warning ")) { + // Borland warning message + return SCE_ERR_BORLAND; + } else if (strstr(lineBuffer, "at line ") && + (strstr(lineBuffer, "at line ") < (lineBuffer + lengthLine)) && + strstr(lineBuffer, "file ") && + (strstr(lineBuffer, "file ") < (lineBuffer + lengthLine))) { + // Lua 4 error message + return SCE_ERR_LUA; + } else if (strstr(lineBuffer, " at ") && + (strstr(lineBuffer, " at ") < (lineBuffer + lengthLine)) && + strstr(lineBuffer, " line ") && + (strstr(lineBuffer, " line ") < (lineBuffer + lengthLine)) && + (strstr(lineBuffer, " at ") < (strstr(lineBuffer, " line ")))) { + // perl error message + return SCE_ERR_PERL; + } else if ((memcmp(lineBuffer, " at ", 6) == 0) && + strstr(lineBuffer, ":line ")) { + // A .NET traceback + return SCE_ERR_NET; + } else if (strstart(lineBuffer, "Line ") && + strstr(lineBuffer, ", file ")) { + // Essential Lahey Fortran error message + return SCE_ERR_ELF; + } else if (strstart(lineBuffer, "line ") && + strstr(lineBuffer, " column ")) { + // HTML tidy style: line 42 column 1 + return SCE_ERR_TIDY; + } else if (strstart(lineBuffer, "\tat ") && + strstr(lineBuffer, "(") && + strstr(lineBuffer, ".java:")) { + // Java stack back trace + return SCE_ERR_JAVA_STACK; + } else { + // Look for one of the following formats: + // GCC: :: + // Microsoft: () : + // Common: (): warning|error|note|remark|catastrophic|fatal + // Common: () warning|error|note|remark|catastrophic|fatal + // Microsoft: (,) + // CTags: \t + // Lua 5 traceback: \t:: + // Lua 5.1: : :: + bool initialTab = (lineBuffer[0] == '\t'); + bool initialColonPart = false; + enum { stInitial, + stGccStart, stGccDigit, stGcc, + stMsStart, stMsDigit, stMsBracket, stMsVc, stMsDigitComma, stMsDotNet, + stCtagsStart, stCtagsStartString, stCtagsStringDollar, stCtags, + stUnrecognized + } state = stInitial; + for (unsigned int i = 0; i < lengthLine; i++) { + char ch = lineBuffer[i]; + char chNext = ' '; + if ((i + 1) < lengthLine) + chNext = lineBuffer[i + 1]; + if (state == stInitial) { + if (ch == ':') { + // May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix) + if ((chNext != '\\') && (chNext != '/') && (chNext != ' ')) { + // This check is not completely accurate as may be on + // GTK+ with a file name that includes ':'. + state = stGccStart; + } else if (chNext == ' ') { // indicates a Lua 5.1 error message + initialColonPart = true; + } + } else if ((ch == '(') && Is1To9(chNext) && (!initialTab)) { + // May be Microsoft + // Check against '0' often removes phone numbers + state = stMsStart; + } else if ((ch == '\t') && (!initialTab)) { + // May be CTags + state = stCtagsStart; + } + } else if (state == stGccStart) { // : + state = Is1To9(ch) ? stGccDigit : stUnrecognized; + } else if (state == stGccDigit) { // : + if (ch == ':') { + state = stGcc; // :9.*: is GCC + startValue = i + 1; + break; + } else if (!Is0To9(ch)) { + state = stUnrecognized; + } + } else if (state == stMsStart) { // ( + state = Is0To9(ch) ? stMsDigit : stUnrecognized; + } else if (state == stMsDigit) { // ( + if (ch == ',') { + state = stMsDigitComma; + } else if (ch == ')') { + state = stMsBracket; + } else if ((ch != ' ') && !Is0To9(ch)) { + state = stUnrecognized; + } + } else if (state == stMsBracket) { // () + if ((ch == ' ') && (chNext == ':')) { + state = stMsVc; + } else if ((ch == ':' && chNext == ' ') || (ch == ' ')) { + // Possibly Delphi.. don't test against chNext as it's one of the strings below. + char word[512]; + unsigned int j, chPos; + unsigned numstep; + chPos = 0; + if (ch == ' ') + numstep = 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i. + else + numstep = 2; // otherwise add 2. + for (j = i + numstep; j < lengthLine && IsAlphabetic(lineBuffer[j]) && chPos < sizeof(word) - 1; j++) + word[chPos++] = lineBuffer[j]; + word[chPos] = 0; + if (!CompareCaseInsensitive(word, "error") || !CompareCaseInsensitive(word, "warning") || + !CompareCaseInsensitive(word, "fatal") || !CompareCaseInsensitive(word, "catastrophic") || + !CompareCaseInsensitive(word, "note") || !CompareCaseInsensitive(word, "remark")) { + state = stMsVc; + } else + state = stUnrecognized; + } else { + state = stUnrecognized; + } + } else if (state == stMsDigitComma) { // (, + if (ch == ')') { + state = stMsDotNet; + break; + } else if ((ch != ' ') && !Is0To9(ch)) { + state = stUnrecognized; + } + } else if (state == stCtagsStart) { + if ((lineBuffer[i - 1] == '\t') && + ((ch == '/' && lineBuffer[i + 1] == '^') || Is0To9(ch))) { + state = stCtags; + break; + } else if ((ch == '/') && (lineBuffer[i + 1] == '^')) { + state = stCtagsStartString; + } + } else if ((state == stCtagsStartString) && ((lineBuffer[i] == '$') && (lineBuffer[i + 1] == '/'))) { + state = stCtagsStringDollar; + break; + } + } + if (state == stGcc) { + return initialColonPart ? SCE_ERR_LUA : SCE_ERR_GCC; + } else if ((state == stMsVc) || (state == stMsDotNet)) { + return SCE_ERR_MS; + } else if ((state == stCtagsStringDollar) || (state == stCtags)) { + return SCE_ERR_CTAG; + } else { + return SCE_ERR_DEFAULT; + } + } +} + +static void ColouriseErrorListLine( + char *lineBuffer, + unsigned int lengthLine, + unsigned int endPos, + Accessor &styler, + bool valueSeparate) { + int startValue = -1; + int style = RecogniseErrorListLine(lineBuffer, lengthLine, startValue); + if (valueSeparate && (startValue >= 0)) { + styler.ColourTo(endPos - (lengthLine - startValue), style); + styler.ColourTo(endPos, SCE_ERR_VALUE); + } else { + styler.ColourTo(endPos, style); + } +} + +static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + char lineBuffer[10000]; + styler.StartAt(startPos); + styler.StartSegment(startPos); + unsigned int linePos = 0; + + // property lexer.errorlist.value.separate + // For lines in the output pane that are matches from Find in Files or GCC-style + // diagnostics, style the path and line number separately from the rest of the + // line with style 21 used for the rest of the line. + // This allows matched text to be more easily distinguished from its location. + bool valueSeparate = styler.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0; + for (unsigned int i = startPos; i < startPos + length; i++) { + lineBuffer[linePos++] = styler[i]; + if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { + // End of line (or of line buffer) met, colourise it + lineBuffer[linePos] = '\0'; + ColouriseErrorListLine(lineBuffer, linePos, i, styler, valueSeparate); + linePos = 0; + } + } + if (linePos > 0) { // Last line does not have ending characters + ColouriseErrorListLine(lineBuffer, linePos, startPos + length - 1, styler, valueSeparate); + } +} + +static int isSpecial(char s) { + return (s == '\\') || (s == ',') || (s == ';') || (s == '\'') || (s == ' ') || + (s == '\"') || (s == '`') || (s == '^') || (s == '~'); +} + +static int isTag(int start, Accessor &styler) { + char s[6]; + unsigned int i = 0, e = 1; + while (i < 5 && e) { + s[i] = styler[start + i]; + i++; + e = styler[start + i] != '{'; + } + s[i] = '\0'; + return (strcmp(s, "begin") == 0) || (strcmp(s, "end") == 0); +} + +static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle, + WordList *[], Accessor &styler) { + + styler.StartAt(startPos); + + int state = initStyle; + char chNext = styler[startPos]; + styler.StartSegment(startPos); + int lengthDoc = startPos + length; + + for (int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + i++; + continue; + } + switch (state) { + case SCE_L_DEFAULT : + switch (ch) { + case '\\' : + styler.ColourTo(i - 1, state); + if (isSpecial(styler[i + 1])) { + styler.ColourTo(i + 1, SCE_L_COMMAND); + i++; + chNext = styler.SafeGetCharAt(i + 1); + } else { + if (isTag(i + 1, styler)) + state = SCE_L_TAG; + else + state = SCE_L_COMMAND; + } + break; + case '$' : + styler.ColourTo(i - 1, state); + state = SCE_L_MATH; + if (chNext == '$') { + i++; + chNext = styler.SafeGetCharAt(i + 1); + } + break; + case '%' : + styler.ColourTo(i - 1, state); + state = SCE_L_COMMENT; + break; + } + break; + case SCE_L_COMMAND : + if (chNext == '[' || chNext == '{' || chNext == '}' || + chNext == ' ' || chNext == '\r' || chNext == '\n') { + styler.ColourTo(i, state); + state = SCE_L_DEFAULT; + i++; + chNext = styler.SafeGetCharAt(i + 1); + } + break; + case SCE_L_TAG : + if (ch == '}') { + styler.ColourTo(i, state); + state = SCE_L_DEFAULT; + } + break; + case SCE_L_MATH : + if (ch == '$') { + if (chNext == '$') { + i++; + chNext = styler.SafeGetCharAt(i + 1); + } + styler.ColourTo(i, state); + state = SCE_L_DEFAULT; + } + break; + case SCE_L_COMMENT : + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, state); + state = SCE_L_DEFAULT; + } + } + } + styler.ColourTo(lengthDoc-1, state); +} + +static const char *const batchWordListDesc[] = { + "Internal Commands", + "External Commands", + 0 +}; + +static const char *const emptyWordListDesc[] = { + 0 +}; + +static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[], + Accessor &styler) { + // Null language means all style bytes are 0 so just mark the end - no need to fill in. + if (length > 0) { + styler.StartAt(startPos + length - 1); + styler.StartSegment(startPos + length - 1); + styler.ColourTo(startPos + length - 1, 0); + } +} + +LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", 0, batchWordListDesc); +LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", FoldDiffDoc, emptyWordListDesc); +LexerModule lmPo(SCLEX_PO, ColourisePoDoc, "po", 0, emptyWordListDesc); +LexerModule lmProps(SCLEX_PROPERTIES, ColourisePropsDoc, "props", FoldPropsDoc, emptyWordListDesc); +LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc); +LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", 0, emptyWordListDesc); +LexerModule lmLatex(SCLEX_LATEX, ColouriseLatexDoc, "latex", 0, emptyWordListDesc); +LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null"); diff --git a/lexers/LexPB.cxx b/lexers/LexPB.cxx new file mode 100644 index 000000000..abc0ddc79 --- /dev/null +++ b/lexers/LexPB.cxx @@ -0,0 +1,362 @@ +// Scintilla source code edit control +// @file LexPB.cxx +// Lexer for PowerBasic by Roland Walter, roland@rowalt.de (for PowerBasic see www.powerbasic.com) +// +// Changes: +// 17.10.2003: Toggling of subs/functions now until next sub/function - this gives better results +// 29.10.2003: 1. Bug: Toggling didn't work for subs/functions added in editor +// 2. Own colors for PB constants and Inline Assembler SCE_B_CONSTANT and SCE_B_ASM +// 3. Several smaller syntax coloring improvements and speed optimizations +// 12.07.2004: 1. Toggling for macros added +// 2. Further folding speed optimitations (for people dealing with very large listings) +// +// Necessary changes for the PB lexer in Scintilla project: +// - In SciLexer.h and Scintilla.iface: +// +// #define SCLEX_POWERBASIC 51 //ID for PowerBasic lexer +// (...) +// #define SCE_B_DEFAULT 0 //in both VB and PB lexer +// #define SCE_B_COMMENT 1 //in both VB and PB lexer +// #define SCE_B_NUMBER 2 //in both VB and PB lexer +// #define SCE_B_KEYWORD 3 //in both VB and PB lexer +// #define SCE_B_STRING 4 //in both VB and PB lexer +// #define SCE_B_PREPROCESSOR 5 //VB lexer only, not in PB lexer +// #define SCE_B_OPERATOR 6 //in both VB and PB lexer +// #define SCE_B_IDENTIFIER 7 //in both VB and PB lexer +// #define SCE_B_DATE 8 //VB lexer only, not in PB lexer +// #define SCE_B_CONSTANT 13 //PB lexer only, not in VB lexer +// #define SCE_B_ASM 14 //PB lexer only, not in VB lexer + +// - Statement added to KeyWords.cxx: 'LINK_LEXER(lmPB);' +// - Statement added to scintilla_vc6.mak: '$(DIR_O)\LexPB.obj: ...\src\LexPB.cxx $(LEX_HEADERS)' +// +// Copyright for Scintilla: 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsTypeCharacter(const int ch) +{ + return ch == '%' || ch == '&' || ch == '@' || ch == '!' || ch == '#' || ch == '$' || ch == '?'; +} + +static inline bool IsAWordChar(const int ch) +{ + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); +} + +static inline bool IsAWordStart(const int ch) +{ + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +bool MatchUpperCase(Accessor &styler, int pos, const char *s) //Same as styler.Match() but uppercase comparison (a-z,A-Z and space only) +{ + char ch; + for (int i=0; *s; i++) + { + ch=styler.SafeGetCharAt(pos+i); + if (ch > 0x60) ch -= '\x20'; + if (*s != ch) return false; + s++; + } + return true; +} + +static void ColourisePBDoc(unsigned int startPos, int length, int initStyle,WordList *keywordlists[],Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + + styler.StartAt(startPos); + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + switch (sc.state) + { + case SCE_B_OPERATOR: + { + sc.SetState(SCE_B_DEFAULT); + break; + } + case SCE_B_KEYWORD: + { + if (!IsAWordChar(sc.ch)) + { + if (!IsTypeCharacter(sc.ch)) + { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) + { + if (strcmp(s, "rem") == 0) + { + sc.ChangeState(SCE_B_COMMENT); + if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);} + } + else if (strcmp(s, "asm") == 0) + { + sc.ChangeState(SCE_B_ASM); + if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);} + } + else + { + sc.SetState(SCE_B_DEFAULT); + } + } + else + { + sc.ChangeState(SCE_B_IDENTIFIER); + sc.SetState(SCE_B_DEFAULT); + } + } + } + break; + } + case SCE_B_NUMBER: + { + if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_B_DEFAULT);} + break; + } + case SCE_B_STRING: + { + if (sc.ch == '\"'){sc.ForwardSetState(SCE_B_DEFAULT);} + break; + } + case SCE_B_CONSTANT: + { + if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_B_DEFAULT);} + break; + } + case SCE_B_COMMENT: + { + if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);} + break; + } + case SCE_B_ASM: + { + if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);} + break; + } + } //switch (sc.state) + + // Determine if a new state should be entered: + if (sc.state == SCE_B_DEFAULT) + { + if (sc.ch == '\'') {sc.SetState(SCE_B_COMMENT);} + else if (sc.ch == '\"') {sc.SetState(SCE_B_STRING);} + else if (sc.ch == '&' && tolower(sc.chNext) == 'h') {sc.SetState(SCE_B_NUMBER);} + else if (sc.ch == '&' && tolower(sc.chNext) == 'b') {sc.SetState(SCE_B_NUMBER);} + else if (sc.ch == '&' && tolower(sc.chNext) == 'o') {sc.SetState(SCE_B_NUMBER);} + else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {sc.SetState(SCE_B_NUMBER);} + else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_B_KEYWORD);} + else if (sc.ch == '%') {sc.SetState(SCE_B_CONSTANT);} + else if (sc.ch == '$') {sc.SetState(SCE_B_CONSTANT);} + else if (sc.ch == '#') {sc.SetState(SCE_B_KEYWORD);} + else if (sc.ch == '!') {sc.SetState(SCE_B_ASM);} + else if (isoperator(static_cast(sc.ch)) || (sc.ch == '\\')) {sc.SetState(SCE_B_OPERATOR);} + } + } //for (; sc.More(); sc.Forward()) + sc.Complete(); +} + +//The folding routine for PowerBasic toggles SUBs and FUNCTIONs only. This was exactly what I wanted, +//nothing more. I had worked with this kind of toggling for several years when I used the great good old +//GFA Basic which is dead now. After testing the feature of toggling FOR-NEXT loops, WHILE-WEND loops +//and so on too I found this is more disturbing then helping (for me). So if You think in another way +//you can (or must) write Your own toggling routine ;-) +static void FoldPBDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) +{ + // No folding enabled, no reason to continue... + if( styler.GetPropertyInt("fold") == 0 ) + return; + + unsigned int endPos = startPos + length; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + + bool fNewLine=true; + bool fMightBeMultiLineMacro=false; + bool fBeginOfCommentFound=false; + for (unsigned int i = startPos; i < endPos; i++) + { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if (fNewLine) //Begin of a new line (The Sub/Function/Macro keywords may occur at begin of line only) + { + fNewLine=false; + fBeginOfCommentFound=false; + switch (ch) + { + case ' ': //Most lines start with space - so check this first, the code is the same as for 'default:' + case '\t': //Handle tab too + { + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + styler.SetLevel(lineCurrent, lev); + break; + } + case 'F': + case 'f': + { + switch (chNext) + { + case 'U': + case 'u': + { + if( MatchUpperCase(styler,i,"FUNCTION") ) + { + styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG); + levelNext=SC_FOLDLEVELBASE+1; + } + break; + } + } + break; + } + case 'S': + case 's': + { + switch (chNext) + { + case 'U': + case 'u': + { + if( MatchUpperCase(styler,i,"SUB") ) + { + styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG); + levelNext=SC_FOLDLEVELBASE+1; + } + break; + } + case 'T': + case 't': + { + if( MatchUpperCase(styler,i,"STATIC FUNCTION") ) + { + styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG); + levelNext=SC_FOLDLEVELBASE+1; + } + else if( MatchUpperCase(styler,i,"STATIC SUB") ) + { + styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG); + levelNext=SC_FOLDLEVELBASE+1; + } + break; + } + } + break; + } + case 'C': + case 'c': + { + switch (chNext) + { + case 'A': + case 'a': + { + if( MatchUpperCase(styler,i,"CALLBACK FUNCTION") ) + { + styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG); + levelNext=SC_FOLDLEVELBASE+1; + } + break; + } + } + break; + } + case 'M': + case 'm': + { + switch (chNext) + { + case 'A': + case 'a': + { + if( MatchUpperCase(styler,i,"MACRO") ) + { + fMightBeMultiLineMacro=true; //Set folder level at end of line, we have to check for single line macro + } + break; + } + } + break; + } + default: + { + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + styler.SetLevel(lineCurrent, lev); + break; + } + } //switch (ch) + } //if( fNewLine ) + + switch (ch) + { + case '=': //To test single line macros + { + if (fBeginOfCommentFound==false) + fMightBeMultiLineMacro=false; //The found macro is a single line macro only; + break; + } + case '\'': //A comment starts + { + fBeginOfCommentFound=true; + break; + } + case '\n': + { + if (fMightBeMultiLineMacro) //The current line is the begin of a multi line macro + { + fMightBeMultiLineMacro=false; + styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG); + levelNext=SC_FOLDLEVELBASE+1; + } + lineCurrent++; + levelCurrent = levelNext; + fNewLine=true; + break; + } + case '\r': + { + if (chNext != '\n') + { + lineCurrent++; + levelCurrent = levelNext; + fNewLine=true; + } + break; + } + } //switch (ch) + } //for (unsigned int i = startPos; i < endPos; i++) +} + +static const char * const pbWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmPB(SCLEX_POWERBASIC, ColourisePBDoc, "powerbasic", FoldPBDoc, pbWordListDesc); diff --git a/lexers/LexPLM.cxx b/lexers/LexPLM.cxx new file mode 100644 index 000000000..604850fbe --- /dev/null +++ b/lexers/LexPLM.cxx @@ -0,0 +1,198 @@ +// Copyright (c) 1990-2007, Scientific Toolworks, Inc. +// Author: Jason Haslam +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "StyleContext.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static void GetRange(unsigned int start, + unsigned int end, + Accessor &styler, + char *s, + unsigned int len) { + unsigned int i = 0; + while ((i < end - start + 1) && (i < len-1)) { + s[i] = static_cast(tolower(styler[start + i])); + i++; + } + s[i] = '\0'; +} + +static void ColourisePlmDoc(unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) +{ + unsigned int endPos = startPos + length; + int state = initStyle; + + styler.StartAt(startPos); + styler.StartSegment(startPos); + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = styler.SafeGetCharAt(i); + char chNext = styler.SafeGetCharAt(i + 1); + + if (state == SCE_PLM_DEFAULT) { + if (ch == '/' && chNext == '*') { + styler.ColourTo(i - 1, state); + state = SCE_PLM_COMMENT; + } else if (ch == '\'') { + styler.ColourTo(i - 1, state); + state = SCE_PLM_STRING; + } else if (isdigit(ch)) { + styler.ColourTo(i - 1, state); + state = SCE_PLM_NUMBER; + } else if (isalpha(ch)) { + styler.ColourTo(i - 1, state); + state = SCE_PLM_IDENTIFIER; + } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || + ch == '=' || ch == '<' || ch == '>' || ch == ':') { + styler.ColourTo(i - 1, state); + state = SCE_PLM_OPERATOR; + } else if (ch == '$') { + styler.ColourTo(i - 1, state); + state = SCE_PLM_CONTROL; + } + } else if (state == SCE_PLM_COMMENT) { + if (ch == '*' && chNext == '/') { + i++; + styler.ColourTo(i, state); + state = SCE_PLM_DEFAULT; + } + } else if (state == SCE_PLM_STRING) { + if (ch == '\'') { + if (chNext == '\'') { + i++; + } else { + styler.ColourTo(i, state); + state = SCE_PLM_DEFAULT; + } + } + } else if (state == SCE_PLM_NUMBER) { + if (!isdigit(ch) && !isalpha(ch) && ch != '$') { + i--; + styler.ColourTo(i, state); + state = SCE_PLM_DEFAULT; + } + } else if (state == SCE_PLM_IDENTIFIER) { + if (!isdigit(ch) && !isalpha(ch) && ch != '$') { + // Get the entire identifier. + char word[1024]; + int segmentStart = styler.GetStartSegment(); + GetRange(segmentStart, i - 1, styler, word, sizeof(word)); + + i--; + if (keywordlists[0]->InList(word)) + styler.ColourTo(i, SCE_PLM_KEYWORD); + else + styler.ColourTo(i, state); + state = SCE_PLM_DEFAULT; + } + } else if (state == SCE_PLM_OPERATOR) { + if (ch != '=' && ch != '>') { + i--; + styler.ColourTo(i, state); + state = SCE_PLM_DEFAULT; + } + } else if (state == SCE_PLM_CONTROL) { + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, state); + state = SCE_PLM_DEFAULT; + } + } + } + styler.ColourTo(endPos - 1, state); +} + +static void FoldPlmDoc(unsigned int startPos, + int length, + int initStyle, + WordList *[], + Accessor &styler) +{ + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + int startKeyword = 0; + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (stylePrev != SCE_PLM_KEYWORD && style == SCE_PLM_KEYWORD) + startKeyword = i; + + if (style == SCE_PLM_KEYWORD && styleNext != SCE_PLM_KEYWORD) { + char word[1024]; + GetRange(startKeyword, i, styler, word, sizeof(word)); + + if (strcmp(word, "procedure") == 0 || strcmp(word, "do") == 0) + levelCurrent++; + else if (strcmp(word, "end") == 0) + levelCurrent--; + } + + if (foldComment) { + if (stylePrev != SCE_PLM_COMMENT && style == SCE_PLM_COMMENT) + levelCurrent++; + else if (stylePrev == SCE_PLM_COMMENT && style != SCE_PLM_COMMENT) + levelCurrent--; + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + + if (!isspacechar(ch)) + visibleChars++; + } + + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char *const plmWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmPLM(SCLEX_PLM, ColourisePlmDoc, "PL/M", FoldPlmDoc, plmWordListDesc); diff --git a/lexers/LexPOV.cxx b/lexers/LexPOV.cxx new file mode 100644 index 000000000..b845b2d47 --- /dev/null +++ b/lexers/LexPOV.cxx @@ -0,0 +1,316 @@ +// Scintilla source code edit control +/** @file LexPOV.cxx + ** Lexer for POV-Ray SDL (Persistance of Vision Raytracer, Scene Description Language). + ** Written by Philippe Lhoste but this is mostly a derivative of LexCPP... + **/ +// Copyright 1998-2005 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +// Some points that distinguish from a simple C lexer: +// Identifiers start only by a character. +// No line continuation character. +// Strings are limited to 256 characters. +// Directives are similar to preprocessor commands, +// but we match directive keywords and colorize incorrect ones. +// Block comments can be nested (code stolen from my code in LexLua). + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(int ch) { + return ch < 0x80 && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordStart(int ch) { + return ch < 0x80 && isalpha(ch); +} + +static inline bool IsANumberChar(int ch) { + // Not exactly following number definition (several dots are seen as OK, etc.) + // but probably enough in most cases. + return (ch < 0x80) && + (isdigit(ch) || toupper(ch) == 'E' || + ch == '.' || ch == '-' || ch == '+'); +} + +static void ColourisePovDoc( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords1 = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; + WordList &keywords7 = *keywordlists[6]; + WordList &keywords8 = *keywordlists[7]; + + int currentLine = styler.GetLine(startPos); + // Initialize the block comment /* */ nesting level, if we are inside such a comment. + int blockCommentLevel = 0; + if (initStyle == SCE_POV_COMMENT) { + blockCommentLevel = styler.GetLineState(currentLine - 1); + } + + // Do not leak onto next line + if (initStyle == SCE_POV_STRINGEOL || initStyle == SCE_POV_COMMENTLINE) { + initStyle = SCE_POV_DEFAULT; + } + + short stringLen = 0; + + StyleContext sc(startPos, length, initStyle, styler); + + 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); + if (sc.state == SCE_POV_COMMENT) { + // Inside a block comment, we set the line state + styler.SetLineState(currentLine, blockCommentLevel); + } else { + // Reset the line state + styler.SetLineState(currentLine, 0); + } + } + + if (sc.atLineStart && (sc.state == SCE_POV_STRING)) { + // Prevent SCE_POV_STRINGEOL from leaking back to previous line + sc.SetState(SCE_POV_STRING); + } + + // Determine if the current state should terminate. + if (sc.state == SCE_POV_OPERATOR) { + sc.SetState(SCE_POV_DEFAULT); + } else if (sc.state == SCE_POV_NUMBER) { + // We stop the number definition on non-numerical non-dot non-eE non-sign char + if (!IsANumberChar(sc.ch)) { + sc.SetState(SCE_POV_DEFAULT); + } + } else if (sc.state == SCE_POV_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + if (keywords2.InList(s)) { + sc.ChangeState(SCE_POV_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_POV_WORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_POV_WORD4); + } else if (keywords5.InList(s)) { + sc.ChangeState(SCE_POV_WORD5); + } else if (keywords6.InList(s)) { + sc.ChangeState(SCE_POV_WORD6); + } else if (keywords7.InList(s)) { + sc.ChangeState(SCE_POV_WORD7); + } else if (keywords8.InList(s)) { + sc.ChangeState(SCE_POV_WORD8); + } + sc.SetState(SCE_POV_DEFAULT); + } + } else if (sc.state == SCE_POV_DIRECTIVE) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + char *p; + sc.GetCurrent(s, sizeof(s)); + p = s; + // Skip # and whitespace between # and directive word + do { + p++; + } while ((*p == ' ' || *p == '\t') && *p != '\0'); + if (!keywords1.InList(p)) { + sc.ChangeState(SCE_POV_BADDIRECTIVE); + } + sc.SetState(SCE_POV_DEFAULT); + } + } else if (sc.state == SCE_POV_COMMENT) { + if (sc.Match('/', '*')) { + blockCommentLevel++; + sc.Forward(); + } else if (sc.Match('*', '/') && blockCommentLevel > 0) { + blockCommentLevel--; + sc.Forward(); + if (blockCommentLevel == 0) { + sc.ForwardSetState(SCE_POV_DEFAULT); + } + } + } else if (sc.state == SCE_POV_COMMENTLINE) { + if (sc.atLineEnd) { + sc.ForwardSetState(SCE_POV_DEFAULT); + } + } else if (sc.state == SCE_POV_STRING) { + if (sc.ch == '\\') { + stringLen++; + if (strchr("abfnrtuv0'\"", sc.chNext)) { + // Compound characters are counted as one. + // Note: for Unicode chars \u, we shouldn't count the next 4 digits... + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_POV_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_POV_STRINGEOL); + sc.ForwardSetState(SCE_POV_DEFAULT); + } else { + stringLen++; + } + if (stringLen > 256) { + // Strings are limited to 256 chars + sc.SetState(SCE_POV_STRINGEOL); + } + } else if (sc.state == SCE_POV_STRINGEOL) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_C_DEFAULT); + } else if (sc.atLineEnd) { + sc.ForwardSetState(SCE_POV_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_POV_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_POV_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_POV_IDENTIFIER); + } else if (sc.Match('/', '*')) { + blockCommentLevel = 1; + sc.SetState(SCE_POV_COMMENT); + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + sc.SetState(SCE_POV_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_POV_STRING); + stringLen = 0; + } else if (sc.ch == '#') { + sc.SetState(SCE_POV_DIRECTIVE); + // Skip whitespace between # and directive word + do { + sc.Forward(); + } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); + if (sc.atLineEnd) { + sc.SetState(SCE_POV_DEFAULT); + } + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_POV_OPERATOR); + } + } + } + sc.Complete(); +} + +static void FoldPovDoc( + unsigned int startPos, + int length, + int initStyle, + WordList *[], + Accessor &styler) { + + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldDirective = styler.GetPropertyInt("fold.directive") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && (style == SCE_POV_COMMENT)) { + if (stylePrev != SCE_POV_COMMENT) { + levelCurrent++; + } else if ((styleNext != SCE_POV_COMMENT) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + if (foldComment && (style == SCE_POV_COMMENTLINE)) { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelCurrent++; + } else if (chNext2 == '}') { + levelCurrent--; + } + } + } + if (foldDirective && (style == SCE_POV_DIRECTIVE)) { + if (ch == '#') { + unsigned int j=i+1; + while ((j levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const povWordLists[] = { + "Language directives", + "Objects & CSG & Appearance", + "Types & Modifiers & Items", + "Predefined Identifiers", + "Predefined Functions", + "User defined 1", + "User defined 2", + "User defined 3", + 0, +}; + +LexerModule lmPOV(SCLEX_POV, ColourisePovDoc, "pov", FoldPovDoc, povWordLists); diff --git a/lexers/LexPS.cxx b/lexers/LexPS.cxx new file mode 100644 index 000000000..2edcff150 --- /dev/null +++ b/lexers/LexPS.cxx @@ -0,0 +1,347 @@ +// Scintilla source code edit control +/** @file LexPS.cxx + ** Lexer for PostScript + ** + ** Written by Nigel Hathaway . + ** The License.txt file describes the conditions under which this software may be distributed. + **/ + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsASelfDelimitingChar(const int ch) { + return (ch == '[' || ch == ']' || ch == '{' || ch == '}' || + ch == '/' || ch == '<' || ch == '>' || + ch == '(' || ch == ')' || ch == '%'); +} + +static inline bool IsAWhitespaceChar(const int ch) { + return (ch == ' ' || ch == '\t' || ch == '\r' || + ch == '\n' || ch == '\f' || ch == '\0'); +} + +static bool IsABaseNDigit(const int ch, const int base) { + int maxdig = '9'; + int letterext = -1; + + if (base <= 10) + maxdig = '0' + base - 1; + else + letterext = base - 11; + + return ((ch >= '0' && ch <= maxdig) || + (ch >= 'A' && ch <= ('A' + letterext)) || + (ch >= 'a' && ch <= ('a' + letterext))); +} + +static inline bool IsABase85Char(const int ch) { + return ((ch >= '!' && ch <= 'u') || ch == 'z'); +} + +static void ColourisePSDoc( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords1 = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + + StyleContext sc(startPos, length, initStyle, styler); + + bool tokenizing = styler.GetPropertyInt("ps.tokenize") != 0; + int pslevel = styler.GetPropertyInt("ps.level", 3); + int lineCurrent = styler.GetLine(startPos); + int nestTextCurrent = 0; + if (lineCurrent > 0 && initStyle == SCE_PS_TEXT) + nestTextCurrent = styler.GetLineState(lineCurrent - 1); + int numRadix = 0; + bool numHasPoint = false; + bool numHasExponent = false; + bool numHasSign = false; + + // Clear out existing tokenization + if (tokenizing && length > 0) { + styler.StartAt(startPos, static_cast(INDIC2_MASK)); + styler.ColourTo(startPos + length-1, 0); + styler.Flush(); + styler.StartAt(startPos); + styler.StartSegment(startPos); + } + + for (; sc.More(); sc.Forward()) { + if (sc.atLineStart) + lineCurrent = styler.GetLine(sc.currentPos); + + // Determine if the current state should terminate. + if (sc.state == SCE_PS_COMMENT || sc.state == SCE_PS_DSC_VALUE) { + if (sc.atLineEnd) { + sc.SetState(SCE_C_DEFAULT); + } + } else if (sc.state == SCE_PS_DSC_COMMENT) { + if (sc.ch == ':') { + sc.Forward(); + if (!sc.atLineEnd) + sc.SetState(SCE_PS_DSC_VALUE); + else + sc.SetState(SCE_C_DEFAULT); + } else if (sc.atLineEnd) { + sc.SetState(SCE_C_DEFAULT); + } else if (IsAWhitespaceChar(sc.ch) && sc.ch != '\r') { + sc.ChangeState(SCE_PS_COMMENT); + } + } else if (sc.state == SCE_PS_NUMBER) { + if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) { + if ((sc.chPrev == '+' || sc.chPrev == '-' || + sc.chPrev == 'E' || sc.chPrev == 'e') && numRadix == 0) + sc.ChangeState(SCE_PS_NAME); + sc.SetState(SCE_C_DEFAULT); + } else if (sc.ch == '#') { + if (numHasPoint || numHasExponent || numHasSign || numRadix != 0) { + sc.ChangeState(SCE_PS_NAME); + } else { + char szradix[5]; + sc.GetCurrent(szradix, 4); + numRadix = atoi(szradix); + if (numRadix < 2 || numRadix > 36) + sc.ChangeState(SCE_PS_NAME); + } + } else if ((sc.ch == 'E' || sc.ch == 'e') && numRadix == 0) { + if (numHasExponent) { + sc.ChangeState(SCE_PS_NAME); + } else { + numHasExponent = true; + if (sc.chNext == '+' || sc.chNext == '-') + sc.Forward(); + } + } else if (sc.ch == '.') { + if (numHasPoint || numHasExponent || numRadix != 0) { + sc.ChangeState(SCE_PS_NAME); + } else { + numHasPoint = true; + } + } else if (numRadix == 0) { + if (!IsABaseNDigit(sc.ch, 10)) + sc.ChangeState(SCE_PS_NAME); + } else { + if (!IsABaseNDigit(sc.ch, numRadix)) + sc.ChangeState(SCE_PS_NAME); + } + } else if (sc.state == SCE_PS_NAME || sc.state == SCE_PS_KEYWORD) { + if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + if ((pslevel >= 1 && keywords1.InList(s)) || + (pslevel >= 2 && keywords2.InList(s)) || + (pslevel >= 3 && keywords3.InList(s)) || + keywords4.InList(s) || keywords5.InList(s)) { + sc.ChangeState(SCE_PS_KEYWORD); + } + sc.SetState(SCE_C_DEFAULT); + } + } else if (sc.state == SCE_PS_LITERAL || sc.state == SCE_PS_IMMEVAL) { + if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) + sc.SetState(SCE_C_DEFAULT); + } else if (sc.state == SCE_PS_PAREN_ARRAY || sc.state == SCE_PS_PAREN_DICT || + sc.state == SCE_PS_PAREN_PROC) { + sc.SetState(SCE_C_DEFAULT); + } else if (sc.state == SCE_PS_TEXT) { + if (sc.ch == '(') { + nestTextCurrent++; + } else if (sc.ch == ')') { + if (--nestTextCurrent == 0) + sc.ForwardSetState(SCE_PS_DEFAULT); + } else if (sc.ch == '\\') { + sc.Forward(); + } + } else if (sc.state == SCE_PS_HEXSTRING) { + if (sc.ch == '>') { + sc.ForwardSetState(SCE_PS_DEFAULT); + } else if (!IsABaseNDigit(sc.ch, 16) && !IsAWhitespaceChar(sc.ch)) { + sc.SetState(SCE_PS_HEXSTRING); + styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR); + } + } else if (sc.state == SCE_PS_BASE85STRING) { + if (sc.Match('~', '>')) { + sc.Forward(); + sc.ForwardSetState(SCE_PS_DEFAULT); + } else if (!IsABase85Char(sc.ch) && !IsAWhitespaceChar(sc.ch)) { + sc.SetState(SCE_PS_BASE85STRING); + styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_C_DEFAULT) { + unsigned int tokenpos = sc.currentPos; + + if (sc.ch == '[' || sc.ch == ']') { + sc.SetState(SCE_PS_PAREN_ARRAY); + } else if (sc.ch == '{' || sc.ch == '}') { + sc.SetState(SCE_PS_PAREN_PROC); + } else if (sc.ch == '/') { + if (sc.chNext == '/') { + sc.SetState(SCE_PS_IMMEVAL); + sc.Forward(); + } else { + sc.SetState(SCE_PS_LITERAL); + } + } else if (sc.ch == '<') { + if (sc.chNext == '<') { + sc.SetState(SCE_PS_PAREN_DICT); + sc.Forward(); + } else if (sc.chNext == '~') { + sc.SetState(SCE_PS_BASE85STRING); + sc.Forward(); + } else { + sc.SetState(SCE_PS_HEXSTRING); + } + } else if (sc.ch == '>' && sc.chNext == '>') { + sc.SetState(SCE_PS_PAREN_DICT); + sc.Forward(); + } else if (sc.ch == '>' || sc.ch == ')') { + sc.SetState(SCE_C_DEFAULT); + styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR); + } else if (sc.ch == '(') { + sc.SetState(SCE_PS_TEXT); + nestTextCurrent = 1; + } else if (sc.ch == '%') { + if (sc.chNext == '%' && sc.atLineStart) { + sc.SetState(SCE_PS_DSC_COMMENT); + sc.Forward(); + if (sc.chNext == '+') { + sc.Forward(); + sc.ForwardSetState(SCE_PS_DSC_VALUE); + } + } else { + sc.SetState(SCE_PS_COMMENT); + } + } else if ((sc.ch == '+' || sc.ch == '-' || sc.ch == '.') && + IsABaseNDigit(sc.chNext, 10)) { + sc.SetState(SCE_PS_NUMBER); + numRadix = 0; + numHasPoint = (sc.ch == '.'); + numHasExponent = false; + numHasSign = (sc.ch == '+' || sc.ch == '-'); + } else if ((sc.ch == '+' || sc.ch == '-') && sc.chNext == '.' && + IsABaseNDigit(sc.GetRelative(2), 10)) { + sc.SetState(SCE_PS_NUMBER); + numRadix = 0; + numHasPoint = false; + numHasExponent = false; + numHasSign = true; + } else if (IsABaseNDigit(sc.ch, 10)) { + sc.SetState(SCE_PS_NUMBER); + numRadix = 0; + numHasPoint = false; + numHasExponent = false; + numHasSign = false; + } else if (!IsAWhitespaceChar(sc.ch)) { + sc.SetState(SCE_PS_NAME); + } + + // Mark the start of tokens + if (tokenizing && sc.state != SCE_C_DEFAULT && sc.state != SCE_PS_COMMENT && + sc.state != SCE_PS_DSC_COMMENT && sc.state != SCE_PS_DSC_VALUE) { + styler.Flush(); + styler.StartAt(tokenpos, static_cast(INDIC2_MASK)); + styler.ColourTo(tokenpos, INDIC2_MASK); + styler.Flush(); + styler.StartAt(tokenpos); + styler.StartSegment(tokenpos); + } + } + + if (sc.atLineEnd) + styler.SetLineState(lineCurrent, nestTextCurrent); + } + + sc.Complete(); +} + +static void FoldPSDoc(unsigned int startPos, int length, int, WordList *[], + Accessor &styler) { + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); //mac?? + if ((style & 31) == SCE_PS_PAREN_PROC) { + if (ch == '{') { + // Measure the minimum before a '{' to allow + // folding on "} {" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + if (atEOL) { + int levelUse = levelCurrent; + if (foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } +} + +static const char * const psWordListDesc[] = { + "PS Level 1 operators", + "PS Level 2 operators", + "PS Level 3 operators", + "RIP-specific operators", + "User-defined operators", + 0 +}; + +LexerModule lmPS(SCLEX_PS, ColourisePSDoc, "ps", FoldPSDoc, psWordListDesc); diff --git a/lexers/LexPascal.cxx b/lexers/LexPascal.cxx new file mode 100644 index 000000000..3dcf35ad5 --- /dev/null +++ b/lexers/LexPascal.cxx @@ -0,0 +1,592 @@ +// Scintilla source code edit control +/** @file LexPascal.cxx + ** Lexer for Pascal. + ** Written by Laurent le Tynevez + ** Updated by Simon Steele September 2002 + ** Updated by Mathias Rauen May 2003 (Delphi adjustments) + ** Completely rewritten by Marko Njezic October 2008 + **/ + +/* + +A few words about features of the new completely rewritten LexPascal... + +Generally speaking LexPascal tries to support all available Delphi features (up +to Delphi 2009 at this time), including .NET specific features. + +~ HIGHLIGHTING: + +If you enable "lexer.pascal.smart.highlighting" property, some keywords will +only be highlighted in appropriate context. As implemented those are keywords +related to property and DLL exports declarations (similar to how Delphi IDE +works). + +For example, keywords "read" and "write" will only be highlighted if they are in +property declaration: + +property MyProperty: boolean read FMyProperty write FMyProperty; + +~ FOLDING: + +Folding is supported in the following cases: + +- Folding of stream-like comments +- Folding of groups of consecutive line comments +- Folding of preprocessor blocks (the following preprocessor blocks are +supported: IF / IFEND; IFDEF, IFNDEF, IFOPT / ENDIF and REGION / ENDREGION +blocks), including nesting of preprocessor blocks up to 255 levels +- Folding of code blocks on appropriate keywords (the following code blocks are +supported: "begin, asm, record, try, case / end" blocks, class & object +declarations and interface declarations) + +Remarks: + +- Folding of code blocks tries to handle all special cases in which folding +should not occur. As implemented those are: + +1. Structure "record case / end" (there's only one "end" statement and "case" is +ignored as fold point) +2. Forward class declarations ("type TMyClass = class;") and object method +declarations ("TNotifyEvent = procedure(Sender: TObject) of object;") are +ignored as fold points +3. Simplified complete class declarations ("type TMyClass = class(TObject);") +are ignored as fold points +4. Every other situation when class keyword doesn't actually start class +declaration ("class procedure", "class function", "class of", "class var", +"class property" and "class operator") + +- Folding of code blocks inside preprocessor blocks is disabled (any comments +inside them will be folded fine) because there is no guarantee that complete +code block will be contained inside folded preprocessor block in which case +folded code block could end prematurely at the end of preprocessor block if +there is no closing statement inside. This was done in order to properly process +document that may contain something like this: + +type +{$IFDEF UNICODE} + TMyClass = class(UnicodeAncestor) +{$ELSE} + TMyClass = class(AnsiAncestor) +{$ENDIF} + private + ... + public + ... + published + ... +end; + +If class declarations were folded, then the second class declaration would end +at "$ENDIF" statement, first class statement would end at "end;" statement and +preprocessor "$IFDEF" block would go all the way to the end of document. +However, having in mind all this, if you want to enable folding of code blocks +inside preprocessor blocks, you can disable folding of preprocessor blocks by +changing "fold.preprocessor" property, in which case everything inside them +would be folded. + +~ KEYWORDS: + +The list of keywords that can be used in pascal.properties file (up to Delphi +2009): + +- Keywords: absolute abstract and array as asm assembler automated begin case +cdecl class const constructor deprecated destructor dispid dispinterface div do +downto dynamic else end except export exports external far file final +finalization finally for forward function goto if implementation in inherited +initialization inline interface is label library message mod near nil not object +of on or out overload override packed pascal platform private procedure program +property protected public published raise record register reintroduce repeat +resourcestring safecall sealed set shl shr static stdcall strict string then +threadvar to try type unit unsafe until uses var varargs virtual while with xor + +- Keywords related to the "smart highlithing" feature: add default implements +index name nodefault read readonly remove stored write writeonly + +- Keywords related to Delphi packages (in addition to all above): package +contains requires + +*/ + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "StyleContext.h" +#include "CharacterSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static void GetRangeLowered(unsigned int start, + unsigned int end, + Accessor &styler, + char *s, + unsigned int len) { + unsigned int i = 0; + while ((i < end - start + 1) && (i < len-1)) { + s[i] = static_cast(tolower(styler[start + i])); + i++; + } + s[i] = '\0'; +} + +static void GetForwardRangeLowered(unsigned int start, + CharacterSet &charSet, + Accessor &styler, + char *s, + unsigned int len) { + unsigned int i = 0; + while ((i < len-1) && charSet.Contains(styler.SafeGetCharAt(start + i))) { + s[i] = static_cast(tolower(styler.SafeGetCharAt(start + i))); + i++; + } + s[i] = '\0'; + +} + +enum { + stateInAsm = 0x1000, + stateInProperty = 0x2000, + stateInExport = 0x4000, + stateFoldInPreprocessor = 0x0100, + stateFoldInRecord = 0x0200, + stateFoldInPreprocessorLevelMask = 0x00FF, + stateFoldMaskAll = 0x0FFF +}; + +static void ClassifyPascalWord(WordList *keywordlists[], StyleContext &sc, int &curLineState, bool bSmartHighlighting) { + WordList& keywords = *keywordlists[0]; + + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + if (curLineState & stateInAsm) { + if (strcmp(s, "end") == 0 && sc.GetRelative(-4) != '@') { + curLineState &= ~stateInAsm; + sc.ChangeState(SCE_PAS_WORD); + } else { + sc.ChangeState(SCE_PAS_ASM); + } + } else { + bool ignoreKeyword = false; + if (strcmp(s, "asm") == 0) { + curLineState |= stateInAsm; + } else if (bSmartHighlighting) { + if (strcmp(s, "property") == 0) { + curLineState |= stateInProperty; + } else if (strcmp(s, "exports") == 0) { + curLineState |= stateInExport; + } else if (!(curLineState & (stateInProperty | stateInExport)) && strcmp(s, "index") == 0) { + ignoreKeyword = true; + } else if (!(curLineState & stateInExport) && strcmp(s, "name") == 0) { + ignoreKeyword = true; + } else if (!(curLineState & stateInProperty) && + (strcmp(s, "read") == 0 || strcmp(s, "write") == 0 || + strcmp(s, "default") == 0 || strcmp(s, "nodefault") == 0 || + strcmp(s, "stored") == 0 || strcmp(s, "implements") == 0 || + strcmp(s, "readonly") == 0 || strcmp(s, "writeonly") == 0 || + strcmp(s, "add") == 0 || strcmp(s, "remove") == 0)) { + ignoreKeyword = true; + } + } + if (!ignoreKeyword) { + sc.ChangeState(SCE_PAS_WORD); + } + } + } else if (curLineState & stateInAsm) { + sc.ChangeState(SCE_PAS_ASM); + } + sc.SetState(SCE_PAS_DEFAULT); +} + +static void ColourisePascalDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + bool bSmartHighlighting = styler.GetPropertyInt("lexer.pascal.smart.highlighting", 1) != 0; + + CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true); + CharacterSet setNumber(CharacterSet::setDigits, ".-+eE"); + CharacterSet setHexNumber(CharacterSet::setDigits, "abcdefABCDEF"); + CharacterSet setOperator(CharacterSet::setNone, "#$&'()*+,-./:;<=>@[]^{}"); + + int curLine = styler.GetLine(startPos); + int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : 0; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + if (sc.atLineEnd) { + // Update the line state, so it can be seen by next line + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curLineState); + } + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_PAS_NUMBER: + if (!setNumber.Contains(sc.ch) || (sc.ch == '.' && sc.chNext == '.')) { + sc.SetState(SCE_PAS_DEFAULT); + } else if (sc.ch == '-' || sc.ch == '+') { + if (sc.chPrev != 'E' && sc.chPrev != 'e') { + sc.SetState(SCE_PAS_DEFAULT); + } + } + break; + case SCE_PAS_IDENTIFIER: + if (!setWord.Contains(sc.ch)) { + ClassifyPascalWord(keywordlists, sc, curLineState, bSmartHighlighting); + } + break; + case SCE_PAS_HEXNUMBER: + if (!setHexNumber.Contains(sc.ch)) { + sc.SetState(SCE_PAS_DEFAULT); + } + break; + case SCE_PAS_COMMENT: + case SCE_PAS_PREPROCESSOR: + if (sc.ch == '}') { + sc.ForwardSetState(SCE_PAS_DEFAULT); + } + break; + case SCE_PAS_COMMENT2: + case SCE_PAS_PREPROCESSOR2: + if (sc.Match('*', ')')) { + sc.Forward(); + sc.ForwardSetState(SCE_PAS_DEFAULT); + } + break; + case SCE_PAS_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_PAS_DEFAULT); + } + break; + case SCE_PAS_STRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_PAS_STRINGEOL); + } else if (sc.ch == '\'' && sc.chNext == '\'') { + sc.Forward(); + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_PAS_DEFAULT); + } + break; + case SCE_PAS_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_PAS_DEFAULT); + } + break; + case SCE_PAS_CHARACTER: + if (!setHexNumber.Contains(sc.ch) && sc.ch != '$') { + sc.SetState(SCE_PAS_DEFAULT); + } + break; + case SCE_PAS_OPERATOR: + if (bSmartHighlighting && sc.chPrev == ';') { + curLineState &= ~(stateInProperty | stateInExport); + } + sc.SetState(SCE_PAS_DEFAULT); + break; + case SCE_PAS_ASM: + sc.SetState(SCE_PAS_DEFAULT); + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_PAS_DEFAULT) { + if (IsADigit(sc.ch) && !(curLineState & stateInAsm)) { + sc.SetState(SCE_PAS_NUMBER); + } else if (setWordStart.Contains(sc.ch)) { + sc.SetState(SCE_PAS_IDENTIFIER); + } else if (sc.ch == '$' && !(curLineState & stateInAsm)) { + sc.SetState(SCE_PAS_HEXNUMBER); + } else if (sc.Match('{', '$')) { + sc.SetState(SCE_PAS_PREPROCESSOR); + } else if (sc.ch == '{') { + sc.SetState(SCE_PAS_COMMENT); + } else if (sc.Match("(*$")) { + sc.SetState(SCE_PAS_PREPROCESSOR2); + } else if (sc.Match('(', '*')) { + sc.SetState(SCE_PAS_COMMENT2); + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + sc.SetState(SCE_PAS_COMMENTLINE); + } else if (sc.ch == '\'') { + sc.SetState(SCE_PAS_STRING); + } else if (sc.ch == '#') { + sc.SetState(SCE_PAS_CHARACTER); + } else if (setOperator.Contains(sc.ch) && !(curLineState & stateInAsm)) { + sc.SetState(SCE_PAS_OPERATOR); + } else if (curLineState & stateInAsm) { + sc.SetState(SCE_PAS_ASM); + } + } + } + + if (sc.state == SCE_PAS_IDENTIFIER && setWord.Contains(sc.chPrev)) { + ClassifyPascalWord(keywordlists, sc, curLineState, bSmartHighlighting); + } + + sc.Complete(); +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_PAS_COMMENT || style == SCE_PAS_COMMENT2; +} + +static bool IsCommentLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eolPos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eolPos; i++) { + char ch = styler[i]; + char chNext = styler.SafeGetCharAt(i + 1); + int style = styler.StyleAt(i); + if (ch == '/' && chNext == '/' && style == SCE_PAS_COMMENTLINE) { + return true; + } else if (!IsASpaceOrTab(ch)) { + return false; + } + } + return false; +} + +static unsigned int GetFoldInPreprocessorLevelFlag(int lineFoldStateCurrent) { + return lineFoldStateCurrent & stateFoldInPreprocessorLevelMask; +} + +static void SetFoldInPreprocessorLevelFlag(int &lineFoldStateCurrent, unsigned int nestLevel) { + lineFoldStateCurrent &= ~stateFoldInPreprocessorLevelMask; + lineFoldStateCurrent |= nestLevel & stateFoldInPreprocessorLevelMask; +} + +static void ClassifyPascalPreprocessorFoldPoint(int &levelCurrent, int &lineFoldStateCurrent, + unsigned int startPos, Accessor &styler) { + CharacterSet setWord(CharacterSet::setAlpha); + + char s[11]; // Size of the longest possible keyword + one additional character + null + GetForwardRangeLowered(startPos, setWord, styler, s, sizeof(s)); + + unsigned int nestLevel = GetFoldInPreprocessorLevelFlag(lineFoldStateCurrent); + + if (strcmp(s, "if") == 0 || + strcmp(s, "ifdef") == 0 || + strcmp(s, "ifndef") == 0 || + strcmp(s, "ifopt") == 0 || + strcmp(s, "region") == 0) { + nestLevel++; + SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel); + lineFoldStateCurrent |= stateFoldInPreprocessor; + levelCurrent++; + } else if (strcmp(s, "endif") == 0 || + strcmp(s, "ifend") == 0 || + strcmp(s, "endregion") == 0) { + nestLevel--; + SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel); + if (nestLevel == 0) { + lineFoldStateCurrent &= ~stateFoldInPreprocessor; + } + levelCurrent--; + if (levelCurrent < SC_FOLDLEVELBASE) { + levelCurrent = SC_FOLDLEVELBASE; + } + } +} + +static unsigned int SkipWhiteSpace(unsigned int currentPos, unsigned int endPos, + Accessor &styler, bool includeChars = false) { + CharacterSet setWord(CharacterSet::setAlphaNum, "_"); + unsigned int j = currentPos + 1; + char ch = styler.SafeGetCharAt(j); + while ((j < endPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' || + IsStreamCommentStyle(styler.StyleAt(j)) || (includeChars && setWord.Contains(ch)))) { + j++; + ch = styler.SafeGetCharAt(j); + } + return j; +} + +static void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCurrent, + int startPos, unsigned int endPos, + unsigned int lastStart, unsigned int currentPos, Accessor &styler) { + char s[100]; + GetRangeLowered(lastStart, currentPos, styler, s, sizeof(s)); + + if (strcmp(s, "record") == 0) { + lineFoldStateCurrent |= stateFoldInRecord; + levelCurrent++; + } else if (strcmp(s, "begin") == 0 || + strcmp(s, "asm") == 0 || + strcmp(s, "try") == 0 || + (strcmp(s, "case") == 0 && !(lineFoldStateCurrent & stateFoldInRecord))) { + levelCurrent++; + } else if (strcmp(s, "class") == 0 || strcmp(s, "object") == 0) { + // "class" & "object" keywords require special handling... + bool ignoreKeyword = false; + unsigned int j = SkipWhiteSpace(currentPos, endPos, styler); + if (j < endPos) { + CharacterSet setWordStart(CharacterSet::setAlpha, "_"); + CharacterSet setWord(CharacterSet::setAlphaNum, "_"); + + if (styler.SafeGetCharAt(j) == ';') { + // Handle forward class declarations ("type TMyClass = class;") + // and object method declarations ("TNotifyEvent = procedure(Sender: TObject) of object;") + ignoreKeyword = true; + } else if (strcmp(s, "class") == 0) { + // "class" keyword has a few more special cases... + if (styler.SafeGetCharAt(j) == '(') { + // Handle simplified complete class declarations ("type TMyClass = class(TObject);") + j = SkipWhiteSpace(j, endPos, styler, true); + if (j < endPos && styler.SafeGetCharAt(j) == ')') { + j = SkipWhiteSpace(j, endPos, styler); + if (j < endPos && styler.SafeGetCharAt(j) == ';') { + ignoreKeyword = true; + } + } + } else if (setWordStart.Contains(styler.SafeGetCharAt(j))) { + char s2[11]; // Size of the longest possible keyword + one additional character + null + GetForwardRangeLowered(j, setWord, styler, s2, sizeof(s2)); + + if (strcmp(s2, "procedure") == 0 || + strcmp(s2, "function") == 0 || + strcmp(s2, "of") == 0 || + strcmp(s2, "var") == 0 || + strcmp(s2, "property") == 0 || + strcmp(s2, "operator") == 0) { + ignoreKeyword = true; + } + } + } + } + if (!ignoreKeyword) { + levelCurrent++; + } + } else if (strcmp(s, "interface") == 0) { + // "interface" keyword requires special handling... + bool ignoreKeyword = true; + int j = lastStart - 1; + char ch = styler.SafeGetCharAt(j); + while ((j >= startPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' || + IsStreamCommentStyle(styler.StyleAt(j)))) { + j--; + ch = styler.SafeGetCharAt(j); + } + if (j >= startPos && styler.SafeGetCharAt(j) == '=') { + ignoreKeyword = false; + } + if (!ignoreKeyword) { + levelCurrent++; + } + } else if (strcmp(s, "end") == 0) { + lineFoldStateCurrent &= ~stateFoldInRecord; + levelCurrent--; + if (levelCurrent < SC_FOLDLEVELBASE) { + levelCurrent = SC_FOLDLEVELBASE; + } + } +} + +static void FoldPascalDoc(unsigned int startPos, int length, int initStyle, WordList *[], + Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + int lineFoldStateCurrent = lineCurrent > 0 ? styler.GetLineState(lineCurrent - 1) & stateFoldMaskAll : 0; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + + int lastStart = 0; + CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true); + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (foldComment && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelCurrent++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) + { + if (!IsCommentLine(lineCurrent - 1, styler) + && IsCommentLine(lineCurrent + 1, styler)) + levelCurrent++; + else if (IsCommentLine(lineCurrent - 1, styler) + && !IsCommentLine(lineCurrent+1, styler)) + levelCurrent--; + } + if (foldPreprocessor) { + if (style == SCE_PAS_PREPROCESSOR && ch == '{' && chNext == '$') { + ClassifyPascalPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 2, styler); + } else if (style == SCE_PAS_PREPROCESSOR2 && ch == '(' && chNext == '*' + && styler.SafeGetCharAt(i + 2) == '$') { + ClassifyPascalPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 3, styler); + } + } + + if (stylePrev != SCE_PAS_WORD && style == SCE_PAS_WORD) + { + // Store last word start point. + lastStart = i; + } + if (stylePrev == SCE_PAS_WORD && !(lineFoldStateCurrent & stateFoldInPreprocessor)) { + if(setWord.Contains(ch) && !setWord.Contains(chNext)) { + ClassifyPascalWordFoldPoint(levelCurrent, lineFoldStateCurrent, startPos, endPos, lastStart, i, styler); + } + } + + if (!IsASpace(ch)) + visibleChars++; + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + int newLineState = (styler.GetLineState(lineCurrent) & ~stateFoldMaskAll) | lineFoldStateCurrent; + styler.SetLineState(lineCurrent, newLineState); + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + } + + // If we didn't reach the EOL in previous loop, store line level and whitespace information. + // The rest will be filled in later... + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + styler.SetLevel(lineCurrent, lev); +} + +static const char * const pascalWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmPascal(SCLEX_PASCAL, ColourisePascalDoc, "pascal", FoldPascalDoc, pascalWordListDesc); diff --git a/lexers/LexPerl.cxx b/lexers/LexPerl.cxx new file mode 100644 index 000000000..bca78f57c --- /dev/null +++ b/lexers/LexPerl.cxx @@ -0,0 +1,1305 @@ +// Scintilla source code edit control +/** @file LexPerl.cxx + ** Lexer for Perl. + **/ +// Copyright 1998-2008 by Neil Hodgson +// Lexical analysis fixes by Kein-Hong Man +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "CharacterSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// Info for HERE document handling from perldata.pod (reformatted): +// ---------------------------------------------------------------- +// A line-oriented form of quoting is based on the shell ``here-doc'' syntax. +// Following a << you specify a string to terminate the quoted material, and +// all lines following the current line down to the terminating string are +// the value of the item. +// * The terminating string may be either an identifier (a word), or some +// quoted text. +// * If quoted, the type of quotes you use determines the treatment of the +// text, just as in regular quoting. +// * An unquoted identifier works like double quotes. +// * There must be no space between the << and the identifier. +// (If you put a space it will be treated as a null identifier, +// which is valid, and matches the first empty line.) +// (This is deprecated, -w warns of this syntax) +// * The terminating string must appear by itself (unquoted and +// with no surrounding whitespace) on the terminating line. + +#define HERE_DELIM_MAX 256 // maximum length of HERE doc delimiter + +#define PERLNUM_BINARY 1 // order is significant: 1-4 cannot have a dot +#define PERLNUM_HEX 2 +#define PERLNUM_OCTAL 3 +#define PERLNUM_FLOAT_EXP 4 // exponent part only +#define PERLNUM_DECIMAL 5 // 1-5 are numbers; 6-7 are strings +#define PERLNUM_VECTOR 6 +#define PERLNUM_V_VECTOR 7 +#define PERLNUM_BAD 8 + +#define BACK_NONE 0 // lookback state for bareword disambiguation: +#define BACK_OPERATOR 1 // whitespace/comments are insignificant +#define BACK_KEYWORD 2 // operators/keywords are needed for disambiguation + +static bool isPerlKeyword(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) +{ + // old-style keyword matcher; needed because GetCurrent() needs + // current segment to be committed, but we may abandon early... + char s[100]; + unsigned int i, len = end - start; + if (len > 30) { len = 30; } + for (i = 0; i < len; i++, start++) s[i] = styler[start]; + s[i] = '\0'; + return keywords.InList(s); +} + +static int disambiguateBareword(Accessor &styler, unsigned int bk, unsigned int fw, + int backFlag, unsigned int backPos, unsigned int endPos) +{ + // identifiers are recognized by Perl as barewords under some + // conditions, the following attempts to do the disambiguation + // by looking backward and forward; result in 2 LSB + int result = 0; + bool moreback = false; // true if passed newline/comments + bool brace = false; // true if opening brace found + // if BACK_NONE, neither operator nor keyword, so skip test + if (backFlag == BACK_NONE) + return result; + // first look backwards past whitespace/comments to set EOL flag + // (some disambiguation patterns must be on a single line) + if (backPos <= static_cast(styler.LineStart(styler.GetLine(bk)))) + moreback = true; + // look backwards at last significant lexed item for disambiguation + bk = backPos - 1; + int ch = static_cast(styler.SafeGetCharAt(bk)); + if (ch == '{' && !moreback) { + // {bareword: possible variable spec + brace = true; + } else if ((ch == '&' && styler.SafeGetCharAt(bk - 1) != '&') + // &bareword: subroutine call + || styler.Match(bk - 1, "->") + // ->bareword: part of variable spec + || styler.Match(bk - 2, "sub")) { + // sub bareword: subroutine declaration + // (implied BACK_KEYWORD, no keywords end in 'sub'!) + result |= 1; + } + // next, scan forward after word past tab/spaces only; + // if ch isn't one of '[{(,' we can skip the test + if ((ch == '{' || ch == '(' || ch == '['|| ch == ',') + && fw < endPos) { + while (ch = static_cast(styler.SafeGetCharAt(fw)), + IsASpaceOrTab(ch) && fw < endPos) { + fw++; + } + if ((ch == '}' && brace) + // {bareword}: variable spec + || styler.Match(fw, "=>")) { + // [{(, bareword=>: hash literal + result |= 2; + } + } + return result; +} + +static void skipWhitespaceComment(Accessor &styler, unsigned int &p) +{ + // when backtracking, we need to skip whitespace and comments + int style; + while ((p > 0) && (style = styler.StyleAt(p), + style == SCE_PL_DEFAULT || style == SCE_PL_COMMENTLINE)) + p--; +} + +static int styleBeforeBracePair(Accessor &styler, unsigned int bk) +{ + // backtrack to find open '{' corresponding to a '}', balanced + // return significant style to be tested for '/' disambiguation + int braceCount = 1; + if (bk == 0) + return SCE_PL_DEFAULT; + while (--bk > 0) { + if (styler.StyleAt(bk) == SCE_PL_OPERATOR) { + int bkch = static_cast(styler.SafeGetCharAt(bk)); + if (bkch == ';') { // early out + break; + } else if (bkch == '}') { + braceCount++; + } else if (bkch == '{') { + if (--braceCount == 0) break; + } + } + } + if (bk > 0 && braceCount == 0) { + // balanced { found, bk > 0, skip more whitespace/comments + bk--; + skipWhitespaceComment(styler, bk); + return styler.StyleAt(bk); + } + return SCE_PL_DEFAULT; +} + +static int styleCheckIdentifier(Accessor &styler, unsigned int bk) +{ + // backtrack to classify sub-styles of identifier under test + // return sub-style to be tested for '/' disambiguation + if (styler.SafeGetCharAt(bk) == '>') // inputsymbol, like + return 1; + // backtrack to check for possible "->" or "::" before identifier + while (bk > 0 && styler.StyleAt(bk) == SCE_PL_IDENTIFIER) { + bk--; + } + while (bk > 0) { + int bkstyle = styler.StyleAt(bk); + if (bkstyle == SCE_PL_DEFAULT + || bkstyle == SCE_PL_COMMENTLINE) { + // skip whitespace, comments + } else if (bkstyle == SCE_PL_OPERATOR) { + // test for "->" and "::" + if (styler.Match(bk - 1, "->") || styler.Match(bk - 1, "::")) + return 2; + } else + return 3; // bare identifier + bk--; + } + return 0; +} + +static int inputsymbolScan(Accessor &styler, unsigned int pos, unsigned int endPos) +{ + // looks forward for matching > on same line; a bit ugly + unsigned int fw = pos; + while (++fw < endPos) { + int fwch = static_cast(styler.SafeGetCharAt(fw)); + if (fwch == '\r' || fwch == '\n') { + return 0; + } else if (fwch == '>') { + if (styler.Match(fw - 2, "<=>")) // '<=>' case + return 0; + return fw - pos; + } + } + return 0; +} + +static int podLineScan(Accessor &styler, unsigned int &pos, unsigned int endPos) +{ + // forward scan the current line to classify line for POD style + int state = -1; + while (pos <= endPos) { + int ch = static_cast(styler.SafeGetCharAt(pos)); + if (ch == '\n' || ch == '\r' || pos >= endPos) { + if (ch == '\r' && styler.SafeGetCharAt(pos + 1) == '\n') pos++; + break; + } + if (IsASpaceOrTab(ch)) { // whitespace, take note + if (state == -1) + state = SCE_PL_DEFAULT; + } else if (state == SCE_PL_DEFAULT) { // verbatim POD line + state = SCE_PL_POD_VERB; + } else if (state != SCE_PL_POD_VERB) { // regular POD line + state = SCE_PL_POD; + } + pos++; + } + if (state == -1) + state = SCE_PL_DEFAULT; + return state; +} + +static bool styleCheckSubPrototype(Accessor &styler, unsigned int bk) +{ + // backtrack to identify if we're starting a subroutine prototype + // we also need to ignore whitespace/comments: + // 'sub' [whitespace|comment] [whitespace|comment] + styler.Flush(); + skipWhitespaceComment(styler, bk); + if (bk == 0 || styler.StyleAt(bk) != SCE_PL_IDENTIFIER) // check identifier + return false; + while (bk > 0 && (styler.StyleAt(bk) == SCE_PL_IDENTIFIER)) { + bk--; + } + skipWhitespaceComment(styler, bk); + if (bk < 2 || styler.StyleAt(bk) != SCE_PL_WORD // check "sub" keyword + || !styler.Match(bk - 2, "sub")) // assume suffix is unique! + return false; + return true; +} + +static bool isMatch(const char *sref, char *s) +{ + // match per-line delimiter - must kill trailing CR if CRLF + int i = strlen(s); + if (i != 0 && s[i - 1] == '\r') + s[i - 1] = '\0'; + return (strcmp(sref, s) == 0); +} + +static int actualNumStyle(int numberStyle) { + if (numberStyle == PERLNUM_VECTOR || numberStyle == PERLNUM_V_VECTOR) { + return SCE_PL_STRING; + } else if (numberStyle == PERLNUM_BAD) { + return SCE_PL_ERROR; + } + return SCE_PL_NUMBER; +} + +static int opposite(int ch) { + if (ch == '(') return ')'; + if (ch == '[') return ']'; + if (ch == '{') return '}'; + if (ch == '<') return '>'; + return ch; +} + +static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + + // keywords that forces /PATTERN/ at all times; should track vim's behaviour + WordList reWords; + reWords.Set("elsif if split while"); + + // charset classes + CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true); + CharacterSet setSingleCharOp(CharacterSet::setNone, "rwxoRWXOezsfdlpSbctugkTBMAC"); + // lexing of "%*,?!.~"); + CharacterSet setQDelim(CharacterSet::setNone, "qrwx"); + CharacterSet setModifiers(CharacterSet::setAlpha); + CharacterSet setPreferRE(CharacterSet::setNone, "*/<%"); + // setArray and setHash also accepts chars for special vars like $_, + // which are then truncated when the next char does not match setVar + CharacterSet setVar(CharacterSet::setAlphaNum, "#$_'", 0x80, true); + CharacterSet setArray(CharacterSet::setAlpha, "#$_+-", 0x80, true); + CharacterSet setHash(CharacterSet::setAlpha, "#$_!^+-", 0x80, true); + CharacterSet &setPOD = setModifiers; + CharacterSet setNonHereDoc(CharacterSet::setDigits, "=$@"); + CharacterSet setHereDocDelim(CharacterSet::setAlphaNum, "_"); + CharacterSet setSubPrototype(CharacterSet::setNone, "\\[$@%&*];"); + // for format identifiers + CharacterSet setFormatStart(CharacterSet::setAlpha, "_="); + CharacterSet &setFormat = setHereDocDelim; + + // Lexer for perl often has to backtrack to start of current style to determine + // which characters are being used as quotes, how deeply nested is the + // start position and what the termination string is for HERE documents. + + class HereDocCls { // Class to manage HERE doc sequence + public: + int State; // 0: '<<' encountered + // 1: collect the delimiter + // 2: here doc text (lines after the delimiter) + int Quote; // the char after '<<' + bool Quoted; // true if Quote in ('\'','"','`') + int DelimiterLength; // strlen(Delimiter) + char *Delimiter; // the Delimiter, 256: sizeof PL_tokenbuf + HereDocCls() { + State = 0; + Quote = 0; + Quoted = false; + DelimiterLength = 0; + Delimiter = new char[HERE_DELIM_MAX]; + Delimiter[0] = '\0'; + } + void Append(int ch) { + Delimiter[DelimiterLength++] = static_cast(ch); + Delimiter[DelimiterLength] = '\0'; + } + ~HereDocCls() { + delete []Delimiter; + } + }; + HereDocCls HereDoc; // TODO: FIFO for stacked here-docs + + class QuoteCls { // Class to manage quote pairs + public: + int Rep; + int Count; + int Up, Down; + QuoteCls() { + this->New(1); + } + void New(int r = 1) { + Rep = r; + Count = 0; + Up = '\0'; + Down = '\0'; + } + void Open(int u) { + Count++; + Up = u; + Down = opposite(Up); + } + }; + QuoteCls Quote; + + // additional state for number lexing + int numState = PERLNUM_DECIMAL; + int dotCount = 0; + + unsigned int endPos = startPos + length; + + // Backtrack to beginning of style if required... + // If in a long distance lexical state, backtrack to find quote characters. + // Includes strings (may be multi-line), numbers (additional state), format + // bodies, as well as POD sections. + if (initStyle == SCE_PL_HERE_Q + || initStyle == SCE_PL_HERE_QQ + || initStyle == SCE_PL_HERE_QX + || initStyle == SCE_PL_FORMAT + ) { + int delim = (initStyle == SCE_PL_FORMAT) ? SCE_PL_FORMAT_IDENT:SCE_PL_HERE_DELIM; + while ((startPos > 1) && (styler.StyleAt(startPos) != delim)) { + startPos--; + } + startPos = styler.LineStart(styler.GetLine(startPos)); + initStyle = styler.StyleAt(startPos - 1); + } + if (initStyle == SCE_PL_STRING_Q + || initStyle == SCE_PL_STRING_QQ + || initStyle == SCE_PL_STRING_QX + || initStyle == SCE_PL_STRING_QR + || initStyle == SCE_PL_STRING_QW + || initStyle == SCE_PL_REGEX + || initStyle == SCE_PL_REGSUBST + || initStyle == SCE_PL_STRING + || initStyle == SCE_PL_BACKTICKS + || initStyle == SCE_PL_CHARACTER + || initStyle == SCE_PL_NUMBER + || initStyle == SCE_PL_IDENTIFIER + || initStyle == SCE_PL_ERROR + || initStyle == SCE_PL_SUB_PROTOTYPE + ) { + while ((startPos > 1) && (styler.StyleAt(startPos - 1) == initStyle)) { + startPos--; + } + initStyle = SCE_PL_DEFAULT; + } else if (initStyle == SCE_PL_POD + || initStyle == SCE_PL_POD_VERB + ) { + // POD backtracking finds preceeding blank lines and goes back past them + int ln = styler.GetLine(startPos); + if (ln > 0) { + initStyle = styler.StyleAt(styler.LineStart(--ln)); + if (initStyle == SCE_PL_POD || initStyle == SCE_PL_POD_VERB) { + while (ln > 0 && styler.GetLineState(ln) == SCE_PL_DEFAULT) + ln--; + } + startPos = styler.LineStart(++ln); + initStyle = styler.StyleAt(startPos - 1); + } else { + startPos = 0; + initStyle = SCE_PL_DEFAULT; + } + } + + // backFlag, backPos are additional state to aid identifier corner cases. + // Look backwards past whitespace and comments in order to detect either + // operator or keyword. Later updated as we go along. + int backFlag = BACK_NONE; + unsigned int backPos = startPos; + if (backPos > 0) { + backPos--; + skipWhitespaceComment(styler, backPos); + if (styler.StyleAt(backPos) == SCE_PL_OPERATOR) + backFlag = BACK_OPERATOR; + else if (styler.StyleAt(backPos) == SCE_PL_WORD) + backFlag = BACK_KEYWORD; + backPos++; + } + + StyleContext sc(startPos, endPos - startPos, initStyle, styler, static_cast(STYLE_MAX)); + + for (; sc.More(); sc.Forward()) { + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_PL_OPERATOR: + sc.SetState(SCE_PL_DEFAULT); + backFlag = BACK_OPERATOR; + backPos = sc.currentPos; + break; + case SCE_PL_IDENTIFIER: // identifier, bareword, inputsymbol + if ((!setWord.Contains(sc.ch) && sc.ch != '\'') + || sc.Match('.', '.') + || sc.chPrev == '>') { // end of inputsymbol + sc.SetState(SCE_PL_DEFAULT); + } + break; + case SCE_PL_WORD: // keyword, plus special cases + if (!setWord.Contains(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + if ((strcmp(s, "__DATA__") == 0) || (strcmp(s, "__END__") == 0)) { + sc.ChangeState(SCE_PL_DATASECTION); + } else { + if ((strcmp(s, "format") == 0)) { + sc.SetState(SCE_PL_FORMAT_IDENT); + HereDoc.State = 0; + } else { + sc.SetState(SCE_PL_DEFAULT); + } + backFlag = BACK_KEYWORD; + backPos = sc.currentPos; + } + } + break; + case SCE_PL_SCALAR: + case SCE_PL_ARRAY: + case SCE_PL_HASH: + case SCE_PL_SYMBOLTABLE: + if (sc.Match(':', ':')) { // skip :: + sc.Forward(); + } else if (!setVar.Contains(sc.ch)) { + if (sc.LengthCurrent() == 1) { + // Special variable: $(, $_ etc. + sc.Forward(); + } + sc.SetState(SCE_PL_DEFAULT); + } + break; + case SCE_PL_NUMBER: + // if no early break, number style is terminated at "(go through)" + if (sc.ch == '.') { + if (sc.chNext == '.') { + // double dot is always an operator (go through) + } else if (numState <= PERLNUM_FLOAT_EXP) { + // non-decimal number or float exponent, consume next dot + sc.SetState(SCE_PL_OPERATOR); + break; + } else { // decimal or vectors allows dots + dotCount++; + if (numState == PERLNUM_DECIMAL) { + if (dotCount <= 1) // number with one dot in it + break; + if (IsADigit(sc.chNext)) { // really a vector + numState = PERLNUM_VECTOR; + break; + } + // number then dot (go through) + } else if (IsADigit(sc.chNext)) // vectors + break; + // vector then dot (go through) + } + } else if (sc.ch == '_') { + // permissive underscoring for number and vector literals + break; + } else if (numState == PERLNUM_DECIMAL) { + if (sc.ch == 'E' || sc.ch == 'e') { // exponent, sign + numState = PERLNUM_FLOAT_EXP; + if (sc.chNext == '+' || sc.chNext == '-') { + sc.Forward(); + } + break; + } else if (IsADigit(sc.ch)) + break; + // number then word (go through) + } else if (numState == PERLNUM_HEX) { + if (IsADigit(sc.ch, 16)) + break; + } else if (numState == PERLNUM_VECTOR || numState == PERLNUM_V_VECTOR) { + if (IsADigit(sc.ch)) // vector + break; + if (setWord.Contains(sc.ch) && dotCount == 0) { // change to word + sc.ChangeState(SCE_PL_IDENTIFIER); + break; + } + // vector then word (go through) + } else if (IsADigit(sc.ch)) { + if (numState == PERLNUM_FLOAT_EXP) { + break; + } else if (numState == PERLNUM_OCTAL) { + if (sc.ch <= '7') break; + } else if (numState == PERLNUM_BINARY) { + if (sc.ch <= '1') break; + } + // mark invalid octal, binary numbers (go through) + numState = PERLNUM_BAD; + break; + } + // complete current number or vector + sc.ChangeState(actualNumStyle(numState)); + sc.SetState(SCE_PL_DEFAULT); + break; + case SCE_PL_COMMENTLINE: + if (sc.atLineEnd) { + sc.SetState(SCE_PL_DEFAULT); + } + break; + case SCE_PL_HERE_DELIM: + if (HereDoc.State == 0) { // '<<' encountered + int delim_ch = sc.chNext; + int ws_skip = 0; + HereDoc.State = 1; // pre-init HERE doc class + HereDoc.Quote = sc.chNext; + HereDoc.Quoted = false; + HereDoc.DelimiterLength = 0; + HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; + if (IsASpaceOrTab(delim_ch)) { + // skip whitespace; legal only for quoted delimiters + unsigned int i = sc.currentPos + 1; + while ((i < endPos) && IsASpaceOrTab(delim_ch)) { + i++; + delim_ch = static_cast(styler.SafeGetCharAt(i)); + } + ws_skip = i - sc.currentPos - 1; + } + if (delim_ch == '\'' || delim_ch == '"' || delim_ch == '`') { + // a quoted here-doc delimiter; skip any whitespace + sc.Forward(ws_skip + 1); + HereDoc.Quote = delim_ch; + HereDoc.Quoted = true; + } else if ((ws_skip == 0 && setNonHereDoc.Contains(sc.chNext)) + || ws_skip > 0) { + // left shift << or <<= operator cases + // restore position if operator + sc.ChangeState(SCE_PL_OPERATOR); + sc.ForwardSetState(SCE_PL_DEFAULT); + backFlag = BACK_OPERATOR; + backPos = sc.currentPos; + HereDoc.State = 0; + } else { + // specially handle initial '\' for identifier + if (ws_skip == 0 && HereDoc.Quote == '\\') + sc.Forward(); + // an unquoted here-doc delimiter, no special handling + // (cannot be prefixed by spaces/tabs), or + // symbols terminates; deprecated zero-length delimiter + } + } else if (HereDoc.State == 1) { // collect the delimiter + backFlag = BACK_NONE; + if (HereDoc.Quoted) { // a quoted here-doc delimiter + if (sc.ch == HereDoc.Quote) { // closing quote => end of delimiter + sc.ForwardSetState(SCE_PL_DEFAULT); + } else if (!sc.atLineEnd) { + if (sc.Match('\\', static_cast(HereDoc.Quote))) { // escaped quote + sc.Forward(); + } + if (sc.ch != '\r') { // skip CR if CRLF + HereDoc.Append(sc.ch); + } + } + } else { // an unquoted here-doc delimiter + if (setHereDocDelim.Contains(sc.ch)) { + HereDoc.Append(sc.ch); + } else { + sc.SetState(SCE_PL_DEFAULT); + } + } + if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) { + sc.SetState(SCE_PL_ERROR); + HereDoc.State = 0; + } + } + break; + case SCE_PL_HERE_Q: + case SCE_PL_HERE_QQ: + case SCE_PL_HERE_QX: { + // also implies HereDoc.State == 2 + sc.Complete(); + while (!sc.atLineEnd) + sc.Forward(); + char s[HERE_DELIM_MAX]; + sc.GetCurrent(s, sizeof(s)); + if (isMatch(HereDoc.Delimiter, s)) { + sc.SetState(SCE_PL_DEFAULT); + backFlag = BACK_NONE; + HereDoc.State = 0; + } + } break; + case SCE_PL_POD: + case SCE_PL_POD_VERB: { + unsigned int fw = sc.currentPos; + int ln = styler.GetLine(fw); + if (sc.atLineStart && sc.Match("=cut")) { // end of POD + sc.SetState(SCE_PL_POD); + sc.Forward(4); + sc.SetState(SCE_PL_DEFAULT); + styler.SetLineState(ln, SCE_PL_POD); + break; + } + int pod = podLineScan(styler, fw, endPos); // classify POD line + styler.SetLineState(ln, pod); + if (pod == SCE_PL_DEFAULT) { + if (sc.state == SCE_PL_POD_VERB) { + unsigned int fw2 = fw; + while (fw2 <= endPos && pod == SCE_PL_DEFAULT) { + fw = fw2++; // penultimate line (last blank line) + pod = podLineScan(styler, fw2, endPos); + styler.SetLineState(styler.GetLine(fw2), pod); + } + if (pod == SCE_PL_POD) { // truncate verbatim POD early + sc.SetState(SCE_PL_POD); + } else + fw = fw2; + } else + pod = SCE_PL_POD; + } else { + if (pod == SCE_PL_POD_VERB // still part of current paragraph + && (styler.GetLineState(ln - 1) == SCE_PL_POD)) { + pod = SCE_PL_POD; + styler.SetLineState(ln, pod); + } else if (pod == SCE_PL_POD + && (styler.GetLineState(ln - 1) == SCE_PL_POD_VERB)) { + pod = SCE_PL_POD_VERB; + styler.SetLineState(ln, pod); + } + sc.SetState(pod); + } + sc.Forward(fw - sc.currentPos); // commit style + } break; + case SCE_PL_REGEX: + case SCE_PL_STRING_QR: + if (Quote.Rep <= 0) { + if (!setModifiers.Contains(sc.ch)) + sc.SetState(SCE_PL_DEFAULT); + } else if (!Quote.Up && !IsASpace(sc.ch)) { + Quote.Open(sc.ch); + } else if (sc.ch == '\\' && Quote.Up != '\\') { + sc.Forward(); + } else if (sc.ch == Quote.Down) { + Quote.Count--; + if (Quote.Count == 0) + Quote.Rep--; + } else if (sc.ch == Quote.Up) { + Quote.Count++; + } + break; + case SCE_PL_REGSUBST: + if (Quote.Rep <= 0) { + if (!setModifiers.Contains(sc.ch)) + sc.SetState(SCE_PL_DEFAULT); + } else if (!Quote.Up && !IsASpace(sc.ch)) { + Quote.Open(sc.ch); + } else if (sc.ch == '\\' && Quote.Up != '\\') { + sc.Forward(); + } else if (Quote.Count == 0 && Quote.Rep == 1) { + // We matched something like s(...) or tr{...}, Perl 5.10 + // appears to allow almost any character for use as the + // next delimiters. Whitespace and comments are accepted in + // between, but we'll limit to whitespace here. + // For '#', if no whitespace in between, it's a delimiter. + if (IsASpace(sc.ch)) { + // Keep going + } else if (sc.ch == '#' && IsASpaceOrTab(sc.chPrev)) { + sc.SetState(SCE_PL_DEFAULT); + } else { + Quote.Open(sc.ch); + } + } else if (sc.ch == Quote.Down) { + Quote.Count--; + if (Quote.Count == 0) + Quote.Rep--; + if (Quote.Up == Quote.Down) + Quote.Count++; + } else if (sc.ch == Quote.Up) { + Quote.Count++; + } + break; + case SCE_PL_STRING_Q: + case SCE_PL_STRING_QQ: + case SCE_PL_STRING_QX: + case SCE_PL_STRING_QW: + case SCE_PL_STRING: + case SCE_PL_CHARACTER: + case SCE_PL_BACKTICKS: + if (!Quote.Down && !IsASpace(sc.ch)) { + Quote.Open(sc.ch); + } else if (sc.ch == '\\' && Quote.Up != '\\') { + sc.Forward(); + } else if (sc.ch == Quote.Down) { + Quote.Count--; + if (Quote.Count == 0) + sc.ForwardSetState(SCE_PL_DEFAULT); + } else if (sc.ch == Quote.Up) { + Quote.Count++; + } + break; + case SCE_PL_SUB_PROTOTYPE: { + int i = 0; + // forward scan; must all be valid proto characters + while (setSubPrototype.Contains(sc.GetRelative(i))) + i++; + if (sc.GetRelative(i) == ')') { // valid sub prototype + sc.Forward(i); + sc.ForwardSetState(SCE_PL_DEFAULT); + } else { + // abandon prototype, restart from '(' + sc.ChangeState(SCE_PL_OPERATOR); + sc.SetState(SCE_PL_DEFAULT); + } + } break; + case SCE_PL_FORMAT: { + sc.Complete(); + while (!sc.atLineEnd) + sc.Forward(); + char s[10]; + sc.GetCurrent(s, sizeof(s)); + if (isMatch(".", s)) + sc.SetState(SCE_PL_DEFAULT); + } break; + case SCE_PL_ERROR: + break; + } + // Needed for specific continuation styles (one follows the other) + switch (sc.state) { + // continued from SCE_PL_WORD + case SCE_PL_FORMAT_IDENT: + // occupies HereDoc state 3 to avoid clashing with HERE docs + if (IsASpaceOrTab(sc.ch)) { // skip whitespace + sc.ChangeState(SCE_PL_DEFAULT); + while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) + sc.Forward(); + sc.SetState(SCE_PL_FORMAT_IDENT); + } + if (setFormatStart.Contains(sc.ch)) { // identifier or '=' + if (sc.ch != '=') { + do { + sc.Forward(); + } while (setFormat.Contains(sc.ch)); + } + while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) + sc.Forward(); + if (sc.ch == '=') { + sc.ForwardSetState(SCE_PL_DEFAULT); + HereDoc.State = 3; + } else { + // invalid indentifier; inexact fallback, but hey + sc.ChangeState(SCE_PL_IDENTIFIER); + sc.SetState(SCE_PL_DEFAULT); + } + } else { + sc.ChangeState(SCE_PL_DEFAULT); // invalid indentifier + } + backFlag = BACK_NONE; + break; + } + + // Must check end of HereDoc states here before default state is handled + if (HereDoc.State == 1 && sc.atLineEnd) { + // Begin of here-doc (the line after the here-doc delimiter): + // Lexically, the here-doc starts from the next line after the >>, but the + // first line of here-doc seem to follow the style of the last EOL sequence + int st_new = SCE_PL_HERE_QQ; + HereDoc.State = 2; + if (HereDoc.Quoted) { + if (sc.state == SCE_PL_HERE_DELIM) { + // Missing quote at end of string! We are stricter than perl. + // Colour here-doc anyway while marking this bit as an error. + sc.ChangeState(SCE_PL_ERROR); + } + switch (HereDoc.Quote) { + case '\'': st_new = SCE_PL_HERE_Q ; break; + case '"' : st_new = SCE_PL_HERE_QQ; break; + case '`' : st_new = SCE_PL_HERE_QX; break; + } + } else { + if (HereDoc.Quote == '\\') + st_new = SCE_PL_HERE_Q; + } + sc.SetState(st_new); + } + if (HereDoc.State == 3 && sc.atLineEnd) { + // Start of format body. + HereDoc.State = 0; + sc.SetState(SCE_PL_FORMAT); + } + + // Determine if a new state should be entered. + if (sc.state == SCE_PL_DEFAULT) { + if (IsADigit(sc.ch) || + (IsADigit(sc.chNext) && (sc.ch == '.' || sc.ch == 'v'))) { + sc.SetState(SCE_PL_NUMBER); + backFlag = BACK_NONE; + numState = PERLNUM_DECIMAL; + dotCount = 0; + if (sc.ch == '0') { // hex,bin,octal + if (sc.chNext == 'x') { + numState = PERLNUM_HEX; + } else if (sc.chNext == 'b') { + numState = PERLNUM_BINARY; + } else if (IsADigit(sc.chNext)) { + numState = PERLNUM_OCTAL; + } + if (numState != PERLNUM_DECIMAL) { + sc.Forward(); + } + } else if (sc.ch == 'v') { // vector + numState = PERLNUM_V_VECTOR; + } + } else if (setWord.Contains(sc.ch)) { + // if immediately prefixed by '::', always a bareword + sc.SetState(SCE_PL_WORD); + if (sc.chPrev == ':' && sc.GetRelative(-2) == ':') { + sc.ChangeState(SCE_PL_IDENTIFIER); + } + unsigned int bk = sc.currentPos; + unsigned int fw = sc.currentPos + 1; + // first check for possible quote-like delimiter + if (sc.ch == 's' && !setWord.Contains(sc.chNext)) { + sc.ChangeState(SCE_PL_REGSUBST); + Quote.New(2); + } else if (sc.ch == 'm' && !setWord.Contains(sc.chNext)) { + sc.ChangeState(SCE_PL_REGEX); + Quote.New(); + } else if (sc.ch == 'q' && !setWord.Contains(sc.chNext)) { + sc.ChangeState(SCE_PL_STRING_Q); + Quote.New(); + } else if (sc.ch == 'y' && !setWord.Contains(sc.chNext)) { + sc.ChangeState(SCE_PL_REGSUBST); + Quote.New(2); + } else if (sc.Match('t', 'r') && !setWord.Contains(sc.GetRelative(2))) { + sc.ChangeState(SCE_PL_REGSUBST); + Quote.New(2); + sc.Forward(); + fw++; + } else if (sc.ch == 'q' && setQDelim.Contains(sc.chNext) + && !setWord.Contains(sc.GetRelative(2))) { + if (sc.chNext == 'q') sc.ChangeState(SCE_PL_STRING_QQ); + else if (sc.chNext == 'x') sc.ChangeState(SCE_PL_STRING_QX); + else if (sc.chNext == 'r') sc.ChangeState(SCE_PL_STRING_QR); + else sc.ChangeState(SCE_PL_STRING_QW); // sc.chNext == 'w' + Quote.New(); + sc.Forward(); + fw++; + } else if (sc.ch == 'x' && (sc.chNext == '=' || // repetition + !setWord.Contains(sc.chNext) || + (IsADigit(sc.chPrev) && IsADigit(sc.chNext)))) { + sc.ChangeState(SCE_PL_OPERATOR); + } + // if potentially a keyword, scan forward and grab word, then check + // if it's really one; if yes, disambiguation test is performed + // otherwise it is always a bareword and we skip a lot of scanning + if (sc.state == SCE_PL_WORD) { + while (setWord.Contains(static_cast(styler.SafeGetCharAt(fw)))) + fw++; + if (!isPerlKeyword(styler.GetStartSegment(), fw, keywords, styler)) { + sc.ChangeState(SCE_PL_IDENTIFIER); + } + } + // if already SCE_PL_IDENTIFIER, then no ambiguity, skip this + // for quote-like delimiters/keywords, attempt to disambiguate + // to select for bareword, change state -> SCE_PL_IDENTIFIER + if (sc.state != SCE_PL_IDENTIFIER && bk > 0) { + if (disambiguateBareword(styler, bk, fw, backFlag, backPos, endPos)) + sc.ChangeState(SCE_PL_IDENTIFIER); + } + backFlag = BACK_NONE; + } else if (sc.ch == '#') { + sc.SetState(SCE_PL_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_PL_STRING); + Quote.New(); + Quote.Open(sc.ch); + backFlag = BACK_NONE; + } else if (sc.ch == '\'') { + if (sc.chPrev == '&' && setWordStart.Contains(sc.chNext)) { + // Archaic call + sc.SetState(SCE_PL_IDENTIFIER); + } else { + sc.SetState(SCE_PL_CHARACTER); + Quote.New(); + Quote.Open(sc.ch); + } + backFlag = BACK_NONE; + } else if (sc.ch == '`') { + sc.SetState(SCE_PL_BACKTICKS); + Quote.New(); + Quote.Open(sc.ch); + backFlag = BACK_NONE; + } else if (sc.ch == '$') { + sc.SetState(SCE_PL_SCALAR); + if (sc.chNext == '{') { + sc.ForwardSetState(SCE_PL_OPERATOR); + } else if (IsASpace(sc.chNext)) { + sc.ForwardSetState(SCE_PL_DEFAULT); + } else { + sc.Forward(); + if (sc.Match('`', '`') || sc.Match(':', ':')) { + sc.Forward(); + } + } + backFlag = BACK_NONE; + } else if (sc.ch == '@') { + sc.SetState(SCE_PL_ARRAY); + if (setArray.Contains(sc.chNext)) { + // no special treatment + } else if (sc.chNext == ':' && sc.GetRelative(2) == ':') { + sc.Forward(2); + } else if (sc.chNext == '{' || sc.chNext == '[') { + sc.ForwardSetState(SCE_PL_OPERATOR); + } else { + sc.ChangeState(SCE_PL_OPERATOR); + } + backFlag = BACK_NONE; + } else if (setPreferRE.Contains(sc.ch)) { + // Explicit backward peeking to set a consistent preferRE for + // any slash found, so no longer need to track preferRE state. + // Find first previous significant lexed element and interpret. + // A few symbols shares this code for disambiguation. + bool preferRE = false; + bool isHereDoc = sc.Match('<', '<'); + bool hereDocSpace = false; // for: SCALAR [whitespace] '<<' + unsigned int bk = (sc.currentPos > 0) ? sc.currentPos - 1: 0; + unsigned int bkend; + sc.Complete(); + styler.Flush(); + if (styler.StyleAt(bk) == SCE_PL_DEFAULT) + hereDocSpace = true; + skipWhitespaceComment(styler, bk); + if (bk == 0) { + // avoid backward scanning breakage + preferRE = true; + } else { + int bkstyle = styler.StyleAt(bk); + int bkch = static_cast(styler.SafeGetCharAt(bk)); + switch(bkstyle) { + case SCE_PL_OPERATOR: + preferRE = true; + if (bkch == ')' || bkch == ']') { + preferRE = false; + } else if (bkch == '}') { + // backtrack by counting balanced brace pairs + // needed to test for variables like ${}, @{} etc. + bkstyle = styleBeforeBracePair(styler, bk); + if (bkstyle == SCE_PL_SCALAR + || bkstyle == SCE_PL_ARRAY + || bkstyle == SCE_PL_HASH + || bkstyle == SCE_PL_SYMBOLTABLE + || bkstyle == SCE_PL_OPERATOR) { + preferRE = false; + } + } else if (bkch == '+' || bkch == '-') { + if (bkch == static_cast(styler.SafeGetCharAt(bk - 1)) + && bkch != static_cast(styler.SafeGetCharAt(bk - 2))) + // exceptions for operators: unary suffixes ++, -- + preferRE = false; + } + break; + case SCE_PL_IDENTIFIER: + preferRE = true; + bkstyle = styleCheckIdentifier(styler, bk); + if ((bkstyle == 1) || (bkstyle == 2)) { + // inputsymbol or var with "->" or "::" before identifier + preferRE = false; + } else if (bkstyle == 3) { + // bare identifier, test cases follows: + if (sc.ch == '/') { + // if '/', /PATTERN/ unless digit/space immediately after '/' + // if '//', always expect defined-or operator to follow identifier + if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.chNext == '/') + preferRE = false; + } else if (sc.ch == '*' || sc.ch == '%') { + if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.Match('*', '*')) + preferRE = false; + } else if (sc.ch == '<') { + if (IsASpace(sc.chNext) || sc.chNext == '=') + preferRE = false; + } + } + break; + case SCE_PL_SCALAR: // for $var<< case: + if (isHereDoc && hereDocSpace) // if SCALAR whitespace '<<', *always* a HERE doc + preferRE = true; + break; + case SCE_PL_WORD: + preferRE = true; + // for HERE docs, always true + if (sc.ch == '/') { + // adopt heuristics similar to vim-style rules: + // keywords always forced as /PATTERN/: split, if, elsif, while + // everything else /PATTERN/ unless digit/space immediately after '/' + // for '//', defined-or favoured unless special keywords + bkend = bk + 1; + while (bk > 0 && styler.StyleAt(bk - 1) == SCE_PL_WORD) { + bk--; + } + if (isPerlKeyword(bk, bkend, reWords, styler)) + break; + if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.chNext == '/') + preferRE = false; + } else if (sc.ch == '*' || sc.ch == '%') { + if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.Match('*', '*')) + preferRE = false; + } else if (sc.ch == '<') { + if (IsASpace(sc.chNext) || sc.chNext == '=') + preferRE = false; + } + break; + // other styles uses the default, preferRE=false + case SCE_PL_POD: + case SCE_PL_HERE_Q: + case SCE_PL_HERE_QQ: + case SCE_PL_HERE_QX: + preferRE = true; + break; + } + } + backFlag = BACK_NONE; + if (isHereDoc) { // handle '<<', HERE doc + if (preferRE) { + sc.SetState(SCE_PL_HERE_DELIM); + HereDoc.State = 0; + } else { // << operator + sc.SetState(SCE_PL_OPERATOR); + sc.Forward(); + } + } else if (sc.ch == '*') { // handle '*', typeglob + if (preferRE) { + sc.SetState(SCE_PL_SYMBOLTABLE); + if (sc.chNext == ':' && sc.GetRelative(2) == ':') { + sc.Forward(2); + } else if (sc.chNext == '{') { + sc.ForwardSetState(SCE_PL_OPERATOR); + } else { + sc.Forward(); + } + } else { + sc.SetState(SCE_PL_OPERATOR); + if (sc.chNext == '*') // exponentiation + sc.Forward(); + } + } else if (sc.ch == '%') { // handle '%', hash + if (preferRE) { + sc.SetState(SCE_PL_HASH); + if (setHash.Contains(sc.chNext)) { + sc.Forward(); + } else if (sc.chNext == ':' && sc.GetRelative(2) == ':') { + sc.Forward(2); + } else if (sc.chNext == '{') { + sc.ForwardSetState(SCE_PL_OPERATOR); + } else { + sc.ChangeState(SCE_PL_OPERATOR); + } + } else { + sc.SetState(SCE_PL_OPERATOR); + } + } else if (sc.ch == '<') { // handle '<', inputsymbol + if (preferRE) { + // forward scan + int i = inputsymbolScan(styler, sc.currentPos, endPos); + if (i > 0) { + sc.SetState(SCE_PL_IDENTIFIER); + sc.Forward(i); + } else { + sc.SetState(SCE_PL_OPERATOR); + } + } else { + sc.SetState(SCE_PL_OPERATOR); + } + } else { // handle '/', regexp + if (preferRE) { + sc.SetState(SCE_PL_REGEX); + Quote.New(); + Quote.Open(sc.ch); + } else { // / and // operators + sc.SetState(SCE_PL_OPERATOR); + if (sc.chNext == '/') { + sc.Forward(); + } + } + } + } else if (sc.ch == '=' // POD + && setPOD.Contains(sc.chNext) + && sc.atLineStart) { + sc.SetState(SCE_PL_POD); + backFlag = BACK_NONE; + } else if (sc.ch == '-' && setWordStart.Contains(sc.chNext)) { // extended '-' cases + unsigned int bk = sc.currentPos; + unsigned int fw = 2; + if (setSingleCharOp.Contains(sc.chNext) && // file test operators + !setWord.Contains(sc.GetRelative(2))) { + sc.SetState(SCE_PL_WORD); + } else { + // nominally a minus and bareword; find extent of bareword + while (setWord.Contains(sc.GetRelative(fw))) + fw++; + sc.SetState(SCE_PL_OPERATOR); + } + // force to bareword for hash key => or {variable literal} cases + if (disambiguateBareword(styler, bk, bk + fw, backFlag, backPos, endPos) & 2) { + sc.ChangeState(SCE_PL_IDENTIFIER); + } + backFlag = BACK_NONE; + } else if (sc.ch == '(' && sc.currentPos > 0) { // '(' or subroutine prototype + sc.Complete(); + if (styleCheckSubPrototype(styler, sc.currentPos - 1)) { + sc.SetState(SCE_PL_SUB_PROTOTYPE); + backFlag = BACK_NONE; + } else { + sc.SetState(SCE_PL_OPERATOR); + } + } else if (setPerlOperator.Contains(sc.ch)) { // operators + sc.SetState(SCE_PL_OPERATOR); + if (sc.Match('.', '.')) { // .. and ... + sc.Forward(); + if (sc.chNext == '.') sc.Forward(); + } + } else if (sc.ch == 4 || sc.ch == 26) { // ^D and ^Z ends valid perl source + sc.SetState(SCE_PL_DATASECTION); + } else { + // keep colouring defaults + sc.Complete(); + } + } + } + sc.Complete(); +} + +static bool IsCommentLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eol_pos; i++) { + char ch = styler[i]; + int style = styler.StyleAt(i); + if (ch == '#' && style == SCE_PL_COMMENTLINE) + return true; + else if (!IsASpaceOrTab(ch)) + return false; + } + return false; +} + +static void FoldPerlDoc(unsigned int startPos, int length, int, WordList *[], + Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + // Custom folding of POD and packages + + // property fold.perl.pod + // Enable folding Pod blocks when using the Perl lexer. + bool foldPOD = styler.GetPropertyInt("fold.perl.pod", 1) != 0; + + // property fold.perl.package + // Enable folding packages when using the Perl lexer. + bool foldPackage = styler.GetPropertyInt("fold.perl.package", 1) != 0; + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelPrev = styler.LevelAt(lineCurrent - 1) >> 16; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + char chPrev = styler.SafeGetCharAt(startPos - 1); + int styleNext = styler.StyleAt(startPos); + // Used at end of line to determine if the line was a package definition + bool isPackageLine = false; + bool isPodHeading = false; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + bool atLineStart = ((chPrev == '\r') || (chPrev == '\n')) || i == 0; + // Comment folding + if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) + { + if (!IsCommentLine(lineCurrent - 1, styler) + && IsCommentLine(lineCurrent + 1, styler)) + levelCurrent++; + else if (IsCommentLine(lineCurrent - 1, styler) + && !IsCommentLine(lineCurrent+1, styler)) + levelCurrent--; + } + if (style == SCE_PL_OPERATOR) { + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + } + // Custom POD folding + if (foldPOD && atLineStart) { + int stylePrevCh = (i) ? styler.StyleAt(i - 1):SCE_PL_DEFAULT; + if (style == SCE_PL_POD) { + if (stylePrevCh != SCE_PL_POD && stylePrevCh != SCE_PL_POD_VERB) + levelCurrent++; + else if (styler.Match(i, "=cut")) + levelCurrent--; + else if (styler.Match(i, "=head")) + isPodHeading = true; + } else if (style == SCE_PL_DATASECTION) { + if (ch == '=' && isascii(chNext) && isalpha(chNext) && levelCurrent == SC_FOLDLEVELBASE) + levelCurrent++; + else if (styler.Match(i, "=cut") && levelCurrent > SC_FOLDLEVELBASE) + levelCurrent--; + else if (styler.Match(i, "=head")) + isPodHeading = true; + // if package used or unclosed brace, level > SC_FOLDLEVELBASE! + // reset needed as level test is vs. SC_FOLDLEVELBASE + else if (styler.Match(i, "__END__")) + levelCurrent = SC_FOLDLEVELBASE; + } + } + // Custom package folding + if (foldPackage && atLineStart) { + if (style == SCE_PL_WORD && styler.Match(i, "package")) { + isPackageLine = true; + } + } + + if (atEOL) { + int lev = levelPrev; + if (isPodHeading) { + lev = levelPrev - 1; + lev |= SC_FOLDLEVELHEADERFLAG; + isPodHeading = false; + } + // Check if line was a package declaration + // because packages need "special" treatment + if (isPackageLine) { + lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; + levelCurrent = SC_FOLDLEVELBASE + 1; + isPackageLine = false; + } + lev |= levelCurrent << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + chPrev = ch; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const perlWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmPerl(SCLEX_PERL, ColourisePerlDoc, "perl", FoldPerlDoc, perlWordListDesc, 8); diff --git a/lexers/LexPowerPro.cxx b/lexers/LexPowerPro.cxx new file mode 100644 index 000000000..9320baf94 --- /dev/null +++ b/lexers/LexPowerPro.cxx @@ -0,0 +1,600 @@ +// Scintilla source code edit control +// @file LexPowerPro.cxx +// PowerPro utility, written by Bruce Switzer, is available from http://powerpro.webeddie.com +// PowerPro lexer is written by Christopher Bean (cbean@cb-software.net) +// +// Lexer code heavily borrowed from: +// LexAU3.cxx by Jos van der Zande +// LexCPP.cxx by Neil Hodgson +// LexVB.cxx by Neil Hodgson +// +// Changes: +// 2008-10-25 - Initial release +// 2008-10-26 - Changed how is hilighted in 'function ' so that +// local isFunction = "" and local functions = "" don't get falsely highlighted +// 2008-12-14 - Added bounds checking for szKeyword and szDo +// - Replaced SetOfCharacters with CharacterSet +// - Made sure that CharacterSet::Contains is passed only positive values +// - Made sure that the return value of Accessor::SafeGetCharAt is positive before +// passsing to functions that require positive values like isspacechar() +// - Removed unused visibleChars processing from ColourisePowerProDoc() +// - Fixed bug with folding logic where line continuations didn't end where +// they were supposed to +// - Moved all helper functions to the top of the file +// +// Copyright 1998-2005 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "CharacterSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsStreamCommentStyle(int style) { + return style == SCE_POWERPRO_COMMENTBLOCK; +} + +static bool IsContinuationLine(unsigned int szLine, Accessor &styler) +{ + int nsPos = styler.LineStart(szLine); + int nePos = styler.LineStart(szLine + 1) - 2; + while (nsPos < nePos) + { + int stylech = styler.StyleAt(nsPos); + if (!(stylech == SCE_POWERPRO_COMMENTBLOCK)) { + char ch = styler.SafeGetCharAt(nePos); + char chPrev = styler.SafeGetCharAt(nePos-1); + char chPrevPrev = styler.SafeGetCharAt(nePos-2); + if (ch > 0 && chPrev > 0 && chPrevPrev > 0 && !isspacechar(ch) && !isspacechar(chPrev) && !isspacechar(chPrevPrev) ) { + if (chPrevPrev == ';' && chPrev == ';' && ch == '+') + return true; + else + return false; + } + } + nePos--; // skip to next char + } + return false; +} + +// Routine to find first none space on the current line and return its Style +// needed for comment lines not starting on pos 1 +static int GetStyleFirstWord(unsigned int szLine, Accessor &styler) +{ + int nsPos = styler.LineStart(szLine); + int nePos = styler.LineStart(szLine+1) - 1; + char ch = styler.SafeGetCharAt(nsPos); + + while (ch > 0 && isspacechar(ch) && nsPos < nePos) + { + nsPos++; // skip to next char + ch = styler.SafeGetCharAt(nsPos); + + } + return styler.StyleAt(nsPos); +} + +//returns true if there is a function to highlight +//used to highlight in 'function ' +static bool HasFunction(Accessor &styler, unsigned int currentPos) { + + //check for presence of 'function ' + return (styler.SafeGetCharAt(currentPos) == ' ' + && tolower(styler.SafeGetCharAt(currentPos-1)) == 'n' + && tolower(styler.SafeGetCharAt(currentPos-2)) == 'o' + && tolower(styler.SafeGetCharAt(currentPos-3)) == 'i' + && tolower(styler.SafeGetCharAt(currentPos-4)) == 't' + && tolower(styler.SafeGetCharAt(currentPos-5)) == 'c' + && tolower(styler.SafeGetCharAt(currentPos-6)) == 'n' + && tolower(styler.SafeGetCharAt(currentPos-7)) == 'u' + && tolower(styler.SafeGetCharAt(currentPos-8)) == 'f' + //only allow 'function ' to appear at the beginning of a line + && (styler.SafeGetCharAt(currentPos-9) == '\n' + || styler.SafeGetCharAt(currentPos-9) == '\r' + || (styler.SafeGetCharAt(currentPos -9, '\0')) == '\0') //is the first line + ); +} + +static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler, bool caseSensitive) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + + //define the character sets + CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); + + StyleContext sc(startPos, length, initStyle, styler); + char s_save[100]; //for last line highlighting + + for (; sc.More(); sc.Forward()) { + + // ********************************************** + // save the total current word for eof processing + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + + if ((sc.ch > 0) && setWord.Contains(sc.ch)) + { + strcpy(s_save,s); + int tp = strlen(s_save); + if (tp < 99) { + s_save[tp] = static_cast(tolower(sc.ch)); + s_save[tp+1] = '\0'; + } + } + // ********************************************** + // + + if (sc.atLineStart) { + if (sc.state == SCE_POWERPRO_DOUBLEQUOTEDSTRING) { + // Prevent SCE_POWERPRO_STRINGEOL from leaking back to previous line which + // ends with a line continuation by locking in the state upto this position. + sc.SetState(SCE_POWERPRO_DOUBLEQUOTEDSTRING); + } + } + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_POWERPRO_OPERATOR: + sc.SetState(SCE_POWERPRO_DEFAULT); + break; + + case SCE_POWERPRO_NUMBER: + + if (!IsADigit(sc.ch)) + sc.SetState(SCE_POWERPRO_DEFAULT); + + break; + + case SCE_POWERPRO_IDENTIFIER: + //if ((sc.ch > 0) && !setWord.Contains(sc.ch) || (sc.ch == '.')) { // use this line if don't want to match keywords with . in them. ie: win.debug will match both win and debug so win debug will also be colorized + if ((sc.ch > 0) && !setWord.Contains(sc.ch)){ // || (sc.ch == '.')) { // use this line if you want to match keywords with a . ie: win.debug will only match win.debug neither win nor debug will be colorized separately + char s[1000]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (keywords.InList(s)) { + sc.ChangeState(SCE_POWERPRO_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_POWERPRO_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_POWERPRO_WORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_POWERPRO_WORD4); + } + sc.SetState(SCE_POWERPRO_DEFAULT); + } + break; + + case SCE_POWERPRO_LINECONTINUE: + if (sc.atLineStart) { + sc.SetState(SCE_POWERPRO_DEFAULT); + } else if (sc.Match('/', '*') || sc.Match('/', '/')) { + sc.SetState(SCE_POWERPRO_DEFAULT); + } + break; + + case SCE_POWERPRO_COMMENTBLOCK: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_POWERPRO_DEFAULT); + } + break; + + case SCE_POWERPRO_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_POWERPRO_DEFAULT); + } + break; + + case SCE_POWERPRO_DOUBLEQUOTEDSTRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_POWERPRO_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_POWERPRO_DEFAULT); + } + break; + + case SCE_POWERPRO_SINGLEQUOTEDSTRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_POWERPRO_STRINGEOL); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_POWERPRO_DEFAULT); + } + break; + + case SCE_POWERPRO_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_POWERPRO_DEFAULT); + } + break; + + case SCE_POWERPRO_VERBATIM: + if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_POWERPRO_DEFAULT); + } + } + break; + + case SCE_POWERPRO_ALTQUOTE: + if (sc.ch == '#') { + if (sc.chNext == '#') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_POWERPRO_DEFAULT); + } + } + break; + + case SCE_POWERPRO_FUNCTION: + if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ' ' || sc.ch == '(') { + sc.SetState(SCE_POWERPRO_DEFAULT); + } + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_POWERPRO_DEFAULT) { + if (sc.Match('?', '\"')) { + sc.SetState(SCE_POWERPRO_VERBATIM); + sc.Forward(); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_POWERPRO_NUMBER); + }else if (sc.Match('?','#')) { + if (sc.ch == '?' && sc.chNext == '#') { + sc.SetState(SCE_POWERPRO_ALTQUOTE); + sc.Forward(); + } + } else if (HasFunction(styler, sc.currentPos)) { //highlight in 'function ' + sc.SetState(SCE_POWERPRO_FUNCTION); + } else if (sc.ch == '@' && sc.atLineStart) { //alternate function definition [label] + sc.SetState(SCE_POWERPRO_FUNCTION); + } else if ((sc.ch > 0) && (setWordStart.Contains(sc.ch) || (sc.ch == '?'))) { + sc.SetState(SCE_POWERPRO_IDENTIFIER); + } else if (sc.Match(";;+")) { + sc.SetState(SCE_POWERPRO_LINECONTINUE); + } else if (sc.Match('/', '*')) { + sc.SetState(SCE_POWERPRO_COMMENTBLOCK); + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + sc.SetState(SCE_POWERPRO_COMMENTLINE); + } else if (sc.atLineStart && sc.ch == ';') { //legacy comment that can only appear at the beginning of a line + sc.SetState(SCE_POWERPRO_COMMENTLINE); + } else if (sc.Match(";;")) { + sc.SetState(SCE_POWERPRO_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_POWERPRO_DOUBLEQUOTEDSTRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_POWERPRO_SINGLEQUOTEDSTRING); + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_POWERPRO_OPERATOR); + } + } + } + + //************************************* + // Colourize the last word correctly + //************************************* + if (sc.state == SCE_POWERPRO_IDENTIFIER) + { + if (keywords.InList(s_save)) { + sc.ChangeState(SCE_POWERPRO_WORD); + sc.SetState(SCE_POWERPRO_DEFAULT); + } + else if (keywords2.InList(s_save)) { + sc.ChangeState(SCE_POWERPRO_WORD2); + sc.SetState(SCE_POWERPRO_DEFAULT); + } + else if (keywords3.InList(s_save)) { + sc.ChangeState(SCE_POWERPRO_WORD3); + sc.SetState(SCE_POWERPRO_DEFAULT); + } + else if (keywords4.InList(s_save)) { + sc.ChangeState(SCE_POWERPRO_WORD4); + sc.SetState(SCE_POWERPRO_DEFAULT); + } + else { + sc.SetState(SCE_POWERPRO_DEFAULT); + } + } + sc.Complete(); +} + +static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) +{ + //define the character sets + CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); + + bool isFoldingAll = true; //used to tell if we're recursively folding the whole document, or just a small piece (ie: if statement or 1 function) + int endPos = startPos + length; + int lastLine = styler.GetLine(styler.Length()); //used to help fold the last line correctly + + // get settings from the config files for folding comments and preprocessor lines + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldInComment = styler.GetPropertyInt("fold.comment") == 2; + bool foldCompact = true; + + // Backtrack to previous line in case need to fix its fold status + int lineCurrent = styler.GetLine(startPos); + if (startPos > 0) { + isFoldingAll = false; + if (lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + } + // vars for style of previous/current/next lines + int style = GetStyleFirstWord(lineCurrent,styler); + int stylePrev = 0; + + // find the first previous line without continuation character at the end + while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || + (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + if (lineCurrent > 0) { + stylePrev = GetStyleFirstWord(lineCurrent-1,styler); + } + // vars for getting first word to check for keywords + bool FirstWordStart = false; + bool FirstWordEnd = false; + + const unsigned int KEYWORD_MAX = 10; + char szKeyword[KEYWORD_MAX]=""; + unsigned int szKeywordlen = 0; + + char szDo[3]=""; + int szDolen = 0; + bool DoFoundLast = false; + + // var for indentlevel + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) { + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + } + int levelNext = levelCurrent; + + int visibleChars = 0; + int functionCount = 0; + + char chNext = styler.SafeGetCharAt(startPos); + char chPrev = '\0'; + char chPrevPrev = '\0'; + char chPrevPrevPrev = '\0'; + + for (int i = startPos; i < endPos; i++) { + + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch > 0) && setWord.Contains(ch)) { + visibleChars++; + } + + // get the syle for the current character neede to check in comment + int stylech = styler.StyleAt(i); + + // get first word for the line for indent check max 9 characters + if (FirstWordStart && (!(FirstWordEnd))) { + if ((ch > 0) && !setWord.Contains(ch)) { + FirstWordEnd = true; + } + else if (szKeywordlen < KEYWORD_MAX - 1) { + szKeyword[szKeywordlen++] = static_cast(tolower(ch)); + szKeyword[szKeywordlen] = '\0'; + } + } + + // start the capture of the first word + if (!(FirstWordStart)) { + if ((ch > 0) && (setWord.Contains(ch) || setWordStart.Contains(ch) || ch == ';' || ch == '/')) { + FirstWordStart = true; + if (szKeywordlen < KEYWORD_MAX - 1) { + szKeyword[szKeywordlen++] = static_cast(tolower(ch)); + szKeyword[szKeywordlen] = '\0'; + } + } + } + // only process this logic when not in comment section + if (stylech != SCE_POWERPRO_COMMENTLINE) { + if (DoFoundLast) { + if (DoFoundLast && (ch > 0) && setWord.Contains(ch)) { + DoFoundLast = false; + } + } + // find out if the word "do" is the last on a "if" line + if (FirstWordEnd && strcmp(szKeyword,"if") == 0) { + if (szDolen == 2) { + szDo[0] = szDo[1]; + szDo[1] = static_cast(tolower(ch)); + szDo[2] = '\0'; + if (strcmp(szDo,"do") == 0 ) { + DoFoundLast = true; + } + } + else if (szDolen < 2) { + szDo[szDolen++] = static_cast(tolower(ch)); + szDo[szDolen] = '\0'; + } + } + } + + // End of Line found so process the information + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { + + // ************************** + // Folding logic for Keywords + // ************************** + + // if a keyword is found on the current line and the line doesn't end with ;;+ (continuation) + // and we are not inside a commentblock. + if (szKeywordlen > 0 && + (!(chPrev == '+' && chPrevPrev == ';' && chPrevPrevPrev ==';')) && + ((!(IsStreamCommentStyle(style)) || foldInComment)) ) { + + // only fold "if" last keyword is "then" (else its a one line if) + if (strcmp(szKeyword,"if") == 0 && DoFoundLast) { + levelNext++; + } + // create new fold for these words + if (strcmp(szKeyword,"for") == 0) { + levelNext++; + } + + //handle folding for functions/labels + //Note: Functions and labels don't have an explicit end like [end function] + // 1. functions/labels end at the start of another function + // 2. functions/labels end at the end of the file + if ((strcmp(szKeyword,"function") == 0) || (szKeywordlen > 0 && szKeyword[0] == '@')) { + if (isFoldingAll) { //if we're folding the whole document (recursivly by lua script) + + if (functionCount > 0) { + levelCurrent--; + } else { + levelNext++; + } + functionCount++; + + } else { //if just folding a small piece (by clicking on the minus sign next to the word) + levelCurrent--; + } + } + + // end the fold for these words before the current line + if (strcmp(szKeyword,"endif") == 0 || strcmp(szKeyword,"endfor") == 0) { + levelNext--; + levelCurrent--; + } + // end the fold for these words before the current line and Start new fold + if (strcmp(szKeyword,"else") == 0 || strcmp(szKeyword,"elseif") == 0 ) { + levelCurrent--; + } + } + // Preprocessor and Comment folding + int styleNext = GetStyleFirstWord(lineCurrent + 1,styler); + + // ********************************* + // Folding logic for Comment blocks + // ********************************* + if (foldComment && IsStreamCommentStyle(style)) { + // Start of a comment block + if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) { + levelNext++; + } + // fold till the last line for normal comment lines + else if (IsStreamCommentStyle(stylePrev) + && !(styleNext == SCE_POWERPRO_COMMENTLINE) + && stylePrev == SCE_POWERPRO_COMMENTLINE + && style == SCE_POWERPRO_COMMENTLINE) { + levelNext--; + } + // fold till the one but last line for Blockcomment lines + else if (IsStreamCommentStyle(stylePrev) + && !(styleNext == SCE_POWERPRO_COMMENTBLOCK) + && style == SCE_POWERPRO_COMMENTBLOCK) { + levelNext--; + levelCurrent--; + } + } + + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + + // reset values for the next line + lineCurrent++; + stylePrev = style; + style = styleNext; + levelCurrent = levelNext; + visibleChars = 0; + + // if the last characters are ;;+ then don't reset since the line continues on the next line. + if (chPrev == '+' && chPrevPrev == ';' && chPrevPrevPrev == ';') { + //do nothing + } else { + szKeywordlen = 0; + szDolen = 0; + FirstWordStart = false; + FirstWordEnd = false; + DoFoundLast = false; + //blank out keyword + for (unsigned int i = 0; i < KEYWORD_MAX; i++) { + szKeyword[i] = '\0'; + } + } + } + + // save the last processed characters + if ((ch > 0) && !isspacechar(ch)) { + chPrevPrevPrev = chPrevPrev; + chPrevPrev = chPrev; + chPrev = ch; + visibleChars++; + } + } + + //close folds on the last line - without this a 'phantom' + //fold can appear when an open fold is on the last line + //this can occur because functions and labels don't have an explicit end + if (lineCurrent >= lastLine) { + int lev = 0; + lev |= SC_FOLDLEVELWHITEFLAG; + styler.SetLevel(lineCurrent, lev); + } + +} + +static const char * const powerProWordLists[] = { + "Keyword list 1", + "Keyword list 2", + "Keyword list 3", + "Keyword list 4", + 0, + }; + +static void ColourisePowerProDocWrapper(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + ColourisePowerProDoc(startPos, length, initStyle, keywordlists, styler, false); +} + +LexerModule lmPowerPro(SCLEX_POWERPRO, ColourisePowerProDocWrapper, "powerpro", FoldPowerProDoc, powerProWordLists); diff --git a/lexers/LexPowerShell.cxx b/lexers/LexPowerShell.cxx new file mode 100644 index 000000000..f2014ca8d --- /dev/null +++ b/lexers/LexPowerShell.cxx @@ -0,0 +1,198 @@ +// Scintilla source code edit control +/** @file LexPowerShell.cxx + ** Lexer for PowerShell scripts. + **/ +// Copyright 2008 by Tim Gerundt +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// Extended to accept accented characters +static inline bool IsAWordChar(int ch) { + return ch >= 0x80 || isalnum(ch) || ch == '-'; +} + +static void ColourisePowerShellDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + + styler.StartAt(startPos); + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.state == SCE_POWERSHELL_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_POWERSHELL_DEFAULT); + } + } else if (sc.state == SCE_POWERSHELL_COMMENTSTREAM) { + if (sc.ch == '>' && sc.chPrev == '#') { + sc.ForwardSetState(SCE_POWERSHELL_DEFAULT); + } + } else if (sc.state == SCE_POWERSHELL_STRING) { + // This is a doubles quotes string + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_POWERSHELL_DEFAULT); + } + } else if (sc.state == SCE_POWERSHELL_CHARACTER) { + // This is a single quote string + if (sc.ch == '\'') { + sc.ForwardSetState(SCE_POWERSHELL_DEFAULT); + } + } else if (sc.state == SCE_POWERSHELL_NUMBER) { + if (!IsADigit(sc.ch)) { + sc.SetState(SCE_POWERSHELL_DEFAULT); + } + } else if (sc.state == SCE_POWERSHELL_VARIABLE) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_POWERSHELL_DEFAULT); + } + } else if (sc.state == SCE_POWERSHELL_OPERATOR) { + if (!isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_POWERSHELL_DEFAULT); + } + } else if (sc.state == SCE_POWERSHELL_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + + if (keywords.InList(s)) { + sc.ChangeState(SCE_POWERSHELL_KEYWORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_POWERSHELL_CMDLET); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_POWERSHELL_ALIAS); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_POWERSHELL_FUNCTION); + } else if (keywords5.InList(s)) { + sc.ChangeState(SCE_POWERSHELL_USER1); + } + sc.SetState(SCE_POWERSHELL_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_POWERSHELL_DEFAULT) { + if (sc.ch == '#') { + sc.SetState(SCE_POWERSHELL_COMMENT); + } else if (sc.ch == '<' && sc.chNext == '#') { + sc.SetState(SCE_POWERSHELL_COMMENTSTREAM); + } else if (sc.ch == '\"') { + sc.SetState(SCE_POWERSHELL_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_POWERSHELL_CHARACTER); + } else if (sc.ch == '$') { + sc.SetState(SCE_POWERSHELL_VARIABLE); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_POWERSHELL_NUMBER); + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_POWERSHELL_OPERATOR); + } else if (IsAWordChar(sc.ch)) { + sc.SetState(SCE_POWERSHELL_IDENTIFIER); + } + } + } + sc.Complete(); +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "} else {". +static void FoldPowerShellDoc(unsigned int startPos, int length, int initStyle, + WordList *[], Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (style == SCE_POWERSHELL_OPERATOR) { + if (ch == '{') { + // Measure the minimum before a '{' to allow + // folding on "} else {" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } else if (foldComment && style == SCE_POWERSHELL_COMMENTSTREAM) { + if (stylePrev != SCE_POWERSHELL_COMMENTSTREAM) { + levelNext++; + } else if (styleNext != SCE_POWERSHELL_COMMENTSTREAM) { + levelNext--; + } + } + if (!IsASpace(ch)) + visibleChars++; + if (atEOL || (i == endPos-1)) { + int levelUse = levelCurrent; + if (foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + visibleChars = 0; + } + } +} + +static const char * const powershellWordLists[] = { + "Commands", + "Cmdlets", + "Aliases", + "Functions", + "User1", + 0 +}; + +LexerModule lmPowerShell(SCLEX_POWERSHELL, ColourisePowerShellDoc, "powershell", FoldPowerShellDoc, powershellWordLists); + diff --git a/lexers/LexProgress.cxx b/lexers/LexProgress.cxx new file mode 100644 index 000000000..9e1940e29 --- /dev/null +++ b/lexers/LexProgress.cxx @@ -0,0 +1,279 @@ +// Scintilla source code edit control +/** @file LexProgress.cxx + ** Lexer for Progress 4GL. + ** Based on LexCPP.cxx of Neil Hodgson + **/ +// Copyright 2006-2007 by Yuval Papish +// The License.txt file describes the conditions under which this software may be distributed. + +/** TODO: +WebSpeed support in html lexer +Support "end triggers" expression of the triggers phrase +Support more than 6 comments levels +**/ +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordStart(int ch) { + return (ch < 0x80) && (isalpha(ch) || ch == '_'); +} + +enum SentenceStart { SetSentenceStart = 0xf, ResetSentenceStart = 0x10}; // true -> bit = 0 + +static void Colourise4glDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords1 = *keywordlists[0]; // regular keywords + WordList &keywords2 = *keywordlists[1]; // block opening keywords, only when SentenceStart + WordList &keywords3 = *keywordlists[2]; // block opening keywords + //WordList &keywords4 = *keywordlists[3]; // preprocessor keywords. Not implemented + + + int visibleChars = 0; + int mask; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart) { + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + } + + // Handle line continuation generically. + if ((sc.state & 0xf) < SCE_4GL_COMMENT1) { + if (sc.ch == '~') { + if (sc.chNext > ' ') { + // skip special char after ~ + sc.Forward(); + continue; + } + else { + // Skip whitespace between ~ and EOL + while (sc.More() && (sc.chNext == ' ' || sc.chNext == '\t') ) { + sc.Forward(); + } + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + sc.Forward(); + continue; + } + } + } + } + // Determine if a new state should be terminated. + mask = sc.state & 0x10; + switch (sc.state & 0xf) { + case SCE_4GL_OPERATOR: + sc.SetState(SCE_4GL_DEFAULT | mask); + break; + case SCE_4GL_NUMBER: + if (!(IsADigit(sc.ch))) { + sc.SetState(SCE_4GL_DEFAULT | mask); + } + break; + case SCE_4GL_IDENTIFIER: + if (!IsAWordChar(sc.ch) && sc.ch != '-') { + char s[1000]; + sc.GetCurrentLowered(s, sizeof(s)); + if ((((sc.state & 0x10) == 0) && keywords2.InList(s)) || keywords3.InList(s)) { + sc.ChangeState(SCE_4GL_BLOCK | ResetSentenceStart); + } + else if (keywords1.InList(s)) { + if ((s[0] == 'e' && s[1] =='n' && s[2] == 'd' && !isalnum(s[3]) && s[3] != '-') || + (s[0] == 'f' && s[1] =='o' && s[2] == 'r' && s[3] == 'w' && s[4] =='a' && s[5] == 'r' && s[6] == 'd'&& !isalnum(s[7]))) { + sc.ChangeState(SCE_4GL_END | ResetSentenceStart); + } + else if ((s[0] == 'e' && s[1] =='l' && s[2] == 's' && s[3] == 'e') || + (s[0] == 't' && s[1] =='h' && s[2] == 'e' && s[3] == 'n')) { + sc.ChangeState(SCE_4GL_WORD & SetSentenceStart); + } + else { + sc.ChangeState(SCE_4GL_WORD | ResetSentenceStart); + } + } + sc.SetState(SCE_4GL_DEFAULT | (sc.state & 0x10)); + } + break; + case SCE_4GL_PREPROCESSOR: + if (sc.atLineStart) { + sc.SetState(SCE_4GL_DEFAULT & SetSentenceStart); + } + /* code removed to allow comments inside preprocessor + else if (sc.ch == '*' && sc.chNext == '/') { + sc.ForwardSetState(SCE_4GL_DEFAULT | sentenceStartState); } */ + break; + case SCE_4GL_STRING: + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_4GL_DEFAULT | mask); + } + break; + case SCE_4GL_CHARACTER: + if (sc.ch == '\'') { + sc.ForwardSetState(SCE_4GL_DEFAULT | mask); + } + break; + default: + if ((sc.state & 0xf) >= SCE_4GL_COMMENT1) { + if (sc.ch == '*' && sc.chNext == '/') { + sc.Forward(); + if ((sc.state & 0xf) == SCE_4GL_COMMENT1) { + sc.ForwardSetState(SCE_4GL_DEFAULT | mask); + } + else + sc.SetState((sc.state & 0x1f) - 1); + } else if (sc.ch == '/' && sc.chNext == '*') { + sc.Forward(); + sc.SetState((sc.state & 0x1f) + 1); + } + } + } + + // Determine if a new state should be entered. + mask = sc.state & 0x10; + if ((sc.state & 0xf) == SCE_4GL_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_4GL_NUMBER | ResetSentenceStart); + } else if (IsAWordStart(sc.ch) || (sc.ch == '@')) { + sc.SetState(SCE_4GL_IDENTIFIER | mask); + } else if (sc.ch == '/' && sc.chNext == '*') { + sc.SetState(SCE_4GL_COMMENT1 | mask); + sc.Forward(); + } else if (sc.ch == '\"') { + sc.SetState(SCE_4GL_STRING | ResetSentenceStart); + } else if (sc.ch == '\'') { + sc.SetState(SCE_4GL_CHARACTER | ResetSentenceStart); + } else if (sc.ch == '&' && visibleChars == 0 && ((sc.state & 0x10) == 0)) { + sc.SetState(SCE_4GL_PREPROCESSOR | ResetSentenceStart); + // Skip whitespace between & and preprocessor word + do { + sc.Forward(); + } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); + // Handle syntactical line termination + } else if ((sc.ch == '.' || sc.ch == ':' || sc.ch == '}') && (sc.chNext == ' ' || sc.chNext == '\t' || sc.chNext == '\n' || sc.chNext == '\r')) { + sc.SetState(sc.state & SetSentenceStart); + } else if (isoperator(static_cast(sc.ch))) { + /* This code allows highlight of handles. Alas, it would cause the phrase "last-event:function" + to be recognized as a BlockBegin */ + + if (sc.ch == ':') + sc.SetState(SCE_4GL_OPERATOR & SetSentenceStart); + /* else */ + sc.SetState(SCE_4GL_OPERATOR | ResetSentenceStart); + } + } + + if (!IsASpace(sc.ch)) { + visibleChars++; + } + } + sc.Complete(); +} + +static bool IsStreamCommentStyle(int style) { + return (style & 0xf) >= SCE_4GL_COMMENT1 ; +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "} else {". +static void FoldNoBox4glDoc(unsigned int startPos, int length, int initStyle, + Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = static_cast(tolower(styler[startPos])); + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = static_cast(tolower(styler.SafeGetCharAt(i + 1))); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext)) { // && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + else if ((style & 0xf) == SCE_4GL_BLOCK && !isalnum(chNext)) { + levelNext++; + } + else if ((style & 0xf) == SCE_4GL_END && (ch == 'e' || ch == 'f')) { + levelNext--; + } + if (atEOL) { + int levelUse = levelCurrent; + if (foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } +} + +static void Fold4glDoc(unsigned int startPos, int length, int initStyle, WordList *[], + Accessor &styler) { + FoldNoBox4glDoc(startPos, length, initStyle, styler); +} + +static const char * const FglWordLists[] = { + "Primary keywords and identifiers", + "Secondary keywords and identifiers", + "Documentation comment keywords", + "Unused", + "Global classes and typedefs", + 0, + }; + +LexerModule lmProgress(SCLEX_PROGRESS, Colourise4glDoc, "progress", Fold4glDoc, FglWordLists); diff --git a/lexers/LexPython.cxx b/lexers/LexPython.cxx new file mode 100644 index 000000000..b8921865c --- /dev/null +++ b/lexers/LexPython.cxx @@ -0,0 +1,569 @@ +// Scintilla source code edit control +/** @file LexPython.cxx + ** Lexer for Python. + **/ +// Copyright 1998-2002 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +/* kwCDef, kwCTypeName only used for Cython */ +enum kwType { kwOther, kwClass, kwDef, kwImport, kwCDef, kwCTypeName }; + +static const int indicatorWhitespace = 1; + +static bool IsPyComment(Accessor &styler, int pos, int len) { + return len > 0 && styler[pos] == '#'; +} + +enum literalsAllowed { litNone=0, litU=1, litB=2}; + +static bool IsPyStringTypeChar(int ch, literalsAllowed allowed) { + return + ((allowed & litB) && (ch == 'b' || ch == 'B')) || + ((allowed & litU) && (ch == 'u' || ch == 'U')); +} + +static bool IsPyStringStart(int ch, int chNext, int chNext2, literalsAllowed allowed) { + if (ch == '\'' || ch == '"') + return true; + if (IsPyStringTypeChar(ch, allowed)) { + if (chNext == '"' || chNext == '\'') + return true; + if ((chNext == 'r' || chNext == 'R') && (chNext2 == '"' || chNext2 == '\'')) + return true; + } + if ((ch == 'r' || ch == 'R') && (chNext == '"' || chNext == '\'')) + return true; + + return false; +} + +/* Return the state to use for the string starting at i; *nextIndex will be set to the first index following the quote(s) */ +static int GetPyStringState(Accessor &styler, int i, unsigned int *nextIndex, literalsAllowed allowed) { + char ch = styler.SafeGetCharAt(i); + char chNext = styler.SafeGetCharAt(i + 1); + + // Advance beyond r, u, or ur prefix (or r, b, or br in Python 3.0), but bail if there are any unexpected chars + if (ch == 'r' || ch == 'R') { + i++; + ch = styler.SafeGetCharAt(i); + chNext = styler.SafeGetCharAt(i + 1); + } else if (IsPyStringTypeChar(ch, allowed)) { + if (chNext == 'r' || chNext == 'R') + i += 2; + else + i += 1; + ch = styler.SafeGetCharAt(i); + chNext = styler.SafeGetCharAt(i + 1); + } + + if (ch != '"' && ch != '\'') { + *nextIndex = i + 1; + return SCE_P_DEFAULT; + } + + if (ch == chNext && ch == styler.SafeGetCharAt(i + 2)) { + *nextIndex = i + 3; + + if (ch == '"') + return SCE_P_TRIPLEDOUBLE; + else + return SCE_P_TRIPLE; + } else { + *nextIndex = i + 1; + + if (ch == '"') + return SCE_P_STRING; + else + return SCE_P_CHARACTER; + } +} + +static inline bool IsAWordChar(int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); +} + +static inline bool IsAWordStart(int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static void ColourisePyDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + int endPos = startPos + length; + + // Backtrack to previous line in case need to fix its tab whinging + int lineCurrent = styler.GetLine(startPos); + if (startPos > 0) { + if (lineCurrent > 0) { + lineCurrent--; + // Look for backslash-continued lines + while (lineCurrent > 0) { + int eolPos = styler.LineStart(lineCurrent) - 1; + int eolStyle = styler.StyleAt(eolPos); + if (eolStyle == SCE_P_STRING + || eolStyle == SCE_P_CHARACTER + || eolStyle == SCE_P_STRINGEOL) { + lineCurrent -= 1; + } else { + break; + } + } + startPos = styler.LineStart(lineCurrent); + } + initStyle = startPos == 0 ? SCE_P_DEFAULT : styler.StyleAt(startPos - 1); + } + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + + // property tab.timmy.whinge.level + // For Python code, checks whether indenting is consistent. + // The default, 0 turns off indentation checking, + // 1 checks whether each line is potentially inconsistent with the previous line, + // 2 checks whether any space characters occur before a tab character in the indentation, + // 3 checks whether any spaces are in the indentation, and + // 4 checks for any tab characters in the indentation. + // 1 is a good level to use. + const int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level"); + + // property lexer.python.literals.binary + // Set to 0 to not recognise Python 3 binary and octal literals: 0b1011 0o712. + bool base2or8Literals = styler.GetPropertyInt("lexer.python.literals.binary", 1) != 0; + + // property lexer.python.strings.u + // Set to 0 to not recognise Python Unicode literals u"x" as used before Python 3. + literalsAllowed allowedLiterals = (styler.GetPropertyInt("lexer.python.strings.u", 1)) ? litU : litNone; + + // property lexer.python.strings.b + // Set to 0 to not recognise Python 3 bytes literals b"x". + if (styler.GetPropertyInt("lexer.python.strings.b", 1)) + allowedLiterals = static_cast(allowedLiterals | litB); + + // property lexer.python.strings.over.newline + // Set to 1 to allow strings to span newline characters. + bool stringsOverNewline = styler.GetPropertyInt("lexer.python.strings.over.newline") != 0; + + initStyle = initStyle & 31; + if (initStyle == SCE_P_STRINGEOL) { + initStyle = SCE_P_DEFAULT; + } + + kwType kwLast = kwOther; + int spaceFlags = 0; + styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment); + bool base_n_number = false; + + StyleContext sc(startPos, endPos - startPos, initStyle, styler); + + bool indentGood = true; + int startIndicator = sc.currentPos; + bool inContinuedString = false; + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart) { + styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment); + indentGood = true; + if (whingeLevel == 1) { + indentGood = (spaceFlags & wsInconsistent) == 0; + } else if (whingeLevel == 2) { + indentGood = (spaceFlags & wsSpaceTab) == 0; + } else if (whingeLevel == 3) { + indentGood = (spaceFlags & wsSpace) == 0; + } else if (whingeLevel == 4) { + indentGood = (spaceFlags & wsTab) == 0; + } + if (!indentGood) { + styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 0); + startIndicator = sc.currentPos; + } + } + + if (sc.atLineEnd) { + if ((sc.state == SCE_P_DEFAULT) || + (sc.state == SCE_P_TRIPLE) || + (sc.state == SCE_P_TRIPLEDOUBLE)) { + // Perform colourisation of white space and triple quoted strings at end of each line to allow + // tab marking to work inside white space and triple quoted strings + sc.SetState(sc.state); + } + lineCurrent++; + if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) { + if (inContinuedString || stringsOverNewline) { + inContinuedString = false; + } else { + sc.ChangeState(SCE_P_STRINGEOL); + sc.ForwardSetState(SCE_P_DEFAULT); + } + } + if (!sc.More()) + break; + } + + bool needEOLCheck = false; + + // Check for a state end + if (sc.state == SCE_P_OPERATOR) { + kwLast = kwOther; + sc.SetState(SCE_P_DEFAULT); + } else if (sc.state == SCE_P_NUMBER) { + if (!IsAWordChar(sc.ch) && + !(!base_n_number && ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) { + sc.SetState(SCE_P_DEFAULT); + } + } else if (sc.state == SCE_P_IDENTIFIER) { + if ((sc.ch == '.') || (!IsAWordChar(sc.ch))) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + int style = SCE_P_IDENTIFIER; + if ((kwLast == kwImport) && (strcmp(s, "as") == 0)) { + style = SCE_P_WORD; + } else if (keywords.InList(s)) { + style = SCE_P_WORD; + } else if (kwLast == kwClass) { + style = SCE_P_CLASSNAME; + } else if (kwLast == kwDef) { + style = SCE_P_DEFNAME; + } else if (kwLast == kwCDef) { + int pos = sc.currentPos; + unsigned char ch = styler.SafeGetCharAt(pos, '\0'); + while (ch != '\0') { + if (ch == '(') { + style = SCE_P_DEFNAME; + break; + } else if (ch == ':') { + style = SCE_P_CLASSNAME; + break; + } else if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') { + pos++; + ch = styler.SafeGetCharAt(pos, '\0'); + } else { + break; + } + } + } else if (keywords2.InList(s)) { + style = SCE_P_WORD2; + } + sc.ChangeState(style); + sc.SetState(SCE_P_DEFAULT); + if (style == SCE_P_WORD) { + if (0 == strcmp(s, "class")) + kwLast = kwClass; + else if (0 == strcmp(s, "def")) + kwLast = kwDef; + else if (0 == strcmp(s, "import")) + kwLast = kwImport; + else if (0 == strcmp(s, "cdef")) + kwLast = kwCDef; + else if (0 == strcmp(s, "cimport")) + kwLast = kwImport; + else if (kwLast != kwCDef) + kwLast = kwOther; + } else if (kwLast != kwCDef) { + kwLast = kwOther; + } + } + } else if ((sc.state == SCE_P_COMMENTLINE) || (sc.state == SCE_P_COMMENTBLOCK)) { + if (sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_P_DEFAULT); + } + } else if (sc.state == SCE_P_DECORATOR) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_P_DEFAULT); + } + } else if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) { + if (sc.ch == '\\') { + if ((sc.chNext == '\r') && (sc.GetRelative(2) == '\n')) { + sc.Forward(); + } + if (sc.chNext == '\n' || sc.chNext == '\r') { + inContinuedString = true; + } else { + // Don't roll over the newline. + sc.Forward(); + } + } else if ((sc.state == SCE_P_STRING) && (sc.ch == '\"')) { + sc.ForwardSetState(SCE_P_DEFAULT); + needEOLCheck = true; + } else if ((sc.state == SCE_P_CHARACTER) && (sc.ch == '\'')) { + sc.ForwardSetState(SCE_P_DEFAULT); + needEOLCheck = true; + } + } else if (sc.state == SCE_P_TRIPLE) { + if (sc.ch == '\\') { + sc.Forward(); + } else if (sc.Match("\'\'\'")) { + sc.Forward(); + sc.Forward(); + sc.ForwardSetState(SCE_P_DEFAULT); + needEOLCheck = true; + } + } else if (sc.state == SCE_P_TRIPLEDOUBLE) { + if (sc.ch == '\\') { + sc.Forward(); + } else if (sc.Match("\"\"\"")) { + sc.Forward(); + sc.Forward(); + sc.ForwardSetState(SCE_P_DEFAULT); + needEOLCheck = true; + } + } + + if (!indentGood && !IsASpaceOrTab(sc.ch)) { + styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 1); + startIndicator = sc.currentPos; + indentGood = true; + } + + // One cdef line, clear kwLast only at end of line + if (kwLast == kwCDef && sc.atLineEnd) { + kwLast = kwOther; + } + + // State exit code may have moved on to end of line + if (needEOLCheck && sc.atLineEnd) { + lineCurrent++; + styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment); + if (!sc.More()) + break; + } + + // Check for a new state starting character + if (sc.state == SCE_P_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + if (sc.ch == '0' && (sc.chNext == 'x' || sc.chNext == 'X')) { + base_n_number = true; + sc.SetState(SCE_P_NUMBER); + } else if (sc.ch == '0' && + (sc.chNext == 'o' || sc.chNext == 'O' || sc.chNext == 'b' || sc.chNext == 'B')) { + if (base2or8Literals) { + base_n_number = true; + sc.SetState(SCE_P_NUMBER); + } else { + sc.SetState(SCE_P_NUMBER); + sc.ForwardSetState(SCE_P_IDENTIFIER); + } + } else { + base_n_number = false; + sc.SetState(SCE_P_NUMBER); + } + } else if ((isascii(sc.ch) && isoperator(static_cast(sc.ch))) || sc.ch == '`') { + sc.SetState(SCE_P_OPERATOR); + } else if (sc.ch == '#') { + sc.SetState(sc.chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE); + } else if (sc.ch == '@') { + sc.SetState(SCE_P_DECORATOR); + } else if (IsPyStringStart(sc.ch, sc.chNext, sc.GetRelative(2), allowedLiterals)) { + unsigned int nextIndex = 0; + sc.SetState(GetPyStringState(styler, sc.currentPos, &nextIndex, allowedLiterals)); + while (nextIndex > (sc.currentPos + 1) && sc.More()) { + sc.Forward(); + } + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_P_IDENTIFIER); + } + } + } + styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 0); + sc.Complete(); +} + +static bool IsCommentLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eol_pos; i++) { + char ch = styler[i]; + if (ch == '#') + return true; + else if (ch != ' ' && ch != '\t') + return false; + } + return false; +} + +static bool IsQuoteLine(int line, Accessor &styler) { + int style = styler.StyleAt(styler.LineStart(line)) & 31; + return ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE)); +} + + +static void FoldPyDoc(unsigned int startPos, int length, int /*initStyle - unused*/, + WordList *[], Accessor &styler) { + const int maxPos = startPos + length; + const int maxLines = styler.GetLine(maxPos - 1); // Requested last line + const int docLines = styler.GetLine(styler.Length() - 1); // Available last line + + // property fold.comment.python + // This option enables folding multi-line comments when using the Python lexer. + const bool foldComment = styler.GetPropertyInt("fold.comment.python") != 0; + + // property fold.quotes.python + // This option enables folding multi-line quoted strings when using the Python lexer. + const bool foldQuotes = styler.GetPropertyInt("fold.quotes.python") != 0; + + const bool foldCompact = styler.GetPropertyInt("fold.compact") != 0; + + // Backtrack to previous non-blank line so we can determine indent level + // for any white space lines (needed esp. within triple quoted strings) + // and so we can fix any preceding fold level (which is why we go back + // at least one line in all cases) + int spaceFlags = 0; + int lineCurrent = styler.GetLine(startPos); + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); + while (lineCurrent > 0) { + lineCurrent--; + indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) && + (!IsCommentLine(lineCurrent, styler)) && + (!IsQuoteLine(lineCurrent, styler))) + break; + } + int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + + // Set up initial loop state + startPos = styler.LineStart(lineCurrent); + int prev_state = SCE_P_DEFAULT & 31; + if (lineCurrent >= 1) + prev_state = styler.StyleAt(startPos - 1) & 31; + int prevQuote = foldQuotes && ((prev_state == SCE_P_TRIPLE) || (prev_state == SCE_P_TRIPLEDOUBLE)); + int prevComment = 0; + if (lineCurrent >= 1) + prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler); + + // Process all characters to end of requested range or end of any triple quote + // or comment that hangs over the end of the range. Cap processing in all cases + // to end of document (in case of unclosed quote or comment at end). + while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevQuote || prevComment)) { + + // Gather info + int lev = indentCurrent; + int lineNext = lineCurrent + 1; + int indentNext = indentCurrent; + int quote = false; + if (lineNext <= docLines) { + // Information about next line is only available if not at end of document + indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); + int style = styler.StyleAt(styler.LineStart(lineNext)) & 31; + quote = foldQuotes && ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE)); + } + const int quote_start = (quote && !prevQuote); + const int quote_continue = (quote && prevQuote); + const int comment = foldComment && IsCommentLine(lineCurrent, styler); + const int comment_start = (comment && !prevComment && (lineNext <= docLines) && + IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE)); + const int comment_continue = (comment && prevComment); + if ((!quote || !prevQuote) && !comment) + indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + if (quote) + indentNext = indentCurrentLevel; + if (indentNext & SC_FOLDLEVELWHITEFLAG) + indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel; + + if (quote_start) { + // Place fold point at start of triple quoted string + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (quote_continue || prevQuote) { + // Add level to rest of lines in the string + lev = lev + 1; + } else if (comment_start) { + // Place fold point at start of a block of comments + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (comment_continue) { + // Add level to rest of lines in the block + lev = lev + 1; + } + + // Skip past any blank lines for next indent level info; we skip also + // comments (all comments, not just those starting in column 0) + // which effectively folds them into surrounding code rather + // than screwing up folding. + + while (!quote && + (lineNext < docLines) && + ((indentNext & SC_FOLDLEVELWHITEFLAG) || + (lineNext <= docLines && IsCommentLine(lineNext, styler)))) { + + lineNext++; + indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); + } + + const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK; + const int levelBeforeComments = Platform::Maximum(indentCurrentLevel,levelAfterComments); + + // Now set all the indent levels on the lines we skipped + // Do this from end to start. Once we encounter one line + // which is indented more than the line after the end of + // the comment-block, use the level of the block before + + int skipLine = lineNext; + int skipLevel = levelAfterComments; + + while (--skipLine > lineCurrent) { + int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL); + + if (foldCompact) { + if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments) + skipLevel = levelBeforeComments; + + int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG; + + styler.SetLevel(skipLine, skipLevel | whiteFlag); + } else { + if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments && + !(skipLineIndent & SC_FOLDLEVELWHITEFLAG) && + !IsCommentLine(skipLine, styler)) + skipLevel = levelBeforeComments; + + styler.SetLevel(skipLine, skipLevel); + } + } + + // Set fold header on non-quote/non-comment line + if (!quote && !comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) + lev |= SC_FOLDLEVELHEADERFLAG; + } + + // Keep track of triple quote and block comment state of previous line + prevQuote = quote; + prevComment = comment_start || comment_continue; + + // Set fold level for this line and move to next line + styler.SetLevel(lineCurrent, lev); + indentCurrent = indentNext; + lineCurrent = lineNext; + } + + // NOTE: Cannot set level of last line here because indentCurrent doesn't have + // header flag set; the loop above is crafted to take care of this case! + //styler.SetLevel(lineCurrent, indentCurrent); +} + +static const char *const pythonWordListDesc[] = { + "Keywords", + "Highlighted identifiers", + 0 +}; + +LexerModule lmPython(SCLEX_PYTHON, ColourisePyDoc, "python", FoldPyDoc, + pythonWordListDesc); + diff --git a/lexers/LexR.cxx b/lexers/LexR.cxx new file mode 100644 index 000000000..cabbf5788 --- /dev/null +++ b/lexers/LexR.cxx @@ -0,0 +1,213 @@ +// Scintilla source code edit control +/** @file Lexr.cxx + ** Lexer for R, S, SPlus Statistics Program (Heavily derived from CPP Lexer). + ** + **/ +// Copyright 1998-2002 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAnOperator(const int ch) { + if (isascii(ch) && isalnum(ch)) + return false; + // '.' left out as it is used to make up numbers + if (ch == '-' || ch == '+' || ch == '!' || ch == '~' || + ch == '?' || ch == ':' || ch == '*' || ch == '/' || + ch == '^' || ch == '<' || ch == '>' || ch == '=' || + ch == '&' || ch == '|' || ch == '$' || ch == '(' || + ch == ')' || ch == '}' || ch == '{' || ch == '[' || + ch == ']') + return true; + return false; +} + +static void ColouriseRDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + + + // Do not leak onto next line + if (initStyle == SCE_R_INFIXEOL) + initStyle = SCE_R_DEFAULT; + + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart && (sc.state == SCE_R_STRING)) { + // Prevent SCE_R_STRINGEOL from leaking back to previous line + sc.SetState(SCE_R_STRING); + } + + // Determine if the current state should terminate. + if (sc.state == SCE_R_OPERATOR) { + sc.SetState(SCE_R_DEFAULT); + } else if (sc.state == SCE_R_NUMBER) { + if (!IsADigit(sc.ch) && !(sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_R_DEFAULT); + } + } else if (sc.state == SCE_R_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_R_KWORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_R_BASEKWORD); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_R_OTHERKWORD); + } + sc.SetState(SCE_R_DEFAULT); + } + } else if (sc.state == SCE_R_COMMENT) { + if (sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_R_DEFAULT); + } + } else if (sc.state == SCE_R_STRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_R_DEFAULT); + } + } else if (sc.state == SCE_R_INFIX) { + if (sc.ch == '%') { + sc.ForwardSetState(SCE_R_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_R_INFIXEOL); + sc.ForwardSetState(SCE_R_DEFAULT); + } + }else if (sc.state == SCE_R_STRING2) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_R_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_R_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_R_NUMBER); + } else if (IsAWordStart(sc.ch) ) { + sc.SetState(SCE_R_IDENTIFIER); + } else if (sc.Match('#')) { + sc.SetState(SCE_R_COMMENT); + } else if (sc.ch == '\"') { + sc.SetState(SCE_R_STRING); + } else if (sc.ch == '%') { + sc.SetState(SCE_R_INFIX); + } else if (sc.ch == '\'') { + sc.SetState(SCE_R_STRING2); + } else if (IsAnOperator(sc.ch)) { + sc.SetState(SCE_R_OPERATOR); + } + } + } + sc.Complete(); +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "} else {". +static void FoldRDoc(unsigned int startPos, int length, int, WordList *[], + Accessor &styler) { + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (style == SCE_R_OPERATOR) { + if (ch == '{') { + // Measure the minimum before a '{' to allow + // folding on "} else {" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + if (atEOL) { + int levelUse = levelCurrent; + if (foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } +} + + +static const char * const RWordLists[] = { + "Language Keywords", + "Base / Default package function", + "Other Package Functions", + "Unused", + "Unused", + 0, + }; + + + +LexerModule lmR(SCLEX_R, ColouriseRDoc, "r", FoldRDoc, RWordLists); diff --git a/lexers/LexRebol.cxx b/lexers/LexRebol.cxx new file mode 100644 index 000000000..7139b8dbd --- /dev/null +++ b/lexers/LexRebol.cxx @@ -0,0 +1,322 @@ +// Scintilla source code edit control +/** @file LexRebol.cxx + ** Lexer for REBOL. + ** Written by Pascal Hurni, inspired from LexLua by Paul Winwood & Marcos E. Wurzius & Philippe Lhoste + ** + ** History: + ** 2005-04-07 First release. + ** 2005-04-10 Closing parens and brackets go now in default style + ** String and comment nesting should be more safe + **/ +// Copyright 2005 by Pascal Hurni +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "StyleContext.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (isalnum(ch) || ch == '?' || ch == '!' || ch == '.' || ch == '\'' || ch == '+' || ch == '-' || ch == '*' || ch == '&' || ch == '|' || ch == '=' || ch == '_' || ch == '~'); +} + +static inline bool IsAWordStart(const int ch, const int ch2) { + return ((ch == '+' || ch == '-' || ch == '.') && !isdigit(ch2)) || + (isalpha(ch) || ch == '?' || ch == '!' || ch == '\'' || ch == '*' || ch == '&' || ch == '|' || ch == '=' || ch == '_' || ch == '~'); +} + +static inline bool IsAnOperator(const int ch, const int ch2, const int ch3) { + // One char operators + if (IsASpaceOrTab(ch2)) { + return ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '<' || ch == '>' || ch == '=' || ch == '?'; + } + + // Two char operators + if (IsASpaceOrTab(ch3)) { + return (ch == '*' && ch2 == '*') || + (ch == '/' && ch2 == '/') || + (ch == '<' && (ch2 == '=' || ch2 == '>')) || + (ch == '>' && ch2 == '=') || + (ch == '=' && (ch2 == '=' || ch2 == '?')) || + (ch == '?' && ch2 == '?'); + } + + return false; +} + +static inline bool IsBinaryStart(const int ch, const int ch2, const int ch3, const int ch4) { + return (ch == '#' && ch2 == '{') || + (IsADigit(ch) && ch2 == '#' && ch3 == '{' ) || + (IsADigit(ch) && IsADigit(ch2) && ch3 == '#' && ch4 == '{' ); +} + + +static void ColouriseRebolDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; + WordList &keywords7 = *keywordlists[6]; + WordList &keywords8 = *keywordlists[7]; + + int currentLine = styler.GetLine(startPos); + // Initialize the braced string {.. { ... } ..} nesting level, if we are inside such a string. + int stringLevel = 0; + if (initStyle == SCE_REBOL_BRACEDSTRING || initStyle == SCE_REBOL_COMMENTBLOCK) { + stringLevel = styler.GetLineState(currentLine - 1); + } + + bool blockComment = initStyle == SCE_REBOL_COMMENTBLOCK; + int dotCount = 0; + + // Do not leak onto next line + if (initStyle == SCE_REBOL_COMMENTLINE) { + initStyle = SCE_REBOL_DEFAULT; + } + + StyleContext sc(startPos, length, initStyle, styler); + if (startPos == 0) { + sc.SetState(SCE_REBOL_PREFACE); + } + for (; sc.More(); sc.Forward()) { + + //--- What to do at line end ? + if (sc.atLineEnd) { + // Can be either inside a {} string or simply at eol + if (sc.state != SCE_REBOL_BRACEDSTRING && sc.state != SCE_REBOL_COMMENTBLOCK && + sc.state != SCE_REBOL_BINARY && sc.state != SCE_REBOL_PREFACE) + sc.SetState(SCE_REBOL_DEFAULT); + + // Update the line state, so it can be seen by next line + currentLine = styler.GetLine(sc.currentPos); + switch (sc.state) { + case SCE_REBOL_BRACEDSTRING: + case SCE_REBOL_COMMENTBLOCK: + // Inside a braced string, we set the line state + styler.SetLineState(currentLine, stringLevel); + break; + default: + // Reset the line state + styler.SetLineState(currentLine, 0); + break; + } + + // continue with next char + continue; + } + + //--- What to do on white-space ? + if (IsASpaceOrTab(sc.ch)) + { + // Return to default if any of these states + if (sc.state == SCE_REBOL_OPERATOR || sc.state == SCE_REBOL_CHARACTER || + sc.state == SCE_REBOL_NUMBER || sc.state == SCE_REBOL_PAIR || + sc.state == SCE_REBOL_TUPLE || sc.state == SCE_REBOL_FILE || + sc.state == SCE_REBOL_DATE || sc.state == SCE_REBOL_TIME || + sc.state == SCE_REBOL_MONEY || sc.state == SCE_REBOL_ISSUE || + sc.state == SCE_REBOL_URL || sc.state == SCE_REBOL_EMAIL) { + sc.SetState(SCE_REBOL_DEFAULT); + } + } + + //--- Specialize state ? + // URL, Email look like identifier + if (sc.state == SCE_REBOL_IDENTIFIER) + { + if (sc.ch == ':' && !IsASpace(sc.chNext)) { + sc.ChangeState(SCE_REBOL_URL); + } else if (sc.ch == '@') { + sc.ChangeState(SCE_REBOL_EMAIL); + } else if (sc.ch == '$') { + sc.ChangeState(SCE_REBOL_MONEY); + } + } + // Words look like identifiers + if (sc.state == SCE_REBOL_IDENTIFIER || (sc.state >= SCE_REBOL_WORD && sc.state <= SCE_REBOL_WORD8)) { + // Keywords ? + if (!IsAWordChar(sc.ch) || sc.Match('/')) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + blockComment = strcmp(s, "comment") == 0; + if (keywords8.InList(s)) { + sc.ChangeState(SCE_REBOL_WORD8); + } else if (keywords7.InList(s)) { + sc.ChangeState(SCE_REBOL_WORD7); + } else if (keywords6.InList(s)) { + sc.ChangeState(SCE_REBOL_WORD6); + } else if (keywords5.InList(s)) { + sc.ChangeState(SCE_REBOL_WORD5); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_REBOL_WORD4); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_REBOL_WORD3); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_REBOL_WORD2); + } else if (keywords.InList(s)) { + sc.ChangeState(SCE_REBOL_WORD); + } + // Keep same style if there are refinements + if (!sc.Match('/')) { + sc.SetState(SCE_REBOL_DEFAULT); + } + } + // special numbers + } else if (sc.state == SCE_REBOL_NUMBER) { + switch (sc.ch) { + case 'x': sc.ChangeState(SCE_REBOL_PAIR); + break; + case ':': sc.ChangeState(SCE_REBOL_TIME); + break; + case '-': + case '/': sc.ChangeState(SCE_REBOL_DATE); + break; + case '.': if (++dotCount >= 2) sc.ChangeState(SCE_REBOL_TUPLE); + break; + } + } + + //--- Determine if the current state should terminate + if (sc.state == SCE_REBOL_QUOTEDSTRING || sc.state == SCE_REBOL_CHARACTER) { + if (sc.ch == '^' && sc.chNext == '\"') { + sc.Forward(); + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_REBOL_DEFAULT); + } + } else if (sc.state == SCE_REBOL_BRACEDSTRING || sc.state == SCE_REBOL_COMMENTBLOCK) { + if (sc.ch == '}') { + if (--stringLevel == 0) { + sc.ForwardSetState(SCE_REBOL_DEFAULT); + } + } else if (sc.ch == '{') { + stringLevel++; + } + } else if (sc.state == SCE_REBOL_BINARY) { + if (sc.ch == '}') { + sc.ForwardSetState(SCE_REBOL_DEFAULT); + } + } else if (sc.state == SCE_REBOL_TAG) { + if (sc.ch == '>') { + sc.ForwardSetState(SCE_REBOL_DEFAULT); + } + } else if (sc.state == SCE_REBOL_PREFACE) { + if (sc.MatchIgnoreCase("rebol")) + { + int i; + for (i=5; IsASpaceOrTab(styler.SafeGetCharAt(sc.currentPos+i, 0)); i++); + if (sc.GetRelative(i) == '[') + sc.SetState(SCE_REBOL_DEFAULT); + } + } + + //--- Parens and bracket changes to default style when the current is a number + if (sc.state == SCE_REBOL_NUMBER || sc.state == SCE_REBOL_PAIR || sc.state == SCE_REBOL_TUPLE || + sc.state == SCE_REBOL_MONEY || sc.state == SCE_REBOL_ISSUE || sc.state == SCE_REBOL_EMAIL || + sc.state == SCE_REBOL_URL || sc.state == SCE_REBOL_DATE || sc.state == SCE_REBOL_TIME) { + if (sc.ch == '(' || sc.ch == '[' || sc.ch == ')' || sc.ch == ']') { + sc.SetState(SCE_REBOL_DEFAULT); + } + } + + //--- Determine if a new state should be entered. + if (sc.state == SCE_REBOL_DEFAULT) { + if (IsAnOperator(sc.ch, sc.chNext, sc.GetRelative(2))) { + sc.SetState(SCE_REBOL_OPERATOR); + } else if (IsBinaryStart(sc.ch, sc.chNext, sc.GetRelative(2), sc.GetRelative(3))) { + sc.SetState(SCE_REBOL_BINARY); + } else if (IsAWordStart(sc.ch, sc.chNext)) { + sc.SetState(SCE_REBOL_IDENTIFIER); + } else if (IsADigit(sc.ch) || sc.ch == '+' || sc.ch == '-' || /*Decimal*/ sc.ch == '.' || sc.ch == ',') { + dotCount = 0; + sc.SetState(SCE_REBOL_NUMBER); + } else if (sc.ch == '\"') { + sc.SetState(SCE_REBOL_QUOTEDSTRING); + } else if (sc.ch == '{') { + sc.SetState(blockComment ? SCE_REBOL_COMMENTBLOCK : SCE_REBOL_BRACEDSTRING); + ++stringLevel; + } else if (sc.ch == ';') { + sc.SetState(SCE_REBOL_COMMENTLINE); + } else if (sc.ch == '$') { + sc.SetState(SCE_REBOL_MONEY); + } else if (sc.ch == '%') { + sc.SetState(SCE_REBOL_FILE); + } else if (sc.ch == '<') { + sc.SetState(SCE_REBOL_TAG); + } else if (sc.ch == '#' && sc.chNext == '"') { + sc.SetState(SCE_REBOL_CHARACTER); + sc.Forward(); + } else if (sc.ch == '#' && sc.chNext != '"' && sc.chNext != '{' ) { + sc.SetState(SCE_REBOL_ISSUE); + } + } + } + sc.Complete(); +} + + +static void FoldRebolDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[], + Accessor &styler) { + unsigned int lengthDoc = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (style == SCE_REBOL_DEFAULT) { + if (ch == '[') { + levelCurrent++; + } else if (ch == ']') { + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const rebolWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmREBOL(SCLEX_REBOL, ColouriseRebolDoc, "rebol", FoldRebolDoc, rebolWordListDesc); + diff --git a/lexers/LexRuby.cxx b/lexers/LexRuby.cxx new file mode 100644 index 000000000..8d6dc90b8 --- /dev/null +++ b/lexers/LexRuby.cxx @@ -0,0 +1,1715 @@ +// Scintilla source code edit control +/** @file LexRuby.cxx + ** Lexer for Ruby. + **/ +// Copyright 2001- by Clemens Wyss +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +//XXX Identical to Perl, put in common area +static inline bool isEOLChar(char ch) { + return (ch == '\r') || (ch == '\n'); +} + +#define isSafeASCII(ch) ((unsigned int)(ch) <= 127) +// This one's redundant, but makes for more readable code +#define isHighBitChar(ch) ((unsigned int)(ch) > 127) + +static inline bool isSafeAlpha(char ch) { + return (isSafeASCII(ch) && isalpha(ch)) || ch == '_'; +} + +static inline bool isSafeAlnum(char ch) { + return (isSafeASCII(ch) && isalnum(ch)) || ch == '_'; +} + +static inline bool isSafeAlnumOrHigh(char ch) { + return isHighBitChar(ch) || isalnum(ch) || ch == '_'; +} + +static inline bool isSafeDigit(char ch) { + return isSafeASCII(ch) && isdigit(ch); +} + +static inline bool isSafeWordcharOrHigh(char ch) { + // Error: scintilla's KeyWords.h includes '.' as a word-char + // we want to separate things that can take methods from the + // methods. + return isHighBitChar(ch) || isalnum(ch) || ch == '_'; +} + +static bool inline iswhitespace(char ch) { + return ch == ' ' || ch == '\t'; +} + +#define MAX_KEYWORD_LENGTH 200 + +#define STYLE_MASK 63 +#define actual_style(style) (style & STYLE_MASK) + +static bool followsDot(unsigned int pos, Accessor &styler) { + styler.Flush(); + for (; pos >= 1; --pos) { + int style = actual_style(styler.StyleAt(pos)); + char ch; + switch (style) { + case SCE_RB_DEFAULT: + ch = styler[pos]; + if (ch == ' ' || ch == '\t') { + //continue + } else { + return false; + } + break; + + case SCE_RB_OPERATOR: + return styler[pos] == '.'; + + default: + return false; + } + } + return false; +} + +// Forward declarations +static bool keywordIsAmbiguous(const char *prevWord); +static bool keywordDoStartsLoop(int pos, + Accessor &styler); +static bool keywordIsModifier(const char *word, + int pos, + Accessor &styler); + +static int ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) { + char s[MAX_KEYWORD_LENGTH]; + unsigned int i, j; + unsigned int lim = end - start + 1; // num chars to copy + if (lim >= MAX_KEYWORD_LENGTH) { + lim = MAX_KEYWORD_LENGTH - 1; + } + for (i = start, j = 0; j < lim; i++, j++) { + s[j] = styler[i]; + } + s[j] = '\0'; + int chAttr; + if (0 == strcmp(prevWord, "class")) + chAttr = SCE_RB_CLASSNAME; + else if (0 == strcmp(prevWord, "module")) + chAttr = SCE_RB_MODULE_NAME; + else if (0 == strcmp(prevWord, "def")) + chAttr = SCE_RB_DEFNAME; + else if (keywords.InList(s) && !followsDot(start - 1, styler)) { + if (keywordIsAmbiguous(s) + && keywordIsModifier(s, start, styler)) { + + // Demoted keywords are colored as keywords, + // but do not affect changes in indentation. + // + // Consider the word 'if': + // 1. <> : normal + // 2. <> : demoted + // 3. <> : normal: start a new indent level + // 4. <> : color as identifer, since it follows '.' + + chAttr = SCE_RB_WORD_DEMOTED; + } else { + chAttr = SCE_RB_WORD; + } + } else + chAttr = SCE_RB_IDENTIFIER; + styler.ColourTo(end, chAttr); + if (chAttr == SCE_RB_WORD) { + strcpy(prevWord, s); + } else { + prevWord[0] = 0; + } + return chAttr; +} + + +//XXX Identical to Perl, put in common area +static bool isMatch(Accessor &styler, int lengthDoc, int pos, const char *val) { + if ((pos + static_cast(strlen(val))) >= lengthDoc) { + return false; + } + while (*val) { + if (*val != styler[pos++]) { + return false; + } + val++; + } + return true; +} + +// Do Ruby better -- find the end of the line, work back, +// and then check for leading white space + +// Precondition: the here-doc target can be indented +static bool lookingAtHereDocDelim(Accessor &styler, + int pos, + int lengthDoc, + const char *HereDocDelim) +{ + if (!isMatch(styler, lengthDoc, pos, HereDocDelim)) { + return false; + } + while (--pos > 0) { + char ch = styler[pos]; + if (isEOLChar(ch)) { + return true; + } else if (ch != ' ' && ch != '\t') { + return false; + } + } + return false; +} + +//XXX Identical to Perl, put in common area +static char opposite(char ch) { + if (ch == '(') + return ')'; + if (ch == '[') + return ']'; + if (ch == '{') + return '}'; + if (ch == '<') + return '>'; + return ch; +} + +// Null transitions when we see we've reached the end +// and need to relex the curr char. + +static void redo_char(int &i, char &ch, char &chNext, char &chNext2, + int &state) { + i--; + chNext2 = chNext; + chNext = ch; + state = SCE_RB_DEFAULT; +} + +static void advance_char(int &i, char &ch, char &chNext, char &chNext2) { + i++; + ch = chNext; + chNext = chNext2; +} + +// precondition: startPos points to one after the EOL char +static bool currLineContainsHereDelims(int& startPos, + Accessor &styler) { + if (startPos <= 1) + return false; + + int pos; + for (pos = startPos - 1; pos > 0; pos--) { + char ch = styler.SafeGetCharAt(pos); + if (isEOLChar(ch)) { + // Leave the pointers where they are -- there are no + // here doc delims on the current line, even if + // the EOL isn't default style + + return false; + } else { + styler.Flush(); + if (actual_style(styler.StyleAt(pos)) == SCE_RB_HERE_DELIM) { + break; + } + } + } + if (pos == 0) { + return false; + } + // Update the pointers so we don't have to re-analyze the string + startPos = pos; + return true; +} + +// This class is used by the enter and exit methods, so it needs +// to be hoisted out of the function. + +class QuoteCls { + public: + int Count; + char Up; + char Down; + QuoteCls() { + this->New(); + } + void New() { + Count = 0; + Up = '\0'; + Down = '\0'; + } + void Open(char u) { + Count++; + Up = u; + Down = opposite(Up); + } + QuoteCls(const QuoteCls& q) { + // copy constructor -- use this for copying in + Count = q.Count; + Up = q.Up; + Down = q.Down; + } + QuoteCls& operator=(const QuoteCls& q) { // assignment constructor + if (this != &q) { + Count = q.Count; + Up = q.Up; + Down = q.Down; + } + return *this; + } + +}; + + +static void enterInnerExpression(int *p_inner_string_types, + int *p_inner_expn_brace_counts, + QuoteCls *p_inner_quotes, + int& inner_string_count, + int& state, + int& brace_counts, + QuoteCls curr_quote + ) { + p_inner_string_types[inner_string_count] = state; + state = SCE_RB_DEFAULT; + p_inner_expn_brace_counts[inner_string_count] = brace_counts; + brace_counts = 0; + p_inner_quotes[inner_string_count] = curr_quote; + ++inner_string_count; +} + +static void exitInnerExpression(int *p_inner_string_types, + int *p_inner_expn_brace_counts, + QuoteCls *p_inner_quotes, + int& inner_string_count, + int& state, + int& brace_counts, + QuoteCls& curr_quote + ) { + --inner_string_count; + state = p_inner_string_types[inner_string_count]; + brace_counts = p_inner_expn_brace_counts[inner_string_count]; + curr_quote = p_inner_quotes[inner_string_count]; +} + +static bool isEmptyLine(int pos, + Accessor &styler) { + int spaceFlags = 0; + int lineCurrent = styler.GetLine(pos); + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); + return (indentCurrent & SC_FOLDLEVELWHITEFLAG) != 0; +} + +static bool RE_CanFollowKeyword(const char *keyword) { + if (!strcmp(keyword, "and") + || !strcmp(keyword, "begin") + || !strcmp(keyword, "break") + || !strcmp(keyword, "case") + || !strcmp(keyword, "do") + || !strcmp(keyword, "else") + || !strcmp(keyword, "elsif") + || !strcmp(keyword, "if") + || !strcmp(keyword, "next") + || !strcmp(keyword, "return") + || !strcmp(keyword, "when") + || !strcmp(keyword, "unless") + || !strcmp(keyword, "until") + || !strcmp(keyword, "not") + || !strcmp(keyword, "or")) { + return true; + } + return false; +} + +// Look at chars up to but not including endPos +// Don't look at styles in case we're looking forward + +static int skipWhitespace(int startPos, + int endPos, + Accessor &styler) { + for (int i = startPos; i < endPos; i++) { + if (!iswhitespace(styler[i])) { + return i; + } + } + return endPos; +} + +// This routine looks for false positives like +// undef foo, << +// There aren't too many. +// +// iPrev points to the start of << + +static bool sureThisIsHeredoc(int iPrev, + Accessor &styler, + char *prevWord) { + + // Not so fast, since Ruby's so dynamic. Check the context + // to make sure we're OK. + int prevStyle; + int lineStart = styler.GetLine(iPrev); + int lineStartPosn = styler.LineStart(lineStart); + styler.Flush(); + + // Find the first word after some whitespace + int firstWordPosn = skipWhitespace(lineStartPosn, iPrev, styler); + if (firstWordPosn >= iPrev) { + // Have something like {^ <<} + //XXX Look at the first previous non-comment non-white line + // to establish the context. Not too likely though. + return true; + } else { + switch (prevStyle = styler.StyleAt(firstWordPosn)) { + case SCE_RB_WORD: + case SCE_RB_WORD_DEMOTED: + case SCE_RB_IDENTIFIER: + break; + default: + return true; + } + } + int firstWordEndPosn = firstWordPosn; + char *dst = prevWord; + for (;;) { + if (firstWordEndPosn >= iPrev || + styler.StyleAt(firstWordEndPosn) != prevStyle) { + *dst = 0; + break; + } + *dst++ = styler[firstWordEndPosn]; + firstWordEndPosn += 1; + } + //XXX Write a style-aware thing to regex scintilla buffer objects + if (!strcmp(prevWord, "undef") + || !strcmp(prevWord, "def") + || !strcmp(prevWord, "alias")) { + // These keywords are what we were looking for + return false; + } + return true; +} + +// Routine that saves us from allocating a buffer for the here-doc target +// targetEndPos points one past the end of the current target +static bool haveTargetMatch(int currPos, + int lengthDoc, + int targetStartPos, + int targetEndPos, + Accessor &styler) { + if (lengthDoc - currPos < targetEndPos - targetStartPos) { + return false; + } + int i, j; + for (i = targetStartPos, j = currPos; + i < targetEndPos && j < lengthDoc; + i++, j++) { + if (styler[i] != styler[j]) { + return false; + } + } + return true; +} + +// We need a check because the form +// [identifier] <<[target] +// is ambiguous. The Ruby lexer/parser resolves it by +// looking to see if [identifier] names a variable or a +// function. If it's the first, it's the start of a here-doc. +// If it's a var, it's an operator. This lexer doesn't +// maintain a symbol table, so it looks ahead to see what's +// going on, in cases where we have +// ^[white-space]*[identifier([.|::]identifier)*][white-space]*<<[target] +// +// If there's no occurrence of [target] on a line, assume we don't. + +// return true == yes, we have no heredocs + +static bool sureThisIsNotHeredoc(int lt2StartPos, + Accessor &styler) { + int prevStyle; + // Use full document, not just part we're styling + int lengthDoc = styler.Length(); + int lineStart = styler.GetLine(lt2StartPos); + int lineStartPosn = styler.LineStart(lineStart); + styler.Flush(); + const bool definitely_not_a_here_doc = true; + const bool looks_like_a_here_doc = false; + + // Find the first word after some whitespace + int firstWordPosn = skipWhitespace(lineStartPosn, lt2StartPos, styler); + if (firstWordPosn >= lt2StartPos) { + return definitely_not_a_here_doc; + } + prevStyle = styler.StyleAt(firstWordPosn); + // If we have '<<' following a keyword, it's not a heredoc + if (prevStyle != SCE_RB_IDENTIFIER) { + return definitely_not_a_here_doc; + } + int newStyle = prevStyle; + // Some compilers incorrectly warn about uninit newStyle + for (firstWordPosn += 1; firstWordPosn <= lt2StartPos; firstWordPosn += 1) { + // Inner loop looks at the name + for (; firstWordPosn <= lt2StartPos; firstWordPosn += 1) { + newStyle = styler.StyleAt(firstWordPosn); + if (newStyle != prevStyle) { + break; + } + } + // Do we have '::' or '.'? + if (firstWordPosn < lt2StartPos && newStyle == SCE_RB_OPERATOR) { + char ch = styler[firstWordPosn]; + if (ch == '.') { + // yes + } else if (ch == ':') { + if (styler.StyleAt(++firstWordPosn) != SCE_RB_OPERATOR) { + return definitely_not_a_here_doc; + } else if (styler[firstWordPosn] != ':') { + return definitely_not_a_here_doc; + } + } else { + break; + } + } else { + break; + } + } + // Skip next batch of white-space + firstWordPosn = skipWhitespace(firstWordPosn, lt2StartPos, styler); + if (firstWordPosn != lt2StartPos) { + // Have [[^ws[identifier]ws[*something_else*]ws<< + return definitely_not_a_here_doc; + } + // OK, now 'j' will point to the current spot moving ahead + int j = firstWordPosn + 1; + if (styler.StyleAt(j) != SCE_RB_OPERATOR || styler[j] != '<') { + // This shouldn't happen + return definitely_not_a_here_doc; + } + int nextLineStartPosn = styler.LineStart(lineStart + 1); + if (nextLineStartPosn >= lengthDoc) { + return definitely_not_a_here_doc; + } + j = skipWhitespace(j + 1, nextLineStartPosn, styler); + if (j >= lengthDoc) { + return definitely_not_a_here_doc; + } + bool allow_indent; + int target_start, target_end; + // From this point on no more styling, since we're looking ahead + if (styler[j] == '-') { + allow_indent = true; + j++; + } else { + allow_indent = false; + } + + // Allow for quoted targets. + char target_quote = 0; + switch (styler[j]) { + case '\'': + case '"': + case '`': + target_quote = styler[j]; + j += 1; + } + + if (isSafeAlnum(styler[j])) { + // Init target_end because some compilers think it won't + // be initialized by the time it's used + target_start = target_end = j; + j++; + } else { + return definitely_not_a_here_doc; + } + for (; j < lengthDoc; j++) { + if (!isSafeAlnum(styler[j])) { + if (target_quote && styler[j] != target_quote) { + // unquoted end + return definitely_not_a_here_doc; + } + + // And for now make sure that it's a newline + // don't handle arbitrary expressions yet + + target_end = j; + if (target_quote) { + // Now we can move to the character after the string delimiter. + j += 1; + } + j = skipWhitespace(j, lengthDoc, styler); + if (j >= lengthDoc) { + return definitely_not_a_here_doc; + } else { + char ch = styler[j]; + if (ch == '#' || isEOLChar(ch)) { + // This is OK, so break and continue; + break; + } else { + return definitely_not_a_here_doc; + } + } + } + } + + // Just look at the start of each line + int last_line = styler.GetLine(lengthDoc - 1); + // But don't go too far + if (last_line > lineStart + 50) { + last_line = lineStart + 50; + } + for (int line_num = lineStart + 1; line_num <= last_line; line_num++) { + if (allow_indent) { + j = skipWhitespace(styler.LineStart(line_num), lengthDoc, styler); + } else { + j = styler.LineStart(line_num); + } + // target_end is one past the end + if (haveTargetMatch(j, lengthDoc, target_start, target_end, styler)) { + // We got it + return looks_like_a_here_doc; + } + } + return definitely_not_a_here_doc; +} + +//todo: if we aren't looking at a stdio character, +// move to the start of the first line that is not in a +// multi-line construct + +static void synchronizeDocStart(unsigned int& startPos, + int &length, + int &initStyle, + Accessor &styler, + bool skipWhiteSpace=false) { + + styler.Flush(); + int style = actual_style(styler.StyleAt(startPos)); + switch (style) { + case SCE_RB_STDIN: + case SCE_RB_STDOUT: + case SCE_RB_STDERR: + // Don't do anything else with these. + return; + } + + int pos = startPos; + // Quick way to characterize each line + int lineStart; + for (lineStart = styler.GetLine(pos); lineStart > 0; lineStart--) { + // Now look at the style before the previous line's EOL + pos = styler.LineStart(lineStart) - 1; + if (pos <= 10) { + lineStart = 0; + break; + } + char ch = styler.SafeGetCharAt(pos); + char chPrev = styler.SafeGetCharAt(pos - 1); + if (ch == '\n' && chPrev == '\r') { + pos--; + } + if (styler.SafeGetCharAt(pos - 1) == '\\') { + // Continuation line -- keep going + } else if (actual_style(styler.StyleAt(pos)) != SCE_RB_DEFAULT) { + // Part of multi-line construct -- keep going + } else if (currLineContainsHereDelims(pos, styler)) { + // Keep going, with pos and length now pointing + // at the end of the here-doc delimiter + } else if (skipWhiteSpace && isEmptyLine(pos, styler)) { + // Keep going + } else { + break; + } + } + pos = styler.LineStart(lineStart); + length += (startPos - pos); + startPos = pos; + initStyle = SCE_RB_DEFAULT; +} + +static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + // Lexer for Ruby often has to backtrack to start of current style to determine + // which characters are being used as quotes, how deeply nested is the + // start position and what the termination string is for here documents + + WordList &keywords = *keywordlists[0]; + + class HereDocCls { + public: + int State; + // States + // 0: '<<' encountered + // 1: collect the delimiter + // 1b: text between the end of the delimiter and the EOL + // 2: here doc text (lines after the delimiter) + char Quote; // the char after '<<' + bool Quoted; // true if Quote in ('\'','"','`') + int DelimiterLength; // strlen(Delimiter) + char Delimiter[256]; // the Delimiter, limit of 256: from Perl + bool CanBeIndented; + HereDocCls() { + State = 0; + DelimiterLength = 0; + Delimiter[0] = '\0'; + CanBeIndented = false; + } + }; + HereDocCls HereDoc; + + QuoteCls Quote; + + int numDots = 0; // For numbers -- + // Don't start lexing in the middle of a num + + synchronizeDocStart(startPos, length, initStyle, styler, // ref args + false); + + bool preferRE = true; + int state = initStyle; + int lengthDoc = startPos + length; + + char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero + prevWord[0] = '\0'; + if (length == 0) + return; + + char chPrev = styler.SafeGetCharAt(startPos - 1); + char chNext = styler.SafeGetCharAt(startPos); + bool is_real_number = true; // Differentiate between constants and ?-sequences. + // Ruby uses a different mask because bad indentation is marked by oring with 32 + styler.StartAt(startPos, 127); + styler.StartSegment(startPos); + + static int q_states[] = {SCE_RB_STRING_Q, + SCE_RB_STRING_QQ, + SCE_RB_STRING_QR, + SCE_RB_STRING_QW, + SCE_RB_STRING_QW, + SCE_RB_STRING_QX}; + static const char* q_chars = "qQrwWx"; + + // In most cases a value of 2 should be ample for the code in the + // Ruby library, and the code the user is likely to enter. + // For example, + // fu_output_message "mkdir #{options[:mode] ? ('-m %03o ' % options[:mode]) : ''}#{list.join ' '}" + // if options[:verbose] + // from fileutils.rb nests to a level of 2 + // If the user actually hits a 6th occurrence of '#{' in a double-quoted + // string (including regex'es, %Q, %, %w, and other strings + // that interpolate), it will stay as a string. The problem with this + // is that quotes might flip, a 7th '#{' will look like a comment, + // and code-folding might be wrong. + + // If anyone runs into this problem, I recommend raising this + // value slightly higher to replacing the fixed array with a linked + // list. Keep in mind this code will be called everytime the lexer + // is invoked. + +#define INNER_STRINGS_MAX_COUNT 5 + // These vars track our instances of "...#{,,,%Q<..#{,,,}...>,,,}..." + int inner_string_types[INNER_STRINGS_MAX_COUNT]; + // Track # braces when we push a new #{ thing + int inner_expn_brace_counts[INNER_STRINGS_MAX_COUNT]; + QuoteCls inner_quotes[INNER_STRINGS_MAX_COUNT]; + int inner_string_count = 0; + int brace_counts = 0; // Number of #{ ... } things within an expression + + int i; + for (i = 0; i < INNER_STRINGS_MAX_COUNT; i++) { + inner_string_types[i] = 0; + inner_expn_brace_counts[i] = 0; + } + for (i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + char chNext2 = styler.SafeGetCharAt(i + 2); + + if (styler.IsLeadByte(ch)) { + chNext = chNext2; + chPrev = ' '; + i += 1; + continue; + } + + // skip on DOS/Windows + //No, don't, because some things will get tagged on, + // so we won't recognize keywords, for example +#if 0 + if (ch == '\r' && chNext == '\n') { + continue; + } +#endif + + if (HereDoc.State == 1 && isEOLChar(ch)) { + // Begin of here-doc (the line after the here-doc delimiter): + HereDoc.State = 2; + styler.ColourTo(i-1, state); + // Don't check for a missing quote, just jump into + // the here-doc state + state = SCE_RB_HERE_Q; + } + + // Regular transitions + if (state == SCE_RB_DEFAULT) { + if (isSafeDigit(ch)) { + styler.ColourTo(i - 1, state); + state = SCE_RB_NUMBER; + is_real_number = true; + numDots = 0; + } else if (isHighBitChar(ch) || iswordstart(ch)) { + styler.ColourTo(i - 1, state); + state = SCE_RB_WORD; + } else if (ch == '#') { + styler.ColourTo(i - 1, state); + state = SCE_RB_COMMENTLINE; + } else if (ch == '=') { + // =begin indicates the start of a comment (doc) block + if (i == 0 || (isEOLChar(chPrev) + && chNext == 'b' + && styler.SafeGetCharAt(i + 2) == 'e' + && styler.SafeGetCharAt(i + 3) == 'g' + && styler.SafeGetCharAt(i + 4) == 'i' + && styler.SafeGetCharAt(i + 5) == 'n' + && !isSafeWordcharOrHigh(styler.SafeGetCharAt(i + 6)))) { + styler.ColourTo(i - 1, state); + state = SCE_RB_POD; + } else { + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_RB_OPERATOR); + preferRE = true; + } + } else if (ch == '"') { + styler.ColourTo(i - 1, state); + state = SCE_RB_STRING; + Quote.New(); + Quote.Open(ch); + } else if (ch == '\'') { + styler.ColourTo(i - 1, state); + state = SCE_RB_CHARACTER; + Quote.New(); + Quote.Open(ch); + } else if (ch == '`') { + styler.ColourTo(i - 1, state); + state = SCE_RB_BACKTICKS; + Quote.New(); + Quote.Open(ch); + } else if (ch == '@') { + // Instance or class var + styler.ColourTo(i - 1, state); + if (chNext == '@') { + state = SCE_RB_CLASS_VAR; + advance_char(i, ch, chNext, chNext2); // pass by ref + } else { + state = SCE_RB_INSTANCE_VAR; + } + } else if (ch == '$') { + // Check for a builtin global + styler.ColourTo(i - 1, state); + // Recognize it bit by bit + state = SCE_RB_GLOBAL; + } else if (ch == '/' && preferRE) { + // Ambigous operator + styler.ColourTo(i - 1, state); + state = SCE_RB_REGEX; + Quote.New(); + Quote.Open(ch); + } else if (ch == '<' && chNext == '<' && chNext2 != '=') { + + // Recognise the '<<' symbol - either a here document or a binary op + styler.ColourTo(i - 1, state); + i++; + chNext = chNext2; + styler.ColourTo(i, SCE_RB_OPERATOR); + + if (! (strchr("\"\'`_-", chNext2) || isSafeAlpha(chNext2))) { + // It's definitely not a here-doc, + // based on Ruby's lexer/parser in the + // heredoc_identifier routine. + // Nothing else to do. + } else if (preferRE) { + if (sureThisIsHeredoc(i - 1, styler, prevWord)) { + state = SCE_RB_HERE_DELIM; + HereDoc.State = 0; + } + // else leave it in default state + } else { + if (sureThisIsNotHeredoc(i - 1, styler)) { + // leave state as default + // We don't have all the heuristics Perl has for indications + // of a here-doc, because '<<' is overloadable and used + // for so many other classes. + } else { + state = SCE_RB_HERE_DELIM; + HereDoc.State = 0; + } + } + preferRE = (state != SCE_RB_HERE_DELIM); + } else if (ch == ':') { + styler.ColourTo(i - 1, state); + if (chNext == ':') { + // Mark "::" as an operator, not symbol start + styler.ColourTo(i + 1, SCE_RB_OPERATOR); + advance_char(i, ch, chNext, chNext2); // pass by ref + state = SCE_RB_DEFAULT; + preferRE = false; + } else if (isSafeWordcharOrHigh(chNext)) { + state = SCE_RB_SYMBOL; + } else if (strchr("[*!~+-*/%=<>&^|", chNext)) { + // Do the operator analysis in-line, looking ahead + // Based on the table in pickaxe 2nd ed., page 339 + bool doColoring = true; + switch (chNext) { + case '[': + if (chNext2 == ']' ) { + char ch_tmp = styler.SafeGetCharAt(i + 3); + if (ch_tmp == '=') { + i += 3; + ch = ch_tmp; + chNext = styler.SafeGetCharAt(i + 1); + } else { + i += 2; + ch = chNext2; + chNext = ch_tmp; + } + } else { + doColoring = false; + } + break; + + case '*': + if (chNext2 == '*') { + i += 2; + ch = chNext2; + chNext = styler.SafeGetCharAt(i + 1); + } else { + advance_char(i, ch, chNext, chNext2); + } + break; + + case '!': + if (chNext2 == '=' || chNext2 == '~') { + i += 2; + ch = chNext2; + chNext = styler.SafeGetCharAt(i + 1); + } else { + advance_char(i, ch, chNext, chNext2); + } + break; + + case '<': + if (chNext2 == '<') { + i += 2; + ch = chNext2; + chNext = styler.SafeGetCharAt(i + 1); + } else if (chNext2 == '=') { + char ch_tmp = styler.SafeGetCharAt(i + 3); + if (ch_tmp == '>') { // <=> operator + i += 3; + ch = ch_tmp; + chNext = styler.SafeGetCharAt(i + 1); + } else { + i += 2; + ch = chNext2; + chNext = ch_tmp; + } + } else { + advance_char(i, ch, chNext, chNext2); + } + break; + + default: + // Simple one-character operators + advance_char(i, ch, chNext, chNext2); + break; + } + if (doColoring) { + styler.ColourTo(i, SCE_RB_SYMBOL); + state = SCE_RB_DEFAULT; + } + } else if (!preferRE) { + // Don't color symbol strings (yet) + // Just color the ":" and color rest as string + styler.ColourTo(i, SCE_RB_SYMBOL); + state = SCE_RB_DEFAULT; + } else { + styler.ColourTo(i, SCE_RB_OPERATOR); + state = SCE_RB_DEFAULT; + preferRE = true; + } + } else if (ch == '%') { + styler.ColourTo(i - 1, state); + bool have_string = false; + if (strchr(q_chars, chNext) && !isSafeWordcharOrHigh(chNext2)) { + Quote.New(); + const char *hit = strchr(q_chars, chNext); + if (hit != NULL) { + state = q_states[hit - q_chars]; + Quote.Open(chNext2); + i += 2; + ch = chNext2; + chNext = styler.SafeGetCharAt(i + 1); + have_string = true; + } + } else if (preferRE && !isSafeWordcharOrHigh(chNext)) { + // Ruby doesn't allow high bit chars here, + // but the editor host might + state = SCE_RB_STRING_QQ; + Quote.Open(chNext); + advance_char(i, ch, chNext, chNext2); // pass by ref + have_string = true; + } + if (!have_string) { + styler.ColourTo(i, SCE_RB_OPERATOR); + // stay in default + preferRE = true; + } + } else if (ch == '?') { + styler.ColourTo(i - 1, state); + if (iswhitespace(chNext) || chNext == '\n' || chNext == '\r') { + styler.ColourTo(i, SCE_RB_OPERATOR); + } else { + // It's the start of a character code escape sequence + // Color it as a number. + state = SCE_RB_NUMBER; + is_real_number = false; + } + } else if (isoperator(ch) || ch == '.') { + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_RB_OPERATOR); + // If we're ending an expression or block, + // assume it ends an object, and the ambivalent + // constructs are binary operators + // + // So if we don't have one of these chars, + // we aren't ending an object exp'n, and ops + // like : << / are unary operators. + + if (ch == '{') { + ++brace_counts; + preferRE = true; + } else if (ch == '}' && --brace_counts < 0 + && inner_string_count > 0) { + styler.ColourTo(i, SCE_RB_OPERATOR); + exitInnerExpression(inner_string_types, + inner_expn_brace_counts, + inner_quotes, + inner_string_count, + state, brace_counts, Quote); + } else { + preferRE = (strchr(")}].", ch) == NULL); + } + // Stay in default state + } else if (isEOLChar(ch)) { + // Make sure it's a true line-end, with no backslash + if ((ch == '\r' || (ch == '\n' && chPrev != '\r')) + && chPrev != '\\') { + // Assume we've hit the end of the statement. + preferRE = true; + } + } + } else if (state == SCE_RB_WORD) { + if (ch == '.' || !isSafeWordcharOrHigh(ch)) { + // Words include x? in all contexts, + // and = after either 'def' or a dot + // Move along until a complete word is on our left + + // Default accessor treats '.' as word-chars, + // but we don't for now. + + if (ch == '=' + && isSafeWordcharOrHigh(chPrev) + && (chNext == '(' + || strchr(" \t\n\r", chNext) != NULL) + && (!strcmp(prevWord, "def") + || followsDot(styler.GetStartSegment(), styler))) { + // = is a name only when being def'd -- Get it the next time + // This means that = is always lexed as + // , (op, =), + } else if ((ch == '?' || ch == '!') + && isSafeWordcharOrHigh(chPrev) + && !isSafeWordcharOrHigh(chNext)) { + // ? is a name -- Get it the next time + // But ? is always lexed as + // , (op, ?), + // Same with ! to indicate a method that + // modifies its target + } else if (isEOLChar(ch) + && isMatch(styler, lengthDoc, i - 7, "__END__")) { + styler.ColourTo(i, SCE_RB_DATASECTION); + state = SCE_RB_DATASECTION; + // No need to handle this state -- we'll just move to the end + preferRE = false; + } else { + int wordStartPos = styler.GetStartSegment(); + int word_style = ClassifyWordRb(wordStartPos, i - 1, keywords, styler, prevWord); + switch (word_style) { + case SCE_RB_WORD: + preferRE = RE_CanFollowKeyword(prevWord); + break; + + case SCE_RB_WORD_DEMOTED: + preferRE = true; + break; + + case SCE_RB_IDENTIFIER: + if (isMatch(styler, lengthDoc, wordStartPos, "print")) { + preferRE = true; + } else if (isEOLChar(ch)) { + preferRE = true; + } else { + preferRE = false; + } + break; + default: + preferRE = false; + } + if (ch == '.') { + // We might be redefining an operator-method + preferRE = false; + } + // And if it's the first + redo_char(i, ch, chNext, chNext2, state); // pass by ref + } + } + } else if (state == SCE_RB_NUMBER) { + if (!is_real_number) { + if (ch != '\\') { + styler.ColourTo(i, state); + state = SCE_RB_DEFAULT; + preferRE = false; + } else if (strchr("\\ntrfvaebs", chNext)) { + // Terminal escape sequence -- handle it next time + // Nothing more to do this time through the loop + } else if (chNext == 'C' || chNext == 'M') { + if (chNext2 != '-') { + // \C or \M ends the sequence -- handle it next time + } else { + // Move from abc?\C-x + // ^ + // to + // ^ + i += 2; + ch = chNext2; + chNext = styler.SafeGetCharAt(i + 1); + } + } else if (chNext == 'c') { + // Stay here, \c is a combining sequence + advance_char(i, ch, chNext, chNext2); // pass by ref + } else { + // ?\x, including ?\\ is final. + styler.ColourTo(i + 1, state); + state = SCE_RB_DEFAULT; + preferRE = false; + advance_char(i, ch, chNext, chNext2); + } + } else if (isSafeAlnumOrHigh(ch) || ch == '_') { + // Keep going + } else if (ch == '.' && ++numDots == 1) { + // Keep going + } else { + styler.ColourTo(i - 1, state); + redo_char(i, ch, chNext, chNext2, state); // pass by ref + preferRE = false; + } + } else if (state == SCE_RB_COMMENTLINE) { + if (isEOLChar(ch)) { + styler.ColourTo(i - 1, state); + state = SCE_RB_DEFAULT; + // Use whatever setting we had going into the comment + } + } else if (state == SCE_RB_HERE_DELIM) { + // See the comment for SCE_RB_HERE_DELIM in LexPerl.cxx + // Slightly different: if we find an immediate '-', + // the target can appear indented. + + if (HereDoc.State == 0) { // '<<' encountered + HereDoc.State = 1; + HereDoc.DelimiterLength = 0; + if (ch == '-') { + HereDoc.CanBeIndented = true; + advance_char(i, ch, chNext, chNext2); // pass by ref + } else { + HereDoc.CanBeIndented = false; + } + if (isEOLChar(ch)) { + // Bail out of doing a here doc if there's no target + state = SCE_RB_DEFAULT; + preferRE = false; + } else { + HereDoc.Quote = ch; + + if (ch == '\'' || ch == '"' || ch == '`') { + HereDoc.Quoted = true; + HereDoc.Delimiter[0] = '\0'; + } else { + HereDoc.Quoted = false; + HereDoc.Delimiter[0] = ch; + HereDoc.Delimiter[1] = '\0'; + HereDoc.DelimiterLength = 1; + } + } + } else if (HereDoc.State == 1) { // collect the delimiter + if (isEOLChar(ch)) { + // End the quote now, and go back for more + styler.ColourTo(i - 1, state); + state = SCE_RB_DEFAULT; + i--; + chNext = ch; + chNext2 = chNext; + preferRE = false; + } else if (HereDoc.Quoted) { + if (ch == HereDoc.Quote) { // closing quote => end of delimiter + styler.ColourTo(i, state); + state = SCE_RB_DEFAULT; + preferRE = false; + } else { + if (ch == '\\' && !isEOLChar(chNext)) { + advance_char(i, ch, chNext, chNext2); + } + HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch; + HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; + } + } else { // an unquoted here-doc delimiter + if (isSafeAlnumOrHigh(ch) || ch == '_') { + HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch; + HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; + } else { + styler.ColourTo(i - 1, state); + redo_char(i, ch, chNext, chNext2, state); + preferRE = false; + } + } + if (HereDoc.DelimiterLength >= static_cast(sizeof(HereDoc.Delimiter)) - 1) { + styler.ColourTo(i - 1, state); + state = SCE_RB_ERROR; + preferRE = false; + } + } + } else if (state == SCE_RB_HERE_Q) { + // Not needed: HereDoc.State == 2 + // Indentable here docs: look backwards + // Non-indentable: look forwards, like in Perl + // + // Why: so we can quickly resolve things like <<-" abc" + + if (!HereDoc.CanBeIndented) { + if (isEOLChar(chPrev) + && isMatch(styler, lengthDoc, i, HereDoc.Delimiter)) { + styler.ColourTo(i - 1, state); + i += HereDoc.DelimiterLength - 1; + chNext = styler.SafeGetCharAt(i + 1); + if (isEOLChar(chNext)) { + styler.ColourTo(i, SCE_RB_HERE_DELIM); + state = SCE_RB_DEFAULT; + HereDoc.State = 0; + preferRE = false; + } + // Otherwise we skipped through the here doc faster. + } + } else if (isEOLChar(chNext) + && lookingAtHereDocDelim(styler, + i - HereDoc.DelimiterLength + 1, + lengthDoc, + HereDoc.Delimiter)) { + styler.ColourTo(i - 1 - HereDoc.DelimiterLength, state); + styler.ColourTo(i, SCE_RB_HERE_DELIM); + state = SCE_RB_DEFAULT; + preferRE = false; + HereDoc.State = 0; + } + } else if (state == SCE_RB_CLASS_VAR + || state == SCE_RB_INSTANCE_VAR + || state == SCE_RB_SYMBOL) { + if (!isSafeWordcharOrHigh(ch)) { + styler.ColourTo(i - 1, state); + redo_char(i, ch, chNext, chNext2, state); // pass by ref + preferRE = false; + } + } else if (state == SCE_RB_GLOBAL) { + if (!isSafeWordcharOrHigh(ch)) { + // handle special globals here as well + if (chPrev == '$') { + if (ch == '-') { + // Include the next char, like $-a + advance_char(i, ch, chNext, chNext2); + } + styler.ColourTo(i, state); + state = SCE_RB_DEFAULT; + } else { + styler.ColourTo(i - 1, state); + redo_char(i, ch, chNext, chNext2, state); // pass by ref + } + preferRE = false; + } + } else if (state == SCE_RB_POD) { + // PODs end with ^=end\s, -- any whitespace can follow =end + if (strchr(" \t\n\r", ch) != NULL + && i > 5 + && isEOLChar(styler[i - 5]) + && isMatch(styler, lengthDoc, i - 4, "=end")) { + styler.ColourTo(i - 1, state); + state = SCE_RB_DEFAULT; + preferRE = false; + } + } else if (state == SCE_RB_REGEX || state == SCE_RB_STRING_QR) { + if (ch == '\\' && Quote.Up != '\\') { + // Skip one + advance_char(i, ch, chNext, chNext2); + } else if (ch == Quote.Down) { + Quote.Count--; + if (Quote.Count == 0) { + // Include the options + while (isSafeAlpha(chNext)) { + i++; + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + } + styler.ColourTo(i, state); + state = SCE_RB_DEFAULT; + preferRE = false; + } + } else if (ch == Quote.Up) { + // Only if close quoter != open quoter + Quote.Count++; + + } else if (ch == '#' ) { + if (chNext == '{' + && inner_string_count < INNER_STRINGS_MAX_COUNT) { + // process #{ ... } + styler.ColourTo(i - 1, state); + styler.ColourTo(i + 1, SCE_RB_OPERATOR); + enterInnerExpression(inner_string_types, + inner_expn_brace_counts, + inner_quotes, + inner_string_count, + state, + brace_counts, + Quote); + preferRE = true; + // Skip one + advance_char(i, ch, chNext, chNext2); + } else { + //todo: distinguish comments from pound chars + // for now, handle as comment + styler.ColourTo(i - 1, state); + bool inEscape = false; + while (++i < lengthDoc) { + ch = styler.SafeGetCharAt(i); + if (ch == '\\') { + inEscape = true; + } else if (isEOLChar(ch)) { + // Comment inside a regex + styler.ColourTo(i - 1, SCE_RB_COMMENTLINE); + break; + } else if (inEscape) { + inEscape = false; // don't look at char + } else if (ch == Quote.Down) { + // Have the regular handler deal with this + // to get trailing modifiers. + i--; + ch = styler[i]; + break; + } + } + chNext = styler.SafeGetCharAt(i + 1); + chNext2 = styler.SafeGetCharAt(i + 2); + } + } + // Quotes of all kinds... + } else if (state == SCE_RB_STRING_Q || state == SCE_RB_STRING_QQ || + state == SCE_RB_STRING_QX || state == SCE_RB_STRING_QW || + state == SCE_RB_STRING || state == SCE_RB_CHARACTER || + state == SCE_RB_BACKTICKS) { + if (!Quote.Down && !isspacechar(ch)) { + Quote.Open(ch); + } else if (ch == '\\' && Quote.Up != '\\') { + //Riddle me this: Is it safe to skip *every* escaped char? + advance_char(i, ch, chNext, chNext2); + } else if (ch == Quote.Down) { + Quote.Count--; + if (Quote.Count == 0) { + styler.ColourTo(i, state); + state = SCE_RB_DEFAULT; + preferRE = false; + } + } else if (ch == Quote.Up) { + Quote.Count++; + } else if (ch == '#' && chNext == '{' + && inner_string_count < INNER_STRINGS_MAX_COUNT + && state != SCE_RB_CHARACTER + && state != SCE_RB_STRING_Q) { + // process #{ ... } + styler.ColourTo(i - 1, state); + styler.ColourTo(i + 1, SCE_RB_OPERATOR); + enterInnerExpression(inner_string_types, + inner_expn_brace_counts, + inner_quotes, + inner_string_count, + state, + brace_counts, + Quote); + preferRE = true; + // Skip one + advance_char(i, ch, chNext, chNext2); + } + } + + if (state == SCE_RB_ERROR) { + break; + } + chPrev = ch; + } + if (state == SCE_RB_WORD) { + // We've ended on a word, possibly at EOF, and need to + // classify it. + (void) ClassifyWordRb(styler.GetStartSegment(), lengthDoc - 1, keywords, styler, prevWord); + } else { + styler.ColourTo(lengthDoc - 1, state); + } +} + +// Helper functions for folding, disambiguation keywords +// Assert that there are no high-bit chars + +static void getPrevWord(int pos, + char *prevWord, + Accessor &styler, + int word_state) +{ + int i; + styler.Flush(); + for (i = pos - 1; i > 0; i--) { + if (actual_style(styler.StyleAt(i)) != word_state) { + i++; + break; + } + } + if (i < pos - MAX_KEYWORD_LENGTH) // overflow + i = pos - MAX_KEYWORD_LENGTH; + char *dst = prevWord; + for (; i <= pos; i++) { + *dst++ = styler[i]; + } + *dst = 0; +} + +static bool keywordIsAmbiguous(const char *prevWord) +{ + // Order from most likely used to least likely + // Lots of ways to do a loop in Ruby besides 'while/until' + if (!strcmp(prevWord, "if") + || !strcmp(prevWord, "do") + || !strcmp(prevWord, "while") + || !strcmp(prevWord, "unless") + || !strcmp(prevWord, "until")) { + return true; + } else { + return false; + } +} + +// Demote keywords in the following conditions: +// if, while, unless, until modify a statement +// do after a while or until, as a noise word (like then after if) + +static bool keywordIsModifier(const char *word, + int pos, + Accessor &styler) +{ + if (word[0] == 'd' && word[1] == 'o' && !word[2]) { + return keywordDoStartsLoop(pos, styler); + } + char ch; + int style = SCE_RB_DEFAULT; + int lineStart = styler.GetLine(pos); + int lineStartPosn = styler.LineStart(lineStart); + styler.Flush(); + while (--pos >= lineStartPosn) { + style = actual_style(styler.StyleAt(pos)); + if (style == SCE_RB_DEFAULT) { + if (iswhitespace(ch = styler[pos])) { + //continue + } else if (ch == '\r' || ch == '\n') { + // Scintilla's LineStart() and GetLine() routines aren't + // platform-independent, so if we have text prepared with + // a different system we can't rely on it. + return false; + } + } else { + break; + } + } + if (pos < lineStartPosn) { + return false; //XXX not quite right if the prev line is a continuation + } + // First things where the action is unambiguous + switch (style) { + case SCE_RB_DEFAULT: + case SCE_RB_COMMENTLINE: + case SCE_RB_POD: + case SCE_RB_CLASSNAME: + case SCE_RB_DEFNAME: + case SCE_RB_MODULE_NAME: + return false; + case SCE_RB_OPERATOR: + break; + case SCE_RB_WORD: + // Watch out for uses of 'else if' + //XXX: Make a list of other keywords where 'if' isn't a modifier + // and can appear legitimately + // Formulate this to avoid warnings from most compilers + if (strcmp(word, "if") == 0) { + char prevWord[MAX_KEYWORD_LENGTH + 1]; + getPrevWord(pos, prevWord, styler, SCE_RB_WORD); + return strcmp(prevWord, "else") != 0; + } + return true; + default: + return true; + } + // Assume that if the keyword follows an operator, + // usually it's a block assignment, like + // a << if x then y else z + + ch = styler[pos]; + switch (ch) { + case ')': + case ']': + case '}': + return true; + default: + return false; + } +} + +#define WHILE_BACKWARDS "elihw" +#define UNTIL_BACKWARDS "litnu" + +// Nothing fancy -- look to see if we follow a while/until somewhere +// on the current line + +static bool keywordDoStartsLoop(int pos, + Accessor &styler) +{ + char ch; + int style; + int lineStart = styler.GetLine(pos); + int lineStartPosn = styler.LineStart(lineStart); + styler.Flush(); + while (--pos >= lineStartPosn) { + style = actual_style(styler.StyleAt(pos)); + if (style == SCE_RB_DEFAULT) { + if ((ch = styler[pos]) == '\r' || ch == '\n') { + // Scintilla's LineStart() and GetLine() routines aren't + // platform-independent, so if we have text prepared with + // a different system we can't rely on it. + return false; + } + } else if (style == SCE_RB_WORD) { + // Check for while or until, but write the word in backwards + char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero + char *dst = prevWord; + int wordLen = 0; + int start_word; + for (start_word = pos; + start_word >= lineStartPosn && actual_style(styler.StyleAt(start_word)) == SCE_RB_WORD; + start_word--) { + if (++wordLen < MAX_KEYWORD_LENGTH) { + *dst++ = styler[start_word]; + } + } + *dst = 0; + // Did we see our keyword? + if (!strcmp(prevWord, WHILE_BACKWARDS) + || !strcmp(prevWord, UNTIL_BACKWARDS)) { + return true; + } + // We can move pos to the beginning of the keyword, and then + // accept another decrement, as we can never have two contiguous + // keywords: + // word1 word2 + // ^ + // <- move to start_word + // ^ + // <- loop decrement + // ^ # pointing to end of word1 is fine + pos = start_word; + } + } + return false; +} + +/* + * Folding Ruby + * + * The language is quite complex to analyze without a full parse. + * For example, this line shouldn't affect fold level: + * + * print "hello" if feeling_friendly? + * + * Neither should this: + * + * print "hello" \ + * if feeling_friendly? + * + * + * But this should: + * + * if feeling_friendly? #++ + * print "hello" \ + * print "goodbye" + * end #-- + * + * So we cheat, by actually looking at the existing indentation + * levels for each line, and just echoing it back. Like Python. + * Then if we get better at it, we'll take braces into consideration, + * which always affect folding levels. + + * How the keywords should work: + * No effect: + * __FILE__ __LINE__ BEGIN END alias and + * defined? false in nil not or self super then + * true undef + + * Always increment: + * begin class def do for module when { + * + * Always decrement: + * end } + * + * Increment if these start a statement + * if unless until while -- do nothing if they're modifiers + + * These end a block if there's no modifier, but don't bother + * break next redo retry return yield + * + * These temporarily de-indent, but re-indent + * case else elsif ensure rescue + * + * This means that the folder reflects indentation rather + * than setting it. The language-service updates indentation + * when users type return and finishes entering de-denters. + * + * Later offer to fold POD, here-docs, strings, and blocks of comments + */ + +static void FoldRbDoc(unsigned int startPos, int length, int initStyle, + WordList *[], Accessor &styler) { + const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + + synchronizeDocStart(startPos, length, initStyle, styler, // ref args + false); + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = startPos == 0 ? 0 : (styler.LevelAt(lineCurrent) + & SC_FOLDLEVELNUMBERMASK + & ~SC_FOLDLEVELBASE); + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int stylePrev = startPos <= 1 ? SCE_RB_DEFAULT : styler.StyleAt(startPos - 1); + bool buffer_ends_with_eol = false; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (style == SCE_RB_COMMENTLINE) { + if (foldComment && stylePrev != SCE_RB_COMMENTLINE) { + if (chNext == '{') { + levelCurrent++; + } else if (chNext == '}' && levelCurrent > 0) { + levelCurrent--; + } + } + } else if (style == SCE_RB_OPERATOR) { + if (strchr("[{(", ch)) { + levelCurrent++; + } else if (strchr(")}]", ch)) { + // Don't decrement below 0 + if (levelCurrent > 0) + levelCurrent--; + } + } else if (style == SCE_RB_WORD && styleNext != SCE_RB_WORD) { + // Look at the keyword on the left and decide what to do + char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero + prevWord[0] = 0; + getPrevWord(i, prevWord, styler, SCE_RB_WORD); + if (!strcmp(prevWord, "end")) { + // Don't decrement below 0 + if (levelCurrent > 0) + levelCurrent--; + } else if ( !strcmp(prevWord, "if") + || !strcmp(prevWord, "def") + || !strcmp(prevWord, "class") + || !strcmp(prevWord, "module") + || !strcmp(prevWord, "begin") + || !strcmp(prevWord, "case") + || !strcmp(prevWord, "do") + || !strcmp(prevWord, "while") + || !strcmp(prevWord, "unless") + || !strcmp(prevWord, "until") + || !strcmp(prevWord, "for") + ) { + levelCurrent++; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + styler.SetLevel(lineCurrent, lev|SC_FOLDLEVELBASE); + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + buffer_ends_with_eol = true; + } else if (!isspacechar(ch)) { + visibleChars++; + buffer_ends_with_eol = false; + } + stylePrev = style; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + if (!buffer_ends_with_eol) { + lineCurrent++; + int new_lev = levelCurrent; + if (visibleChars == 0 && foldCompact) + new_lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + new_lev |= SC_FOLDLEVELHEADERFLAG; + levelCurrent = new_lev; + } + styler.SetLevel(lineCurrent, levelCurrent|SC_FOLDLEVELBASE); +} + +static const char * const rubyWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmRuby(SCLEX_RUBY, ColouriseRbDoc, "ruby", FoldRbDoc, rubyWordListDesc); diff --git a/lexers/LexSML.cxx b/lexers/LexSML.cxx new file mode 100644 index 000000000..a41b4c10d --- /dev/null +++ b/lexers/LexSML.cxx @@ -0,0 +1,221 @@ +// Scintilla source code edit control +/** @file LexSML.cxx + ** Lexer for SML. + **/ +// Copyright 2009 by James Moffatt and Yuzhou Xin +// Modified from LexCaml.cxx by Robert Roessler Copyright 2005 +// The License.txt file describes the conditions under which this software may be distributed. + + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +inline int issml(int c) {return isalnum(c) || c == '_';} +inline int issmlf(int c) {return isalpha(c) || c == '_';} +inline int issmld(int c) {return isdigit(c) || c == '_';} + + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +void ColouriseSMLDoc( + unsigned int startPos, int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) +{ + StyleContext sc(startPos, length, initStyle, styler); + int nesting = 0; + if (sc.state < SCE_SML_STRING) + sc.state = SCE_SML_DEFAULT; + if (sc.state >= SCE_SML_COMMENT) + nesting = (sc.state & 0x0f) - SCE_SML_COMMENT; + + int chBase = 0, chToken = 0, chLit = 0; + WordList& keywords = *keywordlists[0]; + WordList& keywords2 = *keywordlists[1]; + WordList& keywords3 = *keywordlists[2]; + const int useMagic = styler.GetPropertyInt("lexer.caml.magic", 0); + + while (sc.More()) { + int state2 = -1; + int chColor = sc.currentPos - 1; + bool advance = true; + + switch (sc.state & 0x0f) { + case SCE_SML_DEFAULT: + chToken = sc.currentPos; + if (issmlf(sc.ch)) + state2 = SCE_SML_IDENTIFIER; + else if (sc.Match('`') && issmlf(sc.chNext)) + state2 = SCE_SML_TAGNAME; + else if (sc.Match('#')&&isdigit(sc.chNext)) + state2 = SCE_SML_LINENUM; + else if (sc.Match('#','\"')){ + state2 = SCE_SML_CHAR,chLit = 0; + sc.Forward(); + + } + else if (isdigit(sc.ch)) { + state2 = SCE_SML_NUMBER, chBase = 10; + if (sc.Match('0') && strchr("xX", sc.chNext)) + chBase = 16, sc.Forward();} + else if (sc.Match('\"')&&sc.chPrev!='#') + state2 = SCE_SML_STRING; + else if (sc.Match('(', '*')){ + state2 = SCE_SML_COMMENT, + sc.ch = ' ', + sc.Forward();} + else if (strchr("!~" + "=<>@^+-*/" + "()[];,:.#", sc.ch)) + state2 = SCE_SML_OPERATOR; + break; + + case SCE_SML_IDENTIFIER: + if (!(issml(sc.ch) || sc.Match('\''))) { + const int n = sc.currentPos - chToken; + if (n < 24) { + char t[24]; + for (int i = -n; i < 0; i++) + t[n + i] = static_cast(sc.GetRelative(i)); + t[n] = '\0'; + if ((n == 1 && sc.chPrev == '_') || keywords.InList(t)) + sc.ChangeState(SCE_SML_KEYWORD); + else if (keywords2.InList(t)) + sc.ChangeState(SCE_SML_KEYWORD2); + else if (keywords3.InList(t)) + sc.ChangeState(SCE_SML_KEYWORD3); + } + state2 = SCE_SML_DEFAULT, advance = false; + } + break; + + case SCE_SML_TAGNAME: + if (!(issml(sc.ch) || sc.Match('\''))) + state2 = SCE_SML_DEFAULT, advance = false; + break; + + case SCE_SML_LINENUM: + if (!isdigit(sc.ch)) + state2 = SCE_SML_DEFAULT, advance = false; + break; + + case SCE_SML_OPERATOR: { + const char* o = 0; + if (issml(sc.ch) || isspace(sc.ch) + || (o = strchr(")]};,\'\"`#", sc.ch),o) + || !strchr("!$%&*+-./:<=>?@^|~", sc.ch)) { + if (o && strchr(")]};,", sc.ch)) { + if ((sc.Match(')') && sc.chPrev == '(') + || (sc.Match(']') && sc.chPrev == '[')) + sc.ChangeState(SCE_SML_KEYWORD); + chColor++; + } else + advance = false; + state2 = SCE_SML_DEFAULT; + } + break; + } + + case SCE_SML_NUMBER: + if (issmld(sc.ch) || IsADigit(sc.ch, chBase)) + break; + if ((sc.Match('l') || sc.Match('L') || sc.Match('n')) + && (issmld(sc.chPrev) || IsADigit(sc.chPrev, chBase))) + break; + if (chBase == 10) { + if (sc.Match('.') && issmld(sc.chPrev)) + break; + if ((sc.Match('e') || sc.Match('E')) + && (issmld(sc.chPrev) || sc.chPrev == '.')) + break; + if ((sc.Match('+') || sc.Match('-')) + && (sc.chPrev == 'e' || sc.chPrev == 'E')) + break; + } + state2 = SCE_SML_DEFAULT, advance = false; + break; + + case SCE_SML_CHAR: + if (sc.Match('\\')) { + chLit = 1; + if (sc.chPrev == '\\') + sc.ch = ' '; + } else if ((sc.Match('\"') && sc.chPrev != '\\') || sc.atLineEnd) { + state2 = SCE_SML_DEFAULT; + chLit = 1; + if (sc.Match('\"')) + chColor++; + else + sc.ChangeState(SCE_SML_IDENTIFIER); + } else if (chLit < 1 && sc.currentPos - chToken >= 3) + sc.ChangeState(SCE_SML_IDENTIFIER), advance = false; + break; + + case SCE_SML_STRING: + if (sc.Match('\\') && sc.chPrev == '\\') + sc.ch = ' '; + else if (sc.Match('\"') && sc.chPrev != '\\') + state2 = SCE_SML_DEFAULT, chColor++; + break; + + case SCE_SML_COMMENT: + case SCE_SML_COMMENT1: + case SCE_SML_COMMENT2: + case SCE_SML_COMMENT3: + if (sc.Match('(', '*')) + state2 = sc.state + 1, chToken = sc.currentPos, + sc.ch = ' ', + sc.Forward(), nesting++; + else if (sc.Match(')') && sc.chPrev == '*') { + if (nesting) + state2 = (sc.state & 0x0f) - 1, chToken = 0, nesting--; + else + state2 = SCE_SML_DEFAULT; + chColor++; + } else if (useMagic && sc.currentPos - chToken == 4 + && sc.Match('c') && sc.chPrev == 'r' && sc.GetRelative(-2) == '@') + sc.state |= 0x10; + break; + } + + if (state2 >= 0) + styler.ColourTo(chColor, sc.state), sc.ChangeState(state2); + if (advance) + sc.Forward(); + } + + sc.Complete(); +} + +void FoldSMLDoc( + unsigned int, int, + int, + WordList *[], + Accessor &) +{ +} + +static const char * const SMLWordListDesc[] = { + "Keywords", + "Keywords2", + "Keywords3", + 0 +}; + +LexerModule lmSML(SCLEX_SML, ColouriseSMLDoc, "SML", FoldSMLDoc, SMLWordListDesc); + diff --git a/lexers/LexSQL.cxx b/lexers/LexSQL.cxx new file mode 100644 index 000000000..7a4335bd2 --- /dev/null +++ b/lexers/LexSQL.cxx @@ -0,0 +1,357 @@ +// Scintilla source code edit control +/** @file LexSQL.cxx + ** Lexer for SQL, including PL/SQL and SQL*Plus. + **/ +// Copyright 1998-2005 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordStart(int ch) { + return (ch < 0x80) && (isalpha(ch) || ch == '_'); +} + +static inline bool IsADoxygenChar(int ch) { + return (islower(ch) || ch == '$' || ch == '@' || + ch == '\\' || ch == '&' || ch == '<' || + ch == '>' || ch == '#' || ch == '{' || + ch == '}' || ch == '[' || ch == ']'); +} + +static inline bool IsANumberChar(int ch) { + // Not exactly following number definition (several dots are seen as OK, etc.) + // but probably enough in most cases. + return (ch < 0x80) && + (isdigit(ch) || toupper(ch) == 'E' || + ch == '.' || ch == '-' || ch == '+'); +} + +static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords1 = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &kw_pldoc = *keywordlists[2]; + WordList &kw_sqlplus = *keywordlists[3]; + WordList &kw_user1 = *keywordlists[4]; + WordList &kw_user2 = *keywordlists[5]; + WordList &kw_user3 = *keywordlists[6]; + WordList &kw_user4 = *keywordlists[7]; + + StyleContext sc(startPos, length, initStyle, styler); + + // property sql.backslash.escapes + // Enables backslash as an escape character in SQL. + bool sqlBackslashEscapes = styler.GetPropertyInt("sql.backslash.escapes", 0) != 0; + + bool sqlBackticksIdentifier = styler.GetPropertyInt("lexer.sql.backticks.identifier", 0) != 0; + int styleBeforeDCKeyword = SCE_SQL_DEFAULT; + for (; sc.More(); sc.Forward()) { + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_SQL_OPERATOR: + sc.SetState(SCE_SQL_DEFAULT); + break; + case SCE_SQL_NUMBER: + // We stop the number definition on non-numerical non-dot non-eE non-sign char + if (!IsANumberChar(sc.ch)) { + sc.SetState(SCE_SQL_DEFAULT); + } + break; + case SCE_SQL_IDENTIFIER: + if (!IsAWordChar(sc.ch)) { + int nextState = SCE_SQL_DEFAULT; + char s[1000]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords1.InList(s)) { + sc.ChangeState(SCE_SQL_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_SQL_WORD2); + } else if (kw_sqlplus.InListAbbreviated(s, '~')) { + sc.ChangeState(SCE_SQL_SQLPLUS); + if (strncmp(s, "rem", 3) == 0) { + nextState = SCE_SQL_SQLPLUS_COMMENT; + } else if (strncmp(s, "pro", 3) == 0) { + nextState = SCE_SQL_SQLPLUS_PROMPT; + } + } else if (kw_user1.InList(s)) { + sc.ChangeState(SCE_SQL_USER1); + } else if (kw_user2.InList(s)) { + sc.ChangeState(SCE_SQL_USER2); + } else if (kw_user3.InList(s)) { + sc.ChangeState(SCE_SQL_USER3); + } else if (kw_user4.InList(s)) { + sc.ChangeState(SCE_SQL_USER4); + } + sc.SetState(nextState); + } + break; + case SCE_SQL_QUOTEDIDENTIFIER: + if (sc.ch == 0x60) { + if (sc.chNext == 0x60) { + sc.Forward(); // Ignore it + } else { + sc.ForwardSetState(SCE_SQL_DEFAULT); + } + } + break; + case SCE_SQL_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_SQL_DEFAULT); + } + break; + case SCE_SQL_COMMENTDOC: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_SQL_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_SQL_COMMENTDOC; + sc.SetState(SCE_SQL_COMMENTDOCKEYWORD); + } + } + break; + case SCE_SQL_COMMENTLINE: + case SCE_SQL_COMMENTLINEDOC: + case SCE_SQL_SQLPLUS_COMMENT: + case SCE_SQL_SQLPLUS_PROMPT: + if (sc.atLineStart) { + sc.SetState(SCE_SQL_DEFAULT); + } + break; + case SCE_SQL_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_SQL_COMMENTDOC) && sc.Match('*', '/')) { + sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(SCE_SQL_DEFAULT); + } else if (!IsADoxygenChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (!isspace(sc.ch) || !kw_pldoc.InList(s + 1)) { + sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR); + } + sc.SetState(styleBeforeDCKeyword); + } + break; + case SCE_SQL_CHARACTER: + if (sqlBackslashEscapes && sc.ch == '\\') { + sc.Forward(); + } else if (sc.ch == '\'') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_SQL_DEFAULT); + } + } + break; + case SCE_SQL_STRING: + if (sc.ch == '\\') { + // Escape sequence + sc.Forward(); + } else if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_SQL_DEFAULT); + } + } + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_SQL_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_SQL_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_SQL_IDENTIFIER); + } else if (sc.ch == 0x60 && sqlBackticksIdentifier) { + sc.SetState(SCE_SQL_QUOTEDIDENTIFIER); + } else if (sc.Match('/', '*')) { + if (sc.Match("/**") || sc.Match("/*!")) { // Support of Doxygen doc. style + sc.SetState(SCE_SQL_COMMENTDOC); + } else { + sc.SetState(SCE_SQL_COMMENT); + } + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('-', '-')) { + // MySQL requires a space or control char after -- + // http://dev.mysql.com/doc/mysql/en/ansi-diff-comments.html + // Perhaps we should enforce that with proper property: +//~ } else if (sc.Match("-- ")) { + sc.SetState(SCE_SQL_COMMENTLINE); + } else if (sc.ch == '#') { + sc.SetState(SCE_SQL_COMMENTLINEDOC); + } else if (sc.ch == '\'') { + sc.SetState(SCE_SQL_CHARACTER); + } else if (sc.ch == '\"') { + sc.SetState(SCE_SQL_STRING); + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_SQL_OPERATOR); + } + } + } + sc.Complete(); +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_SQL_COMMENT || + style == SCE_SQL_COMMENTDOC || + style == SCE_SQL_COMMENTDOCKEYWORD || + style == SCE_SQL_COMMENTDOCKEYWORDERROR; +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment. +static void FoldSQLDoc(unsigned int startPos, int length, int initStyle, + WordList *[], Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldOnlyBegin = styler.GetPropertyInt("fold.sql.only.begin", 0) != 0; + + // property fold.sql.exists + // Enables "EXISTS" to end a fold as is started by "IF" in "DROP TABLE IF EXISTS". + bool foldSqlExists = styler.GetPropertyInt("fold.sql.exists", 1) != 0; + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) { + levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16; + } + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + bool endFound = false; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (foldComment && (style == SCE_SQL_COMMENTLINE)) { + // MySQL needs -- comments to be followed by space or control char + if ((ch == '-') && (chNext == '-')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + char chNext3 = styler.SafeGetCharAt(i + 3); + if (chNext2 == '{' || chNext3 == '{') { + levelNext++; + } else if (chNext2 == '}' || chNext3 == '}') { + levelNext--; + } + } + } + if (style == SCE_SQL_OPERATOR) { + if (ch == '(') { + levelNext++; + } else if (ch == ')') { + levelNext--; + } + } + // If new keyword (cannot trigger on elseif or nullif, does less tests) + if (style == SCE_SQL_WORD && stylePrev != SCE_SQL_WORD) { + const int MAX_KW_LEN = 6; // Maximum length of folding keywords + char s[MAX_KW_LEN + 2]; + unsigned int j = 0; + for (; j < MAX_KW_LEN + 1; j++) { + if (!iswordchar(styler[i + j])) { + break; + } + s[j] = static_cast(tolower(styler[i + j])); + } + if (j == MAX_KW_LEN + 1) { + // Keyword too long, don't test it + s[0] = '\0'; + } else { + s[j] = '\0'; + } + if ((!foldOnlyBegin) && (strcmp(s, "if") == 0 || strcmp(s, "loop") == 0)) { + if (endFound) { + // ignore + endFound = false; + } else { + levelNext++; + } + } else if (strcmp(s, "begin") == 0) { + levelNext++; + } else if ((strcmp(s, "end") == 0) || +// // DROP TABLE IF EXISTS or CREATE TABLE IF NOT EXISTS + (foldSqlExists && (strcmp(s, "exists") == 0)) || +// // SQL Anywhere permits IF ... ELSE ... ENDIF +// // will only be active if "endif" appears in the +// // keyword list. + (strcmp(s, "endif") == 0)) { + endFound = true; + levelNext--; + if (levelNext < SC_FOLDLEVELBASE) { + levelNext = SC_FOLDLEVELBASE; + } + } + } + if (atEOL) { + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + visibleChars = 0; + endFound = false; + } + if (!isspacechar(ch)) { + visibleChars++; + } + } +} + +static const char * const sqlWordListDesc[] = { + "Keywords", + "Database Objects", + "PLDoc", + "SQL*Plus", + "User Keywords 1", + "User Keywords 2", + "User Keywords 3", + "User Keywords 4", + 0 +}; + +LexerModule lmSQL(SCLEX_SQL, ColouriseSQLDoc, "sql", FoldSQLDoc, sqlWordListDesc); diff --git a/lexers/LexScriptol.cxx b/lexers/LexScriptol.cxx new file mode 100644 index 000000000..76c38e6b6 --- /dev/null +++ b/lexers/LexScriptol.cxx @@ -0,0 +1,408 @@ +// Scintilla source code edit control +/** @file LexScriptol.cxx + ** Lexer for Scriptol. + **/ + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static void ClassifyWordSol(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) +{ + char s[100]; + bool wordIsNumber = isdigit(styler[start]) != 0; + for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) + { + s[i] = styler[start + i]; + s[i + 1] = '\0'; + } + char chAttr = SCE_SCRIPTOL_IDENTIFIER; + if (0 == strcmp(prevWord, "class")) chAttr = SCE_SCRIPTOL_CLASSNAME; + else if (wordIsNumber) chAttr = SCE_SCRIPTOL_NUMBER; + else if (keywords.InList(s)) chAttr = SCE_SCRIPTOL_KEYWORD; + else for (unsigned int i = 0; i < end - start + 1; i++) // test dotted idents + { + if (styler[start + i] == '.') + { + styler.ColourTo(start + i - 1, chAttr); + styler.ColourTo(start + i, SCE_SCRIPTOL_OPERATOR); + } + } + styler.ColourTo(end, chAttr); + strcpy(prevWord, s); +} + +static bool IsSolComment(Accessor &styler, int pos, int len) +{ + char c; + if(len > 0) + { + c = styler[pos]; + if(c == '`') return true; + if(len > 1) + { + if(c == '/') + { + c = styler[pos + 1]; + if(c == '/') return true; + if(c == '*') return true; + } + } + } + return false; +} + +static bool IsSolStringStart(char ch) +{ + if (ch == '\'' || ch == '"') return true; + return false; +} + +static bool IsSolWordStart(char ch) +{ + return (iswordchar(ch) && !IsSolStringStart(ch)); +} + + +static int GetSolStringState(Accessor &styler, int i, int *nextIndex) +{ + char ch = styler.SafeGetCharAt(i); + char chNext = styler.SafeGetCharAt(i + 1); + + if (ch != '\"' && ch != '\'') + { + *nextIndex = i + 1; + return SCE_SCRIPTOL_DEFAULT; + } + // ch is either single or double quotes in string + // code below seem non-sense but is here for future extensions + if (ch == chNext && ch == styler.SafeGetCharAt(i + 2)) + { + *nextIndex = i + 3; + if(ch == '\"') return SCE_SCRIPTOL_TRIPLE; + if(ch == '\'') return SCE_SCRIPTOL_TRIPLE; + return SCE_SCRIPTOL_STRING; + } + else + { + *nextIndex = i + 1; + if (ch == '"') return SCE_SCRIPTOL_STRING; + else return SCE_SCRIPTOL_STRING; + } +} + + +static void ColouriseSolDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) + { + + int lengthDoc = startPos + length; + char stringType = '\"'; + + if (startPos > 0) + { + int lineCurrent = styler.GetLine(startPos); + if (lineCurrent > 0) + { + startPos = styler.LineStart(lineCurrent-1); + if (startPos == 0) initStyle = SCE_SCRIPTOL_DEFAULT; + else initStyle = styler.StyleAt(startPos-1); + } + } + + styler.StartAt(startPos, 127); + + WordList &keywords = *keywordlists[0]; + + int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level"); + char prevWord[200]; + prevWord[0] = '\0'; + if (length == 0) return; + + int state = initStyle & 31; + + int nextIndex = 0; + char chPrev = ' '; + char chPrev2 = ' '; + char chNext = styler[startPos]; + styler.StartSegment(startPos); + bool atStartLine = true; + int spaceFlags = 0; + for (int i = startPos; i < lengthDoc; i++) + { + + if (atStartLine) + { + char chBad = static_cast(64); + char chGood = static_cast(0); + char chFlags = chGood; + + if (whingeLevel == 1) + { + chFlags = (spaceFlags & wsInconsistent) ? chBad : chGood; + } + else if (whingeLevel == 2) + { + chFlags = (spaceFlags & wsSpaceTab) ? chBad : chGood; + } + else if (whingeLevel == 3) + { + chFlags = (spaceFlags & wsSpace) ? chBad : chGood; + } + else if (whingeLevel == 4) + { + chFlags = (spaceFlags & wsTab) ? chBad : chGood; + } + styler.SetFlags(chFlags, static_cast(state)); + atStartLine = false; + } + + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) + { + if ((state == SCE_SCRIPTOL_DEFAULT) || + (state == SCE_SCRIPTOL_TRIPLE) || + (state == SCE_SCRIPTOL_COMMENTBLOCK)) + { + styler.ColourTo(i, state); + } + atStartLine = true; + } + + if (styler.IsLeadByte(ch)) + { + chNext = styler.SafeGetCharAt(i + 2); + chPrev = ' '; + chPrev2 = ' '; + i += 1; + continue; + } + + if (state == SCE_SCRIPTOL_STRINGEOL) + { + if (ch != '\r' && ch != '\n') + { + styler.ColourTo(i - 1, state); + state = SCE_SCRIPTOL_DEFAULT; + } + } + + if (state == SCE_SCRIPTOL_DEFAULT) + { + if (IsSolWordStart(ch)) + { + styler.ColourTo(i - 1, state); + state = SCE_SCRIPTOL_KEYWORD; + } + else if (ch == '`') + { + styler.ColourTo(i - 1, state); + state = SCE_SCRIPTOL_COMMENTLINE; + } + else if (ch == '/') + { + styler.ColourTo(i - 1, state); + if(chNext == '/') state = SCE_SCRIPTOL_CSTYLE; + if(chNext == '*') state = SCE_SCRIPTOL_COMMENTBLOCK; + } + + else if (IsSolStringStart(ch)) + { + styler.ColourTo(i - 1, state); + state = GetSolStringState(styler, i, &nextIndex); + if(state == SCE_SCRIPTOL_STRING) + { + stringType = ch; + } + if (nextIndex != i + 1) + { + i = nextIndex - 1; + ch = ' '; + chPrev = ' '; + chNext = styler.SafeGetCharAt(i + 1); + } + } + else if (isoperator(ch)) + { + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_SCRIPTOL_OPERATOR); + } + } + else if (state == SCE_SCRIPTOL_KEYWORD) + { + if (!iswordchar(ch)) + { + ClassifyWordSol(styler.GetStartSegment(), i - 1, keywords, styler, prevWord); + state = SCE_SCRIPTOL_DEFAULT; + if (ch == '`') + { + state = chNext == '`' ? SCE_SCRIPTOL_PERSISTENT : SCE_SCRIPTOL_COMMENTLINE; + } + else if (IsSolStringStart(ch)) + { + styler.ColourTo(i - 1, state); + state = GetSolStringState(styler, i, &nextIndex); + if (nextIndex != i + 1) + { + i = nextIndex - 1; + ch = ' '; + chPrev = ' '; + chNext = styler.SafeGetCharAt(i + 1); + } + } + else if (isoperator(ch)) + { + styler.ColourTo(i, SCE_SCRIPTOL_OPERATOR); + } + } + } + else + { + if (state == SCE_SCRIPTOL_COMMENTLINE || + state == SCE_SCRIPTOL_PERSISTENT || + state == SCE_SCRIPTOL_CSTYLE) + { + if (ch == '\r' || ch == '\n') + { + styler.ColourTo(i - 1, state); + state = SCE_SCRIPTOL_DEFAULT; + } + } + else if(state == SCE_SCRIPTOL_COMMENTBLOCK) + { + if(chPrev == '*' && ch == '/') + { + styler.ColourTo(i, state); + state = SCE_SCRIPTOL_DEFAULT; + } + } + else if ((state == SCE_SCRIPTOL_STRING) || + (state == SCE_SCRIPTOL_CHARACTER)) + { + if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) + { + styler.ColourTo(i - 1, state); + state = SCE_SCRIPTOL_STRINGEOL; + } + else if (ch == '\\') + { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') + { + i++; + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + } + } + else if ((ch == '\"') || (ch == '\'')) + { + // must match the entered quote type + if(ch == stringType) + { + styler.ColourTo(i, state); + state = SCE_SCRIPTOL_DEFAULT; + } + } + } + else if (state == SCE_SCRIPTOL_TRIPLE) + { + if ((ch == '\'' && chPrev == '\'' && chPrev2 == '\'') || + (ch == '\"' && chPrev == '\"' && chPrev2 == '\"')) + { + styler.ColourTo(i, state); + state = SCE_SCRIPTOL_DEFAULT; + } + } + + } + chPrev2 = chPrev; + chPrev = ch; + } + if (state == SCE_SCRIPTOL_KEYWORD) + { + ClassifyWordSol(styler.GetStartSegment(), + lengthDoc-1, keywords, styler, prevWord); + } + else + { + styler.ColourTo(lengthDoc-1, state); + } +} + +static void FoldSolDoc(unsigned int startPos, int length, int initStyle, + WordList *[], Accessor &styler) + { + int lengthDoc = startPos + length; + + int lineCurrent = styler.GetLine(startPos); + if (startPos > 0) + { + if (lineCurrent > 0) + { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + if (startPos == 0) + initStyle = SCE_SCRIPTOL_DEFAULT; + else + initStyle = styler.StyleAt(startPos-1); + } + } + int state = initStyle & 31; + int spaceFlags = 0; + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsSolComment); + if ((state == SCE_SCRIPTOL_TRIPLE)) + indentCurrent |= SC_FOLDLEVELWHITEFLAG; + char chNext = styler[startPos]; + for (int i = startPos; i < lengthDoc; i++) + { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styler.StyleAt(i) & 31; + + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) + { + int lev = indentCurrent; + int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsSolComment); + if (style == SCE_SCRIPTOL_TRIPLE) + indentNext |= SC_FOLDLEVELWHITEFLAG; + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) + { + // Only non whitespace lines can be headers + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) + { + lev |= SC_FOLDLEVELHEADERFLAG; + } + else if (indentNext & SC_FOLDLEVELWHITEFLAG) + { + // Line after is blank so check the next - maybe should continue further? + int spaceFlags2 = 0; + int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsSolComment); + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) + { + lev |= SC_FOLDLEVELHEADERFLAG; + } + } + } + indentCurrent = indentNext; + styler.SetLevel(lineCurrent, lev); + lineCurrent++; + } + } +} + +LexerModule lmScriptol(SCLEX_SCRIPTOL, ColouriseSolDoc, "scriptol", FoldSolDoc); diff --git a/lexers/LexSmalltalk.cxx b/lexers/LexSmalltalk.cxx new file mode 100644 index 000000000..265de3803 --- /dev/null +++ b/lexers/LexSmalltalk.cxx @@ -0,0 +1,321 @@ +// Scintilla source code edit control +/** @file LexSmalltalk.cxx + ** Lexer for Smalltalk language. + ** Written by Sergey Philippov, sphilippov-at-gmail-dot-com + **/ +// Copyright 1998-2002 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +/* +| lexTable classificationBlock charClasses | +charClasses := #(#DecDigit #Letter #Special #Upper #BinSel). +lexTable := ByteArray new: 128. +classificationBlock := [ :charClass :chars | + | flag | + flag := 1 bitShift: (charClasses indexOf: charClass) - 1. + chars do: [ :char | lexTable at: char codePoint + 1 put: ((lexTable at: char codePoint + 1) bitOr: flag)]]. + +classificationBlock + value: #DecDigit value: '0123456789'; + value: #Letter value: '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + value: #Special value: '()[]{};.^:'; + value: #BinSel value: '~@%&*-+=|\/,<>?!'; + value: #Upper value: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. + +((String new: 500) streamContents: [ :stream | + stream crLf; nextPutAll: 'static int ClassificationTable[256] = {'. + lexTable keysAndValuesDo: [ :index :value | + ((index - 1) rem: 16) == 0 ifTrue: [ + stream crLf; tab] + ifFalse: [ + stream space]. + stream print: value. + index ~= 256 ifTrue: [ + stream nextPut: $,]]. + stream crLf; nextPutAll: '};'; crLf. + + charClasses keysAndValuesDo: [ :index :name | + stream + crLf; + nextPutAll: ( + ('static inline bool is<1s>(int ch) {return (ch > 0) && (ch %< 0x80) && ((ClassificationTable[ch] & <2p>) != 0);}') + expandMacrosWith: name with: (1 bitShift: (index - 1))) + ]]) edit +*/ + +// autogenerated {{{{ + +static int ClassificationTable[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 16, 16, 0, 4, 4, 16, 16, 16, 16, 4, 16, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 16, 16, 16, 16, + 16, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 16, 4, 4, 2, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 16, 4, 16, 0, +}; + +static inline bool isDecDigit(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 1) != 0);} +static inline bool isLetter(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 2) != 0);} +static inline bool isSpecial(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 4) != 0);} +static inline bool isUpper(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 8) != 0);} +static inline bool isBinSel(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 16) != 0);} +// autogenerated }}}} + +static inline bool isAlphaNumeric(int ch) { + return isDecDigit(ch) || isLetter(ch); +} + +static inline bool isDigitOfRadix(int ch, int radix) +{ + if (isDecDigit(ch)) + return (ch - '0') < radix; + else if (!isUpper(ch)) + return false; + else + return (ch - 'A' + 10) < radix; +} + +static inline void skipComment(StyleContext& sc) +{ + while (sc.More() && sc.ch != '\"') + sc.Forward(); +} + +static inline void skipString(StyleContext& sc) +{ + while (sc.More()) { + if (sc.ch == '\'') { + if (sc.chNext != '\'') + return; + sc.Forward(); + } + sc.Forward(); + } +} + +static void handleHash(StyleContext& sc) +{ + if (isSpecial(sc.chNext)) { + sc.SetState(SCE_ST_SPECIAL); + return; + } + + sc.SetState(SCE_ST_SYMBOL); + sc.Forward(); + if (sc.ch == '\'') { + sc.Forward(); + skipString(sc); + } + else { + if (isLetter(sc.ch)) { + while (isAlphaNumeric(sc.chNext) || sc.chNext == ':') + sc.Forward(); + } + else if (isBinSel(sc.ch)) { + while (isBinSel(sc.chNext)) + sc.Forward(); + } + } +} + +static inline void handleSpecial(StyleContext& sc) +{ + if (sc.ch == ':' && sc.chNext == '=') { + sc.SetState(SCE_ST_ASSIGN); + sc.Forward(); + } + else { + if (sc.ch == '^') + sc.SetState(SCE_ST_RETURN); + else + sc.SetState(SCE_ST_SPECIAL); + } +} + +static inline void skipInt(StyleContext& sc, int radix) +{ + while (isDigitOfRadix(sc.chNext, radix)) + sc.Forward(); +} + +static void handleNumeric(StyleContext& sc) +{ + char num[256]; + int nl; + int radix; + + sc.SetState(SCE_ST_NUMBER); + num[0] = static_cast(sc.ch); + nl = 1; + while (isDecDigit(sc.chNext)) { + num[nl++] = static_cast(sc.chNext); + sc.Forward(); + if (nl+1 == sizeof(num)/sizeof(num[0])) // overrun check + break; + } + if (sc.chNext == 'r') { + num[nl] = 0; + if (num[0] == '-') + radix = atoi(num + 1); + else + radix = atoi(num); + sc.Forward(); + if (sc.chNext == '-') + sc.Forward(); + skipInt(sc, radix); + } + else + radix = 10; + if (sc.chNext != '.' || !isDigitOfRadix(sc.GetRelative(2), radix)) + return; + sc.Forward(); + skipInt(sc, radix); + if (sc.chNext == 's') { + // ScaledDecimal + sc.Forward(); + while (isDecDigit(sc.chNext)) + sc.Forward(); + return; + } + else if (sc.chNext != 'e' && sc.chNext != 'd' && sc.chNext != 'q') + return; + sc.Forward(); + if (sc.chNext == '+' || sc.chNext == '-') + sc.Forward(); + skipInt(sc, radix); +} + +static inline void handleBinSel(StyleContext& sc) +{ + sc.SetState(SCE_ST_BINARY); + while (isBinSel(sc.chNext)) + sc.Forward(); +} + +static void handleLetter(StyleContext& sc, WordList* specialSelectorList) +{ + char ident[256]; + int il; + int state; + bool doubleColonPresent; + + sc.SetState(SCE_ST_DEFAULT); + + ident[0] = static_cast(sc.ch); + il = 1; + while (isAlphaNumeric(sc.chNext)) { + ident[il++] = static_cast(sc.chNext); + sc.Forward(); + if (il+2 == sizeof(ident)/sizeof(ident[0])) // overrun check + break; + } + + if (sc.chNext == ':') { + doubleColonPresent = true; + ident[il++] = ':'; + sc.Forward(); + } + else + doubleColonPresent = false; + ident[il] = 0; + + if (specialSelectorList->InList(ident)) + state = SCE_ST_SPEC_SEL; + else if (doubleColonPresent) + state = SCE_ST_KWSEND; + else if (isUpper(ident[0])) + state = SCE_ST_GLOBAL; + else { + if (!strcmp(ident, "self")) + state = SCE_ST_SELF; + else if (!strcmp(ident, "super")) + state = SCE_ST_SUPER; + else if (!strcmp(ident, "nil")) + state = SCE_ST_NIL; + else if (!strcmp(ident, "true") || !strcmp(ident, "false")) + state = SCE_ST_BOOL; + else + state = SCE_ST_DEFAULT; + } + + sc.ChangeState(state); +} + +static void colorizeSmalltalkDoc(unsigned int startPos, int length, int initStyle, WordList *wordLists[], Accessor &styler) +{ + StyleContext sc(startPos, length, initStyle, styler); + + if (initStyle == SCE_ST_COMMENT) { + skipComment(sc); + if (sc.More()) + sc.Forward(); + } + else if (initStyle == SCE_ST_STRING) { + skipString(sc); + if (sc.More()) + sc.Forward(); + } + + for (; sc.More(); sc.Forward()) { + int ch; + + ch = sc.ch; + if (ch == '\"') { + sc.SetState(SCE_ST_COMMENT); + sc.Forward(); + skipComment(sc); + } + else if (ch == '\'') { + sc.SetState(SCE_ST_STRING); + sc.Forward(); + skipString(sc); + } + else if (ch == '#') + handleHash(sc); + else if (ch == '$') { + sc.SetState(SCE_ST_CHARACTER); + sc.Forward(); + } + else if (isSpecial(ch)) + handleSpecial(sc); + else if (isDecDigit(ch)) + handleNumeric(sc); + else if (isLetter(ch)) + handleLetter(sc, wordLists[0]); + else if (isBinSel(ch)) { + if (ch == '-' && isDecDigit(sc.chNext)) + handleNumeric(sc); + else + handleBinSel(sc); + } + else + sc.SetState(SCE_ST_DEFAULT); + } + sc.Complete(); +} + +static const char* const smalltalkWordListDesc[] = { + "Special selectors", + 0 +}; + +LexerModule lmSmalltalk(SCLEX_SMALLTALK, colorizeSmalltalkDoc, "smalltalk", NULL, smalltalkWordListDesc); diff --git a/lexers/LexSorcus.cxx b/lexers/LexSorcus.cxx new file mode 100644 index 000000000..1d8ba277a --- /dev/null +++ b/lexers/LexSorcus.cxx @@ -0,0 +1,205 @@ +// Scintilla source code edit control +/** @file LexSorcus.cxx +** Lexer for SORCUS installation files +** Written by Eugen Bitter and Christoph Baumann at SORCUS Computer, Heidelberg Germany +** Based on the ASM Lexer by The Black Horus +**/ + +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + + +//each character a..z and A..Z + '_' can be part of a keyword +//additionally numbers that follow 'M' can be contained in a keyword +static inline bool IsSWordStart(const int ch, const int prev_ch) +{ + if (isalpha(ch) || (ch == '_') || ((isdigit(ch)) && (prev_ch == 'M'))) + return true; + + return false; +} + + +//only digits that are not preceded by 'M' count as a number +static inline bool IsSorcusNumber(const int ch, const int prev_ch) +{ + if ((isdigit(ch)) && (prev_ch != 'M')) + return true; + + return false; +} + + +//only = is a valid operator +static inline bool IsSorcusOperator(const int ch) +{ + if (ch == '=') + return true; + + return false; +} + + +static void ColouriseSorcusDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) +{ + + WordList &Command = *keywordlists[0]; + WordList &Parameter = *keywordlists[1]; + WordList &Constant = *keywordlists[2]; + + // Do not leak onto next line + if (initStyle == SCE_SORCUS_STRINGEOL) + initStyle = SCE_SORCUS_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) + { + + // Prevent SCE_SORCUS_STRINGEOL from leaking back to previous line + if (sc.atLineStart && (sc.state == SCE_SORCUS_STRING)) + { + sc.SetState(SCE_SORCUS_STRING); + } + + // Determine if the current state should terminate. + if (sc.state == SCE_SORCUS_OPERATOR) + { + if (!IsSorcusOperator(sc.ch)) + { + sc.SetState(SCE_SORCUS_DEFAULT); + } + } + else if(sc.state == SCE_SORCUS_NUMBER) + { + if(!IsSorcusNumber(sc.ch, sc.chPrev)) + { + sc.SetState(SCE_SORCUS_DEFAULT); + } + } + else if (sc.state == SCE_SORCUS_IDENTIFIER) + { + if (!IsSWordStart(sc.ch, sc.chPrev)) + { + char s[100]; + + sc.GetCurrent(s, sizeof(s)); + + if (Command.InList(s)) + { + sc.ChangeState(SCE_SORCUS_COMMAND); + } + else if (Parameter.InList(s)) + { + sc.ChangeState(SCE_SORCUS_PARAMETER); + } + else if (Constant.InList(s)) + { + sc.ChangeState(SCE_SORCUS_CONSTANT); + } + + sc.SetState(SCE_SORCUS_DEFAULT); + } + } + else if (sc.state == SCE_SORCUS_COMMENTLINE ) + { + if (sc.atLineEnd) + { + sc.SetState(SCE_SORCUS_DEFAULT); + } + } + else if (sc.state == SCE_SORCUS_STRING) + { + if (sc.ch == '\"') + { + sc.ForwardSetState(SCE_SORCUS_DEFAULT); + } + else if (sc.atLineEnd) + { + sc.ChangeState(SCE_SORCUS_STRINGEOL); + sc.ForwardSetState(SCE_SORCUS_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_SORCUS_DEFAULT) + { + if ((sc.ch == ';') || (sc.ch == '\'')) + { + sc.SetState(SCE_SORCUS_COMMENTLINE); + } + else if (IsSWordStart(sc.ch, sc.chPrev)) + { + sc.SetState(SCE_SORCUS_IDENTIFIER); + } + else if (sc.ch == '\"') + { + sc.SetState(SCE_SORCUS_STRING); + } + else if (IsSorcusOperator(sc.ch)) + { + sc.SetState(SCE_SORCUS_OPERATOR); + } + else if (IsSorcusNumber(sc.ch, sc.chPrev)) + { + sc.SetState(SCE_SORCUS_NUMBER); + } + } + + } + sc.Complete(); +} + + +static const char* const SorcusWordListDesc[] = {"Command","Parameter", "Constant", 0}; + +LexerModule lmSorc(SCLEX_SORCUS, ColouriseSorcusDoc, "sorcins", 0, SorcusWordListDesc); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lexers/LexSpecman.cxx b/lexers/LexSpecman.cxx new file mode 100644 index 000000000..093efae75 --- /dev/null +++ b/lexers/LexSpecman.cxx @@ -0,0 +1,289 @@ +// Scintilla source code edit control +/** @file LexSpecman.cxx + ** Lexer for Specman E language. + ** Written by Avi Yegudin, based on C++ lexer by Neil Hodgson + **/ +// Copyright 1998-2002 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''); +} + +static inline bool IsANumberChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '\''); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '`'); +} + +static void ColouriseSpecmanDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler, bool caseSensitive) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + + // Do not leak onto next line + if (initStyle == SCE_SN_STRINGEOL) + initStyle = SCE_SN_CODE; + + int visibleChars = 0; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart && (sc.state == SCE_SN_STRING)) { + // Prevent SCE_SN_STRINGEOL from leaking back to previous line + sc.SetState(SCE_SN_STRING); + } + + // Handle line continuation generically. + if (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_SN_OPERATOR) { + sc.SetState(SCE_SN_CODE); + } else if (sc.state == SCE_SN_NUMBER) { + if (!IsANumberChar(sc.ch)) { + sc.SetState(SCE_SN_CODE); + } + } else if (sc.state == SCE_SN_IDENTIFIER) { + if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { + char s[100]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (keywords.InList(s)) { + sc.ChangeState(SCE_SN_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_SN_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_SN_WORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_SN_USER); + } + sc.SetState(SCE_SN_CODE); + } + } else if (sc.state == SCE_SN_PREPROCESSOR) { + if (IsASpace(sc.ch)) { + sc.SetState(SCE_SN_CODE); + } + } else if (sc.state == SCE_SN_DEFAULT) { + if (sc.Match('<', '\'')) { + sc.Forward(); + sc.ForwardSetState(SCE_SN_CODE); + } + } else if (sc.state == SCE_SN_COMMENTLINE || sc.state == SCE_SN_COMMENTLINEBANG) { + if (sc.atLineEnd) { + sc.SetState(SCE_SN_CODE); + visibleChars = 0; + } + } else if (sc.state == SCE_SN_STRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_SN_CODE); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_SN_STRINGEOL); + sc.ForwardSetState(SCE_SN_CODE); + visibleChars = 0; + } + } else if (sc.state == SCE_SN_SIGNAL) { + if (sc.atLineEnd) { + sc.ChangeState(SCE_SN_STRINGEOL); + sc.ForwardSetState(SCE_SN_CODE); + visibleChars = 0; + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_SN_CODE); + } + } else if (sc.state == SCE_SN_REGEXTAG) { + if (!IsADigit(sc.ch)) { + sc.SetState(SCE_SN_CODE); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_SN_CODE) { + if (sc.ch == '$' && IsADigit(sc.chNext)) { + sc.SetState(SCE_SN_REGEXTAG); + sc.Forward(); + } else if (IsADigit(sc.ch)) { + sc.SetState(SCE_SN_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_SN_IDENTIFIER); + } else if (sc.Match('\'', '>')) { + sc.SetState(SCE_SN_DEFAULT); + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + if (sc.Match("//!")) // Nice to have a different comment style + sc.SetState(SCE_SN_COMMENTLINEBANG); + else + sc.SetState(SCE_SN_COMMENTLINE); + } else if (sc.Match('-', '-')) { + if (sc.Match("--!")) // Nice to have a different comment style + sc.SetState(SCE_SN_COMMENTLINEBANG); + else + sc.SetState(SCE_SN_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_SN_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_SN_SIGNAL); + } else if (sc.ch == '#' && visibleChars == 0) { + // Preprocessor commands are alone on their line + sc.SetState(SCE_SN_PREPROCESSOR); + // Skip whitespace between # and preprocessor word + do { + sc.Forward(); + } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); + if (sc.atLineEnd) { + sc.SetState(SCE_SN_CODE); + } + } else if (isoperator(static_cast(sc.ch)) || sc.ch == '@') { + sc.SetState(SCE_SN_OPERATOR); + } + } + + if (sc.atLineEnd) { + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + } + if (!IsASpace(sc.ch)) { + visibleChars++; + } + } + sc.Complete(); +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "} else {". +static void FoldNoBoxSpecmanDoc(unsigned int startPos, int length, int, + Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + //int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && (style == SCE_SN_COMMENTLINE)) { + if (((ch == '/') && (chNext == '/')) || + ((ch == '-') && (chNext == '-'))) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelNext++; + } else if (chNext2 == '}') { + levelNext--; + } + } + } + if (style == SCE_SN_OPERATOR) { + if (ch == '{') { + // Measure the minimum before a '{' to allow + // folding on "} else {" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + if (atEOL) { + int levelUse = levelCurrent; + if (foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } +} + +static void FoldSpecmanDoc(unsigned int startPos, int length, int initStyle, WordList *[], + Accessor &styler) { + FoldNoBoxSpecmanDoc(startPos, length, initStyle, styler); +} + +static const char * const specmanWordLists[] = { + "Primary keywords and identifiers", + "Secondary keywords and identifiers", + "Sequence keywords and identifiers", + "User defined keywords and identifiers", + "Unused", + 0, + }; + +static void ColouriseSpecmanDocSensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + ColouriseSpecmanDoc(startPos, length, initStyle, keywordlists, styler, true); +} + + +LexerModule lmSpecman(SCLEX_SPECMAN, ColouriseSpecmanDocSensitive, "specman", FoldSpecmanDoc, specmanWordLists); diff --git a/lexers/LexSpice.cxx b/lexers/LexSpice.cxx new file mode 100644 index 000000000..6aa2e8fdc --- /dev/null +++ b/lexers/LexSpice.cxx @@ -0,0 +1,226 @@ +// Scintilla source code edit control +/** @file LexSpice.cxx + ** Lexer for Spice + **/ +// Copyright 2006 by Fabien Proriol +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include + +#include + +#include "Platform.h" + +#include "Accessor.h" +#include "StyleContext.h" +#include "PropSet.h" +#include "KeyWords.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +/* + * Interface + */ + +static void ColouriseDocument( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler); + +static const char * const spiceWordListDesc[] = { + "Keywords", // SPICE command + "Keywords2", // SPICE functions + "Keywords3", // SPICE params + 0 +}; + +LexerModule lmSpice(SCLEX_SPICE, ColouriseDocument, "spice", NULL, spiceWordListDesc); + +/* + * Implementation + */ + +static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute); +static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute); + +static inline bool IsDelimiterCharacter(int ch); +static inline bool IsNumberStartCharacter(int ch); +static inline bool IsNumberCharacter(int ch); +static inline bool IsSeparatorOrDelimiterCharacter(int ch); +static inline bool IsWordStartCharacter(int ch); +static inline bool IsWordCharacter(int ch); + +static void ColouriseComment(StyleContext& sc, bool&) { + sc.SetState(SCE_SPICE_COMMENTLINE); + while (!sc.atLineEnd) { + sc.Forward(); + } +} + +static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = sc.Match (')'); + sc.SetState(SCE_SPICE_DELIMITER); + sc.ForwardSetState(SCE_SPICE_DEFAULT); +} + +static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = true; + std::string number; + sc.SetState(SCE_SPICE_NUMBER); + // Get all characters up to a delimiter or a separator, including points, but excluding + // double points (ranges). + while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) { + number += static_cast(sc.ch); + sc.Forward(); + } + // Special case: exponent with sign + if ((sc.chPrev == 'e' || sc.chPrev == 'E') && + (sc.ch == '+' || sc.ch == '-')) { + number += static_cast(sc.ch); + sc.Forward (); + while (!IsSeparatorOrDelimiterCharacter(sc.ch)) { + number += static_cast(sc.ch); + sc.Forward(); + } + } + sc.SetState(SCE_SPICE_DEFAULT); +} + +static void ColouriseWhiteSpace(StyleContext& sc, bool& ) { + sc.SetState(SCE_SPICE_DEFAULT); + sc.ForwardSetState(SCE_SPICE_DEFAULT); +} + +static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute) { + apostropheStartsAttribute = true; + sc.SetState(SCE_SPICE_IDENTIFIER); + std::string word; + while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) { + word += static_cast(tolower(sc.ch)); + sc.Forward(); + } + if (keywords.InList(word.c_str())) { + sc.ChangeState(SCE_SPICE_KEYWORD); + if (word != "all") { + apostropheStartsAttribute = false; + } + } + else if (keywords2.InList(word.c_str())) { + sc.ChangeState(SCE_SPICE_KEYWORD2); + if (word != "all") { + apostropheStartsAttribute = false; + } + } + else if (keywords3.InList(word.c_str())) { + sc.ChangeState(SCE_SPICE_KEYWORD3); + if (word != "all") { + apostropheStartsAttribute = false; + } + } + sc.SetState(SCE_SPICE_DEFAULT); +} + +// +// ColouriseDocument +// +static void ColouriseDocument( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + StyleContext sc(startPos, length, initStyle, styler); + int lineCurrent = styler.GetLine(startPos); + bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0; + while (sc.More()) { + if (sc.atLineEnd) { + // Go to the next line + sc.Forward(); + lineCurrent++; + // Remember the line state for future incremental lexing + styler.SetLineState(lineCurrent, apostropheStartsAttribute); + // Don't continue any styles on the next line + sc.SetState(SCE_SPICE_DEFAULT); + } + // Comments + if ((sc.Match('*') && sc.atLineStart) || sc.Match('*','~')) { + ColouriseComment(sc, apostropheStartsAttribute); + // Whitespace + } else if (IsASpace(sc.ch)) { + ColouriseWhiteSpace(sc, apostropheStartsAttribute); + // Delimiters + } else if (IsDelimiterCharacter(sc.ch)) { + ColouriseDelimiter(sc, apostropheStartsAttribute); + // Numbers + } else if (IsADigit(sc.ch) || sc.ch == '#') { + ColouriseNumber(sc, apostropheStartsAttribute); + // Keywords or identifiers + } else { + ColouriseWord(sc, keywords, keywords2, keywords3, apostropheStartsAttribute); + } + } + sc.Complete(); +} + +static inline bool IsDelimiterCharacter(int ch) { + switch (ch) { + case '&': + case '\'': + case '(': + case ')': + case '*': + case '+': + case ',': + case '-': + case '.': + case '/': + case ':': + case ';': + case '<': + case '=': + case '>': + case '|': + return true; + default: + return false; + } +} + +static inline bool IsNumberCharacter(int ch) { + return IsNumberStartCharacter(ch) || + ch == '_' || + ch == '.' || + ch == '#' || + (ch >= 'a' && ch <= 'f') || + (ch >= 'A' && ch <= 'F'); +} + +static inline bool IsNumberStartCharacter(int ch) { + return IsADigit(ch); +} + +static inline bool IsSeparatorOrDelimiterCharacter(int ch) { + return IsASpace(ch) || IsDelimiterCharacter(ch); +} + +static inline bool IsWordCharacter(int ch) { + return IsWordStartCharacter(ch) || IsADigit(ch); +} + +static inline bool IsWordStartCharacter(int ch) { + return (isascii(ch) && isalpha(ch)) || ch == '_'; +} diff --git a/lexers/LexTACL.cxx b/lexers/LexTACL.cxx new file mode 100644 index 000000000..b0c12440d --- /dev/null +++ b/lexers/LexTACL.cxx @@ -0,0 +1,397 @@ +// Scintilla source code edit control +/** @file LexTAL.cxx + ** Lexer for TAL + ** Based on LexPascal.cxx + ** Written by Laurent le Tynevez + ** Updated by Simon Steele September 2002 + ** Updated by Mathias Rauen May 2003 (Delphi adjustments) + ** Updated by Rod Falck, Aug 2006 Converted to TACL + **/ + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "StyleContext.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +inline bool isTACLoperator(char ch) + { + return ch == '\'' || isoperator(ch); + } + +inline bool isTACLwordchar(char ch) + { + return ch == '#' || ch == '^' || ch == '|' || ch == '_' || iswordchar(ch); + } + +inline bool isTACLwordstart(char ch) + { + return ch == '#' || ch == '|' || ch == '_' || iswordstart(ch); + } + +static void getRange(unsigned int start, + unsigned int end, + Accessor &styler, + char *s, + unsigned int len) { + unsigned int i = 0; + while ((i < end - start + 1) && (i < len-1)) { + s[i] = static_cast(tolower(styler[start + i])); + i++; + } + s[i] = '\0'; +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_C_COMMENT || + style == SCE_C_COMMENTDOC || + style == SCE_C_COMMENTDOCKEYWORD || + style == SCE_C_COMMENTDOCKEYWORDERROR; +} + +static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr, bool bInAsm) { + if ((bInAsm) && (attr == SCE_C_OPERATOR || attr == SCE_C_NUMBER || attr == SCE_C_DEFAULT || attr == SCE_C_WORD || attr == SCE_C_IDENTIFIER)) { + styler.ColourTo(end, SCE_C_REGEX); + } else + styler.ColourTo(end, attr); +} + +// returns 1 if the item starts a class definition, and -1 if the word is "end", and 2 if the word is "asm" +static int classifyWordTACL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, bool bInAsm) { + int ret = 0; + + WordList& keywords = *keywordlists[0]; + WordList& builtins = *keywordlists[1]; + WordList& commands = *keywordlists[2]; + + char s[100]; + getRange(start, end, styler, s, sizeof(s)); + + char chAttr = SCE_C_IDENTIFIER; + if (isdigit(s[0]) || (s[0] == '.')) { + chAttr = SCE_C_NUMBER; + } + else { + if (s[0] == '#' || keywords.InList(s)) { + chAttr = SCE_C_WORD; + + if (strcmp(s, "asm") == 0) { + ret = 2; + } + else if (strcmp(s, "end") == 0) { + ret = -1; + } + } + else if (s[0] == '|' || builtins.InList(s)) { + chAttr = SCE_C_WORD2; + } + else if (commands.InList(s)) { + chAttr = SCE_C_UUID; + } + else if (strcmp(s, "comment") == 0) { + chAttr = SCE_C_COMMENTLINE; + ret = 3; + } + } + ColourTo(styler, end, chAttr, (bInAsm && ret != -1)); + return ret; +} + +static int classifyFoldPointTACL(const char* s) { + int lev = 0; + if (s[0] == '[') + lev=1; + else if (s[0] == ']') + lev=-1; + return lev; +} + +static void ColouriseTACLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + styler.StartAt(startPos); + + int state = initStyle; + if (state == SCE_C_CHARACTER) // Does not leak onto next line + state = SCE_C_DEFAULT; + char chPrev = ' '; + char chNext = styler[startPos]; + unsigned int lengthDoc = startPos + length; + + bool bInClassDefinition; + + int currentLine = styler.GetLine(startPos); + if (currentLine > 0) { + styler.SetLineState(currentLine, styler.GetLineState(currentLine-1)); + bInClassDefinition = (styler.GetLineState(currentLine) == 1); + } else { + styler.SetLineState(currentLine, 0); + bInClassDefinition = false; + } + + bool bInAsm = (state == SCE_C_REGEX); + if (bInAsm) + state = SCE_C_DEFAULT; + + styler.StartSegment(startPos); + int visibleChars = 0; + unsigned int i; + for (i = startPos; i < lengthDoc; i++) { + char ch = chNext; + + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // End of line + if (state == SCE_C_CHARACTER) { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + visibleChars = 0; + currentLine++; + styler.SetLineState(currentLine, (bInClassDefinition ? 1 : 0)); + } + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + chPrev = ' '; + i += 1; + continue; + } + + if (state == SCE_C_DEFAULT) { + if (isTACLwordstart(ch)) { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_IDENTIFIER; + } else if (ch == '{') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENT; + } else if (ch == '{' && chNext == '*') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENTDOC; + } else if (ch == '=' && chNext == '=') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENTLINE; + } else if (ch == '"') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_STRING; + } else if (ch == '?' && visibleChars == 0) { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_PREPROCESSOR; + } else if (isTACLoperator(ch)) { + ColourTo(styler, i-1, state, bInAsm); + ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); + } + } else if (state == SCE_C_IDENTIFIER) { + if (!isTACLwordchar(ch)) { + int lStateChange = classifyWordTACL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm); + + if(lStateChange == 1) { + styler.SetLineState(currentLine, 1); + bInClassDefinition = true; + } else if(lStateChange == 2) { + bInAsm = true; + } else if(lStateChange == -1) { + styler.SetLineState(currentLine, 0); + bInClassDefinition = false; + bInAsm = false; + } + + if (lStateChange == 3) { + state = SCE_C_COMMENTLINE; + } + else { + state = SCE_C_DEFAULT; + chNext = styler.SafeGetCharAt(i + 1); + if (ch == '{') { + state = SCE_C_COMMENT; + } else if (ch == '{' && chNext == '*') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENTDOC; + } else if (ch == '=' && chNext == '=') { + state = SCE_C_COMMENTLINE; + } else if (ch == '"') { + state = SCE_C_STRING; + } else if (isTACLoperator(ch)) { + ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); + } + } + } + } else { + if (state == SCE_C_PREPROCESSOR) { + if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENT) { + if (ch == '}' || (ch == '\r' || ch == '\n') ) { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENTDOC) { + if (ch == '}' || (ch == '\r' || ch == '\n')) { + if (((i > styler.GetStartSegment() + 2) || ( + (initStyle == SCE_C_COMMENTDOC) && + (styler.GetStartSegment() == static_cast(startPos))))) { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + } + } else if (state == SCE_C_COMMENTLINE) { + if (ch == '\r' || ch == '\n') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_STRING) { + if (ch == '"' || ch == '\r' || ch == '\n') { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + } + } + if (!isspacechar(ch)) + visibleChars++; + chPrev = ch; + } + + // Process to end of document + if (state == SCE_C_IDENTIFIER) { + classifyWordTACL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm); + } + else + ColourTo(styler, lengthDoc - 1, state, bInAsm); +} + +static void FoldTACLDoc(unsigned int startPos, int length, int initStyle, WordList *[], + Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + bool section = false; + + int lastStart = 0; + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (stylePrev == SCE_C_DEFAULT && (style == SCE_C_WORD || style == SCE_C_PREPROCESSOR)) + { + // Store last word start point. + lastStart = i; + } + + if (stylePrev == SCE_C_WORD || stylePrev == SCE_C_PREPROCESSOR) { + if(isTACLwordchar(ch) && !isTACLwordchar(chNext)) { + char s[100]; + getRange(lastStart, i, styler, s, sizeof(s)); + if (stylePrev == SCE_C_PREPROCESSOR && strcmp(s, "?section") == 0) + { + section = true; + levelCurrent = 1; + levelPrev = 0; + } + else if (stylePrev == SCE_C_WORD) + levelCurrent += classifyFoldPointTACL(s); + } + } + + if (style == SCE_C_OPERATOR) { + if (ch == '[') { + levelCurrent++; + } else if (ch == ']') { + levelCurrent--; + } + } + if (foldComment && (style == SCE_C_COMMENTLINE)) { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelCurrent++; + } else if (chNext2 == '}') { + levelCurrent--; + } + } + } + + if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { + if (ch == '{' && chNext == '$') { + unsigned int j=i+2; // skip {$ + while ((j levelPrev || section) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + section = false; + } + + if (!isspacechar(ch)) + visibleChars++; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const TACLWordListDesc[] = { + "Builtins", + "Labels", + "Commands", + 0 +}; + +LexerModule lmTACL(SCLEX_TACL, ColouriseTACLDoc, "TACL", FoldTACLDoc, TACLWordListDesc); diff --git a/lexers/LexTADS3.cxx b/lexers/LexTADS3.cxx new file mode 100644 index 000000000..ee16a0ac0 --- /dev/null +++ b/lexers/LexTADS3.cxx @@ -0,0 +1,904 @@ +// Scintilla source code edit control +/** @file LexTADS3.cxx + ** Lexer for TADS3. + **/ +// Copyright 1998-2006 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +/* + * TADS3 is a language designed by Michael J. Roberts for the writing of text + * based games. TADS comes from Text Adventure Development System. It has good + * support for the processing and outputting of formatted text and much of a + * TADS program listing consists of strings. + * + * TADS has two types of strings, those enclosed in single quotes (') and those + * enclosed in double quotes ("). These strings have different symantics and + * can be given different highlighting if desired. + * + * There can be embedded within both types of strings html tags + * ( ), library directives ( <.directive> ), and message + * parameters ( {The doctor's/his} ). + * + * Double quoted strings can also contain interpolated expressions + * ( << rug.moved ? ' and a hole in the floor. ' : nil >> ). These expressions + * may themselves contain single or double quoted strings, although the double + * quoted strings may not contain interpolated expressions. + * + * These embedded constructs influence the output and formatting and are an + * important part of a program and require highlighting. + * + * LINKS + * http://www.tads.org/ + */ + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static const int T3_SINGLE_QUOTE = 1; +static const int T3_INT_EXPRESSION = 2; +static const int T3_INT_EXPRESSION_IN_TAG = 4; +static const int T3_HTML_SQUOTE = 8; + +static inline bool IsEOL(const int ch, const int chNext) { + return (ch == '\r' && chNext != '\n') || (ch == '\n'); +} + +/* + * Test the current character to see if it's the START of an EOL sequence; + * if so, skip ahead to the last character of the sequence and return true, + * and if not just return false. There are a few places where we want to + * check to see if a newline sequence occurs at a particular point, but + * where a caller expects a subroutine to stop only upon reaching the END + * of a newline sequence (in particular, CR-LF on Windows). That's why + * IsEOL() above only returns true on CR if the CR isn't followed by an LF + * - it doesn't want to admit that there's a newline until reaching the END + * of the sequence. We meet both needs by saying that there's a newline + * when we see the CR in a CR-LF, but skipping the CR before returning so + * that the caller's caller will see that we've stopped at the LF. + */ +static inline bool IsEOLSkip(StyleContext &sc) +{ + /* test for CR-LF */ + if (sc.ch == '\r' && sc.chNext == '\n') + { + /* got CR-LF - skip the CR and indicate that we're at a newline */ + sc.Forward(); + return true; + } + + /* + * in other cases, we have at most a 1-character newline, so do the + * normal IsEOL test + */ + return IsEOL(sc.ch, sc.chNext); +} + +static inline bool IsASpaceOrTab(const int ch) { + return ch == ' ' || ch == '\t'; +} + +static inline bool IsATADS3Operator(const int ch) { + return ch == '=' || ch == '{' || ch == '}' || ch == '(' || ch == ')' + || ch == '[' || ch == ']' || ch == ',' || ch == ':' || ch == ';' + || ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '%' + || ch == '?' || ch == '!' || ch == '<' || ch == '>' || ch == '|' + || ch == '@' || ch == '&' || ch == '~'; +} + +static inline bool IsAWordChar(const int ch) { + return isalnum(ch) || ch == '_'; +} + +static inline bool IsAWordStart(const int ch) { + return isalpha(ch) || ch == '_'; +} + +static inline bool IsAHexDigit(const int ch) { + int lch = tolower(ch); + return isdigit(lch) || lch == 'a' || lch == 'b' || lch == 'c' + || lch == 'd' || lch == 'e' || lch == 'f'; +} + +static inline bool IsAnHTMLChar(int ch) { + return isalnum(ch) || ch == '-' || ch == '_' || ch == '.'; +} + +static inline bool IsADirectiveChar(int ch) { + return isalnum(ch) || isspace(ch) || ch == '-' || ch == '/'; +} + +static inline bool IsANumberStart(StyleContext &sc) { + return isdigit(sc.ch) + || (!isdigit(sc.chPrev) && sc.ch == '.' && isdigit(sc.chNext)); +} + +inline static void ColouriseTADS3Operator(StyleContext &sc) { + int initState = sc.state; + int c = sc.ch; + sc.SetState(c == '{' || c == '}' ? SCE_T3_BRACE : SCE_T3_OPERATOR); + sc.ForwardSetState(initState); +} + +static void ColouriseTADSHTMLString(StyleContext &sc, int &lineState) { + int endState = sc.state; + int chQuote = sc.ch; + int chString = (lineState & T3_SINGLE_QUOTE) ? '\'' : '"'; + if (endState == SCE_T3_HTML_STRING) { + if (lineState&T3_SINGLE_QUOTE) { + endState = SCE_T3_S_STRING; + chString = '\''; + } else if (lineState&T3_INT_EXPRESSION) { + endState = SCE_T3_X_STRING; + chString = '"'; + } else { + endState = SCE_T3_HTML_DEFAULT; + chString = '"'; + } + chQuote = (lineState & T3_HTML_SQUOTE) ? '\'' : '"'; + } else { + sc.SetState(SCE_T3_HTML_STRING); + sc.Forward(); + } + if (chQuote == '"') + lineState &= ~T3_HTML_SQUOTE; + else + lineState |= T3_HTML_SQUOTE; + + while (sc.More()) { + if (IsEOL(sc.ch, sc.chNext)) { + return; + } + if (sc.ch == chQuote) { + sc.ForwardSetState(endState); + return; + } + if (sc.Match('\\', static_cast(chQuote))) { + sc.Forward(2); + sc.SetState(endState); + return; + } + if (sc.ch == chString) { + sc.SetState(SCE_T3_DEFAULT); + return; + } + + if (sc.Match('<', '<')) { + lineState |= T3_INT_EXPRESSION | T3_INT_EXPRESSION_IN_TAG; + sc.SetState(SCE_T3_X_DEFAULT); + sc.Forward(2); + return; + } + + if (sc.Match('\\', static_cast(chQuote)) + || sc.Match('\\', static_cast(chString)) + || sc.Match('\\', '\\')) { + sc.Forward(2); + } else { + sc.Forward(); + } + } +} + +static void ColouriseTADS3HTMLTagStart(StyleContext &sc) { + sc.SetState(SCE_T3_HTML_TAG); + sc.Forward(); + if (sc.ch == '/') { + sc.Forward(); + } + while (IsAnHTMLChar(sc.ch)) { + sc.Forward(); + } +} + +static void ColouriseTADS3HTMLTag(StyleContext &sc, int &lineState) { + int endState = sc.state; + int chQuote = '"'; + int chString = '\''; + switch (endState) { + case SCE_T3_S_STRING: + ColouriseTADS3HTMLTagStart(sc); + sc.SetState(SCE_T3_HTML_DEFAULT); + chQuote = '\''; + chString = '"'; + break; + case SCE_T3_D_STRING: + case SCE_T3_X_STRING: + ColouriseTADS3HTMLTagStart(sc); + sc.SetState(SCE_T3_HTML_DEFAULT); + break; + case SCE_T3_HTML_DEFAULT: + if (lineState&T3_SINGLE_QUOTE) { + endState = SCE_T3_S_STRING; + chQuote = '\''; + chString = '"'; + } else if (lineState&T3_INT_EXPRESSION) { + endState = SCE_T3_X_STRING; + } else { + endState = SCE_T3_D_STRING; + } + break; + } + + while (sc.More()) { + if (IsEOL(sc.ch, sc.chNext)) { + return; + } + if (sc.Match('/', '>')) { + sc.SetState(SCE_T3_HTML_TAG); + sc.Forward(2); + sc.SetState(endState); + return; + } + if (sc.ch == '>') { + sc.SetState(SCE_T3_HTML_TAG); + sc.ForwardSetState(endState); + return; + } + if (sc.ch == chQuote) { + sc.SetState(endState); + return; + } + if (sc.Match('\\', static_cast(chQuote))) { + sc.Forward(); + ColouriseTADSHTMLString(sc, lineState); + if (sc.state == SCE_T3_X_DEFAULT) + break; + } else if (sc.ch == chString) { + ColouriseTADSHTMLString(sc, lineState); + } else if (sc.ch == '=') { + ColouriseTADS3Operator(sc); + } else { + sc.Forward(); + } + } +} + +static void ColouriseTADS3Keyword(StyleContext &sc, + WordList *keywordlists[], unsigned int endPos) { + char s[250]; + WordList &keywords = *keywordlists[0]; + WordList &userwords1 = *keywordlists[1]; + WordList &userwords2 = *keywordlists[2]; + WordList &userwords3 = *keywordlists[3]; + int initState = sc.state; + sc.SetState(SCE_T3_IDENTIFIER); + while (sc.More() && (IsAWordChar(sc.ch))) { + sc.Forward(); + } + sc.GetCurrent(s, sizeof(s)); + if ( strcmp(s, "is") == 0 || strcmp(s, "not") == 0) { + // have to find if "in" is next + int n = 1; + while (n + sc.currentPos < endPos && IsASpaceOrTab(sc.GetRelative(n))) + n++; + if (sc.GetRelative(n) == 'i' && sc.GetRelative(n+1) == 'n') { + sc.Forward(n+2); + sc.ChangeState(SCE_T3_KEYWORD); + } + } else if (keywords.InList(s)) { + sc.ChangeState(SCE_T3_KEYWORD); + } else if (userwords3.InList(s)) { + sc.ChangeState(SCE_T3_USER3); + } else if (userwords2.InList(s)) { + sc.ChangeState(SCE_T3_USER2); + } else if (userwords1.InList(s)) { + sc.ChangeState(SCE_T3_USER1); + } + sc.SetState(initState); +} + +static void ColouriseTADS3MsgParam(StyleContext &sc, int &lineState) { + int endState = sc.state; + int chQuote = '"'; + switch (endState) { + case SCE_T3_S_STRING: + sc.SetState(SCE_T3_MSG_PARAM); + sc.Forward(); + chQuote = '\''; + break; + case SCE_T3_D_STRING: + case SCE_T3_X_STRING: + sc.SetState(SCE_T3_MSG_PARAM); + sc.Forward(); + break; + case SCE_T3_MSG_PARAM: + if (lineState&T3_SINGLE_QUOTE) { + endState = SCE_T3_S_STRING; + chQuote = '\''; + } else if (lineState&T3_INT_EXPRESSION) { + endState = SCE_T3_X_STRING; + } else { + endState = SCE_T3_D_STRING; + } + break; + } + while (sc.More() && sc.ch != '}' && sc.ch != chQuote) { + if (IsEOL(sc.ch, sc.chNext)) { + return; + } + if (sc.ch == '\\') { + sc.Forward(); + } + sc.Forward(); + } + if (sc.ch == chQuote) { + sc.SetState(endState); + } else { + sc.ForwardSetState(endState); + } +} + +static void ColouriseTADS3LibDirective(StyleContext &sc, int &lineState) { + int initState = sc.state; + int chQuote = '"'; + switch (initState) { + case SCE_T3_S_STRING: + sc.SetState(SCE_T3_LIB_DIRECTIVE); + sc.Forward(2); + chQuote = '\''; + break; + case SCE_T3_D_STRING: + sc.SetState(SCE_T3_LIB_DIRECTIVE); + sc.Forward(2); + break; + case SCE_T3_LIB_DIRECTIVE: + if (lineState&T3_SINGLE_QUOTE) { + initState = SCE_T3_S_STRING; + chQuote = '\''; + } else { + initState = SCE_T3_D_STRING; + } + break; + } + while (sc.More() && IsADirectiveChar(sc.ch)) { + if (IsEOL(sc.ch, sc.chNext)) { + return; + } + sc.Forward(); + }; + if (sc.ch == '>' || !sc.More()) { + sc.ForwardSetState(initState); + } else if (sc.ch == chQuote) { + sc.SetState(initState); + } else { + sc.ChangeState(initState); + sc.Forward(); + } +} + +static void ColouriseTADS3String(StyleContext &sc, int &lineState) { + int chQuote = sc.ch; + int endState = sc.state; + switch (sc.state) { + case SCE_T3_DEFAULT: + case SCE_T3_X_DEFAULT: + if (chQuote == '"') { + if (sc.state == SCE_T3_DEFAULT) { + sc.SetState(SCE_T3_D_STRING); + } else { + sc.SetState(SCE_T3_X_STRING); + } + lineState &= ~T3_SINGLE_QUOTE; + } else { + sc.SetState(SCE_T3_S_STRING); + lineState |= T3_SINGLE_QUOTE; + } + sc.Forward(); + break; + case SCE_T3_S_STRING: + chQuote = '\''; + endState = lineState&T3_INT_EXPRESSION ? + SCE_T3_X_DEFAULT : SCE_T3_DEFAULT; + break; + case SCE_T3_D_STRING: + chQuote = '"'; + endState = SCE_T3_DEFAULT; + break; + case SCE_T3_X_STRING: + chQuote = '"'; + endState = SCE_T3_X_DEFAULT; + break; + } + while (sc.More()) { + if (IsEOL(sc.ch, sc.chNext)) { + return; + } + if (sc.ch == chQuote) { + sc.ForwardSetState(endState); + return; + } + if (sc.state == SCE_T3_D_STRING && sc.Match('<', '<')) { + lineState |= T3_INT_EXPRESSION; + sc.SetState(SCE_T3_X_DEFAULT); + sc.Forward(2); + return; + } + if (sc.Match('\\', static_cast(chQuote)) + || sc.Match('\\', '\\')) { + sc.Forward(2); + } else if (sc.ch == '{') { + ColouriseTADS3MsgParam(sc, lineState); + } else if (sc.Match('<', '.')) { + ColouriseTADS3LibDirective(sc, lineState); + } else if (sc.ch == '<') { + ColouriseTADS3HTMLTag(sc, lineState); + if (sc.state == SCE_T3_X_DEFAULT) + return; + } else { + sc.Forward(); + } + } +} + +static void ColouriseTADS3Comment(StyleContext &sc, int endState) { + sc.SetState(SCE_T3_BLOCK_COMMENT); + while (sc.More()) { + if (IsEOL(sc.ch, sc.chNext)) { + return; + } + if (sc.Match('*', '/')) { + sc.Forward(2); + sc.SetState(endState); + return; + } + sc.Forward(); + } +} + +static void ColouriseToEndOfLine(StyleContext &sc, int initState, int endState) { + sc.SetState(initState); + while (sc.More()) { + if (sc.ch == '\\') { + sc.Forward(); + if (IsEOLSkip(sc)) { + return; + } + } + if (IsEOL(sc.ch, sc.chNext)) { + sc.SetState(endState); + return; + } + sc.Forward(); + } +} + +static void ColouriseTADS3Number(StyleContext &sc) { + int endState = sc.state; + bool inHexNumber = false; + bool seenE = false; + bool seenDot = sc.ch == '.'; + sc.SetState(SCE_T3_NUMBER); + if (sc.More()) { + sc.Forward(); + } + if (sc.chPrev == '0' && tolower(sc.ch) == 'x') { + inHexNumber = true; + sc.Forward(); + } + while (sc.More()) { + if (inHexNumber) { + if (!IsAHexDigit(sc.ch)) { + break; + } + } else if (!isdigit(sc.ch)) { + if (!seenE && tolower(sc.ch) == 'e') { + seenE = true; + seenDot = true; + if (sc.chNext == '+' || sc.chNext == '-') { + sc.Forward(); + } + } else if (!seenDot && sc.ch == '.') { + seenDot = true; + } else { + break; + } + } + sc.Forward(); + } + sc.SetState(endState); +} + +static void ColouriseTADS3Doc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + int visibleChars = 0; + int bracketLevel = 0; + int lineState = 0; + unsigned int endPos = startPos + length; + int lineCurrent = styler.GetLine(startPos); + if (lineCurrent > 0) { + lineState = styler.GetLineState(lineCurrent-1); + } + StyleContext sc(startPos, length, initStyle, styler); + + while (sc.More()) { + + if (IsEOL(sc.ch, sc.chNext)) { + styler.SetLineState(lineCurrent, lineState); + lineCurrent++; + visibleChars = 0; + sc.Forward(); + if (sc.ch == '\n') { + sc.Forward(); + } + } + + switch(sc.state) { + case SCE_T3_PREPROCESSOR: + case SCE_T3_LINE_COMMENT: + ColouriseToEndOfLine(sc, sc.state, lineState&T3_INT_EXPRESSION ? + SCE_T3_X_DEFAULT : SCE_T3_DEFAULT); + break; + case SCE_T3_S_STRING: + case SCE_T3_D_STRING: + case SCE_T3_X_STRING: + ColouriseTADS3String(sc, lineState); + visibleChars++; + break; + case SCE_T3_MSG_PARAM: + ColouriseTADS3MsgParam(sc, lineState); + break; + case SCE_T3_LIB_DIRECTIVE: + ColouriseTADS3LibDirective(sc, lineState); + break; + case SCE_T3_HTML_DEFAULT: + ColouriseTADS3HTMLTag(sc, lineState); + break; + case SCE_T3_HTML_STRING: + ColouriseTADSHTMLString(sc, lineState); + break; + case SCE_T3_BLOCK_COMMENT: + ColouriseTADS3Comment(sc, lineState&T3_INT_EXPRESSION ? + SCE_T3_X_DEFAULT : SCE_T3_DEFAULT); + break; + case SCE_T3_DEFAULT: + case SCE_T3_X_DEFAULT: + if (IsASpaceOrTab(sc.ch)) { + sc.Forward(); + } else if (sc.ch == '#' && visibleChars == 0) { + ColouriseToEndOfLine(sc, SCE_T3_PREPROCESSOR, sc.state); + } else if (sc.Match('/', '*')) { + ColouriseTADS3Comment(sc, sc.state); + visibleChars++; + } else if (sc.Match('/', '/')) { + ColouriseToEndOfLine(sc, SCE_T3_LINE_COMMENT, sc.state); + } else if (sc.ch == '"') { + bracketLevel = 0; + ColouriseTADS3String(sc, lineState); + visibleChars++; + } else if (sc.ch == '\'') { + ColouriseTADS3String(sc, lineState); + visibleChars++; + } else if (sc.state == SCE_T3_X_DEFAULT && bracketLevel == 0 + && sc.Match('>', '>')) { + sc.Forward(2); + sc.SetState(SCE_T3_D_STRING); + if (lineState & T3_INT_EXPRESSION_IN_TAG) + sc.SetState(SCE_T3_HTML_STRING); + lineState &= ~(T3_SINGLE_QUOTE|T3_INT_EXPRESSION + |T3_INT_EXPRESSION_IN_TAG); + } else if (IsATADS3Operator(sc.ch)) { + if (sc.state == SCE_T3_X_DEFAULT) { + if (sc.ch == '(') { + bracketLevel++; + } else if (sc.ch == ')' && bracketLevel > 0) { + bracketLevel--; + } + } + ColouriseTADS3Operator(sc); + visibleChars++; + } else if (IsANumberStart(sc)) { + ColouriseTADS3Number(sc); + visibleChars++; + } else if (IsAWordStart(sc.ch)) { + ColouriseTADS3Keyword(sc, keywordlists, endPos); + visibleChars++; + } else if (sc.Match("...")) { + sc.SetState(SCE_T3_IDENTIFIER); + sc.Forward(3); + sc.SetState(SCE_T3_DEFAULT); + } else { + sc.Forward(); + visibleChars++; + } + break; + default: + sc.SetState(SCE_T3_DEFAULT); + sc.Forward(); + } + } + sc.Complete(); +} + +/* + TADS3 has two styles of top level block (TLB). Eg + + // default style + silverKey : Key 'small silver key' 'small silver key' + "A small key glints in the sunlight. " + ; + + and + + silverKey : Key { + 'small silver key' + 'small silver key' + "A small key glints in the sunlight. " + } + + Some constructs mandate one or the other, but usually the author has may choose + either. + + T3_SEENSTART is used to indicate that a braceless TLB has been (potentially) + seen and is also used to match the closing ';' of the default style. + + T3_EXPECTINGIDENTIFIER and T3_EXPECTINGPUNCTUATION are used to keep track of + what characters may be seen without incrementing the block level. The general + pattern is identifier identifier, acceptable punctuation characters + are ':', ',', '(' and ')'. No attempt is made to ensure that punctuation + characters are syntactically correct, eg parentheses match. A ')' always + signifies the start of a block. We just need to check if it is followed by a + '{', in which case we let the brace handling code handle the folding level. + + expectingIdentifier == false && expectingIdentifier == false + Before the start of a TLB. + + expectingIdentifier == true && expectingIdentifier == true + Currently in an identifier. Will accept identifier or punctuation. + + expectingIdentifier == true && expectingIdentifier == false + Just seen a punctuation character & now waiting for an identifier to start. + + expectingIdentifier == false && expectingIdentifier == truee + We were in an identifier and have seen space. Now waiting to see a punctuation + character + + Space, comments & preprocessor directives are always acceptable and are + equivalent. +*/ + +static const int T3_SEENSTART = 1 << 12; +static const int T3_EXPECTINGIDENTIFIER = 1 << 13; +static const int T3_EXPECTINGPUNCTUATION = 1 << 14; + +static inline bool IsStringTransition(int s1, int s2) { + return s1 != s2 + && (s1 == SCE_T3_S_STRING || s1 == SCE_T3_X_STRING + || (s1 == SCE_T3_D_STRING && s2 != SCE_T3_X_DEFAULT)) + && s2 != SCE_T3_LIB_DIRECTIVE + && s2 != SCE_T3_MSG_PARAM + && s2 != SCE_T3_HTML_TAG + && s2 != SCE_T3_HTML_STRING; +} + +static inline bool IsATADS3Punctuation(const int ch) { + return ch == ':' || ch == ',' || ch == '(' || ch == ')'; +} + +static inline bool IsAnIdentifier(const int style) { + return style == SCE_T3_IDENTIFIER + || style == SCE_T3_USER1 + || style == SCE_T3_USER2 + || style == SCE_T3_USER3; +} + +static inline bool IsAnOperator(const int style) { + return style == SCE_T3_OPERATOR || SCE_T3_BRACE; +} + +static inline bool IsSpaceEquivalent(const int ch, const int style) { + return isspace(ch) + || style == SCE_T3_BLOCK_COMMENT + || style == SCE_T3_LINE_COMMENT + || style == SCE_T3_PREPROCESSOR; +} + +static char peekAhead(unsigned int startPos, unsigned int endPos, + Accessor &styler) { + for (unsigned int i = startPos; i < endPos; i++) { + int style = styler.StyleAt(i); + char ch = styler[i]; + if (!IsSpaceEquivalent(ch, style)) { + if (IsAnIdentifier(style)) { + return 'a'; + } + if (IsATADS3Punctuation(ch)) { + return ':'; + } + if (ch == '{') { + return '{'; + } + return '*'; + } + } + return ' '; +} + +static void FoldTADS3Doc(unsigned int startPos, int length, int initStyle, + WordList *[], Accessor &styler) { + unsigned int endPos = startPos + length; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int seenStart = levelCurrent & T3_SEENSTART; + int expectingIdentifier = levelCurrent & T3_EXPECTINGIDENTIFIER; + int expectingPunctuation = levelCurrent & T3_EXPECTINGPUNCTUATION; + levelCurrent &= SC_FOLDLEVELNUMBERMASK; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + char ch = chNext; + int stylePrev = style; + bool redo = false; + for (unsigned int i = startPos; i < endPos; i++) { + if (redo) { + redo = false; + i--; + } else { + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + } + bool atEOL = IsEOL(ch, chNext); + + if (levelNext == SC_FOLDLEVELBASE) { + if (IsSpaceEquivalent(ch, style)) { + if (expectingPunctuation) { + expectingIdentifier = 0; + } + if (style == SCE_T3_BLOCK_COMMENT) { + levelNext++; + } + } else if (ch == '{') { + levelNext++; + seenStart = 0; + } else if (ch == '\'' || ch == '"' || ch == '[') { + levelNext++; + if (seenStart) { + redo = true; + } + } else if (ch == ';') { + seenStart = 0; + expectingIdentifier = 0; + expectingPunctuation = 0; + } else if (expectingIdentifier && expectingPunctuation) { + if (IsATADS3Punctuation(ch)) { + if (ch == ')' && peekAhead(i+1, endPos, styler) != '{') { + levelNext++; + } else { + expectingPunctuation = 0; + } + } else if (!IsAnIdentifier(style)) { + levelNext++; + } + } else if (expectingIdentifier && !expectingPunctuation) { + if (!IsAnIdentifier(style)) { + levelNext++; + } else { + expectingPunctuation = T3_EXPECTINGPUNCTUATION; + } + } else if (!expectingIdentifier && expectingPunctuation) { + if (!IsATADS3Punctuation(ch)) { + levelNext++; + } else { + if (ch == ')' && peekAhead(i+1, endPos, styler) != '{') { + levelNext++; + } else { + expectingIdentifier = T3_EXPECTINGIDENTIFIER; + expectingPunctuation = 0; + } + } + } else if (!expectingIdentifier && !expectingPunctuation) { + if (IsAnIdentifier(style)) { + seenStart = T3_SEENSTART; + expectingIdentifier = T3_EXPECTINGIDENTIFIER; + expectingPunctuation = T3_EXPECTINGPUNCTUATION; + } + } + + if (levelNext != SC_FOLDLEVELBASE && style != SCE_T3_BLOCK_COMMENT) { + expectingIdentifier = 0; + expectingPunctuation = 0; + } + + } else if (levelNext == SC_FOLDLEVELBASE+1 && seenStart + && ch == ';' && IsAnOperator(style)) { + levelNext--; + seenStart = 0; + } else if (style == SCE_T3_BLOCK_COMMENT) { + if (stylePrev != SCE_T3_BLOCK_COMMENT) { + levelNext++; + } else if (styleNext != SCE_T3_BLOCK_COMMENT && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } else if (ch == '\'' || ch == '"') { + if (IsStringTransition(style, stylePrev)) { + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (IsStringTransition(style, styleNext)) { + levelNext--; + } + } else if (IsAnOperator(style)) { + if (ch == '{' || ch == '[') { + // Measure the minimum before a '{' to allow + // folding on "} else {" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}' || ch == ']') { + levelNext--; + } + } + + if (atEOL) { + if (seenStart && levelNext == SC_FOLDLEVELBASE) { + switch (peekAhead(i+1, endPos, styler)) { + case ' ': + case '{': + break; + case '*': + levelNext++; + break; + case 'a': + if (expectingPunctuation) { + levelNext++; + } + break; + case ':': + if (expectingIdentifier) { + levelNext++; + } + break; + } + if (levelNext != SC_FOLDLEVELBASE) { + expectingIdentifier = 0; + expectingPunctuation = 0; + } + } + int lev = levelMinCurrent | (levelNext | expectingIdentifier + | expectingPunctuation | seenStart) << 16; + if (levelMinCurrent < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + } + } +} + +static const char * const tads3WordList[] = { + "TADS3 Keywords", + "User defined 1", + "User defined 2", + "User defined 3", + 0 +}; + +LexerModule lmTADS3(SCLEX_TADS3, ColouriseTADS3Doc, "tads3", FoldTADS3Doc, tads3WordList); diff --git a/lexers/LexTAL.cxx b/lexers/LexTAL.cxx new file mode 100644 index 000000000..a76a296d6 --- /dev/null +++ b/lexers/LexTAL.cxx @@ -0,0 +1,396 @@ +// Scintilla source code edit control +/** @file LexTAL.cxx + ** Lexer for TAL + ** Based on LexPascal.cxx + ** Written by Laurent le Tynevez + ** Updated by Simon Steele September 2002 + ** Updated by Mathias Rauen May 2003 (Delphi adjustments) + ** Updated by Rod Falck, Aug 2006 Converted to TAL + **/ + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "StyleContext.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +inline bool isTALoperator(char ch) + { + return ch == '\'' || ch == '@' || ch == '#' || isoperator(ch); + } + +inline bool isTALwordchar(char ch) + { + return ch == '$' || ch == '^' || iswordchar(ch); + } + +inline bool isTALwordstart(char ch) + { + return ch == '$' || ch == '^' || iswordstart(ch); + } + +static void getRange(unsigned int start, + unsigned int end, + Accessor &styler, + char *s, + unsigned int len) { + unsigned int i = 0; + while ((i < end - start + 1) && (i < len-1)) { + s[i] = static_cast(tolower(styler[start + i])); + i++; + } + s[i] = '\0'; +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_C_COMMENT || + style == SCE_C_COMMENTDOC || + style == SCE_C_COMMENTDOCKEYWORD || + style == SCE_C_COMMENTDOCKEYWORDERROR; +} + +static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr, bool bInAsm) { + if ((bInAsm) && (attr == SCE_C_OPERATOR || attr == SCE_C_NUMBER || attr == SCE_C_DEFAULT || attr == SCE_C_WORD || attr == SCE_C_IDENTIFIER)) { + styler.ColourTo(end, SCE_C_REGEX); + } else + styler.ColourTo(end, attr); +} + +// returns 1 if the item starts a class definition, and -1 if the word is "end", and 2 if the word is "asm" +static int classifyWordTAL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, bool bInAsm) { + int ret = 0; + + WordList& keywords = *keywordlists[0]; + WordList& builtins = *keywordlists[1]; + WordList& nonreserved_keywords = *keywordlists[2]; + + char s[100]; + getRange(start, end, styler, s, sizeof(s)); + + char chAttr = SCE_C_IDENTIFIER; + if (isdigit(s[0]) || (s[0] == '.')) { + chAttr = SCE_C_NUMBER; + } + else { + if (keywords.InList(s)) { + chAttr = SCE_C_WORD; + + if (strcmp(s, "asm") == 0) { + ret = 2; + } + else if (strcmp(s, "end") == 0) { + ret = -1; + } + } + else if (s[0] == '$' || builtins.InList(s)) { + chAttr = SCE_C_WORD2; + } + else if (nonreserved_keywords.InList(s)) { + chAttr = SCE_C_UUID; + } + } + ColourTo(styler, end, chAttr, (bInAsm && ret != -1)); + return ret; +} + +static int classifyFoldPointTAL(const char* s) { + int lev = 0; + if (!(isdigit(s[0]) || (s[0] == '.'))) { + if (strcmp(s, "begin") == 0 || + strcmp(s, "block") == 0) { + lev=1; + } else if (strcmp(s, "end") == 0) { + lev=-1; + } + } + return lev; +} + +static void ColouriseTALDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + styler.StartAt(startPos); + + int state = initStyle; + if (state == SCE_C_CHARACTER) // Does not leak onto next line + state = SCE_C_DEFAULT; + char chPrev = ' '; + char chNext = styler[startPos]; + unsigned int lengthDoc = startPos + length; + + bool bInClassDefinition; + + int currentLine = styler.GetLine(startPos); + if (currentLine > 0) { + styler.SetLineState(currentLine, styler.GetLineState(currentLine-1)); + bInClassDefinition = (styler.GetLineState(currentLine) == 1); + } else { + styler.SetLineState(currentLine, 0); + bInClassDefinition = false; + } + + bool bInAsm = (state == SCE_C_REGEX); + if (bInAsm) + state = SCE_C_DEFAULT; + + styler.StartSegment(startPos); + int visibleChars = 0; + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // End of line + if (state == SCE_C_CHARACTER) { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + visibleChars = 0; + currentLine++; + styler.SetLineState(currentLine, (bInClassDefinition ? 1 : 0)); + } + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + chPrev = ' '; + i += 1; + continue; + } + + if (state == SCE_C_DEFAULT) { + if (isTALwordstart(ch)) { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_IDENTIFIER; + } else if (ch == '!' && chNext != '*') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENT; + } else if (ch == '!' && chNext == '*') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENTDOC; + } else if (ch == '-' && chNext == '-') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENTLINE; + } else if (ch == '"') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_STRING; + } else if (ch == '?' && visibleChars == 0) { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_PREPROCESSOR; + } else if (isTALoperator(ch)) { + ColourTo(styler, i-1, state, bInAsm); + ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); + } + } else if (state == SCE_C_IDENTIFIER) { + if (!isTALwordchar(ch)) { + int lStateChange = classifyWordTAL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm); + + if(lStateChange == 1) { + styler.SetLineState(currentLine, 1); + bInClassDefinition = true; + } else if(lStateChange == 2) { + bInAsm = true; + } else if(lStateChange == -1) { + styler.SetLineState(currentLine, 0); + bInClassDefinition = false; + bInAsm = false; + } + + state = SCE_C_DEFAULT; + chNext = styler.SafeGetCharAt(i + 1); + if (ch == '!' && chNext != '*') { + state = SCE_C_COMMENT; + } else if (ch == '!' && chNext == '*') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_COMMENTDOC; + } else if (ch == '-' && chNext == '-') { + state = SCE_C_COMMENTLINE; + } else if (ch == '"') { + state = SCE_C_STRING; + } else if (isTALoperator(ch)) { + ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); + } + } + } else { + if (state == SCE_C_PREPROCESSOR) { + if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENT) { + if (ch == '!' || (ch == '\r' || ch == '\n') ) { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_COMMENTDOC) { + if (ch == '!' || (ch == '\r' || ch == '\n')) { + if (((i > styler.GetStartSegment() + 2) || ( + (initStyle == SCE_C_COMMENTDOC) && + (styler.GetStartSegment() == static_cast(startPos))))) { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + } + } else if (state == SCE_C_COMMENTLINE) { + if (ch == '\r' || ch == '\n') { + ColourTo(styler, i-1, state, bInAsm); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_STRING) { + if (ch == '"') { + ColourTo(styler, i, state, bInAsm); + state = SCE_C_DEFAULT; + } + } + } + if (!isspacechar(ch)) + visibleChars++; + chPrev = ch; + } + ColourTo(styler, lengthDoc - 1, state, bInAsm); +} + +static void FoldTALDoc(unsigned int startPos, int length, int initStyle, WordList *[], + Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + bool was_end = false; + bool section = false; + + int lastStart = 0; + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (stylePrev == SCE_C_DEFAULT && (style == SCE_C_WORD || style == SCE_C_UUID || style == SCE_C_PREPROCESSOR)) + { + // Store last word start point. + lastStart = i; + } + + if (stylePrev == SCE_C_WORD || style == SCE_C_UUID || stylePrev == SCE_C_PREPROCESSOR) { + if(isTALwordchar(ch) && !isTALwordchar(chNext)) { + char s[100]; + getRange(lastStart, i, styler, s, sizeof(s)); + if (stylePrev == SCE_C_PREPROCESSOR && strcmp(s, "?section") == 0) + { + section = true; + levelCurrent = 1; + levelPrev = 0; + } + else if (stylePrev == SCE_C_WORD || stylePrev == SCE_C_UUID) + { + if (strcmp(s, "block") == 0) + { + // block keyword is ignored immediately after end keyword + if (!was_end) + levelCurrent++; + } + else + levelCurrent += classifyFoldPointTAL(s); + if (strcmp(s, "end") == 0) + { + was_end = true; + } + else + { + was_end = false; + } + } + } + } + + if (foldComment && (style == SCE_C_COMMENTLINE)) { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelCurrent++; + } else if (chNext2 == '}') { + levelCurrent--; + } + } + } + + if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { + if (ch == '{' && chNext == '$') { + unsigned int j=i+2; // skip {$ + while ((j levelPrev || section) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + section = false; + } + + if (!isspacechar(ch)) + visibleChars++; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const TALWordListDesc[] = { + "Keywords", + "Builtins", + 0 +}; + +LexerModule lmTAL(SCLEX_TAL, ColouriseTALDoc, "TAL", FoldTALDoc, TALWordListDesc); diff --git a/lexers/LexTCL.cxx b/lexers/LexTCL.cxx new file mode 100644 index 000000000..3c175de2a --- /dev/null +++ b/lexers/LexTCL.cxx @@ -0,0 +1,366 @@ +// Scintilla source code edit control +/** @file LexTCL.cxx + ** Lexer for TCL language. + **/ +// Copyright 1998-2001 by Andre Arpin +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// Extended to accept accented characters +static inline bool IsAWordChar(int ch) { + return ch >= 0x80 || + (isalnum(ch) || ch == '_' || ch ==':' || ch=='.'); // : name space separator +} + +static inline bool IsAWordStart(int ch) { + return ch >= 0x80 || (ch ==':' || isalpha(ch) || ch == '_'); +} + +static inline bool IsANumberChar(int ch) { + // Not exactly following number definition (several dots are seen as OK, etc.) + // but probably enough in most cases. + return (ch < 0x80) && + (IsADigit(ch, 0x10) || toupper(ch) == 'E' || + ch == '.' || ch == '-' || ch == '+'); +} + +static void ColouriseTCLDoc(unsigned int startPos, int length, int , WordList *keywordlists[], Accessor &styler) { +#define isComment(s) (s==SCE_TCL_COMMENT || s==SCE_TCL_COMMENTLINE || s==SCE_TCL_COMMENT_BOX || s==SCE_TCL_BLOCK_COMMENT) + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool commentLevel = false; + bool subBrace = false; // substitution begin with a brace ${.....} + enum tLineState {LS_DEFAULT, LS_OPEN_COMMENT, LS_OPEN_DOUBLE_QUOTE, LS_COMMENT_BOX, LS_MASK_STATE = 0xf, + LS_COMMAND_EXPECTED = 16, LS_BRACE_ONLY = 32 } lineState = LS_DEFAULT; + bool prevSlash = false; + int currentLevel = 0; + bool expected = 0; + bool subParen = 0; + + int currentLine = styler.GetLine(startPos); + if (currentLine > 0) + currentLine--; + length += startPos - styler.LineStart(currentLine); + // make sure lines overlap + startPos = styler.LineStart(currentLine); + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; + WordList &keywords7 = *keywordlists[6]; + WordList &keywords8 = *keywordlists[7]; + WordList &keywords9 = *keywordlists[8]; + + if (currentLine > 0) { + int ls = styler.GetLineState(currentLine - 1); + lineState = tLineState(ls & LS_MASK_STATE); + expected = LS_COMMAND_EXPECTED == tLineState(ls & LS_COMMAND_EXPECTED); + subBrace = LS_BRACE_ONLY == tLineState(ls & LS_BRACE_ONLY); + currentLevel = styler.LevelAt(currentLine - 1) >> 17; + commentLevel = (styler.LevelAt(currentLine - 1) >> 16) & 1; + } else + styler.SetLevel(0, SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG); + bool visibleChars = false; + + int previousLevel = currentLevel; + StyleContext sc(startPos, length, SCE_TCL_DEFAULT, styler); + for (; ; sc.Forward()) { +next: + if (sc.ch=='\r' && sc.chNext == '\n') // only ignore \r on PC process on the mac + continue; + bool atEnd = !sc.More(); // make sure we coloured the last word + if (lineState != LS_DEFAULT) { + sc.SetState(SCE_TCL_DEFAULT); + if (lineState == LS_OPEN_COMMENT) + sc.SetState(SCE_TCL_COMMENTLINE); + else if (lineState == LS_OPEN_DOUBLE_QUOTE) + sc.SetState(SCE_TCL_IN_QUOTE); + else if (lineState == LS_COMMENT_BOX && (sc.ch == '#' || (sc.ch == ' ' && sc.chNext=='#'))) + sc.SetState(SCE_TCL_COMMENT_BOX); + lineState = LS_DEFAULT; + } + if (subBrace) { // ${ overrides every thing even \ except } + if (sc.ch == '}') { + subBrace = false; + sc.SetState(SCE_TCL_OPERATOR); + sc.ForwardSetState(SCE_TCL_DEFAULT); + goto next; + } + else + sc.SetState(SCE_TCL_SUB_BRACE); + if (!sc.atLineEnd) + continue; + } else if (sc.state == SCE_TCL_DEFAULT || sc.state ==SCE_TCL_OPERATOR) { + expected &= isspacechar(static_cast(sc.ch)) || IsAWordStart(sc.ch) || sc.ch =='#'; + } else if (sc.state == SCE_TCL_SUBSTITUTION) { + switch(sc.ch) { + case '(': + subParen=true; + sc.SetState(SCE_TCL_OPERATOR); + sc.ForwardSetState(SCE_TCL_SUBSTITUTION); + continue; + case ')': + sc.SetState(SCE_TCL_OPERATOR); + subParen=false; + continue; + case '$': + continue; + case ',': + sc.SetState(SCE_TCL_OPERATOR); + if (subParen) + sc.ForwardSetState(SCE_TCL_SUBSTITUTION); + continue; + default : + // maybe spaces should be allowed ??? + if (!IsAWordChar(sc.ch)) { // probably the code is wrong + sc.SetState(SCE_TCL_DEFAULT); + subParen = 0; + } + break; + } + } else if (isComment(sc.state)) { + } else if (!IsAWordChar(sc.ch)) { + if ((sc.state == SCE_TCL_IDENTIFIER && expected) || sc.state == SCE_TCL_MODIFIER) { + char w[100]; + char *s=w; + sc.GetCurrent(w, sizeof(w)); + if (w[strlen(w)-1]=='\r') + w[strlen(w)-1]=0; + while(*s == ':') // ignore leading : like in ::set a 10 + ++s; + bool quote = sc.state == SCE_TCL_IN_QUOTE; + if (commentLevel || expected) { + if (keywords.InList(s)) { + sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD4); + } else if (sc.GetRelative(-static_cast(strlen(s))-1) == '{' && + keywords5.InList(s) && sc.ch == '}') { // {keyword} exactly no spaces + sc.ChangeState(SCE_TCL_EXPAND); + } + if (keywords6.InList(s)) { + sc.ChangeState(SCE_TCL_WORD5); + } else if (keywords7.InList(s)) { + sc.ChangeState(SCE_TCL_WORD6); + } else if (keywords8.InList(s)) { + sc.ChangeState(SCE_TCL_WORD7); + } else if (keywords9.InList(s)) { + sc.ChangeState(SCE_TCL_WORD8); + } + } + expected = false; + sc.SetState(quote ? SCE_TCL_IN_QUOTE : SCE_TCL_DEFAULT); + } else if (sc.state == SCE_TCL_MODIFIER || sc.state == SCE_TCL_IDENTIFIER) { + sc.SetState(SCE_TCL_DEFAULT); + } + } + if (atEnd) + break; + if (sc.atLineEnd) { + lineState = LS_DEFAULT; + currentLine = styler.GetLine(sc.currentPos); + if (foldComment && sc.state!=SCE_TCL_COMMENT && isComment(sc.state)) { + if (currentLevel == 0) { + ++currentLevel; + commentLevel = true; + } + } else { + if (visibleChars && commentLevel) { + --currentLevel; + --previousLevel; + commentLevel = false; + } + } + int flag = 0; + if (!visibleChars) + flag = SC_FOLDLEVELWHITEFLAG; + if (currentLevel > previousLevel) + flag = SC_FOLDLEVELHEADERFLAG; + styler.SetLevel(currentLine, flag + previousLevel + SC_FOLDLEVELBASE + (currentLevel << 17) + (commentLevel << 16)); + + // Update the line state, so it can be seen by next line + if (sc.state == SCE_TCL_IN_QUOTE) + lineState = LS_OPEN_DOUBLE_QUOTE; + else { + if (prevSlash) { + if (isComment(sc.state)) + lineState = LS_OPEN_COMMENT; + } else if (sc.state == SCE_TCL_COMMENT_BOX) + lineState = LS_COMMENT_BOX; + } + styler.SetLineState(currentLine, + (subBrace ? LS_BRACE_ONLY : 0) | + (expected ? LS_COMMAND_EXPECTED : 0) | lineState); + if (lineState == LS_COMMENT_BOX) + sc.ForwardSetState(SCE_TCL_COMMENT_BOX); + else if (lineState == LS_OPEN_DOUBLE_QUOTE) + sc.ForwardSetState(SCE_TCL_IN_QUOTE); + else + sc.ForwardSetState(SCE_TCL_DEFAULT); + prevSlash = false; + previousLevel = currentLevel; + goto next; + } + + if (prevSlash) { + prevSlash = false; + if (sc.ch == '#' && IsANumberChar(sc.chNext)) + sc.ForwardSetState(SCE_TCL_NUMBER); + continue; + } + prevSlash = sc.ch == '\\'; + if (isComment(sc.state)) + continue; + if (sc.atLineStart) { + visibleChars = false; + if (sc.state!=SCE_TCL_IN_QUOTE && !isComment(sc.state)) + { + sc.SetState(SCE_TCL_DEFAULT); + expected = IsAWordStart(sc.ch)|| isspacechar(static_cast(sc.ch)); + } + } + + switch (sc.state) { + case SCE_TCL_NUMBER: + if (!IsANumberChar(sc.ch)) + sc.SetState(SCE_TCL_DEFAULT); + break; + case SCE_TCL_IN_QUOTE: + if (sc.ch == '"') { + sc.ForwardSetState(SCE_TCL_DEFAULT); + visibleChars = true; // necessary if a " is the first and only character on a line + goto next; + } else if (sc.ch == '[' || sc.ch == ']' || sc.ch == '$') { + sc.SetState(SCE_TCL_OPERATOR); + expected = sc.ch == '['; + sc.ForwardSetState(SCE_TCL_IN_QUOTE); + goto next; + } + continue; + case SCE_TCL_OPERATOR: + sc.SetState(SCE_TCL_DEFAULT); + break; + } + + if (sc.ch == '#') { + if (visibleChars) { + if (sc.state != SCE_TCL_IN_QUOTE && expected) + sc.SetState(SCE_TCL_COMMENT); + } else { + sc.SetState(SCE_TCL_COMMENTLINE); + if (sc.chNext == '~') + sc.SetState(SCE_TCL_BLOCK_COMMENT); + if (sc.atLineStart && (sc.chNext == '#' || sc.chNext == '-')) + sc.SetState(SCE_TCL_COMMENT_BOX); + } + } + + if (!isspacechar(static_cast(sc.ch))) { + visibleChars = true; + } + + if (sc.ch == '\\') { + prevSlash = true; + continue; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_TCL_DEFAULT) { + if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_TCL_IDENTIFIER); + } else if (IsADigit(sc.ch) && !IsAWordChar(sc.chPrev)) { + sc.SetState(SCE_TCL_NUMBER); + } else { + switch (sc.ch) { + case '\"': + sc.SetState(SCE_TCL_IN_QUOTE); + break; + case '{': + sc.SetState(SCE_TCL_OPERATOR); + expected = true; + ++currentLevel; + break; + case '}': + sc.SetState(SCE_TCL_OPERATOR); + --currentLevel; + break; + case '[': + expected = true; + case ']': + case '(': + case ')': + sc.SetState(SCE_TCL_OPERATOR); + break; + case ';': + expected = true; + break; + case '$': + subParen = 0; + if (sc.chNext != '{') { + sc.SetState(SCE_TCL_SUBSTITUTION); + } + else { + sc.SetState(SCE_TCL_OPERATOR); // $ + sc.Forward(); // { + sc.ForwardSetState(SCE_TCL_SUB_BRACE); + subBrace = true; + } + break; + case '#': + if ((isspacechar(static_cast(sc.chPrev))|| + isoperator(static_cast(sc.chPrev))) && IsADigit(sc.chNext,0x10)) + sc.SetState(SCE_TCL_NUMBER); + break; + case '-': + sc.SetState(IsADigit(sc.chNext)? SCE_TCL_NUMBER: SCE_TCL_MODIFIER); + break; + default: + if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_TCL_OPERATOR); + } + } + } + } + } + sc.Complete(); +} + +static const char * const tclWordListDesc[] = { + "TCL Keywords", + "TK Keywords", + "iTCL Keywords", + "tkCommands", + "expand" + "user1", + "user2", + "user3", + "user4", + 0 + }; + +// this code supports folding in the colourizer +LexerModule lmTCL(SCLEX_TCL, ColouriseTCLDoc, "tcl", 0, tclWordListDesc); diff --git a/lexers/LexTeX.cxx b/lexers/LexTeX.cxx new file mode 100644 index 000000000..62ade1d75 --- /dev/null +++ b/lexers/LexTeX.cxx @@ -0,0 +1,494 @@ +// Scintilla source code edit control + +// File: LexTeX.cxx - general context conformant tex coloring scheme +// Author: Hans Hagen - PRAGMA ADE - Hasselt NL - www.pragma-ade.com +// Version: September 28, 2003 + +// Copyright: 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +// This lexer is derived from the one written for the texwork environment (1999++) which in +// turn is inspired on texedit (1991++) which finds its roots in wdt (1986). + +// If you run into strange boundary cases, just tell me and I'll look into it. + + +// TeX Folding code added by instanton (soft_share@126.com) with borrowed code from VisualTeX source by Alex Romanenko. +// Version: June 22, 2007 + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "StyleContext.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// val SCE_TEX_DEFAULT = 0 +// val SCE_TEX_SPECIAL = 1 +// val SCE_TEX_GROUP = 2 +// val SCE_TEX_SYMBOL = 3 +// val SCE_TEX_COMMAND = 4 +// val SCE_TEX_TEXT = 5 + +// Definitions in SciTEGlobal.properties: +// +// TeX Highlighting +// +// # Default +// style.tex.0=fore:#7F7F00 +// # Special +// style.tex.1=fore:#007F7F +// # Group +// style.tex.2=fore:#880000 +// # Symbol +// style.tex.3=fore:#7F7F00 +// # Command +// style.tex.4=fore:#008800 +// # Text +// style.tex.5=fore:#000000 + +// lexer.tex.interface.default=0 +// lexer.tex.comment.process=0 + +// todo: lexer.tex.auto.if + +// Auxiliary functions: + +static inline bool endOfLine(Accessor &styler, unsigned int i) { + return + (styler[i] == '\n') || ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')) ; +} + +static inline bool isTeXzero(int ch) { + return + (ch == '%') ; +} + +static inline bool isTeXone(int ch) { + return + (ch == '[') || (ch == ']') || (ch == '=') || (ch == '#') || + (ch == '(') || (ch == ')') || (ch == '<') || (ch == '>') || + (ch == '"') ; +} + +static inline bool isTeXtwo(int ch) { + return + (ch == '{') || (ch == '}') || (ch == '$') ; +} + +static inline bool isTeXthree(int ch) { + return + (ch == '~') || (ch == '^') || (ch == '_') || (ch == '&') || + (ch == '-') || (ch == '+') || (ch == '\"') || (ch == '`') || + (ch == '/') || (ch == '|') || (ch == '%') ; +} + +static inline bool isTeXfour(int ch) { + return + (ch == '\\') ; +} + +static inline bool isTeXfive(int ch) { + return + ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) || + (ch == '@') || (ch == '!') || (ch == '?') ; +} + +static inline bool isTeXsix(int ch) { + return + (ch == ' ') ; +} + +static inline bool isTeXseven(int ch) { + return + (ch == '^') ; +} + +// Interface determination + +static int CheckTeXInterface( + unsigned int startPos, + int length, + Accessor &styler, + int defaultInterface) { + + char lineBuffer[1024] ; + unsigned int linePos = 0 ; + + // some day we can make something lexer.tex.mapping=(all,0)(nl,1)(en,2)... + + if (styler.SafeGetCharAt(0) == '%') { + for (unsigned int i = 0; i < startPos + length; i++) { + lineBuffer[linePos++] = styler.SafeGetCharAt(i) ; + if (endOfLine(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { + lineBuffer[linePos] = '\0'; + if (strstr(lineBuffer, "interface=all")) { + return 0 ; + } else if (strstr(lineBuffer, "interface=tex")) { + return 1 ; + } else if (strstr(lineBuffer, "interface=nl")) { + return 2 ; + } else if (strstr(lineBuffer, "interface=en")) { + return 3 ; + } else if (strstr(lineBuffer, "interface=de")) { + return 4 ; + } else if (strstr(lineBuffer, "interface=cz")) { + return 5 ; + } else if (strstr(lineBuffer, "interface=it")) { + return 6 ; + } else if (strstr(lineBuffer, "interface=ro")) { + return 7 ; + } else if (strstr(lineBuffer, "interface=latex")) { + // we will move latex cum suis up to 91+ when more keyword lists are supported + return 8 ; + } else if (styler.SafeGetCharAt(1) == 'D' && strstr(lineBuffer, "%D \\module")) { + // better would be to limit the search to just one line + return 3 ; + } else { + return defaultInterface ; + } + } + } + } + + return defaultInterface ; +} + +static void ColouriseTeXDoc( + unsigned int startPos, + int length, + int, + WordList *keywordlists[], + Accessor &styler) { + + styler.StartAt(startPos) ; + styler.StartSegment(startPos) ; + + bool processComment = styler.GetPropertyInt("lexer.tex.comment.process", 0) == 1 ; + bool useKeywords = styler.GetPropertyInt("lexer.tex.use.keywords", 1) == 1 ; + bool autoIf = styler.GetPropertyInt("lexer.tex.auto.if", 1) == 1 ; + int defaultInterface = styler.GetPropertyInt("lexer.tex.interface.default", 1) ; + + char key[100] ; + int k ; + bool newifDone = false ; + bool inComment = false ; + + int currentInterface = CheckTeXInterface(startPos,length,styler,defaultInterface) ; + + if (currentInterface == 0) { + useKeywords = false ; + currentInterface = 1 ; + } + + WordList &keywords = *keywordlists[currentInterface-1] ; + + StyleContext sc(startPos, length, SCE_TEX_TEXT, styler); + + bool going = sc.More() ; // needed because of a fuzzy end of file state + + for (; going; sc.Forward()) { + + if (! sc.More()) { going = false ; } // we need to go one behind the end of text + + if (inComment) { + if (sc.atLineEnd) { + sc.SetState(SCE_TEX_TEXT) ; + newifDone = false ; + inComment = false ; + } + } else { + if (! isTeXfive(sc.ch)) { + if (sc.state == SCE_TEX_COMMAND) { + if (sc.LengthCurrent() == 1) { // \ + if (isTeXseven(sc.ch) && isTeXseven(sc.chNext)) { + sc.Forward(2) ; // \^^ and \^^ + } + sc.ForwardSetState(SCE_TEX_TEXT) ; + } else { + sc.GetCurrent(key, sizeof(key)-1) ; + k = strlen(key) ; + memmove(key,key+1,k) ; // shift left over escape token + key[k] = '\0' ; + k-- ; + if (! keywords || ! useKeywords) { + sc.SetState(SCE_TEX_COMMAND) ; + newifDone = false ; + } else if (k == 1) { //\ + sc.SetState(SCE_TEX_COMMAND) ; + newifDone = false ; + } else if (keywords.InList(key)) { + sc.SetState(SCE_TEX_COMMAND) ; + newifDone = autoIf && (strcmp(key,"newif") == 0) ; + } else if (autoIf && ! newifDone && (key[0] == 'i') && (key[1] == 'f') && keywords.InList("if")) { + sc.SetState(SCE_TEX_COMMAND) ; + } else { + sc.ChangeState(SCE_TEX_TEXT) ; + sc.SetState(SCE_TEX_TEXT) ; + newifDone = false ; + } + } + } + if (isTeXzero(sc.ch)) { + sc.SetState(SCE_TEX_SYMBOL); + + if (!endOfLine(styler,sc.currentPos + 1)) + sc.ForwardSetState(SCE_TEX_DEFAULT) ; + + inComment = ! processComment ; + newifDone = false ; + } else if (isTeXseven(sc.ch) && isTeXseven(sc.chNext)) { + sc.SetState(SCE_TEX_TEXT) ; + sc.ForwardSetState(SCE_TEX_TEXT) ; + } else if (isTeXone(sc.ch)) { + sc.SetState(SCE_TEX_SPECIAL) ; + newifDone = false ; + } else if (isTeXtwo(sc.ch)) { + sc.SetState(SCE_TEX_GROUP) ; + newifDone = false ; + } else if (isTeXthree(sc.ch)) { + sc.SetState(SCE_TEX_SYMBOL) ; + newifDone = false ; + } else if (isTeXfour(sc.ch)) { + sc.SetState(SCE_TEX_COMMAND) ; + } else if (isTeXsix(sc.ch)) { + sc.SetState(SCE_TEX_TEXT) ; + } else if (sc.atLineEnd) { + sc.SetState(SCE_TEX_TEXT) ; + newifDone = false ; + inComment = false ; + } else { + sc.SetState(SCE_TEX_TEXT) ; + } + } else if (sc.state != SCE_TEX_COMMAND) { + sc.SetState(SCE_TEX_TEXT) ; + } + } + } + sc.ChangeState(SCE_TEX_TEXT) ; + sc.Complete(); + +} + + +static inline bool isNumber(int ch) { + return + (ch == '0') || (ch == '1') || (ch == '2') || + (ch == '3') || (ch == '4') || (ch == '5') || + (ch == '6') || (ch == '7') || (ch == '8') || (ch == '9'); +} + +static inline bool isWordChar(int ch) { + return ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')); +} + +static int ParseTeXCommand(unsigned int pos, Accessor &styler, char *command) +{ + int length=0; + char ch=styler.SafeGetCharAt(pos+1); + + if(ch==',' || ch==':' || ch==';' || ch=='%'){ + command[0]=ch; + command[1]=0; + return 1; + } + + // find end + while(isWordChar(ch) && !isNumber(ch) && ch!='_' && ch!='.' && length<100){ + command[length]=ch; + length++; + ch=styler.SafeGetCharAt(pos+length+1); + } + + command[length]='\0'; + if(!length) return 0; + return length+1; +} + +static int classifyFoldPointTeXPaired(const char* s) { + int lev=0; + if (!(isdigit(s[0]) || (s[0] == '.'))){ + if (strcmp(s, "begin")==0||strcmp(s,"FoldStart")==0|| + strcmp(s,"abstract")==0||strcmp(s,"unprotect")==0|| + strcmp(s,"title")==0||strncmp(s,"start",5)==0||strncmp(s,"Start",5)==0|| + strcmp(s,"documentclass")==0||strncmp(s,"if",2)==0 + ) + lev=1; + if (strcmp(s, "end")==0||strcmp(s,"FoldStop")==0|| + strcmp(s,"maketitle")==0||strcmp(s,"protect")==0|| + strncmp(s,"stop",4)==0||strncmp(s,"Stop",4)==0|| + strcmp(s,"fi")==0 + ) + lev=-1; + } + return lev; +} + +static int classifyFoldPointTeXUnpaired(const char* s) { + int lev=0; + if (!(isdigit(s[0]) || (s[0] == '.'))){ + if (strcmp(s,"part")==0|| + strcmp(s,"chapter")==0|| + strcmp(s,"section")==0|| + strcmp(s,"subsection")==0|| + strcmp(s,"subsubsection")==0|| + strcmp(s,"CJKfamily")==0|| + strcmp(s,"appendix")==0|| + strcmp(s,"Topic")==0||strcmp(s,"topic")==0|| + strcmp(s,"subject")==0||strcmp(s,"subsubject")==0|| + strcmp(s,"def")==0||strcmp(s,"gdef")==0||strcmp(s,"edef")==0|| + strcmp(s,"xdef")==0||strcmp(s,"framed")==0|| + strcmp(s,"frame")==0|| + strcmp(s,"foilhead")==0||strcmp(s,"overlays")==0||strcmp(s,"slide")==0 + ){ + lev=1; + } + } + return lev; +} + +static bool IsTeXCommentLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + + int startpos = pos; + + while (startpos SC_FOLDLEVELBASE && ((ch == '\r' || ch=='\n') && (chNext == '\\'))) { + ParseTeXCommand(i+1, styler, buffer); + levelCurrent -= classifyFoldPointTeXUnpaired(buffer); + } + + char chNext2; + char chNext3; + char chNext4; + char chNext5; + chNext2=styler.SafeGetCharAt(i+2); + chNext3=styler.SafeGetCharAt(i+3); + chNext4=styler.SafeGetCharAt(i+4); + chNext5=styler.SafeGetCharAt(i+5); + + bool atEOfold = (ch == '%') && + (chNext == '%') && (chNext2=='}') && + (chNext3=='}')&& (chNext4=='-')&& (chNext5=='-'); + + bool atBOfold = (ch == '%') && + (chNext == '%') && (chNext2=='-') && + (chNext3=='-')&& (chNext4=='{')&& (chNext5=='{'); + + if(atBOfold){ + levelCurrent+=1; + } + + if(atEOfold){ + levelCurrent-=1; + } + + if(ch=='\\' && chNext=='['){ + levelCurrent+=1; + } + + if(ch=='\\' && chNext==']'){ + levelCurrent-=1; + } + + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + + if (foldComment && atEOL && IsTeXCommentLine(lineCurrent, styler)) + { + if (lineCurrent==0 && IsTeXCommentLine(lineCurrent + 1, styler) + ) + levelCurrent++; + else if (lineCurrent!=0 && !IsTeXCommentLine(lineCurrent - 1, styler) + && IsTeXCommentLine(lineCurrent + 1, styler) + ) + levelCurrent++; + else if (lineCurrent!=0 && IsTeXCommentLine(lineCurrent - 1, styler) && + !IsTeXCommentLine(lineCurrent+1, styler)) + levelCurrent--; + } + +//--------------------------------------------------------------------------------------------- + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + + if (!isspacechar(ch)) + visibleChars++; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + + + + +static const char * const texWordListDesc[] = { + "TeX, eTeX, pdfTeX, Omega", + "ConTeXt Dutch", + "ConTeXt English", + "ConTeXt German", + "ConTeXt Czech", + "ConTeXt Italian", + "ConTeXt Romanian", + 0, +} ; + +LexerModule lmTeX(SCLEX_TEX, ColouriseTeXDoc, "tex", FoldTexDoc, texWordListDesc); diff --git a/lexers/LexVB.cxx b/lexers/LexVB.cxx new file mode 100644 index 000000000..c57a9ac49 --- /dev/null +++ b/lexers/LexVB.cxx @@ -0,0 +1,316 @@ +// Scintilla source code edit control +/** @file LexVB.cxx + ** Lexer for Visual Basic and VBScript. + **/ +// Copyright 1998-2005 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// Internal state, highlighted as number +#define SCE_B_FILENUMBER SCE_B_DEFAULT+100 + + +static bool IsVBComment(Accessor &styler, int pos, int len) { + return len > 0 && styler[pos] == '\''; +} + +static inline bool IsTypeCharacter(int ch) { + return ch == '%' || ch == '&' || ch == '@' || ch == '!' || ch == '#' || ch == '$'; +} + +// Extended to accept accented characters +static inline bool IsAWordChar(int ch) { + return ch >= 0x80 || + (isalnum(ch) || ch == '.' || ch == '_'); +} + +static inline bool IsAWordStart(int ch) { + return ch >= 0x80 || + (isalpha(ch) || ch == '_'); +} + +static inline bool IsANumberChar(int ch) { + // Not exactly following number definition (several dots are seen as OK, etc.) + // but probably enough in most cases. + return (ch < 0x80) && + (isdigit(ch) || toupper(ch) == 'E' || + ch == '.' || ch == '-' || ch == '+'); +} + +static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler, bool vbScriptSyntax) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + + styler.StartAt(startPos); + + int visibleChars = 0; + int fileNbDigits = 0; + + // Do not leak onto next line + if (initStyle == SCE_B_STRINGEOL || initStyle == SCE_B_COMMENT || initStyle == SCE_B_PREPROCESSOR) { + initStyle = SCE_B_DEFAULT; + } + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.state == SCE_B_OPERATOR) { + sc.SetState(SCE_B_DEFAULT); + } else if (sc.state == SCE_B_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + // In Basic (except VBScript), a variable name or a function name + // can end with a special character indicating the type of the value + // held or returned. + bool skipType = false; + if (!vbScriptSyntax && IsTypeCharacter(sc.ch)) { + sc.Forward(); // Skip it + skipType = true; + } + if (sc.ch == ']') { + sc.Forward(); + } + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (skipType) { + s[strlen(s) - 1] = '\0'; + } + if (strcmp(s, "rem") == 0) { + sc.ChangeState(SCE_B_COMMENT); + } else { + if (keywords.InList(s)) { + sc.ChangeState(SCE_B_KEYWORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_B_KEYWORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_B_KEYWORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_B_KEYWORD4); + } // Else, it is really an identifier... + sc.SetState(SCE_B_DEFAULT); + } + } + } else if (sc.state == SCE_B_NUMBER) { + // We stop the number definition on non-numerical non-dot non-eE non-sign char + // Also accepts A-F for hex. numbers + if (!IsANumberChar(sc.ch) && !(tolower(sc.ch) >= 'a' && tolower(sc.ch) <= 'f')) { + sc.SetState(SCE_B_DEFAULT); + } + } else if (sc.state == SCE_B_STRING) { + // VB doubles quotes to preserve them, so just end this string + // state now as a following quote will start again + if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + if (tolower(sc.chNext) == 'c') { + sc.Forward(); + } + sc.ForwardSetState(SCE_B_DEFAULT); + } + } else if (sc.atLineEnd) { + visibleChars = 0; + sc.ChangeState(SCE_B_STRINGEOL); + sc.ForwardSetState(SCE_B_DEFAULT); + } + } else if (sc.state == SCE_B_COMMENT) { + if (sc.atLineEnd) { + visibleChars = 0; + sc.ForwardSetState(SCE_B_DEFAULT); + } + } else if (sc.state == SCE_B_PREPROCESSOR) { + if (sc.atLineEnd) { + visibleChars = 0; + sc.ForwardSetState(SCE_B_DEFAULT); + } + } else if (sc.state == SCE_B_FILENUMBER) { + if (IsADigit(sc.ch)) { + fileNbDigits++; + if (fileNbDigits > 3) { + sc.ChangeState(SCE_B_DATE); + } + } else if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ',') { + // Regular uses: Close #1; Put #1, ...; Get #1, ... etc. + // Too bad if date is format #27, Oct, 2003# or something like that... + // Use regular number state + sc.ChangeState(SCE_B_NUMBER); + sc.SetState(SCE_B_DEFAULT); + } else if (sc.ch == '#') { + sc.ChangeState(SCE_B_DATE); + sc.ForwardSetState(SCE_B_DEFAULT); + } else { + sc.ChangeState(SCE_B_DATE); + } + if (sc.state != SCE_B_FILENUMBER) { + fileNbDigits = 0; + } + } else if (sc.state == SCE_B_DATE) { + if (sc.atLineEnd) { + visibleChars = 0; + sc.ChangeState(SCE_B_STRINGEOL); + sc.ForwardSetState(SCE_B_DEFAULT); + } else if (sc.ch == '#') { + sc.ForwardSetState(SCE_B_DEFAULT); + } + } + + if (sc.state == SCE_B_DEFAULT) { + if (sc.ch == '\'') { + sc.SetState(SCE_B_COMMENT); + } else if (sc.ch == '\"') { + sc.SetState(SCE_B_STRING); + } else if (sc.ch == '#' && visibleChars == 0) { + // Preprocessor commands are alone on their line + sc.SetState(SCE_B_PREPROCESSOR); + } else if (sc.ch == '#') { + // It can be a date literal, ending with #, or a file number, from 1 to 511 + // The date literal depends on the locale, so anything can go between #'s. + // Can be #January 1, 1993# or #1 Jan 93# or #05/11/2003#, etc. + // So we set the FILENUMBER state, and switch to DATE if it isn't a file number + sc.SetState(SCE_B_FILENUMBER); + } else if (sc.ch == '&' && tolower(sc.chNext) == 'h') { + // Hexadecimal number + sc.SetState(SCE_B_NUMBER); + sc.Forward(); + } else if (sc.ch == '&' && tolower(sc.chNext) == 'o') { + // Octal number + sc.SetState(SCE_B_NUMBER); + sc.Forward(); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_B_NUMBER); + } else if (IsAWordStart(sc.ch) || (sc.ch == '[')) { + sc.SetState(SCE_B_IDENTIFIER); + } else if (isoperator(static_cast(sc.ch)) || (sc.ch == '\\')) { // Integer division + sc.SetState(SCE_B_OPERATOR); + } + } + + if (sc.atLineEnd) { + visibleChars = 0; + } + if (!IsASpace(sc.ch)) { + visibleChars++; + } + } + + if (sc.state == SCE_B_IDENTIFIER && !IsAWordChar(sc.ch)) { + // In Basic (except VBScript), a variable name or a function name + // can end with a special character indicating the type of the value + // held or returned. + bool skipType = false; + if (!vbScriptSyntax && IsTypeCharacter(sc.ch)) { + sc.Forward(); // Skip it + skipType = true; + } + if (sc.ch == ']') { + sc.Forward(); + } + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (skipType) { + s[strlen(s) - 1] = '\0'; + } + if (strcmp(s, "rem") == 0) { + sc.ChangeState(SCE_B_COMMENT); + } else { + if (keywords.InList(s)) { + sc.ChangeState(SCE_B_KEYWORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_B_KEYWORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_B_KEYWORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_B_KEYWORD4); + } // Else, it is really an identifier... + sc.SetState(SCE_B_DEFAULT); + } + } + + sc.Complete(); +} + +static void FoldVBDoc(unsigned int startPos, int length, int, + WordList *[], Accessor &styler) { + int endPos = startPos + length; + + // Backtrack to previous line in case need to fix its fold status + int lineCurrent = styler.GetLine(startPos); + if (startPos > 0) { + if (lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + } + int spaceFlags = 0; + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsVBComment); + char chNext = styler[startPos]; + for (int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { + int lev = indentCurrent; + int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsVBComment); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + // Only non whitespace lines can be headers + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { + // Line after is blank so check the next - maybe should continue further? + int spaceFlags2 = 0; + int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsVBComment); + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + } + } + indentCurrent = indentNext; + styler.SetLevel(lineCurrent, lev); + lineCurrent++; + } + } +} + +static void ColouriseVBNetDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + ColouriseVBDoc(startPos, length, initStyle, keywordlists, styler, false); +} + +static void ColouriseVBScriptDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + ColouriseVBDoc(startPos, length, initStyle, keywordlists, styler, true); +} + +static const char * const vbWordListDesc[] = { + "Keywords", + "user1", + "user2", + "user3", + 0 +}; + +LexerModule lmVB(SCLEX_VB, ColouriseVBNetDoc, "vb", FoldVBDoc, vbWordListDesc); +LexerModule lmVBScript(SCLEX_VBSCRIPT, ColouriseVBScriptDoc, "vbscript", FoldVBDoc, vbWordListDesc); + diff --git a/lexers/LexVHDL.cxx b/lexers/LexVHDL.cxx new file mode 100644 index 000000000..c0733ab82 --- /dev/null +++ b/lexers/LexVHDL.cxx @@ -0,0 +1,476 @@ +// Scintilla source code edit control +/** @file LexVHDL.cxx + ** Lexer for VHDL + ** Written by Phil Reid, + ** Based on: + ** - The Verilog Lexer by Avi Yegudin + ** - The Fortran Lexer by Chuan-jian Shen + ** - The C++ lexer by Neil Hodgson + **/ +// Copyright 1998-2002 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static void ColouriseVHDLDoc( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler); + + +/***************************************/ +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' ); +} + +/***************************************/ +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +/***************************************/ +inline bool IsABlank(unsigned int ch) { + return (ch == ' ') || (ch == 0x09) || (ch == 0x0b) ; +} + +/***************************************/ +static void ColouriseVHDLDoc( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) +{ + WordList &Keywords = *keywordlists[0]; + WordList &Operators = *keywordlists[1]; + WordList &Attributes = *keywordlists[2]; + WordList &Functions = *keywordlists[3]; + WordList &Packages = *keywordlists[4]; + WordList &Types = *keywordlists[5]; + WordList &User = *keywordlists[6]; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) + { + + // Determine if the current state should terminate. + if (sc.state == SCE_VHDL_OPERATOR) { + sc.SetState(SCE_VHDL_DEFAULT); + } else if (sc.state == SCE_VHDL_NUMBER) { + if (!IsAWordChar(sc.ch) && (sc.ch != '#')) { + sc.SetState(SCE_VHDL_DEFAULT); + } + } else if (sc.state == SCE_VHDL_IDENTIFIER) { + if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (Keywords.InList(s)) { + sc.ChangeState(SCE_VHDL_KEYWORD); + } else if (Operators.InList(s)) { + sc.ChangeState(SCE_VHDL_STDOPERATOR); + } else if (Attributes.InList(s)) { + sc.ChangeState(SCE_VHDL_ATTRIBUTE); + } else if (Functions.InList(s)) { + sc.ChangeState(SCE_VHDL_STDFUNCTION); + } else if (Packages.InList(s)) { + sc.ChangeState(SCE_VHDL_STDPACKAGE); + } else if (Types.InList(s)) { + sc.ChangeState(SCE_VHDL_STDTYPE); + } else if (User.InList(s)) { + sc.ChangeState(SCE_VHDL_USERWORD); + } + sc.SetState(SCE_VHDL_DEFAULT); + } + } else if (sc.state == SCE_VHDL_COMMENT || sc.state == SCE_V_COMMENTLINEBANG) { + if (sc.atLineEnd) { + sc.SetState(SCE_VHDL_DEFAULT); + } + } else if (sc.state == SCE_VHDL_STRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_VHDL_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_V_STRINGEOL); + sc.ForwardSetState(SCE_VHDL_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_VHDL_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_VHDL_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_VHDL_IDENTIFIER); + } else if (sc.Match('-', '-')) { + sc.SetState(SCE_VHDL_COMMENT); + sc.Forward(); + } else if (sc.Match('-', '-')) { + if (sc.Match("--!")) // Nice to have a different comment style + sc.SetState(SCE_VHDL_COMMENTLINEBANG); + else + sc.SetState(SCE_VHDL_COMMENT); + } else if (sc.ch == '\"') { + sc.SetState(SCE_VHDL_STRING); + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_VHDL_OPERATOR); + } + } + } + sc.Complete(); +} +//============================================================================= +static bool IsCommentLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eol_pos; i++) { + char ch = styler[i]; + char chNext = styler[i+1]; + if ((ch == '-') && (chNext == '-')) + return true; + else if (ch != ' ' && ch != '\t') + return false; + } + return false; +} + +//============================================================================= +// Folding the code +static void FoldNoBoxVHDLDoc( + unsigned int startPos, + int length, + int, + Accessor &styler) +{ + // Decided it would be smarter to have the lexer have all keywords included. Therefore I + // don't check if the style for the keywords that I use to adjust the levels. + char words[] = + "architecture begin case component else elsif end entity generate loop package process record then " + "procedure function when"; + WordList keywords; + keywords.Set(words); + + bool foldComment = styler.GetPropertyInt("fold.comment", 1) != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldAtElse = styler.GetPropertyInt("fold.at.else", 1) != 0; + bool foldAtBegin = styler.GetPropertyInt("fold.at.Begin", 1) != 0; + bool foldAtParenthese = styler.GetPropertyInt("fold.at.Parenthese", 1) != 0; + //bool foldAtWhen = styler.GetPropertyInt("fold.at.When", 1) != 0; //< fold at when in case statements + + int visibleChars = 0; + unsigned int endPos = startPos + length; + + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if(lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + //int levelMinCurrent = levelCurrent; + int levelMinCurrentElse = levelCurrent; //< Used for folding at 'else' + int levelMinCurrentBegin = levelCurrent; //< Used for folding at 'begin' + int levelNext = levelCurrent; + + /***************************************/ + int lastStart = 0; + char prevWord[32] = ""; + + /***************************************/ + // Find prev word + // The logic for going up or down a level depends on a the previous keyword + // This code could be cleaned up. + int end = 0; + unsigned int j; + for(j = startPos; j>0; j--) + { + char ch = styler.SafeGetCharAt(j); + char chPrev = styler.SafeGetCharAt(j-1); + int style = styler.StyleAt(j); + int stylePrev = styler.StyleAt(j-1); + if ((stylePrev != SCE_VHDL_COMMENT) && (stylePrev != SCE_VHDL_STRING)) + { + if(IsAWordChar(chPrev) && !IsAWordChar(ch)) + { + end = j-1; + } + } + if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING)) + { + if(!IsAWordChar(chPrev) && IsAWordStart(ch) && (end != 0)) + { + char s[32]; + unsigned int k; + for(k=0; (k<31 ) && (k(tolower(styler[j+k])); + } + s[k] = '\0'; + + if(keywords.InList(s)) { + strcpy(prevWord, s); + break; + } + } + } + } + for(j=j+strlen(prevWord); j(tolower(styler[lastStart+k])); + } + s[k] = '\0'; + + if(keywords.InList(s)) + { + if ( + strcmp(s, "architecture") == 0 || + strcmp(s, "case") == 0 || + strcmp(s, "component") == 0 || + strcmp(s, "entity") == 0 || + strcmp(s, "generate") == 0 || + strcmp(s, "loop") == 0 || + strcmp(s, "package") ==0 || + strcmp(s, "process") == 0 || + strcmp(s, "record") == 0 || + strcmp(s, "then") == 0) + { + if (strcmp(prevWord, "end") != 0) + { + if (levelMinCurrentElse > levelNext) { + levelMinCurrentElse = levelNext; + } + levelNext++; + } + } else if ( + strcmp(s, "procedure") == 0 || + strcmp(s, "function") == 0) + { + if (strcmp(prevWord, "end") != 0) // check for "end procedure" etc. + { // This code checks to see if the procedure / function is a definition within a "package" + // rather than the actual code in the body. + int BracketLevel = 0; + for(int j=i+1; j levelNext) { + levelMinCurrentElse = levelNext; + } + levelNext++; + break; + } + if((BracketLevel == 0) && (LocalCh == ';')) + { + break; + } + } + } + + } else if (strcmp(s, "end") == 0) { + levelNext--; + } else if(strcmp(s, "elsif") == 0) { // elsif is followed by then so folding occurs correctly + levelNext--; + } else if (strcmp(s, "else") == 0) { + if(strcmp(prevWord, "when") != 0) // ignore a <= x when y else z; + { + levelMinCurrentElse = levelNext - 1; // VHDL else is all on its own so just dec. the min level + } + } else if( + ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "architecture") == 0)) || + ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "function") == 0)) || + ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "procedure") == 0))) + { + levelMinCurrentBegin = levelNext - 1; + } + //Platform::DebugPrintf("Line[%04d] Prev[%20s] Cur[%20s] Level[%x]\n", lineCurrent+1, prevWord, s, levelCurrent); + strcpy(prevWord, s); + } + } + } + if (atEOL) { + int levelUse = levelCurrent; + + if (foldAtElse && (levelMinCurrentElse < levelUse)) { + levelUse = levelMinCurrentElse; + } + if (foldAtBegin && (levelMinCurrentBegin < levelUse)) { + levelUse = levelMinCurrentBegin; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + //Platform::DebugPrintf("Line[%04d] ---------------------------------------------------- Level[%x]\n", lineCurrent+1, levelCurrent); + lineCurrent++; + levelCurrent = levelNext; + //levelMinCurrent = levelCurrent; + levelMinCurrentElse = levelCurrent; + levelMinCurrentBegin = levelCurrent; + visibleChars = 0; + } + /***************************************/ + if (!isspacechar(ch)) visibleChars++; + } + + /***************************************/ +// Platform::DebugPrintf("Line[%04d] ---------------------------------------------------- Level[%x]\n", lineCurrent+1, levelCurrent); +} + +//============================================================================= +static void FoldVHDLDoc(unsigned int startPos, int length, int initStyle, WordList *[], + Accessor &styler) { + FoldNoBoxVHDLDoc(startPos, length, initStyle, styler); +} + +//============================================================================= +static const char * const VHDLWordLists[] = { + "Keywords", + "Operators", + "Attributes", + "Standard Functions", + "Standard Packages", + "Standard Types", + "User Words", + 0, + }; + + +LexerModule lmVHDL(SCLEX_VHDL, ColouriseVHDLDoc, "vhdl", FoldVHDLDoc, VHDLWordLists); + + +// Keyword: +// access after alias all architecture array assert attribute begin block body buffer bus case component +// configuration constant disconnect downto else elsif end entity exit file for function generate generic +// group guarded if impure in inertial inout is label library linkage literal loop map new next null of +// on open others out package port postponed procedure process pure range record register reject report +// return select severity shared signal subtype then to transport type unaffected units until use variable +// wait when while with +// +// Operators: +// abs and mod nand nor not or rem rol ror sla sll sra srl xnor xor +// +// Attributes: +// left right low high ascending image value pos val succ pred leftof rightof base range reverse_range +// length delayed stable quiet transaction event active last_event last_active last_value driving +// driving_value simple_name path_name instance_name +// +// Std Functions: +// now readline read writeline write endfile resolved to_bit to_bitvector to_stdulogic to_stdlogicvector +// to_stdulogicvector to_x01 to_x01z to_UX01 rising_edge falling_edge is_x shift_left shift_right rotate_left +// rotate_right resize to_integer to_unsigned to_signed std_match to_01 +// +// Std Packages: +// std ieee work standard textio std_logic_1164 std_logic_arith std_logic_misc std_logic_signed +// std_logic_textio std_logic_unsigned numeric_bit numeric_std math_complex math_real vital_primitives +// vital_timing +// +// Std Types: +// boolean bit character severity_level integer real time delay_length natural positive string bit_vector +// file_open_kind file_open_status line text side width std_ulogic std_ulogic_vector std_logic +// std_logic_vector X01 X01Z UX01 UX01Z unsigned signed +// + diff --git a/lexers/LexVerilog.cxx b/lexers/LexVerilog.cxx new file mode 100644 index 000000000..8b531bb7e --- /dev/null +++ b/lexers/LexVerilog.cxx @@ -0,0 +1,330 @@ +// Scintilla source code edit control +/** @file LexVerilog.cxx + ** Lexer for Verilog. + ** Written by Avi Yegudin, based on C++ lexer by Neil Hodgson + **/ +// Copyright 1998-2002 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '$'); +} + +static void ColouriseVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + + // Do not leak onto next line + if (initStyle == SCE_V_STRINGEOL) + initStyle = SCE_V_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart && (sc.state == SCE_V_STRING)) { + // Prevent SCE_V_STRINGEOL from leaking back to previous line + sc.SetState(SCE_V_STRING); + } + + // Handle line continuation generically. + if (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_V_OPERATOR) { + sc.SetState(SCE_V_DEFAULT); + } else if (sc.state == SCE_V_NUMBER) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_V_DEFAULT); + } + } else if (sc.state == SCE_V_IDENTIFIER) { + if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_V_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_V_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_V_WORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_V_USER); + } + sc.SetState(SCE_V_DEFAULT); + } + } else if (sc.state == SCE_V_PREPROCESSOR) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_V_DEFAULT); + } + } else if (sc.state == SCE_V_COMMENT) { + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_V_DEFAULT); + } + } else if (sc.state == SCE_V_COMMENTLINE || sc.state == SCE_V_COMMENTLINEBANG) { + if (sc.atLineStart) { + sc.SetState(SCE_V_DEFAULT); + } + } else if (sc.state == SCE_V_STRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_V_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_V_STRINGEOL); + sc.ForwardSetState(SCE_V_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_V_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '\'') || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_V_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_V_IDENTIFIER); + } else if (sc.Match('/', '*')) { + sc.SetState(SCE_V_COMMENT); + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + if (sc.Match("//!")) // Nice to have a different comment style + sc.SetState(SCE_V_COMMENTLINEBANG); + else + sc.SetState(SCE_V_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_V_STRING); + } else if (sc.ch == '`') { + sc.SetState(SCE_V_PREPROCESSOR); + // Skip whitespace between ` and preprocessor word + do { + sc.Forward(); + } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); + if (sc.atLineEnd) { + sc.SetState(SCE_V_DEFAULT); + } + } else if (isoperator(static_cast(sc.ch)) || sc.ch == '@' || sc.ch == '#') { + sc.SetState(SCE_V_OPERATOR); + } + } + } + sc.Complete(); +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_V_COMMENT; +} + +static bool IsCommentLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eolPos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eolPos; i++) { + char ch = styler[i]; + char chNext = styler.SafeGetCharAt(i + 1); + int style = styler.StyleAt(i); + if (ch == '/' && chNext == '/' && + (style == SCE_V_COMMENTLINE || style == SCE_V_COMMENTLINEBANG)) { + return true; + } else if (!IsASpaceOrTab(ch)) { + return false; + } + } + return false; +} +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "} else {". +static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle, + Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; + // Verilog specific folding options: + // fold_at_module - + // Generally used methodology in verilog code is + // one module per file, so folding at module definition is useless. + // fold_at_brace/parenthese - + // Folding of long port lists can be convenient. + bool foldAtModule = styler.GetPropertyInt("fold.verilog.flags", 0) != 0; + bool foldAtBrace = 1; + bool foldAtParenthese = 1; + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) + { + if (!IsCommentLine(lineCurrent - 1, styler) + && IsCommentLine(lineCurrent + 1, styler)) + levelNext++; + else if (IsCommentLine(lineCurrent - 1, styler) + && !IsCommentLine(lineCurrent+1, styler)) + levelNext--; + } + if (foldComment && (style == SCE_V_COMMENTLINE)) { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelNext++; + } else if (chNext2 == '}') { + levelNext--; + } + } + } + if (foldPreprocessor && (style == SCE_V_PREPROCESSOR)) { + if (ch == '`') { + unsigned int j = i + 1; + while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { + j++; + } + if (styler.Match(j, "if")) { + levelNext++; + } else if (styler.Match(j, "end")) { + levelNext--; + } + } + } + if (style == SCE_V_OPERATOR) { + if (foldAtParenthese) { + if (ch == '(') { + levelNext++; + } else if (ch == ')') { + levelNext--; + } + } + } + if (style == SCE_V_OPERATOR) { + if (foldAtBrace) { + if (ch == '{') { + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + } + if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) { + unsigned int j = i; + if (styler.Match(j, "case") || + styler.Match(j, "casex") || + styler.Match(j, "casez") || + styler.Match(j, "function") || + styler.Match(j, "fork") || + styler.Match(j, "table") || + styler.Match(j, "task") || + styler.Match(j, "generate") || + styler.Match(j, "specify") || + styler.Match(j, "primitive") || + (styler.Match(j, "module") && foldAtModule) || + styler.Match(j, "begin")) { + levelNext++; + } else if (styler.Match(j, "endcase") || + styler.Match(j, "endfunction") || + styler.Match(j, "join") || + styler.Match(j, "endtask") || + styler.Match(j, "endgenerate") || + styler.Match(j, "endtable") || + styler.Match(j, "endspecify") || + styler.Match(j, "endprimitive") || + (styler.Match(j, "endmodule") && foldAtModule) || + (styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j+3)))) { + levelNext--; + } + } + if (atEOL) { + int levelUse = levelCurrent; + if (foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } +} + +static void FoldVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *[], + Accessor &styler) { + FoldNoBoxVerilogDoc(startPos, length, initStyle, styler); +} + +static const char * const verilogWordLists[] = { + "Primary keywords and identifiers", + "Secondary keywords and identifiers", + "System Tasks", + "User defined tasks and identifiers", + "Unused", + 0, + }; + + +LexerModule lmVerilog(SCLEX_VERILOG, ColouriseVerilogDoc, "verilog", FoldVerilogDoc, verilogWordLists); diff --git a/lexers/LexYAML.cxx b/lexers/LexYAML.cxx new file mode 100644 index 000000000..99f34da88 --- /dev/null +++ b/lexers/LexYAML.cxx @@ -0,0 +1,314 @@ +// Scintilla source code edit control +/** @file LexYAML.cxx + ** Lexer for YAML. + **/ +// Copyright 2003- by Sean O'Dell +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static const char * const yamlWordListDesc[] = { + "Keywords", + 0 +}; + +static inline bool AtEOL(Accessor &styler, unsigned int i) { + return (styler[i] == '\n') || + ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); +} + +static unsigned int SpaceCount(char* lineBuffer) { + if (lineBuffer == NULL) + return 0; + + char* headBuffer = lineBuffer; + + while (*headBuffer == ' ') + headBuffer++; + + return headBuffer - lineBuffer; +} + +#define YAML_STATE_BITSIZE 16 +#define YAML_STATE_MASK (0xFFFF0000) +#define YAML_STATE_DOCUMENT (1 << YAML_STATE_BITSIZE) +#define YAML_STATE_VALUE (2 << YAML_STATE_BITSIZE) +#define YAML_STATE_COMMENT (3 << YAML_STATE_BITSIZE) +#define YAML_STATE_TEXT_PARENT (4 << YAML_STATE_BITSIZE) +#define YAML_STATE_TEXT (5 << YAML_STATE_BITSIZE) + +static void ColouriseYAMLLine( + char *lineBuffer, + unsigned int currentLine, + unsigned int lengthLine, + unsigned int startLine, + unsigned int endPos, + WordList &keywords, + Accessor &styler) { + + unsigned int i = 0; + bool bInQuotes = false; + unsigned int indentAmount = SpaceCount(lineBuffer); + + if (currentLine > 0) { + int parentLineState = styler.GetLineState(currentLine - 1); + + if ((parentLineState&YAML_STATE_MASK) == YAML_STATE_TEXT || (parentLineState&YAML_STATE_MASK) == YAML_STATE_TEXT_PARENT) { + unsigned int parentIndentAmount = parentLineState&(~YAML_STATE_MASK); + if (indentAmount > parentIndentAmount) { + styler.SetLineState(currentLine, YAML_STATE_TEXT | parentIndentAmount); + styler.ColourTo(endPos, SCE_YAML_TEXT); + return; + } + } + } + styler.SetLineState(currentLine, 0); + if (strncmp(lineBuffer, "---", 3) == 0) { // Document marker + styler.SetLineState(currentLine, YAML_STATE_DOCUMENT); + styler.ColourTo(endPos, SCE_YAML_DOCUMENT); + return; + } + // Skip initial spaces + while ((i < lengthLine) && lineBuffer[i] == ' ') { // YAML always uses space, never TABS or anything else + i++; + } + if (lineBuffer[i] == '\t') { // if we skipped all spaces, and we are NOT inside a text block, this is wrong + styler.ColourTo(endPos, SCE_YAML_ERROR); + return; + } + if (lineBuffer[i] == '#') { // Comment + styler.SetLineState(currentLine, YAML_STATE_COMMENT); + styler.ColourTo(endPos, SCE_YAML_COMMENT); + return; + } + while (i < lengthLine) { + if (lineBuffer[i] == '\'' || lineBuffer[i] == '\"') { + bInQuotes = !bInQuotes; + } else if (lineBuffer[i] == ':' && !bInQuotes) { + styler.ColourTo(startLine + i - 1, SCE_YAML_IDENTIFIER); + styler.ColourTo(startLine + i, SCE_YAML_OPERATOR); + // Non-folding scalar + i++; + while ((i < lengthLine) && isspacechar(lineBuffer[i])) + i++; + unsigned int endValue = lengthLine - 1; + while ((endValue >= i) && isspacechar(lineBuffer[endValue])) + endValue--; + lineBuffer[endValue + 1] = '\0'; + if (lineBuffer[i] == '|' || lineBuffer[i] == '>') { + i++; + if (lineBuffer[i] == '+' || lineBuffer[i] == '-') + i++; + while ((i < lengthLine) && isspacechar(lineBuffer[i])) + i++; + if (lineBuffer[i] == '\0') { + styler.SetLineState(currentLine, YAML_STATE_TEXT_PARENT | indentAmount); + styler.ColourTo(endPos, SCE_YAML_DEFAULT); + return; + } else if (lineBuffer[i] == '#') { + styler.SetLineState(currentLine, YAML_STATE_TEXT_PARENT | indentAmount); + styler.ColourTo(startLine + i - 1, SCE_YAML_DEFAULT); + styler.ColourTo(endPos, SCE_YAML_COMMENT); + return; + } else { + styler.ColourTo(endPos, SCE_YAML_ERROR); + return; + } + } else if (lineBuffer[i] == '#') { + styler.ColourTo(startLine + i - 1, SCE_YAML_DEFAULT); + styler.ColourTo(endPos, SCE_YAML_COMMENT); + return; + } + styler.SetLineState(currentLine, YAML_STATE_VALUE); + if (lineBuffer[i] == '&' || lineBuffer[i] == '*') { + styler.ColourTo(endPos, SCE_YAML_REFERENCE); + return; + } + if (keywords.InList(&lineBuffer[i])) { // Convertible value (true/false, etc.) + styler.ColourTo(endPos, SCE_YAML_KEYWORD); + return; + } else { + unsigned int i2 = i; + while ((i < lengthLine) && lineBuffer[i]) { + if (!(isascii(lineBuffer[i]) && isdigit(lineBuffer[i])) && lineBuffer[i] != '-' && lineBuffer[i] != '.' && lineBuffer[i] != ',') { + styler.ColourTo(endPos, SCE_YAML_DEFAULT); + return; + } + i++; + } + if (i > i2) { + styler.ColourTo(endPos, SCE_YAML_NUMBER); + return; + } + } + break; // shouldn't get here, but just in case, the rest of the line is coloured the default + } + i++; + } + styler.ColourTo(endPos, SCE_YAML_DEFAULT); +} + +static void ColouriseYAMLDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) { + char lineBuffer[1024]; + styler.StartAt(startPos); + styler.StartSegment(startPos); + unsigned int linePos = 0; + unsigned int startLine = startPos; + unsigned int endPos = startPos + length; + unsigned int maxPos = styler.Length(); + unsigned int lineCurrent = styler.GetLine(startPos); + + for (unsigned int i = startPos; i < maxPos && i < endPos; i++) { + lineBuffer[linePos++] = styler[i]; + if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { + // End of line (or of line buffer) met, colourise it + lineBuffer[linePos] = '\0'; + ColouriseYAMLLine(lineBuffer, lineCurrent, linePos, startLine, i, *keywordLists[0], styler); + linePos = 0; + startLine = i + 1; + lineCurrent++; + } + } + if (linePos > 0) { // Last line does not have ending characters + ColouriseYAMLLine(lineBuffer, lineCurrent, linePos, startLine, startPos + length - 1, *keywordLists[0], styler); + } +} + +static bool IsCommentLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + if (styler[pos] == '#') + return true; + return false; +} + +static void FoldYAMLDoc(unsigned int startPos, int length, int /*initStyle - unused*/, + WordList *[], Accessor &styler) { + const int maxPos = startPos + length; + const int maxLines = styler.GetLine(maxPos - 1); // Requested last line + const int docLines = styler.GetLine(styler.Length() - 1); // Available last line + const bool foldComment = styler.GetPropertyInt("fold.comment.yaml") != 0; + + // Backtrack to previous non-blank line so we can determine indent level + // for any white space lines + // and so we can fix any preceding fold level (which is why we go back + // at least one line in all cases) + int spaceFlags = 0; + int lineCurrent = styler.GetLine(startPos); + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); + while (lineCurrent > 0) { + lineCurrent--; + indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) && + (!IsCommentLine(lineCurrent, styler))) + break; + } + int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + + // Set up initial loop state + int prevComment = 0; + if (lineCurrent >= 1) + prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler); + + // Process all characters to end of requested range + // or comment that hangs over the end of the range. Cap processing in all cases + // to end of document (in case of unclosed comment at end). + while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevComment)) { + + // Gather info + int lev = indentCurrent; + int lineNext = lineCurrent + 1; + int indentNext = indentCurrent; + if (lineNext <= docLines) { + // Information about next line is only available if not at end of document + indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); + } + const int comment = foldComment && IsCommentLine(lineCurrent, styler); + const int comment_start = (comment && !prevComment && (lineNext <= docLines) && + IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE)); + const int comment_continue = (comment && prevComment); + if (!comment) + indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + if (indentNext & SC_FOLDLEVELWHITEFLAG) + indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel; + + if (comment_start) { + // Place fold point at start of a block of comments + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (comment_continue) { + // Add level to rest of lines in the block + lev = lev + 1; + } + + // Skip past any blank lines for next indent level info; we skip also + // comments (all comments, not just those starting in column 0) + // which effectively folds them into surrounding code rather + // than screwing up folding. + + while ((lineNext < docLines) && + ((indentNext & SC_FOLDLEVELWHITEFLAG) || + (lineNext <= docLines && IsCommentLine(lineNext, styler)))) { + + lineNext++; + indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); + } + + const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK; + const int levelBeforeComments = Platform::Maximum(indentCurrentLevel,levelAfterComments); + + // Now set all the indent levels on the lines we skipped + // Do this from end to start. Once we encounter one line + // which is indented more than the line after the end of + // the comment-block, use the level of the block before + + int skipLine = lineNext; + int skipLevel = levelAfterComments; + + while (--skipLine > lineCurrent) { + int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL); + + if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments) + skipLevel = levelBeforeComments; + + int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG; + + styler.SetLevel(skipLine, skipLevel | whiteFlag); + } + + // Set fold header on non-comment line + if (!comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG) ) { + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) + lev |= SC_FOLDLEVELHEADERFLAG; + } + + // Keep track of block comment state of previous line + prevComment = comment_start || comment_continue; + + // Set fold level for this line and move to next line + styler.SetLevel(lineCurrent, lev); + indentCurrent = indentNext; + lineCurrent = lineNext; + } + + // NOTE: Cannot set level of last line here because indentCurrent doesn't have + // header flag set; the loop above is crafted to take care of this case! + //styler.SetLevel(lineCurrent, indentCurrent); +} + +LexerModule lmYAML(SCLEX_YAML, ColouriseYAMLDoc, "yaml", FoldYAMLDoc, yamlWordListDesc); diff --git a/src/LexAPDL.cxx b/src/LexAPDL.cxx deleted file mode 100644 index 7bf597b42..000000000 --- a/src/LexAPDL.cxx +++ /dev/null @@ -1,256 +0,0 @@ -// Scintilla source code edit control -/** @file LexAPDL.cxx - ** Lexer for APDL. Based on the lexer for Assembler by The Black Horus. - ** By Hadar Raz. - **/ -// Copyright 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80 && (isalnum(ch) || ch == '_')); -} - -static inline bool IsAnOperator(char ch) { - // '.' left out as it is used to make up numbers - if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || - ch == '(' || ch == ')' || ch == '=' || ch == '^' || - ch == '[' || ch == ']' || ch == '<' || ch == '&' || - ch == '>' || ch == ',' || ch == '|' || ch == '~' || - ch == '$' || ch == ':' || ch == '%') - return true; - return false; -} - -static void ColouriseAPDLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - int stringStart = ' '; - - WordList &processors = *keywordlists[0]; - WordList &commands = *keywordlists[1]; - WordList &slashcommands = *keywordlists[2]; - WordList &starcommands = *keywordlists[3]; - WordList &arguments = *keywordlists[4]; - WordList &functions = *keywordlists[5]; - - // Do not leak onto next line - initStyle = SCE_APDL_DEFAULT; - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - // Determine if the current state should terminate. - if (sc.state == SCE_APDL_NUMBER) { - if (!(IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') || - ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) { - sc.SetState(SCE_APDL_DEFAULT); - } - } else if (sc.state == SCE_APDL_COMMENT) { - if (sc.atLineEnd) { - sc.SetState(SCE_APDL_DEFAULT); - } - } else if (sc.state == SCE_APDL_COMMENTBLOCK) { - if (sc.atLineEnd) { - if (sc.ch == '\r') { - sc.Forward(); - } - sc.ForwardSetState(SCE_APDL_DEFAULT); - } - } else if (sc.state == SCE_APDL_STRING) { - if (sc.atLineEnd) { - sc.SetState(SCE_APDL_DEFAULT); - } else if ((sc.ch == '\'' && stringStart == '\'') || (sc.ch == '\"' && stringStart == '\"')) { - sc.ForwardSetState(SCE_APDL_DEFAULT); - } - } else if (sc.state == SCE_APDL_WORD) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (processors.InList(s)) { - sc.ChangeState(SCE_APDL_PROCESSOR); - } else if (slashcommands.InList(s)) { - sc.ChangeState(SCE_APDL_SLASHCOMMAND); - } else if (starcommands.InList(s)) { - sc.ChangeState(SCE_APDL_STARCOMMAND); - } else if (commands.InList(s)) { - sc.ChangeState(SCE_APDL_COMMAND); - } else if (arguments.InList(s)) { - sc.ChangeState(SCE_APDL_ARGUMENT); - } else if (functions.InList(s)) { - sc.ChangeState(SCE_APDL_FUNCTION); - } - sc.SetState(SCE_APDL_DEFAULT); - } - } else if (sc.state == SCE_APDL_OPERATOR) { - if (!IsAnOperator(static_cast(sc.ch))) { - sc.SetState(SCE_APDL_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_APDL_DEFAULT) { - if (sc.ch == '!' && sc.chNext == '!') { - sc.SetState(SCE_APDL_COMMENTBLOCK); - } else if (sc.ch == '!') { - sc.SetState(SCE_APDL_COMMENT); - } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_APDL_NUMBER); - } else if (sc.ch == '\'' || sc.ch == '\"') { - sc.SetState(SCE_APDL_STRING); - stringStart = sc.ch; - } else if (IsAWordChar(sc.ch) || ((sc.ch == '*' || sc.ch == '/') && !isgraph(sc.chPrev))) { - sc.SetState(SCE_APDL_WORD); - } else if (IsAnOperator(static_cast(sc.ch))) { - sc.SetState(SCE_APDL_OPERATOR); - } - } - } - sc.Complete(); -} - -//------------------------------------------------------------------------------ -// 06-27-07 Sergio Lucato -// - Included code folding for Ansys APDL lexer -// - Copyied from LexBasic.cxx and modified for APDL -//------------------------------------------------------------------------------ - -/* Bits: - * 1 - whitespace - * 2 - operator - * 4 - identifier - * 8 - decimal digit - * 16 - hex digit - * 32 - bin digit - */ -static int character_classification[128] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 10, 6, - 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2, - 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4, - 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0 -}; - -static bool IsSpace(int c) { - return c < 128 && (character_classification[c] & 1); -} - -static bool IsIdentifier(int c) { - return c < 128 && (character_classification[c] & 4); -} - -static int LowerCase(int c) -{ - if (c >= 'A' && c <= 'Z') - return 'a' + c - 'A'; - return c; -} - -static int CheckAPDLFoldPoint(char const *token, int &level) { - if (!strcmp(token, "*if") || - !strcmp(token, "*do") || - !strcmp(token, "*dowhile") ) { - level |= SC_FOLDLEVELHEADERFLAG; - return 1; - } - if (!strcmp(token, "*endif") || - !strcmp(token, "*enddo") ) { - return -1; - } - return 0; -} - -static void FoldAPDLDoc(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) { - - int line = styler.GetLine(startPos); - int level = styler.LevelAt(line); - int go = 0, done = 0; - int endPos = startPos + length; - char word[256]; - int wordlen = 0; - int i; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - // Scan for tokens at the start of the line (they may include - // whitespace, for tokens like "End Function" - for (i = startPos; i < endPos; i++) { - int c = styler.SafeGetCharAt(i); - if (!done && !go) { - if (wordlen) { // are we scanning a token already? - word[wordlen] = static_cast(LowerCase(c)); - if (!IsIdentifier(c)) { // done with token - word[wordlen] = '\0'; - go = CheckAPDLFoldPoint(word, level); - if (!go) { - // Treat any whitespace as single blank, for - // things like "End Function". - if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) { - word[wordlen] = ' '; - if (wordlen < 255) - wordlen++; - } - else // done with this line - done = 1; - } - } else if (wordlen < 255) { - wordlen++; - } - } else { // start scanning at first non-whitespace character - if (!IsSpace(c)) { - if (IsIdentifier(c)) { - word[0] = static_cast(LowerCase(c)); - wordlen = 1; - } else // done with this line - done = 1; - } - } - } - if (c == '\n') { // line end - if (!done && wordlen == 0 && foldCompact) // line was only space - level |= SC_FOLDLEVELWHITEFLAG; - if (level != styler.LevelAt(line)) - styler.SetLevel(line, level); - level += go; - line++; - // reset state - wordlen = 0; - level &= ~SC_FOLDLEVELHEADERFLAG; - level &= ~SC_FOLDLEVELWHITEFLAG; - go = 0; - done = 0; - } - } -} - -static const char * const apdlWordListDesc[] = { - "processors", - "commands", - "slashommands", - "starcommands", - "arguments", - "functions", - 0 -}; - -LexerModule lmAPDL(SCLEX_APDL, ColouriseAPDLDoc, "apdl", FoldAPDLDoc, apdlWordListDesc); diff --git a/src/LexASY.cxx b/src/LexASY.cxx deleted file mode 100644 index 5bf979fd3..000000000 --- a/src/LexASY.cxx +++ /dev/null @@ -1,270 +0,0 @@ -// Scintilla source code edit control -//Author: instanton (email: soft_share126com) -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "CharacterSet.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static void ColouriseAsyDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - - CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); - - int visibleChars = 0; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.atLineStart) { - if (sc.state == SCE_ASY_STRING) { - sc.SetState(SCE_ASY_STRING); - } - visibleChars = 0; - } - - if (sc.ch == '\\') { - if (sc.chNext == '\n' || sc.chNext == '\r') { - sc.Forward(); - if (sc.ch == '\r' && sc.chNext == '\n') { - sc.Forward(); - } -// continuationLine = true; - continue; - } - } - - // Determine if the current state should terminate. - switch (sc.state) { - case SCE_ASY_OPERATOR: - sc.SetState(SCE_ASY_DEFAULT); - break; - case SCE_ASY_NUMBER: - if (!setWord.Contains(sc.ch)) { - sc.SetState(SCE_ASY_DEFAULT); - } - break; - case SCE_ASY_IDENTIFIER: - if (!setWord.Contains(sc.ch) || (sc.ch == '.')) { - char s[1000]; - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(SCE_ASY_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_ASY_WORD2); - } - sc.SetState(SCE_ASY_DEFAULT); - } - break; - case SCE_ASY_COMMENT: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_ASY_DEFAULT); - } - break; - case SCE_ASY_COMMENTLINE: - if (sc.atLineStart) { - sc.SetState(SCE_ASY_DEFAULT); - } - break; - case SCE_ASY_STRING: - if (sc.atLineEnd) { - sc.ChangeState(SCE_ASY_STRINGEOL); - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_ASY_DEFAULT); - } - break; - case SCE_ASY_CHARACTER: - if (sc.atLineEnd) { - sc.ChangeState(SCE_ASY_STRINGEOL); - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_ASY_DEFAULT); - } - break; - } - - // Determine if a new state should be entered. - if (sc.state == SCE_ASY_DEFAULT) { - if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) { - sc.SetState(SCE_ASY_IDENTIFIER); - } else if (sc.Match('/', '*')) { - sc.SetState(SCE_ASY_COMMENT); - sc.Forward(); // - } else if (sc.Match('/', '/')) { - sc.SetState(SCE_ASY_COMMENTLINE); - } else if (sc.ch == '\"') { - sc.SetState(SCE_ASY_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_ASY_CHARACTER); - } else if (sc.ch == '#' && visibleChars == 0) { - do { - sc.Forward(); - } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); - if (sc.atLineEnd) { - sc.SetState(SCE_ASY_DEFAULT); - } - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_ASY_OPERATOR); - } - } - - } - sc.Complete(); -} - -static bool IsAsyCommentStyle(int style) { - return style == SCE_ASY_COMMENT; -} - - -static inline bool isASYidentifier(int ch) { - return - ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ; -} - -static int ParseASYWord(unsigned int pos, Accessor &styler, char *word) -{ - int length=0; - char ch=styler.SafeGetCharAt(pos); - *word=0; - - while(isASYidentifier(ch) && length<100){ - word[length]=ch; - length++; - ch=styler.SafeGetCharAt(pos+length); - } - word[length]=0; - return length; -} - -static bool IsASYDrawingLine(int line, Accessor &styler) { - int pos = styler.LineStart(line); - int eol_pos = styler.LineStart(line + 1) - 1; - - int startpos = pos; - char buffer[100]=""; - - while (startpos 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelMinCurrent = levelCurrent; - int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && IsAsyCommentStyle(style)) { - if (!IsAsyCommentStyle(stylePrev) && (stylePrev != SCE_ASY_COMMENTLINEDOC)) { - levelNext++; - } else if (!IsAsyCommentStyle(styleNext) && (styleNext != SCE_ASY_COMMENTLINEDOC) && !atEOL) { - levelNext--; - } - } - if (style == SCE_ASY_OPERATOR) { - if (ch == '{') { - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - levelNext++; - } else if (ch == '}') { - levelNext--; - } - } - - if (atEOL && IsASYDrawingLine(lineCurrent, styler)){ - if (lineCurrent==0 && IsASYDrawingLine(lineCurrent + 1, styler)) - levelNext++; - else if (lineCurrent!=0 && !IsASYDrawingLine(lineCurrent - 1, styler) - && IsASYDrawingLine(lineCurrent + 1, styler) - ) - levelNext++; - else if (lineCurrent!=0 && IsASYDrawingLine(lineCurrent - 1, styler) && - !IsASYDrawingLine(lineCurrent+1, styler)) - levelNext--; - } - - if (atEOL) { - int levelUse = levelCurrent; - if (foldAtElse) { - levelUse = levelMinCurrent; - } - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - levelMinCurrent = levelCurrent; - visibleChars = 0; - } - if (!IsASpace(ch)) - visibleChars++; - } -} - -static const char * const asyWordLists[] = { - "Primary keywords and identifiers", - "Secondary keywords and identifiers", - 0, - }; - -LexerModule lmASY(SCLEX_ASYMPTOTE, ColouriseAsyDoc, "asy", FoldAsyDoc, asyWordLists); diff --git a/src/LexAU3.cxx b/src/LexAU3.cxx deleted file mode 100644 index cfff9279d..000000000 --- a/src/LexAU3.cxx +++ /dev/null @@ -1,907 +0,0 @@ -// Scintilla source code edit control -// @file LexAU3.cxx -// Lexer for AutoIt3 http://www.hiddensoft.com/autoit3 -// by Jos van der Zande, jvdzande@yahoo.com -// -// Changes: -// March 28, 2004 - Added the standard Folding code -// April 21, 2004 - Added Preprosessor Table + Syntax Highlighting -// Fixed Number highlighting -// Changed default isoperator to IsAOperator to have a better match to AutoIt3 -// Fixed "#comments_start" -> "#comments-start" -// Fixed "#comments_end" -> "#comments-end" -// Fixed Sendkeys in Strings when not terminated with } -// Added support for Sendkey strings that have second parameter e.g. {UP 5} or {a down} -// April 26, 2004 - Fixed # pre-processor statement inside of comment block would invalidly change the color. -// Added logic for #include to treat the <> as string -// Added underscore to IsAOperator. -// May 17, 2004 - Changed the folding logic from indent to keyword folding. -// Added Folding logic for blocks of single-commentlines or commentblock. -// triggered by: fold.comment=1 -// Added Folding logic for preprocessor blocks triggered by fold.preprocessor=1 -// Added Special for #region - #endregion syntax highlight and folding. -// May 30, 2004 - Fixed issue with continuation lines on If statements. -// June 5, 2004 - Added comma to Operators for better readability. -// Added fold.compact support set with fold.compact=1 -// Changed folding inside of #cs-#ce. Default is no keyword folding inside comment blocks when fold.comment=1 -// it will now only happen when fold.comment=2. -// Sep 5, 2004 - Added logic to handle colourizing words on the last line. -// Typed Characters now show as "default" till they match any table. -// Oct 10, 2004 - Added logic to show Comments in "Special" directives. -// Nov 1, 2004 - Added better testing for Numbers supporting x and e notation. -// Nov 28, 2004 - Added logic to handle continuation lines for syntax highlighting. -// Jan 10, 2005 - Added Abbreviations Keyword used for expansion -// Mar 24, 2005 - Updated Abbreviations Keywords to fix when followed by Operator. -// Apr 18, 2005 - Updated #CE/#Comment-End logic to take a linecomment ";" into account -// - Added folding support for With...EndWith -// - Added support for a DOT in variable names -// - Fixed Underscore in CommentBlock -// May 23, 2005 - Fixed the SentKey lexing in case of a missing } -// Aug 11, 2005 - Fixed possible bug with s_save length > 100. -// Aug 23, 2005 - Added Switch/endswitch support to the folding logic. -// Sep 27, 2005 - Fixed the SentKey lexing logic in case of multiple sentkeys. -// Mar 12, 2006 - Fixed issue with <> coloring as String in stead of Operator in rare occasions. -// Apr 8, 2006 - Added support for AutoIt3 Standard UDF library (SCE_AU3_UDF) -// Mar 9, 2007 - Fixed bug with + following a String getting the wrong Color. -// Jun 20, 2007 - Fixed Commentblock issue when LF's are used as EOL. -// Jul 26, 2007 - Fixed #endregion undetected bug. -// -// Copyright for Scintilla: 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. -// Scintilla source code edit control - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsTypeCharacter(const int ch) -{ - return ch == '$'; -} -static inline bool IsAWordChar(const int ch) -{ - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static inline bool IsAWordStart(const int ch) -{ - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$' || ch == '.'); -} - -static inline bool IsAOperator(char ch) { - if (isascii(ch) && isalnum(ch)) - return false; - if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || - ch == '&' || ch == '^' || ch == '=' || ch == '<' || ch == '>' || - ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == ',' ) - return true; - return false; -} - -/////////////////////////////////////////////////////////////////////////////// -// GetSendKey() filters the portion before and after a/multiple space(s) -// and return the first portion to be looked-up in the table -// also check if the second portion is valid... (up,down.on.off,toggle or a number) -/////////////////////////////////////////////////////////////////////////////// - -static int GetSendKey(const char *szLine, char *szKey) -{ - int nFlag = 0; - int nStartFound = 0; - int nKeyPos = 0; - int nSpecPos= 0; - int nSpecNum= 1; - int nPos = 0; - char cTemp; - char szSpecial[100]; - - // split the portion of the sendkey in the part before and after the spaces - while ( ( (cTemp = szLine[nPos]) != '\0')) - { - // skip leading Ctrl/Shift/Alt state - if (cTemp == '{') { - nStartFound = 1; - } - // - if (nStartFound == 1) { - if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space - { - nFlag = 1; - // Add } to the end of the first bit for table lookup later. - szKey[nKeyPos++] = '}'; - } - else if (cTemp == ' ') - { - // skip other spaces - } - else if (nFlag == 0) - { - // save first portion into var till space or } is hit - szKey[nKeyPos++] = cTemp; - } - else if ((nFlag == 1) && (cTemp != '}')) - { - // Save second portion into var... - szSpecial[nSpecPos++] = cTemp; - // check if Second portion is all numbers for repeat fuction - if (isdigit(cTemp) == false) {nSpecNum = 0;} - } - } - nPos++; // skip to next char - - } // End While - - - // Check if the second portion is either a number or one of these keywords - szKey[nKeyPos] = '\0'; - szSpecial[nSpecPos] = '\0'; - if (strcmp(szSpecial,"down")== 0 || strcmp(szSpecial,"up")== 0 || - strcmp(szSpecial,"on")== 0 || strcmp(szSpecial,"off")== 0 || - strcmp(szSpecial,"toggle")== 0 || nSpecNum == 1 ) - { - nFlag = 0; - } - else - { - nFlag = 1; - } - return nFlag; // 1 is bad, 0 is good - -} // GetSendKey() - -// -// Routine to check the last "none comment" character on a line to see if its a continuation -// -static bool IsContinuationLine(unsigned int szLine, Accessor &styler) -{ - int nsPos = styler.LineStart(szLine); - int nePos = styler.LineStart(szLine+1) - 2; - //int stylech = styler.StyleAt(nsPos); - while (nsPos < nePos) - { - //stylech = styler.StyleAt(nePos); - int stylech = styler.StyleAt(nsPos); - if (!(stylech == SCE_AU3_COMMENT)) { - char ch = styler.SafeGetCharAt(nePos); - if (!isspacechar(ch)) { - if (ch == '_') - return true; - else - return false; - } - } - nePos--; // skip to next char - } // End While - return false; -} // IsContinuationLine() - -// -// syntax highlighting logic -static void ColouriseAU3Doc(unsigned int startPos, - int length, int initStyle, - WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - WordList &keywords6 = *keywordlists[5]; - WordList &keywords7 = *keywordlists[6]; - WordList &keywords8 = *keywordlists[7]; - // find the first previous line without continuation character at the end - int lineCurrent = styler.GetLine(startPos); - int s_startPos = startPos; - // When not inside a Block comment: find First line without _ - if (!(initStyle==SCE_AU3_COMMENTBLOCK)) { - while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || - (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); // get start position - initStyle = 0; // reset the start style to 0 - } - } - // Set the new length to include it from the start and set the start position - length = length + s_startPos - startPos; // correct the total length to process - styler.StartAt(startPos); - - StyleContext sc(startPos, length, initStyle, styler); - char si; // string indicator "=1 '=2 - char ni; // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 Enot=3 - char ci; // comment indicator 0=not linecomment(;) - char s_save[100]; - si=0; - ni=0; - ci=0; - //$$$ - for (; sc.More(); sc.Forward()) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - // ********************************************** - // save the total current word for eof processing - if (IsAWordChar(sc.ch) || sc.ch == '}') - { - strcpy(s_save,s); - int tp = strlen(s_save); - if (tp < 99) { - s_save[tp] = static_cast(tolower(sc.ch)); - s_save[tp+1] = '\0'; - } - } - // ********************************************** - // - switch (sc.state) - { - case SCE_AU3_COMMENTBLOCK: - { - //Reset at line end - if (sc.atLineEnd) { - ci=0; - if (strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0) { - if (sc.atLineEnd) - sc.SetState(SCE_AU3_DEFAULT); - else - sc.SetState(SCE_AU3_COMMENTBLOCK); - } - break; - } - //skip rest of line when a ; is encountered - if (sc.chPrev == ';') { - ci=2; - sc.SetState(SCE_AU3_COMMENTBLOCK); - } - // skip rest of the line - if (ci==2) - break; - // check when first character is detected on the line - if (ci==0) { - if (IsAWordStart(static_cast(sc.ch)) || IsAOperator(static_cast(sc.ch))) { - ci=1; - sc.SetState(SCE_AU3_COMMENTBLOCK); - } - break; - } - if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && strcmp(s, "#comments") == 0))) { - if ((strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0)) - sc.SetState(SCE_AU3_COMMENT); // set to comment line for the rest of the line - else - ci=2; // line doesn't begin with #CE so skip the rest of the line - } - break; - } - case SCE_AU3_COMMENT: - { - if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} - break; - } - case SCE_AU3_OPERATOR: - { - // check if its a COMobject - if (sc.chPrev == '.' && IsAWordChar(sc.ch)) { - sc.SetState(SCE_AU3_COMOBJ); - } - else { - sc.SetState(SCE_AU3_DEFAULT); - } - break; - } - case SCE_AU3_SPECIAL: - { - if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);} - if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} - break; - } - case SCE_AU3_KEYWORD: - { - if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && (strcmp(s, "#comments") == 0 || strcmp(s, "#include") == 0)))) - { - if (!IsTypeCharacter(sc.ch)) - { - if (strcmp(s, "#cs")== 0 || strcmp(s, "#comments-start")== 0 ) - { - sc.ChangeState(SCE_AU3_COMMENTBLOCK); - sc.SetState(SCE_AU3_COMMENTBLOCK); - break; - } - else if (keywords.InList(s)) { - sc.ChangeState(SCE_AU3_KEYWORD); - sc.SetState(SCE_AU3_DEFAULT); - } - else if (keywords2.InList(s)) { - sc.ChangeState(SCE_AU3_FUNCTION); - sc.SetState(SCE_AU3_DEFAULT); - } - else if (keywords3.InList(s)) { - sc.ChangeState(SCE_AU3_MACRO); - sc.SetState(SCE_AU3_DEFAULT); - } - else if (keywords5.InList(s)) { - sc.ChangeState(SCE_AU3_PREPROCESSOR); - sc.SetState(SCE_AU3_DEFAULT); - if (strcmp(s, "#include")== 0) - { - si = 3; // use to determine string start for #inlude <> - } - } - else if (keywords6.InList(s)) { - sc.ChangeState(SCE_AU3_SPECIAL); - sc.SetState(SCE_AU3_SPECIAL); - } - else if ((keywords7.InList(s)) && (!IsAOperator(static_cast(sc.ch)))) { - sc.ChangeState(SCE_AU3_EXPAND); - sc.SetState(SCE_AU3_DEFAULT); - } - else if (keywords8.InList(s)) { - sc.ChangeState(SCE_AU3_UDF); - sc.SetState(SCE_AU3_DEFAULT); - } - else if (strcmp(s, "_") == 0) { - sc.ChangeState(SCE_AU3_OPERATOR); - sc.SetState(SCE_AU3_DEFAULT); - } - else if (!IsAWordChar(sc.ch)) { - sc.ChangeState(SCE_AU3_DEFAULT); - sc.SetState(SCE_AU3_DEFAULT); - } - } - } - if (sc.atLineEnd) { - sc.SetState(SCE_AU3_DEFAULT);} - break; - } - case SCE_AU3_NUMBER: - { - // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 E-not=3 - // - // test for Hex notation - if (strcmp(s, "0") == 0 && (sc.ch == 'x' || sc.ch == 'X') && ni == 0) - { - ni = 2; - break; - } - // test for E notation - if (IsADigit(sc.chPrev) && (sc.ch == 'e' || sc.ch == 'E') && ni <= 1) - { - ni = 3; - break; - } - // Allow Hex characters inside hex numeric strings - if ((ni == 2) && - (sc.ch == 'a' || sc.ch == 'b' || sc.ch == 'c' || sc.ch == 'd' || sc.ch == 'e' || sc.ch == 'f' || - sc.ch == 'A' || sc.ch == 'B' || sc.ch == 'C' || sc.ch == 'D' || sc.ch == 'E' || sc.ch == 'F' )) - { - break; - } - // test for 1 dec point only - if (sc.ch == '.') - { - if (ni==0) - { - ni=1; - } - else - { - ni=9; - } - break; - } - // end of numeric string ? - if (!(IsADigit(sc.ch))) - { - if (ni==9) - { - sc.ChangeState(SCE_AU3_DEFAULT); - } - sc.SetState(SCE_AU3_DEFAULT); - } - break; - } - case SCE_AU3_VARIABLE: - { - // Check if its a COMObject - if (sc.ch == '.' && !IsADigit(sc.chNext)) { - sc.SetState(SCE_AU3_OPERATOR); - } - else if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_AU3_DEFAULT); - } - break; - } - case SCE_AU3_COMOBJ: - { - if (!(IsAWordChar(sc.ch))) { - sc.SetState(SCE_AU3_DEFAULT); - } - break; - } - case SCE_AU3_STRING: - { - // check for " to end a double qouted string or - // check for ' to end a single qouted string - if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'') || (si == 3 && sc.ch == '>')) - { - sc.ForwardSetState(SCE_AU3_DEFAULT); - si=0; - break; - } - if (sc.atLineEnd) - { - si=0; - // at line end and not found a continuation char then reset to default - int lineCurrent = styler.GetLine(sc.currentPos); - if (!IsContinuationLine(lineCurrent,styler)) - { - sc.SetState(SCE_AU3_DEFAULT); - break; - } - } - // find Sendkeys in a STRING - if (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ) { - sc.SetState(SCE_AU3_SENT);} - break; - } - - case SCE_AU3_SENT: - { - // Send key string ended - if (sc.chPrev == '}' && sc.ch != '}') - { - // set color to SENDKEY when valid sendkey .. else set back to regular string - char sk[100]; - // split {111 222} and return {111} and check if 222 is valid. - // if return code = 1 then invalid 222 so must be string - if (GetSendKey(s,sk)) - { - sc.ChangeState(SCE_AU3_STRING); - } - // if single char between {?} then its ok as sendkey for a single character - else if (strlen(sk) == 3) - { - sc.ChangeState(SCE_AU3_SENT); - } - // if sendkey {111} is in table then ok as sendkey - else if (keywords4.InList(sk)) - { - sc.ChangeState(SCE_AU3_SENT); - } - else - { - sc.ChangeState(SCE_AU3_STRING); - } - sc.SetState(SCE_AU3_STRING); - } - else - { - // check if the start is a valid SendKey start - int nPos = 0; - int nState = 1; - char cTemp; - while (!(nState == 2) && ((cTemp = s[nPos]) != '\0')) - { - if (cTemp == '{' && nState == 1) - { - nState = 2; - } - if (nState == 1 && !(cTemp == '+' || cTemp == '!' || cTemp == '^' || cTemp == '#' )) - { - nState = 0; - } - nPos++; - } - //Verify characters infront of { ... if not assume regular string - if (nState == 1 && (!(sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ))) { - sc.ChangeState(SCE_AU3_STRING); - sc.SetState(SCE_AU3_STRING); - } - // If invalid character found then assume its a regular string - if (nState == 0) { - sc.ChangeState(SCE_AU3_STRING); - sc.SetState(SCE_AU3_STRING); - } - } - // check if next portion is again a sendkey - if (sc.atLineEnd) - { - sc.ChangeState(SCE_AU3_STRING); - sc.SetState(SCE_AU3_DEFAULT); - si = 0; // reset string indicator - } - //* check in next characters following a sentkey are again a sent key - // Need this test incase of 2 sentkeys like {F1}{ENTER} but not detect {{} - if (sc.state == SCE_AU3_STRING && (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' )) { - sc.SetState(SCE_AU3_SENT);} - // check to see if the string ended... - // Sendkey string isn't complete but the string ended.... - if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'')) - { - sc.ChangeState(SCE_AU3_STRING); - sc.ForwardSetState(SCE_AU3_DEFAULT); - } - break; - } - } //switch (sc.state) - - // Determine if a new state should be entered: - - if (sc.state == SCE_AU3_DEFAULT) - { - if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);} - else if (sc.ch == '#') {sc.SetState(SCE_AU3_KEYWORD);} - else if (sc.ch == '$') {sc.SetState(SCE_AU3_VARIABLE);} - else if (sc.ch == '.' && !IsADigit(sc.chNext)) {sc.SetState(SCE_AU3_OPERATOR);} - else if (sc.ch == '@') {sc.SetState(SCE_AU3_KEYWORD);} - //else if (sc.ch == '_') {sc.SetState(SCE_AU3_KEYWORD);} - else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);} // string after #include - else if (sc.ch == '\"') { - sc.SetState(SCE_AU3_STRING); - si = 1; } - else if (sc.ch == '\'') { - sc.SetState(SCE_AU3_STRING); - si = 2; } - else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) - { - sc.SetState(SCE_AU3_NUMBER); - ni = 0; - } - else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_AU3_KEYWORD);} - else if (IsAOperator(static_cast(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);} - else if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} - } - } //for (; sc.More(); sc.Forward()) - - //************************************* - // Colourize the last word correctly - //************************************* - if (sc.state == SCE_AU3_KEYWORD) - { - if (strcmp(s_save, "#cs")== 0 || strcmp(s_save, "#comments-start")== 0 ) - { - sc.ChangeState(SCE_AU3_COMMENTBLOCK); - sc.SetState(SCE_AU3_COMMENTBLOCK); - } - else if (keywords.InList(s_save)) { - sc.ChangeState(SCE_AU3_KEYWORD); - sc.SetState(SCE_AU3_KEYWORD); - } - else if (keywords2.InList(s_save)) { - sc.ChangeState(SCE_AU3_FUNCTION); - sc.SetState(SCE_AU3_FUNCTION); - } - else if (keywords3.InList(s_save)) { - sc.ChangeState(SCE_AU3_MACRO); - sc.SetState(SCE_AU3_MACRO); - } - else if (keywords5.InList(s_save)) { - sc.ChangeState(SCE_AU3_PREPROCESSOR); - sc.SetState(SCE_AU3_PREPROCESSOR); - } - else if (keywords6.InList(s_save)) { - sc.ChangeState(SCE_AU3_SPECIAL); - sc.SetState(SCE_AU3_SPECIAL); - } - else if (keywords7.InList(s_save) && sc.atLineEnd) { - sc.ChangeState(SCE_AU3_EXPAND); - sc.SetState(SCE_AU3_EXPAND); - } - else if (keywords8.InList(s_save)) { - sc.ChangeState(SCE_AU3_UDF); - sc.SetState(SCE_AU3_UDF); - } - else { - sc.ChangeState(SCE_AU3_DEFAULT); - sc.SetState(SCE_AU3_DEFAULT); - } - } - if (sc.state == SCE_AU3_SENT) - { - // Send key string ended - if (sc.chPrev == '}' && sc.ch != '}') - { - // set color to SENDKEY when valid sendkey .. else set back to regular string - char sk[100]; - // split {111 222} and return {111} and check if 222 is valid. - // if return code = 1 then invalid 222 so must be string - if (GetSendKey(s_save,sk)) - { - sc.ChangeState(SCE_AU3_STRING); - } - // if single char between {?} then its ok as sendkey for a single character - else if (strlen(sk) == 3) - { - sc.ChangeState(SCE_AU3_SENT); - } - // if sendkey {111} is in table then ok as sendkey - else if (keywords4.InList(sk)) - { - sc.ChangeState(SCE_AU3_SENT); - } - else - { - sc.ChangeState(SCE_AU3_STRING); - } - sc.SetState(SCE_AU3_STRING); - } - // check if next portion is again a sendkey - if (sc.atLineEnd) - { - sc.ChangeState(SCE_AU3_STRING); - sc.SetState(SCE_AU3_DEFAULT); - } - } - //************************************* - sc.Complete(); -} - -// -static bool IsStreamCommentStyle(int style) { - return style == SCE_AU3_COMMENT || style == SCE_AU3_COMMENTBLOCK; -} - -// -// Routine to find first none space on the current line and return its Style -// needed for comment lines not starting on pos 1 -static int GetStyleFirstWord(unsigned int szLine, Accessor &styler) -{ - int nsPos = styler.LineStart(szLine); - int nePos = styler.LineStart(szLine+1) - 1; - while (isspacechar(styler.SafeGetCharAt(nsPos)) && nsPos < nePos) - { - nsPos++; // skip to next char - - } // End While - return styler.StyleAt(nsPos); - -} // GetStyleFirstWord() - - -// -static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) -{ - int endPos = startPos + length; - // get settings from the config files for folding comments and preprocessor lines - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldInComment = styler.GetPropertyInt("fold.comment") == 2; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldpreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; - // Backtrack to previous line in case need to fix its fold status - int lineCurrent = styler.GetLine(startPos); - if (startPos > 0) { - if (lineCurrent > 0) { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); - } - } - // vars for style of previous/current/next lines - int style = GetStyleFirstWord(lineCurrent,styler); - int stylePrev = 0; - // find the first previous line without continuation character at the end - while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || - (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); - } - if (lineCurrent > 0) { - stylePrev = GetStyleFirstWord(lineCurrent-1,styler); - } - // vars for getting first word to check for keywords - bool FirstWordStart = false; - bool FirstWordEnd = false; - char szKeyword[11]=""; - int szKeywordlen = 0; - char szThen[5]=""; - int szThenlen = 0; - bool ThenFoundLast = false; - // var for indentlevel - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelNext = levelCurrent; - // - int visibleChars = 0; - char chNext = styler.SafeGetCharAt(startPos); - char chPrev = ' '; - // - for (int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - if (IsAWordChar(ch)) { - visibleChars++; - } - // get the syle for the current character neede to check in comment - int stylech = styler.StyleAt(i); - // get first word for the line for indent check max 9 characters - if (FirstWordStart && (!(FirstWordEnd))) { - if (!IsAWordChar(ch)) { - FirstWordEnd = true; - szKeyword[szKeywordlen] = '\0'; - } - else { - if (szKeywordlen < 10) { - szKeyword[szKeywordlen++] = static_cast(tolower(ch)); - } - } - } - // start the capture of the first word - if (!(FirstWordStart)) { - if (IsAWordChar(ch) || IsAWordStart(ch) || ch == ';') { - FirstWordStart = true; - szKeyword[szKeywordlen++] = static_cast(tolower(ch)); - } - } - // only process this logic when not in comment section - if (!(stylech == SCE_AU3_COMMENT)) { - if (ThenFoundLast) { - if (IsAWordChar(ch)) { - ThenFoundLast = false; - } - } - // find out if the word "then" is the last on a "if" line - if (FirstWordEnd && strcmp(szKeyword,"if") == 0) { - if (szThenlen == 4) { - szThen[0] = szThen[1]; - szThen[1] = szThen[2]; - szThen[2] = szThen[3]; - szThen[3] = static_cast(tolower(ch)); - if (strcmp(szThen,"then") == 0 ) { - ThenFoundLast = true; - } - } - else { - szThen[szThenlen++] = static_cast(tolower(ch)); - if (szThenlen == 5) { - szThen[4] = '\0'; - } - } - } - } - // End of Line found so process the information - if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { - // ************************** - // Folding logic for Keywords - // ************************** - // if a keyword is found on the current line and the line doesn't end with _ (continuation) - // and we are not inside a commentblock. - if (szKeywordlen > 0 && (!(chPrev == '_')) && - ((!(IsStreamCommentStyle(style)) || foldInComment)) ) { - szKeyword[szKeywordlen] = '\0'; - // only fold "if" last keyword is "then" (else its a one line if) - if (strcmp(szKeyword,"if") == 0 && ThenFoundLast) { - levelNext++; - } - // create new fold for these words - if (strcmp(szKeyword,"do") == 0 || strcmp(szKeyword,"for") == 0 || - strcmp(szKeyword,"func") == 0 || strcmp(szKeyword,"while") == 0|| - strcmp(szKeyword,"with") == 0 || strcmp(szKeyword,"#region") == 0 ) { - levelNext++; - } - // create double Fold for select&switch because Case will subtract one of the current level - if (strcmp(szKeyword,"select") == 0 || strcmp(szKeyword,"switch") == 0) { - levelNext++; - levelNext++; - } - // end the fold for these words before the current line - if (strcmp(szKeyword,"endfunc") == 0 || strcmp(szKeyword,"endif") == 0 || - strcmp(szKeyword,"next") == 0 || strcmp(szKeyword,"until") == 0 || - strcmp(szKeyword,"endwith") == 0 ||strcmp(szKeyword,"wend") == 0){ - levelNext--; - levelCurrent--; - } - // end the fold for these words before the current line and Start new fold - if (strcmp(szKeyword,"case") == 0 || strcmp(szKeyword,"else") == 0 || - strcmp(szKeyword,"elseif") == 0 ) { - levelCurrent--; - } - // end the double fold for this word before the current line - if (strcmp(szKeyword,"endselect") == 0 || strcmp(szKeyword,"endswitch") == 0 ) { - levelNext--; - levelNext--; - levelCurrent--; - levelCurrent--; - } - // end the fold for these words on the current line - if (strcmp(szKeyword,"#endregion") == 0 ) { - levelNext--; - } - } - // Preprocessor and Comment folding - int styleNext = GetStyleFirstWord(lineCurrent + 1,styler); - // ************************************* - // Folding logic for preprocessor blocks - // ************************************* - // process preprosessor line - if (foldpreprocessor && style == SCE_AU3_PREPROCESSOR) { - if (!(stylePrev == SCE_AU3_PREPROCESSOR) && (styleNext == SCE_AU3_PREPROCESSOR)) { - levelNext++; - } - // fold till the last line for normal comment lines - else if (stylePrev == SCE_AU3_PREPROCESSOR && !(styleNext == SCE_AU3_PREPROCESSOR)) { - levelNext--; - } - } - // ********************************* - // Folding logic for Comment blocks - // ********************************* - if (foldComment && IsStreamCommentStyle(style)) { - // Start of a comment block - if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) { - levelNext++; - } - // fold till the last line for normal comment lines - else if (IsStreamCommentStyle(stylePrev) - && !(styleNext == SCE_AU3_COMMENT) - && stylePrev == SCE_AU3_COMMENT - && style == SCE_AU3_COMMENT) { - levelNext--; - } - // fold till the one but last line for Blockcomment lines - else if (IsStreamCommentStyle(stylePrev) - && !(styleNext == SCE_AU3_COMMENTBLOCK) - && style == SCE_AU3_COMMENTBLOCK) { - levelNext--; - levelCurrent--; - } - } - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - // reset values for the next line - lineCurrent++; - stylePrev = style; - style = styleNext; - levelCurrent = levelNext; - visibleChars = 0; - // if the last character is an Underscore then don't reset since the line continues on the next line. - if (!(chPrev == '_')) { - szKeywordlen = 0; - szThenlen = 0; - FirstWordStart = false; - FirstWordEnd = false; - ThenFoundLast = false; - } - } - // save the last processed character - if (!isspacechar(ch)) { - chPrev = ch; - visibleChars++; - } - } -} - - -// - -static const char * const AU3WordLists[] = { - "#autoit keywords", - "#autoit functions", - "#autoit macros", - "#autoit Sent keys", - "#autoit Pre-processors", - "#autoit Special", - "#autoit Expand", - "#autoit UDF", - 0 -}; -LexerModule lmAU3(SCLEX_AU3, ColouriseAU3Doc, "au3", FoldAU3Doc , AU3WordLists); diff --git a/src/LexAVE.cxx b/src/LexAVE.cxx deleted file mode 100644 index 09b393343..000000000 --- a/src/LexAVE.cxx +++ /dev/null @@ -1,228 +0,0 @@ -// SciTE - Scintilla based Text Editor -/** @file LexAVE.cxx - ** Lexer for Avenue. - ** - ** Written by Alexey Yutkin . - **/ -// Copyright 1998-2002 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); -} -static inline bool IsEnumChar(const int ch) { - return (ch < 0x80) && (isalnum(ch)|| ch == '_'); -} -static inline bool IsANumberChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' ); -} - -inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -inline bool isAveOperator(char ch) { - if (isascii(ch) && isalnum(ch)) - return false; - // '.' left out as it is used to make up numbers - if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || - ch == '(' || ch == ')' || ch == '=' || - ch == '{' || ch == '}' || - ch == '[' || ch == ']' || ch == ';' || - ch == '<' || ch == '>' || ch == ',' || - ch == '.' ) - return true; - return false; -} - -static void ColouriseAveDoc( - unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - WordList &keywords6 = *keywordlists[5]; - - // Do not leak onto next line - if (initStyle == SCE_AVE_STRINGEOL) { - initStyle = SCE_AVE_DEFAULT; - } - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - if (sc.atLineEnd) { - // Update the line state, so it can be seen by next line - int currentLine = styler.GetLine(sc.currentPos); - styler.SetLineState(currentLine, 0); - } - if (sc.atLineStart && (sc.state == SCE_AVE_STRING)) { - // Prevent SCE_AVE_STRINGEOL from leaking back to previous line - sc.SetState(SCE_AVE_STRING); - } - - - // Determine if the current state should terminate. - if (sc.state == SCE_AVE_OPERATOR) { - sc.SetState(SCE_AVE_DEFAULT); - } else if (sc.state == SCE_AVE_NUMBER) { - if (!IsANumberChar(sc.ch)) { - sc.SetState(SCE_AVE_DEFAULT); - } - } else if (sc.state == SCE_AVE_ENUM) { - if (!IsEnumChar(sc.ch)) { - sc.SetState(SCE_AVE_DEFAULT); - } - } else if (sc.state == SCE_AVE_IDENTIFIER) { - if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { - char s[100]; - //sc.GetCurrent(s, sizeof(s)); - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(SCE_AVE_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_AVE_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_AVE_WORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_AVE_WORD4); - } else if (keywords5.InList(s)) { - sc.ChangeState(SCE_AVE_WORD5); - } else if (keywords6.InList(s)) { - sc.ChangeState(SCE_AVE_WORD6); - } - sc.SetState(SCE_AVE_DEFAULT); - } - } else if (sc.state == SCE_AVE_COMMENT) { - if (sc.atLineEnd) { - sc.SetState(SCE_AVE_DEFAULT); - } - } else if (sc.state == SCE_AVE_STRING) { - if (sc.ch == '\"') { - sc.ForwardSetState(SCE_AVE_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_AVE_STRINGEOL); - sc.ForwardSetState(SCE_AVE_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_AVE_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_AVE_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_AVE_IDENTIFIER); - } else if (sc.Match('\"')) { - sc.SetState(SCE_AVE_STRING); - } else if (sc.Match('\'')) { - sc.SetState(SCE_AVE_COMMENT); - sc.Forward(); - } else if (isAveOperator(static_cast(sc.ch))) { - sc.SetState(SCE_AVE_OPERATOR); - } else if (sc.Match('#')) { - sc.SetState(SCE_AVE_ENUM); - sc.Forward(); - } - } - } - sc.Complete(); -} - -static void FoldAveDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[], - Accessor &styler) { - unsigned int lengthDoc = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = static_cast(tolower(styler[startPos])); - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - int styleNext = styler.StyleAt(startPos); - char s[10]; - - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = static_cast(tolower(chNext)); - chNext = static_cast(tolower(styler.SafeGetCharAt(i + 1))); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (style == SCE_AVE_WORD) { - if (ch == 't' || ch == 'f' || ch == 'w' || ch == 'e') { - for (unsigned int j = 0; j < 6; j++) { - if (!iswordchar(styler[i + j])) { - break; - } - s[j] = static_cast(tolower(styler[i + j])); - s[j + 1] = '\0'; - } - - if ((strcmp(s, "then") == 0) || (strcmp(s, "for") == 0) || (strcmp(s, "while") == 0)) { - levelCurrent++; - } - if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0)) { - // Normally "elseif" and "then" will be on the same line and will cancel - // each other out. // As implemented, this does not support fold.at.else. - levelCurrent--; - } - } - } else if (style == SCE_AVE_OPERATOR) { - if (ch == '{' || ch == '(') { - levelCurrent++; - } else if (ch == '}' || ch == ')') { - levelCurrent--; - } - } - - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) { - lev |= SC_FOLDLEVELWHITEFLAG; - } - if ((levelCurrent > levelPrev) && (visibleChars > 0)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) { - visibleChars++; - } - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -LexerModule lmAVE(SCLEX_AVE, ColouriseAveDoc, "ave", FoldAveDoc); - diff --git a/src/LexAbaqus.cxx b/src/LexAbaqus.cxx deleted file mode 100644 index 10e8b76b1..000000000 --- a/src/LexAbaqus.cxx +++ /dev/null @@ -1,617 +0,0 @@ -// Scintilla source code edit control -/** @file LexABAQUS.cxx - ** Lexer for ABAQUS. Based on the lexer for APDL by Hadar Raz. - ** By Sergio Lucato. - ** Sort of completely rewritten by Gertjan Kloosterman - **/ -// The License.txt file describes the conditions under which this software may be distributed. - -// Code folding copyied and modified from LexBasic.cxx - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80 && (isalnum(ch) || (ch == '_'))); -} - -static inline bool IsAKeywordChar(const int ch) { - return (ch < 0x80 && (isalnum(ch) || (ch == '_') || (ch == ' '))); -} - -static inline bool IsASetChar(const int ch) { - return (ch < 0x80 && (isalnum(ch) || (ch == '_') || (ch == '.') || (ch == '-'))); -} - -static inline bool IsAnOperator(char ch) { - // '.' left out as it is used to make up numbers - if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || - ch == '(' || ch == ')' || ch == '=' || ch == '^' || - ch == '[' || ch == ']' || ch == '<' || ch == '&' || - ch == '>' || ch == ',' || ch == '|' || ch == '~' || - ch == '$' || ch == ':' || ch == '%') - return true; - return false; -} - -static void ColouriseABAQUSDoc(unsigned int startPos, int length, int initStyle, WordList*[] /* *keywordlists[] */, - Accessor &styler) { - enum localState { KW_LINE_KW, KW_LINE_COMMA, KW_LINE_PAR, KW_LINE_EQ, KW_LINE_VAL, \ - DAT_LINE_VAL, DAT_LINE_COMMA,\ - COMMENT_LINE,\ - ST_ERROR, LINE_END } state ; - - // Do not leak onto next line - state = LINE_END ; - initStyle = SCE_ABAQUS_DEFAULT; - StyleContext sc(startPos, length, initStyle, styler); - - // Things are actually quite simple - // we have commentlines - // keywordlines and datalines - // On a data line there will only be colouring of numbers - // a keyword line is constructed as - // *word,[ paramname[=paramvalue]]* - // if the line ends with a , the keyword line continues onto the new line - - for (; sc.More(); sc.Forward()) { - switch ( state ) { - case KW_LINE_KW : - if ( sc.atLineEnd ) { - // finished the line in keyword state, switch to LINE_END - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = LINE_END ; - } else if ( IsAKeywordChar(sc.ch) ) { - // nothing changes - state = KW_LINE_KW ; - } else if ( sc.ch == ',' ) { - // Well well we say a comma, arguments *MUST* follow - sc.SetState(SCE_ABAQUS_OPERATOR) ; - state = KW_LINE_COMMA ; - } else { - // Flag an error - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - // Done with processing - break ; - case KW_LINE_COMMA : - // acomma on a keywordline was seen - if ( IsAKeywordChar(sc.ch)) { - sc.SetState(SCE_ABAQUS_ARGUMENT) ; - state = KW_LINE_PAR ; - } else if ( sc.atLineEnd || (sc.ch == ',') ) { - // we remain in keyword mode - state = KW_LINE_COMMA ; - } else if ( sc.ch == ' ' ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = KW_LINE_COMMA ; - } else { - // Anything else constitutes an error - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - break ; - case KW_LINE_PAR : - if ( sc.atLineEnd ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = LINE_END ; - } else if ( IsAKeywordChar(sc.ch) || (sc.ch == '-') ) { - // remain in this state - state = KW_LINE_PAR ; - } else if ( sc.ch == ',' ) { - sc.SetState(SCE_ABAQUS_OPERATOR) ; - state = KW_LINE_COMMA ; - } else if ( sc.ch == '=' ) { - sc.SetState(SCE_ABAQUS_OPERATOR) ; - state = KW_LINE_EQ ; - } else { - // Anything else constitutes an error - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - break ; - case KW_LINE_EQ : - if ( sc.ch == ' ' ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - // remain in this state - state = KW_LINE_EQ ; - } else if ( IsADigit(sc.ch) || (sc.ch == '-') || (sc.ch == '.' && IsADigit(sc.chNext)) ) { - sc.SetState(SCE_ABAQUS_NUMBER) ; - state = KW_LINE_VAL ; - } else if ( IsAKeywordChar(sc.ch) ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = KW_LINE_VAL ; - } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) { - sc.SetState(SCE_ABAQUS_STRING) ; - state = KW_LINE_VAL ; - } else { - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - break ; - case KW_LINE_VAL : - if ( sc.atLineEnd ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = LINE_END ; - } else if ( IsASetChar(sc.ch) && (sc.state == SCE_ABAQUS_DEFAULT) ) { - // nothing changes - state = KW_LINE_VAL ; - } else if (( (IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') || - ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) && - (sc.state == SCE_ABAQUS_NUMBER)) { - // remain in number mode - state = KW_LINE_VAL ; - } else if (sc.state == SCE_ABAQUS_STRING) { - // accept everything until a closing quote - if ( sc.ch == '\'' || sc.ch == '\"' ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = KW_LINE_VAL ; - } - } else if ( sc.ch == ',' ) { - sc.SetState(SCE_ABAQUS_OPERATOR) ; - state = KW_LINE_COMMA ; - } else { - // anything else is an error - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - break ; - case DAT_LINE_VAL : - if ( sc.atLineEnd ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = LINE_END ; - } else if ( IsASetChar(sc.ch) && (sc.state == SCE_ABAQUS_DEFAULT) ) { - // nothing changes - state = DAT_LINE_VAL ; - } else if (( (IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') || - ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) && - (sc.state == SCE_ABAQUS_NUMBER)) { - // remain in number mode - state = DAT_LINE_VAL ; - } else if (sc.state == SCE_ABAQUS_STRING) { - // accept everything until a closing quote - if ( sc.ch == '\'' || sc.ch == '\"' ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = DAT_LINE_VAL ; - } - } else if ( sc.ch == ',' ) { - sc.SetState(SCE_ABAQUS_OPERATOR) ; - state = DAT_LINE_COMMA ; - } else { - // anything else is an error - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - break ; - case DAT_LINE_COMMA : - // a comma on a data line was seen - if ( sc.atLineEnd ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = LINE_END ; - } else if ( sc.ch == ' ' ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = DAT_LINE_COMMA ; - } else if (sc.ch == ',') { - sc.SetState(SCE_ABAQUS_OPERATOR) ; - state = DAT_LINE_COMMA ; - } else if ( IsADigit(sc.ch) || (sc.ch == '-')|| (sc.ch == '.' && IsADigit(sc.chNext)) ) { - sc.SetState(SCE_ABAQUS_NUMBER) ; - state = DAT_LINE_VAL ; - } else if ( IsAKeywordChar(sc.ch) ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = DAT_LINE_VAL ; - } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) { - sc.SetState(SCE_ABAQUS_STRING) ; - state = DAT_LINE_VAL ; - } else { - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - break ; - case COMMENT_LINE : - if ( sc.atLineEnd ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = LINE_END ; - } - break ; - case ST_ERROR : - if ( sc.atLineEnd ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = LINE_END ; - } - break ; - case LINE_END : - if ( sc.atLineEnd || sc.ch == ' ' ) { - // nothing changes - state = LINE_END ; - } else if ( sc.ch == '*' ) { - if ( sc.chNext == '*' ) { - state = COMMENT_LINE ; - sc.SetState(SCE_ABAQUS_COMMENT) ; - } else { - state = KW_LINE_KW ; - sc.SetState(SCE_ABAQUS_STARCOMMAND) ; - } - } else { - // it must be a data line, things are as if we are in DAT_LINE_COMMA - if ( sc.ch == ',' ) { - sc.SetState(SCE_ABAQUS_OPERATOR) ; - state = DAT_LINE_COMMA ; - } else if ( IsADigit(sc.ch) || (sc.ch == '-')|| (sc.ch == '.' && IsADigit(sc.chNext)) ) { - sc.SetState(SCE_ABAQUS_NUMBER) ; - state = DAT_LINE_VAL ; - } else if ( IsAKeywordChar(sc.ch) ) { - sc.SetState(SCE_ABAQUS_DEFAULT) ; - state = DAT_LINE_VAL ; - } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) { - sc.SetState(SCE_ABAQUS_STRING) ; - state = DAT_LINE_VAL ; - } else { - sc.SetState(SCE_ABAQUS_PROCESSOR) ; - state = ST_ERROR ; - } - } - break ; - } - } - sc.Complete(); -} - -//------------------------------------------------------------------------------ -// This copyied and modified from LexBasic.cxx -//------------------------------------------------------------------------------ - -/* Bits: - * 1 - whitespace - * 2 - operator - * 4 - identifier - * 8 - decimal digit - * 16 - hex digit - * 32 - bin digit - */ -static int character_classification[128] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 10, 6, - 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2, - 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4, - 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0 -}; - -static bool IsSpace(int c) { - return c < 128 && (character_classification[c] & 1); -} - -static bool IsIdentifier(int c) { - return c < 128 && (character_classification[c] & 4); -} - -static int LowerCase(int c) -{ - if (c >= 'A' && c <= 'Z') - return 'a' + c - 'A'; - return c; -} - -static int LineEnd(int line, Accessor &styler) -{ - const int docLines = styler.GetLine(styler.Length() - 1); // Available last line - int eol_pos ; - // if the line is the last line, the eol_pos is styler.Length() - // eol will contain a new line, or a virtual new line - if ( docLines == line ) - eol_pos = styler.Length() ; - else - eol_pos = styler.LineStart(line + 1) - 1; - return eol_pos ; -} - -static int LineStart(int line, Accessor &styler) -{ - return styler.LineStart(line) ; -} - -// LineType -// -// bits determines the line type -// 1 : data line -// 2 : only whitespace -// 3 : data line with only whitespace -// 4 : keyword line -// 5 : block open keyword line -// 6 : block close keyword line -// 7 : keyword line in error -// 8 : comment line -static int LineType(int line, Accessor &styler) { - int pos = LineStart(line, styler) ; - int eol_pos = LineEnd(line, styler) ; - - int c ; - char ch = ' '; - - int i = pos ; - while ( i < eol_pos ) { - c = styler.SafeGetCharAt(i); - ch = static_cast(LowerCase(c)); - // We can say something as soon as no whitespace - // was encountered - if ( !IsSpace(c) ) - break ; - i++ ; - } - - if ( i >= eol_pos ) { - // This is a whitespace line, currently - // classifies as data line - return 3 ; - } - - if ( ch != '*' ) { - // This is a data line - return 1 ; - } - - if ( i == eol_pos - 1 ) { - // Only a single *, error but make keyword line - return 4+3 ; - } - - // This means we can have a second character - // if that is also a * this means a comment - // otherwise it is a keyword. - c = styler.SafeGetCharAt(i+1); - ch = static_cast(LowerCase(c)); - if ( ch == '*' ) { - return 8 ; - } - - // At this point we know this is a keyword line - // the character at position i is a * - // it is not a comment line - char word[256] ; - int wlen = 0; - - word[wlen] = '*' ; - wlen++ ; - - i++ ; - while ( (i < eol_pos) && (wlen < 255) ) { - c = styler.SafeGetCharAt(i); - ch = static_cast(LowerCase(c)); - - if ( (!IsSpace(c)) && (!IsIdentifier(c)) ) - break ; - - if ( IsIdentifier(c) ) { - word[wlen] = ch ; - wlen++ ; - } - - i++ ; - } - - word[wlen] = 0 ; - - // Make a comparison - if ( !strcmp(word, "*step") || - !strcmp(word, "*part") || - !strcmp(word, "*instance") || - !strcmp(word, "*assembly")) { - return 4+1 ; - } - - if ( !strcmp(word, "*endstep") || - !strcmp(word, "*endpart") || - !strcmp(word, "*endinstance") || - !strcmp(word, "*endassembly")) { - return 4+2 ; - } - - return 4 ; -} - -static void SafeSetLevel(int line, int level, Accessor &styler) -{ - if ( line < 0 ) - return ; - - int mask = ((~SC_FOLDLEVELHEADERFLAG) | (~SC_FOLDLEVELWHITEFLAG)); - - if ( (level & mask) < 0 ) - return ; - - if ( styler.LevelAt(line) != level ) - styler.SetLevel(line, level) ; -} - -static void FoldABAQUSDoc(unsigned int startPos, int length, int, -WordList *[], Accessor &styler) { - int startLine = styler.GetLine(startPos) ; - int endLine = styler.GetLine(startPos+length-1) ; - - // bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - // We want to deal with all the cases - // To know the correct indentlevel, we need to look back to the - // previous command line indentation level - // order of formatting keyline datalines commentlines - int beginData = -1 ; - int beginComment = -1 ; - int prvKeyLine = startLine ; - int prvKeyLineTp = 0 ; - - // Scan until we find the previous keyword line - // this will give us the level reference that we need - while ( prvKeyLine > 0 ) { - prvKeyLine-- ; - prvKeyLineTp = LineType(prvKeyLine, styler) ; - if ( prvKeyLineTp & 4 ) - break ; - } - - // Determine the base line level of all lines following - // the previous keyword - // new keyword lines are placed on this level - //if ( prvKeyLineTp & 4 ) { - int level = styler.LevelAt(prvKeyLine) & ~SC_FOLDLEVELHEADERFLAG ; - //} - - // uncomment line below if weird behaviour continues - prvKeyLine = -1 ; - - // Now start scanning over the lines. - for ( int line = startLine; line <= endLine; line++ ) { - int lineType = LineType(line, styler) ; - - // Check for comment line - if ( lineType == 8 ) { - if ( beginComment < 0 ) { - beginComment = line ; - } - } - - // Check for data line - if ( (lineType == 1) || (lineType == 3) ) { - if ( beginData < 0 ) { - if ( beginComment >= 0 ) { - beginData = beginComment ; - } else { - beginData = line ; - } - } - beginComment = -1 ; - } - - // Check for keywordline. - // As soon as a keyword line is encountered, we can set the - // levels of everything from the previous keyword line to this one - if ( lineType & 4 ) { - // this is a keyword, we can now place the previous keyword - // all its data lines and the remainder - - // Write comments and data line - if ( beginComment < 0 ) { - beginComment = line ; - } - - if ( beginData < 0 ) { - beginData = beginComment ; - if ( prvKeyLineTp != 5 ) - SafeSetLevel(prvKeyLine, level, styler) ; - else - SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; - } else { - SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; - } - - int datLevel = level + 1 ; - if ( !(prvKeyLineTp & 4) ) { - datLevel = level ; - } - - for ( int ll = beginData; ll < beginComment; ll++ ) - SafeSetLevel(ll, datLevel, styler) ; - - // The keyword we just found is going to be written at another level - // if we have a type 5 and type 6 - if ( prvKeyLineTp == 5 ) { - level += 1 ; - } - - if ( prvKeyLineTp == 6 ) { - level -= 1 ; - if ( level < 0 ) { - level = 0 ; - } - } - - for ( int lll = beginComment; lll < line; lll++ ) - SafeSetLevel(lll, level, styler) ; - - // wrap and reset - beginComment = -1 ; - beginData = -1 ; - prvKeyLine = line ; - prvKeyLineTp = lineType ; - } - - } - - if ( beginComment < 0 ) { - beginComment = endLine + 1 ; - } else { - // We need to find out whether this comment block is followed by - // a data line or a keyword line - const int docLines = styler.GetLine(styler.Length() - 1); - - for ( int line = endLine + 1; line <= docLines; line++ ) { - int lineType = LineType(line, styler) ; - - if ( lineType != 8 ) { - if ( !(lineType & 4) ) { - beginComment = endLine + 1 ; - } - break ; - } - } - } - - if ( beginData < 0 ) { - beginData = beginComment ; - if ( prvKeyLineTp != 5 ) - SafeSetLevel(prvKeyLine, level, styler) ; - else - SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; - } else { - SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; - } - - int datLevel = level + 1 ; - if ( !(prvKeyLineTp & 4) ) { - datLevel = level ; - } - - for ( int ll = beginData; ll < beginComment; ll++ ) - SafeSetLevel(ll, datLevel, styler) ; - - if ( prvKeyLineTp == 5 ) { - level += 1 ; - } - - if ( prvKeyLineTp == 6 ) { - level -= 1 ; - } - for ( int m = beginComment; m <= endLine; m++ ) - SafeSetLevel(m, level, styler) ; -} - -static const char * const abaqusWordListDesc[] = { - "processors", - "commands", - "slashommands", - "starcommands", - "arguments", - "functions", - 0 -}; - -LexerModule lmAbaqus(SCLEX_ABAQUS, ColouriseABAQUSDoc, "abaqus", FoldABAQUSDoc, abaqusWordListDesc); diff --git a/src/LexAda.cxx b/src/LexAda.cxx deleted file mode 100644 index 654bfbeba..000000000 --- a/src/LexAda.cxx +++ /dev/null @@ -1,525 +0,0 @@ -// Scintilla source code edit control -/** @file LexAda.cxx - ** Lexer for Ada 95 - **/ -// Copyright 2002 by Sergey Koshcheyev -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include - -#include - -#include "Platform.h" - -#include "Accessor.h" -#include "StyleContext.h" -#include "PropSet.h" -#include "KeyWords.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/* - * Interface - */ - -static void ColouriseDocument( - unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler); - -static const char * const adaWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmAda(SCLEX_ADA, ColouriseDocument, "ada", NULL, adaWordListDesc); - -/* - * Implementation - */ - -// Functions that have apostropheStartsAttribute as a parameter set it according to whether -// an apostrophe encountered after processing the current token will start an attribute or -// a character literal. -static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL); -static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute); -static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute); - -static inline bool IsDelimiterCharacter(int ch); -static inline bool IsNumberStartCharacter(int ch); -static inline bool IsNumberCharacter(int ch); -static inline bool IsSeparatorOrDelimiterCharacter(int ch); -static bool IsValidIdentifier(const std::string& identifier); -static bool IsValidNumber(const std::string& number); -static inline bool IsWordStartCharacter(int ch); -static inline bool IsWordCharacter(int ch); - -static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute) { - apostropheStartsAttribute = true; - - sc.SetState(SCE_ADA_CHARACTER); - - // Skip the apostrophe and one more character (so that '' is shown as non-terminated and ''' - // is handled correctly) - sc.Forward(); - sc.Forward(); - - ColouriseContext(sc, '\'', SCE_ADA_CHARACTEREOL); -} - -static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL) { - while (!sc.atLineEnd && !sc.Match(chEnd)) { - sc.Forward(); - } - - if (!sc.atLineEnd) { - sc.ForwardSetState(SCE_ADA_DEFAULT); - } else { - sc.ChangeState(stateEOL); - } -} - -static void ColouriseComment(StyleContext& sc, bool& /*apostropheStartsAttribute*/) { - // Apostrophe meaning is not changed, but the parameter is present for uniformity - - sc.SetState(SCE_ADA_COMMENTLINE); - - while (!sc.atLineEnd) { - sc.Forward(); - } -} - -static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) { - apostropheStartsAttribute = sc.Match (')'); - sc.SetState(SCE_ADA_DELIMITER); - sc.ForwardSetState(SCE_ADA_DEFAULT); -} - -static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) { - apostropheStartsAttribute = false; - - sc.SetState(SCE_ADA_LABEL); - - // Skip "<<" - sc.Forward(); - sc.Forward(); - - std::string identifier; - - while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) { - identifier += static_cast(tolower(sc.ch)); - sc.Forward(); - } - - // Skip ">>" - if (sc.Match('>', '>')) { - sc.Forward(); - sc.Forward(); - } else { - sc.ChangeState(SCE_ADA_ILLEGAL); - } - - // If the name is an invalid identifier or a keyword, then make it invalid label - if (!IsValidIdentifier(identifier) || keywords.InList(identifier.c_str())) { - sc.ChangeState(SCE_ADA_ILLEGAL); - } - - sc.SetState(SCE_ADA_DEFAULT); - -} - -static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) { - apostropheStartsAttribute = true; - - std::string number; - sc.SetState(SCE_ADA_NUMBER); - - // Get all characters up to a delimiter or a separator, including points, but excluding - // double points (ranges). - while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) { - number += static_cast(sc.ch); - sc.Forward(); - } - - // Special case: exponent with sign - if ((sc.chPrev == 'e' || sc.chPrev == 'E') && - (sc.ch == '+' || sc.ch == '-')) { - number += static_cast(sc.ch); - sc.Forward (); - - while (!IsSeparatorOrDelimiterCharacter(sc.ch)) { - number += static_cast(sc.ch); - sc.Forward(); - } - } - - if (!IsValidNumber(number)) { - sc.ChangeState(SCE_ADA_ILLEGAL); - } - - sc.SetState(SCE_ADA_DEFAULT); -} - -static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute) { - apostropheStartsAttribute = true; - - sc.SetState(SCE_ADA_STRING); - sc.Forward(); - - ColouriseContext(sc, '"', SCE_ADA_STRINGEOL); -} - -static void ColouriseWhiteSpace(StyleContext& sc, bool& /*apostropheStartsAttribute*/) { - // Apostrophe meaning is not changed, but the parameter is present for uniformity - sc.SetState(SCE_ADA_DEFAULT); - sc.ForwardSetState(SCE_ADA_DEFAULT); -} - -static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) { - apostropheStartsAttribute = true; - sc.SetState(SCE_ADA_IDENTIFIER); - - std::string word; - - while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) { - word += static_cast(tolower(sc.ch)); - sc.Forward(); - } - - if (!IsValidIdentifier(word)) { - sc.ChangeState(SCE_ADA_ILLEGAL); - - } else if (keywords.InList(word.c_str())) { - sc.ChangeState(SCE_ADA_WORD); - - if (word != "all") { - apostropheStartsAttribute = false; - } - } - - sc.SetState(SCE_ADA_DEFAULT); -} - -// -// ColouriseDocument -// - -static void ColouriseDocument( - unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) { - WordList &keywords = *keywordlists[0]; - - StyleContext sc(startPos, length, initStyle, styler); - - int lineCurrent = styler.GetLine(startPos); - bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0; - - while (sc.More()) { - if (sc.atLineEnd) { - // Go to the next line - sc.Forward(); - lineCurrent++; - - // Remember the line state for future incremental lexing - styler.SetLineState(lineCurrent, apostropheStartsAttribute); - - // Don't continue any styles on the next line - sc.SetState(SCE_ADA_DEFAULT); - } - - // Comments - if (sc.Match('-', '-')) { - ColouriseComment(sc, apostropheStartsAttribute); - - // Strings - } else if (sc.Match('"')) { - ColouriseString(sc, apostropheStartsAttribute); - - // Characters - } else if (sc.Match('\'') && !apostropheStartsAttribute) { - ColouriseCharacter(sc, apostropheStartsAttribute); - - // Labels - } else if (sc.Match('<', '<')) { - ColouriseLabel(sc, keywords, apostropheStartsAttribute); - - // Whitespace - } else if (IsASpace(sc.ch)) { - ColouriseWhiteSpace(sc, apostropheStartsAttribute); - - // Delimiters - } else if (IsDelimiterCharacter(sc.ch)) { - ColouriseDelimiter(sc, apostropheStartsAttribute); - - // Numbers - } else if (IsADigit(sc.ch) || sc.ch == '#') { - ColouriseNumber(sc, apostropheStartsAttribute); - - // Keywords or identifiers - } else { - ColouriseWord(sc, keywords, apostropheStartsAttribute); - } - } - - sc.Complete(); -} - -static inline bool IsDelimiterCharacter(int ch) { - switch (ch) { - case '&': - case '\'': - case '(': - case ')': - case '*': - case '+': - case ',': - case '-': - case '.': - case '/': - case ':': - case ';': - case '<': - case '=': - case '>': - case '|': - return true; - default: - return false; - } -} - -static inline bool IsNumberCharacter(int ch) { - return IsNumberStartCharacter(ch) || - ch == '_' || - ch == '.' || - ch == '#' || - (ch >= 'a' && ch <= 'f') || - (ch >= 'A' && ch <= 'F'); -} - -static inline bool IsNumberStartCharacter(int ch) { - return IsADigit(ch); -} - -static inline bool IsSeparatorOrDelimiterCharacter(int ch) { - return IsASpace(ch) || IsDelimiterCharacter(ch); -} - -static bool IsValidIdentifier(const std::string& identifier) { - // First character can't be '_', so initialize the flag to true - bool lastWasUnderscore = true; - - size_t length = identifier.length(); - - // Zero-length identifiers are not valid (these can occur inside labels) - if (length == 0) { - return false; - } - - // Check for valid character at the start - if (!IsWordStartCharacter(identifier[0])) { - return false; - } - - // Check for only valid characters and no double underscores - for (size_t i = 0; i < length; i++) { - if (!IsWordCharacter(identifier[i]) || - (identifier[i] == '_' && lastWasUnderscore)) { - return false; - } - lastWasUnderscore = identifier[i] == '_'; - } - - // Check for underscore at the end - if (lastWasUnderscore == true) { - return false; - } - - // All checks passed - return true; -} - -static bool IsValidNumber(const std::string& number) { - size_t hashPos = number.find("#"); - bool seenDot = false; - - size_t i = 0; - size_t length = number.length(); - - if (length == 0) - return false; // Just in case - - // Decimal number - if (hashPos == std::string::npos) { - bool canBeSpecial = false; - - for (; i < length; i++) { - if (number[i] == '_') { - if (!canBeSpecial) { - return false; - } - canBeSpecial = false; - } else if (number[i] == '.') { - if (!canBeSpecial || seenDot) { - return false; - } - canBeSpecial = false; - seenDot = true; - } else if (IsADigit(number[i])) { - canBeSpecial = true; - } else { - break; - } - } - - if (!canBeSpecial) - return false; - } else { - // Based number - bool canBeSpecial = false; - int base = 0; - - // Parse base - for (; i < length; i++) { - int ch = number[i]; - if (ch == '_') { - if (!canBeSpecial) - return false; - canBeSpecial = false; - } else if (IsADigit(ch)) { - base = base * 10 + (ch - '0'); - if (base > 16) - return false; - canBeSpecial = true; - } else if (ch == '#' && canBeSpecial) { - break; - } else { - return false; - } - } - - if (base < 2) - return false; - if (i == length) - return false; - - i++; // Skip over '#' - - // Parse number - canBeSpecial = false; - - for (; i < length; i++) { - int ch = tolower(number[i]); - - if (ch == '_') { - if (!canBeSpecial) { - return false; - } - canBeSpecial = false; - - } else if (ch == '.') { - if (!canBeSpecial || seenDot) { - return false; - } - canBeSpecial = false; - seenDot = true; - - } else if (IsADigit(ch)) { - if (ch - '0' >= base) { - return false; - } - canBeSpecial = true; - - } else if (ch >= 'a' && ch <= 'f') { - if (ch - 'a' + 10 >= base) { - return false; - } - canBeSpecial = true; - - } else if (ch == '#' && canBeSpecial) { - break; - - } else { - return false; - } - } - - if (i == length) { - return false; - } - - i++; - } - - // Exponent (optional) - if (i < length) { - if (number[i] != 'e' && number[i] != 'E') - return false; - - i++; // Move past 'E' - - if (i == length) { - return false; - } - - if (number[i] == '+') - i++; - else if (number[i] == '-') { - if (seenDot) { - i++; - } else { - return false; // Integer literals should not have negative exponents - } - } - - if (i == length) { - return false; - } - - bool canBeSpecial = false; - - for (; i < length; i++) { - if (number[i] == '_') { - if (!canBeSpecial) { - return false; - } - canBeSpecial = false; - } else if (IsADigit(number[i])) { - canBeSpecial = true; - } else { - return false; - } - } - - if (!canBeSpecial) - return false; - } - - // if i == length, number was parsed successfully. - return i == length; -} - -static inline bool IsWordCharacter(int ch) { - return IsWordStartCharacter(ch) || IsADigit(ch); -} - -static inline bool IsWordStartCharacter(int ch) { - return (isascii(ch) && isalpha(ch)) || ch == '_'; -} diff --git a/src/LexAsm.cxx b/src/LexAsm.cxx deleted file mode 100644 index 17c938420..000000000 --- a/src/LexAsm.cxx +++ /dev/null @@ -1,180 +0,0 @@ -// Scintilla source code edit control -/** @file LexAsm.cxx - ** Lexer for Assembler, just for the MASM syntax - ** Written by The Black Horus - ** Enhancements and NASM stuff by Kein-Hong Man, 2003-10 - ** SCE_ASM_COMMENTBLOCK and SCE_ASM_CHARACTER are for future GNU as colouring - **/ -// Copyright 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || - ch == '_' || ch == '?'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' || - ch == '%' || ch == '@' || ch == '$' || ch == '?'); -} - -static inline bool IsAsmOperator(const int ch) { - if ((ch < 0x80) && (isalnum(ch))) - return false; - // '.' left out as it is used to make up numbers - if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || - ch == '(' || ch == ')' || ch == '=' || ch == '^' || - ch == '[' || ch == ']' || ch == '<' || ch == '&' || - ch == '>' || ch == ',' || ch == '|' || ch == '~' || - ch == '%' || ch == ':') - return true; - return false; -} - -static void ColouriseAsmDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &cpuInstruction = *keywordlists[0]; - WordList &mathInstruction = *keywordlists[1]; - WordList ®isters = *keywordlists[2]; - WordList &directive = *keywordlists[3]; - WordList &directiveOperand = *keywordlists[4]; - WordList &extInstruction = *keywordlists[5]; - - // Do not leak onto next line - if (initStyle == SCE_ASM_STRINGEOL) - initStyle = SCE_ASM_DEFAULT; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) - { - - // Prevent SCE_ASM_STRINGEOL from leaking back to previous line - if (sc.atLineStart && (sc.state == SCE_ASM_STRING)) { - sc.SetState(SCE_ASM_STRING); - } else if (sc.atLineStart && (sc.state == SCE_ASM_CHARACTER)) { - sc.SetState(SCE_ASM_CHARACTER); - } - - // Handle line continuation generically. - if (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_ASM_OPERATOR) { - if (!IsAsmOperator(sc.ch)) { - sc.SetState(SCE_ASM_DEFAULT); - } - }else if (sc.state == SCE_ASM_NUMBER) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_ASM_DEFAULT); - } - } else if (sc.state == SCE_ASM_IDENTIFIER) { - if (!IsAWordChar(sc.ch) ) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - - if (cpuInstruction.InList(s)) { - sc.ChangeState(SCE_ASM_CPUINSTRUCTION); - } else if (mathInstruction.InList(s)) { - sc.ChangeState(SCE_ASM_MATHINSTRUCTION); - } else if (registers.InList(s)) { - sc.ChangeState(SCE_ASM_REGISTER); - } else if (directive.InList(s)) { - sc.ChangeState(SCE_ASM_DIRECTIVE); - } else if (directiveOperand.InList(s)) { - sc.ChangeState(SCE_ASM_DIRECTIVEOPERAND); - } else if (extInstruction.InList(s)) { - sc.ChangeState(SCE_ASM_EXTINSTRUCTION); - } - sc.SetState(SCE_ASM_DEFAULT); - } - } - else if (sc.state == SCE_ASM_COMMENT ) { - if (sc.atLineEnd) { - sc.SetState(SCE_ASM_DEFAULT); - } - } else if (sc.state == SCE_ASM_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_ASM_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_ASM_STRINGEOL); - sc.ForwardSetState(SCE_ASM_DEFAULT); - } - } else if (sc.state == SCE_ASM_CHARACTER) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_ASM_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_ASM_STRINGEOL); - sc.ForwardSetState(SCE_ASM_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_ASM_DEFAULT) { - if (sc.ch == ';'){ - sc.SetState(SCE_ASM_COMMENT); - } else if (isascii(sc.ch) && (isdigit(sc.ch) || (sc.ch == '.' && isascii(sc.chNext) && isdigit(sc.chNext)))) { - sc.SetState(SCE_ASM_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_ASM_IDENTIFIER); - } else if (sc.ch == '\"') { - sc.SetState(SCE_ASM_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_ASM_CHARACTER); - } else if (IsAsmOperator(sc.ch)) { - sc.SetState(SCE_ASM_OPERATOR); - } - } - - } - sc.Complete(); -} - -static const char * const asmWordListDesc[] = { - "CPU instructions", - "FPU instructions", - "Registers", - "Directives", - "Directive operands", - "Extended instructions", - 0 -}; - -LexerModule lmAsm(SCLEX_ASM, ColouriseAsmDoc, "asm", 0, asmWordListDesc); - diff --git a/src/LexAsn1.cxx b/src/LexAsn1.cxx deleted file mode 100644 index 36f1d5dc2..000000000 --- a/src/LexAsn1.cxx +++ /dev/null @@ -1,185 +0,0 @@ -// Scintilla source code edit control -/** @file LexAsn1.cxx - ** Lexer for ASN.1 - **/ -// Copyright 2004 by Herr Pfarrer rpfarrer yahoo de -// Last Updated: 20/07/2004 -// The License.txt file describes the conditions under which this software may be distributed. -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// Some char test functions -static bool isAsn1Number(int ch) -{ - return (ch >= '0' && ch <= '9'); -} - -static bool isAsn1Letter(int ch) -{ - return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); -} - -static bool isAsn1Char(int ch) -{ - return (ch == '-' ) || isAsn1Number(ch) || isAsn1Letter (ch); -} - -// -// Function determining the color of a given code portion -// Based on a "state" -// -static void ColouriseAsn1Doc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[], Accessor &styler) -{ - // The keywords - WordList &Keywords = *keywordLists[0]; - WordList &Attributes = *keywordLists[1]; - WordList &Descriptors = *keywordLists[2]; - WordList &Types = *keywordLists[3]; - - // Parse the whole buffer character by character using StyleContext - StyleContext sc(startPos, length, initStyle, styler); - for (; sc.More(); sc.Forward()) - { - // The state engine - switch (sc.state) - { - case SCE_ASN1_DEFAULT: // Plain characters -asn1_default: - if (sc.ch == '-' && sc.chNext == '-') - // A comment begins here - sc.SetState(SCE_ASN1_COMMENT); - else if (sc.ch == '"') - // A string begins here - sc.SetState(SCE_ASN1_STRING); - else if (isAsn1Number (sc.ch)) - // A number starts here (identifier should start with a letter in ASN.1) - sc.SetState(SCE_ASN1_SCALAR); - else if (isAsn1Char (sc.ch)) - // An identifier starts here (identifier always start with a letter) - sc.SetState(SCE_ASN1_IDENTIFIER); - else if (sc.ch == ':') - // A ::= operator starts here - sc.SetState(SCE_ASN1_OPERATOR); - break; - case SCE_ASN1_COMMENT: // A comment - if (sc.ch == '\r' || sc.ch == '\n') - // A comment ends here - sc.SetState(SCE_ASN1_DEFAULT); - break; - case SCE_ASN1_IDENTIFIER: // An identifier (keyword, attribute, descriptor or type) - if (!isAsn1Char (sc.ch)) - { - // The end of identifier is here: we can look for it in lists by now and change its state - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if (Keywords.InList(s)) - // It's a keyword, change its state - sc.ChangeState(SCE_ASN1_KEYWORD); - else if (Attributes.InList(s)) - // It's an attribute, change its state - sc.ChangeState(SCE_ASN1_ATTRIBUTE); - else if (Descriptors.InList(s)) - // It's a descriptor, change its state - sc.ChangeState(SCE_ASN1_DESCRIPTOR); - else if (Types.InList(s)) - // It's a type, change its state - sc.ChangeState(SCE_ASN1_TYPE); - - // Set to default now - sc.SetState(SCE_ASN1_DEFAULT); - } - break; - case SCE_ASN1_STRING: // A string delimited by "" - if (sc.ch == '"') - { - // A string ends here - sc.ForwardSetState(SCE_ASN1_DEFAULT); - - // To correctly manage a char sticking to the string quote - goto asn1_default; - } - break; - case SCE_ASN1_SCALAR: // A plain number - if (!isAsn1Number (sc.ch)) - // A number ends here - sc.SetState(SCE_ASN1_DEFAULT); - break; - case SCE_ASN1_OPERATOR: // The affectation operator ::= and wath follows (eg: ::= { org 6 } OID or ::= 12 trap) - if (sc.ch == '{') - { - // An OID definition starts here: enter the sub loop - for (; sc.More(); sc.Forward()) - { - if (isAsn1Number (sc.ch) && (!isAsn1Char (sc.chPrev) || isAsn1Number (sc.chPrev))) - // The OID number is highlighted - sc.SetState(SCE_ASN1_OID); - else if (isAsn1Char (sc.ch)) - // The OID parent identifier is plain - sc.SetState(SCE_ASN1_IDENTIFIER); - else - sc.SetState(SCE_ASN1_DEFAULT); - - if (sc.ch == '}') - // Here ends the OID and the operator sub loop: go back to main loop - break; - } - } - else if (isAsn1Number (sc.ch)) - { - // A trap number definition starts here: enter the sub loop - for (; sc.More(); sc.Forward()) - { - if (isAsn1Number (sc.ch)) - // The trap number is highlighted - sc.SetState(SCE_ASN1_OID); - else - { - // The number ends here: go back to main loop - sc.SetState(SCE_ASN1_DEFAULT); - break; - } - } - } - else if (sc.ch != ':' && sc.ch != '=' && sc.ch != ' ') - // The operator doesn't imply an OID definition nor a trap, back to main loop - goto asn1_default; // To be sure to handle actually the state change - break; - } - } - sc.Complete(); -} - -static void FoldAsn1Doc(unsigned int, int, int, WordList *[], Accessor &styler) -{ - // No folding enabled, no reason to continue... - if( styler.GetPropertyInt("fold") == 0 ) - return; - - // No folding implemented: doesn't make sense for ASN.1 -} - -static const char * const asn1WordLists[] = { - "Keywords", - "Attributes", - "Descriptors", - "Types", - 0, }; - - -LexerModule lmAns1(SCLEX_ASN1, ColouriseAsn1Doc, "asn1", FoldAsn1Doc, asn1WordLists); diff --git a/src/LexBaan.cxx b/src/LexBaan.cxx deleted file mode 100644 index a6847db71..000000000 --- a/src/LexBaan.cxx +++ /dev/null @@ -1,193 +0,0 @@ -// Scintilla source code edit control -/** @file LexBaan.cxx - ** Lexer for Baan. - ** Based heavily on LexCPP.cxx - **/ -// Copyright 2001- by Vamsi Potluru & Praveen Ambekar -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '$' || ch == ':'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static void ColouriseBaanDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; - - if (initStyle == SCE_BAAN_STRINGEOL) // Does not leak onto next line - initStyle = SCE_BAAN_DEFAULT; - - int visibleChars = 0; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.state == SCE_BAAN_OPERATOR) { - sc.SetState(SCE_BAAN_DEFAULT); - } else if (sc.state == SCE_BAAN_NUMBER) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_BAAN_DEFAULT); - } - } else if (sc.state == SCE_BAAN_IDENTIFIER) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(SCE_BAAN_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_BAAN_WORD2); - } - sc.SetState(SCE_BAAN_DEFAULT); - } - } else if (sc.state == SCE_BAAN_PREPROCESSOR) { - if (stylingWithinPreprocessor) { - if (IsASpace(sc.ch)) { - sc.SetState(SCE_BAAN_DEFAULT); - } - } else { - if (sc.atLineEnd && (sc.chNext != '^')) { - sc.SetState(SCE_BAAN_DEFAULT); - } - } - } else if (sc.state == SCE_BAAN_COMMENT) { - if (sc.atLineEnd) { - sc.SetState(SCE_BAAN_DEFAULT); - } - } else if (sc.state == SCE_BAAN_COMMENTDOC) { - if (sc.MatchIgnoreCase("enddllusage")) { - for (unsigned int i = 0; i < 10; i++){ - sc.Forward(); - } - sc.ForwardSetState(SCE_BAAN_DEFAULT); - } - } else if (sc.state == SCE_BAAN_STRING) { - if (sc.ch == '\"') { - sc.ForwardSetState(SCE_BAAN_DEFAULT); - } else if ((sc.atLineEnd) && (sc.chNext != '^')) { - sc.ChangeState(SCE_BAAN_STRINGEOL); - sc.ForwardSetState(SCE_C_DEFAULT); - visibleChars = 0; - } - } - - if (sc.state == SCE_BAAN_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_BAAN_NUMBER); - } else if (sc.MatchIgnoreCase("dllusage")){ - sc.SetState(SCE_BAAN_COMMENTDOC); - do { - sc.Forward(); - } while ((!sc.atLineEnd) && sc.More()); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_BAAN_IDENTIFIER); - } else if (sc.Match('|')){ - sc.SetState(SCE_BAAN_COMMENT); - } else if (sc.ch == '\"') { - sc.SetState(SCE_BAAN_STRING); - } else if (sc.ch == '#' && visibleChars == 0) { - // Preprocessor commands are alone on their line - sc.SetState(SCE_BAAN_PREPROCESSOR); - // Skip whitespace between # and preprocessor word - do { - sc.Forward(); - } while (IsASpace(sc.ch) && sc.More()); - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_BAAN_OPERATOR); - } - } - if (sc.atLineEnd) { - // Reset states to begining of colourise so no surprises - // if different sets of lines lexed. - visibleChars = 0; - } - if (!IsASpace(sc.ch)) { - visibleChars++; - } - } - sc.Complete(); -} - -static void FoldBaanDoc(unsigned int startPos, int length, int initStyle, WordList *[], - Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && - (style == SCE_BAAN_COMMENT || style == SCE_BAAN_COMMENTDOC)) { - if (style != stylePrev) { - levelCurrent++; - } else if ((style != styleNext) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelCurrent--; - } - } - if (style == SCE_BAAN_OPERATOR) { - if (ch == '{') { - levelCurrent++; - } else if (ch == '}') { - levelCurrent--; - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -LexerModule lmBaan(SCLEX_BAAN, ColouriseBaanDoc, "baan", FoldBaanDoc); diff --git a/src/LexBash.cxx b/src/LexBash.cxx deleted file mode 100644 index 1f97e4829..000000000 --- a/src/LexBash.cxx +++ /dev/null @@ -1,521 +0,0 @@ -// Scintilla source code edit control -/** @file LexBash.cxx - ** Lexer for Bash. - **/ -// Copyright 2004-2008 by Neil Hodgson -// Adapted from LexPerl by Kein-Hong Man 2004 -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "CharacterSet.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#define HERE_DELIM_MAX 256 - -// define this if you want 'invalid octals' to be marked as errors -// usually, this is not a good idea, permissive lexing is better -#undef PEDANTIC_OCTAL - -#define BASH_BASE_ERROR 65 -#define BASH_BASE_DECIMAL 66 -#define BASH_BASE_HEX 67 -#ifdef PEDANTIC_OCTAL -#define BASH_BASE_OCTAL 68 -#define BASH_BASE_OCTAL_ERROR 69 -#endif - -static inline int translateBashDigit(int ch) { - if (ch >= '0' && ch <= '9') { - return ch - '0'; - } else if (ch >= 'a' && ch <= 'z') { - return ch - 'a' + 10; - } else if (ch >= 'A' && ch <= 'Z') { - return ch - 'A' + 36; - } else if (ch == '@') { - return 62; - } else if (ch == '_') { - return 63; - } - return BASH_BASE_ERROR; -} - -static inline int getBashNumberBase(char *s) { - int i = 0; - int base = 0; - while (*s) { - base = base * 10 + (*s++ - '0'); - i++; - } - if (base > 64 || i > 2) { - return BASH_BASE_ERROR; - } - return base; -} - -static int opposite(int ch) { - if (ch == '(') return ')'; - if (ch == '[') return ']'; - if (ch == '{') return '}'; - if (ch == '<') return '>'; - return ch; -} - -static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - - CharacterSet setWordStart(CharacterSet::setAlpha, "_"); - // note that [+-] are often parts of identifiers in shell scripts - CharacterSet setWord(CharacterSet::setAlphaNum, "._+-"); - CharacterSet setBashOperator(CharacterSet::setNone, "^&\\%()-+=|{}[]:;>,*/(ch); - Delimiter[DelimiterLength] = '\0'; - } - ~HereDocCls() { - delete []Delimiter; - } - }; - HereDocCls HereDoc; - - class QuoteCls { // Class to manage quote pairs (simplified vs LexPerl) - public: - int Count; - int Up, Down; - QuoteCls() { - Count = 0; - Up = '\0'; - Down = '\0'; - } - void Open(int u) { - Count++; - Up = u; - Down = opposite(Up); - } - void Start(int u) { - Count = 0; - Open(u); - } - }; - QuoteCls Quote; - - int numBase = 0; - int digit; - unsigned int endPos = startPos + length; - - // Backtrack to beginning of style if required... - // If in a long distance lexical state, backtrack to find quote characters - if (initStyle == SCE_SH_HERE_Q) { - while ((startPos > 1) && (styler.StyleAt(startPos) != SCE_SH_HERE_DELIM)) { - startPos--; - } - startPos = styler.LineStart(styler.GetLine(startPos)); - initStyle = styler.StyleAt(startPos - 1); - } - // Bash strings can be multi-line with embedded newlines, so backtrack. - // Bash numbers have additional state during lexing, so backtrack too. - if (initStyle == SCE_SH_STRING - || initStyle == SCE_SH_BACKTICKS - || initStyle == SCE_SH_CHARACTER - || initStyle == SCE_SH_NUMBER - || initStyle == SCE_SH_IDENTIFIER - || initStyle == SCE_SH_COMMENTLINE) { - while ((startPos > 1) && (styler.StyleAt(startPos - 1) == initStyle)) { - startPos--; - } - initStyle = SCE_SH_DEFAULT; - } - - StyleContext sc(startPos, endPos - startPos, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - // Determine if the current state should terminate. - switch (sc.state) { - case SCE_SH_OPERATOR: - sc.SetState(SCE_SH_DEFAULT); - break; - case SCE_SH_WORD: - // "." never used in Bash variable names but used in file names - if (!setWord.Contains(sc.ch)) { - char s[1000]; - sc.GetCurrent(s, sizeof(s)); - if (s[0] != '-' && // for file operators - !keywords.InList(s)) { - sc.ChangeState(SCE_SH_IDENTIFIER); - } - sc.SetState(SCE_SH_DEFAULT); - } - break; - case SCE_SH_IDENTIFIER: - if (sc.chPrev == '\\') { // for escaped chars - sc.ForwardSetState(SCE_SH_DEFAULT); - } else if (!setWord.Contains(sc.ch)) { - sc.SetState(SCE_SH_DEFAULT); - } - break; - case SCE_SH_NUMBER: - digit = translateBashDigit(sc.ch); - if (numBase == BASH_BASE_DECIMAL) { - if (sc.ch == '#') { - char s[10]; - sc.GetCurrent(s, sizeof(s)); - numBase = getBashNumberBase(s); - if (numBase != BASH_BASE_ERROR) - break; - } else if (IsADigit(sc.ch)) - break; - } else if (numBase == BASH_BASE_HEX) { - if (IsADigit(sc.ch, 16)) - break; -#ifdef PEDANTIC_OCTAL - } else if (numBase == BASH_BASE_OCTAL || - numBase == BASH_BASE_OCTAL_ERROR) { - if (digit <= 7) - break; - if (digit <= 9) { - numBase = BASH_BASE_OCTAL_ERROR; - break; - } -#endif - } else if (numBase == BASH_BASE_ERROR) { - if (digit <= 9) - break; - } else { // DD#DDDD number style handling - if (digit != BASH_BASE_ERROR) { - if (numBase <= 36) { - // case-insensitive if base<=36 - if (digit >= 36) digit -= 26; - } - if (digit < numBase) - break; - if (digit <= 9) { - numBase = BASH_BASE_ERROR; - break; - } - } - } - // fallthrough when number is at an end or error - if (numBase == BASH_BASE_ERROR -#ifdef PEDANTIC_OCTAL - || numBase == BASH_BASE_OCTAL_ERROR -#endif - ) { - sc.ChangeState(SCE_SH_ERROR); - } - sc.SetState(SCE_SH_DEFAULT); - break; - case SCE_SH_COMMENTLINE: - if (sc.atLineEnd && sc.chPrev != '\\') { - sc.SetState(SCE_SH_DEFAULT); - } - break; - case SCE_SH_HERE_DELIM: - // From Bash info: - // --------------- - // Specifier format is: <<[-]WORD - // Optional '-' is for removal of leading tabs from here-doc. - // Whitespace acceptable after <<[-] operator - // - if (HereDoc.State == 0) { // '<<' encountered - HereDoc.Quote = sc.chNext; - HereDoc.Quoted = false; - HereDoc.DelimiterLength = 0; - HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; - if (sc.chNext == '\'' || sc.chNext == '\"') { // a quoted here-doc delimiter (' or ") - sc.Forward(); - HereDoc.Quoted = true; - HereDoc.State = 1; - } else if (!HereDoc.Indent && sc.chNext == '-') { // <<- indent case - HereDoc.Indent = true; - } else if (setHereDoc.Contains(sc.chNext)) { - // an unquoted here-doc delimiter, no special handling - // TODO check what exactly bash considers part of the delim - HereDoc.State = 1; - } else if (sc.chNext == '<') { // HERE string <<< - sc.Forward(); - sc.ForwardSetState(SCE_SH_DEFAULT); - } else if (IsASpace(sc.chNext)) { - // eat whitespace - } else if (setLeftShift.Contains(sc.chNext)) { - // left shift << or <<= operator cases - sc.ChangeState(SCE_SH_OPERATOR); - sc.ForwardSetState(SCE_SH_DEFAULT); - } else { - // symbols terminates; deprecated zero-length delimiter - HereDoc.State = 1; - } - } else if (HereDoc.State == 1) { // collect the delimiter - if (setHereDoc2.Contains(sc.ch) || sc.chPrev == '\\') { - HereDoc.Append(sc.ch); - } else if (HereDoc.Quoted && sc.ch == HereDoc.Quote) { // closing quote => end of delimiter - sc.ForwardSetState(SCE_SH_DEFAULT); - } else if (sc.ch == '\\') { - // skip escape prefix - } else { - sc.SetState(SCE_SH_DEFAULT); - } - if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) { // force blowup - sc.SetState(SCE_SH_ERROR); - HereDoc.State = 0; - } - } - break; - case SCE_SH_HERE_Q: - // HereDoc.State == 2 - if (sc.atLineStart) { - sc.SetState(SCE_SH_HERE_Q); - int prefixws = 0; - while (IsASpace(sc.ch) && !sc.atLineEnd) { // whitespace prefix - sc.Forward(); - prefixws++; - } - if (prefixws > 0) - sc.SetState(SCE_SH_HERE_Q); - while (!sc.atLineEnd) { - sc.Forward(); - } - char s[HERE_DELIM_MAX]; - sc.GetCurrent(s, sizeof(s)); - if (sc.LengthCurrent() == 0) - break; - if (s[strlen(s) - 1] == '\r') - s[strlen(s) - 1] = '\0'; - if (strcmp(HereDoc.Delimiter, s) == 0) { - if ((prefixws > 0 && HereDoc.Indent) || // indentation rule - (prefixws == 0 && !HereDoc.Indent)) { - sc.SetState(SCE_SH_DEFAULT); - break; - } - } - } - break; - case SCE_SH_SCALAR: // variable names - if (!setParam.Contains(sc.ch)) { - if (sc.LengthCurrent() == 1) { - // Special variable: $(, $_ etc. - sc.ForwardSetState(SCE_SH_DEFAULT); - } else { - sc.SetState(SCE_SH_DEFAULT); - } - } - break; - case SCE_SH_STRING: // delimited styles - case SCE_SH_CHARACTER: - case SCE_SH_BACKTICKS: - case SCE_SH_PARAM: - if (sc.ch == '\\' && Quote.Up != '\\') { - sc.Forward(); - } else if (sc.ch == Quote.Down) { - Quote.Count--; - if (Quote.Count == 0) { - sc.ForwardSetState(SCE_SH_DEFAULT); - } - } else if (sc.ch == Quote.Up) { - Quote.Count++; - } - break; - } - - // Must check end of HereDoc state 1 before default state is handled - if (HereDoc.State == 1 && sc.atLineEnd) { - // Begin of here-doc (the line after the here-doc delimiter): - // Lexically, the here-doc starts from the next line after the >>, but the - // first line of here-doc seem to follow the style of the last EOL sequence - HereDoc.State = 2; - if (HereDoc.Quoted) { - if (sc.state == SCE_SH_HERE_DELIM) { - // Missing quote at end of string! We are stricter than bash. - // Colour here-doc anyway while marking this bit as an error. - sc.ChangeState(SCE_SH_ERROR); - } - // HereDoc.Quote always == '\'' - } - sc.SetState(SCE_SH_HERE_Q); - } - - // Determine if a new state should be entered. - if (sc.state == SCE_SH_DEFAULT) { - if (sc.ch == '\\') { // escaped character - sc.SetState(SCE_SH_IDENTIFIER); - } else if (IsADigit(sc.ch)) { - sc.SetState(SCE_SH_NUMBER); - numBase = BASH_BASE_DECIMAL; - if (sc.ch == '0') { // hex,octal - if (sc.chNext == 'x' || sc.chNext == 'X') { - numBase = BASH_BASE_HEX; - sc.Forward(); - } else if (IsADigit(sc.chNext)) { -#ifdef PEDANTIC_OCTAL - numBase = BASH_BASE_OCTAL; -#else - numBase = BASH_BASE_HEX; -#endif - } - } - } else if (setWordStart.Contains(sc.ch)) { - sc.SetState(SCE_SH_WORD); - } else if (sc.ch == '#') { - sc.SetState(SCE_SH_COMMENTLINE); - } else if (sc.ch == '\"') { - sc.SetState(SCE_SH_STRING); - Quote.Start(sc.ch); - } else if (sc.ch == '\'') { - sc.SetState(SCE_SH_CHARACTER); - Quote.Start(sc.ch); - } else if (sc.ch == '`') { - sc.SetState(SCE_SH_BACKTICKS); - Quote.Start(sc.ch); - } else if (sc.ch == '$') { - sc.SetState(SCE_SH_SCALAR); - sc.Forward(); - if (sc.ch == '{') { - sc.ChangeState(SCE_SH_PARAM); - } else if (sc.ch == '\'') { - sc.ChangeState(SCE_SH_CHARACTER); - } else if (sc.ch == '"') { - sc.ChangeState(SCE_SH_STRING); - } else if (sc.ch == '(' || sc.ch == '`') { - sc.ChangeState(SCE_SH_BACKTICKS); - if (sc.chNext == '(') { // $(( is lexed as operator - sc.ChangeState(SCE_SH_OPERATOR); - } - } else { - continue; // scalar has no delimiter pair - } - // fallthrough, open delim for $[{'"(`] - Quote.Start(sc.ch); - } else if (sc.Match('<', '<')) { - sc.SetState(SCE_SH_HERE_DELIM); - HereDoc.State = 0; - HereDoc.Indent = false; - } else if (sc.ch == '-' && // one-char file test operators - setSingleCharOp.Contains(sc.chNext) && - !setWord.Contains(sc.GetRelative(2)) && - IsASpace(sc.chPrev)) { - sc.SetState(SCE_SH_WORD); - sc.Forward(); - } else if (setBashOperator.Contains(sc.ch)) { - sc.SetState(SCE_SH_OPERATOR); - } - } - } - sc.Complete(); -} - -static bool IsCommentLine(int line, Accessor &styler) { - int pos = styler.LineStart(line); - int eol_pos = styler.LineStart(line + 1) - 1; - for (int i = pos; i < eol_pos; i++) { - char ch = styler[i]; - if (ch == '#') - return true; - else if (ch != ' ' && ch != '\t') - return false; - } - return false; -} - -static void FoldBashDoc(unsigned int startPos, int length, int, WordList *[], - Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - // Comment folding - if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) - { - if (!IsCommentLine(lineCurrent - 1, styler) - && IsCommentLine(lineCurrent + 1, styler)) - levelCurrent++; - else if (IsCommentLine(lineCurrent - 1, styler) - && !IsCommentLine(lineCurrent + 1, styler)) - levelCurrent--; - } - if (style == SCE_SH_OPERATOR) { - if (ch == '{') { - levelCurrent++; - } else if (ch == '}') { - levelCurrent--; - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const bashWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmBash(SCLEX_BASH, ColouriseBashDoc, "bash", FoldBashDoc, bashWordListDesc); diff --git a/src/LexBasic.cxx b/src/LexBasic.cxx deleted file mode 100644 index 1c5d7b425..000000000 --- a/src/LexBasic.cxx +++ /dev/null @@ -1,373 +0,0 @@ -// Scintilla source code edit control -/** @file LexBasic.cxx - ** Lexer for BlitzBasic and PureBasic. - **/ -// Copyright 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -// This tries to be a unified Lexer/Folder for all the BlitzBasic/BlitzMax/PurBasic basics -// and derivatives. Once they diverge enough, might want to split it into multiple -// lexers for more code clearity. -// -// Mail me (elias users sf net) for any bugs. - -// Folding only works for simple things like functions or types. - -// You may want to have a look at my ctags lexer as well, if you additionally to coloring -// and folding need to extract things like label tags in your editor. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/* Bits: - * 1 - whitespace - * 2 - operator - * 4 - identifier - * 8 - decimal digit - * 16 - hex digit - * 32 - bin digit - */ -static int character_classification[128] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 2, - 60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2, 2, 2, - 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 4, - 2, 20, 20, 20, 20, 20, 20, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0 -}; - -static bool IsSpace(int c) { - return c < 128 && (character_classification[c] & 1); -} - -static bool IsOperator(int c) { - return c < 128 && (character_classification[c] & 2); -} - -static bool IsIdentifier(int c) { - return c < 128 && (character_classification[c] & 4); -} - -static bool IsDigit(int c) { - return c < 128 && (character_classification[c] & 8); -} - -static bool IsHexDigit(int c) { - return c < 128 && (character_classification[c] & 16); -} - -static bool IsBinDigit(int c) { - return c < 128 && (character_classification[c] & 32); -} - -static int LowerCase(int c) -{ - if (c >= 'A' && c <= 'Z') - return 'a' + c - 'A'; - return c; -} - -static void ColouriseBasicDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler, char comment_char) { - bool wasfirst = true, isfirst = true; // true if first token in a line - styler.StartAt(startPos); - - StyleContext sc(startPos, length, initStyle, styler); - - // Can't use sc.More() here else we miss the last character - for (; ; sc.Forward()) { - if (sc.state == SCE_B_IDENTIFIER) { - if (!IsIdentifier(sc.ch)) { - // Labels - if (wasfirst && sc.Match(':')) { - sc.ChangeState(SCE_B_LABEL); - sc.ForwardSetState(SCE_B_DEFAULT); - } else { - char s[100]; - int kstates[4] = { - SCE_B_KEYWORD, - SCE_B_KEYWORD2, - SCE_B_KEYWORD3, - SCE_B_KEYWORD4, - }; - sc.GetCurrentLowered(s, sizeof(s)); - for (int i = 0; i < 4; i++) { - if (keywordlists[i]->InList(s)) { - sc.ChangeState(kstates[i]); - } - } - // Types, must set them as operator else they will be - // matched as number/constant - if (sc.Match('.') || sc.Match('$') || sc.Match('%') || - sc.Match('#')) { - sc.SetState(SCE_B_OPERATOR); - } else { - sc.SetState(SCE_B_DEFAULT); - } - } - } - } else if (sc.state == SCE_B_OPERATOR) { - if (!IsOperator(sc.ch) || sc.Match('#')) - sc.SetState(SCE_B_DEFAULT); - } else if (sc.state == SCE_B_LABEL) { - if (!IsIdentifier(sc.ch)) - sc.SetState(SCE_B_DEFAULT); - } else if (sc.state == SCE_B_CONSTANT) { - if (!IsIdentifier(sc.ch)) - sc.SetState(SCE_B_DEFAULT); - } else if (sc.state == SCE_B_NUMBER) { - if (!IsDigit(sc.ch)) - sc.SetState(SCE_B_DEFAULT); - } else if (sc.state == SCE_B_HEXNUMBER) { - if (!IsHexDigit(sc.ch)) - sc.SetState(SCE_B_DEFAULT); - } else if (sc.state == SCE_B_BINNUMBER) { - if (!IsBinDigit(sc.ch)) - sc.SetState(SCE_B_DEFAULT); - } else if (sc.state == SCE_B_STRING) { - if (sc.ch == '"') { - sc.ForwardSetState(SCE_B_DEFAULT); - } - if (sc.atLineEnd) { - sc.ChangeState(SCE_B_ERROR); - sc.SetState(SCE_B_DEFAULT); - } - } else if (sc.state == SCE_B_COMMENT || sc.state == SCE_B_PREPROCESSOR) { - if (sc.atLineEnd) { - sc.SetState(SCE_B_DEFAULT); - } - } - - if (sc.atLineStart) - isfirst = true; - - if (sc.state == SCE_B_DEFAULT || sc.state == SCE_B_ERROR) { - if (isfirst && sc.Match('.')) { - sc.SetState(SCE_B_LABEL); - } else if (isfirst && sc.Match('#')) { - wasfirst = isfirst; - sc.SetState(SCE_B_IDENTIFIER); - } else if (sc.Match(comment_char)) { - // Hack to make deprecated QBASIC '$Include show - // up in freebasic with SCE_B_PREPROCESSOR. - if (comment_char == '\'' && sc.Match(comment_char, '$')) - sc.SetState(SCE_B_PREPROCESSOR); - else - sc.SetState(SCE_B_COMMENT); - } else if (sc.Match('"')) { - sc.SetState(SCE_B_STRING); - } else if (IsDigit(sc.ch)) { - sc.SetState(SCE_B_NUMBER); - } else if (sc.Match('$')) { - sc.SetState(SCE_B_HEXNUMBER); - } else if (sc.Match('%')) { - sc.SetState(SCE_B_BINNUMBER); - } else if (sc.Match('#')) { - sc.SetState(SCE_B_CONSTANT); - } else if (IsOperator(sc.ch)) { - sc.SetState(SCE_B_OPERATOR); - } else if (IsIdentifier(sc.ch)) { - wasfirst = isfirst; - sc.SetState(SCE_B_IDENTIFIER); - } else if (!IsSpace(sc.ch)) { - sc.SetState(SCE_B_ERROR); - } - } - - if (!IsSpace(sc.ch)) - isfirst = false; - - if (!sc.More()) - break; - } - sc.Complete(); -} - -static int CheckBlitzFoldPoint(char const *token, int &level) { - if (!strcmp(token, "function") || - !strcmp(token, "type")) { - level |= SC_FOLDLEVELHEADERFLAG; - return 1; - } - if (!strcmp(token, "end function") || - !strcmp(token, "end type")) { - return -1; - } - return 0; -} - -static int CheckPureFoldPoint(char const *token, int &level) { - if (!strcmp(token, "procedure") || - !strcmp(token, "enumeration") || - !strcmp(token, "interface") || - !strcmp(token, "structure")) { - level |= SC_FOLDLEVELHEADERFLAG; - return 1; - } - if (!strcmp(token, "endprocedure") || - !strcmp(token, "endenumeration") || - !strcmp(token, "endinterface") || - !strcmp(token, "endstructure")) { - return -1; - } - return 0; -} - -static int CheckFreeFoldPoint(char const *token, int &level) { - if (!strcmp(token, "function") || - !strcmp(token, "sub") || - !strcmp(token, "type")) { - level |= SC_FOLDLEVELHEADERFLAG; - return 1; - } - if (!strcmp(token, "end function") || - !strcmp(token, "end sub") || - !strcmp(token, "end type")) { - return -1; - } - return 0; -} - -static void FoldBasicDoc(unsigned int startPos, int length, - Accessor &styler, int (*CheckFoldPoint)(char const *, int &)) { - int line = styler.GetLine(startPos); - int level = styler.LevelAt(line); - int go = 0, done = 0; - int endPos = startPos + length; - char word[256]; - int wordlen = 0; - int i; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - // Scan for tokens at the start of the line (they may include - // whitespace, for tokens like "End Function" - for (i = startPos; i < endPos; i++) { - int c = styler.SafeGetCharAt(i); - if (!done && !go) { - if (wordlen) { // are we scanning a token already? - word[wordlen] = static_cast(LowerCase(c)); - if (!IsIdentifier(c)) { // done with token - word[wordlen] = '\0'; - go = CheckFoldPoint(word, level); - if (!go) { - // Treat any whitespace as single blank, for - // things like "End Function". - if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) { - word[wordlen] = ' '; - if (wordlen < 255) - wordlen++; - } - else // done with this line - done = 1; - } - } else if (wordlen < 255) { - wordlen++; - } - } else { // start scanning at first non-whitespace character - if (!IsSpace(c)) { - if (IsIdentifier(c)) { - word[0] = static_cast(LowerCase(c)); - wordlen = 1; - } else // done with this line - done = 1; - } - } - } - if (c == '\n') { // line end - if (!done && wordlen == 0 && foldCompact) // line was only space - level |= SC_FOLDLEVELWHITEFLAG; - if (level != styler.LevelAt(line)) - styler.SetLevel(line, level); - level += go; - line++; - // reset state - wordlen = 0; - level &= ~SC_FOLDLEVELHEADERFLAG; - level &= ~SC_FOLDLEVELWHITEFLAG; - go = 0; - done = 0; - } - } -} - -static void ColouriseBlitzBasicDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, ';'); -} - -static void ColourisePureBasicDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, ';'); -} - -static void ColouriseFreeBasicDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, '\''); -} - -static void FoldBlitzBasicDoc(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) { - FoldBasicDoc(startPos, length, styler, CheckBlitzFoldPoint); -} - -static void FoldPureBasicDoc(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) { - FoldBasicDoc(startPos, length, styler, CheckPureFoldPoint); -} - -static void FoldFreeBasicDoc(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) { - FoldBasicDoc(startPos, length, styler, CheckFreeFoldPoint); -} - -static const char * const blitzbasicWordListDesc[] = { - "BlitzBasic Keywords", - "user1", - "user2", - "user3", - 0 -}; - -static const char * const purebasicWordListDesc[] = { - "PureBasic Keywords", - "PureBasic PreProcessor Keywords", - "user defined 1", - "user defined 2", - 0 -}; - -static const char * const freebasicWordListDesc[] = { - "FreeBasic Keywords", - "FreeBasic PreProcessor Keywords", - "user defined 1", - "user defined 2", - 0 -}; - -LexerModule lmBlitzBasic(SCLEX_BLITZBASIC, ColouriseBlitzBasicDoc, "blitzbasic", - FoldBlitzBasicDoc, blitzbasicWordListDesc); - -LexerModule lmPureBasic(SCLEX_PUREBASIC, ColourisePureBasicDoc, "purebasic", - FoldPureBasicDoc, purebasicWordListDesc); - -LexerModule lmFreeBasic(SCLEX_FREEBASIC, ColouriseFreeBasicDoc, "freebasic", - FoldFreeBasicDoc, freebasicWordListDesc); - diff --git a/src/LexBullant.cxx b/src/LexBullant.cxx deleted file mode 100644 index 28e2e7543..000000000 --- a/src/LexBullant.cxx +++ /dev/null @@ -1,229 +0,0 @@ -// SciTE - Scintilla based Text Editor -// LexBullant.cxx - lexer for Bullant - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static int classifyWordBullant(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { - char s[100]; - s[0] = '\0'; - for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) { - s[i] = static_cast(tolower(styler[start + i])); - s[i + 1] = '\0'; - } - int lev= 0; - char chAttr = SCE_C_IDENTIFIER; - if (isdigit(s[0]) || (s[0] == '.')){ - chAttr = SCE_C_NUMBER; - } - else { - if (keywords.InList(s)) { - chAttr = SCE_C_WORD; - if (strcmp(s, "end") == 0) - lev = -1; - else if (strcmp(s, "method") == 0 || - strcmp(s, "case") == 0 || - strcmp(s, "class") == 0 || - strcmp(s, "debug") == 0 || - strcmp(s, "test") == 0 || - strcmp(s, "if") == 0 || - strcmp(s, "lock") == 0 || - strcmp(s, "transaction") == 0 || - strcmp(s, "trap") == 0 || - strcmp(s, "until") == 0 || - strcmp(s, "while") == 0) - lev = 1; - } - } - styler.ColourTo(end, chAttr); - return lev; -} - -static void ColouriseBullantDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - WordList &keywords = *keywordlists[0]; - - styler.StartAt(startPos); - - bool fold = styler.GetPropertyInt("fold") != 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - - int state = initStyle; - if (state == SCE_C_STRINGEOL) // Does not leak onto next line - state = SCE_C_DEFAULT; - char chPrev = ' '; - char chNext = styler[startPos]; - unsigned int lengthDoc = startPos + length; - int visibleChars = 0; - styler.StartSegment(startPos); - int endFoundThisLine = 0; - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { - // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) - // Avoid triggering two times on Dos/Win - // End of line - endFoundThisLine = 0; - if (state == SCE_C_STRINGEOL) { - styler.ColourTo(i, state); - state = SCE_C_DEFAULT; - } - if (fold) { - int lev = levelPrev; - if (visibleChars == 0) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - styler.SetLevel(lineCurrent, lev); - lineCurrent++; - levelPrev = levelCurrent; - } - visibleChars = 0; - -/* int indentBlock = GetLineIndentation(lineCurrent); - if (blockChange==1){ - lineCurrent++; - int pos=SetLineIndentation(lineCurrent, indentBlock + indentSize); - } else if (blockChange==-1) { - indentBlock -= indentSize; - if (indentBlock < 0) - indentBlock = 0; - SetLineIndentation(lineCurrent, indentBlock); - lineCurrent++; - } - blockChange=0; -*/ } - if (!(isascii(ch) && isspace(ch))) - visibleChars++; - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - chPrev = ' '; - i += 1; - continue; - } - - if (state == SCE_C_DEFAULT) { - if (iswordstart(ch)) { - styler.ColourTo(i-1, state); - state = SCE_C_IDENTIFIER; - } else if (ch == '@' && chNext == 'o') { - if ((styler.SafeGetCharAt(i+2) =='f') && (styler.SafeGetCharAt(i+3) == 'f')) { - styler.ColourTo(i-1, state); - state = SCE_C_COMMENT; - } - } else if (ch == '#') { - styler.ColourTo(i-1, state); - state = SCE_C_COMMENTLINE; - } else if (ch == '\"') { - styler.ColourTo(i-1, state); - state = SCE_C_STRING; - } else if (ch == '\'') { - styler.ColourTo(i-1, state); - state = SCE_C_CHARACTER; - } else if (isoperator(ch)) { - styler.ColourTo(i-1, state); - styler.ColourTo(i, SCE_C_OPERATOR); - } - } else if (state == SCE_C_IDENTIFIER) { - if (!iswordchar(ch)) { - int levelChange = classifyWordBullant(styler.GetStartSegment(), i - 1, keywords, styler); - state = SCE_C_DEFAULT; - chNext = styler.SafeGetCharAt(i + 1); - if (ch == '#') { - state = SCE_C_COMMENTLINE; - } else if (ch == '\"') { - state = SCE_C_STRING; - } else if (ch == '\'') { - state = SCE_C_CHARACTER; - } else if (isoperator(ch)) { - styler.ColourTo(i, SCE_C_OPERATOR); - } - if (endFoundThisLine == 0) - levelCurrent+=levelChange; - if (levelChange == -1) - endFoundThisLine=1; - } - } else if (state == SCE_C_COMMENT) { - if (ch == '@' && chNext == 'o') { - if (styler.SafeGetCharAt(i+2) == 'n') { - styler.ColourTo(i+2, state); - state = SCE_C_DEFAULT; - i+=2; - } - } - } else if (state == SCE_C_COMMENTLINE) { - if (ch == '\r' || ch == '\n') { - endFoundThisLine = 0; - styler.ColourTo(i-1, state); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_STRING) { - if (ch == '\\') { - if (chNext == '\"' || chNext == '\'' || chNext == '\\') { - i++; - ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - } - } else if (ch == '\"') { - styler.ColourTo(i, state); - state = SCE_C_DEFAULT; - } else if (chNext == '\r' || chNext == '\n') { - endFoundThisLine = 0; - styler.ColourTo(i-1, SCE_C_STRINGEOL); - state = SCE_C_STRINGEOL; - } - } else if (state == SCE_C_CHARACTER) { - if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) { - endFoundThisLine = 0; - styler.ColourTo(i-1, SCE_C_STRINGEOL); - state = SCE_C_STRINGEOL; - } else if (ch == '\\') { - if (chNext == '\"' || chNext == '\'' || chNext == '\\') { - i++; - ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - } - } else if (ch == '\'') { - styler.ColourTo(i, state); - state = SCE_C_DEFAULT; - } - } - chPrev = ch; - } - styler.ColourTo(lengthDoc - 1, state); - - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - if (fold) { - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - //styler.SetLevel(lineCurrent, levelCurrent | flagsNext); - styler.SetLevel(lineCurrent, levelPrev | flagsNext); - - } -} - -static const char * const bullantWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmBullant(SCLEX_BULLANT, ColouriseBullantDoc, "bullant", 0, bullantWordListDesc); diff --git a/src/LexCLW.cxx b/src/LexCLW.cxx deleted file mode 100644 index 624ef0f2b..000000000 --- a/src/LexCLW.cxx +++ /dev/null @@ -1,679 +0,0 @@ -// Scintilla source code edit control -/** @file LexClw.cxx - ** Lexer for Clarion. - ** 2004/12/17 Updated Lexer - **/ -// Copyright 2003-2004 by Ron Schofield -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// Is an end of line character -inline bool IsEOL(const int ch) { - - return(ch == '\n'); -} - -// Convert character to uppercase -static char CharacterUpper(char chChar) { - - if (chChar < 'a' || chChar > 'z') { - return(chChar); - } - else { - return(static_cast(chChar - 'a' + 'A')); - } -} - -// Convert string to uppercase -static void StringUpper(char *szString) { - - while (*szString) { - *szString = CharacterUpper(*szString); - szString++; - } -} - -// Is a label start character -inline bool IsALabelStart(const int iChar) { - - return(isalpha(iChar) || iChar == '_'); -} - -// Is a label character -inline bool IsALabelCharacter(const int iChar) { - - return(isalnum(iChar) || iChar == '_' || iChar == ':'); -} - -// Is the character is a ! and the the next character is not a ! -inline bool IsACommentStart(const int iChar) { - - return(iChar == '!'); -} - -// Is the character a Clarion hex character (ABCDEF) -inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) { - - // Case insensitive. - if (!bCaseSensitive) { - if (strchr("ABCDEFabcdef", iChar) != NULL) { - return(true); - } - } - // Case sensitive - else { - if (strchr("ABCDEF", iChar) != NULL) { - return(true); - } - } - return(false); -} - -// Is the character a Clarion base character (B=Binary, O=Octal, H=Hex) -inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) { - - // Case insensitive. - if (!bCaseSensitive) { - // If character is a numeric base character - if (strchr("BOHboh", iChar) != NULL) { - return(true); - } - } - // Case sensitive - else { - // If character is a numeric base character - if (strchr("BOH", iChar) != NULL) { - return(true); - } - } - return(false); -} - -// Set the correct numeric constant state -inline bool SetNumericConstantState(StyleContext &scDoc) { - - int iPoints = 0; // Point counter - char cNumericString[512]; // Numeric string buffer - - // Buffer the current numberic string - scDoc.GetCurrent(cNumericString, sizeof(cNumericString)); - // Loop through the string until end of string (NULL termination) - for (int iIndex = 0; cNumericString[iIndex] != '\0'; iIndex++) { - // Depending on the character - switch (cNumericString[iIndex]) { - // Is a . (point) - case '.' : - // Increment point counter - iPoints++; - break; - default : - break; - } - } - // If points found (can be more than one for improper formatted number - if (iPoints > 0) { - return(true); - } - // Else no points found - else { - return(false); - } -} - -// Get the next word in uppercase from the current position (keyword lookahead) -inline bool GetNextWordUpper(Accessor &styler, unsigned int uiStartPos, int iLength, char *cWord) { - - unsigned int iIndex = 0; // Buffer Index - - // Loop through the remaining string from the current position - for (int iOffset = uiStartPos; iOffset < iLength; iOffset++) { - // Get the character from the buffer using the offset - char cCharacter = styler[iOffset]; - if (IsEOL(cCharacter)) { - break; - } - // If the character is alphabet character - if (isalpha(cCharacter)) { - // Add UPPERCASE character to the word buffer - cWord[iIndex++] = CharacterUpper(cCharacter); - } - } - // Add null termination - cWord[iIndex] = '\0'; - // If no word was found - if (iIndex == 0) { - // Return failure - return(false); - } - // Else word was found - else { - // Return success - return(true); - } -} - -// Clarion Language Colouring Procedure -static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) { - - int iParenthesesLevel = 0; // Parenthese Level - int iColumn1Label = false; // Label starts in Column 1 - - WordList &wlClarionKeywords = *wlKeywords[0]; // Clarion Keywords - WordList &wlCompilerDirectives = *wlKeywords[1]; // Compiler Directives - WordList &wlRuntimeExpressions = *wlKeywords[2]; // Runtime Expressions - WordList &wlBuiltInProcsFuncs = *wlKeywords[3]; // Builtin Procedures and Functions - WordList &wlStructsDataTypes = *wlKeywords[4]; // Structures and Data Types - WordList &wlAttributes = *wlKeywords[5]; // Procedure Attributes - WordList &wlStandardEquates = *wlKeywords[6]; // Standard Equates - WordList &wlLabelReservedWords = *wlKeywords[7]; // Clarion Reserved Keywords (Labels) - WordList &wlProcLabelReservedWords = *wlKeywords[8]; // Clarion Reserved Keywords (Procedure Labels) - - const char wlProcReservedKeywordList[] = - "PROCEDURE FUNCTION"; - WordList wlProcReservedKeywords; - wlProcReservedKeywords.Set(wlProcReservedKeywordList); - - const char wlCompilerKeywordList[] = - "COMPILE OMIT"; - WordList wlCompilerKeywords; - wlCompilerKeywords.Set(wlCompilerKeywordList); - - const char wlLegacyStatementsList[] = - "BOF EOF FUNCTION POINTER SHARE"; - WordList wlLegacyStatements; - wlLegacyStatements.Set(wlLegacyStatementsList); - - StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler); - - // lex source code - for (; scDoc.More(); scDoc.Forward()) - { - // - // Determine if the current state should terminate. - // - - // Label State Handling - if (scDoc.state == SCE_CLW_LABEL) { - // If the character is not a valid label - if (!IsALabelCharacter(scDoc.ch)) { - // If the character is a . (dot syntax) - if (scDoc.ch == '.') { - // Turn off column 1 label flag as label now cannot be reserved work - iColumn1Label = false; - // Uncolour the . (dot) to default state, move forward one character, - // and change back to the label state. - scDoc.SetState(SCE_CLW_DEFAULT); - scDoc.Forward(); - scDoc.SetState(SCE_CLW_LABEL); - } - // Else check label - else { - char cLabel[512]; // Label buffer - // Buffer the current label string - scDoc.GetCurrent(cLabel,sizeof(cLabel)); - // If case insensitive, convert string to UPPERCASE to match passed keywords. - if (!bCaseSensitive) { - StringUpper(cLabel); - } - // Else if UPPERCASE label string is in the Clarion compiler keyword list - if (wlCompilerKeywords.InList(cLabel) && iColumn1Label){ - // change the label to error state - scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); - } - // Else if UPPERCASE label string is in the Clarion reserved keyword list - else if (wlLabelReservedWords.InList(cLabel) && iColumn1Label){ - // change the label to error state - scDoc.ChangeState(SCE_CLW_ERROR); - } - // Else if UPPERCASE label string is - else if (wlProcLabelReservedWords.InList(cLabel) && iColumn1Label) { - char cWord[512]; // Word buffer - // Get the next word from the current position - if (GetNextWordUpper(accStyler,scDoc.currentPos,uiStartPos+iLength,cWord)) { - // If the next word is a procedure reserved word - if (wlProcReservedKeywords.InList(cWord)) { - // Change the label to error state - scDoc.ChangeState(SCE_CLW_ERROR); - } - } - } - // Else if label string is in the compiler directive keyword list - else if (wlCompilerDirectives.InList(cLabel)) { - // change the state to compiler directive state - scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); - } - // Terminate the label state and set to default state - scDoc.SetState(SCE_CLW_DEFAULT); - } - } - } - // Keyword State Handling - else if (scDoc.state == SCE_CLW_KEYWORD) { - // If character is : (colon) - if (scDoc.ch == ':') { - char cEquate[512]; // Equate buffer - // Move forward to include : (colon) in buffer - scDoc.Forward(); - // Buffer the equate string - scDoc.GetCurrent(cEquate,sizeof(cEquate)); - // If case insensitive, convert string to UPPERCASE to match passed keywords. - if (!bCaseSensitive) { - StringUpper(cEquate); - } - // If statement string is in the equate list - if (wlStandardEquates.InList(cEquate)) { - // Change to equate state - scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE); - } - } - // If the character is not a valid label character - else if (!IsALabelCharacter(scDoc.ch)) { - char cStatement[512]; // Statement buffer - // Buffer the statement string - scDoc.GetCurrent(cStatement,sizeof(cStatement)); - // If case insensitive, convert string to UPPERCASE to match passed keywords. - if (!bCaseSensitive) { - StringUpper(cStatement); - } - // If statement string is in the Clarion keyword list - if (wlClarionKeywords.InList(cStatement)) { - // Change the statement string to the Clarion keyword state - scDoc.ChangeState(SCE_CLW_KEYWORD); - } - // Else if statement string is in the compiler directive keyword list - else if (wlCompilerDirectives.InList(cStatement)) { - // Change the statement string to the compiler directive state - scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); - } - // Else if statement string is in the runtime expressions keyword list - else if (wlRuntimeExpressions.InList(cStatement)) { - // Change the statement string to the runtime expressions state - scDoc.ChangeState(SCE_CLW_RUNTIME_EXPRESSIONS); - } - // Else if statement string is in the builtin procedures and functions keyword list - else if (wlBuiltInProcsFuncs.InList(cStatement)) { - // Change the statement string to the builtin procedures and functions state - scDoc.ChangeState(SCE_CLW_BUILTIN_PROCEDURES_FUNCTION); - } - // Else if statement string is in the tructures and data types keyword list - else if (wlStructsDataTypes.InList(cStatement)) { - // Change the statement string to the structures and data types state - scDoc.ChangeState(SCE_CLW_STRUCTURE_DATA_TYPE); - } - // Else if statement string is in the procedure attribute keyword list - else if (wlAttributes.InList(cStatement)) { - // Change the statement string to the procedure attribute state - scDoc.ChangeState(SCE_CLW_ATTRIBUTE); - } - // Else if statement string is in the standard equate keyword list - else if (wlStandardEquates.InList(cStatement)) { - // Change the statement string to the standard equate state - scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE); - } - // Else if statement string is in the deprecated or legacy keyword list - else if (wlLegacyStatements.InList(cStatement)) { - // Change the statement string to the standard equate state - scDoc.ChangeState(SCE_CLW_DEPRECATED); - } - // Else the statement string doesn't match any work list - else { - // Change the statement string to the default state - scDoc.ChangeState(SCE_CLW_DEFAULT); - } - // Terminate the keyword state and set to default state - scDoc.SetState(SCE_CLW_DEFAULT); - } - } - // String State Handling - else if (scDoc.state == SCE_CLW_STRING) { - // If the character is an ' (single quote) - if (scDoc.ch == '\'') { - // Set the state to default and move forward colouring - // the ' (single quote) as default state - // terminating the string state - scDoc.SetState(SCE_CLW_DEFAULT); - scDoc.Forward(); - } - // If the next character is an ' (single quote) - if (scDoc.chNext == '\'') { - // Move forward one character and set to default state - // colouring the next ' (single quote) as default state - // terminating the string state - scDoc.ForwardSetState(SCE_CLW_DEFAULT); - scDoc.Forward(); - } - } - // Picture String State Handling - else if (scDoc.state == SCE_CLW_PICTURE_STRING) { - // If the character is an ( (open parenthese) - if (scDoc.ch == '(') { - // Increment the parenthese level - iParenthesesLevel++; - } - // Else if the character is a ) (close parenthese) - else if (scDoc.ch == ')') { - // If the parenthese level is set to zero - // parentheses matched - if (!iParenthesesLevel) { - scDoc.SetState(SCE_CLW_DEFAULT); - } - // Else parenthese level is greater than zero - // still looking for matching parentheses - else { - // Decrement the parenthese level - iParenthesesLevel--; - } - } - } - // Standard Equate State Handling - else if (scDoc.state == SCE_CLW_STANDARD_EQUATE) { - if (!isalnum(scDoc.ch)) { - scDoc.SetState(SCE_CLW_DEFAULT); - } - } - // Integer Constant State Handling - else if (scDoc.state == SCE_CLW_INTEGER_CONSTANT) { - // If the character is not a digit (0-9) - // or character is not a hexidecimal character (A-F) - // or character is not a . (point) - // or character is not a numberic base character (B,O,H) - if (!(isdigit(scDoc.ch) - || IsAHexCharacter(scDoc.ch, bCaseSensitive) - || scDoc.ch == '.' - || IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) { - // If the number was a real - if (SetNumericConstantState(scDoc)) { - // Colour the matched string to the real constant state - scDoc.ChangeState(SCE_CLW_REAL_CONSTANT); - } - // Else the number was an integer - else { - // Colour the matched string to an integer constant state - scDoc.ChangeState(SCE_CLW_INTEGER_CONSTANT); - } - // Terminate the integer constant state and set to default state - scDoc.SetState(SCE_CLW_DEFAULT); - } - } - - // - // Determine if a new state should be entered. - // - - // Beginning of Line Handling - if (scDoc.atLineStart) { - // Reset the column 1 label flag - iColumn1Label = false; - // If column 1 character is a label start character - if (IsALabelStart(scDoc.ch)) { - // Label character is found in column 1 - // so set column 1 label flag and clear last column 1 label - iColumn1Label = true; - // Set the state to label - scDoc.SetState(SCE_CLW_LABEL); - } - // else if character is a space or tab - else if (IsASpace(scDoc.ch)){ - // Set to default state - scDoc.SetState(SCE_CLW_DEFAULT); - } - // else if comment start (!) or is an * (asterisk) - else if (IsACommentStart(scDoc.ch) || scDoc.ch == '*' ) { - // then set the state to comment. - scDoc.SetState(SCE_CLW_COMMENT); - } - // else the character is a ? (question mark) - else if (scDoc.ch == '?') { - // Change to the compiler directive state, move forward, - // colouring the ? (question mark), change back to default state. - scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); - scDoc.Forward(); - scDoc.SetState(SCE_CLW_DEFAULT); - } - // else an invalid character in column 1 - else { - // Set to error state - scDoc.SetState(SCE_CLW_ERROR); - } - } - // End of Line Handling - else if (scDoc.atLineEnd) { - // Reset to the default state at the end of each line. - scDoc.SetState(SCE_CLW_DEFAULT); - } - // Default Handling - else { - // If in default state - if (scDoc.state == SCE_CLW_DEFAULT) { - // If is a letter could be a possible statement - if (isalpha(scDoc.ch)) { - // Set the state to Clarion Keyword and verify later - scDoc.SetState(SCE_CLW_KEYWORD); - } - // else is a number - else if (isdigit(scDoc.ch)) { - // Set the state to Integer Constant and verify later - scDoc.SetState(SCE_CLW_INTEGER_CONSTANT); - } - // else if the start of a comment or a | (line continuation) - else if (IsACommentStart(scDoc.ch) || scDoc.ch == '|') { - // then set the state to comment. - scDoc.SetState(SCE_CLW_COMMENT); - } - // else if the character is a ' (single quote) - else if (scDoc.ch == '\'') { - // If the character is also a ' (single quote) - // Embedded Apostrophe - if (scDoc.chNext == '\'') { - // Move forward colouring it as default state - scDoc.ForwardSetState(SCE_CLW_DEFAULT); - } - else { - // move to the next character and then set the state to comment. - scDoc.ForwardSetState(SCE_CLW_STRING); - } - } - // else the character is an @ (ampersand) - else if (scDoc.ch == '@') { - // Case insensitive. - if (!bCaseSensitive) { - // If character is a valid picture token character - if (strchr("DEKNPSTdeknpst", scDoc.chNext) != NULL) { - // Set to the picture string state - scDoc.SetState(SCE_CLW_PICTURE_STRING); - } - } - // Case sensitive - else { - // If character is a valid picture token character - if (strchr("DEKNPST", scDoc.chNext) != NULL) { - // Set the picture string state - scDoc.SetState(SCE_CLW_PICTURE_STRING); - } - } - } - } - } - } - // lexing complete - scDoc.Complete(); -} - -// Clarion Language Case Sensitive Colouring Procedure -static void ColouriseClarionDocSensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) { - - ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true); -} - -// Clarion Language Case Insensitive Colouring Procedure -static void ColouriseClarionDocInsensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) { - - ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false); -} - -// Fill Buffer - -static void FillBuffer(unsigned int uiStart, unsigned int uiEnd, Accessor &accStyler, char *szBuffer, unsigned int uiLength) { - - unsigned int uiPos = 0; - - while ((uiPos < uiEnd - uiStart + 1) && (uiPos < uiLength-1)) { - szBuffer[uiPos] = static_cast(toupper(accStyler[uiStart + uiPos])); - uiPos++; - } - szBuffer[uiPos] = '\0'; -} - -// Classify Clarion Fold Point - -static int ClassifyClarionFoldPoint(int iLevel, const char* szString) { - - if (!(isdigit(szString[0]) || (szString[0] == '.'))) { - if (strcmp(szString, "PROCEDURE") == 0) { - // iLevel = SC_FOLDLEVELBASE + 1; - } - else if (strcmp(szString, "MAP") == 0 || - strcmp(szString,"ACCEPT") == 0 || - strcmp(szString,"BEGIN") == 0 || - strcmp(szString,"CASE") == 0 || - strcmp(szString,"EXECUTE") == 0 || - strcmp(szString,"IF") == 0 || - strcmp(szString,"ITEMIZE") == 0 || - strcmp(szString,"INTERFACE") == 0 || - strcmp(szString,"JOIN") == 0 || - strcmp(szString,"LOOP") == 0 || - strcmp(szString,"MODULE") == 0 || - strcmp(szString,"RECORD") == 0) { - iLevel++; - } - else if (strcmp(szString, "APPLICATION") == 0 || - strcmp(szString, "CLASS") == 0 || - strcmp(szString, "DETAIL") == 0 || - strcmp(szString, "FILE") == 0 || - strcmp(szString, "FOOTER") == 0 || - strcmp(szString, "FORM") == 0 || - strcmp(szString, "GROUP") == 0 || - strcmp(szString, "HEADER") == 0 || - strcmp(szString, "INTERFACE") == 0 || - strcmp(szString, "MENU") == 0 || - strcmp(szString, "MENUBAR") == 0 || - strcmp(szString, "OLE") == 0 || - strcmp(szString, "OPTION") == 0 || - strcmp(szString, "QUEUE") == 0 || - strcmp(szString, "REPORT") == 0 || - strcmp(szString, "SHEET") == 0 || - strcmp(szString, "TAB") == 0 || - strcmp(szString, "TOOLBAR") == 0 || - strcmp(szString, "VIEW") == 0 || - strcmp(szString, "WINDOW") == 0) { - iLevel++; - } - else if (strcmp(szString, "END") == 0 || - strcmp(szString, "UNTIL") == 0 || - strcmp(szString, "WHILE") == 0) { - iLevel--; - } - } - return(iLevel); -} - -// Clarion Language Folding Procedure -static void FoldClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *[], Accessor &accStyler) { - - unsigned int uiEndPos = uiStartPos + iLength; - int iLineCurrent = accStyler.GetLine(uiStartPos); - int iLevelPrev = accStyler.LevelAt(iLineCurrent) & SC_FOLDLEVELNUMBERMASK; - int iLevelCurrent = iLevelPrev; - char chNext = accStyler[uiStartPos]; - int iStyle = iInitStyle; - int iStyleNext = accStyler.StyleAt(uiStartPos); - int iVisibleChars = 0; - int iLastStart = 0; - - for (unsigned int uiPos = uiStartPos; uiPos < uiEndPos; uiPos++) { - - char chChar = chNext; - chNext = accStyler.SafeGetCharAt(uiPos + 1); - int iStylePrev = iStyle; - iStyle = iStyleNext; - iStyleNext = accStyler.StyleAt(uiPos + 1); - bool bEOL = (chChar == '\r' && chNext != '\n') || (chChar == '\n'); - - if (iStylePrev == SCE_CLW_DEFAULT) { - if (iStyle == SCE_CLW_KEYWORD || iStyle == SCE_CLW_STRUCTURE_DATA_TYPE) { - // Store last word start point. - iLastStart = uiPos; - } - } - - if (iStylePrev == SCE_CLW_KEYWORD || iStylePrev == SCE_CLW_STRUCTURE_DATA_TYPE) { - if(iswordchar(chChar) && !iswordchar(chNext)) { - char chBuffer[100]; - FillBuffer(iLastStart, uiPos, accStyler, chBuffer, sizeof(chBuffer)); - iLevelCurrent = ClassifyClarionFoldPoint(iLevelCurrent,chBuffer); - // if ((iLevelCurrent == SC_FOLDLEVELBASE + 1) && iLineCurrent > 1) { - // accStyler.SetLevel(iLineCurrent-1,SC_FOLDLEVELBASE); - // iLevelPrev = SC_FOLDLEVELBASE; - // } - } - } - - if (bEOL) { - int iLevel = iLevelPrev; - if ((iLevelCurrent > iLevelPrev) && (iVisibleChars > 0)) - iLevel |= SC_FOLDLEVELHEADERFLAG; - if (iLevel != accStyler.LevelAt(iLineCurrent)) { - accStyler.SetLevel(iLineCurrent,iLevel); - } - iLineCurrent++; - iLevelPrev = iLevelCurrent; - iVisibleChars = 0; - } - - if (!isspacechar(chChar)) - iVisibleChars++; - } - - // Fill in the real level of the next line, keeping the current flags - // as they will be filled in later. - int iFlagsNext = accStyler.LevelAt(iLineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - accStyler.SetLevel(iLineCurrent, iLevelPrev | iFlagsNext); -} - -// Word List Descriptions -static const char * const rgWordListDescriptions[] = { - "Clarion Keywords", - "Compiler Directives", - "Built-in Procedures and Functions", - "Runtime Expressions", - "Structure and Data Types", - "Attributes", - "Standard Equates", - "Reserved Words (Labels)", - "Reserved Words (Procedure Labels)", - 0, -}; - -// Case Sensitive Clarion Language Lexer -LexerModule lmClw(SCLEX_CLW, ColouriseClarionDocSensitive, "clarion", FoldClarionDoc, rgWordListDescriptions); - -// Case Insensitive Clarion Language Lexer -LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClarionDocInsensitive, "clarionnocase", FoldClarionDoc, rgWordListDescriptions); diff --git a/src/LexCOBOL.cxx b/src/LexCOBOL.cxx deleted file mode 100644 index 05bf1d973..000000000 --- a/src/LexCOBOL.cxx +++ /dev/null @@ -1,368 +0,0 @@ -// Scintilla source code edit control -/** @file LexCOBOL.cxx - ** Lexer for COBOL - ** Based on LexPascal.cxx - ** Written by Laurent le Tynevez - ** Updated by Simon Steele September 2002 - ** Updated by Mathias Rauen May 2003 (Delphi adjustments) - ** Updated by Rod Falck, Aug 2006 Converted to COBOL - **/ - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "StyleContext.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#define IN_DIVISION 0x01 -#define IN_DECLARATIVES 0x02 -#define IN_SECTION 0x04 -#define IN_PARAGRAPH 0x08 -#define IN_FLAGS 0xF -#define NOT_HEADER 0x10 - -inline bool isCOBOLoperator(char ch) - { - return isoperator(ch); - } - -inline bool isCOBOLwordchar(char ch) - { - return isascii(ch) && (isalnum(ch) || ch == '-'); - - } - -inline bool isCOBOLwordstart(char ch) - { - return isascii(ch) && isalnum(ch); - } - -static int CountBits(int nBits) - { - int count = 0; - for (int i = 0; i < 32; ++i) - { - count += nBits & 1; - nBits >>= 1; - } - return count; - } - -static void getRange(unsigned int start, - unsigned int end, - Accessor &styler, - char *s, - unsigned int len) { - unsigned int i = 0; - while ((i < end - start + 1) && (i < len-1)) { - s[i] = static_cast(tolower(styler[start + i])); - i++; - } - s[i] = '\0'; -} - -static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr) { - styler.ColourTo(end, attr); -} - - -static int classifyWordCOBOL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, int nContainment, bool *bAarea) { - int ret = 0; - - WordList& a_keywords = *keywordlists[0]; - WordList& b_keywords = *keywordlists[1]; - WordList& c_keywords = *keywordlists[2]; - - char s[100]; - getRange(start, end, styler, s, sizeof(s)); - - char chAttr = SCE_C_IDENTIFIER; - if (isdigit(s[0]) || (s[0] == '.') || (s[0] == 'v')) { - chAttr = SCE_C_NUMBER; - char *p = s + 1; - while (*p) { - if ((!isdigit(*p) && (*p) != 'v') && isCOBOLwordchar(*p)) { - chAttr = SCE_C_IDENTIFIER; - break; - } - ++p; - } - } - else { - if (a_keywords.InList(s)) { - chAttr = SCE_C_WORD; - } - else if (b_keywords.InList(s)) { - chAttr = SCE_C_WORD2; - } - else if (c_keywords.InList(s)) { - chAttr = SCE_C_UUID; - } - } - if (*bAarea) { - if (strcmp(s, "division") == 0) { - ret = IN_DIVISION; - // we've determined the containment, anything else is just ignored for those purposes - *bAarea = false; - } else if (strcmp(s, "declaratives") == 0) { - ret = IN_DIVISION | IN_DECLARATIVES; - if (nContainment & IN_DECLARATIVES) - ret |= NOT_HEADER | IN_SECTION; - // we've determined the containment, anything else is just ignored for those purposes - *bAarea = false; - } else if (strcmp(s, "section") == 0) { - ret = (nContainment &~ IN_PARAGRAPH) | IN_SECTION; - // we've determined the containment, anything else is just ignored for those purposes - *bAarea = false; - } else if (strcmp(s, "end") == 0 && (nContainment & IN_DECLARATIVES)) { - ret = IN_DIVISION | IN_DECLARATIVES | IN_SECTION | NOT_HEADER; - } else { - ret = nContainment | IN_PARAGRAPH; - } - } - ColourTo(styler, end, chAttr); - return ret; -} - -static void ColouriseCOBOLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - styler.StartAt(startPos); - - int state = initStyle; - if (state == SCE_C_CHARACTER) // Does not leak onto next line - state = SCE_C_DEFAULT; - char chPrev = ' '; - char chNext = styler[startPos]; - unsigned int lengthDoc = startPos + length; - - int nContainment; - - int currentLine = styler.GetLine(startPos); - if (currentLine > 0) { - styler.SetLineState(currentLine, styler.GetLineState(currentLine-1)); - nContainment = styler.GetLineState(currentLine); - nContainment &= ~NOT_HEADER; - } else { - styler.SetLineState(currentLine, 0); - nContainment = 0; - } - - styler.StartSegment(startPos); - bool bNewLine = true; - bool bAarea = !isspacechar(chNext); - int column = 0; - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - - chNext = styler.SafeGetCharAt(i + 1); - - ++column; - - if (bNewLine) { - column = 0; - } - if (column <= 1 && !bAarea) { - bAarea = !isspacechar(ch); - } - bool bSetNewLine = false; - if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { - // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) - // Avoid triggering two times on Dos/Win - // End of line - if (state == SCE_C_CHARACTER) { - ColourTo(styler, i, state); - state = SCE_C_DEFAULT; - } - styler.SetLineState(currentLine, nContainment); - currentLine++; - bSetNewLine = true; - if (nContainment & NOT_HEADER) - nContainment &= ~(NOT_HEADER | IN_DECLARATIVES | IN_SECTION); - } - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - chPrev = ' '; - i += 1; - continue; - } - - if (state == SCE_C_DEFAULT) { - if (isCOBOLwordstart(ch) || (ch == '$' && isascii(chNext) && isalpha(chNext))) { - ColourTo(styler, i-1, state); - state = SCE_C_IDENTIFIER; - } else if (column == 0 && ch == '*' && chNext != '*') { - ColourTo(styler, i-1, state); - state = SCE_C_COMMENTLINE; - } else if (column == 0 && ch == '/' && chNext != '*') { - ColourTo(styler, i-1, state); - state = SCE_C_COMMENTLINE; - } else if (column == 0 && ch == '*' && chNext == '*') { - ColourTo(styler, i-1, state); - state = SCE_C_COMMENTDOC; - } else if (column == 0 && ch == '/' && chNext == '*') { - ColourTo(styler, i-1, state); - state = SCE_C_COMMENTDOC; - } else if (ch == '"') { - ColourTo(styler, i-1, state); - state = SCE_C_STRING; - } else if (ch == '\'') { - ColourTo(styler, i-1, state); - state = SCE_C_CHARACTER; - } else if (ch == '?' && column == 0) { - ColourTo(styler, i-1, state); - state = SCE_C_PREPROCESSOR; - } else if (isCOBOLoperator(ch)) { - ColourTo(styler, i-1, state); - ColourTo(styler, i, SCE_C_OPERATOR); - } - } else if (state == SCE_C_IDENTIFIER) { - if (!isCOBOLwordchar(ch)) { - int lStateChange = classifyWordCOBOL(styler.GetStartSegment(), i - 1, keywordlists, styler, nContainment, &bAarea); - - if(lStateChange != 0) { - styler.SetLineState(currentLine, lStateChange); - nContainment = lStateChange; - } - - state = SCE_C_DEFAULT; - chNext = styler.SafeGetCharAt(i + 1); - if (ch == '"') { - state = SCE_C_STRING; - } else if (ch == '\'') { - state = SCE_C_CHARACTER; - } else if (isCOBOLoperator(ch)) { - ColourTo(styler, i, SCE_C_OPERATOR); - } - } - } else { - if (state == SCE_C_PREPROCESSOR) { - if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) { - ColourTo(styler, i-1, state); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_COMMENT) { - if (ch == '\r' || ch == '\n') { - ColourTo(styler, i, state); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_COMMENTDOC) { - if (ch == '\r' || ch == '\n') { - if (((i > styler.GetStartSegment() + 2) || ( - (initStyle == SCE_C_COMMENTDOC) && - (styler.GetStartSegment() == static_cast(startPos))))) { - ColourTo(styler, i, state); - state = SCE_C_DEFAULT; - } - } - } else if (state == SCE_C_COMMENTLINE) { - if (ch == '\r' || ch == '\n') { - ColourTo(styler, i-1, state); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_STRING) { - if (ch == '"') { - ColourTo(styler, i, state); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_CHARACTER) { - if (ch == '\'') { - ColourTo(styler, i, state); - state = SCE_C_DEFAULT; - } - } - } - chPrev = ch; - bNewLine = bSetNewLine; - if (bNewLine) - { - bAarea = false; - } - } - ColourTo(styler, lengthDoc - 1, state); -} - -static void FoldCOBOLDoc(unsigned int startPos, int length, int, WordList *[], - Accessor &styler) { - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) & SC_FOLDLEVELNUMBERMASK : 0xFFF; - char chNext = styler[startPos]; - - bool bNewLine = true; - bool bAarea = !isspacechar(chNext); - int column = 0; - bool bComment = false; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - ++column; - - if (bNewLine) { - column = 0; - bComment = (ch == '*' || ch == '/' || ch == '?'); - } - if (column <= 1 && !bAarea) { - bAarea = !isspacechar(ch); - } - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (atEOL) { - int nContainment = styler.GetLineState(lineCurrent); - int lev = CountBits(nContainment & IN_FLAGS) | SC_FOLDLEVELBASE; - if (bAarea && !bComment) - --lev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((bAarea) && (visibleChars > 0) && !(nContainment & NOT_HEADER) && !bComment) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - if ((lev & SC_FOLDLEVELNUMBERMASK) <= (levelPrev & SC_FOLDLEVELNUMBERMASK)) { - // this level is at the same level or less than the previous line - // therefore these is nothing for the previous header to collapse, so remove the header - styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG); - } - levelPrev = lev; - visibleChars = 0; - bAarea = false; - bNewLine = true; - lineCurrent++; - } else { - bNewLine = false; - } - - - if (!isspacechar(ch)) - visibleChars++; - } - - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const COBOLWordListDesc[] = { - "A Keywords", - "B Keywords", - "Extended Keywords", - 0 -}; - -LexerModule lmCOBOL(SCLEX_COBOL, ColouriseCOBOLDoc, "COBOL", FoldCOBOLDoc, COBOLWordListDesc); diff --git a/src/LexCPP.cxx b/src/LexCPP.cxx deleted file mode 100644 index 8a9395e17..000000000 --- a/src/LexCPP.cxx +++ /dev/null @@ -1,506 +0,0 @@ -// Scintilla source code edit control -/** @file LexCPP.cxx - ** Lexer for C++, C, Java, and JavaScript. - **/ -// Copyright 1998-2005 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "CharacterSet.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static bool IsSpaceEquiv(int state) { - return (state <= SCE_C_COMMENTDOC) || - // including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE - (state == SCE_C_COMMENTLINEDOC) || (state == SCE_C_COMMENTDOCKEYWORD) || - (state == SCE_C_COMMENTDOCKEYWORDERROR); -} - -// Preconditions: sc.currentPos points to a character after '+' or '-'. -// The test for pos reaching 0 should be redundant, -// and is in only for safety measures. -// Limitation: this code will give the incorrect answer for code like -// a = b+++/ptn/... -// Putting a space between the '++' post-inc operator and the '+' binary op -// fixes this, and is highly recommended for readability anyway. -static bool FollowsPostfixOperator(StyleContext &sc, Accessor &styler) { - int pos = (int) sc.currentPos; - while (--pos > 0) { - char ch = styler[pos]; - if (ch == '+' || ch == '-') { - return styler[pos - 1] == ch; - } - } - return false; -} - -static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler, bool caseSensitive) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - - // property styling.within.preprocessor - // For C++ code, determines whether all preprocessor code is styled in the preprocessor style (0, the default) - // or only from the initial # to the end of the command word(1). - bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; - - CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-"); - CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-"); - - CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); - - CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); - - // property lexer.cpp.allow.dollars - // Set to 0 to disallow the '$' character in identifiers with the cpp lexer. - if (styler.GetPropertyInt("lexer.cpp.allow.dollars", 1) != 0) { - setWordStart.Add('$'); - setWord.Add('$'); - } - - int chPrevNonWhite = ' '; - int visibleChars = 0; - bool lastWordWasUUID = false; - int styleBeforeDCKeyword = SCE_C_DEFAULT; - bool continuationLine = false; - bool isIncludePreprocessor = false; - - if (initStyle == SCE_C_PREPROCESSOR) { - // Set continuationLine if last character of previous line is '\' - int lineCurrent = styler.GetLine(startPos); - if (lineCurrent > 0) { - int chBack = styler.SafeGetCharAt(startPos-1, 0); - int chBack2 = styler.SafeGetCharAt(startPos-2, 0); - int lineEndChar = '!'; - if (chBack2 == '\r' && chBack == '\n') { - lineEndChar = styler.SafeGetCharAt(startPos-3, 0); - } else if (chBack == '\n' || chBack == '\r') { - lineEndChar = chBack2; - } - continuationLine = lineEndChar == '\\'; - } - } - - // look back to set chPrevNonWhite properly for better regex colouring - if (startPos > 0) { - int back = startPos; - while (--back && IsSpaceEquiv(styler.StyleAt(back))) - ; - if (styler.StyleAt(back) == SCE_C_OPERATOR) { - chPrevNonWhite = styler.SafeGetCharAt(back); - } - } - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.atLineStart) { - if (sc.state == SCE_C_STRING) { - // Prevent SCE_C_STRINGEOL from leaking back to previous line which - // ends with a line continuation by locking in the state upto this position. - sc.SetState(SCE_C_STRING); - } - // Reset states to begining of colourise so no surprises - // if different sets of lines lexed. - visibleChars = 0; - lastWordWasUUID = false; - isIncludePreprocessor = false; - } - - // Handle line continuation generically. - if (sc.ch == '\\') { - if (sc.chNext == '\n' || sc.chNext == '\r') { - sc.Forward(); - if (sc.ch == '\r' && sc.chNext == '\n') { - sc.Forward(); - } - continuationLine = true; - continue; - } - } - - // Determine if the current state should terminate. - switch (sc.state) { - case SCE_C_OPERATOR: - sc.SetState(SCE_C_DEFAULT); - break; - case SCE_C_NUMBER: - // We accept almost anything because of hex. and number suffixes - if (!setWord.Contains(sc.ch)) { - sc.SetState(SCE_C_DEFAULT); - } - break; - case SCE_C_IDENTIFIER: - if (!setWord.Contains(sc.ch) || (sc.ch == '.')) { - char s[1000]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); - } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - if (keywords.InList(s)) { - lastWordWasUUID = strcmp(s, "uuid") == 0; - sc.ChangeState(SCE_C_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_C_WORD2); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_C_GLOBALCLASS); - } - sc.SetState(SCE_C_DEFAULT); - } - break; - case SCE_C_PREPROCESSOR: - if (sc.atLineStart && !continuationLine) { - sc.SetState(SCE_C_DEFAULT); - } else if (stylingWithinPreprocessor) { - if (IsASpace(sc.ch)) { - sc.SetState(SCE_C_DEFAULT); - } - } else { - if (sc.Match('/', '*') || sc.Match('/', '/')) { - sc.SetState(SCE_C_DEFAULT); - } - } - break; - case SCE_C_COMMENT: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT); - } - break; - case SCE_C_COMMENTDOC: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_C_COMMENTDOC; - sc.SetState(SCE_C_COMMENTDOCKEYWORD); - } - } - break; - case SCE_C_COMMENTLINE: - if (sc.atLineStart) { - sc.SetState(SCE_C_DEFAULT); - } - break; - case SCE_C_COMMENTLINEDOC: - if (sc.atLineStart) { - sc.SetState(SCE_C_DEFAULT); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC; - sc.SetState(SCE_C_COMMENTDOCKEYWORD); - } - } - break; - case SCE_C_COMMENTDOCKEYWORD: - if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) { - sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); - sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT); - } else if (!setDoxygen.Contains(sc.ch)) { - char s[100]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); - } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { - sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); - } - sc.SetState(styleBeforeDCKeyword); - } - break; - case SCE_C_STRING: - if (sc.atLineEnd) { - sc.ChangeState(SCE_C_STRINGEOL); - } else if (isIncludePreprocessor) { - if (sc.ch == '>') { - sc.ForwardSetState(SCE_C_DEFAULT); - isIncludePreprocessor = false; - } - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_C_DEFAULT); - } - break; - case SCE_C_CHARACTER: - if (sc.atLineEnd) { - sc.ChangeState(SCE_C_STRINGEOL); - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_C_DEFAULT); - } - break; - case SCE_C_REGEX: - if (sc.atLineStart) { - sc.SetState(SCE_C_DEFAULT); - } else if (sc.ch == '/') { - sc.Forward(); - while ((sc.ch < 0x80) && islower(sc.ch)) - sc.Forward(); // gobble regex flags - sc.SetState(SCE_C_DEFAULT); - } else if (sc.ch == '\\') { - // Gobble up the quoted character - if (sc.chNext == '\\' || sc.chNext == '/') { - sc.Forward(); - } - } - break; - case SCE_C_STRINGEOL: - if (sc.atLineStart) { - sc.SetState(SCE_C_DEFAULT); - } - break; - case SCE_C_VERBATIM: - if (sc.ch == '\"') { - if (sc.chNext == '\"') { - sc.Forward(); - } else { - sc.ForwardSetState(SCE_C_DEFAULT); - } - } - break; - case SCE_C_UUID: - if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { - sc.SetState(SCE_C_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_C_DEFAULT) { - if (sc.Match('@', '\"')) { - sc.SetState(SCE_C_VERBATIM); - sc.Forward(); - } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - if (lastWordWasUUID) { - sc.SetState(SCE_C_UUID); - lastWordWasUUID = false; - } else { - sc.SetState(SCE_C_NUMBER); - } - } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) { - if (lastWordWasUUID) { - sc.SetState(SCE_C_UUID); - lastWordWasUUID = false; - } else { - sc.SetState(SCE_C_IDENTIFIER); - } - } else if (sc.Match('/', '*')) { - if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style - sc.SetState(SCE_C_COMMENTDOC); - } else { - sc.SetState(SCE_C_COMMENT); - } - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match('/', '/')) { - if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!")) - // Support of Qt/Doxygen doc. style - sc.SetState(SCE_C_COMMENTLINEDOC); - else - sc.SetState(SCE_C_COMMENTLINE); - } else if (sc.ch == '/' && setOKBeforeRE.Contains(chPrevNonWhite) && - (!setCouldBePostOp.Contains(chPrevNonWhite) || !FollowsPostfixOperator(sc, styler))) { - sc.SetState(SCE_C_REGEX); // JavaScript's RegEx - } else if (sc.ch == '\"') { - sc.SetState(SCE_C_STRING); - isIncludePreprocessor = false; // ensure that '>' won't end the string - } else if (isIncludePreprocessor && sc.ch == '<') { - sc.SetState(SCE_C_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_C_CHARACTER); - } else if (sc.ch == '#' && visibleChars == 0) { - // Preprocessor commands are alone on their line - sc.SetState(SCE_C_PREPROCESSOR); - // Skip whitespace between # and preprocessor word - do { - sc.Forward(); - } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); - if (sc.atLineEnd) { - sc.SetState(SCE_C_DEFAULT); - } else if (sc.Match("include")) { - isIncludePreprocessor = true; - } - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_C_OPERATOR); - } - } - - if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) { - chPrevNonWhite = sc.ch; - visibleChars++; - } - continuationLine = false; - } - sc.Complete(); -} - -static bool IsStreamCommentStyle(int style) { - return style == SCE_C_COMMENT || - style == SCE_C_COMMENTDOC || - style == SCE_C_COMMENTDOCKEYWORD || - style == SCE_C_COMMENTDOCKEYWORDERROR; -} - -// Store both the current line's fold level and the next lines in the -// level store to make it easy to pick up with each increment -// and to make it possible to fiddle the current level for "} else {". -static void FoldCppDoc(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) { - - // property fold.comment - // This option enables folding multi-line comments and explicit fold points when using the C++ lexer. - // Explicit fold points allows adding extra folding by placing a //{ comment at the start and a //} - // at the end of a section that should fold. - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - - // property fold.preprocessor - // This option enables folding preprocessor directives when using the C++ lexer. - // Includes C#'s explicit #region and #endregion folding directives. - bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; - - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - - // property fold.at.else - // This option enables C++ folding on a "} else {" line of an if statement. - bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; - - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelMinCurrent = levelCurrent; - int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && IsStreamCommentStyle(style)) { - if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_C_COMMENTLINEDOC)) { - levelNext++; - } else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_C_COMMENTLINEDOC) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelNext--; - } - } - if (foldComment && (style == SCE_C_COMMENTLINE)) { - if ((ch == '/') && (chNext == '/')) { - char chNext2 = styler.SafeGetCharAt(i + 2); - if (chNext2 == '{') { - levelNext++; - } else if (chNext2 == '}') { - levelNext--; - } - } - } - if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { - if (ch == '#') { - unsigned int j = i + 1; - while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { - j++; - } - if (styler.Match(j, "region") || styler.Match(j, "if")) { - levelNext++; - } else if (styler.Match(j, "end")) { - levelNext--; - } - } - } - if (style == SCE_C_OPERATOR) { - if (ch == '{') { - // Measure the minimum before a '{' to allow - // folding on "} else {" - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - levelNext++; - } else if (ch == '}') { - levelNext--; - } - } - if (!IsASpace(ch)) - visibleChars++; - if (atEOL || (i == endPos-1)) { - int levelUse = levelCurrent; - if (foldAtElse) { - levelUse = levelMinCurrent; - } - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - levelMinCurrent = levelCurrent; - if (atEOL && (i == static_cast(styler.Length()-1))) { - // There is an empty line at end of file so give it same level and empty - styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); - } - visibleChars = 0; - } - } -} - -static const char *const cppWordLists[] = { - "Primary keywords and identifiers", - "Secondary keywords and identifiers", - "Documentation comment keywords", - "Unused", - "Global classes and typedefs", - 0, -}; - -static void ColouriseCppDocSensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - ColouriseCppDoc(startPos, length, initStyle, keywordlists, styler, true); -} - -static void ColouriseCppDocInsensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - ColouriseCppDoc(startPos, length, initStyle, keywordlists, styler, false); -} - -LexerModule lmCPP(SCLEX_CPP, ColouriseCppDocSensitive, "cpp", FoldCppDoc, cppWordLists); -LexerModule lmCPPNoCase(SCLEX_CPPNOCASE, ColouriseCppDocInsensitive, "cppnocase", FoldCppDoc, cppWordLists); diff --git a/src/LexCSS.cxx b/src/LexCSS.cxx deleted file mode 100644 index f63103de3..000000000 --- a/src/LexCSS.cxx +++ /dev/null @@ -1,371 +0,0 @@ -// Scintilla source code edit control -/** @file LexCSS.cxx - ** Lexer for Cascading Style Sheets - ** Written by Jakub Vrána - ** Improved by Philippe Lhoste (CSS2) - **/ -// Copyright 1998-2002 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - - -static inline bool IsAWordChar(const unsigned int ch) { - /* FIXME: - * The CSS spec allows "ISO 10646 characters U+00A1 and higher" to be treated as word chars. - * Unfortunately, we are only getting string bytes here, and not full unicode characters. We cannot guarantee - * that our byte is between U+0080 - U+00A0 (to return false), so we have to allow all characters U+0080 and higher - */ - return ch >= 0x80 || isalnum(ch) || ch == '-' || ch == '_'; -} - -inline bool IsCssOperator(const int ch) { - if (!((ch < 0x80) && isalnum(ch)) && - (ch == '{' || ch == '}' || ch == ':' || ch == ',' || ch == ';' || - ch == '.' || ch == '#' || ch == '!' || ch == '@' || - /* CSS2 */ - ch == '*' || ch == '>' || ch == '+' || ch == '=' || ch == '~' || ch == '|' || - ch == '[' || ch == ']' || ch == '(' || ch == ')')) { - return true; - } - return false; -} - -static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { - WordList &css1Props = *keywordlists[0]; - WordList &pseudoClasses = *keywordlists[1]; - WordList &css2Props = *keywordlists[2]; - WordList &css3Props = *keywordlists[3]; - WordList &pseudoElements = *keywordlists[4]; - WordList &exProps = *keywordlists[5]; - WordList &exPseudoClasses = *keywordlists[6]; - WordList &exPseudoElements = *keywordlists[7]; - - StyleContext sc(startPos, length, initStyle, styler); - - int lastState = -1; // before operator - int lastStateC = -1; // before comment - int lastStateS = -1; // before single-quoted/double-quoted string - int op = ' '; // last operator - int opPrev = ' '; // last operator - - for (; sc.More(); sc.Forward()) { - if (sc.state == SCE_CSS_COMMENT && sc.Match('*', '/')) { - if (lastStateC == -1) { - // backtrack to get last state: - // comments are like whitespace, so we must return to the previous state - unsigned int i = startPos; - for (; i > 0; i--) { - if ((lastStateC = styler.StyleAt(i-1)) != SCE_CSS_COMMENT) { - if (lastStateC == SCE_CSS_OPERATOR) { - op = styler.SafeGetCharAt(i-1); - opPrev = styler.SafeGetCharAt(i-2); - while (--i) { - lastState = styler.StyleAt(i-1); - if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT) - break; - } - if (i == 0) - lastState = SCE_CSS_DEFAULT; - } - break; - } - } - if (i == 0) - lastStateC = SCE_CSS_DEFAULT; - } - sc.Forward(); - sc.ForwardSetState(lastStateC); - } - - if (sc.state == SCE_CSS_COMMENT) - continue; - - if (sc.state == SCE_CSS_DOUBLESTRING || sc.state == SCE_CSS_SINGLESTRING) { - if (sc.ch != (sc.state == SCE_CSS_DOUBLESTRING ? '\"' : '\'')) - continue; - unsigned int i = sc.currentPos; - while (i && styler[i-1] == '\\') - i--; - if ((sc.currentPos - i) % 2 == 1) - continue; - sc.ForwardSetState(lastStateS); - } - - if (sc.state == SCE_CSS_OPERATOR) { - if (op == ' ') { - unsigned int i = startPos; - op = styler.SafeGetCharAt(i-1); - opPrev = styler.SafeGetCharAt(i-2); - while (--i) { - lastState = styler.StyleAt(i-1); - if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT) - break; - } - } - switch (op) { - case '@': - if (lastState == SCE_CSS_DEFAULT) - sc.SetState(SCE_CSS_DIRECTIVE); - break; - case '>': - case '+': - if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || - lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) - sc.SetState(SCE_CSS_DEFAULT); - break; - case '[': - if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || - lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) - sc.SetState(SCE_CSS_ATTRIBUTE); - break; - case ']': - if (lastState == SCE_CSS_ATTRIBUTE) - sc.SetState(SCE_CSS_TAG); - break; - case '{': - if (lastState == SCE_CSS_MEDIA) - sc.SetState(SCE_CSS_DEFAULT); - else if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DIRECTIVE) - sc.SetState(SCE_CSS_IDENTIFIER); - break; - case '}': - if (lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT || - lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2 || lastState == SCE_CSS_IDENTIFIER3) - sc.SetState(SCE_CSS_DEFAULT); - break; - case '(': - if (lastState == SCE_CSS_PSEUDOCLASS) - sc.SetState(SCE_CSS_TAG); - else if (lastState == SCE_CSS_EXTENDED_PSEUDOCLASS) - sc.SetState(SCE_CSS_EXTENDED_PSEUDOCLASS); - break; - case ')': - if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || - lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS || - lastState == SCE_CSS_PSEUDOELEMENT || lastState == SCE_CSS_EXTENDED_PSEUDOELEMENT) - sc.SetState(SCE_CSS_TAG); - break; - case ':': - if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || - lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS || - lastState == SCE_CSS_PSEUDOELEMENT || lastState == SCE_CSS_EXTENDED_PSEUDOELEMENT) - sc.SetState(SCE_CSS_PSEUDOCLASS); - else if (lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2 || - lastState == SCE_CSS_IDENTIFIER3 || lastState == SCE_CSS_EXTENDED_IDENTIFIER || - lastState == SCE_CSS_UNKNOWN_IDENTIFIER) - sc.SetState(SCE_CSS_VALUE); - break; - case '.': - if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || - lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) - sc.SetState(SCE_CSS_CLASS); - break; - case '#': - if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || - lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS) - sc.SetState(SCE_CSS_ID); - break; - case ',': - case '|': - case '~': - if (lastState == SCE_CSS_TAG) - sc.SetState(SCE_CSS_DEFAULT); - break; - case ';': - if (lastState == SCE_CSS_DIRECTIVE) - sc.SetState(SCE_CSS_DEFAULT); - else if (lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT) - sc.SetState(SCE_CSS_IDENTIFIER); - break; - case '!': - if (lastState == SCE_CSS_VALUE) - sc.SetState(SCE_CSS_IMPORTANT); - break; - } - } - - if (IsAWordChar(sc.ch)) { - if (sc.state == SCE_CSS_DEFAULT) - sc.SetState(SCE_CSS_TAG); - continue; - } - - if (sc.ch == '*' && sc.state == SCE_CSS_DEFAULT) { - sc.SetState(SCE_CSS_TAG); - continue; - } - - if (IsAWordChar(sc.chPrev) && ( - sc.state == SCE_CSS_IDENTIFIER || sc.state == SCE_CSS_IDENTIFIER2 || - sc.state == SCE_CSS_IDENTIFIER3 || sc.state == SCE_CSS_EXTENDED_IDENTIFIER || - sc.state == SCE_CSS_UNKNOWN_IDENTIFIER || - sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT || - sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT || - sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS || - sc.state == SCE_CSS_IMPORTANT || - sc.state == SCE_CSS_DIRECTIVE - )) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - char *s2 = s; - while (*s2 && !IsAWordChar(*s2)) - s2++; - switch (sc.state) { - case SCE_CSS_IDENTIFIER: - case SCE_CSS_IDENTIFIER2: - case SCE_CSS_IDENTIFIER3: - case SCE_CSS_EXTENDED_IDENTIFIER: - case SCE_CSS_UNKNOWN_IDENTIFIER: - if (css1Props.InList(s2)) - sc.ChangeState(SCE_CSS_IDENTIFIER); - else if (css2Props.InList(s2)) - sc.ChangeState(SCE_CSS_IDENTIFIER2); - else if (css3Props.InList(s2)) - sc.ChangeState(SCE_CSS_IDENTIFIER3); - else if (exProps.InList(s2)) - sc.ChangeState(SCE_CSS_EXTENDED_IDENTIFIER); - else - sc.ChangeState(SCE_CSS_UNKNOWN_IDENTIFIER); - break; - case SCE_CSS_PSEUDOCLASS: - case SCE_CSS_PSEUDOELEMENT: - case SCE_CSS_EXTENDED_PSEUDOCLASS: - case SCE_CSS_EXTENDED_PSEUDOELEMENT: - case SCE_CSS_UNKNOWN_PSEUDOCLASS: - if (op == ':' && opPrev != ':' && pseudoClasses.InList(s2)) - sc.ChangeState(SCE_CSS_PSEUDOCLASS); - else if (opPrev == ':' && pseudoElements.InList(s2)) - sc.ChangeState(SCE_CSS_PSEUDOELEMENT); - else if ((op == ':' || (op == '(' && lastState == SCE_CSS_EXTENDED_PSEUDOCLASS)) && opPrev != ':' && exPseudoClasses.InList(s2)) - sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOCLASS); - else if (opPrev == ':' && exPseudoElements.InList(s2)) - sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOELEMENT); - else - sc.ChangeState(SCE_CSS_UNKNOWN_PSEUDOCLASS); - break; - case SCE_CSS_IMPORTANT: - if (strcmp(s2, "important") != 0) - sc.ChangeState(SCE_CSS_VALUE); - break; - case SCE_CSS_DIRECTIVE: - if (op == '@' && strcmp(s2, "media") == 0) - sc.ChangeState(SCE_CSS_MEDIA); - break; - } - } - - if (sc.ch != '.' && sc.ch != ':' && sc.ch != '#' && ( - sc.state == SCE_CSS_CLASS || sc.state == SCE_CSS_ID || - (sc.ch != '(' && sc.ch != ')' && ( /* This line of the condition makes it possible to extend pseudo-classes with parentheses */ - sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT || - sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT || - sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS - )) - )) - sc.SetState(SCE_CSS_TAG); - - if (sc.Match('/', '*')) { - lastStateC = sc.state; - sc.SetState(SCE_CSS_COMMENT); - sc.Forward(); - } else if ((sc.state == SCE_CSS_VALUE || sc.state == SCE_CSS_ATTRIBUTE) - && (sc.ch == '\"' || sc.ch == '\'')) { - lastStateS = sc.state; - sc.SetState((sc.ch == '\"' ? SCE_CSS_DOUBLESTRING : SCE_CSS_SINGLESTRING)); - } else if (IsCssOperator(sc.ch) - && (sc.state != SCE_CSS_ATTRIBUTE || sc.ch == ']') - && (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!') - && ((sc.state != SCE_CSS_DIRECTIVE && sc.state != SCE_CSS_MEDIA) || sc.ch == ';' || sc.ch == '{') - ) { - if (sc.state != SCE_CSS_OPERATOR) - lastState = sc.state; - sc.SetState(SCE_CSS_OPERATOR); - op = sc.ch; - opPrev = sc.chPrev; - } - } - - sc.Complete(); -} - -static void FoldCSSDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - bool inComment = (styler.StyleAt(startPos-1) == SCE_CSS_COMMENT); - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styler.StyleAt(i); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment) { - if (!inComment && (style == SCE_CSS_COMMENT)) - levelCurrent++; - else if (inComment && (style != SCE_CSS_COMMENT)) - levelCurrent--; - inComment = (style == SCE_CSS_COMMENT); - } - if (style == SCE_CSS_OPERATOR) { - if (ch == '{') { - levelCurrent++; - } else if (ch == '}') { - levelCurrent--; - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const cssWordListDesc[] = { - "CSS1 Properties", - "Pseudo-classes", - "CSS2 Properties", - "CSS3 Properties", - "Pseudo-elements", - "Browser-Specific CSS Properties", - "Browser-Specific Pseudo-classes", - "Browser-Specific Pseudo-elements", - 0 -}; - -LexerModule lmCss(SCLEX_CSS, ColouriseCssDoc, "css", FoldCSSDoc, cssWordListDesc); diff --git a/src/LexCaml.cxx b/src/LexCaml.cxx deleted file mode 100644 index ca1b65f38..000000000 --- a/src/LexCaml.cxx +++ /dev/null @@ -1,449 +0,0 @@ -// Scintilla source code edit control -/** @file LexCaml.cxx - ** Lexer for Objective Caml. - **/ -// Copyright 2005-2009 by Robert Roessler -// The License.txt file describes the conditions under which this software may be distributed. -/* Release History - 20050204 Initial release. - 20050205 Quick compiler standards/"cleanliness" adjustment. - 20050206 Added cast for IsLeadByte(). - 20050209 Changes to "external" build support. - 20050306 Fix for 1st-char-in-doc "corner" case. - 20050502 Fix for [harmless] one-past-the-end coloring. - 20050515 Refined numeric token recognition logic. - 20051125 Added 2nd "optional" keywords class. - 20051129 Support "magic" (read-only) comments for RCaml. - 20051204 Swtich to using StyleContext infrastructure. - 20090629 Add full Standard ML '97 support. -*/ - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "PropSetSimple.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -// Since the Microsoft __iscsym[f] funcs are not ANSI... -inline int iscaml(int c) {return isalnum(c) || c == '_';} -inline int iscamlf(int c) {return isalpha(c) || c == '_';} - -static const int baseT[24] = { - 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A - L */ - 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,16 /* M - X */ -}; - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#ifdef BUILD_AS_EXTERNAL_LEXER -/* - (actually seems to work!) -*/ -#include "WindowAccessor.h" -#include "ExternalLexer.h" - -#if PLAT_WIN -#include -#endif - -static void ColouriseCamlDoc( - unsigned int startPos, int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler); - -static void FoldCamlDoc( - unsigned int startPos, int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler); - -static void InternalLexOrFold(int lexOrFold, unsigned int startPos, int length, - int initStyle, char *words[], WindowID window, char *props); - -static const char* LexerName = "caml"; - -#ifdef TRACE -void Platform::DebugPrintf(const char *format, ...) { - char buffer[2000]; - va_list pArguments; - va_start(pArguments, format); - vsprintf(buffer,format,pArguments); - va_end(pArguments); - Platform::DebugDisplay(buffer); -} -#else -void Platform::DebugPrintf(const char *, ...) { -} -#endif - -bool Platform::IsDBCSLeadByte(int codePage, char ch) { - return ::IsDBCSLeadByteEx(codePage, ch) != 0; -} - -long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam, long lParam) { - return ::SendMessage(reinterpret_cast(w), msg, wParam, lParam); -} - -long Platform::SendScintillaPointer(WindowID w, unsigned int msg, unsigned long wParam, void *lParam) { - return ::SendMessage(reinterpret_cast(w), msg, wParam, - reinterpret_cast(lParam)); -} - -void EXT_LEXER_DECL Fold(unsigned int lexer, unsigned int startPos, int length, - int initStyle, char *words[], WindowID window, char *props) -{ - // below useless evaluation(s) to supress "not used" warnings - lexer; - // build expected data structures and do the Fold - InternalLexOrFold(1, startPos, length, initStyle, words, window, props); - -} - -int EXT_LEXER_DECL GetLexerCount() -{ - return 1; // just us [Objective] Caml lexers here! -} - -void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength) -{ - // below useless evaluation(s) to supress "not used" warnings - Index; - // return as much of our lexer name as will fit (what's up with Index?) - if (buflength > 0) { - buflength--; - int n = strlen(LexerName); - if (n > buflength) - n = buflength; - memcpy(name, LexerName, n), name[n] = '\0'; - } -} - -void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, - int initStyle, char *words[], WindowID window, char *props) -{ - // below useless evaluation(s) to supress "not used" warnings - lexer; - // build expected data structures and do the Lex - InternalLexOrFold(0, startPos, length, initStyle, words, window, props); -} - -static void InternalLexOrFold(int foldOrLex, unsigned int startPos, int length, - int initStyle, char *words[], WindowID window, char *props) -{ - // create and initialize a WindowAccessor (including contained PropSet) - PropSetSimple ps; - ps.SetMultiple(props); - WindowAccessor wa(window, ps); - // create and initialize WordList(s) - int nWL = 0; - for (; words[nWL]; nWL++) ; // count # of WordList PTRs needed - WordList** wl = new WordList* [nWL + 1];// alloc WordList PTRs - int i = 0; - for (; i < nWL; i++) { - wl[i] = new WordList(); // (works or THROWS bad_alloc EXCEPTION) - wl[i]->Set(words[i]); - } - wl[i] = 0; - // call our "internal" folder/lexer (... then do Flush!) - if (foldOrLex) - FoldCamlDoc(startPos, length, initStyle, wl, wa); - else - ColouriseCamlDoc(startPos, length, initStyle, wl, wa); - wa.Flush(); - // clean up before leaving - for (i = nWL - 1; i >= 0; i--) - delete wl[i]; - delete [] wl; -} - -static -#endif /* BUILD_AS_EXTERNAL_LEXER */ - -void ColouriseCamlDoc( - unsigned int startPos, int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) -{ - // initialize styler - StyleContext sc(startPos, length, initStyle, styler); - - int chBase = 0, chToken = 0, chLit = 0; - WordList& keywords = *keywordlists[0]; - WordList& keywords2 = *keywordlists[1]; - WordList& keywords3 = *keywordlists[2]; - const bool isSML = keywords.InList("andalso"); - const int useMagic = styler.GetPropertyInt("lexer.caml.magic", 0); - - // set up [initial] state info (terminating states that shouldn't "bleed") - const int state_ = sc.state & 0x0f; - if (state_ <= SCE_CAML_CHAR - || (isSML && state_ == SCE_CAML_STRING)) - sc.state = SCE_CAML_DEFAULT; - int nesting = (state_ >= SCE_CAML_COMMENT)? (state_ - SCE_CAML_COMMENT): 0; - - // foreach char in range... - while (sc.More()) { - // set up [per-char] state info - int state2 = -1; // (ASSUME no state change) - int chColor = sc.currentPos - 1;// (ASSUME standard coloring range) - bool advance = true; // (ASSUME scanner "eats" 1 char) - - // step state machine - switch (sc.state & 0x0f) { - case SCE_CAML_DEFAULT: - chToken = sc.currentPos; // save [possible] token start (JIC) - // it's wide open; what do we have? - if (iscamlf(sc.ch)) - state2 = SCE_CAML_IDENTIFIER; - else if (!isSML && sc.Match('`') && iscamlf(sc.chNext)) - state2 = SCE_CAML_TAGNAME; - else if (!isSML && sc.Match('#') && isdigit(sc.chNext)) - state2 = SCE_CAML_LINENUM; - else if (isdigit(sc.ch)) { - // it's a number, assume base 10 - state2 = SCE_CAML_NUMBER, chBase = 10; - if (sc.Match('0')) { - // there MAY be a base specified... - const char* baseC = "bBoOxX"; - if (isSML) { - if (sc.chNext == 'w') - sc.Forward(); // (consume SML "word" indicator) - baseC = "x"; - } - // ... change to specified base AS REQUIRED - if (strchr(baseC, sc.chNext)) - chBase = baseT[tolower(sc.chNext) - 'a'], sc.Forward(); - } - } else if (!isSML && sc.Match('\'')) // (Caml char literal?) - state2 = SCE_CAML_CHAR, chLit = 0; - else if (isSML && sc.Match('#', '"')) // (SML char literal?) - state2 = SCE_CAML_CHAR, sc.Forward(); - else if (sc.Match('"')) - state2 = SCE_CAML_STRING; - else if (sc.Match('(', '*')) - state2 = SCE_CAML_COMMENT, sc.Forward(), sc.ch = ' '; // (*)... - else if (strchr("!?~" /* Caml "prefix-symbol" */ - "=<>@^|&+-*/$%" /* Caml "infix-symbol" */ - "()[]{};,:.#", sc.ch) // Caml "bracket" or ;,:.# - // SML "extra" ident chars - || (isSML && (sc.Match('\\') || sc.Match('`')))) - state2 = SCE_CAML_OPERATOR; - break; - - case SCE_CAML_IDENTIFIER: - // [try to] interpret as [additional] identifier char - if (!(iscaml(sc.ch) || sc.Match('\''))) { - const int n = sc.currentPos - chToken; - if (n < 24) { - // length is believable as keyword, [re-]construct token - char t[24]; - for (int i = -n; i < 0; i++) - t[n + i] = static_cast(sc.GetRelative(i)); - t[n] = '\0'; - // special-case "_" token as KEYWORD - if ((n == 1 && sc.chPrev == '_') || keywords.InList(t)) - sc.ChangeState(SCE_CAML_KEYWORD); - else if (keywords2.InList(t)) - sc.ChangeState(SCE_CAML_KEYWORD2); - else if (keywords3.InList(t)) - sc.ChangeState(SCE_CAML_KEYWORD3); - } - state2 = SCE_CAML_DEFAULT, advance = false; - } - break; - - case SCE_CAML_TAGNAME: - // [try to] interpret as [additional] tagname char - if (!(iscaml(sc.ch) || sc.Match('\''))) - state2 = SCE_CAML_DEFAULT, advance = false; - break; - - /*case SCE_CAML_KEYWORD: - case SCE_CAML_KEYWORD2: - case SCE_CAML_KEYWORD3: - // [try to] interpret as [additional] keyword char - if (!iscaml(ch)) - state2 = SCE_CAML_DEFAULT, advance = false; - break;*/ - - case SCE_CAML_LINENUM: - // [try to] interpret as [additional] linenum directive char - if (!isdigit(sc.ch)) - state2 = SCE_CAML_DEFAULT, advance = false; - break; - - case SCE_CAML_OPERATOR: { - // [try to] interpret as [additional] operator char - const char* o = 0; - if (iscaml(sc.ch) || isspace(sc.ch) // ident or whitespace - || (o = strchr(")]};,\'\"#", sc.ch),o) // "termination" chars - || (!isSML && sc.Match('`')) // Caml extra term char - || (!strchr("!$%&*+-./:<=>?@^|~", sc.ch)// "operator" chars - // SML extra ident chars - && !(isSML && (sc.Match('\\') || sc.Match('`'))))) { - // check for INCLUSIVE termination - if (o && strchr(")]};,", sc.ch)) { - if ((sc.Match(')') && sc.chPrev == '(') - || (sc.Match(']') && sc.chPrev == '[')) - // special-case "()" and "[]" tokens as KEYWORDS - sc.ChangeState(SCE_CAML_KEYWORD); - chColor++; - } else - advance = false; - state2 = SCE_CAML_DEFAULT; - } - break; - } - - case SCE_CAML_NUMBER: - // [try to] interpret as [additional] numeric literal char - if ((!isSML && sc.Match('_')) || IsADigit(sc.ch, chBase)) - break; - // how about an integer suffix? - if (!isSML && (sc.Match('l') || sc.Match('L') || sc.Match('n')) - && (sc.chPrev == '_' || IsADigit(sc.chPrev, chBase))) - break; - // or a floating-point literal? - if (chBase == 10) { - // with a decimal point? - if (sc.Match('.') - && ((!isSML && sc.chPrev == '_') - || IsADigit(sc.chPrev, chBase))) - break; - // with an exponent? (I) - if ((sc.Match('e') || sc.Match('E')) - && ((!isSML && (sc.chPrev == '.' || sc.chPrev == '_')) - || IsADigit(sc.chPrev, chBase))) - break; - // with an exponent? (II) - if (((!isSML && (sc.Match('+') || sc.Match('-'))) - || (isSML && sc.Match('~'))) - && (sc.chPrev == 'e' || sc.chPrev == 'E')) - break; - } - // it looks like we have run out of number - state2 = SCE_CAML_DEFAULT, advance = false; - break; - - case SCE_CAML_CHAR: - if (!isSML) { - // [try to] interpret as [additional] char literal char - if (sc.Match('\\')) { - chLit = 1; // (definitely IS a char literal) - if (sc.chPrev == '\\') - sc.ch = ' '; // (...\\') - // should we be terminating - one way or another? - } else if ((sc.Match('\'') && sc.chPrev != '\\') - || sc.atLineEnd) { - state2 = SCE_CAML_DEFAULT; - if (sc.Match('\'')) - chColor++; - else - sc.ChangeState(SCE_CAML_IDENTIFIER); - // ... maybe a char literal, maybe not - } else if (chLit < 1 && sc.currentPos - chToken >= 2) - sc.ChangeState(SCE_CAML_IDENTIFIER), advance = false; - break; - }/* else - // fall through for SML char literal (handle like string) */ - - case SCE_CAML_STRING: - // [try to] interpret as [additional] [SML char/] string literal char - if (isSML && sc.Match('\\') && sc.chPrev != '\\' && isspace(sc.chNext)) - state2 = SCE_CAML_WHITE; - else if (sc.Match('\\') && sc.chPrev == '\\') - sc.ch = ' '; // (...\\") - // should we be terminating - one way or another? - else if ((sc.Match('"') && sc.chPrev != '\\') - || (isSML && sc.atLineEnd)) { - state2 = SCE_CAML_DEFAULT; - if (sc.Match('"')) - chColor++; - } - break; - - case SCE_CAML_WHITE: - // [try to] interpret as [additional] SML embedded whitespace char - if (sc.Match('\\')) { - // style this puppy NOW... - state2 = SCE_CAML_STRING, sc.ch = ' ' /* (...\") */, chColor++, - styler.ColourTo(chColor, SCE_CAML_WHITE), styler.Flush(); - // ... then backtrack to determine original SML literal type - int p = chColor - 2; - for (; p >= 0 && styler.StyleAt(p) == SCE_CAML_WHITE; p--) ; - if (p >= 0) - state2 = static_cast(styler.StyleAt(p)); - // take care of state change NOW - sc.ChangeState(state2), state2 = -1; - } - break; - - case SCE_CAML_COMMENT: - case SCE_CAML_COMMENT1: - case SCE_CAML_COMMENT2: - case SCE_CAML_COMMENT3: - // we're IN a comment - does this start a NESTED comment? - if (sc.Match('(', '*')) - state2 = sc.state + 1, chToken = sc.currentPos, - sc.Forward(), sc.ch = ' ' /* (*)... */, nesting++; - // [try to] interpret as [additional] comment char - else if (sc.Match(')') && sc.chPrev == '*') { - if (nesting) - state2 = (sc.state & 0x0f) - 1, chToken = 0, nesting--; - else - state2 = SCE_CAML_DEFAULT; - chColor++; - // enable "magic" (read-only) comment AS REQUIRED - } else if (useMagic && sc.currentPos - chToken == 4 - && sc.Match('c') && sc.chPrev == 'r' && sc.GetRelative(-2) == '@') - sc.state |= 0x10; // (switch to read-only comment style) - break; - } - - // handle state change and char coloring AS REQUIRED - if (state2 >= 0) - styler.ColourTo(chColor, sc.state), sc.ChangeState(state2); - // move to next char UNLESS re-scanning current char - if (advance) - sc.Forward(); - } - - // do any required terminal char coloring (JIC) - sc.Complete(); -} - -#ifdef BUILD_AS_EXTERNAL_LEXER -static -#endif /* BUILD_AS_EXTERNAL_LEXER */ -void FoldCamlDoc( - unsigned int, int, - int, - WordList *[], - Accessor &) -{ -} - -static const char * const camlWordListDesc[] = { - "Keywords", // primary Objective Caml keywords - "Keywords2", // "optional" keywords (typically from Pervasives) - "Keywords3", // "optional" keywords (typically typenames) - 0 -}; - -#ifndef BUILD_AS_EXTERNAL_LEXER -LexerModule lmCaml(SCLEX_CAML, ColouriseCamlDoc, "caml", FoldCamlDoc, camlWordListDesc); -#endif /* BUILD_AS_EXTERNAL_LEXER */ diff --git a/src/LexCmake.cxx b/src/LexCmake.cxx deleted file mode 100644 index 1f51f474e..000000000 --- a/src/LexCmake.cxx +++ /dev/null @@ -1,457 +0,0 @@ -// Scintilla source code edit control -/** @file LexCmake.cxx - ** Lexer for Cmake - **/ -// Copyright 2007 by Cristian Adam -// based on the NSIS lexer -// The License.txt file describes the conditions under which this software may be distributed. -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "CharClassify.h" -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static bool isCmakeNumber(char ch) -{ - return(ch >= '0' && ch <= '9'); -} - -static bool isCmakeChar(char ch) -{ - return(ch == '.' ) || (ch == '_' ) || isCmakeNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); -} - -static bool isCmakeLetter(char ch) -{ - return(ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); -} - -static bool CmakeNextLineHasElse(unsigned int start, unsigned int end, Accessor &styler) -{ - int nNextLine = -1; - for ( unsigned int i = start; i < end; i++ ) { - char cNext = styler.SafeGetCharAt( i ); - if ( cNext == '\n' ) { - nNextLine = i+1; - break; - } - } - - if ( nNextLine == -1 ) // We never foudn the next line... - return false; - - for ( unsigned int firstChar = nNextLine; firstChar < end; firstChar++ ) { - char cNext = styler.SafeGetCharAt( firstChar ); - if ( cNext == ' ' ) - continue; - if ( cNext == '\t' ) - continue; - if ( styler.Match(firstChar, "ELSE") || styler.Match(firstChar, "else")) - return true; - break; - } - - return false; -} - -static int calculateFoldCmake(unsigned int start, unsigned int end, int foldlevel, Accessor &styler, bool bElse) -{ - // If the word is too long, it is not what we are looking for - if ( end - start > 20 ) - return foldlevel; - - int newFoldlevel = foldlevel; - - char s[20]; // The key word we are looking for has atmost 13 characters - for (unsigned int i = 0; i < end - start + 1 && i < 19; i++) { - s[i] = static_cast( styler[ start + i ] ); - s[i + 1] = '\0'; - } - - if ( CompareCaseInsensitive(s, "IF") == 0 || CompareCaseInsensitive(s, "WHILE") == 0 - || CompareCaseInsensitive(s, "MACRO") == 0 || CompareCaseInsensitive(s, "FOREACH") == 0 - || CompareCaseInsensitive(s, "ELSEIF") == 0 ) - newFoldlevel++; - else if ( CompareCaseInsensitive(s, "ENDIF") == 0 || CompareCaseInsensitive(s, "ENDWHILE") == 0 - || CompareCaseInsensitive(s, "ENDMACRO") == 0 || CompareCaseInsensitive(s, "ENDFOREACH") == 0) - newFoldlevel--; - else if ( bElse && CompareCaseInsensitive(s, "ELSEIF") == 0 ) - newFoldlevel++; - else if ( bElse && CompareCaseInsensitive(s, "ELSE") == 0 ) - newFoldlevel++; - - return newFoldlevel; -} - -static int classifyWordCmake(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler ) -{ - char word[100] = {0}; - char lowercaseWord[100] = {0}; - - WordList &Commands = *keywordLists[0]; - WordList &Parameters = *keywordLists[1]; - WordList &UserDefined = *keywordLists[2]; - - for (unsigned int i = 0; i < end - start + 1 && i < 99; i++) { - word[i] = static_cast( styler[ start + i ] ); - lowercaseWord[i] = static_cast(tolower(word[i])); - } - - // Check for special words... - if ( CompareCaseInsensitive(word, "MACRO") == 0 || CompareCaseInsensitive(word, "ENDMACRO") == 0 ) - return SCE_CMAKE_MACRODEF; - - if ( CompareCaseInsensitive(word, "IF") == 0 || CompareCaseInsensitive(word, "ENDIF") == 0 ) - return SCE_CMAKE_IFDEFINEDEF; - - if ( CompareCaseInsensitive(word, "ELSEIF") == 0 || CompareCaseInsensitive(word, "ELSE") == 0 ) - return SCE_CMAKE_IFDEFINEDEF; - - if ( CompareCaseInsensitive(word, "WHILE") == 0 || CompareCaseInsensitive(word, "ENDWHILE") == 0) - return SCE_CMAKE_WHILEDEF; - - if ( CompareCaseInsensitive(word, "FOREACH") == 0 || CompareCaseInsensitive(word, "ENDFOREACH") == 0) - return SCE_CMAKE_FOREACHDEF; - - if ( Commands.InList(lowercaseWord) ) - return SCE_CMAKE_COMMANDS; - - if ( Parameters.InList(word) ) - return SCE_CMAKE_PARAMETERS; - - - if ( UserDefined.InList(word) ) - return SCE_CMAKE_USERDEFINED; - - if ( strlen(word) > 3 ) { - if ( word[1] == '{' && word[strlen(word)-1] == '}' ) - return SCE_CMAKE_VARIABLE; - } - - // To check for numbers - if ( isCmakeNumber( word[0] ) ) { - bool bHasSimpleCmakeNumber = true; - for (unsigned int j = 1; j < end - start + 1 && j < 99; j++) { - if ( !isCmakeNumber( word[j] ) ) { - bHasSimpleCmakeNumber = false; - break; - } - } - - if ( bHasSimpleCmakeNumber ) - return SCE_CMAKE_NUMBER; - } - - return SCE_CMAKE_DEFAULT; -} - -static void ColouriseCmakeDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) -{ - int state = SCE_CMAKE_DEFAULT; - if ( startPos > 0 ) - state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox - - styler.StartAt( startPos ); - styler.GetLine( startPos ); - - unsigned int nLengthDoc = startPos + length; - styler.StartSegment( startPos ); - - char cCurrChar; - bool bVarInString = false; - bool bClassicVarInString = false; - - unsigned int i; - for ( i = startPos; i < nLengthDoc; i++ ) { - cCurrChar = styler.SafeGetCharAt( i ); - char cNextChar = styler.SafeGetCharAt(i+1); - - switch (state) { - case SCE_CMAKE_DEFAULT: - if ( cCurrChar == '#' ) { // we have a comment line - styler.ColourTo(i-1, state ); - state = SCE_CMAKE_COMMENT; - break; - } - if ( cCurrChar == '"' ) { - styler.ColourTo(i-1, state ); - state = SCE_CMAKE_STRINGDQ; - bVarInString = false; - bClassicVarInString = false; - break; - } - if ( cCurrChar == '\'' ) { - styler.ColourTo(i-1, state ); - state = SCE_CMAKE_STRINGRQ; - bVarInString = false; - bClassicVarInString = false; - break; - } - if ( cCurrChar == '`' ) { - styler.ColourTo(i-1, state ); - state = SCE_CMAKE_STRINGLQ; - bVarInString = false; - bClassicVarInString = false; - break; - } - - // CMake Variable - if ( cCurrChar == '$' || isCmakeChar(cCurrChar)) { - styler.ColourTo(i-1,state); - state = SCE_CMAKE_VARIABLE; - - // If it is a number, we must check and set style here first... - if ( isCmakeNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) ) - styler.ColourTo( i, SCE_CMAKE_NUMBER); - - break; - } - - break; - case SCE_CMAKE_COMMENT: - if ( cNextChar == '\n' || cNextChar == '\r' ) { - // Special case: - if ( cCurrChar == '\\' ) { - styler.ColourTo(i-2,state); - styler.ColourTo(i,SCE_CMAKE_DEFAULT); - } - else { - styler.ColourTo(i,state); - state = SCE_CMAKE_DEFAULT; - } - } - break; - case SCE_CMAKE_STRINGDQ: - case SCE_CMAKE_STRINGLQ: - case SCE_CMAKE_STRINGRQ: - - if ( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' ) - break; // Ignore the next character, even if it is a quote of some sort - - if ( cCurrChar == '"' && state == SCE_CMAKE_STRINGDQ ) { - styler.ColourTo(i,state); - state = SCE_CMAKE_DEFAULT; - break; - } - - if ( cCurrChar == '`' && state == SCE_CMAKE_STRINGLQ ) { - styler.ColourTo(i,state); - state = SCE_CMAKE_DEFAULT; - break; - } - - if ( cCurrChar == '\'' && state == SCE_CMAKE_STRINGRQ ) { - styler.ColourTo(i,state); - state = SCE_CMAKE_DEFAULT; - break; - } - - if ( cNextChar == '\r' || cNextChar == '\n' ) { - int nCurLine = styler.GetLine(i+1); - int nBack = i; - // We need to check if the previous line has a \ in it... - bool bNextLine = false; - - while ( nBack > 0 ) { - if ( styler.GetLine(nBack) != nCurLine ) - break; - - char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here - - if ( cTemp == '\\' ) { - bNextLine = true; - break; - } - if ( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' ) - break; - - nBack--; - } - - if ( bNextLine ) { - styler.ColourTo(i+1,state); - } - if ( bNextLine == false ) { - styler.ColourTo(i,state); - state = SCE_CMAKE_DEFAULT; - } - } - break; - - case SCE_CMAKE_VARIABLE: - - // CMake Variable: - if ( cCurrChar == '$' ) - state = SCE_CMAKE_DEFAULT; - else if ( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) ) - state = SCE_CMAKE_DEFAULT; - else if ( (isCmakeChar(cCurrChar) && !isCmakeChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' ) { - state = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler ); - styler.ColourTo( i, state); - state = SCE_CMAKE_DEFAULT; - } - else if ( !isCmakeChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' ) { - if ( classifyWordCmake( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_CMAKE_NUMBER ) - styler.ColourTo( i-1, SCE_CMAKE_NUMBER ); - - state = SCE_CMAKE_DEFAULT; - - if ( cCurrChar == '"' ) { - state = SCE_CMAKE_STRINGDQ; - bVarInString = false; - bClassicVarInString = false; - } - else if ( cCurrChar == '`' ) { - state = SCE_CMAKE_STRINGLQ; - bVarInString = false; - bClassicVarInString = false; - } - else if ( cCurrChar == '\'' ) { - state = SCE_CMAKE_STRINGRQ; - bVarInString = false; - bClassicVarInString = false; - } - else if ( cCurrChar == '#' ) { - state = SCE_CMAKE_COMMENT; - } - } - break; - } - - if ( state == SCE_CMAKE_COMMENT) { - styler.ColourTo(i,state); - } - else if ( state == SCE_CMAKE_STRINGDQ || state == SCE_CMAKE_STRINGLQ || state == SCE_CMAKE_STRINGRQ ) { - bool bIngoreNextDollarSign = false; - - if ( bVarInString && cCurrChar == '$' ) { - bVarInString = false; - bIngoreNextDollarSign = true; - } - else if ( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) ) { - styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR); - bVarInString = false; - bIngoreNextDollarSign = false; - } - - else if ( bVarInString && !isCmakeChar(cNextChar) ) { - int nWordState = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler); - if ( nWordState == SCE_CMAKE_VARIABLE ) - styler.ColourTo( i, SCE_CMAKE_STRINGVAR); - bVarInString = false; - } - // Covers "${TEST}..." - else if ( bClassicVarInString && cNextChar == '}' ) { - styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR); - bClassicVarInString = false; - } - - // Start of var in string - if ( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' ) { - styler.ColourTo( i-1, state); - bClassicVarInString = true; - bVarInString = false; - } - else if ( !bIngoreNextDollarSign && cCurrChar == '$' ) { - styler.ColourTo( i-1, state); - bVarInString = true; - bClassicVarInString = false; - } - } - } - - // Colourise remaining document - styler.ColourTo(nLengthDoc-1,state); -} - -static void FoldCmakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) -{ - // No folding enabled, no reason to continue... - if ( styler.GetPropertyInt("fold") == 0 ) - return; - - bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1; - - int lineCurrent = styler.GetLine(startPos); - unsigned int safeStartPos = styler.LineStart( lineCurrent ); - - bool bArg1 = true; - int nWordStart = -1; - - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelNext = levelCurrent; - - for (unsigned int i = safeStartPos; i < startPos + length; i++) { - char chCurr = styler.SafeGetCharAt(i); - - if ( bArg1 ) { - if ( nWordStart == -1 && (isCmakeLetter(chCurr)) ) { - nWordStart = i; - } - else if ( isCmakeLetter(chCurr) == false && nWordStart > -1 ) { - int newLevel = calculateFoldCmake( nWordStart, i-1, levelNext, styler, foldAtElse); - - if ( newLevel == levelNext ) { - if ( foldAtElse ) { - if ( CmakeNextLineHasElse(i, startPos + length, styler) ) - levelNext--; - } - } - else - levelNext = newLevel; - bArg1 = false; - } - } - - if ( chCurr == '\n' ) { - if ( bArg1 && foldAtElse) { - if ( CmakeNextLineHasElse(i, startPos + length, styler) ) - levelNext--; - } - - // If we are on a new line... - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - if (levelUse < levelNext ) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) - styler.SetLevel(lineCurrent, lev); - - lineCurrent++; - levelCurrent = levelNext; - bArg1 = true; // New line, lets look at first argument again - nWordStart = -1; - } - } - - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) - styler.SetLevel(lineCurrent, lev); -} - -static const char * const cmakeWordLists[] = { - "Commands", - "Parameters", - "UserDefined", - 0, - 0,}; - -LexerModule lmCmake(SCLEX_CMAKE, ColouriseCmakeDoc, "cmake", FoldCmakeDoc, cmakeWordLists); diff --git a/src/LexConf.cxx b/src/LexConf.cxx deleted file mode 100644 index 7b066af7b..000000000 --- a/src/LexConf.cxx +++ /dev/null @@ -1,188 +0,0 @@ -// Scintilla source code edit control -/** @file LexConf.cxx - ** Lexer for Apache Configuration Files. - ** - ** First working version contributed by Ahmad Zawawi on October 28, 2000. - ** i created this lexer because i needed something pretty when dealing - ** when Apache Configuration files... - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static void ColouriseConfDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) -{ - int state = SCE_CONF_DEFAULT; - char chNext = styler[startPos]; - int lengthDoc = startPos + length; - // create a buffer large enough to take the largest chunk... - char *buffer = new char[length]; - int bufferCount = 0; - - // this assumes that we have 2 keyword list in conf.properties - WordList &directives = *keywordLists[0]; - WordList ¶ms = *keywordLists[1]; - - // go through all provided text segment - // using the hand-written state machine shown below - styler.StartAt(startPos); - styler.StartSegment(startPos); - for (int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - i++; - continue; - } - switch(state) { - case SCE_CONF_DEFAULT: - if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') { - // whitespace is simply ignored here... - styler.ColourTo(i,SCE_CONF_DEFAULT); - break; - } else if( ch == '#' ) { - // signals the start of a comment... - state = SCE_CONF_COMMENT; - styler.ColourTo(i,SCE_CONF_COMMENT); - } else if( ch == '.' /*|| ch == '/'*/) { - // signals the start of a file... - state = SCE_CONF_EXTENSION; - styler.ColourTo(i,SCE_CONF_EXTENSION); - } else if( ch == '"') { - state = SCE_CONF_STRING; - styler.ColourTo(i,SCE_CONF_STRING); - } else if( isascii(ch) && ispunct(ch) ) { - // signals an operator... - // no state jump necessary for this - // simple case... - styler.ColourTo(i,SCE_CONF_OPERATOR); - } else if( isascii(ch) && isalpha(ch) ) { - // signals the start of an identifier - bufferCount = 0; - buffer[bufferCount++] = static_cast(tolower(ch)); - state = SCE_CONF_IDENTIFIER; - } else if( isascii(ch) && isdigit(ch) ) { - // signals the start of a number - bufferCount = 0; - buffer[bufferCount++] = ch; - //styler.ColourTo(i,SCE_CONF_NUMBER); - state = SCE_CONF_NUMBER; - } else { - // style it the default style.. - styler.ColourTo(i,SCE_CONF_DEFAULT); - } - break; - - case SCE_CONF_COMMENT: - // if we find a newline here, - // we simply go to default state - // else continue to work on it... - if( ch == '\n' || ch == '\r' ) { - state = SCE_CONF_DEFAULT; - } else { - styler.ColourTo(i,SCE_CONF_COMMENT); - } - break; - - case SCE_CONF_EXTENSION: - // if we find a non-alphanumeric char, - // we simply go to default state - // else we're still dealing with an extension... - if( (isascii(ch) && isalnum(ch)) || (ch == '_') || - (ch == '-') || (ch == '$') || - (ch == '/') || (ch == '.') || (ch == '*') ) - { - styler.ColourTo(i,SCE_CONF_EXTENSION); - } else { - state = SCE_CONF_DEFAULT; - chNext = styler[i--]; - } - break; - - case SCE_CONF_STRING: - // if we find the end of a string char, we simply go to default state - // else we're still dealing with an string... - if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') || (ch == '\n') || (ch == '\r') ) { - state = SCE_CONF_DEFAULT; - } - styler.ColourTo(i,SCE_CONF_STRING); - break; - - case SCE_CONF_IDENTIFIER: - // stay in CONF_IDENTIFIER state until we find a non-alphanumeric - if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') || (ch == '$') || (ch == '.') || (ch == '*')) { - buffer[bufferCount++] = static_cast(tolower(ch)); - } else { - state = SCE_CONF_DEFAULT; - buffer[bufferCount] = '\0'; - - // check if the buffer contains a keyword, and highlight it if it is a keyword... - if(directives.InList(buffer)) { - styler.ColourTo(i-1,SCE_CONF_DIRECTIVE ); - } else if(params.InList(buffer)) { - styler.ColourTo(i-1,SCE_CONF_PARAMETER ); - } else if(strchr(buffer,'/') || strchr(buffer,'.')) { - styler.ColourTo(i-1,SCE_CONF_EXTENSION); - } else { - styler.ColourTo(i-1,SCE_CONF_DEFAULT); - } - - // push back the faulty character - chNext = styler[i--]; - - } - break; - - case SCE_CONF_NUMBER: - // stay in CONF_NUMBER state until we find a non-numeric - if( (isascii(ch) && isdigit(ch)) || ch == '.') { - buffer[bufferCount++] = ch; - } else { - state = SCE_CONF_DEFAULT; - buffer[bufferCount] = '\0'; - - // Colourize here... - if( strchr(buffer,'.') ) { - // it is an IP address... - styler.ColourTo(i-1,SCE_CONF_IP); - } else { - // normal number - styler.ColourTo(i-1,SCE_CONF_NUMBER); - } - - // push back a character - chNext = styler[i--]; - } - break; - - } - } - delete []buffer; -} - -static const char * const confWordListDesc[] = { - "Directives", - "Parameters", - 0 -}; - -LexerModule lmConf(SCLEX_CONF, ColouriseConfDoc, "conf", 0, confWordListDesc); diff --git a/src/LexCrontab.cxx b/src/LexCrontab.cxx deleted file mode 100644 index f6c4d42f1..000000000 --- a/src/LexCrontab.cxx +++ /dev/null @@ -1,222 +0,0 @@ -// Scintilla source code edit control -/** @file LexCrontab.cxx - ** Lexer to use with extended crontab files used by a powerful - ** Windows scheduler/event monitor/automation manager nnCron. - ** (http://nemtsev.eserv.ru/) - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static void ColouriseNncrontabDoc(unsigned int startPos, int length, int, WordList -*keywordLists[], Accessor &styler) -{ - int state = SCE_NNCRONTAB_DEFAULT; - char chNext = styler[startPos]; - int lengthDoc = startPos + length; - // create a buffer large enough to take the largest chunk... - char *buffer = new char[length]; - int bufferCount = 0; - // used when highliting environment variables inside quoted string: - bool insideString = false; - - // this assumes that we have 3 keyword list in conf.properties - WordList §ion = *keywordLists[0]; - WordList &keyword = *keywordLists[1]; - WordList &modifier = *keywordLists[2]; - - // go through all provided text segment - // using the hand-written state machine shown below - styler.StartAt(startPos); - styler.StartSegment(startPos); - for (int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - i++; - continue; - } - switch(state) { - case SCE_NNCRONTAB_DEFAULT: - if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') { - // whitespace is simply ignored here... - styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT); - break; - } else if( ch == '#' && styler.SafeGetCharAt(i+1) == '(') { - // signals the start of a task... - state = SCE_NNCRONTAB_TASK; - styler.ColourTo(i,SCE_NNCRONTAB_TASK); - } - else if( ch == '\\' && (styler.SafeGetCharAt(i+1) == ' ' || - styler.SafeGetCharAt(i+1) == '\t')) { - // signals the start of an extended comment... - state = SCE_NNCRONTAB_COMMENT; - styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); - } else if( ch == '#' ) { - // signals the start of a plain comment... - state = SCE_NNCRONTAB_COMMENT; - styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); - } else if( ch == ')' && styler.SafeGetCharAt(i+1) == '#') { - // signals the end of a task... - state = SCE_NNCRONTAB_TASK; - styler.ColourTo(i,SCE_NNCRONTAB_TASK); - } else if( ch == '"') { - state = SCE_NNCRONTAB_STRING; - styler.ColourTo(i,SCE_NNCRONTAB_STRING); - } else if( ch == '%') { - // signals environment variables - state = SCE_NNCRONTAB_ENVIRONMENT; - styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); - } else if( ch == '<' && styler.SafeGetCharAt(i+1) == '%') { - // signals environment variables - state = SCE_NNCRONTAB_ENVIRONMENT; - styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); - } else if( ch == '*' ) { - // signals an asterisk - // no state jump necessary for this simple case... - styler.ColourTo(i,SCE_NNCRONTAB_ASTERISK); - } else if( (isascii(ch) && isalpha(ch)) || ch == '<' ) { - // signals the start of an identifier - bufferCount = 0; - buffer[bufferCount++] = ch; - state = SCE_NNCRONTAB_IDENTIFIER; - } else if( isascii(ch) && isdigit(ch) ) { - // signals the start of a number - bufferCount = 0; - buffer[bufferCount++] = ch; - state = SCE_NNCRONTAB_NUMBER; - } else { - // style it the default style.. - styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT); - } - break; - - case SCE_NNCRONTAB_COMMENT: - // if we find a newline here, - // we simply go to default state - // else continue to work on it... - if( ch == '\n' || ch == '\r' ) { - state = SCE_NNCRONTAB_DEFAULT; - } else { - styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); - } - break; - - case SCE_NNCRONTAB_TASK: - // if we find a newline here, - // we simply go to default state - // else continue to work on it... - if( ch == '\n' || ch == '\r' ) { - state = SCE_NNCRONTAB_DEFAULT; - } else { - styler.ColourTo(i,SCE_NNCRONTAB_TASK); - } - break; - - case SCE_NNCRONTAB_STRING: - if( ch == '%' ) { - state = SCE_NNCRONTAB_ENVIRONMENT; - insideString = true; - styler.ColourTo(i-1,SCE_NNCRONTAB_STRING); - break; - } - // if we find the end of a string char, we simply go to default state - // else we're still dealing with an string... - if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') || - (ch == '\n') || (ch == '\r') ) { - state = SCE_NNCRONTAB_DEFAULT; - } - styler.ColourTo(i,SCE_NNCRONTAB_STRING); - break; - - case SCE_NNCRONTAB_ENVIRONMENT: - // if we find the end of a string char, we simply go to default state - // else we're still dealing with an string... - if( ch == '%' && insideString ) { - state = SCE_NNCRONTAB_STRING; - insideString = false; - break; - } - if( (ch == '%' && styler.SafeGetCharAt(i-1)!='\\') - || (ch == '\n') || (ch == '\r') || (ch == '>') ) { - state = SCE_NNCRONTAB_DEFAULT; - styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); - break; - } - styler.ColourTo(i+1,SCE_NNCRONTAB_ENVIRONMENT); - break; - - case SCE_NNCRONTAB_IDENTIFIER: - // stay in CONF_IDENTIFIER state until we find a non-alphanumeric - if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') || - (ch == '$') || (ch == '.') || (ch == '<') || (ch == '>') || - (ch == '@') ) { - buffer[bufferCount++] = ch; - } else { - state = SCE_NNCRONTAB_DEFAULT; - buffer[bufferCount] = '\0'; - - // check if the buffer contains a keyword, - // and highlight it if it is a keyword... - if(section.InList(buffer)) { - styler.ColourTo(i,SCE_NNCRONTAB_SECTION ); - } else if(keyword.InList(buffer)) { - styler.ColourTo(i-1,SCE_NNCRONTAB_KEYWORD ); - } // else if(strchr(buffer,'/') || strchr(buffer,'.')) { - // styler.ColourTo(i-1,SCE_NNCRONTAB_EXTENSION); - // } - else if(modifier.InList(buffer)) { - styler.ColourTo(i-1,SCE_NNCRONTAB_MODIFIER ); - } else { - styler.ColourTo(i-1,SCE_NNCRONTAB_DEFAULT); - } - // push back the faulty character - chNext = styler[i--]; - } - break; - - case SCE_NNCRONTAB_NUMBER: - // stay in CONF_NUMBER state until we find a non-numeric - if( isascii(ch) && isdigit(ch) /* || ch == '.' */ ) { - buffer[bufferCount++] = ch; - } else { - state = SCE_NNCRONTAB_DEFAULT; - buffer[bufferCount] = '\0'; - // Colourize here... (normal number) - styler.ColourTo(i-1,SCE_NNCRONTAB_NUMBER); - // push back a character - chNext = styler[i--]; - } - break; - } - } - delete []buffer; -} - -static const char * const cronWordListDesc[] = { - "Section keywords and Forth words", - "nnCrontab keywords", - "Modifiers", - 0 -}; - -LexerModule lmNncrontab(SCLEX_NNCRONTAB, ColouriseNncrontabDoc, "nncrontab", 0, cronWordListDesc); diff --git a/src/LexCsound.cxx b/src/LexCsound.cxx deleted file mode 100644 index 3aa2eb897..000000000 --- a/src/LexCsound.cxx +++ /dev/null @@ -1,210 +0,0 @@ -// Scintilla source code edit control -/** @file LexCsound.cxx - ** Lexer for Csound (Orchestra & Score) - ** Written by Georg Ritter - - **/ -// Copyright 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || - ch == '_' || ch == '?'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' || - ch == '%' || ch == '@' || ch == '$' || ch == '?'); -} - -static inline bool IsCsoundOperator(char ch) { - if (isascii(ch) && isalnum(ch)) - return false; - // '.' left out as it is used to make up numbers - if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || - ch == '(' || ch == ')' || ch == '=' || ch == '^' || - ch == '[' || ch == ']' || ch == '<' || ch == '&' || - ch == '>' || ch == ',' || ch == '|' || ch == '~' || - ch == '%' || ch == ':') - return true; - return false; -} - -static void ColouriseCsoundDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &opcode = *keywordlists[0]; - WordList &headerStmt = *keywordlists[1]; - WordList &otherKeyword = *keywordlists[2]; - - // Do not leak onto next line - if (initStyle == SCE_CSOUND_STRINGEOL) - initStyle = SCE_CSOUND_DEFAULT; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) - { - // Handle line continuation generically. - if (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_CSOUND_OPERATOR) { - if (!IsCsoundOperator(static_cast(sc.ch))) { - sc.SetState(SCE_CSOUND_DEFAULT); - } - }else if (sc.state == SCE_CSOUND_NUMBER) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_CSOUND_DEFAULT); - } - } else if (sc.state == SCE_CSOUND_IDENTIFIER) { - if (!IsAWordChar(sc.ch) ) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - - if (opcode.InList(s)) { - sc.ChangeState(SCE_CSOUND_OPCODE); - } else if (headerStmt.InList(s)) { - sc.ChangeState(SCE_CSOUND_HEADERSTMT); - } else if (otherKeyword.InList(s)) { - sc.ChangeState(SCE_CSOUND_USERKEYWORD); - } else if (s[0] == 'p') { - sc.ChangeState(SCE_CSOUND_PARAM); - } else if (s[0] == 'a') { - sc.ChangeState(SCE_CSOUND_ARATE_VAR); - } else if (s[0] == 'k') { - sc.ChangeState(SCE_CSOUND_KRATE_VAR); - } else if (s[0] == 'i') { // covers both i-rate variables and i-statements - sc.ChangeState(SCE_CSOUND_IRATE_VAR); - } else if (s[0] == 'g') { - sc.ChangeState(SCE_CSOUND_GLOBAL_VAR); - } - sc.SetState(SCE_CSOUND_DEFAULT); - } - } - else if (sc.state == SCE_CSOUND_COMMENT ) { - if (sc.atLineEnd) { - sc.SetState(SCE_CSOUND_DEFAULT); - } - } - else if ((sc.state == SCE_CSOUND_ARATE_VAR) || - (sc.state == SCE_CSOUND_KRATE_VAR) || - (sc.state == SCE_CSOUND_IRATE_VAR)) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_CSOUND_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_CSOUND_DEFAULT) { - if (sc.ch == ';'){ - sc.SetState(SCE_CSOUND_COMMENT); - } else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) { - sc.SetState(SCE_CSOUND_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_CSOUND_IDENTIFIER); - } else if (IsCsoundOperator(static_cast(sc.ch))) { - sc.SetState(SCE_CSOUND_OPERATOR); - } else if (sc.ch == 'p') { - sc.SetState(SCE_CSOUND_PARAM); - } else if (sc.ch == 'a') { - sc.SetState(SCE_CSOUND_ARATE_VAR); - } else if (sc.ch == 'k') { - sc.SetState(SCE_CSOUND_KRATE_VAR); - } else if (sc.ch == 'i') { // covers both i-rate variables and i-statements - sc.SetState(SCE_CSOUND_IRATE_VAR); - } else if (sc.ch == 'g') { - sc.SetState(SCE_CSOUND_GLOBAL_VAR); - } - } - } - sc.Complete(); -} - -static void FoldCsoundInstruments(unsigned int startPos, int length, int /* initStyle */, WordList *[], - Accessor &styler) { - unsigned int lengthDoc = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int stylePrev = 0; - int styleNext = styler.StyleAt(startPos); - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if ((stylePrev != SCE_CSOUND_OPCODE) && (style == SCE_CSOUND_OPCODE)) { - char s[20]; - unsigned int j = 0; - while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) { - s[j] = styler[i + j]; - j++; - } - s[j] = '\0'; - - if (strcmp(s, "instr") == 0) - levelCurrent++; - if (strcmp(s, "endin") == 0) - levelCurrent--; - } - - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - stylePrev = style; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - - -static const char * const csoundWordListDesc[] = { - "Opcodes", - "Header Statements", - "User keywords", - 0 -}; - -LexerModule lmCsound(SCLEX_CSOUND, ColouriseCsoundDoc, "csound", FoldCsoundInstruments, csoundWordListDesc); diff --git a/src/LexD.cxx b/src/LexD.cxx deleted file mode 100644 index 4c4bcb343..000000000 --- a/src/LexD.cxx +++ /dev/null @@ -1,399 +0,0 @@ -/** @file LexD.cxx - ** Lexer for D. - ** - ** Copyright (c) 2006 by Waldemar Augustyn - **/ -// Copyright 1998-2005 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/* Nested comments require keeping the value of the nesting level for every - position in the document. But since scintilla always styles line by line, - we only need to store one value per line. The non-negative number indicates - nesting level at the end of the line. -*/ - -// Underscore, letter, digit and universal alphas from C99 Appendix D. - -static bool IsWordStart(int ch) { - return (isascii(ch) && (isalpha(ch) || ch == '_')) || !isascii(ch); -} - -static bool IsWord(int ch) { - return (isascii(ch) && (isalnum(ch) || ch == '_')) || !isascii(ch); -} - -static bool IsDoxygen(int ch) { - if (isascii(ch) && islower(ch)) - return true; - if (ch == '$' || ch == '@' || ch == '\\' || - ch == '&' || ch == '#' || ch == '<' || ch == '>' || - ch == '{' || ch == '}' || ch == '[' || ch == ']') - return true; - return false; -} - -static bool IsStringSuffix(int ch) { - return ch == 'c' || ch == 'w' || ch == 'd'; -} - - -static void ColouriseDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler, bool caseSensitive) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; //doxygen - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - WordList &keywords6 = *keywordlists[5]; - WordList &keywords7 = *keywordlists[6]; - - int styleBeforeDCKeyword = SCE_D_DEFAULT; - - StyleContext sc(startPos, length, initStyle, styler); - - int curLine = styler.GetLine(startPos); - int curNcLevel = curLine > 0? styler.GetLineState(curLine-1): 0; - bool numFloat = false; // Float literals have '+' and '-' signs - bool numHex = false; - - for (; sc.More(); sc.Forward()) { - - if (sc.atLineStart) { - curLine = styler.GetLine(sc.currentPos); - styler.SetLineState(curLine, curNcLevel); - } - - // Determine if the current state should terminate. - switch (sc.state) { - case SCE_D_OPERATOR: - sc.SetState(SCE_D_DEFAULT); - break; - case SCE_D_NUMBER: - // We accept almost anything because of hex. and number suffixes - if (isascii(sc.ch) && (isalnum(sc.ch) || sc.ch == '_')) { - continue; - } else if (sc.ch == '.' && sc.chNext != '.' && !numFloat) { - // Don't parse 0..2 as number. - numFloat=true; - continue; - } else if ( ( sc.ch == '-' || sc.ch == '+' ) && ( /*sign and*/ - ( !numHex && ( sc.chPrev == 'e' || sc.chPrev == 'E' ) ) || /*decimal or*/ - ( sc.chPrev == 'p' || sc.chPrev == 'P' ) ) ) { /*hex*/ - // Parse exponent sign in float literals: 2e+10 0x2e+10 - continue; - } else { - sc.SetState(SCE_D_DEFAULT); - } - break; - case SCE_D_IDENTIFIER: - if (!IsWord(sc.ch)) { - char s[1000]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); - } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - if (keywords.InList(s)) { - sc.ChangeState(SCE_D_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_D_WORD2); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_D_TYPEDEF); - } else if (keywords5.InList(s)) { - sc.ChangeState(SCE_D_WORD5); - } else if (keywords6.InList(s)) { - sc.ChangeState(SCE_D_WORD6); - } else if (keywords7.InList(s)) { - sc.ChangeState(SCE_D_WORD7); - } - sc.SetState(SCE_D_DEFAULT); - } - break; - case SCE_D_COMMENT: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_D_DEFAULT); - } - break; - case SCE_D_COMMENTDOC: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_D_DEFAULT); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_D_COMMENTDOC; - sc.SetState(SCE_D_COMMENTDOCKEYWORD); - } - } - break; - case SCE_D_COMMENTLINE: - if (sc.atLineStart) { - sc.SetState(SCE_D_DEFAULT); - } - break; - case SCE_D_COMMENTLINEDOC: - if (sc.atLineStart) { - sc.SetState(SCE_D_DEFAULT); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_D_COMMENTLINEDOC; - sc.SetState(SCE_D_COMMENTDOCKEYWORD); - } - } - break; - case SCE_D_COMMENTDOCKEYWORD: - if ((styleBeforeDCKeyword == SCE_D_COMMENTDOC) && sc.Match('*', '/')) { - sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR); - sc.Forward(); - sc.ForwardSetState(SCE_D_DEFAULT); - } else if (!IsDoxygen(sc.ch)) { - char s[100]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); - } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { - sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR); - } - sc.SetState(styleBeforeDCKeyword); - } - break; - case SCE_D_COMMENTNESTED: - if (sc.Match('+', '/')) { - if (curNcLevel > 0) - curNcLevel -= 1; - curLine = styler.GetLine(sc.currentPos); - styler.SetLineState(curLine, curNcLevel); - sc.Forward(); - if (curNcLevel == 0) { - sc.ForwardSetState(SCE_D_DEFAULT); - } - } else if (sc.Match('/','+')) { - curNcLevel += 1; - curLine = styler.GetLine(sc.currentPos); - styler.SetLineState(curLine, curNcLevel); - sc.Forward(); - } - break; - case SCE_D_STRING: - if (sc.ch == '\\') { - if (sc.chNext == '"' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '"') { - if(IsStringSuffix(sc.chNext)) - sc.Forward(); - sc.ForwardSetState(SCE_D_DEFAULT); - } - break; - case SCE_D_CHARACTER: - if (sc.atLineEnd) { - sc.ChangeState(SCE_D_STRINGEOL); - } else if (sc.ch == '\\') { - if (sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - // Char has no suffixes - sc.ForwardSetState(SCE_D_DEFAULT); - } - break; - case SCE_D_STRINGEOL: - if (sc.atLineStart) { - sc.SetState(SCE_D_DEFAULT); - } - break; - case SCE_D_STRINGB: - if (sc.ch == '`') { - if(IsStringSuffix(sc.chNext)) - sc.Forward(); - sc.ForwardSetState(SCE_D_DEFAULT); - } - break; - case SCE_D_STRINGR: - if (sc.ch == '"') { - if(IsStringSuffix(sc.chNext)) - sc.Forward(); - sc.ForwardSetState(SCE_D_DEFAULT); - } - break; - } - - // Determine if a new state should be entered. - if (sc.state == SCE_D_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_D_NUMBER); - numFloat = sc.ch == '.'; - // Remember hex literal - numHex = sc.ch == '0' && ( sc.chNext == 'x' || sc.chNext == 'X' ); - } else if ( (sc.ch == 'r' || sc.ch == 'x' || sc.ch == 'q') - && sc.chNext == '"' ) { - // Limited support for hex and delimited strings: parse as r"" - sc.SetState(SCE_D_STRINGR); - sc.Forward(); - } else if (IsWordStart(sc.ch) || sc.ch == '$') { - sc.SetState(SCE_D_IDENTIFIER); - } else if (sc.Match('/','+')) { - curNcLevel += 1; - curLine = styler.GetLine(sc.currentPos); - styler.SetLineState(curLine, curNcLevel); - sc.SetState(SCE_D_COMMENTNESTED); - sc.Forward(); - } else if (sc.Match('/', '*')) { - if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style - sc.SetState(SCE_D_COMMENTDOC); - } else { - sc.SetState(SCE_D_COMMENT); - } - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match('/', '/')) { - if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!")) - // Support of Qt/Doxygen doc. style - sc.SetState(SCE_D_COMMENTLINEDOC); - else - sc.SetState(SCE_D_COMMENTLINE); - } else if (sc.ch == '"') { - sc.SetState(SCE_D_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_D_CHARACTER); - } else if (sc.ch == '`') { - sc.SetState(SCE_D_STRINGB); - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_D_OPERATOR); - if (sc.ch == '.' && sc.chNext == '.') sc.Forward(); // Range operator - } - } - } - sc.Complete(); -} - -static bool IsStreamCommentStyle(int style) { - return style == SCE_D_COMMENT || - style == SCE_D_COMMENTDOC || - style == SCE_D_COMMENTDOCKEYWORD || - style == SCE_D_COMMENTDOCKEYWORDERROR; -} - -// Store both the current line's fold level and the next lines in the -// level store to make it easy to pick up with each increment -// and to make it possible to fiddle the current level for "} else {". -static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - - // property lexer.d.fold.at.else - // This option enables D folding on a "} else {" line of an if statement. - bool foldAtElse = styler.GetPropertyInt("lexer.d.fold.at.else", - styler.GetPropertyInt("fold.at.else", 0)) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelMinCurrent = levelCurrent; - int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && IsStreamCommentStyle(style)) { - if (!IsStreamCommentStyle(stylePrev)) { - levelNext++; - } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelNext--; - } - } - if (style == SCE_D_OPERATOR) { - if (ch == '{') { - // Measure the minimum before a '{' to allow - // folding on "} else {" - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - levelNext++; - } else if (ch == '}') { - levelNext--; - } - } - if (atEOL) { - if (foldComment) { // Handle nested comments - int nc; - nc = styler.GetLineState(lineCurrent); - nc -= lineCurrent>0? styler.GetLineState(lineCurrent-1): 0; - levelNext += nc; - } - int levelUse = levelCurrent; - if (foldAtElse) { - levelUse = levelMinCurrent; - } - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - levelMinCurrent = levelCurrent; - visibleChars = 0; - } - if (!IsASpace(ch)) - visibleChars++; - } -} - -static void FoldDDoc(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) { - FoldDoc(startPos, length, initStyle, styler); -} - -static const char * const dWordLists[] = { - "Primary keywords and identifiers", - "Secondary keywords and identifiers", - "Documentation comment keywords", - "Type definitions and aliases", - "Keywords 5", - "Keywords 6", - "Keywords 7", - 0, - }; - -static void ColouriseDDoc(unsigned int startPos, int length, - int initStyle, WordList *keywordlists[], Accessor &styler) { - ColouriseDoc(startPos, length, initStyle, keywordlists, styler, true); -} - -LexerModule lmD(SCLEX_D, ColouriseDDoc, "d", FoldDDoc, dWordLists); diff --git a/src/LexEScript.cxx b/src/LexEScript.cxx deleted file mode 100644 index 295aaec53..000000000 --- a/src/LexEScript.cxx +++ /dev/null @@ -1,273 +0,0 @@ -// Scintilla source code edit control -/** @file LexESCRIPT.cxx - ** Lexer for ESCRIPT - **/ -// Copyright 2003 by Patrizio Bekerle (patrizio@bekerle.com) - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - - - -static void ColouriseESCRIPTDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - - // Do not leak onto next line - /*if (initStyle == SCE_ESCRIPT_STRINGEOL) - initStyle = SCE_ESCRIPT_DEFAULT;*/ - - StyleContext sc(startPos, length, initStyle, styler); - - bool caseSensitive = styler.GetPropertyInt("escript.case.sensitive", 0) != 0; - - for (; sc.More(); sc.Forward()) { - - /*if (sc.atLineStart && (sc.state == SCE_ESCRIPT_STRING)) { - // Prevent SCE_ESCRIPT_STRINGEOL from leaking back to previous line - sc.SetState(SCE_ESCRIPT_STRING); - }*/ - - // Handle line continuation generically. - if (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_ESCRIPT_OPERATOR || sc.state == SCE_ESCRIPT_BRACE) { - sc.SetState(SCE_ESCRIPT_DEFAULT); - } else if (sc.state == SCE_ESCRIPT_NUMBER) { - if (!IsADigit(sc.ch) || sc.ch != '.') { - sc.SetState(SCE_ESCRIPT_DEFAULT); - } - } else if (sc.state == SCE_ESCRIPT_IDENTIFIER) { - if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { - char s[100]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); - } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - -// sc.GetCurrentLowered(s, sizeof(s)); - - if (keywords.InList(s)) { - sc.ChangeState(SCE_ESCRIPT_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_ESCRIPT_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_ESCRIPT_WORD3); - // sc.state = SCE_ESCRIPT_IDENTIFIER; - } - sc.SetState(SCE_ESCRIPT_DEFAULT); - } - } else if (sc.state == SCE_ESCRIPT_COMMENT) { - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_ESCRIPT_DEFAULT); - } - } else if (sc.state == SCE_ESCRIPT_COMMENTDOC) { - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_ESCRIPT_DEFAULT); - } - } else if (sc.state == SCE_ESCRIPT_COMMENTLINE) { - if (sc.atLineEnd) { - sc.SetState(SCE_ESCRIPT_DEFAULT); - } - } else if (sc.state == SCE_ESCRIPT_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_ESCRIPT_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_ESCRIPT_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_ESCRIPT_NUMBER); - } else if (IsAWordStart(sc.ch) || (sc.ch == '#')) { - sc.SetState(SCE_ESCRIPT_IDENTIFIER); - } else if (sc.Match('/', '*')) { - sc.SetState(SCE_ESCRIPT_COMMENT); - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match('/', '/')) { - sc.SetState(SCE_ESCRIPT_COMMENTLINE); - } else if (sc.ch == '\"') { - sc.SetState(SCE_ESCRIPT_STRING); - //} else if (isoperator(static_cast(sc.ch))) { - } else if (sc.ch == '+' || sc.ch == '-' || sc.ch == '*' || sc.ch == '/' || sc.ch == '=' || sc.ch == '<' || sc.ch == '>' || sc.ch == '&' || sc.ch == '|' || sc.ch == '!' || sc.ch == '?' || sc.ch == ':') { - sc.SetState(SCE_ESCRIPT_OPERATOR); - } else if (sc.ch == '{' || sc.ch == '}') { - sc.SetState(SCE_ESCRIPT_BRACE); - } - } - - } - sc.Complete(); -} - - -static int classifyFoldPointESCRIPT(const char* s, const char* prevWord) { - int lev = 0; - if (strcmp(prevWord, "end") == 0) return lev; - if ((strcmp(prevWord, "else") == 0 && strcmp(s, "if") == 0) || strcmp(s, "elseif") == 0) - return -1; - - if (strcmp(s, "for") == 0 || strcmp(s, "foreach") == 0 - || strcmp(s, "program") == 0 || strcmp(s, "function") == 0 - || strcmp(s, "while") == 0 || strcmp(s, "case") == 0 - || strcmp(s, "if") == 0 ) { - lev = 1; - } else if ( strcmp(s, "endfor") == 0 || strcmp(s, "endforeach") == 0 - || strcmp(s, "endprogram") == 0 || strcmp(s, "endfunction") == 0 - || strcmp(s, "endwhile") == 0 || strcmp(s, "endcase") == 0 - || strcmp(s, "endif") == 0 ) { - lev = -1; - } - - return lev; -} - - -static bool IsStreamCommentStyle(int style) { - return style == SCE_ESCRIPT_COMMENT || - style == SCE_ESCRIPT_COMMENTDOC || - style == SCE_ESCRIPT_COMMENTLINE; -} - -static void FoldESCRIPTDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { - //~ bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - // Do not know how to fold the comment at the moment. - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldComment = true; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - - int lastStart = 0; - char prevWord[32] = ""; - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - - if (foldComment && IsStreamCommentStyle(style)) { - if (!IsStreamCommentStyle(stylePrev)) { - levelCurrent++; - } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelCurrent--; - } - } - - if (foldComment && (style == SCE_ESCRIPT_COMMENTLINE)) { - if ((ch == '/') && (chNext == '/')) { - char chNext2 = styler.SafeGetCharAt(i + 2); - if (chNext2 == '{') { - levelCurrent++; - } else if (chNext2 == '}') { - levelCurrent--; - } - } - } - - if (stylePrev == SCE_ESCRIPT_DEFAULT && style == SCE_ESCRIPT_WORD3) - { - // Store last word start point. - lastStart = i; - } - - if (style == SCE_ESCRIPT_WORD3) { - if(iswordchar(ch) && !iswordchar(chNext)) { - char s[32]; - unsigned int j; - for(j = 0; ( j < 31 ) && ( j < i-lastStart+1 ); j++) { - s[j] = static_cast(tolower(styler[lastStart + j])); - } - s[j] = '\0'; - levelCurrent += classifyFoldPointESCRIPT(s, prevWord); - strcpy(prevWord, s); - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - strcpy(prevWord, ""); - } - - if (!isspacechar(ch)) - visibleChars++; - } - - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - - - -static const char * const ESCRIPTWordLists[] = { - "Primary keywords and identifiers", - "Intrinsic functions", - "Extended and user defined functions", - 0, -}; - -LexerModule lmESCRIPT(SCLEX_ESCRIPT, ColouriseESCRIPTDoc, "escript", FoldESCRIPTDoc, ESCRIPTWordLists); diff --git a/src/LexEiffel.cxx b/src/LexEiffel.cxx deleted file mode 100644 index 03dea5e73..000000000 --- a/src/LexEiffel.cxx +++ /dev/null @@ -1,238 +0,0 @@ -// Scintilla source code edit control -/** @file LexEiffel.cxx - ** Lexer for Eiffel. - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool isEiffelOperator(unsigned int ch) { - // '.' left out as it is used to make up numbers - return ch == '*' || ch == '/' || ch == '\\' || ch == '-' || ch == '+' || - ch == '(' || ch == ')' || ch == '=' || - ch == '{' || ch == '}' || ch == '~' || - ch == '[' || ch == ']' || ch == ';' || - ch == '<' || ch == '>' || ch == ',' || - ch == '.' || ch == '^' || ch == '%' || ch == ':' || - ch == '!' || ch == '@' || ch == '?'; -} - -static inline bool IsAWordChar(unsigned int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static inline bool IsAWordStart(unsigned int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static void ColouriseEiffelDoc(unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.state == SCE_EIFFEL_STRINGEOL) { - if (sc.ch != '\r' && sc.ch != '\n') { - sc.SetState(SCE_EIFFEL_DEFAULT); - } - } else if (sc.state == SCE_EIFFEL_OPERATOR) { - sc.SetState(SCE_EIFFEL_DEFAULT); - } else if (sc.state == SCE_EIFFEL_WORD) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (!keywords.InList(s)) { - sc.ChangeState(SCE_EIFFEL_IDENTIFIER); - } - sc.SetState(SCE_EIFFEL_DEFAULT); - } - } else if (sc.state == SCE_EIFFEL_NUMBER) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_EIFFEL_DEFAULT); - } - } else if (sc.state == SCE_EIFFEL_COMMENTLINE) { - if (sc.ch == '\r' || sc.ch == '\n') { - sc.SetState(SCE_EIFFEL_DEFAULT); - } - } else if (sc.state == SCE_EIFFEL_STRING) { - if (sc.ch == '%') { - sc.Forward(); - } else if (sc.ch == '\"') { - sc.Forward(); - sc.SetState(SCE_EIFFEL_DEFAULT); - } - } else if (sc.state == SCE_EIFFEL_CHARACTER) { - if (sc.ch == '\r' || sc.ch == '\n') { - sc.SetState(SCE_EIFFEL_STRINGEOL); - } else if (sc.ch == '%') { - sc.Forward(); - } else if (sc.ch == '\'') { - sc.Forward(); - sc.SetState(SCE_EIFFEL_DEFAULT); - } - } - - if (sc.state == SCE_EIFFEL_DEFAULT) { - if (sc.ch == '-' && sc.chNext == '-') { - sc.SetState(SCE_EIFFEL_COMMENTLINE); - } else if (sc.ch == '\"') { - sc.SetState(SCE_EIFFEL_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_EIFFEL_CHARACTER); - } else if (IsADigit(sc.ch) || (sc.ch == '.')) { - sc.SetState(SCE_EIFFEL_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_EIFFEL_WORD); - } else if (isEiffelOperator(sc.ch)) { - sc.SetState(SCE_EIFFEL_OPERATOR); - } - } - } - sc.Complete(); -} - -static bool IsEiffelComment(Accessor &styler, int pos, int len) { - return len>1 && styler[pos]=='-' && styler[pos+1]=='-'; -} - -static void FoldEiffelDocIndent(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) { - int lengthDoc = startPos + length; - - // Backtrack to previous line in case need to fix its fold status - int lineCurrent = styler.GetLine(startPos); - if (startPos > 0) { - if (lineCurrent > 0) { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); - } - } - int spaceFlags = 0; - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsEiffelComment); - char chNext = styler[startPos]; - for (int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) { - int lev = indentCurrent; - int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsEiffelComment); - if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { - // Only non whitespace lines can be headers - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { - // Line after is blank so check the next - maybe should continue further? - int spaceFlags2 = 0; - int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsEiffelComment); - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - } - } - indentCurrent = indentNext; - styler.SetLevel(lineCurrent, lev); - lineCurrent++; - } - } -} - -static void FoldEiffelDocKeyWords(unsigned int startPos, int length, int /* initStyle */, WordList *[], - Accessor &styler) { - unsigned int lengthDoc = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int stylePrev = 0; - int styleNext = styler.StyleAt(startPos); - // lastDeferred should be determined by looking back to last keyword in case - // the "deferred" is on a line before "class" - bool lastDeferred = false; - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if ((stylePrev != SCE_EIFFEL_WORD) && (style == SCE_EIFFEL_WORD)) { - char s[20]; - unsigned int j = 0; - while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) { - s[j] = styler[i + j]; - j++; - } - s[j] = '\0'; - - if ( - (strcmp(s, "check") == 0) || - (strcmp(s, "debug") == 0) || - (strcmp(s, "deferred") == 0) || - (strcmp(s, "do") == 0) || - (strcmp(s, "from") == 0) || - (strcmp(s, "if") == 0) || - (strcmp(s, "inspect") == 0) || - (strcmp(s, "once") == 0) - ) - levelCurrent++; - if (!lastDeferred && (strcmp(s, "class") == 0)) - levelCurrent++; - if (strcmp(s, "end") == 0) - levelCurrent--; - lastDeferred = strcmp(s, "deferred") == 0; - } - - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - stylePrev = style; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const eiffelWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmEiffel(SCLEX_EIFFEL, ColouriseEiffelDoc, "eiffel", FoldEiffelDocIndent, eiffelWordListDesc); -LexerModule lmEiffelkw(SCLEX_EIFFELKW, ColouriseEiffelDoc, "eiffelkw", FoldEiffelDocKeyWords, eiffelWordListDesc); diff --git a/src/LexErlang.cxx b/src/LexErlang.cxx deleted file mode 100644 index 45577bda4..000000000 --- a/src/LexErlang.cxx +++ /dev/null @@ -1,619 +0,0 @@ -// Scintilla source code edit control -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. -/** @file LexErlang.cxx - ** Lexer for Erlang. - ** Enhanced by Etienne 'Lenain' Girondel (lenaing@gmail.com) - ** Originally wrote by Peter-Henry Mander, - ** based on Matlab lexer by José Fonseca. - **/ - -#include -#include -#include -#include -#include - -#include "Platform.h" -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static int is_radix(int radix, int ch) { - int digit; - - if (36 < radix || 2 > radix) - return 0; - - if (isdigit(ch)) { - digit = ch - '0'; - } else if (isalnum(ch)) { - digit = toupper(ch) - 'A' + 10; - } else { - return 0; - } - - return (digit < radix); -} - -typedef enum { - STATE_NULL, - COMMENT, - COMMENT_FUNCTION, - COMMENT_MODULE, - COMMENT_DOC, - COMMENT_DOC_MACRO, - ATOM_UNQUOTED, - ATOM_QUOTED, - NODE_NAME_UNQUOTED, - NODE_NAME_QUOTED, - MACRO_START, - MACRO_UNQUOTED, - MACRO_QUOTED, - RECORD_START, - RECORD_UNQUOTED, - RECORD_QUOTED, - NUMERAL_START, - NUMERAL_BASE_VALUE, - NUMERAL_FLOAT, - NUMERAL_EXPONENT, - PREPROCESSOR -} atom_parse_state_t; - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (ch != ' ') && (isalnum(ch) || ch == '_'); -} - -static void ColouriseErlangDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - StyleContext sc(startPos, length, initStyle, styler); - WordList &reservedWords = *keywordlists[0]; - WordList &erlangBIFs = *keywordlists[1]; - WordList &erlangPreproc = *keywordlists[2]; - WordList &erlangModulesAtt = *keywordlists[3]; - WordList &erlangDoc = *keywordlists[4]; - WordList &erlangDocMacro = *keywordlists[5]; - int radix_digits = 0; - int exponent_digits = 0; - atom_parse_state_t parse_state = STATE_NULL; - atom_parse_state_t old_parse_state = STATE_NULL; - bool to_late_to_comment = false; - char cur[100]; - int old_style = SCE_ERLANG_DEFAULT; - - styler.StartAt(startPos); - - for (; sc.More(); sc.Forward()) { - int style = SCE_ERLANG_DEFAULT; - if (STATE_NULL != parse_state) { - - switch (parse_state) { - - case STATE_NULL : sc.SetState(SCE_ERLANG_DEFAULT); break; - - /* COMMENTS ------------------------------------------------------*/ - case COMMENT : { - if (sc.ch != '%') { - to_late_to_comment = true; - } else if (!to_late_to_comment && sc.ch == '%') { - // Switch to comment level 2 (Function) - sc.ChangeState(SCE_ERLANG_COMMENT_FUNCTION); - old_style = SCE_ERLANG_COMMENT_FUNCTION; - parse_state = COMMENT_FUNCTION; - sc.Forward(); - } - } - // V--- Falling through! - case COMMENT_FUNCTION : { - if (sc.ch != '%') { - to_late_to_comment = true; - } else if (!to_late_to_comment && sc.ch == '%') { - // Switch to comment level 3 (Module) - sc.ChangeState(SCE_ERLANG_COMMENT_MODULE); - old_style = SCE_ERLANG_COMMENT_MODULE; - parse_state = COMMENT_MODULE; - sc.Forward(); - } - } - // V--- Falling through! - case COMMENT_MODULE : { - if (parse_state != COMMENT) { - // Search for comment documentation - if (sc.chNext == '@') { - old_parse_state = parse_state; - parse_state = ('{' == sc.ch) - ? COMMENT_DOC_MACRO - : COMMENT_DOC; - sc.ForwardSetState(sc.state); - } - } - - // All comments types fall here. - if (sc.atLineEnd) { - to_late_to_comment = false; - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - case COMMENT_DOC : - // V--- Falling through! - case COMMENT_DOC_MACRO : { - - if (!isalnum(sc.ch)) { - // Try to match documentation comment - sc.GetCurrent(cur, sizeof(cur)); - - if (parse_state == COMMENT_DOC_MACRO - && erlangDocMacro.InList(cur)) { - sc.ChangeState(SCE_ERLANG_COMMENT_DOC_MACRO); - while (sc.ch != '}' && !sc.atLineEnd) - sc.Forward(); - } else if (erlangDoc.InList(cur)) { - sc.ChangeState(SCE_ERLANG_COMMENT_DOC); - } else { - sc.ChangeState(old_style); - } - - // Switch back to old state - sc.SetState(old_style); - parse_state = old_parse_state; - } - - if (sc.atLineEnd) { - to_late_to_comment = false; - sc.ChangeState(old_style); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* -------------------------------------------------------------- */ - /* Atoms ---------------------------------------------------------*/ - case ATOM_UNQUOTED : { - if ('@' == sc.ch){ - parse_state = NODE_NAME_UNQUOTED; - } else if (sc.ch == ':') { - // Searching for module name - if (sc.chNext == ' ') { - // error - sc.ChangeState(SCE_ERLANG_UNKNOWN); - parse_state = STATE_NULL; - } else { - sc.Forward(); - if (isalnum(sc.ch)) { - sc.GetCurrent(cur, sizeof(cur)); - sc.ChangeState(SCE_ERLANG_MODULES); - sc.SetState(SCE_ERLANG_MODULES); - } - } - } else if (!IsAWordChar(sc.ch)) { - - sc.GetCurrent(cur, sizeof(cur)); - if (reservedWords.InList(cur)) { - style = SCE_ERLANG_KEYWORD; - } else if (erlangBIFs.InList(cur) - && strcmp(cur,"erlang:")){ - style = SCE_ERLANG_BIFS; - } else if (sc.ch == '(' || '/' == sc.ch){ - style = SCE_ERLANG_FUNCTION_NAME; - } else { - style = SCE_ERLANG_ATOM; - } - - sc.ChangeState(style); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - - } break; - - case ATOM_QUOTED : { - if ( '@' == sc.ch ){ - parse_state = NODE_NAME_QUOTED; - } else if ('\'' == sc.ch && '\\' != sc.chPrev) { - sc.ChangeState(SCE_ERLANG_ATOM); - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* -------------------------------------------------------------- */ - /* Node names ----------------------------------------------------*/ - case NODE_NAME_UNQUOTED : { - if ('@' == sc.ch) { - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } else if (!IsAWordChar(sc.ch)) { - sc.ChangeState(SCE_ERLANG_NODE_NAME); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - case NODE_NAME_QUOTED : { - if ('@' == sc.ch) { - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } else if ('\'' == sc.ch && '\\' != sc.chPrev) { - sc.ChangeState(SCE_ERLANG_NODE_NAME_QUOTED); - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* -------------------------------------------------------------- */ - /* Records -------------------------------------------------------*/ - case RECORD_START : { - if ('\'' == sc.ch) { - parse_state = RECORD_QUOTED; - } else if (isalpha(sc.ch) && islower(sc.ch)) { - parse_state = RECORD_UNQUOTED; - } else { // error - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - case RECORD_UNQUOTED : { - if (!IsAWordChar(sc.ch)) { - sc.ChangeState(SCE_ERLANG_RECORD); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - case RECORD_QUOTED : { - if ('\'' == sc.ch && '\\' != sc.chPrev) { - sc.ChangeState(SCE_ERLANG_RECORD_QUOTED); - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* -------------------------------------------------------------- */ - /* Macros --------------------------------------------------------*/ - case MACRO_START : { - if ('\'' == sc.ch) { - parse_state = MACRO_QUOTED; - } else if (isalpha(sc.ch)) { - parse_state = MACRO_UNQUOTED; - } else { // error - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - case MACRO_UNQUOTED : { - if (!IsAWordChar(sc.ch)) { - sc.ChangeState(SCE_ERLANG_MACRO); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - case MACRO_QUOTED : { - if ('\'' == sc.ch && '\\' != sc.chPrev) { - sc.ChangeState(SCE_ERLANG_MACRO_QUOTED); - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* -------------------------------------------------------------- */ - /* Numerics ------------------------------------------------------*/ - /* Simple integer */ - case NUMERAL_START : { - if (isdigit(sc.ch)) { - radix_digits *= 10; - radix_digits += sc.ch - '0'; // Assuming ASCII here! - } else if ('#' == sc.ch) { - if (2 > radix_digits || 36 < radix_digits) { - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } else { - parse_state = NUMERAL_BASE_VALUE; - } - } else if ('.' == sc.ch && isdigit(sc.chNext)) { - radix_digits = 0; - parse_state = NUMERAL_FLOAT; - } else if ('e' == sc.ch || 'E' == sc.ch) { - exponent_digits = 0; - parse_state = NUMERAL_EXPONENT; - } else { - radix_digits = 0; - sc.ChangeState(SCE_ERLANG_NUMBER); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* Integer in other base than 10 (x#yyy) */ - case NUMERAL_BASE_VALUE : { - if (!is_radix(radix_digits,sc.ch)) { - radix_digits = 0; - - if (!isalnum(sc.ch)) - sc.ChangeState(SCE_ERLANG_NUMBER); - - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* Float (x.yyy) */ - case NUMERAL_FLOAT : { - if ('e' == sc.ch || 'E' == sc.ch) { - exponent_digits = 0; - parse_state = NUMERAL_EXPONENT; - } else if (!isdigit(sc.ch)) { - sc.ChangeState(SCE_ERLANG_NUMBER); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - /* Exponent, either integer or float (xEyy, x.yyEzzz) */ - case NUMERAL_EXPONENT : { - if (('-' == sc.ch || '+' == sc.ch) - && (isdigit(sc.chNext))) { - sc.Forward(); - } else if (!isdigit(sc.ch)) { - if (0 < exponent_digits) - sc.ChangeState(SCE_ERLANG_NUMBER); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } else { - ++exponent_digits; - } - } break; - - /* -------------------------------------------------------------- */ - /* Preprocessor --------------------------------------------------*/ - case PREPROCESSOR : { - if (!IsAWordChar(sc.ch)) { - - sc.GetCurrent(cur, sizeof(cur)); - if (erlangPreproc.InList(cur)) { - style = SCE_ERLANG_PREPROC; - } else if (erlangModulesAtt.InList(cur)) { - style = SCE_ERLANG_MODULES_ATT; - } - - sc.ChangeState(style); - sc.SetState(SCE_ERLANG_DEFAULT); - parse_state = STATE_NULL; - } - } break; - - } - - } /* End of : STATE_NULL != parse_state */ - else - { - switch (sc.state) { - case SCE_ERLANG_VARIABLE : { - if (!IsAWordChar(sc.ch)) - sc.SetState(SCE_ERLANG_DEFAULT); - } break; - case SCE_ERLANG_STRING : { - if (sc.ch == '\"' && sc.chPrev != '\\') - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - } break; - case SCE_ERLANG_COMMENT : { - if (sc.atLineEnd) - sc.SetState(SCE_ERLANG_DEFAULT); - } break; - case SCE_ERLANG_CHARACTER : { - if (sc.chPrev == '\\') { - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - } else if (sc.ch != '\\') { - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - } - } break; - case SCE_ERLANG_OPERATOR : { - if (sc.chPrev == '.') { - if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' - || sc.ch == '^') { - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_ERLANG_DEFAULT); - } else { - sc.SetState(SCE_ERLANG_DEFAULT); - } - } else { - sc.SetState(SCE_ERLANG_DEFAULT); - } - } break; - } - } - - if (sc.state == SCE_ERLANG_DEFAULT) { - bool no_new_state = false; - - switch (sc.ch) { - case '\"' : sc.SetState(SCE_ERLANG_STRING); break; - case '$' : sc.SetState(SCE_ERLANG_CHARACTER); break; - case '%' : { - parse_state = COMMENT; - sc.SetState(SCE_ERLANG_COMMENT); - } break; - case '#' : { - parse_state = RECORD_START; - sc.SetState(SCE_ERLANG_UNKNOWN); - } break; - case '?' : { - parse_state = MACRO_START; - sc.SetState(SCE_ERLANG_UNKNOWN); - } break; - case '\'' : { - parse_state = ATOM_QUOTED; - sc.SetState(SCE_ERLANG_UNKNOWN); - } break; - case '+' : - case '-' : { - if (IsADigit(sc.chNext)) { - parse_state = NUMERAL_START; - radix_digits = 0; - sc.SetState(SCE_ERLANG_UNKNOWN); - } else if (sc.ch != '+') { - parse_state = PREPROCESSOR; - sc.SetState(SCE_ERLANG_UNKNOWN); - } - } break; - default : no_new_state = true; - } - - if (no_new_state) { - if (isdigit(sc.ch)) { - parse_state = NUMERAL_START; - radix_digits = sc.ch - '0'; - sc.SetState(SCE_ERLANG_UNKNOWN); - } else if (isupper(sc.ch) || '_' == sc.ch) { - sc.SetState(SCE_ERLANG_VARIABLE); - } else if (isalpha(sc.ch)) { - parse_state = ATOM_UNQUOTED; - sc.SetState(SCE_ERLANG_UNKNOWN); - } else if (isoperator(static_cast(sc.ch)) - || sc.ch == '\\') { - sc.SetState(SCE_ERLANG_OPERATOR); - } - } - } - - } - sc.Complete(); -} - -static int ClassifyErlangFoldPoint( - Accessor &styler, - int styleNext, - int keyword_start -) { - int lev = 0; - if (styler.Match(keyword_start,"case") - || ( - styler.Match(keyword_start,"fun") - && (SCE_ERLANG_FUNCTION_NAME != styleNext) - ) - || styler.Match(keyword_start,"if") - || styler.Match(keyword_start,"query") - || styler.Match(keyword_start,"receive") - ) { - ++lev; - } else if (styler.Match(keyword_start,"end")) { - --lev; - } - - return lev; -} - -static void FoldErlangDoc( - unsigned int startPos, int length, int initStyle, - WordList** /*keywordlists*/, Accessor &styler -) { - unsigned int endPos = startPos + length; - int currentLine = styler.GetLine(startPos); - int lev; - int previousLevel = styler.LevelAt(currentLine) & SC_FOLDLEVELNUMBERMASK; - int currentLevel = previousLevel; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - int stylePrev; - int keyword_start = 0; - char ch; - char chNext = styler.SafeGetCharAt(startPos); - bool atEOL; - - for (unsigned int i = startPos; i < endPos; i++) { - ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - // Get styles - stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - atEOL = ((ch == '\r') && (chNext != '\n')) || (ch == '\n'); - - if (stylePrev != SCE_ERLANG_KEYWORD - && style == SCE_ERLANG_KEYWORD) { - keyword_start = i; - } - - // Fold on keywords - if (stylePrev == SCE_ERLANG_KEYWORD - && style != SCE_ERLANG_KEYWORD - && style != SCE_ERLANG_ATOM - ) { - currentLevel += ClassifyErlangFoldPoint(styler, - styleNext, - keyword_start); - } - - // Fold on comments - if (style == SCE_ERLANG_COMMENT - || style == SCE_ERLANG_COMMENT_MODULE - || style == SCE_ERLANG_COMMENT_FUNCTION) { - - if (ch == '%' && chNext == '{') { - currentLevel++; - } else if (ch == '%' && chNext == '}') { - currentLevel--; - } - } - - // Fold on braces - if (style == SCE_ERLANG_OPERATOR) { - if (ch == '{' || ch == '(' || ch == '[') { - currentLevel++; - } else if (ch == '}' || ch == ')' || ch == ']') { - currentLevel--; - } - } - - - if (atEOL) { - lev = previousLevel; - - if (currentLevel > previousLevel) - lev |= SC_FOLDLEVELHEADERFLAG; - - if (lev != styler.LevelAt(currentLine)) - styler.SetLevel(currentLine, lev); - - currentLine++; - previousLevel = currentLevel; - } - - } - - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - styler.SetLevel(currentLine, - previousLevel - | (styler.LevelAt(currentLine) & ~SC_FOLDLEVELNUMBERMASK)); -} - -static const char * const erlangWordListDesc[] = { - "Erlang Reserved words", - "Erlang BIFs", - "Erlang Preprocessor", - "Erlang Module Attributes", - "Erlang Documentation", - "Erlang Documentation Macro", - 0 -}; - -LexerModule lmErlang( - SCLEX_ERLANG, - ColouriseErlangDoc, - "erlang", - FoldErlangDoc, - erlangWordListDesc); diff --git a/src/LexFlagship.cxx b/src/LexFlagship.cxx deleted file mode 100644 index e3a8b9f25..000000000 --- a/src/LexFlagship.cxx +++ /dev/null @@ -1,352 +0,0 @@ -// Scintilla source code edit control -/** @file LexFlagShip.cxx - ** Lexer for Harbour and FlagShip. - ** (Syntactically compatible to other xBase dialects, like Clipper, dBase, Clip, FoxPro etc.) - **/ -// Copyright 2005 by Randy Butler -// Copyright 2010 by Xavi (Harbour) -// Copyright 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "CharacterSet.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// Extended to accept accented characters -static inline bool IsAWordChar(int ch) -{ - return ch >= 0x80 || - (isalnum(ch) || ch == '_'); -} - -static void ColouriseFlagShipDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) -{ - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - - // property lexer.flagship.styling.within.preprocessor - // For Harbour code, determines whether all preprocessor code is styled in the preprocessor style (0) or only from the - // initial # to the end of the command word(1, the default). It also determines how to present text, dump, and disabled code. - bool stylingWithinPreprocessor = styler.GetPropertyInt("lexer.flagship.styling.within.preprocessor", 1) != 0; - - CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); - - int visibleChars = 0; - int closeStringChar = 0; - int styleBeforeDCKeyword = SCE_FS_DEFAULT; - bool bEnableCode = initStyle < SCE_FS_DISABLEDCODE; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - // Determine if the current state should terminate. - switch (sc.state) { - case SCE_FS_OPERATOR: - case SCE_FS_OPERATOR_C: - case SCE_FS_WORDOPERATOR: - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - break; - case SCE_FS_IDENTIFIER: - case SCE_FS_IDENTIFIER_C: - if (!IsAWordChar(sc.ch)) { - char s[64]; - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD : SCE_FS_KEYWORD_C); - } else if (keywords2.InList(s)) { - sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD2 : SCE_FS_KEYWORD2_C); - } else if (bEnableCode && keywords3.InList(s)) { - sc.ChangeState(SCE_FS_KEYWORD3); - } else if (bEnableCode && keywords4.InList(s)) { - sc.ChangeState(SCE_FS_KEYWORD4); - }// Else, it is really an identifier... - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } - break; - case SCE_FS_NUMBER: - if (!IsAWordChar(sc.ch) && !(sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_FS_DEFAULT); - } - break; - case SCE_FS_NUMBER_C: - if (!IsAWordChar(sc.ch) && sc.ch != '.') { - sc.SetState(SCE_FS_DEFAULT_C); - } - break; - case SCE_FS_CONSTANT: - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_FS_DEFAULT); - } - break; - case SCE_FS_STRING: - case SCE_FS_STRING_C: - if (sc.ch == closeStringChar) { - sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } else if (sc.atLineEnd) { - sc.ChangeState(bEnableCode ? SCE_FS_STRINGEOL : SCE_FS_STRINGEOL_C); - } - break; - case SCE_FS_STRINGEOL: - case SCE_FS_STRINGEOL_C: - if (sc.atLineStart) { - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } - break; - case SCE_FS_COMMENTDOC: - case SCE_FS_COMMENTDOC_C: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C; - sc.SetState(SCE_FS_COMMENTDOCKEYWORD); - } - } - break; - case SCE_FS_COMMENT: - case SCE_FS_COMMENTLINE: - if (sc.atLineStart) { - sc.SetState(SCE_FS_DEFAULT); - } - break; - case SCE_FS_COMMENTLINEDOC: - case SCE_FS_COMMENTLINEDOC_C: - if (sc.atLineStart) { - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C; - sc.SetState(SCE_FS_COMMENTDOCKEYWORD); - } - } - break; - case SCE_FS_COMMENTDOCKEYWORD: - if ((styleBeforeDCKeyword == SCE_FS_COMMENTDOC || styleBeforeDCKeyword == SCE_FS_COMMENTDOC_C) && - sc.Match('*', '/')) { - sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR); - sc.Forward(); - sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } else if (!setDoxygen.Contains(sc.ch)) { - char s[64]; - sc.GetCurrentLowered(s, sizeof(s)); - if (!IsASpace(sc.ch) || !keywords5.InList(s + 1)) { - sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR); - } - sc.SetState(styleBeforeDCKeyword); - } - break; - case SCE_FS_PREPROCESSOR: - case SCE_FS_PREPROCESSOR_C: - if (sc.atLineEnd) { - if (!(sc.chPrev == ';' || sc.GetRelative(-2) == ';')) { - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } - } else if (stylingWithinPreprocessor) { - if (IsASpaceOrTab(sc.ch)) { - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } - } else if (sc.Match('/', '*') || sc.Match('/', '/') || sc.Match('&', '&')) { - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } - break; - case SCE_FS_DISABLEDCODE: - if (sc.ch == '#' && visibleChars == 0) { - sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C); - do { // Skip whitespace between # and preprocessor word - sc.Forward(); - } while (IsASpaceOrTab(sc.ch) && sc.More()); - if (sc.MatchIgnoreCase("pragma")) { - sc.Forward(6); - do { // Skip more whitespace until keyword - sc.Forward(); - } while (IsASpaceOrTab(sc.ch) && sc.More()); - if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) { - bEnableCode = true; - sc.SetState(SCE_FS_DISABLEDCODE); - sc.Forward(sc.ch == '_' ? 8 : 6); - sc.ForwardSetState(SCE_FS_DEFAULT); - } else { - sc.ChangeState(SCE_FS_DISABLEDCODE); - } - } else { - sc.ChangeState(SCE_FS_DISABLEDCODE); - } - } - break; - case SCE_FS_DATE: - if (sc.ch == '}') { - sc.ForwardSetState(SCE_FS_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_FS_STRINGEOL); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_FS_DEFAULT || sc.state == SCE_FS_DEFAULT_C) { - if (bEnableCode && - (sc.MatchIgnoreCase(".and.") || sc.MatchIgnoreCase(".not."))) { - sc.SetState(SCE_FS_WORDOPERATOR); - sc.Forward(4); - } else if (bEnableCode && sc.MatchIgnoreCase(".or.")) { - sc.SetState(SCE_FS_WORDOPERATOR); - sc.Forward(3); - } else if (bEnableCode && - (sc.MatchIgnoreCase(".t.") || sc.MatchIgnoreCase(".f.") || - (!IsAWordChar(sc.GetRelative(3)) && sc.MatchIgnoreCase("nil")))) { - sc.SetState(SCE_FS_CONSTANT); - sc.Forward(2); - } else if (sc.Match('/', '*')) { - sc.SetState(bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C); - sc.Forward(); - } else if (bEnableCode && sc.Match('&', '&')) { - sc.SetState(SCE_FS_COMMENTLINE); - sc.Forward(); - } else if (sc.Match('/', '/')) { - sc.SetState(bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C); - sc.Forward(); - } else if (bEnableCode && sc.ch == '*' && visibleChars == 0) { - sc.SetState(SCE_FS_COMMENT); - } else if (sc.ch == '\"' || sc.ch == '\'') { - sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C); - closeStringChar = sc.ch; - } else if (closeStringChar == '>' && sc.ch == '<') { - sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C); - } else if (sc.ch == '#' && visibleChars == 0) { - sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C); - do { // Skip whitespace between # and preprocessor word - sc.Forward(); - } while (IsASpaceOrTab(sc.ch) && sc.More()); - if (sc.atLineEnd) { - sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); - } else if (sc.MatchIgnoreCase("include")) { - if (stylingWithinPreprocessor) { - closeStringChar = '>'; - } - } else if (sc.MatchIgnoreCase("pragma")) { - sc.Forward(6); - do { // Skip more whitespace until keyword - sc.Forward(); - } while (IsASpaceOrTab(sc.ch) && sc.More()); - if (sc.MatchIgnoreCase("begindump") || sc.MatchIgnoreCase("__cstream")) { - bEnableCode = false; - if (stylingWithinPreprocessor) { - sc.SetState(SCE_FS_DISABLEDCODE); - sc.Forward(8); - sc.ForwardSetState(SCE_FS_DEFAULT_C); - } else { - sc.SetState(SCE_FS_DISABLEDCODE); - } - } else if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) { - bEnableCode = true; - sc.SetState(SCE_FS_DISABLEDCODE); - sc.Forward(sc.ch == '_' ? 8 : 6); - sc.ForwardSetState(SCE_FS_DEFAULT); - } - } - } else if (bEnableCode && sc.ch == '{') { - int p = 0; - int chSeek; - unsigned int endPos(startPos + length); - do { // Skip whitespace - chSeek = sc.GetRelative(++p); - } while (IsASpaceOrTab(chSeek) && (sc.currentPos + p < endPos)); - if (chSeek == '^') { - sc.SetState(SCE_FS_DATE); - } else { - sc.SetState(SCE_FS_OPERATOR); - } - } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(bEnableCode ? SCE_FS_NUMBER : SCE_FS_NUMBER_C); - } else if (IsAWordChar(sc.ch)) { - sc.SetState(bEnableCode ? SCE_FS_IDENTIFIER : SCE_FS_IDENTIFIER_C); - } else if (isoperator(static_cast(sc.ch)) || (bEnableCode && sc.ch == '@')) { - sc.SetState(bEnableCode ? SCE_FS_OPERATOR : SCE_FS_OPERATOR_C); - } - } - - if (sc.atLineEnd) { - visibleChars = 0; - closeStringChar = 0; - } - if (!IsASpace(sc.ch)) { - visibleChars++; - } - } - sc.Complete(); -} - -static void FoldFlagShipDoc(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) -{ - - int endPos = startPos + length; - - // Backtrack to previous line in case need to fix its fold status - int lineCurrent = styler.GetLine(startPos); - if (startPos > 0 && lineCurrent > 0) { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); - } - int spaceFlags = 0; - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags); - char chNext = styler[startPos]; - for (int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos-1)) { - int lev = indentCurrent; - int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags); - if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { - int spaceFlags2 = 0; - int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2); - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - } - } - indentCurrent = indentNext; - styler.SetLevel(lineCurrent, lev); - lineCurrent++; - } - } -} - -static const char * const FSWordListDesc[] = { - "Keywords Commands", - "Std Library Functions", - "Procedure, return, exit", - "Class (oop)", - "Doxygen keywords", - 0 -}; - -LexerModule lmFlagShip(SCLEX_FLAGSHIP, ColouriseFlagShipDoc, "flagship", FoldFlagShipDoc, FSWordListDesc); diff --git a/src/LexForth.cxx b/src/LexForth.cxx deleted file mode 100644 index e52543fa5..000000000 --- a/src/LexForth.cxx +++ /dev/null @@ -1,176 +0,0 @@ -// Scintilla source code edit control -/** @file LexForth.cxx - ** Lexer for FORTH - **/ -// Copyright 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || - ch == '_' || ch == '?' || ch == '"' || ch == '@' || - ch == '!' || ch == '[' || ch == ']' || ch == '/' || - ch == '+' || ch == '-' || ch == '*' || ch == '<' || - ch == '>' || ch == '=' || ch == ';' || ch == '(' || - ch == ')' ); -} - -static inline bool IsAWordStart(int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.'); -} - -static inline bool IsANumChar(int ch) { - return (ch < 0x80) && (isxdigit(ch) || ch == '.' || ch == 'e' || ch == 'E' ); -} - -static inline bool IsASpaceChar(int ch) { - return (ch < 0x80) && isspace(ch); -} - -static void ColouriseForthDoc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[], - Accessor &styler) { - - WordList &control = *keywordLists[0]; - WordList &keyword = *keywordLists[1]; - WordList &defword = *keywordLists[2]; - WordList &preword1 = *keywordLists[3]; - WordList &preword2 = *keywordLists[4]; - WordList &strings = *keywordLists[5]; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) - { - // Determine if the current state should terminate. - if (sc.state == SCE_FORTH_COMMENT) { - if (sc.atLineEnd) { - sc.SetState(SCE_FORTH_DEFAULT); - } - }else if (sc.state == SCE_FORTH_COMMENT_ML) { - if (sc.ch == ')') { - sc.ForwardSetState(SCE_FORTH_DEFAULT); - } - }else if (sc.state == SCE_FORTH_IDENTIFIER || sc.state == SCE_FORTH_NUMBER) { - // handle numbers here too, because what we thought was a number might - // turn out to be a keyword e.g. 2DUP - if (IsASpaceChar(sc.ch) ) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - int newState = sc.state == SCE_FORTH_NUMBER ? SCE_FORTH_NUMBER : SCE_FORTH_DEFAULT; - if (control.InList(s)) { - sc.ChangeState(SCE_FORTH_CONTROL); - } else if (keyword.InList(s)) { - sc.ChangeState(SCE_FORTH_KEYWORD); - } else if (defword.InList(s)) { - sc.ChangeState(SCE_FORTH_DEFWORD); - } else if (preword1.InList(s)) { - sc.ChangeState(SCE_FORTH_PREWORD1); - } else if (preword2.InList(s)) { - sc.ChangeState(SCE_FORTH_PREWORD2); - } else if (strings.InList(s)) { - sc.ChangeState(SCE_FORTH_STRING); - newState = SCE_FORTH_STRING; - } - sc.SetState(newState); - } - if (sc.state == SCE_FORTH_NUMBER) { - if (IsASpaceChar(sc.ch)) { - sc.SetState(SCE_FORTH_DEFAULT); - } else if (!IsANumChar(sc.ch)) { - sc.ChangeState(SCE_FORTH_IDENTIFIER); - } - } - }else if (sc.state == SCE_FORTH_STRING) { - if (sc.ch == '\"') { - sc.ForwardSetState(SCE_FORTH_DEFAULT); - } - }else if (sc.state == SCE_FORTH_LOCALE) { - if (sc.ch == '}') { - sc.ForwardSetState(SCE_FORTH_DEFAULT); - } - }else if (sc.state == SCE_FORTH_DEFWORD) { - if (IsASpaceChar(sc.ch)) { - sc.SetState(SCE_FORTH_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_FORTH_DEFAULT) { - if (sc.ch == '\\'){ - sc.SetState(SCE_FORTH_COMMENT); - } else if (sc.ch == '(' && - (sc.atLineStart || IsASpaceChar(sc.chPrev)) && - (sc.atLineEnd || IsASpaceChar(sc.chNext))) { - sc.SetState(SCE_FORTH_COMMENT_ML); - } else if ( (sc.ch == '$' && (isascii(sc.chNext) && isxdigit(sc.chNext))) ) { - // number starting with $ is a hex number - sc.SetState(SCE_FORTH_NUMBER); - while(sc.More() && isascii(sc.chNext) && isxdigit(sc.chNext)) - sc.Forward(); - } else if ( (sc.ch == '%' && (isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))) ) { - // number starting with % is binary - sc.SetState(SCE_FORTH_NUMBER); - while(sc.More() && isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1')) - sc.Forward(); - } else if ( isascii(sc.ch) && - (isxdigit(sc.ch) || ((sc.ch == '.' || sc.ch == '-') && isascii(sc.chNext) && isxdigit(sc.chNext)) ) - ){ - sc.SetState(SCE_FORTH_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_FORTH_IDENTIFIER); - } else if (sc.ch == '{') { - sc.SetState(SCE_FORTH_LOCALE); - } else if (sc.ch == ':' && isascii(sc.chNext) && isspace(sc.chNext)) { - // highlight word definitions e.g. : GCD ( n n -- n ) ..... ; - // ^ ^^^ - sc.SetState(SCE_FORTH_DEFWORD); - while(sc.More() && isascii(sc.chNext) && isspace(sc.chNext)) - sc.Forward(); - } else if (sc.ch == ';' && - (sc.atLineStart || IsASpaceChar(sc.chPrev)) && - (sc.atLineEnd || IsASpaceChar(sc.chNext)) ) { - // mark the ';' that ends a word - sc.SetState(SCE_FORTH_DEFWORD); - sc.ForwardSetState(SCE_FORTH_DEFAULT); - } - } - - } - sc.Complete(); -} - -static void FoldForthDoc(unsigned int, int, int, WordList *[], - Accessor &) { -} - -static const char * const forthWordLists[] = { - "control keywords", - "keywords", - "definition words", - "prewords with one argument", - "prewords with two arguments", - "string definition keywords", - 0, - }; - -LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth", FoldForthDoc, forthWordLists); - - diff --git a/src/LexFortran.cxx b/src/LexFortran.cxx deleted file mode 100644 index 0b3f2777c..000000000 --- a/src/LexFortran.cxx +++ /dev/null @@ -1,466 +0,0 @@ -// Scintilla source code edit control -/** @file LexFortran.cxx - ** Lexer for Fortran. - ** Writen by Chuan-jian Shen, Last changed Sep. 2003 - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. -/***************************************/ -#include -#include -#include -#include -#include -/***************************************/ -#include "Platform.h" -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/***********************************************/ -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '%'); -} -/**********************************************/ -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch)); -} -/***************************************/ -inline bool IsABlank(unsigned int ch) { - return (ch == ' ') || (ch == 0x09) || (ch == 0x0b) ; -} -/***************************************/ -inline bool IsALineEnd(char ch) { - return ((ch == '\n') || (ch == '\r')) ; -} -/***************************************/ -unsigned int GetContinuedPos(unsigned int pos, Accessor &styler) { - while (!IsALineEnd(styler.SafeGetCharAt(pos++))) continue; - if (styler.SafeGetCharAt(pos) == '\n') pos++; - while (IsABlank(styler.SafeGetCharAt(pos++))) continue; - char chCur = styler.SafeGetCharAt(pos); - if (chCur == '&') { - while (IsABlank(styler.SafeGetCharAt(++pos))) continue; - return pos; - } else { - return pos; - } -} -/***************************************/ -static void ColouriseFortranDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler, bool isFixFormat) { - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - /***************************************/ - int posLineStart = 0, numNonBlank = 0, prevState = 0; - int endPos = startPos + length; - /***************************************/ - // backtrack to the nearest keyword - while ((startPos > 1) && (styler.StyleAt(startPos) != SCE_F_WORD)) { - startPos--; - } - startPos = styler.LineStart(styler.GetLine(startPos)); - initStyle = styler.StyleAt(startPos - 1); - StyleContext sc(startPos, endPos-startPos, initStyle, styler); - /***************************************/ - for (; sc.More(); sc.Forward()) { - // remember the start position of the line - if (sc.atLineStart) { - posLineStart = sc.currentPos; - numNonBlank = 0; - sc.SetState(SCE_F_DEFAULT); - } - if (!IsASpaceOrTab(sc.ch)) numNonBlank ++; - /***********************************************/ - // Handle the fix format generically - int toLineStart = sc.currentPos - posLineStart; - if (isFixFormat && (toLineStart < 6 || toLineStart > 72)) { - if ((toLineStart == 0 && (tolower(sc.ch) == 'c' || sc.ch == '*')) || sc.ch == '!') { - if (sc.MatchIgnoreCase("cdec$") || sc.MatchIgnoreCase("*dec$") || sc.MatchIgnoreCase("!dec$") || - sc.MatchIgnoreCase("cdir$") || sc.MatchIgnoreCase("*dir$") || sc.MatchIgnoreCase("!dir$") || - sc.MatchIgnoreCase("cms$") || sc.MatchIgnoreCase("*ms$") || sc.MatchIgnoreCase("!ms$") || - sc.chNext == '$') { - sc.SetState(SCE_F_PREPROCESSOR); - } else { - sc.SetState(SCE_F_COMMENT); - } - - while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end - } else if (toLineStart > 72) { - sc.SetState(SCE_F_COMMENT); - while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end - } else if (toLineStart < 5) { - if (IsADigit(sc.ch)) - sc.SetState(SCE_F_LABEL); - else - sc.SetState(SCE_F_DEFAULT); - } else if (toLineStart == 5) { - if (!IsASpace(sc.ch) && sc.ch != '0') { - sc.SetState(SCE_F_CONTINUATION); - sc.ForwardSetState(prevState); - } else - sc.SetState(SCE_F_DEFAULT); - } - continue; - } - /***************************************/ - // Handle line continuation generically. - if (!isFixFormat && sc.ch == '&') { - char chTemp = ' '; - int j = 1; - while (IsABlank(chTemp) && j<132) { - chTemp = static_cast(sc.GetRelative(j)); - j++; - } - if (chTemp == '!') { - sc.SetState(SCE_F_CONTINUATION); - if (sc.chNext == '!') sc.ForwardSetState(SCE_F_COMMENT); - } else if (chTemp == '\r' || chTemp == '\n') { - int currentState = sc.state; - sc.SetState(SCE_F_CONTINUATION); - sc.ForwardSetState(SCE_F_DEFAULT); - while (IsASpace(sc.ch) && sc.More()) sc.Forward(); - if (sc.ch == '&') { - sc.SetState(SCE_F_CONTINUATION); - sc.Forward(); - } - sc.SetState(currentState); - } - } - /***************************************/ - // Determine if the current state should terminate. - if (sc.state == SCE_F_OPERATOR) { - sc.SetState(SCE_F_DEFAULT); - } else if (sc.state == SCE_F_NUMBER) { - if (!(IsAWordChar(sc.ch) || sc.ch=='\'' || sc.ch=='\"' || sc.ch=='.')) { - sc.SetState(SCE_F_DEFAULT); - } - } else if (sc.state == SCE_F_IDENTIFIER) { - if (!IsAWordChar(sc.ch) || (sc.ch == '%')) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(SCE_F_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_F_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_F_WORD3); - } - sc.SetState(SCE_F_DEFAULT); - } - } else if (sc.state == SCE_F_COMMENT || sc.state == SCE_F_PREPROCESSOR) { - if (sc.ch == '\r' || sc.ch == '\n') { - sc.SetState(SCE_F_DEFAULT); - } - } else if (sc.state == SCE_F_STRING1) { - prevState = sc.state; - if (sc.ch == '\'') { - if (sc.chNext == '\'') { - sc.Forward(); - } else { - sc.ForwardSetState(SCE_F_DEFAULT); - prevState = SCE_F_DEFAULT; - } - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_F_STRINGEOL); - sc.ForwardSetState(SCE_F_DEFAULT); - } - } else if (sc.state == SCE_F_STRING2) { - prevState = sc.state; - if (sc.atLineEnd) { - sc.ChangeState(SCE_F_STRINGEOL); - sc.ForwardSetState(SCE_F_DEFAULT); - } else if (sc.ch == '\"') { - if (sc.chNext == '\"') { - sc.Forward(); - } else { - sc.ForwardSetState(SCE_F_DEFAULT); - prevState = SCE_F_DEFAULT; - } - } - } else if (sc.state == SCE_F_OPERATOR2) { - if (sc.ch == '.') { - sc.ForwardSetState(SCE_F_DEFAULT); - } - } else if (sc.state == SCE_F_CONTINUATION) { - sc.SetState(SCE_F_DEFAULT); - } else if (sc.state == SCE_F_LABEL) { - if (!IsADigit(sc.ch)) { - sc.SetState(SCE_F_DEFAULT); - } else { - if (isFixFormat && sc.currentPos-posLineStart > 4) - sc.SetState(SCE_F_DEFAULT); - else if (numNonBlank > 5) - sc.SetState(SCE_F_DEFAULT); - } - } - /***************************************/ - // Determine if a new state should be entered. - if (sc.state == SCE_F_DEFAULT) { - if (sc.ch == '!') { - if (sc.MatchIgnoreCase("!dec$") || sc.MatchIgnoreCase("!dir$") || - sc.MatchIgnoreCase("!ms$") || sc.chNext == '$') { - sc.SetState(SCE_F_PREPROCESSOR); - } else { - sc.SetState(SCE_F_COMMENT); - } - } else if ((!isFixFormat) && IsADigit(sc.ch) && numNonBlank == 1) { - sc.SetState(SCE_F_LABEL); - } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_F_NUMBER); - } else if ((tolower(sc.ch) == 'b' || tolower(sc.ch) == 'o' || - tolower(sc.ch) == 'z') && (sc.chNext == '\"' || sc.chNext == '\'')) { - sc.SetState(SCE_F_NUMBER); - sc.Forward(); - } else if (sc.ch == '.' && isalpha(sc.chNext)) { - sc.SetState(SCE_F_OPERATOR2); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_F_IDENTIFIER); - } else if (sc.ch == '\"') { - sc.SetState(SCE_F_STRING2); - } else if (sc.ch == '\'') { - sc.SetState(SCE_F_STRING1); - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_F_OPERATOR); - } - } - } - sc.Complete(); -} -/***************************************/ -// To determine the folding level depending on keywords -static int classifyFoldPointFortran(const char* s, const char* prevWord, const char chNextNonBlank) { - int lev = 0; - if ((strcmp(prevWord, "else") == 0 && strcmp(s, "if") == 0) || strcmp(s, "elseif") == 0) - return -1; - if (strcmp(s, "associate") == 0 || strcmp(s, "block") == 0 - || strcmp(s, "blockdata") == 0 || strcmp(s, "select") == 0 - || strcmp(s, "do") == 0 || strcmp(s, "enum") ==0 - || strcmp(s, "function") == 0 || strcmp(s, "interface") == 0 - || strcmp(s, "module") == 0 || strcmp(s, "program") == 0 - || strcmp(s, "subroutine") == 0 || strcmp(s, "then") == 0 - || (strcmp(s, "type") == 0 && chNextNonBlank != '(') ){ - if (strcmp(prevWord, "end") == 0) - lev = 0; - else - lev = 1; - } else if ((strcmp(s, "end") == 0 && chNextNonBlank != '=') - || strcmp(s, "endassociate") == 0 || strcmp(s, "endblock") == 0 - || strcmp(s, "endblockdata") == 0 || strcmp(s, "endselect") == 0 - || strcmp(s, "enddo") == 0 || strcmp(s, "endenum") ==0 - || strcmp(s, "endif") == 0 || strcmp(s, "endforall") == 0 - || strcmp(s, "endfunction") == 0 || strcmp(s, "endinterface") == 0 - || strcmp(s, "endmodule") == 0 || strcmp(s, "endprogram") == 0 - || strcmp(s, "endsubroutine") == 0 || strcmp(s, "endtype") == 0 - || strcmp(s, "endwhere") == 0 - || strcmp(s, "procedure") == 0 ) { // Take care of the module procedure statement - lev = -1; - } else if (strcmp(prevWord, "end") == 0 && strcmp(s, "if") == 0){ // end if - lev = 0; - } - return lev; -} -// Folding the code -static void FoldFortranDoc(unsigned int startPos, int length, int initStyle, - Accessor &styler, bool isFixFormat) { - // - // bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - // Do not know how to fold the comment at the moment. - // - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - char chNextNonBlank; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - /***************************************/ - int lastStart = 0; - char prevWord[32] = ""; - char Label[6] = ""; - // Variables for do label folding. - static int doLabels[100]; - static int posLabel=-1; - /***************************************/ - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - chNextNonBlank = chNext; - unsigned int j=i+1; - while(IsABlank(chNextNonBlank) && j(tolower(styler[lastStart+k])); - } - s[k] = '\0'; - // Handle the forall and where statement and structure. - if (strcmp(s, "forall") == 0 || strcmp(s, "where") == 0) { - if (strcmp(prevWord, "end") != 0) { - j = i + 1; - char chBrace = '(', chSeek = ')', ch1 = styler.SafeGetCharAt(j); - // Find the position of the first ( - while (ch1 != chBrace && j -1) { - levelCurrent--; - posLabel--; - } - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - strcpy(prevWord, ""); - } - /***************************************/ - if (!isspacechar(ch)) visibleChars++; - } - /***************************************/ - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} -/***************************************/ -static const char * const FortranWordLists[] = { - "Primary keywords and identifiers", - "Intrinsic functions", - "Extended and user defined functions", - 0, -}; -/***************************************/ -static void ColouriseFortranDocFreeFormat(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - ColouriseFortranDoc(startPos, length, initStyle, keywordlists, styler, false); -} -/***************************************/ -static void ColouriseFortranDocFixFormat(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - ColouriseFortranDoc(startPos, length, initStyle, keywordlists, styler, true); -} -/***************************************/ -static void FoldFortranDocFreeFormat(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) { - FoldFortranDoc(startPos, length, initStyle,styler, false); -} -/***************************************/ -static void FoldFortranDocFixFormat(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) { - FoldFortranDoc(startPos, length, initStyle,styler, true); -} -/***************************************/ -LexerModule lmFortran(SCLEX_FORTRAN, ColouriseFortranDocFreeFormat, "fortran", FoldFortranDocFreeFormat, FortranWordLists); -LexerModule lmF77(SCLEX_F77, ColouriseFortranDocFixFormat, "f77", FoldFortranDocFixFormat, FortranWordLists); diff --git a/src/LexGAP.cxx b/src/LexGAP.cxx deleted file mode 100644 index fb6e739bd..000000000 --- a/src/LexGAP.cxx +++ /dev/null @@ -1,263 +0,0 @@ -// Scintilla source code edit control -/** @file LexGAP.cxx - ** Lexer for the GAP language. (The GAP System for Computational Discrete Algebra) - ** http://www.gap-system.org - **/ -// Copyright 2007 by Istvan Szollosi ( szteven gmail com ) -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsGAPOperator(char ch) { - if (isascii(ch) && isalnum(ch)) return false; - if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || - ch == '^' || ch == ',' || ch == '!' || ch == '.' || - ch == '=' || ch == '<' || ch == '>' || ch == '(' || - ch == ')' || ch == ';' || ch == '[' || ch == ']' || - ch == '{' || ch == '}' || ch == ':' ) - return true; - return false; -} - -static void GetRange(unsigned int start, unsigned int end, Accessor &styler, char *s, unsigned int len) { - unsigned int i = 0; - while ((i < end - start + 1) && (i < len-1)) { - s[i] = static_cast(styler[start + i]); - i++; - } - s[i] = '\0'; -} - -static void ColouriseGAPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { - - WordList &keywords1 = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - - // Do not leak onto next line - if (initStyle == SCE_GAP_STRINGEOL) initStyle = SCE_GAP_DEFAULT; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - // Prevent SCE_GAP_STRINGEOL from leaking back to previous line - if ( sc.atLineStart ) { - if (sc.state == SCE_GAP_STRING) sc.SetState(SCE_GAP_STRING); - if (sc.state == SCE_GAP_CHAR) sc.SetState(SCE_GAP_CHAR); - } - - // Handle line continuation generically - if (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 - switch (sc.state) { - case SCE_GAP_OPERATOR : - sc.SetState(SCE_GAP_DEFAULT); - break; - - case SCE_GAP_NUMBER : - if (!IsADigit(sc.ch)) { - if (sc.ch == '\\') { - if (!sc.atLineEnd) { - if (!IsADigit(sc.chNext)) { - sc.Forward(); - sc.ChangeState(SCE_GAP_IDENTIFIER); - } - } - } else if (isalpha(sc.ch) || sc.ch == '_') { - sc.ChangeState(SCE_GAP_IDENTIFIER); - } - else sc.SetState(SCE_GAP_DEFAULT); - } - break; - - case SCE_GAP_IDENTIFIER : - if (!(iswordstart(static_cast(sc.ch)) || sc.ch == '$')) { - if (sc.ch == '\\') sc.Forward(); - else { - char s[1000]; - sc.GetCurrent(s, sizeof(s)); - if (keywords1.InList(s)) { - sc.ChangeState(SCE_GAP_KEYWORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_GAP_KEYWORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_GAP_KEYWORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_GAP_KEYWORD4); - } - sc.SetState(SCE_GAP_DEFAULT); - } - } - break; - - case SCE_GAP_COMMENT : - if (sc.atLineEnd) { - sc.SetState(SCE_GAP_DEFAULT); - } - break; - - case SCE_GAP_STRING: - if (sc.atLineEnd) { - sc.ChangeState(SCE_GAP_STRINGEOL); - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_GAP_DEFAULT); - } - break; - - case SCE_GAP_CHAR: - if (sc.atLineEnd) { - sc.ChangeState(SCE_GAP_STRINGEOL); - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_GAP_DEFAULT); - } - break; - - case SCE_GAP_STRINGEOL: - if (sc.atLineStart) { - sc.SetState(SCE_GAP_DEFAULT); - } - break; - } - - // Determine if a new state should be entered - if (sc.state == SCE_GAP_DEFAULT) { - if (IsGAPOperator(static_cast(sc.ch))) { - sc.SetState(SCE_GAP_OPERATOR); - } - else if (IsADigit(sc.ch)) { - sc.SetState(SCE_GAP_NUMBER); - } else if (isalpha(sc.ch) || sc.ch == '_' || sc.ch == '\\' || sc.ch == '$' || sc.ch == '~') { - sc.SetState(SCE_GAP_IDENTIFIER); - if (sc.ch == '\\') sc.Forward(); - } else if (sc.ch == '#') { - sc.SetState(SCE_GAP_COMMENT); - } else if (sc.ch == '\"') { - sc.SetState(SCE_GAP_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_GAP_CHAR); - } - } - - } - sc.Complete(); -} - -static int ClassifyFoldPointGAP(const char* s) { - int level = 0; - if (strcmp(s, "function") == 0 || - strcmp(s, "do") == 0 || - strcmp(s, "if") == 0 || - strcmp(s, "repeat") == 0 ) { - level = 1; - } else if (strcmp(s, "end") == 0 || - strcmp(s, "od") == 0 || - strcmp(s, "fi") == 0 || - strcmp(s, "until") == 0 ) { - level = -1; - } - return level; -} - -static void FoldGAPDoc( unsigned int startPos, int length, int initStyle, WordList** , Accessor &styler) { - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - - int lastStart = 0; - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - if (stylePrev != SCE_GAP_KEYWORD && style == SCE_GAP_KEYWORD) { - // Store last word start point. - lastStart = i; - } - - if (stylePrev == SCE_GAP_KEYWORD) { - if(iswordchar(ch) && !iswordchar(chNext)) { - char s[100]; - GetRange(lastStart, i, styler, s, sizeof(s)); - levelCurrent += ClassifyFoldPointGAP(s); - } - } - - if (atEOL) { - int lev = levelPrev; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - - if (!isspacechar(ch)) - visibleChars++; - } - - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const GAPWordListDesc[] = { - "Keywords 1", - "Keywords 2", - "Keywords 3 (unused)", - "Keywords 4 (unused)", - 0 -}; - -LexerModule lmGAP( - SCLEX_GAP, - ColouriseGAPDoc, - "gap", - FoldGAPDoc, - GAPWordListDesc); diff --git a/src/LexGui4Cli.cxx b/src/LexGui4Cli.cxx deleted file mode 100644 index 1c92de72e..000000000 --- a/src/LexGui4Cli.cxx +++ /dev/null @@ -1,313 +0,0 @@ -// Scintilla source code edit control -// Copyright 1998-2002 by Neil Hodgson -/* -This is the Lexer for Gui4Cli, included in SciLexer.dll -- by d. Keletsekis, 2/10/2003 - -To add to SciLexer.dll: -1. Add the values below to INCLUDE\Scintilla.iface -2. Run the include/HFacer.py script -3. Run the src/lexGen.py script - -val SCE_GC_DEFAULT=0 -val SCE_GC_COMMENTLINE=1 -val SCE_GC_COMMENTBLOCK=2 -val SCE_GC_GLOBAL=3 -val SCE_GC_EVENT=4 -val SCE_GC_ATTRIBUTE=5 -val SCE_GC_CONTROL=6 -val SCE_GC_COMMAND=7 -val SCE_GC_STRING=8 -val SCE_GC_OPERATOR=9 -*/ - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#define debug Platform::DebugPrintf - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch =='\\'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.'); -} - -inline bool isGCOperator(int ch) -{ if (isalnum(ch)) - return false; - // '.' left out as it is used to make up numbers - if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || - ch == '(' || ch == ')' || ch == '=' || ch == '%' || - ch == '[' || ch == ']' || ch == '<' || ch == '>' || - ch == ',' || ch == ';' || ch == ':') - return true; - return false; -} - -#define isSpace(x) ((x)==' ' || (x)=='\t') -#define isNL(x) ((x)=='\n' || (x)=='\r') -#define isSpaceOrNL(x) (isSpace(x) || isNL(x)) -#define BUFFSIZE 500 -#define isFoldPoint(x) ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024) - -static void colorFirstWord(WordList *keywordlists[], Accessor &styler, - StyleContext *sc, char *buff, int length, int) -{ - int c = 0; - while (sc->More() && isSpaceOrNL(sc->ch)) - { sc->Forward(); - } - styler.ColourTo(sc->currentPos - 1, sc->state); - - if (!IsAWordChar(sc->ch)) // comment, marker, etc.. - return; - - while (sc->More() && !isSpaceOrNL(sc->ch) && (c < length-1) && !isGCOperator(sc->ch)) - { buff[c] = static_cast(sc->ch); - ++c; sc->Forward(); - } - buff[c] = '\0'; - char *p = buff; - while (*p) // capitalize.. - { if (islower(*p)) *p = static_cast(toupper(*p)); - ++p; - } - - WordList &kGlobal = *keywordlists[0]; // keyword lists set by the user - WordList &kEvent = *keywordlists[1]; - WordList &kAttribute = *keywordlists[2]; - WordList &kControl = *keywordlists[3]; - WordList &kCommand = *keywordlists[4]; - - int state = 0; - // int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK; - // debug ("line = %d, level = %d", line, level); - - if (kGlobal.InList(buff)) state = SCE_GC_GLOBAL; - else if (kAttribute.InList(buff)) state = SCE_GC_ATTRIBUTE; - else if (kControl.InList(buff)) state = SCE_GC_CONTROL; - else if (kCommand.InList(buff)) state = SCE_GC_COMMAND; - else if (kEvent.InList(buff)) state = SCE_GC_EVENT; - - if (state) - { sc->ChangeState(state); - styler.ColourTo(sc->currentPos - 1, sc->state); - sc->ChangeState(SCE_GC_DEFAULT); - } - else - { sc->ChangeState(SCE_GC_DEFAULT); - styler.ColourTo(sc->currentPos - 1, sc->state); - } -} - -// Main colorizing function called by Scintilla -static void -ColouriseGui4CliDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) -{ - styler.StartAt(startPos); - - int quotestart = 0, oldstate, currentline = styler.GetLine(startPos); - styler.StartSegment(startPos); - bool noforward; - char buff[BUFFSIZE+1]; // buffer for command name - - StyleContext sc(startPos, length, initStyle, styler); - buff[0] = '\0'; // cbuff = 0; - - if (sc.state != SCE_GC_COMMENTBLOCK) // colorize 1st word.. - colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); - - while (sc.More()) - { noforward = 0; - - switch (sc.ch) - { - case '/': - if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_STRING) - break; - if (sc.chNext == '/') // line comment - { sc.SetState (SCE_GC_COMMENTLINE); - sc.Forward(); - styler.ColourTo(sc.currentPos, sc.state); - } - else if (sc.chNext == '*') // block comment - { sc.SetState(SCE_GC_COMMENTBLOCK); - sc.Forward(); - styler.ColourTo(sc.currentPos, sc.state); - } - else - styler.ColourTo(sc.currentPos, sc.state); - break; - - case '*': // end of comment block, or operator.. - if (sc.state == SCE_GC_STRING) - break; - if (sc.state == SCE_GC_COMMENTBLOCK && sc.chNext == '/') - { sc.Forward(); - styler.ColourTo(sc.currentPos, sc.state); - sc.ChangeState (SCE_GC_DEFAULT); - } - else - styler.ColourTo(sc.currentPos, sc.state); - break; - - case '\'': case '\"': // strings.. - if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_COMMENTLINE) - break; - if (sc.state == SCE_GC_STRING) - { if (sc.ch == quotestart) // match same quote char.. - { styler.ColourTo(sc.currentPos, sc.state); - sc.ChangeState(SCE_GC_DEFAULT); - quotestart = 0; - } } - else - { styler.ColourTo(sc.currentPos - 1, sc.state); - sc.ChangeState(SCE_GC_STRING); - quotestart = sc.ch; - } - break; - - case ';': // end of commandline character - if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE && - sc.state != SCE_GC_STRING) - { - styler.ColourTo(sc.currentPos - 1, sc.state); - styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); - sc.ChangeState(SCE_GC_DEFAULT); - sc.Forward(); - colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); - noforward = 1; // don't move forward - already positioned at next char.. - } - break; - - case '+': case '-': case '=': case '!': // operators.. - case '<': case '>': case '&': case '|': case '$': - if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE && - sc.state != SCE_GC_STRING) - { - styler.ColourTo(sc.currentPos - 1, sc.state); - styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); - sc.ChangeState(SCE_GC_DEFAULT); - } - break; - - case '\\': // escape - same as operator, but also mark in strings.. - if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE) - { - oldstate = sc.state; - styler.ColourTo(sc.currentPos - 1, sc.state); - sc.Forward(); // mark also the next char.. - styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); - sc.ChangeState(oldstate); - } - break; - - case '\n': case '\r': - ++currentline; - if (sc.state == SCE_GC_COMMENTLINE) - { styler.ColourTo(sc.currentPos, sc.state); - sc.ChangeState (SCE_GC_DEFAULT); - } - else if (sc.state != SCE_GC_COMMENTBLOCK) - { colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); - noforward = 1; // don't move forward - already positioned at next char.. - } - break; - -// case ' ': case '\t': -// default : - } - - if (!noforward) sc.Forward(); - - } - sc.Complete(); -} - -// Main folding function called by Scintilla - (based on props (.ini) files function) -static void FoldGui4Cli(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) -{ - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - bool headerPoint = false; - - for (unsigned int i = startPos; i < endPos; i++) - { - char ch = chNext; - chNext = styler[i+1]; - - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - if (style == SCE_GC_EVENT || style == SCE_GC_GLOBAL) - { headerPoint = true; // fold at events and globals - } - - if (atEOL) - { int lev = SC_FOLDLEVELBASE+1; - - if (headerPoint) - lev = SC_FOLDLEVELBASE; - - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - - if (headerPoint) - lev |= SC_FOLDLEVELHEADERFLAG; - - if (lev != styler.LevelAt(lineCurrent)) // set level, if not already correct - { styler.SetLevel(lineCurrent, lev); - } - - lineCurrent++; // re-initialize our flags - visibleChars = 0; - headerPoint = false; - } - - if (!(isspacechar(ch))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK))) - visibleChars++; - } - - int lev = headerPoint ? SC_FOLDLEVELBASE : SC_FOLDLEVELBASE+1; - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, lev | flagsNext); -} - -// I have no idea what these are for.. probably accessible by some message. -static const char * const gui4cliWordListDesc[] = { - "Globals", "Events", "Attributes", "Control", "Commands", - 0 -}; - -// Declare language & pass our function pointers to Scintilla -LexerModule lmGui4Cli(SCLEX_GUI4CLI, ColouriseGui4CliDoc, "gui4cli", FoldGui4Cli, gui4cliWordListDesc); - -#undef debug - diff --git a/src/LexHTML.cxx b/src/LexHTML.cxx deleted file mode 100644 index ed9db9763..000000000 --- a/src/LexHTML.cxx +++ /dev/null @@ -1,2132 +0,0 @@ -// Scintilla source code edit control -/** @file LexHTML.cxx - ** Lexer for HTML. - **/ -// Copyright 1998-2005 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "CharacterSet.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#define SCE_HA_JS (SCE_HJA_START - SCE_HJ_START) -#define SCE_HA_VBS (SCE_HBA_START - SCE_HB_START) -#define SCE_HA_PYTHON (SCE_HPA_START - SCE_HP_START) - -enum script_type { eScriptNone = 0, eScriptJS, eScriptVBS, eScriptPython, eScriptPHP, eScriptXML, eScriptSGML, eScriptSGMLblock, eScriptComment }; -enum script_mode { eHtml = 0, eNonHtmlScript, eNonHtmlPreProc, eNonHtmlScriptPreProc }; - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -inline bool IsOperator(int ch) { - if (isascii(ch) && isalnum(ch)) - return false; - // '.' left out as it is used to make up numbers - if (ch == '%' || ch == '^' || ch == '&' || ch == '*' || - ch == '(' || ch == ')' || ch == '-' || ch == '+' || - ch == '=' || ch == '|' || ch == '{' || ch == '}' || - ch == '[' || ch == ']' || ch == ':' || ch == ';' || - ch == '<' || ch == '>' || ch == ',' || ch == '/' || - ch == '?' || ch == '!' || ch == '.' || ch == '~') - return true; - return false; -} - -static inline int MakeLowerCase(int ch) { - if (ch < 'A' || ch > 'Z') - return ch; - else - return ch - 'A' + 'a'; -} - -static void GetTextSegment(Accessor &styler, unsigned int start, unsigned int end, char *s, size_t len) { - size_t i = 0; - for (; (i < end - start + 1) && (i < len-1); i++) { - s[i] = static_cast(MakeLowerCase(styler[start + i])); - } - s[i] = '\0'; -} - -static const char *GetNextWord(Accessor &styler, unsigned int start, char *s, size_t sLen) { - - size_t i = 0; - for (; i < sLen-1; i++) { - char ch = static_cast(styler.SafeGetCharAt(start + i)); - if ((i == 0) && !IsAWordStart(ch)) - break; - if ((i > 0) && !IsAWordChar(ch)) - break; - s[i] = ch; - } - s[i] = '\0'; - - return s; -} - -static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start, unsigned int end, script_type prevValue) { - char s[100]; - GetTextSegment(styler, start, end, s, sizeof(s)); - //Platform::DebugPrintf("Scripting indicator [%s]\n", s); - if (strstr(s, "src")) // External script - return eScriptNone; - if (strstr(s, "vbs")) - return eScriptVBS; - if (strstr(s, "pyth")) - return eScriptPython; - if (strstr(s, "javas")) - return eScriptJS; - if (strstr(s, "jscr")) - return eScriptJS; - if (strstr(s, "php")) - return eScriptPHP; - if (strstr(s, "xml")) { - const char *xml = strstr(s, "xml"); - for (const char *t=s; t= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) { - return eScriptPython; - } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) { - return eScriptVBS; - } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) { - return eScriptJS; - } else if ((state >= SCE_HPHP_DEFAULT) && (state <= SCE_HPHP_COMMENTLINE)) { - return eScriptPHP; - } else if ((state >= SCE_H_SGML_DEFAULT) && (state < SCE_H_SGML_BLOCK_DEFAULT)) { - return eScriptSGML; - } else if (state == SCE_H_SGML_BLOCK_DEFAULT) { - return eScriptSGMLblock; - } else { - return eScriptNone; - } -} - -static int statePrintForState(int state, script_mode inScriptType) { - int StateToPrint = state; - - if (state >= SCE_HJ_START) { - if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) { - StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_PYTHON); - } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) { - StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_VBS); - } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) { - StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_JS); - } - } - - return StateToPrint; -} - -static int stateForPrintState(int StateToPrint) { - int state; - - if ((StateToPrint >= SCE_HPA_START) && (StateToPrint <= SCE_HPA_IDENTIFIER)) { - state = StateToPrint - SCE_HA_PYTHON; - } else if ((StateToPrint >= SCE_HBA_START) && (StateToPrint <= SCE_HBA_STRINGEOL)) { - state = StateToPrint - SCE_HA_VBS; - } else if ((StateToPrint >= SCE_HJA_START) && (StateToPrint <= SCE_HJA_REGEX)) { - state = StateToPrint - SCE_HA_JS; - } else { - state = StateToPrint; - } - - return state; -} - -static inline bool IsNumber(unsigned int start, Accessor &styler) { - return IsADigit(styler[start]) || (styler[start] == '.') || - (styler[start] == '-') || (styler[start] == '#'); -} - -static inline bool isStringState(int state) { - bool bResult; - - switch (state) { - case SCE_HJ_DOUBLESTRING: - case SCE_HJ_SINGLESTRING: - case SCE_HJA_DOUBLESTRING: - case SCE_HJA_SINGLESTRING: - case SCE_HB_STRING: - case SCE_HBA_STRING: - case SCE_HP_STRING: - case SCE_HP_CHARACTER: - case SCE_HP_TRIPLE: - case SCE_HP_TRIPLEDOUBLE: - case SCE_HPA_STRING: - case SCE_HPA_CHARACTER: - case SCE_HPA_TRIPLE: - case SCE_HPA_TRIPLEDOUBLE: - case SCE_HPHP_HSTRING: - case SCE_HPHP_SIMPLESTRING: - case SCE_HPHP_HSTRING_VARIABLE: - case SCE_HPHP_COMPLEX_VARIABLE: - bResult = true; - break; - default : - bResult = false; - break; - } - return bResult; -} - -static inline bool stateAllowsTermination(int state) { - bool allowTermination = !isStringState(state); - if (allowTermination) { - switch (state) { - case SCE_HB_COMMENTLINE: - case SCE_HPHP_COMMENT: - case SCE_HP_COMMENTLINE: - case SCE_HPA_COMMENTLINE: - allowTermination = false; - } - } - return allowTermination; -} - -// not really well done, since it's only comments that should lex the %> and <% -static inline bool isCommentASPState(int state) { - bool bResult; - - switch (state) { - case SCE_HJ_COMMENT: - case SCE_HJ_COMMENTLINE: - case SCE_HJ_COMMENTDOC: - case SCE_HB_COMMENTLINE: - case SCE_HP_COMMENTLINE: - case SCE_HPHP_COMMENT: - case SCE_HPHP_COMMENTLINE: - bResult = true; - break; - default : - bResult = false; - break; - } - return bResult; -} - -static void classifyAttribHTML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { - bool wordIsNumber = IsNumber(start, styler); - char chAttr = SCE_H_ATTRIBUTEUNKNOWN; - if (wordIsNumber) { - chAttr = SCE_H_NUMBER; - } else { - char s[100]; - GetTextSegment(styler, start, end, s, sizeof(s)); - if (keywords.InList(s)) - chAttr = SCE_H_ATTRIBUTE; - } - if ((chAttr == SCE_H_ATTRIBUTEUNKNOWN) && !keywords) - // No keywords -> all are known - chAttr = SCE_H_ATTRIBUTE; - styler.ColourTo(end, chAttr); -} - -static int classifyTagHTML(unsigned int start, unsigned int end, - WordList &keywords, Accessor &styler, bool &tagDontFold, - bool caseSensitive, bool isXml, bool allowScripts) { - char s[30 + 2]; - // Copy after the '<' - unsigned int i = 0; - for (unsigned int cPos = start; cPos <= end && i < 30; cPos++) { - char ch = styler[cPos]; - if ((ch != '<') && (ch != '/')) { - s[i++] = caseSensitive ? ch : static_cast(MakeLowerCase(ch)); - } - } - - //The following is only a quick hack, to see if this whole thing would work - //we first need the tagname with a trailing space... - s[i] = ' '; - s[i+1] = '\0'; - - // if the current language is XML, I can fold any tag - // if the current language is HTML, I don't want to fold certain tags (input, meta, etc.) - //...to find it in the list of no-container-tags - tagDontFold = (!isXml) && (NULL != strstr("meta link img area br hr input ", s)); - - //now we can remove the trailing space - s[i] = '\0'; - - // No keywords -> all are known - char chAttr = SCE_H_TAGUNKNOWN; - if (s[0] == '!') { - chAttr = SCE_H_SGML_DEFAULT; - } else if (!keywords || keywords.InList(s)) { - chAttr = SCE_H_TAG; - } - styler.ColourTo(end, chAttr); - if (chAttr == SCE_H_TAG) { - if (allowScripts && 0 == strcmp(s, "script")) { - // check to see if this is a self-closing tag by sniffing ahead - bool isSelfClose = false; - for (unsigned int cPos = end; cPos <= end + 100; cPos++) { - char ch = styler.SafeGetCharAt(cPos, '\0'); - if (ch == '\0' || ch == '>') - break; - else if (ch == '/' && styler.SafeGetCharAt(cPos + 1, '\0') == '>') { - isSelfClose = true; - break; - } - } - - // do not enter a script state if the tag self-closed - if (!isSelfClose) - chAttr = SCE_H_SCRIPT; - } else if (!isXml && 0 == strcmp(s, "comment")) { - chAttr = SCE_H_COMMENT; - } - } - return chAttr; -} - -static void classifyWordHTJS(unsigned int start, unsigned int end, - WordList &keywords, Accessor &styler, script_mode inScriptType) { - char chAttr = SCE_HJ_WORD; - bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.'); - if (wordIsNumber) - chAttr = SCE_HJ_NUMBER; - else { - char s[30 + 1]; - unsigned int i = 0; - for (; i < end - start + 1 && i < 30; i++) { - s[i] = styler[start + i]; - } - s[i] = '\0'; - if (keywords.InList(s)) - chAttr = SCE_HJ_KEYWORD; - } - styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); -} - -static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, script_mode inScriptType) { - char chAttr = SCE_HB_IDENTIFIER; - bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.'); - if (wordIsNumber) - chAttr = SCE_HB_NUMBER; - else { - char s[100]; - GetTextSegment(styler, start, end, s, sizeof(s)); - if (keywords.InList(s)) { - chAttr = SCE_HB_WORD; - if (strcmp(s, "rem") == 0) - chAttr = SCE_HB_COMMENTLINE; - } - } - styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); - if (chAttr == SCE_HB_COMMENTLINE) - return SCE_HB_COMMENTLINE; - else - return SCE_HB_DEFAULT; -} - -static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord, script_mode inScriptType) { - bool wordIsNumber = IsADigit(styler[start]); - char s[30 + 1]; - unsigned int i = 0; - for (; i < end - start + 1 && i < 30; i++) { - s[i] = styler[start + i]; - } - s[i] = '\0'; - char chAttr = SCE_HP_IDENTIFIER; - if (0 == strcmp(prevWord, "class")) - chAttr = SCE_HP_CLASSNAME; - else if (0 == strcmp(prevWord, "def")) - chAttr = SCE_HP_DEFNAME; - else if (wordIsNumber) - chAttr = SCE_HP_NUMBER; - else if (keywords.InList(s)) - chAttr = SCE_HP_WORD; - styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); - strcpy(prevWord, s); -} - -// Update the word colour to default or keyword -// Called when in a PHP word -static void classifyWordHTPHP(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { - char chAttr = SCE_HPHP_DEFAULT; - bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.' && start+1 <= end && IsADigit(styler[start+1])); - if (wordIsNumber) - chAttr = SCE_HPHP_NUMBER; - else { - char s[100]; - GetTextSegment(styler, start, end, s, sizeof(s)); - if (keywords.InList(s)) - chAttr = SCE_HPHP_WORD; - } - styler.ColourTo(end, chAttr); -} - -static bool isWordHSGML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { - char s[30 + 1]; - unsigned int i = 0; - for (; i < end - start + 1 && i < 30; i++) { - s[i] = styler[start + i]; - } - s[i] = '\0'; - return keywords.InList(s); -} - -static bool isWordCdata(unsigned int start, unsigned int end, Accessor &styler) { - char s[30 + 1]; - unsigned int i = 0; - for (; i < end - start + 1 && i < 30; i++) { - s[i] = styler[start + i]; - } - s[i] = '\0'; - return (0 == strcmp(s, "[CDATA[")); -} - -// Return the first state to reach when entering a scripting language -static int StateForScript(script_type scriptLanguage) { - int Result; - switch (scriptLanguage) { - case eScriptVBS: - Result = SCE_HB_START; - break; - case eScriptPython: - Result = SCE_HP_START; - break; - case eScriptPHP: - Result = SCE_HPHP_DEFAULT; - break; - case eScriptXML: - Result = SCE_H_TAGUNKNOWN; - break; - case eScriptSGML: - Result = SCE_H_SGML_DEFAULT; - break; - case eScriptComment: - Result = SCE_H_COMMENT; - break; - default : - Result = SCE_HJ_START; - break; - } - return Result; -} - -static inline bool ishtmlwordchar(int ch) { - return !isascii(ch) || - (isalnum(ch) || ch == '.' || ch == '-' || ch == '_' || ch == ':' || ch == '!' || ch == '#'); -} - -static inline bool issgmlwordchar(int ch) { - return !isascii(ch) || - (isalnum(ch) || ch == '.' || ch == '_' || ch == ':' || ch == '!' || ch == '#' || ch == '['); -} - -static inline bool IsPhpWordStart(int ch) { - return (isascii(ch) && (isalpha(ch) || (ch == '_'))) || (ch >= 0x7f); -} - -static inline bool IsPhpWordChar(int ch) { - return IsADigit(ch) || IsPhpWordStart(ch); -} - -static bool InTagState(int state) { - return state == SCE_H_TAG || state == SCE_H_TAGUNKNOWN || - state == SCE_H_SCRIPT || - state == SCE_H_ATTRIBUTE || state == SCE_H_ATTRIBUTEUNKNOWN || - state == SCE_H_NUMBER || state == SCE_H_OTHER || - state == SCE_H_DOUBLESTRING || state == SCE_H_SINGLESTRING; -} - -static bool IsCommentState(const int state) { - return state == SCE_H_COMMENT || state == SCE_H_SGML_COMMENT; -} - -static bool IsScriptCommentState(const int state) { - return state == SCE_HJ_COMMENT || state == SCE_HJ_COMMENTLINE || state == SCE_HJA_COMMENT || - state == SCE_HJA_COMMENTLINE || state == SCE_HB_COMMENTLINE || state == SCE_HBA_COMMENTLINE; -} - -static bool isLineEnd(int ch) { - return ch == '\r' || ch == '\n'; -} - -static bool isOKBeforeRE(int ch) { - return (ch == '(') || (ch == '=') || (ch == ','); -} - -static bool isMakoBlockEnd(const int ch, const int chNext, const char *blockType) { - if (strlen(blockType) == 0) { - return ((ch == '%') && (chNext == '>')); - } else if ((0 == strcmp(blockType, "inherit")) || - (0 == strcmp(blockType, "namespace")) || - (0 == strcmp(blockType, "include")) || - (0 == strcmp(blockType, "page"))) { - return ((ch == '/') && (chNext == '>')); - } else if (0 == strcmp(blockType, "%")) { - return isLineEnd(ch); - } else if (0 == strcmp(blockType, "{")) { - return ch == '}'; - } else { - return (ch == '>'); - } -} - -static bool isDjangoBlockEnd(const int ch, const int chNext, const char *blockType) { - if (strlen(blockType) == 0) { - return 0; - } else if (0 == strcmp(blockType, "%")) { - return ((ch == '%') && (chNext == '}')); - } else if (0 == strcmp(blockType, "{")) { - return ((ch == '}') && (chNext == '}')); - } else { - return 0; - } -} - -static bool isPHPStringState(int state) { - return - (state == SCE_HPHP_HSTRING) || - (state == SCE_HPHP_SIMPLESTRING) || - (state == SCE_HPHP_HSTRING_VARIABLE) || - (state == SCE_HPHP_COMPLEX_VARIABLE); -} - -static int FindPhpStringDelimiter(char *phpStringDelimiter, const int phpStringDelimiterSize, int i, const int lengthDoc, Accessor &styler, bool &isSimpleString) { - int j; - const int beginning = i - 1; - bool isValidSimpleString = false; - - while (i < lengthDoc && (styler[i] == ' ' || styler[i] == '\t')) - i++; - - char ch = styler.SafeGetCharAt(i); - const char chNext = styler.SafeGetCharAt(i + 1); - if (!IsPhpWordStart(ch)) { - if (ch == '\'' && IsPhpWordStart(chNext)) { - i++; - ch = chNext; - isSimpleString = true; - } else { - phpStringDelimiter[0] = '\0'; - return beginning; - } - } - phpStringDelimiter[0] = ch; - i++; - - for (j = i; j < lengthDoc && !isLineEnd(styler[j]); j++) { - if (!IsPhpWordChar(styler[j])) { - if (isSimpleString && (styler[j] == '\'') && isLineEnd(styler.SafeGetCharAt(j + 1))) { - isValidSimpleString = true; - j++; - break; - } else { - phpStringDelimiter[0] = '\0'; - return beginning; - } - } - if (j - i < phpStringDelimiterSize - 2) - phpStringDelimiter[j-i+1] = styler[j]; - else - i++; - } - if (isSimpleString && !isValidSimpleString) { - phpStringDelimiter[0] = '\0'; - return beginning; - } - phpStringDelimiter[j-i+1 - (isSimpleString ? 1 : 0)] = '\0'; - return j - 1; -} - -static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler, bool isXml) { - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - WordList &keywords6 = *keywordlists[5]; // SGML (DTD) keywords - - // Lexer for HTML requires more lexical states (8 bits worth) than most lexers - styler.StartAt(startPos, static_cast(STYLE_MAX)); - char prevWord[200]; - prevWord[0] = '\0'; - char phpStringDelimiter[200]; // PHP is not limited in length, we are - phpStringDelimiter[0] = '\0'; - int StateToPrint = initStyle; - int state = stateForPrintState(StateToPrint); - char makoBlockType[200]; - makoBlockType[0] = '\0'; - char djangoBlockType[2]; - djangoBlockType[0] = '\0'; - - // If inside a tag, it may be a script tag, so reread from the start to ensure any language tags are seen - if (InTagState(state)) { - while ((startPos > 0) && (InTagState(styler.StyleAt(startPos - 1)))) { - startPos--; - length++; - } - state = SCE_H_DEFAULT; - } - // String can be heredoc, must find a delimiter first. Reread from beginning of line containing the string, to get the correct lineState - if (isPHPStringState(state)) { - while (startPos > 0 && (isPHPStringState(state) || !isLineEnd(styler[startPos - 1]))) { - startPos--; - length++; - state = styler.StyleAt(startPos); - } - if (startPos == 0) - state = SCE_H_DEFAULT; - } - styler.StartAt(startPos, static_cast(STYLE_MAX)); - - int lineCurrent = styler.GetLine(startPos); - int lineState; - if (lineCurrent > 0) { - lineState = styler.GetLineState(lineCurrent); - } else { - // Default client and ASP scripting language is JavaScript - lineState = eScriptJS << 8; - - // property asp.default.language - // Script in ASP code is initially assumed to be in JavaScript. - // To change this to VBScript set asp.default.language to 2. Python is 3. - lineState |= styler.GetPropertyInt("asp.default.language", eScriptJS) << 4; - } - script_mode inScriptType = script_mode((lineState >> 0) & 0x03); // 2 bits of scripting mode - bool tagOpened = (lineState >> 2) & 0x01; // 1 bit to know if we are in an opened tag - bool tagClosing = (lineState >> 3) & 0x01; // 1 bit to know if we are in a closing tag - bool tagDontFold = false; //some HTML tags should not be folded - script_type aspScript = script_type((lineState >> 4) & 0x0F); // 4 bits of script name - script_type clientScript = script_type((lineState >> 8) & 0x0F); // 4 bits of script name - int beforePreProc = (lineState >> 12) & 0xFF; // 8 bits of state - - script_type scriptLanguage = ScriptOfState(state); - // If eNonHtmlScript coincides with SCE_H_COMMENT, assume eScriptComment - if (inScriptType == eNonHtmlScript && state == SCE_H_COMMENT) { - scriptLanguage = eScriptComment; - } - script_type beforeLanguage = ScriptOfState(beforePreProc); - - // property fold.html - // Folding is turned on or off for HTML and XML files with this option. - // The fold option must also be on for folding to occur. - const bool foldHTML = styler.GetPropertyInt("fold.html", 0) != 0; - - const bool fold = foldHTML && styler.GetPropertyInt("fold", 0); - - // property fold.html.preprocessor - // Folding is turned on or off for scripts embedded in HTML files with this option. - // The default is on. - const bool foldHTMLPreprocessor = foldHTML && styler.GetPropertyInt("fold.html.preprocessor", 1); - - const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - - // property fold.hypertext.comment - // Allow folding for comments in scripts embedded in HTML. - // The default is off. - const bool foldComment = fold && styler.GetPropertyInt("fold.hypertext.comment", 0) != 0; - - // property fold.hypertext.heredoc - // Allow folding for heredocs in scripts embedded in HTML. - // The default is off. - const bool foldHeredoc = fold && styler.GetPropertyInt("fold.hypertext.heredoc", 0) != 0; - - // property html.tags.case.sensitive - // For XML and HTML, setting this property to 1 will make tags match in a case - // sensitive way which is the expected behaviour for XML and XHTML. - const bool caseSensitive = styler.GetPropertyInt("html.tags.case.sensitive", 0) != 0; - - // property lexer.xml.allow.scripts - // Set to 0 to disable scripts in XML. - const bool allowScripts = styler.GetPropertyInt("lexer.xml.allow.scripts", 1) != 0; - - // property lexer.html.mako - // Set to 1 to enable the mako template language. - const bool isMako = styler.GetPropertyInt("lexer.html.mako", 0) != 0; - - // property lexer.html.django - // Set to 1 to enable the django template language. - const bool isDjango = styler.GetPropertyInt("lexer.html.django", 0) != 0; - - const CharacterSet setHTMLWord(CharacterSet::setAlphaNum, ".-_:!#", 0x80, true); - const CharacterSet setTagContinue(CharacterSet::setAlphaNum, ".-_:!#[", 0x80, true); - const CharacterSet setAttributeContinue(CharacterSet::setAlphaNum, ".-_:!#/", 0x80, true); - - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - int visibleChars = 0; - int lineStartVisibleChars = 0; - - int chPrev = ' '; - int ch = ' '; - int chPrevNonWhite = ' '; - // look back to set chPrevNonWhite properly for better regex colouring - if (scriptLanguage == eScriptJS && startPos > 0) { - int back = startPos; - int style = 0; - while (--back) { - style = styler.StyleAt(back); - if (style < SCE_HJ_DEFAULT || style > SCE_HJ_COMMENTDOC) - // includes SCE_HJ_COMMENT & SCE_HJ_COMMENTLINE - break; - } - if (style == SCE_HJ_SYMBOLS) { - chPrevNonWhite = static_cast(styler.SafeGetCharAt(back)); - } - } - - styler.StartSegment(startPos); - const int lengthDoc = startPos + length; - for (int i = startPos; i < lengthDoc; i++) { - const int chPrev2 = chPrev; - chPrev = ch; - if (!IsASpace(ch) && state != SCE_HJ_COMMENT && - state != SCE_HJ_COMMENTLINE && state != SCE_HJ_COMMENTDOC) - chPrevNonWhite = ch; - ch = static_cast(styler[i]); - int chNext = static_cast(styler.SafeGetCharAt(i + 1)); - const int chNext2 = static_cast(styler.SafeGetCharAt(i + 2)); - - // Handle DBCS codepages - if (styler.IsLeadByte(static_cast(ch))) { - chPrev = ' '; - i += 1; - continue; - } - - if ((!IsASpace(ch) || !foldCompact) && fold) - visibleChars++; - if (!IsASpace(ch)) - lineStartVisibleChars++; - - // decide what is the current state to print (depending of the script tag) - StateToPrint = statePrintForState(state, inScriptType); - - // handle script folding - if (fold) { - switch (scriptLanguage) { - case eScriptJS: - case eScriptPHP: - //not currently supported case eScriptVBS: - - if ((state != SCE_HPHP_COMMENT) && (state != SCE_HPHP_COMMENTLINE) && (state != SCE_HJ_COMMENT) && (state != SCE_HJ_COMMENTLINE) && (state != SCE_HJ_COMMENTDOC) && (!isStringState(state))) { - //Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle); - //if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) { - if ((ch == '{') || (ch == '}') || (foldComment && (ch == '/') && (chNext == '*'))) { - levelCurrent += ((ch == '{') || (ch == '/')) ? 1 : -1; - } - } else if (((state == SCE_HPHP_COMMENT) || (state == SCE_HJ_COMMENT)) && foldComment && (ch == '*') && (chNext == '/')) { - levelCurrent--; - } - break; - case eScriptPython: - if (state != SCE_HP_COMMENTLINE) { - if ((ch == ':') && ((chNext == '\n') || (chNext == '\r' && chNext2 == '\n'))) { - levelCurrent++; - } else if ((ch == '\n') && !((chNext == '\r') && (chNext2 == '\n')) && (chNext != '\n')) { - // check if the number of tabs is lower than the level - int Findlevel = (levelCurrent & ~SC_FOLDLEVELBASE) * 8; - for (int j = 0; Findlevel > 0; j++) { - char chTmp = styler.SafeGetCharAt(i + j + 1); - if (chTmp == '\t') { - Findlevel -= 8; - } else if (chTmp == ' ') { - Findlevel--; - } else { - break; - } - } - - if (Findlevel > 0) { - levelCurrent -= Findlevel / 8; - if (Findlevel % 8) - levelCurrent--; - } - } - } - break; - default: - break; - } - } - - if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { - // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) - // Avoid triggering two times on Dos/Win - // New line -> record any line state onto /next/ line - if (fold) { - int lev = levelPrev; - if (visibleChars == 0) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - - styler.SetLevel(lineCurrent, lev); - visibleChars = 0; - levelPrev = levelCurrent; - } - lineCurrent++; - lineStartVisibleChars = 0; - styler.SetLineState(lineCurrent, - ((inScriptType & 0x03) << 0) | - ((tagOpened & 0x01) << 2) | - ((tagClosing & 0x01) << 3) | - ((aspScript & 0x0F) << 4) | - ((clientScript & 0x0F) << 8) | - ((beforePreProc & 0xFF) << 12)); - } - - // Allow falling through to mako handling code if newline is going to end a block - if (((ch == '\r' && chNext != '\n') || (ch == '\n')) && - (!isMako || (0 != strcmp(makoBlockType, "%")))) { - } - - // generic end of script processing - else if ((inScriptType == eNonHtmlScript) && (ch == '<') && (chNext == '/')) { - // Check if it's the end of the script tag (or any other HTML tag) - switch (state) { - // in these cases, you can embed HTML tags (to confirm !!!!!!!!!!!!!!!!!!!!!!) - case SCE_H_DOUBLESTRING: - case SCE_H_SINGLESTRING: - case SCE_HJ_COMMENT: - case SCE_HJ_COMMENTDOC: - //case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide - // the end of script marker from some JS interpreters. - case SCE_HB_COMMENTLINE: - case SCE_HBA_COMMENTLINE: - case SCE_HJ_DOUBLESTRING: - case SCE_HJ_SINGLESTRING: - case SCE_HJ_REGEX: - case SCE_HB_STRING: - case SCE_HBA_STRING: - case SCE_HP_STRING: - case SCE_HP_TRIPLE: - case SCE_HP_TRIPLEDOUBLE: - case SCE_HPHP_HSTRING: - case SCE_HPHP_SIMPLESTRING: - case SCE_HPHP_COMMENT: - case SCE_HPHP_COMMENTLINE: - break; - default : - // check if the closing tag is a script tag - if (const char *tag = - state == SCE_HJ_COMMENTLINE || isXml ? "script" : - state == SCE_H_COMMENT ? "comment" : 0) { - int j = i + 2; - int chr; - do { - chr = static_cast(*tag++); - } while (chr != 0 && chr == MakeLowerCase(styler.SafeGetCharAt(j++))); - if (chr != 0) break; - } - // closing tag of the script (it's a closing HTML tag anyway) - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_TAGUNKNOWN; - inScriptType = eHtml; - scriptLanguage = eScriptNone; - clientScript = eScriptJS; - i += 2; - visibleChars += 2; - tagClosing = true; - continue; - } - } - - ///////////////////////////////////// - // handle the start of PHP pre-processor = Non-HTML - else if ((state != SCE_H_ASPAT) && - !isPHPStringState(state) && - (state != SCE_HPHP_COMMENT) && - (state != SCE_HPHP_COMMENTLINE) && - (ch == '<') && - (chNext == '?') && - !IsScriptCommentState(state) ) { - scriptLanguage = segIsScriptingIndicator(styler, i + 2, i + 6, eScriptPHP); - if (scriptLanguage != eScriptPHP && isStringState(state)) continue; - styler.ColourTo(i - 1, StateToPrint); - beforePreProc = state; - i++; - visibleChars++; - i += PrintScriptingIndicatorOffset(styler, styler.GetStartSegment() + 2, i + 6); - if (scriptLanguage == eScriptXML) - styler.ColourTo(i, SCE_H_XMLSTART); - else - styler.ColourTo(i, SCE_H_QUESTION); - state = StateForScript(scriptLanguage); - if (inScriptType == eNonHtmlScript) - inScriptType = eNonHtmlScriptPreProc; - else - inScriptType = eNonHtmlPreProc; - // Fold whole script, but not if the XML first tag (all XML-like tags in this case) - if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) { - levelCurrent++; - } - // should be better - ch = static_cast(styler.SafeGetCharAt(i)); - continue; - } - - // handle the start Mako template Python code - else if (isMako && scriptLanguage == eScriptNone && ((ch == '<' && chNext == '%') || - (lineStartVisibleChars == 1 && ch == '%') || - (ch == '$' && chNext == '{') || - (ch == '<' && chNext == '/' && chNext2 == '%'))) { - if (ch == '%') - strcpy(makoBlockType, "%"); - else if (ch == '$') - strcpy(makoBlockType, "{"); - else if (chNext == '/') - GetNextWord(styler, i+3, makoBlockType, sizeof(makoBlockType)); - else - GetNextWord(styler, i+2, makoBlockType, sizeof(makoBlockType)); - styler.ColourTo(i - 1, StateToPrint); - beforePreProc = state; - if (inScriptType == eNonHtmlScript) - inScriptType = eNonHtmlScriptPreProc; - else - inScriptType = eNonHtmlPreProc; - - if (chNext == '/') { - i += 2; - visibleChars += 2; - } else if (ch != '%') { - i++; - visibleChars++; - } - state = SCE_HP_START; - scriptLanguage = eScriptPython; - styler.ColourTo(i, SCE_H_ASP); - if (foldHTMLPreprocessor && ch == '<') - levelCurrent++; - - if (ch != '%' && ch != '$') { - i += strlen(makoBlockType); - visibleChars += strlen(makoBlockType); - if (keywords4.InList(makoBlockType)) - styler.ColourTo(i, SCE_HP_WORD); - else - styler.ColourTo(i, SCE_H_TAGUNKNOWN); - } - - ch = static_cast(styler.SafeGetCharAt(i)); - continue; - } - - // handle the start Django template code - else if (isDjango && scriptLanguage != eScriptPython && (ch == '{' && (chNext == '%' || chNext == '{'))) { - if (chNext == '%') - strcpy(djangoBlockType, "%"); - else - strcpy(djangoBlockType, "{"); - styler.ColourTo(i - 1, StateToPrint); - beforePreProc = state; - if (inScriptType == eNonHtmlScript) - inScriptType = eNonHtmlScriptPreProc; - else - inScriptType = eNonHtmlPreProc; - - i += 1; - visibleChars += 1; - state = SCE_HP_START; - beforeLanguage = scriptLanguage; - scriptLanguage = eScriptPython; - styler.ColourTo(i, SCE_H_ASP); - if (foldHTMLPreprocessor && chNext == '%') - levelCurrent++; - - ch = static_cast(styler.SafeGetCharAt(i)); - continue; - } - - // handle the start of ASP pre-processor = Non-HTML - else if (!isMako && !isDjango && !isCommentASPState(state) && (ch == '<') && (chNext == '%') && !isPHPStringState(state)) { - styler.ColourTo(i - 1, StateToPrint); - beforePreProc = state; - if (inScriptType == eNonHtmlScript) - inScriptType = eNonHtmlScriptPreProc; - else - inScriptType = eNonHtmlPreProc; - - if (chNext2 == '@') { - i += 2; // place as if it was the second next char treated - visibleChars += 2; - state = SCE_H_ASPAT; - } else if ((chNext2 == '-') && (styler.SafeGetCharAt(i + 3) == '-')) { - styler.ColourTo(i + 3, SCE_H_ASP); - state = SCE_H_XCCOMMENT; - scriptLanguage = eScriptVBS; - continue; - } else { - if (chNext2 == '=') { - i += 2; // place as if it was the second next char treated - visibleChars += 2; - } else { - i++; // place as if it was the next char treated - visibleChars++; - } - - state = StateForScript(aspScript); - } - scriptLanguage = eScriptVBS; - styler.ColourTo(i, SCE_H_ASP); - // fold whole script - if (foldHTMLPreprocessor) - levelCurrent++; - // should be better - ch = static_cast(styler.SafeGetCharAt(i)); - continue; - } - - ///////////////////////////////////// - // handle the start of SGML language (DTD) - else if (((scriptLanguage == eScriptNone) || (scriptLanguage == eScriptXML)) && - (chPrev == '<') && - (ch == '!') && - (StateToPrint != SCE_H_CDATA) && - (!IsCommentState(StateToPrint)) && - (!IsScriptCommentState(StateToPrint)) ) { - beforePreProc = state; - styler.ColourTo(i - 2, StateToPrint); - if ((chNext == '-') && (chNext2 == '-')) { - state = SCE_H_COMMENT; // wait for a pending command - styler.ColourTo(i + 2, SCE_H_COMMENT); - i += 2; // follow styling after the -- - } else if (isWordCdata(i + 1, i + 7, styler)) { - state = SCE_H_CDATA; - } else { - styler.ColourTo(i, SCE_H_SGML_DEFAULT); // ') { - i++; - visibleChars++; - } - if (0 != strcmp(makoBlockType, "%")) { - styler.ColourTo(i, SCE_H_ASP); - } - state = beforePreProc; - if (inScriptType == eNonHtmlScriptPreProc) - inScriptType = eNonHtmlScript; - else - inScriptType = eHtml; - if (foldHTMLPreprocessor && ch != '\n' && ch != '\r') { - levelCurrent--; - } - scriptLanguage = eScriptNone; - continue; - } - - // handle the end of Django template code - else if (isDjango && - ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && - (scriptLanguage != eScriptNone) && stateAllowsTermination(state) && - isDjangoBlockEnd(ch, chNext, djangoBlockType)) { - if (state == SCE_H_ASPAT) { - aspScript = segIsScriptingIndicator(styler, - styler.GetStartSegment(), i - 1, aspScript); - } - if (state == SCE_HP_WORD) { - classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType); - } else { - styler.ColourTo(i - 1, StateToPrint); - } - i += 1; - visibleChars += 1; - styler.ColourTo(i, SCE_H_ASP); - state = beforePreProc; - if (inScriptType == eNonHtmlScriptPreProc) - inScriptType = eNonHtmlScript; - else - inScriptType = eHtml; - if (foldHTMLPreprocessor) { - levelCurrent--; - } - scriptLanguage = beforeLanguage; - continue; - } - - // handle the end of a pre-processor = Non-HTML - else if ((!isMako && !isDjango && ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && - (((scriptLanguage != eScriptNone) && stateAllowsTermination(state))) && - (((ch == '%') || (ch == '?')) && (chNext == '>'))) || - ((scriptLanguage == eScriptSGML) && (ch == '>') && (state != SCE_H_SGML_COMMENT))) { - if (state == SCE_H_ASPAT) { - aspScript = segIsScriptingIndicator(styler, - styler.GetStartSegment(), i - 1, aspScript); - } - // Bounce out of any ASP mode - switch (state) { - case SCE_HJ_WORD: - classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType); - break; - case SCE_HB_WORD: - classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType); - break; - case SCE_HP_WORD: - classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType); - break; - case SCE_HPHP_WORD: - classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler); - break; - case SCE_H_XCCOMMENT: - styler.ColourTo(i - 1, state); - break; - default : - styler.ColourTo(i - 1, StateToPrint); - break; - } - if (scriptLanguage != eScriptSGML) { - i++; - visibleChars++; - } - if (ch == '%') - styler.ColourTo(i, SCE_H_ASP); - else if (scriptLanguage == eScriptXML) - styler.ColourTo(i, SCE_H_XMLEND); - else if (scriptLanguage == eScriptSGML) - styler.ColourTo(i, SCE_H_SGML_DEFAULT); - else - styler.ColourTo(i, SCE_H_QUESTION); - state = beforePreProc; - if (inScriptType == eNonHtmlScriptPreProc) - inScriptType = eNonHtmlScript; - else - inScriptType = eHtml; - // Unfold all scripting languages, except for XML tag - if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) { - levelCurrent--; - } - scriptLanguage = eScriptNone; - continue; - } - ///////////////////////////////////// - - switch (state) { - case SCE_H_DEFAULT: - if (ch == '<') { - // in HTML, fold on tag open and unfold on tag close - tagOpened = true; - tagClosing = (chNext == '/'); - styler.ColourTo(i - 1, StateToPrint); - if (chNext != '!') - state = SCE_H_TAGUNKNOWN; - } else if (ch == '&') { - styler.ColourTo(i - 1, SCE_H_DEFAULT); - state = SCE_H_ENTITY; - } - break; - case SCE_H_SGML_DEFAULT: - case SCE_H_SGML_BLOCK_DEFAULT: -// if (scriptLanguage == eScriptSGMLblock) -// StateToPrint = SCE_H_SGML_BLOCK_DEFAULT; - - if (ch == '\"') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_SGML_DOUBLESTRING; - } else if (ch == '\'') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_SGML_SIMPLESTRING; - } else if ((ch == '-') && (chPrev == '-')) { - if (static_cast(styler.GetStartSegment()) <= (i - 2)) { - styler.ColourTo(i - 2, StateToPrint); - } - state = SCE_H_SGML_COMMENT; - } else if (isascii(ch) && isalpha(ch) && (chPrev == '%')) { - styler.ColourTo(i - 2, StateToPrint); - state = SCE_H_SGML_ENTITY; - } else if (ch == '#') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_SGML_SPECIAL; - } else if (ch == '[') { - styler.ColourTo(i - 1, StateToPrint); - scriptLanguage = eScriptSGMLblock; - state = SCE_H_SGML_BLOCK_DEFAULT; - } else if (ch == ']') { - if (scriptLanguage == eScriptSGMLblock) { - styler.ColourTo(i, StateToPrint); - scriptLanguage = eScriptSGML; - } else { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i, SCE_H_SGML_ERROR); - } - state = SCE_H_SGML_DEFAULT; - } else if (scriptLanguage == eScriptSGMLblock) { - if ((ch == '!') && (chPrev == '<')) { - styler.ColourTo(i - 2, StateToPrint); - styler.ColourTo(i, SCE_H_SGML_DEFAULT); - state = SCE_H_SGML_COMMAND; - } else if (ch == '>') { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i, SCE_H_SGML_DEFAULT); - } - } - break; - case SCE_H_SGML_COMMAND: - if ((ch == '-') && (chPrev == '-')) { - styler.ColourTo(i - 2, StateToPrint); - state = SCE_H_SGML_COMMENT; - } else if (!issgmlwordchar(ch)) { - if (isWordHSGML(styler.GetStartSegment(), i - 1, keywords6, styler)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_SGML_1ST_PARAM; - } else { - state = SCE_H_SGML_ERROR; - } - } - break; - case SCE_H_SGML_1ST_PARAM: - // wait for the beginning of the word - if ((ch == '-') && (chPrev == '-')) { - if (scriptLanguage == eScriptSGMLblock) { - styler.ColourTo(i - 2, SCE_H_SGML_BLOCK_DEFAULT); - } else { - styler.ColourTo(i - 2, SCE_H_SGML_DEFAULT); - } - state = SCE_H_SGML_1ST_PARAM_COMMENT; - } else if (issgmlwordchar(ch)) { - if (scriptLanguage == eScriptSGMLblock) { - styler.ColourTo(i - 1, SCE_H_SGML_BLOCK_DEFAULT); - } else { - styler.ColourTo(i - 1, SCE_H_SGML_DEFAULT); - } - // find the length of the word - int size = 1; - while (setHTMLWord.Contains(static_cast(styler.SafeGetCharAt(i + size)))) - size++; - styler.ColourTo(i + size - 1, StateToPrint); - i += size - 1; - visibleChars += size - 1; - ch = static_cast(styler.SafeGetCharAt(i)); - if (scriptLanguage == eScriptSGMLblock) { - state = SCE_H_SGML_BLOCK_DEFAULT; - } else { - state = SCE_H_SGML_DEFAULT; - } - continue; - } - break; - case SCE_H_SGML_ERROR: - if ((ch == '-') && (chPrev == '-')) { - styler.ColourTo(i - 2, StateToPrint); - state = SCE_H_SGML_COMMENT; - } - case SCE_H_SGML_DOUBLESTRING: - if (ch == '\"') { - styler.ColourTo(i, StateToPrint); - state = SCE_H_SGML_DEFAULT; - } - break; - case SCE_H_SGML_SIMPLESTRING: - if (ch == '\'') { - styler.ColourTo(i, StateToPrint); - state = SCE_H_SGML_DEFAULT; - } - break; - case SCE_H_SGML_COMMENT: - if ((ch == '-') && (chPrev == '-')) { - styler.ColourTo(i, StateToPrint); - state = SCE_H_SGML_DEFAULT; - } - break; - case SCE_H_CDATA: - if ((chPrev2 == ']') && (chPrev == ']') && (ch == '>')) { - styler.ColourTo(i, StateToPrint); - state = SCE_H_DEFAULT; - levelCurrent--; - } - break; - case SCE_H_COMMENT: - if ((scriptLanguage != eScriptComment) && (chPrev2 == '-') && (chPrev == '-') && (ch == '>')) { - styler.ColourTo(i, StateToPrint); - state = SCE_H_DEFAULT; - levelCurrent--; - } - break; - case SCE_H_SGML_1ST_PARAM_COMMENT: - if ((ch == '-') && (chPrev == '-')) { - styler.ColourTo(i, SCE_H_SGML_COMMENT); - state = SCE_H_SGML_1ST_PARAM; - } - break; - case SCE_H_SGML_SPECIAL: - if (!(isascii(ch) && isupper(ch))) { - styler.ColourTo(i - 1, StateToPrint); - if (isalnum(ch)) { - state = SCE_H_SGML_ERROR; - } else { - state = SCE_H_SGML_DEFAULT; - } - } - break; - case SCE_H_SGML_ENTITY: - if (ch == ';') { - styler.ColourTo(i, StateToPrint); - state = SCE_H_SGML_DEFAULT; - } else if (!(isascii(ch) && isalnum(ch)) && ch != '-' && ch != '.') { - styler.ColourTo(i, SCE_H_SGML_ERROR); - state = SCE_H_SGML_DEFAULT; - } - break; - case SCE_H_ENTITY: - if (ch == ';') { - styler.ColourTo(i, StateToPrint); - state = SCE_H_DEFAULT; - } - if (ch != '#' && !(isascii(ch) && isalnum(ch)) // Should check that '#' follows '&', but it is unlikely anyway... - && ch != '.' && ch != '-' && ch != '_' && ch != ':') { // valid in XML - if (!isascii(ch)) // Possibly start of a multibyte character so don't allow this byte to be in entity style - styler.ColourTo(i-1, SCE_H_TAGUNKNOWN); - else - styler.ColourTo(i, SCE_H_TAGUNKNOWN); - state = SCE_H_DEFAULT; - } - break; - case SCE_H_TAGUNKNOWN: - if (!setTagContinue.Contains(ch) && !((ch == '/') && (chPrev == '<'))) { - int eClass = classifyTagHTML(styler.GetStartSegment(), - i - 1, keywords, styler, tagDontFold, caseSensitive, isXml, allowScripts); - if (eClass == SCE_H_SCRIPT || eClass == SCE_H_COMMENT) { - if (!tagClosing) { - inScriptType = eNonHtmlScript; - scriptLanguage = eClass == SCE_H_SCRIPT ? clientScript : eScriptComment; - } else { - scriptLanguage = eScriptNone; - } - eClass = SCE_H_TAG; - } - if (ch == '>') { - styler.ColourTo(i, eClass); - if (inScriptType == eNonHtmlScript) { - state = StateForScript(scriptLanguage); - } else { - state = SCE_H_DEFAULT; - } - tagOpened = false; - if (!tagDontFold) { - if (tagClosing) { - levelCurrent--; - } else { - levelCurrent++; - } - } - tagClosing = false; - } else if (ch == '/' && chNext == '>') { - if (eClass == SCE_H_TAGUNKNOWN) { - styler.ColourTo(i + 1, SCE_H_TAGUNKNOWN); - } else { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i + 1, SCE_H_TAGEND); - } - i++; - ch = chNext; - state = SCE_H_DEFAULT; - tagOpened = false; - } else { - if (eClass != SCE_H_TAGUNKNOWN) { - if (eClass == SCE_H_SGML_DEFAULT) { - state = SCE_H_SGML_DEFAULT; - } else { - state = SCE_H_OTHER; - } - } - } - } - break; - case SCE_H_ATTRIBUTE: - if (!setAttributeContinue.Contains(ch)) { - if (inScriptType == eNonHtmlScript) { - int scriptLanguagePrev = scriptLanguage; - clientScript = segIsScriptingIndicator(styler, styler.GetStartSegment(), i - 1, scriptLanguage); - scriptLanguage = clientScript; - if ((scriptLanguagePrev != scriptLanguage) && (scriptLanguage == eScriptNone)) - inScriptType = eHtml; - } - classifyAttribHTML(styler.GetStartSegment(), i - 1, keywords, styler); - if (ch == '>') { - styler.ColourTo(i, SCE_H_TAG); - if (inScriptType == eNonHtmlScript) { - state = StateForScript(scriptLanguage); - } else { - state = SCE_H_DEFAULT; - } - tagOpened = false; - if (!tagDontFold) { - if (tagClosing) { - levelCurrent--; - } else { - levelCurrent++; - } - } - tagClosing = false; - } else if (ch == '=') { - styler.ColourTo(i, SCE_H_OTHER); - state = SCE_H_VALUE; - } else { - state = SCE_H_OTHER; - } - } - break; - case SCE_H_OTHER: - if (ch == '>') { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i, SCE_H_TAG); - if (inScriptType == eNonHtmlScript) { - state = StateForScript(scriptLanguage); - } else { - state = SCE_H_DEFAULT; - } - tagOpened = false; - if (!tagDontFold) { - if (tagClosing) { - levelCurrent--; - } else { - levelCurrent++; - } - } - tagClosing = false; - } else if (ch == '\"') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_DOUBLESTRING; - } else if (ch == '\'') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_SINGLESTRING; - } else if (ch == '=') { - styler.ColourTo(i, StateToPrint); - state = SCE_H_VALUE; - } else if (ch == '/' && chNext == '>') { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i + 1, SCE_H_TAGEND); - i++; - ch = chNext; - state = SCE_H_DEFAULT; - tagOpened = false; - } else if (ch == '?' && chNext == '>') { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i + 1, SCE_H_XMLEND); - i++; - ch = chNext; - state = SCE_H_DEFAULT; - } else if (setHTMLWord.Contains(ch)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_H_ATTRIBUTE; - } - break; - case SCE_H_DOUBLESTRING: - if (ch == '\"') { - if (inScriptType == eNonHtmlScript) { - scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage); - } - styler.ColourTo(i, SCE_H_DOUBLESTRING); - state = SCE_H_OTHER; - } - break; - case SCE_H_SINGLESTRING: - if (ch == '\'') { - if (inScriptType == eNonHtmlScript) { - scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage); - } - styler.ColourTo(i, SCE_H_SINGLESTRING); - state = SCE_H_OTHER; - } - break; - case SCE_H_VALUE: - if (!setHTMLWord.Contains(ch)) { - if (ch == '\"' && chPrev == '=') { - // Should really test for being first character - state = SCE_H_DOUBLESTRING; - } else if (ch == '\'' && chPrev == '=') { - state = SCE_H_SINGLESTRING; - } else { - if (IsNumber(styler.GetStartSegment(), styler)) { - styler.ColourTo(i - 1, SCE_H_NUMBER); - } else { - styler.ColourTo(i - 1, StateToPrint); - } - if (ch == '>') { - styler.ColourTo(i, SCE_H_TAG); - if (inScriptType == eNonHtmlScript) { - state = StateForScript(scriptLanguage); - } else { - state = SCE_H_DEFAULT; - } - tagOpened = false; - if (!tagDontFold) { - if (tagClosing) { - levelCurrent--; - } else { - levelCurrent++; - } - } - tagClosing = false; - } else { - state = SCE_H_OTHER; - } - } - } - break; - case SCE_HJ_DEFAULT: - case SCE_HJ_START: - case SCE_HJ_SYMBOLS: - if (IsAWordStart(ch)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_WORD; - } else if (ch == '/' && chNext == '*') { - styler.ColourTo(i - 1, StateToPrint); - if (chNext2 == '*') - state = SCE_HJ_COMMENTDOC; - else - state = SCE_HJ_COMMENT; - } else if (ch == '/' && chNext == '/') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_COMMENTLINE; - } else if (ch == '/' && isOKBeforeRE(chPrevNonWhite)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_REGEX; - } else if (ch == '\"') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_DOUBLESTRING; - } else if (ch == '\'') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_SINGLESTRING; - } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && - styler.SafeGetCharAt(i + 3) == '-') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_COMMENTLINE; - } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_COMMENTLINE; - i += 2; - } else if (IsOperator(ch)) { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); - state = SCE_HJ_DEFAULT; - } else if ((ch == ' ') || (ch == '\t')) { - if (state == SCE_HJ_START) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_DEFAULT; - } - } - break; - case SCE_HJ_WORD: - if (!IsAWordChar(ch)) { - classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType); - //styler.ColourTo(i - 1, eHTJSKeyword); - state = SCE_HJ_DEFAULT; - if (ch == '/' && chNext == '*') { - if (chNext2 == '*') - state = SCE_HJ_COMMENTDOC; - else - state = SCE_HJ_COMMENT; - } else if (ch == '/' && chNext == '/') { - state = SCE_HJ_COMMENTLINE; - } else if (ch == '\"') { - state = SCE_HJ_DOUBLESTRING; - } else if (ch == '\'') { - state = SCE_HJ_SINGLESTRING; - } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_COMMENTLINE; - i += 2; - } else if (IsOperator(ch)) { - styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); - state = SCE_HJ_DEFAULT; - } - } - break; - case SCE_HJ_COMMENT: - case SCE_HJ_COMMENTDOC: - if (ch == '/' && chPrev == '*') { - styler.ColourTo(i, StateToPrint); - state = SCE_HJ_DEFAULT; - ch = ' '; - } - break; - case SCE_HJ_COMMENTLINE: - if (ch == '\r' || ch == '\n') { - styler.ColourTo(i - 1, statePrintForState(SCE_HJ_COMMENTLINE, inScriptType)); - state = SCE_HJ_DEFAULT; - ch = ' '; - } - break; - case SCE_HJ_DOUBLESTRING: - if (ch == '\\') { - if (chNext == '\"' || chNext == '\'' || chNext == '\\') { - i++; - } - } else if (ch == '\"') { - styler.ColourTo(i, statePrintForState(SCE_HJ_DOUBLESTRING, inScriptType)); - state = SCE_HJ_DEFAULT; - } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_COMMENTLINE; - i += 2; - } else if (isLineEnd(ch)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_STRINGEOL; - } - break; - case SCE_HJ_SINGLESTRING: - if (ch == '\\') { - if (chNext == '\"' || chNext == '\'' || chNext == '\\') { - i++; - } - } else if (ch == '\'') { - styler.ColourTo(i, statePrintForState(SCE_HJ_SINGLESTRING, inScriptType)); - state = SCE_HJ_DEFAULT; - } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_COMMENTLINE; - i += 2; - } else if (isLineEnd(ch)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_STRINGEOL; - } - break; - case SCE_HJ_STRINGEOL: - if (!isLineEnd(ch)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_DEFAULT; - } else if (!isLineEnd(chNext)) { - styler.ColourTo(i, StateToPrint); - state = SCE_HJ_DEFAULT; - } - break; - case SCE_HJ_REGEX: - if (ch == '\r' || ch == '\n' || ch == '/') { - if (ch == '/') { - while (isascii(chNext) && islower(chNext)) { // gobble regex flags - i++; - ch = chNext; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } - } - styler.ColourTo(i, StateToPrint); - state = SCE_HJ_DEFAULT; - } else if (ch == '\\') { - // Gobble up the quoted character - if (chNext == '\\' || chNext == '/') { - i++; - ch = chNext; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } - } - break; - case SCE_HB_DEFAULT: - case SCE_HB_START: - if (IsAWordStart(ch)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_WORD; - } else if (ch == '\'') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_COMMENTLINE; - } else if (ch == '\"') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_STRING; - } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && - styler.SafeGetCharAt(i + 3) == '-') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_COMMENTLINE; - } else if (IsOperator(ch)) { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType)); - state = SCE_HB_DEFAULT; - } else if ((ch == ' ') || (ch == '\t')) { - if (state == SCE_HB_START) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_DEFAULT; - } - } - break; - case SCE_HB_WORD: - if (!IsAWordChar(ch)) { - state = classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType); - if (state == SCE_HB_DEFAULT) { - if (ch == '\"') { - state = SCE_HB_STRING; - } else if (ch == '\'') { - state = SCE_HB_COMMENTLINE; - } else if (IsOperator(ch)) { - styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType)); - state = SCE_HB_DEFAULT; - } - } - } - break; - case SCE_HB_STRING: - if (ch == '\"') { - styler.ColourTo(i, StateToPrint); - state = SCE_HB_DEFAULT; - } else if (ch == '\r' || ch == '\n') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_STRINGEOL; - } - break; - case SCE_HB_COMMENTLINE: - if (ch == '\r' || ch == '\n') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_DEFAULT; - } - break; - case SCE_HB_STRINGEOL: - if (!isLineEnd(ch)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HB_DEFAULT; - } else if (!isLineEnd(chNext)) { - styler.ColourTo(i, StateToPrint); - state = SCE_HB_DEFAULT; - } - break; - case SCE_HP_DEFAULT: - case SCE_HP_START: - if (IsAWordStart(ch)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HP_WORD; - } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && - styler.SafeGetCharAt(i + 3) == '-') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HP_COMMENTLINE; - } else if (ch == '#') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HP_COMMENTLINE; - } else if (ch == '\"') { - styler.ColourTo(i - 1, StateToPrint); - if (chNext == '\"' && chNext2 == '\"') { - i += 2; - state = SCE_HP_TRIPLEDOUBLE; - ch = ' '; - chPrev = ' '; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } else { - // state = statePrintForState(SCE_HP_STRING,inScriptType); - state = SCE_HP_STRING; - } - } else if (ch == '\'') { - styler.ColourTo(i - 1, StateToPrint); - if (chNext == '\'' && chNext2 == '\'') { - i += 2; - state = SCE_HP_TRIPLE; - ch = ' '; - chPrev = ' '; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } else { - state = SCE_HP_CHARACTER; - } - } else if (IsOperator(ch)) { - styler.ColourTo(i - 1, StateToPrint); - styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType)); - } else if ((ch == ' ') || (ch == '\t')) { - if (state == SCE_HP_START) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HP_DEFAULT; - } - } - break; - case SCE_HP_WORD: - if (!IsAWordChar(ch)) { - classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType); - state = SCE_HP_DEFAULT; - if (ch == '#') { - state = SCE_HP_COMMENTLINE; - } else if (ch == '\"') { - if (chNext == '\"' && chNext2 == '\"') { - i += 2; - state = SCE_HP_TRIPLEDOUBLE; - ch = ' '; - chPrev = ' '; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } else { - state = SCE_HP_STRING; - } - } else if (ch == '\'') { - if (chNext == '\'' && chNext2 == '\'') { - i += 2; - state = SCE_HP_TRIPLE; - ch = ' '; - chPrev = ' '; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } else { - state = SCE_HP_CHARACTER; - } - } else if (IsOperator(ch)) { - styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType)); - } - } - break; - case SCE_HP_COMMENTLINE: - if (ch == '\r' || ch == '\n') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HP_DEFAULT; - } - break; - case SCE_HP_STRING: - if (ch == '\\') { - if (chNext == '\"' || chNext == '\'' || chNext == '\\') { - i++; - ch = chNext; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } - } else if (ch == '\"') { - styler.ColourTo(i, StateToPrint); - state = SCE_HP_DEFAULT; - } - break; - case SCE_HP_CHARACTER: - if (ch == '\\') { - if (chNext == '\"' || chNext == '\'' || chNext == '\\') { - i++; - ch = chNext; - chNext = static_cast(styler.SafeGetCharAt(i + 1)); - } - } else if (ch == '\'') { - styler.ColourTo(i, StateToPrint); - state = SCE_HP_DEFAULT; - } - break; - case SCE_HP_TRIPLE: - if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') { - styler.ColourTo(i, StateToPrint); - state = SCE_HP_DEFAULT; - } - break; - case SCE_HP_TRIPLEDOUBLE: - if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') { - styler.ColourTo(i, StateToPrint); - state = SCE_HP_DEFAULT; - } - break; - ///////////// start - PHP state handling - case SCE_HPHP_WORD: - if (!IsAWordChar(ch)) { - classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler); - if (ch == '/' && chNext == '*') { - i++; - state = SCE_HPHP_COMMENT; - } else if (ch == '/' && chNext == '/') { - i++; - state = SCE_HPHP_COMMENTLINE; - } else if (ch == '#') { - state = SCE_HPHP_COMMENTLINE; - } else if (ch == '\"') { - state = SCE_HPHP_HSTRING; - strcpy(phpStringDelimiter, "\""); - } else if (styler.Match(i, "<<<")) { - bool isSimpleString = false; - i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString); - if (strlen(phpStringDelimiter)) { - state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING); - if (foldHeredoc) levelCurrent++; - } - } else if (ch == '\'') { - state = SCE_HPHP_SIMPLESTRING; - strcpy(phpStringDelimiter, "\'"); - } else if (ch == '$' && IsPhpWordStart(chNext)) { - state = SCE_HPHP_VARIABLE; - } else if (IsOperator(ch)) { - state = SCE_HPHP_OPERATOR; - } else { - state = SCE_HPHP_DEFAULT; - } - } - break; - case SCE_HPHP_NUMBER: - // recognize bases 8,10 or 16 integers OR floating-point numbers - if (!IsADigit(ch) - && strchr(".xXabcdefABCDEF", ch) == NULL - && ((ch != '-' && ch != '+') || (chPrev != 'e' && chPrev != 'E'))) { - styler.ColourTo(i - 1, SCE_HPHP_NUMBER); - if (IsOperator(ch)) - state = SCE_HPHP_OPERATOR; - else - state = SCE_HPHP_DEFAULT; - } - break; - case SCE_HPHP_VARIABLE: - if (!IsPhpWordChar(chNext)) { - styler.ColourTo(i, SCE_HPHP_VARIABLE); - state = SCE_HPHP_DEFAULT; - } - break; - case SCE_HPHP_COMMENT: - if (ch == '/' && chPrev == '*') { - styler.ColourTo(i, StateToPrint); - state = SCE_HPHP_DEFAULT; - } - break; - case SCE_HPHP_COMMENTLINE: - if (ch == '\r' || ch == '\n') { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HPHP_DEFAULT; - } - break; - case SCE_HPHP_HSTRING: - if (ch == '\\' && (phpStringDelimiter[0] == '\"' || chNext == '$' || chNext == '{')) { - // skip the next char - i++; - } else if (((ch == '{' && chNext == '$') || (ch == '$' && chNext == '{')) - && IsPhpWordStart(chNext2)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HPHP_COMPLEX_VARIABLE; - } else if (ch == '$' && IsPhpWordStart(chNext)) { - styler.ColourTo(i - 1, StateToPrint); - state = SCE_HPHP_HSTRING_VARIABLE; - } else if (styler.Match(i, phpStringDelimiter)) { - if (phpStringDelimiter[0] == '\"') { - styler.ColourTo(i, StateToPrint); - state = SCE_HPHP_DEFAULT; - } else if (isLineEnd(chPrev)) { - const int psdLength = strlen(phpStringDelimiter); - const char chAfterPsd = styler.SafeGetCharAt(i + psdLength); - const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1); - if (isLineEnd(chAfterPsd) || - (chAfterPsd == ';' && isLineEnd(chAfterPsd2))) { - i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1; - styler.ColourTo(i, StateToPrint); - state = SCE_HPHP_DEFAULT; - if (foldHeredoc) levelCurrent--; - } - } - } - break; - case SCE_HPHP_SIMPLESTRING: - if (phpStringDelimiter[0] == '\'') { - if (ch == '\\') { - // skip the next char - i++; - } else if (ch == '\'') { - styler.ColourTo(i, StateToPrint); - state = SCE_HPHP_DEFAULT; - } - } else if (isLineEnd(chPrev) && styler.Match(i, phpStringDelimiter)) { - const int psdLength = strlen(phpStringDelimiter); - const char chAfterPsd = styler.SafeGetCharAt(i + psdLength); - const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1); - if (isLineEnd(chAfterPsd) || - (chAfterPsd == ';' && isLineEnd(chAfterPsd2))) { - i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1; - styler.ColourTo(i, StateToPrint); - state = SCE_HPHP_DEFAULT; - if (foldHeredoc) levelCurrent--; - } - } - break; - case SCE_HPHP_HSTRING_VARIABLE: - if (!IsPhpWordChar(chNext)) { - styler.ColourTo(i, StateToPrint); - state = SCE_HPHP_HSTRING; - } - break; - case SCE_HPHP_COMPLEX_VARIABLE: - if (ch == '}') { - styler.ColourTo(i, StateToPrint); - state = SCE_HPHP_HSTRING; - } - break; - case SCE_HPHP_OPERATOR: - case SCE_HPHP_DEFAULT: - styler.ColourTo(i - 1, StateToPrint); - if (IsADigit(ch) || (ch == '.' && IsADigit(chNext))) { - state = SCE_HPHP_NUMBER; - } else if (IsAWordStart(ch)) { - state = SCE_HPHP_WORD; - } else if (ch == '/' && chNext == '*') { - i++; - state = SCE_HPHP_COMMENT; - } else if (ch == '/' && chNext == '/') { - i++; - state = SCE_HPHP_COMMENTLINE; - } else if (ch == '#') { - state = SCE_HPHP_COMMENTLINE; - } else if (ch == '\"') { - state = SCE_HPHP_HSTRING; - strcpy(phpStringDelimiter, "\""); - } else if (styler.Match(i, "<<<")) { - bool isSimpleString = false; - i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString); - if (strlen(phpStringDelimiter)) { - state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING); - if (foldHeredoc) levelCurrent++; - } - } else if (ch == '\'') { - state = SCE_HPHP_SIMPLESTRING; - strcpy(phpStringDelimiter, "\'"); - } else if (ch == '$' && IsPhpWordStart(chNext)) { - state = SCE_HPHP_VARIABLE; - } else if (IsOperator(ch)) { - state = SCE_HPHP_OPERATOR; - } else if ((state == SCE_HPHP_OPERATOR) && (IsASpace(ch))) { - state = SCE_HPHP_DEFAULT; - } - break; - ///////////// end - PHP state handling - } - - // Some of the above terminated their lexeme but since the same character starts - // the same class again, only reenter if non empty segment. - - bool nonEmptySegment = i >= static_cast(styler.GetStartSegment()); - if (state == SCE_HB_DEFAULT) { // One of the above succeeded - if ((ch == '\"') && (nonEmptySegment)) { - state = SCE_HB_STRING; - } else if (ch == '\'') { - state = SCE_HB_COMMENTLINE; - } else if (IsAWordStart(ch)) { - state = SCE_HB_WORD; - } else if (IsOperator(ch)) { - styler.ColourTo(i, SCE_HB_DEFAULT); - } - } else if (state == SCE_HBA_DEFAULT) { // One of the above succeeded - if ((ch == '\"') && (nonEmptySegment)) { - state = SCE_HBA_STRING; - } else if (ch == '\'') { - state = SCE_HBA_COMMENTLINE; - } else if (IsAWordStart(ch)) { - state = SCE_HBA_WORD; - } else if (IsOperator(ch)) { - styler.ColourTo(i, SCE_HBA_DEFAULT); - } - } else if (state == SCE_HJ_DEFAULT) { // One of the above succeeded - if (ch == '/' && chNext == '*') { - if (styler.SafeGetCharAt(i + 2) == '*') - state = SCE_HJ_COMMENTDOC; - else - state = SCE_HJ_COMMENT; - } else if (ch == '/' && chNext == '/') { - state = SCE_HJ_COMMENTLINE; - } else if ((ch == '\"') && (nonEmptySegment)) { - state = SCE_HJ_DOUBLESTRING; - } else if ((ch == '\'') && (nonEmptySegment)) { - state = SCE_HJ_SINGLESTRING; - } else if (IsAWordStart(ch)) { - state = SCE_HJ_WORD; - } else if (IsOperator(ch)) { - styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); - } - } - } - - switch (state) { - case SCE_HJ_WORD: - classifyWordHTJS(styler.GetStartSegment(), lengthDoc - 1, keywords2, styler, inScriptType); - break; - case SCE_HB_WORD: - classifyWordHTVB(styler.GetStartSegment(), lengthDoc - 1, keywords3, styler, inScriptType); - break; - case SCE_HP_WORD: - classifyWordHTPy(styler.GetStartSegment(), lengthDoc - 1, keywords4, styler, prevWord, inScriptType); - break; - case SCE_HPHP_WORD: - classifyWordHTPHP(styler.GetStartSegment(), lengthDoc - 1, keywords5, styler); - break; - default: - StateToPrint = statePrintForState(state, inScriptType); - styler.ColourTo(lengthDoc - 1, StateToPrint); - break; - } - - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - if (fold) { - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); - } -} - -static void ColouriseXMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - // Passing in true because we're lexing XML - ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, true); -} - -static void ColouriseHTMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - // Passing in false because we're notlexing XML - ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, false); -} - -static void ColourisePHPScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - if (startPos == 0) - initStyle = SCE_HPHP_DEFAULT; - ColouriseHTMLDoc(startPos, length, initStyle, keywordlists, styler); -} - -static const char * const htmlWordListDesc[] = { - "HTML elements and attributes", - "JavaScript keywords", - "VBScript keywords", - "Python keywords", - "PHP keywords", - "SGML and DTD keywords", - 0, -}; - -static const char * const phpscriptWordListDesc[] = { - "", //Unused - "", //Unused - "", //Unused - "", //Unused - "PHP keywords", - "", //Unused - 0, -}; - -LexerModule lmHTML(SCLEX_HTML, ColouriseHTMLDoc, "hypertext", 0, htmlWordListDesc, 8); -LexerModule lmXML(SCLEX_XML, ColouriseXMLDoc, "xml", 0, htmlWordListDesc, 8); -LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc, 8); diff --git a/src/LexHaskell.cxx b/src/LexHaskell.cxx deleted file mode 100644 index b528f3f0e..000000000 --- a/src/LexHaskell.cxx +++ /dev/null @@ -1,275 +0,0 @@ -/****************************************************************** - * LexHaskell.cxx - * - * A haskell lexer for the scintilla code control. - * Some stuff "lended" from LexPython.cxx and LexCPP.cxx. - * External lexer stuff inspired from the caml external lexer. - * - * Written by Tobias Engvall - tumm at dtek dot chalmers dot se - * - * - * TODO: - * * Implement a folder :) - * * Nice Character-lexing (stuff inside '\''), LexPython has - * this. - * - * - *****************************************************************/ - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "PropSetSimple.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#ifdef BUILD_AS_EXTERNAL_LEXER - -#include "ExternalLexer.h" -#include "WindowAccessor.h" - -#define BUILD_EXTERNAL_LEXER 0 - -#endif - -// Max level of nested comments -#define SCE_HA_COMMENTMAX SCE_HA_COMMENTBLOCK3 - - -enum kwType { kwOther, kwClass, kwData, kwInstance, kwImport, kwModule, kwType}; - -static inline bool IsNewline(const int ch) { - return (ch == '\n' || ch == '\r'); -} - -static inline bool IsWhitespace(const int ch) { - return ( ch == ' ' - || ch == '\t' - || IsNewline(ch) ); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''); -} - -static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - - int kwLast = kwOther; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - // Check for state end - // Operator - if (sc.state == SCE_HA_OPERATOR) { - kwLast = kwOther; - sc.SetState(SCE_HA_DEFAULT); - } - // String - else if (sc.state == SCE_HA_STRING) { - if (sc.ch == '\"') { - sc.ForwardSetState(SCE_HA_DEFAULT); - } else if (sc.ch == '\\') { - sc.Forward(); - } - } - // Char - else if (sc.state == SCE_HA_CHARACTER) { - if (sc.ch == '\'') { - sc.ForwardSetState(SCE_HA_DEFAULT); - } else if (sc.ch == '\\') { - sc.Forward(); - } - } - // Number - else if (sc.state == SCE_HA_NUMBER) { - if (!IsADigit(sc.ch)) { - sc.SetState(SCE_HA_DEFAULT); - } - } - // Types, constructors, etc. - else if (sc.state == SCE_HA_CAPITAL) { - if (!IsAWordChar(sc.ch) || sc.ch == '.') { - sc.SetState(SCE_HA_DEFAULT); - } - } - // Identifier - else if (sc.state == SCE_HA_IDENTIFIER) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - int style = SCE_HA_IDENTIFIER; - if ((kwLast == kwImport) || (strcmp(s,"qualified") == 0) || (strcmp(s,"as") == 0)) { - style = SCE_HA_IMPORT; - } else if (keywords.InList(s)) { - style = SCE_HA_KEYWORD; - } else if (kwLast == kwData) { - style = SCE_HA_DATA; - } else if (kwLast == kwClass) { - style = SCE_HA_CLASS; - } else if (kwLast == kwModule) { - style = SCE_HA_MODULE; - } else if (isupper(s[0])) { - style = SCE_HA_CAPITAL; - } - sc.ChangeState(style); - sc.SetState(SCE_HA_DEFAULT); - if (style == SCE_HA_KEYWORD) { - if (0 == strcmp(s, "class")) - kwLast = kwClass; - else if (0 == strcmp(s, "data")) - kwLast = kwData; - else if (0 == strcmp(s, "instance")) - kwLast = kwInstance; - else if (0 == strcmp(s, "import")) - kwLast = kwImport; - else if (0 == strcmp(s, "module")) - kwLast = kwModule; - else - kwLast = kwOther; - } else if (style == SCE_HA_CLASS || style == SCE_HA_IMPORT || - style == SCE_HA_MODULE || style == SCE_HA_CAPITAL || - style == SCE_HA_DATA || style == SCE_HA_INSTANCE) { - kwLast = kwOther; - } - } - } - // Comments - // Oneliner - else if (sc.state == SCE_HA_COMMENTLINE) { - if (IsNewline(sc.ch)) - sc.SetState(SCE_HA_DEFAULT); - } - // Nested - else if (sc.state >= SCE_HA_COMMENTBLOCK) { - if (sc.Match("{-")) { - if (sc.state < SCE_HA_COMMENTMAX) - sc.SetState(sc.state + 1); - } - else if (sc.Match("-}")) { - sc.Forward(); - if (sc.state == SCE_HA_COMMENTBLOCK) - sc.ForwardSetState(SCE_HA_DEFAULT); - else - sc.ForwardSetState(sc.state - 1); - } - } - // New state? - if (sc.state == SCE_HA_DEFAULT) { - // Digit - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_HA_NUMBER); - if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) { // Match anything starting with "0x" or "0X", too - sc.Forward(1); - } - } - // Comment line - else if (sc.Match("--")) { - sc.SetState(SCE_HA_COMMENTLINE); - // Comment block - } - else if (sc.Match("{-")) { - sc.SetState(SCE_HA_COMMENTBLOCK); - } - // String - else if (sc.Match('\"')) { - sc.SetState(SCE_HA_STRING); - } - // Character - else if (sc.Match('\'')) { - sc.SetState(SCE_HA_CHARACTER); - } - // Stringstart - else if (sc.Match('\"')) { - sc.SetState(SCE_HA_STRING); - } - // Operator - else if (isascii(sc.ch) && isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_HA_OPERATOR); - } - // Keyword - else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_HA_IDENTIFIER); - } - - } - } - sc.Complete(); -} - -// External stuff - used for dynamic-loading, not implemented in wxStyledTextCtrl yet. -// Inspired by the caml external lexer - Credits to Robert Roessler - http://www.rftp.com -#ifdef BUILD_EXTERNAL_LEXER -static const char* LexerName = "haskell"; - -void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, int initStyle, - char *words[], WindowID window, char *props) -{ - PropSetSimple ps; - ps.SetMultiple(props); - WindowAccessor wa(window, ps); - - int nWL = 0; - for (; words[nWL]; nWL++) ; - WordList** wl = new WordList* [nWL + 1]; - int i = 0; - for (; iSet(words[i]); - } - wl[i] = 0; - - ColorizeHaskellDoc(startPos, length, initStyle, wl, wa); - wa.Flush(); - for (i=nWL-1;i>=0;i--) - delete wl[i]; - delete [] wl; -} - -void EXT_LEXER_DECL Fold (unsigned int lexer, unsigned int startPos, int length, int initStyle, - char *words[], WindowID window, char *props) -{ - -} - -int EXT_LEXER_DECL GetLexerCount() -{ - return 1; -} - -void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength) -{ - if (buflength > 0) { - buflength--; - int n = strlen(LexerName); - if (n > buflength) - n = buflength; - memcpy(name, LexerName, n), name[n] = '\0'; - } -} -#endif - -LexerModule lmHaskell(SCLEX_HASKELL, ColorizeHaskellDoc, "haskell"); - diff --git a/src/LexInno.cxx b/src/LexInno.cxx deleted file mode 100644 index 6d1102c65..000000000 --- a/src/LexInno.cxx +++ /dev/null @@ -1,279 +0,0 @@ -// Scintilla source code edit control -/** @file LexInno.cxx - ** Lexer for Inno Setup scripts. - **/ -// Written by Friedrich Vedder , using code from LexOthers.cxx. -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "CharClassify.h" -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) { - int state = SCE_INNO_DEFAULT; - char chPrev; - char ch = 0; - char chNext = styler[startPos]; - int lengthDoc = startPos + length; - char *buffer = new char[length]; - int bufferCount = 0; - bool isBOL, isEOL, isWS, isBOLWS = 0; - bool isCode = false; - bool isCStyleComment = false; - - WordList §ionKeywords = *keywordLists[0]; - WordList &standardKeywords = *keywordLists[1]; - WordList ¶meterKeywords = *keywordLists[2]; - WordList &preprocessorKeywords = *keywordLists[3]; - WordList &pascalKeywords = *keywordLists[4]; - WordList &userKeywords = *keywordLists[5]; - - // Go through all provided text segment - // using the hand-written state machine shown below - styler.StartAt(startPos); - styler.StartSegment(startPos); - for (int i = startPos; i < lengthDoc; i++) { - chPrev = ch; - ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - i++; - continue; - } - - isBOL = (chPrev == 0) || (chPrev == '\n') || (chPrev == '\r' && ch != '\n'); - isBOLWS = (isBOL) ? 1 : (isBOLWS && (chPrev == ' ' || chPrev == '\t')); - isEOL = (ch == '\n' || ch == '\r'); - isWS = (ch == ' ' || ch == '\t'); - - switch(state) { - case SCE_INNO_DEFAULT: - if (!isCode && ch == ';' && isBOLWS) { - // Start of a comment - state = SCE_INNO_COMMENT; - } else if (ch == '[' && isBOLWS) { - // Start of a section name - bufferCount = 0; - state = SCE_INNO_SECTION; - } else if (ch == '#' && isBOLWS) { - // Start of a preprocessor directive - state = SCE_INNO_PREPROC; - } else if (!isCode && ch == '{' && chNext != '{' && chPrev != '{') { - // Start of an inline expansion - state = SCE_INNO_INLINE_EXPANSION; - } else if (isCode && (ch == '{' || (ch == '(' && chNext == '*'))) { - // Start of a Pascal comment - state = SCE_INNO_COMMENT_PASCAL; - isCStyleComment = false; - } else if (isCode && ch == '/' && chNext == '/') { - // Apparently, C-style comments are legal, too - state = SCE_INNO_COMMENT_PASCAL; - isCStyleComment = true; - } else if (ch == '"') { - // Start of a double-quote string - state = SCE_INNO_STRING_DOUBLE; - } else if (ch == '\'') { - // Start of a single-quote string - state = SCE_INNO_STRING_SINGLE; - } else if (isascii(ch) && (isalpha(ch) || (ch == '_'))) { - // Start of an identifier - bufferCount = 0; - buffer[bufferCount++] = static_cast(tolower(ch)); - state = SCE_INNO_IDENTIFIER; - } else { - // Style it the default style - styler.ColourTo(i,SCE_INNO_DEFAULT); - } - break; - - case SCE_INNO_COMMENT: - if (isEOL) { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_COMMENT); - } - break; - - case SCE_INNO_IDENTIFIER: - if (isascii(ch) && (isalnum(ch) || (ch == '_'))) { - buffer[bufferCount++] = static_cast(tolower(ch)); - } else { - state = SCE_INNO_DEFAULT; - buffer[bufferCount] = '\0'; - - // Check if the buffer contains a keyword - if (!isCode && standardKeywords.InList(buffer)) { - styler.ColourTo(i-1,SCE_INNO_KEYWORD); - } else if (!isCode && parameterKeywords.InList(buffer)) { - styler.ColourTo(i-1,SCE_INNO_PARAMETER); - } else if (isCode && pascalKeywords.InList(buffer)) { - styler.ColourTo(i-1,SCE_INNO_KEYWORD_PASCAL); - } else if (!isCode && userKeywords.InList(buffer)) { - styler.ColourTo(i-1,SCE_INNO_KEYWORD_USER); - } else { - styler.ColourTo(i-1,SCE_INNO_DEFAULT); - } - - // Push back the faulty character - chNext = styler[i--]; - ch = chPrev; - } - break; - - case SCE_INNO_SECTION: - if (ch == ']') { - state = SCE_INNO_DEFAULT; - buffer[bufferCount] = '\0'; - - // Check if the buffer contains a section name - if (sectionKeywords.InList(buffer)) { - styler.ColourTo(i,SCE_INNO_SECTION); - isCode = !CompareCaseInsensitive(buffer, "code"); - } else { - styler.ColourTo(i,SCE_INNO_DEFAULT); - } - } else if (isascii(ch) && (isalnum(ch) || (ch == '_'))) { - buffer[bufferCount++] = static_cast(tolower(ch)); - } else { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_DEFAULT); - } - break; - - case SCE_INNO_PREPROC: - if (isWS || isEOL) { - if (isascii(chPrev) && isalpha(chPrev)) { - state = SCE_INNO_DEFAULT; - buffer[bufferCount] = '\0'; - - // Check if the buffer contains a preprocessor directive - if (preprocessorKeywords.InList(buffer)) { - styler.ColourTo(i-1,SCE_INNO_PREPROC); - } else { - styler.ColourTo(i-1,SCE_INNO_DEFAULT); - } - - // Push back the faulty character - chNext = styler[i--]; - ch = chPrev; - } - } else if (isascii(ch) && isalpha(ch)) { - if (chPrev == '#' || chPrev == ' ' || chPrev == '\t') - bufferCount = 0; - buffer[bufferCount++] = static_cast(tolower(ch)); - } - break; - - case SCE_INNO_STRING_DOUBLE: - if (ch == '"' || isEOL) { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_STRING_DOUBLE); - } - break; - - case SCE_INNO_STRING_SINGLE: - if (ch == '\'' || isEOL) { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_STRING_SINGLE); - } - break; - - case SCE_INNO_INLINE_EXPANSION: - if (ch == '}') { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_INLINE_EXPANSION); - } else if (isEOL) { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_DEFAULT); - } - break; - - case SCE_INNO_COMMENT_PASCAL: - if (isCStyleComment) { - if (isEOL) { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL); - } - } else { - if (ch == '}' || (ch == ')' && chPrev == '*')) { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL); - } else if (isEOL) { - state = SCE_INNO_DEFAULT; - styler.ColourTo(i,SCE_INNO_DEFAULT); - } - } - break; - - } - } - delete []buffer; -} - -static const char * const innoWordListDesc[] = { - "Sections", - "Keywords", - "Parameters", - "Preprocessor directives", - "Pascal keywords", - "User defined keywords", - 0 -}; - -static void FoldInnoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - unsigned int endPos = startPos + length; - char chNext = styler[startPos]; - - int lineCurrent = styler.GetLine(startPos); - - bool sectionFlag = false; - int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) : SC_FOLDLEVELBASE; - int level; - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler[i+1]; - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - int style = styler.StyleAt(i); - - if (style == SCE_INNO_SECTION) - sectionFlag = true; - - if (atEOL || i == endPos - 1) { - if (sectionFlag) { - level = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; - if (level == levelPrev) - styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG); - } else { - level = levelPrev & SC_FOLDLEVELNUMBERMASK; - if (levelPrev & SC_FOLDLEVELHEADERFLAG) - level++; - } - - styler.SetLevel(lineCurrent, level); - - levelPrev = level; - lineCurrent++; - sectionFlag = false; - } - } -} - -LexerModule lmInno(SCLEX_INNOSETUP, ColouriseInnoDoc, "inno", FoldInnoDoc, innoWordListDesc); diff --git a/src/LexKix.cxx b/src/LexKix.cxx deleted file mode 100644 index 06e7c1791..000000000 --- a/src/LexKix.cxx +++ /dev/null @@ -1,126 +0,0 @@ -// Scintilla source code edit control -/** @file LexKix.cxx - ** Lexer for KIX-Scripts. - **/ -// Copyright 2004 by Manfred Becker -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// Extended to accept accented characters -static inline bool IsAWordChar(int ch) { - return ch >= 0x80 || isalnum(ch) || ch == '_'; -} - -static inline bool IsOperator(const int ch) { - return (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '&' || ch == '|' || ch == '<' || ch == '>' || ch == '='); -} - -static void ColouriseKixDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; -// WordList &keywords4 = *keywordlists[3]; - - styler.StartAt(startPos); - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.state == SCE_KIX_COMMENT) { - if (sc.atLineEnd) { - sc.SetState(SCE_KIX_DEFAULT); - } - } else if (sc.state == SCE_KIX_STRING1) { - // This is a doubles quotes string - if (sc.ch == '\"') { - sc.ForwardSetState(SCE_KIX_DEFAULT); - } - } else if (sc.state == SCE_KIX_STRING2) { - // This is a single quote string - if (sc.ch == '\'') { - sc.ForwardSetState(SCE_KIX_DEFAULT); - } - } else if (sc.state == SCE_KIX_NUMBER) { - if (!IsADigit(sc.ch)) { - sc.SetState(SCE_KIX_DEFAULT); - } - } else if (sc.state == SCE_KIX_VAR) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_KIX_DEFAULT); - } - } else if (sc.state == SCE_KIX_MACRO) { - if (!IsAWordChar(sc.ch) && !IsADigit(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - - if (!keywords3.InList(&s[1])) { - sc.ChangeState(SCE_KIX_DEFAULT); - } - sc.SetState(SCE_KIX_DEFAULT); - } - } else if (sc.state == SCE_KIX_OPERATOR) { - if (!IsOperator(sc.ch)) { - sc.SetState(SCE_KIX_DEFAULT); - } - } else if (sc.state == SCE_KIX_IDENTIFIER) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - - if (keywords.InList(s)) { - sc.ChangeState(SCE_KIX_KEYWORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_KIX_FUNCTIONS); - } - sc.SetState(SCE_KIX_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_KIX_DEFAULT) { - if (sc.ch == ';') { - sc.SetState(SCE_KIX_COMMENT); - } else if (sc.ch == '\"') { - sc.SetState(SCE_KIX_STRING1); - } else if (sc.ch == '\'') { - sc.SetState(SCE_KIX_STRING2); - } else if (sc.ch == '$') { - sc.SetState(SCE_KIX_VAR); - } else if (sc.ch == '@') { - sc.SetState(SCE_KIX_MACRO); - } else if (IsADigit(sc.ch) || ((sc.ch == '.' || sc.ch == '&') && IsADigit(sc.chNext))) { - sc.SetState(SCE_KIX_NUMBER); - } else if (IsOperator(sc.ch)) { - sc.SetState(SCE_KIX_OPERATOR); - } else if (IsAWordChar(sc.ch)) { - sc.SetState(SCE_KIX_IDENTIFIER); - } - } - } - sc.Complete(); -} - - -LexerModule lmKix(SCLEX_KIX, ColouriseKixDoc, "kix"); - diff --git a/src/LexLisp.cxx b/src/LexLisp.cxx deleted file mode 100644 index ad5535f14..000000000 --- a/src/LexLisp.cxx +++ /dev/null @@ -1,282 +0,0 @@ -// Scintilla source code edit control -/** @file LexLisp.cxx - ** Lexer for Lisp. - ** Written by Alexey Yutkin. - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "StyleContext.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#define SCE_LISP_CHARACTER 29 -#define SCE_LISP_MACRO 30 -#define SCE_LISP_MACRO_DISPATCH 31 - -static inline bool isLispoperator(char ch) { - if (isascii(ch) && isalnum(ch)) - return false; - if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}') - return true; - return false; -} - -static inline bool isLispwordstart(char ch) { - return isascii(ch) && ch != ';' && !isspacechar(ch) && !isLispoperator(ch) && - ch != '\n' && ch != '\r' && ch != '\"'; -} - - -static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, WordList &keywords_kw, Accessor &styler) { - PLATFORM_ASSERT(end >= start); - char s[100]; - unsigned int i; - bool digit_flag = true; - for (i = 0; (i < end - start + 1) && (i < 99); i++) { - s[i] = styler[start + i]; - s[i + 1] = '\0'; - if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false; - } - char chAttr = SCE_LISP_IDENTIFIER; - - if(digit_flag) chAttr = SCE_LISP_NUMBER; - else { - if (keywords.InList(s)) { - chAttr = SCE_LISP_KEYWORD; - } else if (keywords_kw.InList(s)) { - chAttr = SCE_LISP_KEYWORD_KW; - } else if ((s[0] == '*' && s[i-1] == '*') || - (s[0] == '+' && s[i-1] == '+')) { - chAttr = SCE_LISP_SPECIAL; - } - } - styler.ColourTo(end, chAttr); - return; -} - - -static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords_kw = *keywordlists[1]; - - styler.StartAt(startPos); - - int state = initStyle, radix = -1; - char chNext = styler[startPos]; - unsigned int lengthDoc = startPos + length; - styler.StartSegment(startPos); - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - i += 1; - continue; - } - - if (state == SCE_LISP_DEFAULT) { - if (ch == '#') { - styler.ColourTo(i - 1, state); - radix = -1; - state = SCE_LISP_MACRO_DISPATCH; - } else if (ch == ':' && isLispwordstart(chNext)) { - styler.ColourTo(i - 1, state); - state = SCE_LISP_SYMBOL; - } else if (isLispwordstart(ch)) { - styler.ColourTo(i - 1, state); - state = SCE_LISP_IDENTIFIER; - } - else if (ch == ';') { - styler.ColourTo(i - 1, state); - state = SCE_LISP_COMMENT; - } - else if (isLispoperator(ch) || ch=='\'') { - styler.ColourTo(i - 1, state); - styler.ColourTo(i, SCE_LISP_OPERATOR); - if (ch=='\'' && isLispwordstart(chNext)) { - state = SCE_LISP_SYMBOL; - } - } - else if (ch == '\"') { - styler.ColourTo(i - 1, state); - state = SCE_LISP_STRING; - } - } else if (state == SCE_LISP_IDENTIFIER || state == SCE_LISP_SYMBOL) { - if (!isLispwordstart(ch)) { - if (state == SCE_LISP_IDENTIFIER) { - classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler); - } else { - styler.ColourTo(i - 1, state); - } - state = SCE_LISP_DEFAULT; - } /*else*/ - if (isLispoperator(ch) || ch=='\'') { - styler.ColourTo(i - 1, state); - styler.ColourTo(i, SCE_LISP_OPERATOR); - if (ch=='\'' && isLispwordstart(chNext)) { - state = SCE_LISP_SYMBOL; - } - } - } else if (state == SCE_LISP_MACRO_DISPATCH) { - if (!(isascii(ch) && isdigit(ch))) { - if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) { - state = SCE_LISP_DEFAULT; - } else { - switch (ch) { - case '|': state = SCE_LISP_MULTI_COMMENT; break; - case 'o': - case 'O': radix = 8; state = SCE_LISP_MACRO; break; - case 'x': - case 'X': radix = 16; state = SCE_LISP_MACRO; break; - case 'b': - case 'B': radix = 2; state = SCE_LISP_MACRO; break; - case '\\': state = SCE_LISP_CHARACTER; break; - case ':': - case '-': - case '+': state = SCE_LISP_MACRO; break; - case '\'': if (isLispwordstart(chNext)) { - state = SCE_LISP_SPECIAL; - } else { - styler.ColourTo(i - 1, SCE_LISP_DEFAULT); - styler.ColourTo(i, SCE_LISP_OPERATOR); - state = SCE_LISP_DEFAULT; - } - break; - default: if (isLispoperator(ch)) { - styler.ColourTo(i - 1, SCE_LISP_DEFAULT); - styler.ColourTo(i, SCE_LISP_OPERATOR); - } - state = SCE_LISP_DEFAULT; - break; - } - } - } - } else if (state == SCE_LISP_MACRO) { - if (isLispwordstart(ch) && (radix == -1 || IsADigit(ch, radix))) { - state = SCE_LISP_SPECIAL; - } else { - state = SCE_LISP_DEFAULT; - } - } else if (state == SCE_LISP_CHARACTER) { - if (isLispoperator(ch)) { - styler.ColourTo(i, SCE_LISP_SPECIAL); - state = SCE_LISP_DEFAULT; - } else if (isLispwordstart(ch)) { - styler.ColourTo(i, SCE_LISP_SPECIAL); - state = SCE_LISP_SPECIAL; - } else { - state = SCE_LISP_DEFAULT; - } - } else if (state == SCE_LISP_SPECIAL) { - if (!isLispwordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) { - styler.ColourTo(i - 1, state); - state = SCE_LISP_DEFAULT; - } - if (isLispoperator(ch) || ch=='\'') { - styler.ColourTo(i - 1, state); - styler.ColourTo(i, SCE_LISP_OPERATOR); - if (ch=='\'' && isLispwordstart(chNext)) { - state = SCE_LISP_SYMBOL; - } - } - } else { - if (state == SCE_LISP_COMMENT) { - if (atEOL) { - styler.ColourTo(i - 1, state); - state = SCE_LISP_DEFAULT; - } - } else if (state == SCE_LISP_MULTI_COMMENT) { - if (ch == '|' && chNext == '#') { - i++; - chNext = styler.SafeGetCharAt(i + 1); - styler.ColourTo(i, state); - state = SCE_LISP_DEFAULT; - } - } else if (state == SCE_LISP_STRING) { - if (ch == '\\') { - if (chNext == '\"' || chNext == '\'' || chNext == '\\') { - i++; - chNext = styler.SafeGetCharAt(i + 1); - } - } else if (ch == '\"') { - styler.ColourTo(i, state); - state = SCE_LISP_DEFAULT; - } - } - } - - } - styler.ColourTo(lengthDoc - 1, state); -} - -static void FoldLispDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[], - Accessor &styler) { - unsigned int lengthDoc = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (style == SCE_LISP_OPERATOR) { - if (ch == '(' || ch == '[' || ch == '{') { - levelCurrent++; - } else if (ch == ')' || ch == ']' || ch == '}') { - levelCurrent--; - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const lispWordListDesc[] = { - "Functions and special operators", - "Keywords", - 0 -}; - -LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc); diff --git a/src/LexLout.cxx b/src/LexLout.cxx deleted file mode 100644 index 492e4ed6d..000000000 --- a/src/LexLout.cxx +++ /dev/null @@ -1,212 +0,0 @@ -// Scintilla source code edit control -/** @file LexLout.cxx - ** Lexer for the Basser Lout (>= version 3) typesetting language - **/ -// Copyright 2003 by Kein-Hong Man -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalpha(ch) || ch == '@' || ch == '_'); -} - -static inline bool IsAnOther(const int ch) { - return (ch < 0x80) && (ch == '{' || ch == '}' || - ch == '!' || ch == '$' || ch == '%' || ch == '&' || ch == '\'' || - ch == '(' || ch == ')' || ch == '*' || ch == '+' || ch == ',' || - ch == '-' || ch == '.' || ch == '/' || ch == ':' || ch == ';' || - ch == '<' || ch == '=' || ch == '>' || ch == '?' || ch == '[' || - ch == ']' || ch == '^' || ch == '`' || ch == '|' || ch == '~'); -} - -static void ColouriseLoutDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - - int visibleChars = 0; - int firstWordInLine = 0; - int leadingAtSign = 0; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.atLineStart && (sc.state == SCE_LOUT_STRING)) { - // Prevent SCE_LOUT_STRINGEOL from leaking back to previous line - sc.SetState(SCE_LOUT_STRING); - } - - // Determine if the current state should terminate. - if (sc.state == SCE_LOUT_COMMENT) { - if (sc.atLineEnd) { - sc.SetState(SCE_LOUT_DEFAULT); - visibleChars = 0; - } - } else if (sc.state == SCE_LOUT_NUMBER) { - if (!IsADigit(sc.ch) && sc.ch != '.') { - sc.SetState(SCE_LOUT_DEFAULT); - } - } else if (sc.state == SCE_LOUT_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_LOUT_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_LOUT_STRINGEOL); - sc.ForwardSetState(SCE_LOUT_DEFAULT); - visibleChars = 0; - } - } else if (sc.state == SCE_LOUT_IDENTIFIER) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - - if (leadingAtSign) { - if (keywords.InList(s)) { - sc.ChangeState(SCE_LOUT_WORD); - } else { - sc.ChangeState(SCE_LOUT_WORD4); - } - } else if (firstWordInLine && keywords3.InList(s)) { - sc.ChangeState(SCE_LOUT_WORD3); - } - sc.SetState(SCE_LOUT_DEFAULT); - } - } else if (sc.state == SCE_LOUT_OPERATOR) { - if (!IsAnOther(sc.ch)) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - - if (keywords2.InList(s)) { - sc.ChangeState(SCE_LOUT_WORD2); - } - sc.SetState(SCE_LOUT_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_LOUT_DEFAULT) { - if (sc.ch == '#') { - sc.SetState(SCE_LOUT_COMMENT); - } else if (sc.ch == '\"') { - sc.SetState(SCE_LOUT_STRING); - } else if (IsADigit(sc.ch) || - (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_LOUT_NUMBER); - } else if (IsAWordChar(sc.ch)) { - firstWordInLine = (visibleChars == 0); - leadingAtSign = (sc.ch == '@'); - sc.SetState(SCE_LOUT_IDENTIFIER); - } else if (IsAnOther(sc.ch)) { - sc.SetState(SCE_LOUT_OPERATOR); - } - } - - if (sc.atLineEnd) { - // Reset states to begining of colourise so no surprises - // if different sets of lines lexed. - visibleChars = 0; - } - if (!IsASpace(sc.ch)) { - visibleChars++; - } - } - sc.Complete(); -} - -static void FoldLoutDoc(unsigned int startPos, int length, int, WordList *[], - Accessor &styler) { - - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - int styleNext = styler.StyleAt(startPos); - char s[10]; - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - if (style == SCE_LOUT_WORD) { - if (ch == '@') { - for (unsigned int j = 0; j < 8; j++) { - if (!IsAWordChar(styler[i + j])) { - break; - } - s[j] = styler[i + j]; - s[j + 1] = '\0'; - } - if (strcmp(s, "@Begin") == 0) { - levelCurrent++; - } else if (strcmp(s, "@End") == 0) { - levelCurrent--; - } - } - } else if (style == SCE_LOUT_OPERATOR) { - if (ch == '{') { - levelCurrent++; - } else if (ch == '}') { - levelCurrent--; - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) { - lev |= SC_FOLDLEVELWHITEFLAG; - } - if ((levelCurrent > levelPrev) && (visibleChars > 0)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const loutWordLists[] = { - "Predefined identifiers", - "Predefined delimiters", - "Predefined keywords", - 0, - }; - -LexerModule lmLout(SCLEX_LOUT, ColouriseLoutDoc, "lout", FoldLoutDoc, loutWordLists); diff --git a/src/LexLua.cxx b/src/LexLua.cxx deleted file mode 100644 index a1e579f26..000000000 --- a/src/LexLua.cxx +++ /dev/null @@ -1,358 +0,0 @@ -// 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 "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "CharacterSet.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// 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( - unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - WordList &keywords6 = *keywordlists[5]; - WordList &keywords7 = *keywordlists[6]; - WordList &keywords8 = *keywordlists[7]; - - // Accepts accented characters - CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); - // Not exactly following number definition (several dots are seen as OK, etc.) - // but probably enough in most cases. - CharacterSet setNumber(CharacterSet::setDigits, ".-+abcdefABCDEF"); - CharacterSet setLuaOperator(CharacterSet::setNone, "*/-+()={}~[];<>,.^%:#"); - CharacterSet setEscapeSkip(CharacterSet::setNone, "\"'\\"); - - int currentLine = styler.GetLine(startPos); - // Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level, - // if we are inside such a string. Block comment was introduced in Lua 5.0, - // blocks with separators [=[ ... ]=] in Lua 5.1. - int nestLevel = 0; - int sepCount = 0; - if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT) { - int lineState = styler.GetLineState(currentLine - 1); - nestLevel = lineState >> 8; - sepCount = lineState & 0xFF; - } - - // 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 == '#') { - // shbang line: # is a comment only if first char 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: - // Inside a literal string or block comment, we set the line state - styler.SetLineState(currentLine, (nestLevel << 8) | 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) { - sc.SetState(SCE_LUA_DEFAULT); - } else if (sc.state == SCE_LUA_NUMBER) { - // We stop the number definition on non-numerical non-dot non-eE non-sign non-hexdigit char - if (!setNumber.Contains(sc.ch)) { - sc.SetState(SCE_LUA_DEFAULT); - } else if (sc.ch == '-' || sc.ch == '+') { - if (sc.chPrev != 'E' && sc.chPrev != 'e') - sc.SetState(SCE_LUA_DEFAULT); - } - } else if (sc.state == SCE_LUA_IDENTIFIER) { - if (!setWord.Contains(sc.ch) || sc.Match('.', '.')) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(SCE_LUA_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_LUA_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_LUA_WORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_LUA_WORD4); - } else if (keywords5.InList(s)) { - sc.ChangeState(SCE_LUA_WORD5); - } else if (keywords6.InList(s)) { - sc.ChangeState(SCE_LUA_WORD6); - } else if (keywords7.InList(s)) { - sc.ChangeState(SCE_LUA_WORD7); - } else if (keywords8.InList(s)) { - sc.ChangeState(SCE_LUA_WORD8); - } - sc.SetState(SCE_LUA_DEFAULT); - } - } else if (sc.state == SCE_LUA_COMMENTLINE || sc.state == SCE_LUA_PREPROCESSOR) { - if (sc.atLineEnd) { - sc.ForwardSetState(SCE_LUA_DEFAULT); - } - } else if (sc.state == SCE_LUA_STRING) { - if (sc.ch == '\\') { - if (setEscapeSkip.Contains(sc.chNext)) { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_LUA_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_LUA_STRINGEOL); - sc.ForwardSetState(SCE_LUA_DEFAULT); - } - } else if (sc.state == SCE_LUA_CHARACTER) { - if (sc.ch == '\\') { - if (setEscapeSkip.Contains(sc.chNext)) { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_LUA_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_LUA_STRINGEOL); - sc.ForwardSetState(SCE_LUA_DEFAULT); - } - } else if (sc.state == SCE_LUA_LITERALSTRING || sc.state == SCE_LUA_COMMENT) { - if (sc.ch == '[') { - int sep = LongDelimCheck(sc); - if (sep == 1 && sepCount == 1) { // [[-only allowed to nest - nestLevel++; - sc.Forward(); - } - } else if (sc.ch == ']') { - int sep = LongDelimCheck(sc); - if (sep == 1 && sepCount == 1) { // un-nest with ]]-only - nestLevel--; - sc.Forward(); - if (nestLevel == 0) { - sc.ForwardSetState(SCE_LUA_DEFAULT); - } - } else if (sep > 1 && sep == sepCount) { // ]=]-style delim - sc.Forward(sep); - sc.ForwardSetState(SCE_LUA_DEFAULT); - } - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_LUA_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_LUA_NUMBER); - if (sc.ch == '0' && toupper(sc.chNext) == 'X') { - sc.Forward(); - } - } else if (setWordStart.Contains(sc.ch)) { - sc.SetState(SCE_LUA_IDENTIFIER); - } else if (sc.ch == '\"') { - sc.SetState(SCE_LUA_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_LUA_CHARACTER); - } else if (sc.ch == '[') { - sepCount = LongDelimCheck(sc); - if (sepCount == 0) { - sc.SetState(SCE_LUA_OPERATOR); - } else { - nestLevel = 1; - sc.SetState(SCE_LUA_LITERALSTRING); - sc.Forward(sepCount); - } - } else if (sc.Match('-', '-')) { - sc.SetState(SCE_LUA_COMMENTLINE); - if (sc.Match("--[")) { - sc.Forward(2); - sepCount = LongDelimCheck(sc); - if (sepCount > 0) { - nestLevel = 1; - sc.ChangeState(SCE_LUA_COMMENT); - sc.Forward(sepCount); - } - } else { - sc.Forward(); - } - } else if (sc.atLineStart && sc.Match('$')) { - sc.SetState(SCE_LUA_PREPROCESSOR); // Obsolete since Lua 4.0, but still in old code - } else if (setLuaOperator.Contains(sc.ch)) { - sc.SetState(SCE_LUA_OPERATOR); - } - } - } - - if (setWord.Contains(sc.chPrev)) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(SCE_LUA_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_LUA_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_LUA_WORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_LUA_WORD4); - } else if (keywords5.InList(s)) { - sc.ChangeState(SCE_LUA_WORD5); - } else if (keywords6.InList(s)) { - sc.ChangeState(SCE_LUA_WORD6); - } else if (keywords7.InList(s)) { - sc.ChangeState(SCE_LUA_WORD7); - } else if (keywords8.InList(s)) { - sc.ChangeState(SCE_LUA_WORD8); - } - } - - sc.Complete(); -} - -static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[], - Accessor &styler) { - unsigned int lengthDoc = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - int styleNext = styler.StyleAt(startPos); - char s[10]; - - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (style == SCE_LUA_WORD) { - if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e' || ch == 'r' || ch == 'u') { - for (unsigned int j = 0; j < 8; j++) { - if (!iswordchar(styler[i + j])) { - break; - } - s[j] = styler[i + j]; - s[j + 1] = '\0'; - } - - if ((strcmp(s, "if") == 0) || (strcmp(s, "do") == 0) || (strcmp(s, "function") == 0) || (strcmp(s, "repeat") == 0)) { - levelCurrent++; - } - if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0) || (strcmp(s, "until") == 0)) { - levelCurrent--; - } - } - } else if (style == SCE_LUA_OPERATOR) { - if (ch == '{' || ch == '(') { - levelCurrent++; - } else if (ch == '}' || ch == ')') { - levelCurrent--; - } - } else if (style == SCE_LUA_LITERALSTRING || style == SCE_LUA_COMMENT) { - if (ch == '[') { - levelCurrent++; - } else if (ch == ']') { - levelCurrent--; - } - } - - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) { - lev |= SC_FOLDLEVELWHITEFLAG; - } - if ((levelCurrent > levelPrev) && (visibleChars > 0)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) { - visibleChars++; - } - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const luaWordListDesc[] = { - "Keywords", - "Basic functions", - "String, (table) & math functions", - "(coroutines), I/O & system facilities", - "user1", - "user2", - "user3", - "user4", - 0 -}; - -LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc, luaWordListDesc); diff --git a/src/LexMMIXAL.cxx b/src/LexMMIXAL.cxx deleted file mode 100644 index 369929998..000000000 --- a/src/LexMMIXAL.cxx +++ /dev/null @@ -1,186 +0,0 @@ -// Scintilla source code edit control -/** @file LexMMIXAL.cxx - ** Lexer for MMIX Assembler Language. - ** Written by Christoph Hösler - ** For information about MMIX visit http://www-cs-faculty.stanford.edu/~knuth/mmix.html - **/ -// Copyright 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == ':' || ch == '_'); -} - -inline bool isMMIXALOperator(char ch) { - if (isascii(ch) && isalnum(ch)) - return false; - if (ch == '+' || ch == '-' || ch == '|' || ch == '^' || - ch == '*' || ch == '/' || ch == '/' || - ch == '%' || ch == '<' || ch == '>' || ch == '&' || - ch == '~' || ch == '$' || - ch == ',' || ch == '(' || ch == ')' || - ch == '[' || ch == ']') - return true; - return false; -} - -static void ColouriseMMIXALDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &opcodes = *keywordlists[0]; - WordList &special_register = *keywordlists[1]; - WordList &predef_symbols = *keywordlists[2]; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) - { - // No EOL continuation - if (sc.atLineStart) { - if (sc.ch == '@' && sc.chNext == 'i') { - sc.SetState(SCE_MMIXAL_INCLUDE); - } else { - sc.SetState(SCE_MMIXAL_LEADWS); - } - } - - // Check if first non whitespace character in line is alphanumeric - if (sc.state == SCE_MMIXAL_LEADWS && !isspace(sc.ch)) { // LEADWS - if(!IsAWordChar(sc.ch)) { - sc.SetState(SCE_MMIXAL_COMMENT); - } else { - if(sc.atLineStart) { - sc.SetState(SCE_MMIXAL_LABEL); - } else { - sc.SetState(SCE_MMIXAL_OPCODE_PRE); - } - } - } - - // Determine if the current state should terminate. - if (sc.state == SCE_MMIXAL_OPERATOR) { // OPERATOR - sc.SetState(SCE_MMIXAL_OPERANDS); - } else if (sc.state == SCE_MMIXAL_NUMBER) { // NUMBER - if (!isdigit(sc.ch)) { - if (IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - sc.ChangeState(SCE_MMIXAL_REF); - sc.SetState(SCE_MMIXAL_REF); - } else { - sc.SetState(SCE_MMIXAL_OPERANDS); - } - } - } else if (sc.state == SCE_MMIXAL_LABEL) { // LABEL - if (!IsAWordChar(sc.ch) ) { - sc.SetState(SCE_MMIXAL_OPCODE_PRE); - } - } else if (sc.state == SCE_MMIXAL_REF) { // REF - if (!IsAWordChar(sc.ch) ) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if (*s == ':') { // ignore base prefix for match - for (size_t i = 0; i != sizeof(s); ++i) { - *(s+i) = *(s+i+1); - } - } - if (special_register.InList(s)) { - sc.ChangeState(SCE_MMIXAL_REGISTER); - } else if (predef_symbols.InList(s)) { - sc.ChangeState(SCE_MMIXAL_SYMBOL); - } - sc.SetState(SCE_MMIXAL_OPERANDS); - } - } else if (sc.state == SCE_MMIXAL_OPCODE_PRE) { // OPCODE_PRE - if (!isspace(sc.ch)) { - sc.SetState(SCE_MMIXAL_OPCODE); - } - } else if (sc.state == SCE_MMIXAL_OPCODE) { // OPCODE - if (!IsAWordChar(sc.ch) ) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if (opcodes.InList(s)) { - sc.ChangeState(SCE_MMIXAL_OPCODE_VALID); - } else { - sc.ChangeState(SCE_MMIXAL_OPCODE_UNKNOWN); - } - sc.SetState(SCE_MMIXAL_OPCODE_POST); - } - } else if (sc.state == SCE_MMIXAL_STRING) { // STRING - if (sc.ch == '\"') { - sc.ForwardSetState(SCE_MMIXAL_OPERANDS); - } else if (sc.atLineEnd) { - sc.ForwardSetState(SCE_MMIXAL_OPERANDS); - } - } else if (sc.state == SCE_MMIXAL_CHAR) { // CHAR - if (sc.ch == '\'') { - sc.ForwardSetState(SCE_MMIXAL_OPERANDS); - } else if (sc.atLineEnd) { - sc.ForwardSetState(SCE_MMIXAL_OPERANDS); - } - } else if (sc.state == SCE_MMIXAL_REGISTER) { // REGISTER - if (!isdigit(sc.ch)) { - sc.SetState(SCE_MMIXAL_OPERANDS); - } - } else if (sc.state == SCE_MMIXAL_HEX) { // HEX - if (!isxdigit(sc.ch)) { - sc.SetState(SCE_MMIXAL_OPERANDS); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_MMIXAL_OPCODE_POST || // OPCODE_POST - sc.state == SCE_MMIXAL_OPERANDS) { // OPERANDS - if (sc.state == SCE_MMIXAL_OPERANDS && isspace(sc.ch)) { - if (!sc.atLineEnd) { - sc.SetState(SCE_MMIXAL_COMMENT); - } - } else if (isdigit(sc.ch)) { - sc.SetState(SCE_MMIXAL_NUMBER); - } else if (IsAWordChar(sc.ch) || sc.Match('@')) { - sc.SetState(SCE_MMIXAL_REF); - } else if (sc.Match('\"')) { - sc.SetState(SCE_MMIXAL_STRING); - } else if (sc.Match('\'')) { - sc.SetState(SCE_MMIXAL_CHAR); - } else if (sc.Match('$')) { - sc.SetState(SCE_MMIXAL_REGISTER); - } else if (sc.Match('#')) { - sc.SetState(SCE_MMIXAL_HEX); - } else if (isMMIXALOperator(static_cast(sc.ch))) { - sc.SetState(SCE_MMIXAL_OPERATOR); - } - } - } - sc.Complete(); -} - -static const char * const MMIXALWordListDesc[] = { - "Operation Codes", - "Special Register", - "Predefined Symbols", - 0 -}; - -LexerModule lmMMIXAL(SCLEX_MMIXAL, ColouriseMMIXALDoc, "mmixal", 0, MMIXALWordListDesc); - diff --git a/src/LexMPT.cxx b/src/LexMPT.cxx deleted file mode 100644 index a69fe5464..000000000 --- a/src/LexMPT.cxx +++ /dev/null @@ -1,188 +0,0 @@ -// Scintilla source code edit control -/** @file LexMPT.cxx - ** Lexer for MPT specific files. Based on LexOthers.cxx - ** LOT = the text log file created by the MPT application while running a test program - ** Other MPT specific files to be added later. - **/ -// Copyright 2003 by Marius Gheorghe -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include - -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static int GetLotLineState(std::string &line) { - if (line.length()) { - // Most of the time the first non-blank character in line determines that line's type - // Now finds the first non-blank character - unsigned i; // Declares counter here to make it persistent after the for loop - for (i = 0; i < line.length(); ++i) { - if (!(isascii(line[i]) && isspace(line[i]))) - break; - } - - // Checks if it was a blank line - if (i == line.length()) - return SCE_LOT_DEFAULT; - - switch (line[i]) { - case '*': // Fail measurement - return SCE_LOT_FAIL; - - case '+': // Header - case '|': // Header - return SCE_LOT_HEADER; - - case ':': // Set test limits - return SCE_LOT_SET; - - case '-': // Section break - return SCE_LOT_BREAK; - - default: // Any other line - // Checks for message at the end of lot file - if (line.find("PASSED") != std::string::npos) { - return SCE_LOT_PASS; - } - else if (line.find("FAILED") != std::string::npos) { - return SCE_LOT_FAIL; - } - else if (line.find("ABORTED") != std::string::npos) { - return SCE_LOT_ABORT; - } - else { - return i ? SCE_LOT_PASS : SCE_LOT_DEFAULT; - } - } - } - else { - return SCE_LOT_DEFAULT; - } -} - -static void ColourizeLotDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - styler.StartAt(startPos); - styler.StartSegment(startPos); - bool atLineStart = true;// Arms the 'at line start' flag - char chNext = styler.SafeGetCharAt(startPos); - std::string line(""); - line.reserve(256); // Lot lines are less than 256 chars long most of the time. This should avoid reallocations - - // Styles LOT document - unsigned int i; // Declared here because it's used after the for loop - for (i = startPos; i < startPos + length; ++i) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - line += ch; - atLineStart = false; - - // LOT files are only used on the Win32 platform, thus EOL == CR+LF - // Searches for the end of line - if (ch == '\r' && chNext == '\n') { - line += chNext; // Gets the '\n' - ++i; // Advances past the '\n' - chNext = styler.SafeGetCharAt(i + 1); // Gets character of next line - styler.ColourTo(i, GetLotLineState(line)); - line = ""; - atLineStart = true; // Arms flag for next line - } - } - - // Last line may not have a line ending - if (!atLineStart) { - styler.ColourTo(i - 1, GetLotLineState(line)); - } -} - -// Folds an MPT LOT file: the blocks that can be folded are: -// sections (headed by a set line) -// passes (contiguous pass results within a section) -// fails (contiguous fail results within a section) -static void FoldLotDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - bool foldCompact = styler.GetPropertyInt("fold.compact", 0) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - - char chNext = styler.SafeGetCharAt(startPos); - int style = SCE_LOT_DEFAULT; - int styleNext = styler.StyleAt(startPos); - int lev = SC_FOLDLEVELBASE; - - // Gets style of previous line if not at the beginning of the document - if (startPos > 1) - style = styler.StyleAt(startPos - 2); - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if (ch == '\r' && chNext == '\n') { - // TO DO: - // Should really get the state of the previous line from the styler - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 2); - - switch (style) { -/* - case SCE_LOT_SET: - lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; - break; -*/ - case SCE_LOT_FAIL: -/* - if (stylePrev != SCE_LOT_FAIL) - lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; - else - lev = SC_FOLDLEVELBASE + 1; -*/ - lev = SC_FOLDLEVELBASE; - break; - - default: - if (lineCurrent == 0 || stylePrev == SCE_LOT_FAIL) - lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; - else - lev = SC_FOLDLEVELBASE + 1; - - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - break; - } - - if (lev != styler.LevelAt(lineCurrent)) - styler.SetLevel(lineCurrent, lev); - - lineCurrent++; - visibleChars = 0; - } - - if (!isspacechar(ch)) - visibleChars++; - } - - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, lev | flagsNext); -} - -static const char * const emptyWordListDesc[] = { - 0 -}; - -LexerModule lmLot(SCLEX_LOT, ColourizeLotDoc, "lot", FoldLotDoc, emptyWordListDesc); diff --git a/src/LexMSSQL.cxx b/src/LexMSSQL.cxx deleted file mode 100644 index 4a3f3bed8..000000000 --- a/src/LexMSSQL.cxx +++ /dev/null @@ -1,363 +0,0 @@ -// Scintilla source code edit control -/** @file LexMSSQL.cxx - ** Lexer for MSSQL. - **/ -// By Filip Yaghob -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#define KW_MSSQL_STATEMENTS 0 -#define KW_MSSQL_DATA_TYPES 1 -#define KW_MSSQL_SYSTEM_TABLES 2 -#define KW_MSSQL_GLOBAL_VARIABLES 3 -#define KW_MSSQL_FUNCTIONS 4 -#define KW_MSSQL_STORED_PROCEDURES 5 -#define KW_MSSQL_OPERATORS 6 - -static bool isMSSQLOperator(char ch) { - if (isascii(ch) && isalnum(ch)) - return false; - // '.' left out as it is used to make up numbers - if (ch == '%' || ch == '^' || ch == '&' || ch == '*' || - ch == '-' || ch == '+' || ch == '=' || ch == '|' || - ch == '<' || ch == '>' || ch == '/' || - ch == '!' || ch == '~' || ch == '(' || ch == ')' || - ch == ',') - return true; - return false; -} - -static char classifyWordSQL(unsigned int start, - unsigned int end, - WordList *keywordlists[], - Accessor &styler, - unsigned int actualState, - unsigned int prevState) { - char s[256]; - bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.'); - - WordList &kwStatements = *keywordlists[KW_MSSQL_STATEMENTS]; - WordList &kwDataTypes = *keywordlists[KW_MSSQL_DATA_TYPES]; - WordList &kwSystemTables = *keywordlists[KW_MSSQL_SYSTEM_TABLES]; - WordList &kwGlobalVariables = *keywordlists[KW_MSSQL_GLOBAL_VARIABLES]; - WordList &kwFunctions = *keywordlists[KW_MSSQL_FUNCTIONS]; - WordList &kwStoredProcedures = *keywordlists[KW_MSSQL_STORED_PROCEDURES]; - WordList &kwOperators = *keywordlists[KW_MSSQL_OPERATORS]; - - for (unsigned int i = 0; i < end - start + 1 && i < 128; i++) { - s[i] = static_cast(tolower(styler[start + i])); - s[i + 1] = '\0'; - } - char chAttr = SCE_MSSQL_IDENTIFIER; - - if (actualState == SCE_MSSQL_GLOBAL_VARIABLE) { - - if (kwGlobalVariables.InList(&s[2])) - chAttr = SCE_MSSQL_GLOBAL_VARIABLE; - - } else if (wordIsNumber) { - chAttr = SCE_MSSQL_NUMBER; - - } else if (prevState == SCE_MSSQL_DEFAULT_PREF_DATATYPE) { - // Look first in datatypes - if (kwDataTypes.InList(s)) - chAttr = SCE_MSSQL_DATATYPE; - else if (kwOperators.InList(s)) - chAttr = SCE_MSSQL_OPERATOR; - else if (kwStatements.InList(s)) - chAttr = SCE_MSSQL_STATEMENT; - else if (kwSystemTables.InList(s)) - chAttr = SCE_MSSQL_SYSTABLE; - else if (kwFunctions.InList(s)) - chAttr = SCE_MSSQL_FUNCTION; - else if (kwStoredProcedures.InList(s)) - chAttr = SCE_MSSQL_STORED_PROCEDURE; - - } else { - if (kwOperators.InList(s)) - chAttr = SCE_MSSQL_OPERATOR; - else if (kwStatements.InList(s)) - chAttr = SCE_MSSQL_STATEMENT; - else if (kwSystemTables.InList(s)) - chAttr = SCE_MSSQL_SYSTABLE; - else if (kwFunctions.InList(s)) - chAttr = SCE_MSSQL_FUNCTION; - else if (kwStoredProcedures.InList(s)) - chAttr = SCE_MSSQL_STORED_PROCEDURE; - else if (kwDataTypes.InList(s)) - chAttr = SCE_MSSQL_DATATYPE; - } - - styler.ColourTo(end, chAttr); - - return chAttr; -} - -static void ColouriseMSSQLDoc(unsigned int startPos, int length, - int initStyle, WordList *keywordlists[], Accessor &styler) { - - - styler.StartAt(startPos); - - bool fold = styler.GetPropertyInt("fold") != 0; - int lineCurrent = styler.GetLine(startPos); - int spaceFlags = 0; - - int state = initStyle; - int prevState = initStyle; - char chPrev = ' '; - char chNext = styler[startPos]; - styler.StartSegment(startPos); - unsigned int lengthDoc = startPos + length; - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags); - int lev = indentCurrent; - if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { - // Only non whitespace lines can be headers - int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags); - if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - } - if (fold) { - styler.SetLevel(lineCurrent, lev); - } - } - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - chPrev = ' '; - i += 1; - continue; - } - - // When the last char isn't part of the state (have to deal with it too)... - if ( (state == SCE_MSSQL_IDENTIFIER) || - (state == SCE_MSSQL_STORED_PROCEDURE) || - (state == SCE_MSSQL_DATATYPE) || - //~ (state == SCE_MSSQL_COLUMN_NAME) || - (state == SCE_MSSQL_FUNCTION) || - //~ (state == SCE_MSSQL_GLOBAL_VARIABLE) || - (state == SCE_MSSQL_VARIABLE)) { - if (!iswordchar(ch)) { - int stateTmp; - - if ((state == SCE_MSSQL_VARIABLE) || (state == SCE_MSSQL_COLUMN_NAME)) { - styler.ColourTo(i - 1, state); - stateTmp = state; - } else - stateTmp = classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState); - - prevState = state; - - if (stateTmp == SCE_MSSQL_IDENTIFIER || stateTmp == SCE_MSSQL_VARIABLE) - state = SCE_MSSQL_DEFAULT_PREF_DATATYPE; - else - state = SCE_MSSQL_DEFAULT; - } - } else if (state == SCE_MSSQL_LINE_COMMENT) { - if (ch == '\r' || ch == '\n') { - styler.ColourTo(i - 1, state); - prevState = state; - state = SCE_MSSQL_DEFAULT; - } - } else if (state == SCE_MSSQL_GLOBAL_VARIABLE) { - if ((ch != '@') && !iswordchar(ch)) { - classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState); - prevState = state; - state = SCE_MSSQL_DEFAULT; - } - } - - // If is the default or one of the above succeeded - if (state == SCE_MSSQL_DEFAULT || state == SCE_MSSQL_DEFAULT_PREF_DATATYPE) { - if (iswordstart(ch)) { - styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); - prevState = state; - state = SCE_MSSQL_IDENTIFIER; - } else if (ch == '/' && chNext == '*') { - styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); - prevState = state; - state = SCE_MSSQL_COMMENT; - } else if (ch == '-' && chNext == '-') { - styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); - prevState = state; - state = SCE_MSSQL_LINE_COMMENT; - } else if (ch == '\'') { - styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); - prevState = state; - state = SCE_MSSQL_STRING; - } else if (ch == '"') { - styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); - prevState = state; - state = SCE_MSSQL_COLUMN_NAME; - } else if (ch == '[') { - styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); - prevState = state; - state = SCE_MSSQL_COLUMN_NAME_2; - } else if (isMSSQLOperator(ch)) { - styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); - styler.ColourTo(i, SCE_MSSQL_OPERATOR); - //~ style = SCE_MSSQL_DEFAULT; - prevState = state; - state = SCE_MSSQL_DEFAULT; - } else if (ch == '@') { - styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); - prevState = state; - if (chNext == '@') { - state = SCE_MSSQL_GLOBAL_VARIABLE; -// i += 2; - } else - state = SCE_MSSQL_VARIABLE; - } - - - // When the last char is part of the state... - } else if (state == SCE_MSSQL_COMMENT) { - if (ch == '/' && chPrev == '*') { - if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_MSSQL_COMMENT) && - (styler.GetStartSegment() == startPos)))) { - styler.ColourTo(i, state); - //~ state = SCE_MSSQL_COMMENT; - prevState = state; - state = SCE_MSSQL_DEFAULT; - } - } - } else if (state == SCE_MSSQL_STRING) { - if (ch == '\'') { - if ( chNext == '\'' ) { - i++; - ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - } else { - styler.ColourTo(i, state); - prevState = state; - state = SCE_MSSQL_DEFAULT; - //i++; - } - //ch = chNext; - //chNext = styler.SafeGetCharAt(i + 1); - } - } else if (state == SCE_MSSQL_COLUMN_NAME) { - if (ch == '"') { - if (chNext == '"') { - i++; - ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - } else { - styler.ColourTo(i, state); - prevState = state; - state = SCE_MSSQL_DEFAULT_PREF_DATATYPE; - //i++; - } - } - } else if (state == SCE_MSSQL_COLUMN_NAME_2) { - if (ch == ']') { - styler.ColourTo(i, state); - prevState = state; - state = SCE_MSSQL_DEFAULT_PREF_DATATYPE; - //i++; - } - } - - chPrev = ch; - } - styler.ColourTo(lengthDoc - 1, state); -} - -static void FoldMSSQLDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - bool inComment = (styler.StyleAt(startPos-1) == SCE_MSSQL_COMMENT); - char s[10]; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styler.StyleAt(i); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - // Comment folding - if (foldComment) { - if (!inComment && (style == SCE_MSSQL_COMMENT)) - levelCurrent++; - else if (inComment && (style != SCE_MSSQL_COMMENT)) - levelCurrent--; - inComment = (style == SCE_MSSQL_COMMENT); - } - if (style == SCE_MSSQL_STATEMENT) { - // Folding between begin or case and end - if (ch == 'b' || ch == 'B' || ch == 'c' || ch == 'C' || ch == 'e' || ch == 'E') { - for (unsigned int j = 0; j < 5; j++) { - if (!iswordchar(styler[i + j])) { - break; - } - s[j] = static_cast(tolower(styler[i + j])); - s[j + 1] = '\0'; - } - if ((strcmp(s, "begin") == 0) || (strcmp(s, "case") == 0)) { - levelCurrent++; - } - if (strcmp(s, "end") == 0) { - levelCurrent--; - } - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const sqlWordListDesc[] = { - "Statements", - "Data Types", - "System tables", - "Global variables", - "Functions", - "System Stored Procedures", - "Operators", - 0, -}; - -LexerModule lmMSSQL(SCLEX_MSSQL, ColouriseMSSQLDoc, "mssql", FoldMSSQLDoc, sqlWordListDesc); diff --git a/src/LexMagik.cxx b/src/LexMagik.cxx deleted file mode 100644 index c6f6585b3..000000000 --- a/src/LexMagik.cxx +++ /dev/null @@ -1,445 +0,0 @@ -// Scintilla source code edit control -/** - * @file LexMagik.cxx - * Lexer for GE(r) Smallworld(tm) MagikSF - */ -// Copyright 1998-2005 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/** - * Is it a core character (C isalpha(), exclamation and question mark) - * - * \param ch The character - * \return True if ch is a character, False otherwise - */ -static inline bool IsAlphaCore(int ch) { - return (isalpha(ch) || ch == '!' || ch == '?'); -} - -/** - * Is it a character (IsAlphaCore() and underscore) - * - * \param ch The character - * \return True if ch is a character, False otherwise - */ -static inline bool IsAlpha(int ch) { - return (IsAlphaCore(ch) || ch == '_'); -} - -/** - * Is it a symbolic character (IsAlpha() and colon) - * - * \param ch The character - * \return True if ch is a character, False otherwise - */ -static inline bool IsAlphaSym(int ch) { - return (IsAlpha(ch) || ch == ':'); -} - -/** - * Is it a numerical character (IsAlpha() and 0 - 9) - * - * \param ch The character - * \return True if ch is a character, False otherwise - */ -static inline bool IsAlNum(int ch) { - return ((ch >= '0' && ch <= '9') || IsAlpha(ch)); -} - -/** - * Is it a symbolic numerical character (IsAlNum() and colon) - * - * \param ch The character - * \return True if ch is a character, False otherwise - */ -static inline bool IsAlNumSym(int ch) { - return (IsAlNum(ch) || ch == ':'); -} - -/** - * The lexer function - * - * \param startPos Where to start scanning - * \param length Where to scan to - * \param initStyle The style at the initial point, not used in this folder - * \param keywordslists The keywordslists, currently, number 5 is used - * \param styler The styler - */ -static void ColouriseMagikDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - styler.StartAt(startPos); - - WordList &keywords = *keywordlists[0]; - WordList &pragmatics = *keywordlists[1]; - WordList &containers = *keywordlists[2]; - WordList &flow = *keywordlists[3]; - WordList &characters = *keywordlists[4]; - - StyleContext sc(startPos, length, initStyle, styler); - - - for (; sc.More(); sc.Forward()) { - - repeat: - - if(sc.ch == '#') { - if (sc.chNext == '#') sc.SetState(SCE_MAGIK_HYPER_COMMENT); - else sc.SetState(SCE_MAGIK_COMMENT); - for(; sc.More() && !(sc.atLineEnd); sc.Forward()); - sc.SetState(SCE_MAGIK_DEFAULT); - goto repeat; - } - - if(sc.ch == '"') { - sc.SetState(SCE_MAGIK_STRING); - - if(sc.More()) - { - sc.Forward(); - for(; sc.More() && sc.ch != '"'; sc.Forward()); - } - - sc.ForwardSetState(SCE_MAGIK_DEFAULT); - goto repeat; - } - - // The default state - if(sc.state == SCE_MAGIK_DEFAULT) { - - // A certain keyword has been detected - if (sc.ch == '_' && ( - sc.currentPos == 0 || !IsAlNum(sc.chPrev))) { - char keyword[50]; - memset(keyword, '\0', 50); - - for( - int scanPosition = 0; - scanPosition < 50; - scanPosition++) { - char keywordChar = static_cast( - tolower(styler.SafeGetCharAt( - scanPosition + - static_cast(sc.currentPos+1), ' '))); - if(IsAlpha(keywordChar)) { - keyword[scanPosition] = keywordChar; - } else { - break; - } - } - - // It is a pragma - if(pragmatics.InList(keyword)) { - sc.SetState(SCE_MAGIK_PRAGMA); - } - - // it is a normal keyword like _local, _self, etc. - else if(keywords.InList(keyword)) { - sc.SetState(SCE_MAGIK_KEYWORD); - } - - // It is a container keyword, such as _method, _proc, etc. - else if(containers.InList(keyword)) { - sc.SetState(SCE_MAGIK_CONTAINER); - } - - // It is a flow keyword, such as _for, _if, _try, etc. - else if(flow.InList(keyword)) { - sc.SetState(SCE_MAGIK_FLOW); - } - - // Interpret as unknown keyword - else { - sc.SetState(SCE_MAGIK_UNKNOWN_KEYWORD); - } - } - - // Symbolic expression - else if(sc.ch == ':' && !IsAlNum(sc.chPrev)) { - sc.SetState(SCE_MAGIK_SYMBOL); - bool firstTrip = true; - for(sc.Forward(); sc.More(); sc.Forward()) { - if(firstTrip && IsAlphaSym(sc.ch)); - else if(!firstTrip && IsAlNumSym(sc.ch)); - else if(sc.ch == '|') { - for(sc.Forward(); - sc.More() && sc.ch != '|'; - sc.Forward()); - } - else break; - - firstTrip = false; - } - sc.SetState(SCE_MAGIK_DEFAULT); - goto repeat; - } - - // Identifier (label) expression - else if(sc.ch == '@') { - sc.SetState(SCE_MAGIK_IDENTIFIER); - bool firstTrip = true; - for(sc.Forward(); sc.More(); sc.Forward()) { - if(firstTrip && IsAlphaCore(sc.ch)) { - firstTrip = false; - } - else if(!firstTrip && IsAlpha(sc.ch)); - else break; - } - sc.SetState(SCE_MAGIK_DEFAULT); - goto repeat; - } - - // Start of a character - else if(sc.ch == '%') { - sc.SetState(SCE_MAGIK_CHARACTER); - sc.Forward(); - char keyword[50]; - memset(keyword, '\0', 50); - - for( - int scanPosition = 0; - scanPosition < 50; - scanPosition++) { - char keywordChar = static_cast( - tolower(styler.SafeGetCharAt( - scanPosition + - static_cast(sc.currentPos), ' '))); - if(IsAlpha(keywordChar)) { - keyword[scanPosition] = keywordChar; - } else { - break; - } - } - - if(characters.InList(keyword)) { - sc.Forward(strlen(keyword)); - } else { - sc.Forward(); - } - - sc.SetState(SCE_MAGIK_DEFAULT); - goto repeat; - } - - // Operators - else if( - sc.ch == '>' || - sc.ch == '<' || - sc.ch == '.' || - sc.ch == ',' || - sc.ch == '+' || - sc.ch == '-' || - sc.ch == '/' || - sc.ch == '*' || - sc.ch == '~' || - sc.ch == '$' || - sc.ch == '=') { - sc.SetState(SCE_MAGIK_OPERATOR); - } - - // Braces - else if(sc.ch == '(' || sc.ch == ')') { - sc.SetState(SCE_MAGIK_BRACE_BLOCK); - } - - // Brackets - else if(sc.ch == '{' || sc.ch == '}') { - sc.SetState(SCE_MAGIK_BRACKET_BLOCK); - } - - // Square Brackets - else if(sc.ch == '[' || sc.ch == ']') { - sc.SetState(SCE_MAGIK_SQBRACKET_BLOCK); - } - - - } - - // It is an operator - else if( - sc.state == SCE_MAGIK_OPERATOR || - sc.state == SCE_MAGIK_BRACE_BLOCK || - sc.state == SCE_MAGIK_BRACKET_BLOCK || - sc.state == SCE_MAGIK_SQBRACKET_BLOCK) { - sc.SetState(SCE_MAGIK_DEFAULT); - goto repeat; - } - - // It is the pragma state - else if(sc.state == SCE_MAGIK_PRAGMA) { - if(!IsAlpha(sc.ch)) { - sc.SetState(SCE_MAGIK_DEFAULT); - goto repeat; - } - } - - // It is the keyword state - else if( - sc.state == SCE_MAGIK_KEYWORD || - sc.state == SCE_MAGIK_CONTAINER || - sc.state == SCE_MAGIK_FLOW || - sc.state == SCE_MAGIK_UNKNOWN_KEYWORD) { - if(!IsAlpha(sc.ch)) { - sc.SetState(SCE_MAGIK_DEFAULT); - goto repeat; - } - } - } - - sc.Complete(); -} - -/** - * The word list description - */ -static const char * const magikWordListDesc[] = { - "Accessors (local, global, self, super, thisthread)", - "Pragmatic (pragma, private)", - "Containers (method, block, proc)", - "Flow (if, then, elif, else)", - "Characters (space, tab, newline, return)", - "Fold Containers (method, proc, block, if, loop)", - 0}; - -/** - * This function detects keywords which are able to have a body. Note that it - * uses the Fold Containers word description, not the containers description. It - * only works when the style at that particular position is set on Containers - * or Flow (number 3 or 4). - * - * \param keywordslist The list of keywords that are scanned, they should only - * contain the start keywords, not the end keywords - * \param The actual keyword - * \return 1 if it is a folding start-keyword, -1 if it is a folding end-keyword - * 0 otherwise - */ -static inline int IsFoldingContainer(WordList &keywordslist, char * keyword) { - if( - strlen(keyword) > 3 && - keyword[0] == 'e' && keyword[1] == 'n' && keyword[2] == 'd') { - if (keywordslist.InList(keyword + 3)) { - return -1; - } - - } else { - if(keywordslist.InList(keyword)) { - return 1; - } - } - - return 0; -} - -/** - * The folding function - * - * \param startPos Where to start scanning - * \param length Where to scan to - * \param keywordslists The keywordslists, currently, number 5 is used - * \param styler The styler - */ -static void FoldMagikDoc(unsigned int startPos, int length, int, - WordList *keywordslists[], Accessor &styler) { - - bool compact = styler.GetPropertyInt("fold.compact") != 0; - - WordList &foldingElements = *keywordslists[5]; - int endPos = startPos + length; - int line = styler.GetLine(startPos); - int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK; - int flags = styler.LevelAt(line) & ~SC_FOLDLEVELNUMBERMASK; - - for( - int currentPos = startPos; - currentPos < endPos; - currentPos++) { - char currentState = styler.StyleAt(currentPos); - char c = styler.SafeGetCharAt(currentPos, ' '); - int prevLine = styler.GetLine(currentPos - 1); - line = styler.GetLine(currentPos); - - // Default situation - if(prevLine < line) { - styler.SetLevel(line, (level|flags) & ~SC_FOLDLEVELHEADERFLAG); - flags = styler.LevelAt(line) & ~SC_FOLDLEVELNUMBERMASK; - } - - if( - ( - currentState == SCE_MAGIK_CONTAINER || - currentState == SCE_MAGIK_FLOW - ) && - c == '_') { - - char keyword[50]; - memset(keyword, '\0', 50); - - for( - int scanPosition = 0; - scanPosition < 50; - scanPosition++) { - char keywordChar = static_cast( - tolower(styler.SafeGetCharAt( - scanPosition + - currentPos + 1, ' '))); - if(IsAlpha(keywordChar)) { - keyword[scanPosition] = keywordChar; - } else { - break; - } - } - - if(IsFoldingContainer(foldingElements, keyword) > 0) { - styler.SetLevel( - line, - styler.LevelAt(line) | SC_FOLDLEVELHEADERFLAG); - level++; - } else if(IsFoldingContainer(foldingElements, keyword) < 0) { - styler.SetLevel(line, styler.LevelAt(line)); - level--; - } - } - - if( - compact && ( - currentState == SCE_MAGIK_BRACE_BLOCK || - currentState == SCE_MAGIK_BRACKET_BLOCK || - currentState == SCE_MAGIK_SQBRACKET_BLOCK)) { - if(c == '{' || c == '[' || c == '(') { - styler.SetLevel( - line, - styler.LevelAt(line) | SC_FOLDLEVELHEADERFLAG); - level++; - } else if(c == '}' || c == ']' || c == ')') { - styler.SetLevel(line, styler.LevelAt(line)); - level--; - } - } - } - -} - -/** - * Injecting the module - */ -LexerModule lmMagikSF( - SCLEX_MAGIK, ColouriseMagikDoc, "magiksf", FoldMagikDoc, magikWordListDesc); - diff --git a/src/LexMarkdown.cxx b/src/LexMarkdown.cxx deleted file mode 100644 index f7fc48f40..000000000 --- a/src/LexMarkdown.cxx +++ /dev/null @@ -1,412 +0,0 @@ -/****************************************************************** - * LexMarkdown.cxx - * - * A simple Markdown lexer for scintilla. - * - * Includes highlighting for some extra features from the - * Pandoc implementation; strikeout, using '#.' as a default - * ordered list item marker, and delimited code blocks. - * - * Limitations: - * - * Standard indented code blocks are not highlighted at all, - * as it would conflict with other indentation schemes. Use - * delimited code blocks for blanket highlighting of an - * entire code block. Embedded HTML is not highlighted either. - * Blanket HTML highlighting has issues, because some Markdown - * implementations allow Markdown markup inside of the HTML. Also, - * there is a following blank line issue that can't be ignored, - * explained in the next paragraph. Embedded HTML and code - * blocks would be better supported with language specific - * highlighting. - * - * The highlighting aims to accurately reflect correct syntax, - * but a few restrictions are relaxed. Delimited code blocks are - * highlighted, even if the line following the code block is not blank. - * Requiring a blank line after a block, breaks the highlighting - * in certain cases, because of the way Scintilla ends up calling - * the lexer. - * - * Written by Jon Strait - jstrait@moonloop.net - * - * The License.txt file describes the conditions under which this - * software may be distributed. - * - *****************************************************************/ - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsNewline(const int ch) { - return (ch == '\n' || ch == '\r'); -} - -// True if can follow ch down to the end with possibly trailing whitespace -static bool FollowToLineEnd(const int ch, const int state, const unsigned int endPos, StyleContext &sc) { - unsigned int i = 0; - while (sc.GetRelative(++i) == ch) - ; - // Skip over whitespace - while (IsASpaceOrTab(sc.GetRelative(i)) && sc.currentPos + i < endPos) - ++i; - if (IsNewline(sc.GetRelative(i)) || sc.currentPos + i == endPos) { - sc.Forward(i); - sc.ChangeState(state); - sc.SetState(SCE_MARKDOWN_LINE_BEGIN); - return true; - } - else return false; -} - -// Set the state on text section from current to length characters, -// then set the rest until the newline to default, except for any characters matching token -static void SetStateAndZoom(const int state, const int length, const int token, StyleContext &sc) { - sc.SetState(state); - sc.Forward(length); - sc.SetState(SCE_MARKDOWN_DEFAULT); - sc.Forward(); - bool started = false; - while (sc.More() && !IsNewline(sc.ch)) { - if (sc.ch == token && !started) { - sc.SetState(state); - started = true; - } - else if (sc.ch != token) { - sc.SetState(SCE_MARKDOWN_DEFAULT); - started = false; - } - sc.Forward(); - } - sc.SetState(SCE_MARKDOWN_LINE_BEGIN); -} - -// Does the previous line have more than spaces and tabs? -static bool HasPrevLineContent(StyleContext &sc) { - int i = 0; - // Go back to the previous newline - while ((--i + sc.currentPos) && !IsNewline(sc.GetRelative(i))) - ; - while (--i + sc.currentPos) { - if (IsNewline(sc.GetRelative(i))) - break; - if (!IsASpaceOrTab(sc.GetRelative(i))) - return true; - } - return false; -} - -static bool IsValidHrule(const unsigned int endPos, StyleContext &sc) { - int c, count = 1; - unsigned int i = 0; - while (++i) { - c = sc.GetRelative(i); - if (c == sc.ch) - ++count; - // hit a terminating character - else if (!IsASpaceOrTab(c) || sc.currentPos + i == endPos) { - // Are we a valid HRULE - if ((IsNewline(c) || sc.currentPos + i == endPos) && - count >= 3 && !HasPrevLineContent(sc)) { - sc.SetState(SCE_MARKDOWN_HRULE); - sc.Forward(i); - sc.SetState(SCE_MARKDOWN_LINE_BEGIN); - return true; - } - else { - sc.SetState(SCE_MARKDOWN_DEFAULT); - return false; - } - } - } - return false; -} - -static void ColorizeMarkdownDoc(unsigned int startPos, int length, int initStyle, - WordList **, Accessor &styler) { - unsigned int endPos = startPos + length; - int precharCount = 0; - // Don't advance on a new loop iteration and retry at the same position. - // Useful in the corner case of having to start at the beginning file position - // in the default state. - bool freezeCursor = false; - - StyleContext sc(startPos, length, initStyle, styler); - - while (sc.More()) { - // Skip past escaped characters - if (sc.ch == '\\') { - sc.Forward(); - continue; - } - - // A blockquotes resets the line semantics - if (sc.state == SCE_MARKDOWN_BLOCKQUOTE) - sc.SetState(SCE_MARKDOWN_LINE_BEGIN); - - // Conditional state-based actions - if (sc.state == SCE_MARKDOWN_CODE2) { - if (sc.Match("``") && sc.GetRelative(-2) != ' ') { - sc.Forward(2); - sc.SetState(SCE_MARKDOWN_DEFAULT); - } - } - else if (sc.state == SCE_MARKDOWN_CODE) { - if (sc.ch == '`' && sc.chPrev != ' ') - sc.ForwardSetState(SCE_MARKDOWN_DEFAULT); - } - /* De-activated because it gets in the way of other valid indentation - * schemes, for example multiple paragraphs inside a list item. - // Code block - else if (sc.state == SCE_MARKDOWN_CODEBK) { - bool d = true; - if (IsNewline(sc.ch)) { - if (sc.chNext != '\t') { - for (int c = 1; c < 5; ++c) { - if (sc.GetRelative(c) != ' ') - d = false; - } - } - } - else if (sc.atLineStart) { - if (sc.ch != '\t' ) { - for (int i = 0; i < 4; ++i) { - if (sc.GetRelative(i) != ' ') - d = false; - } - } - } - if (!d) - sc.SetState(SCE_MARKDOWN_LINE_BEGIN); - } - */ - // Strong - else if (sc.state == SCE_MARKDOWN_STRONG1) { - if (sc.Match("**") && sc.chPrev != ' ') { - sc.Forward(2); - sc.SetState(SCE_MARKDOWN_DEFAULT); - } - } - else if (sc.state == SCE_MARKDOWN_STRONG2) { - if (sc.Match("__") && sc.chPrev != ' ') { - sc.Forward(2); - sc.SetState(SCE_MARKDOWN_DEFAULT); - } - } - // Emphasis - else if (sc.state == SCE_MARKDOWN_EM1) { - if (sc.ch == '*' && sc.chPrev != ' ') - sc.ForwardSetState(SCE_MARKDOWN_DEFAULT); - } - else if (sc.state == SCE_MARKDOWN_EM2) { - if (sc.ch == '_' && sc.chPrev != ' ') - sc.ForwardSetState(SCE_MARKDOWN_DEFAULT); - } - else if (sc.state == SCE_MARKDOWN_CODEBK) { - if (sc.atLineStart && sc.Match("~~~")) { - int i = 1; - while (!IsNewline(sc.GetRelative(i)) && sc.currentPos + i < endPos) - i++; - sc.Forward(i); - sc.SetState(SCE_MARKDOWN_DEFAULT); - } - } - else if (sc.state == SCE_MARKDOWN_STRIKEOUT) { - if (sc.Match("~~") && sc.chPrev != ' ') { - sc.Forward(2); - sc.SetState(SCE_MARKDOWN_DEFAULT); - } - } - else if (sc.state == SCE_MARKDOWN_LINE_BEGIN) { - // Header - if (sc.Match("######")) - SetStateAndZoom(SCE_MARKDOWN_HEADER6, 6, '#', sc); - else if (sc.Match("#####")) - SetStateAndZoom(SCE_MARKDOWN_HEADER5, 5, '#', sc); - else if (sc.Match("####")) - SetStateAndZoom(SCE_MARKDOWN_HEADER4, 4, '#', sc); - else if (sc.Match("###")) - SetStateAndZoom(SCE_MARKDOWN_HEADER3, 3, '#', sc); - else if (sc.Match("##")) - SetStateAndZoom(SCE_MARKDOWN_HEADER2, 2, '#', sc); - else if (sc.Match("#")) { - // Catch the special case of an unordered list - if (sc.chNext == '.' && IsASpaceOrTab(sc.GetRelative(2))) { - precharCount = 0; - sc.SetState(SCE_MARKDOWN_PRECHAR); - } - else - SetStateAndZoom(SCE_MARKDOWN_HEADER1, 1, '#', sc); - } - // Code block - else if (sc.Match("~~~")) { - if (!HasPrevLineContent(sc)) - sc.SetState(SCE_MARKDOWN_CODEBK); - else - sc.SetState(SCE_MARKDOWN_DEFAULT); - } - else if (sc.ch == '=') { - if (HasPrevLineContent(sc) && FollowToLineEnd('=', SCE_MARKDOWN_HEADER1, endPos, sc)) - ; - else - sc.SetState(SCE_MARKDOWN_DEFAULT); - } - else if (sc.ch == '-') { - if (HasPrevLineContent(sc) && FollowToLineEnd('-', SCE_MARKDOWN_HEADER2, endPos, sc)) - ; - else { - precharCount = 0; - sc.SetState(SCE_MARKDOWN_PRECHAR); - } - } - else if (IsNewline(sc.ch)) - sc.SetState(SCE_MARKDOWN_LINE_BEGIN); - else { - precharCount = 0; - sc.SetState(SCE_MARKDOWN_PRECHAR); - } - } - - // The header lasts until the newline - else if (sc.state == SCE_MARKDOWN_HEADER1 || sc.state == SCE_MARKDOWN_HEADER2 || - sc.state == SCE_MARKDOWN_HEADER3 || sc.state == SCE_MARKDOWN_HEADER4 || - sc.state == SCE_MARKDOWN_HEADER5 || sc.state == SCE_MARKDOWN_HEADER6) { - if (IsNewline(sc.ch)) - sc.SetState(SCE_MARKDOWN_LINE_BEGIN); - } - - // New state only within the initial whitespace - if (sc.state == SCE_MARKDOWN_PRECHAR) { - // Blockquote - if (sc.ch == '>' && precharCount < 5) - sc.SetState(SCE_MARKDOWN_BLOCKQUOTE); - /* - // Begin of code block - else if (!HasPrevLineContent(sc) && (sc.chPrev == '\t' || precharCount >= 4)) - sc.SetState(SCE_MARKDOWN_CODEBK); - */ - // HRule - Total of three or more hyphens, asterisks, or underscores - // on a line by themselves - else if ((sc.ch == '-' || sc.ch == '*' || sc.ch == '_') && IsValidHrule(endPos, sc)) - ; - // Unordered list - else if ((sc.ch == '-' || sc.ch == '*' || sc.ch == '+') && IsASpaceOrTab(sc.chNext)) { - sc.SetState(SCE_MARKDOWN_ULIST_ITEM); - sc.ForwardSetState(SCE_MARKDOWN_DEFAULT); - } - // Ordered list - else if (IsADigit(sc.ch)) { - int digitCount = 0; - while (IsADigit(sc.GetRelative(++digitCount))) - ; - if (sc.GetRelative(digitCount) == '.' && - IsASpaceOrTab(sc.GetRelative(digitCount + 1))) { - sc.SetState(SCE_MARKDOWN_OLIST_ITEM); - sc.Forward(digitCount + 1); - sc.SetState(SCE_MARKDOWN_DEFAULT); - } - } - // Alternate Ordered list - else if (sc.ch == '#' && sc.chNext == '.' && IsASpaceOrTab(sc.GetRelative(2))) { - sc.SetState(SCE_MARKDOWN_OLIST_ITEM); - sc.Forward(2); - sc.SetState(SCE_MARKDOWN_DEFAULT); - } - else if (sc.ch != ' ' || precharCount > 2) - sc.SetState(SCE_MARKDOWN_DEFAULT); - else - ++precharCount; - } - - // New state anywhere in doc - if (sc.state == SCE_MARKDOWN_DEFAULT) { - if (sc.atLineStart && sc.ch == '#') { - sc.SetState(SCE_MARKDOWN_LINE_BEGIN); - freezeCursor = true; - } - // Links and Images - if (sc.Match("![") || sc.ch == '[') { - int i = 0, j = 0, k = 0; - int len = endPos - sc.currentPos; - while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\')) - ; - if (sc.GetRelative(i) == ']') { - j = i; - if (sc.GetRelative(++i) == '(') { - while (i < len && (sc.GetRelative(++i) != ')' || sc.GetRelative(i - 1) == '\\')) - ; - if (sc.GetRelative(i) == ')') - k = i; - } - else if (sc.GetRelative(i) == '[' || sc.GetRelative(++i) == '[') { - while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\')) - ; - if (sc.GetRelative(i) == ']') - k = i; - } - } - // At least a link text - if (j) { - sc.SetState(SCE_MARKDOWN_LINK); - sc.Forward(j); - // Also has a URL or reference portion - if (k) - sc.Forward(k - j); - sc.ForwardSetState(SCE_MARKDOWN_DEFAULT); - } - } - // Code - also a special case for alternate inside spacing - if (sc.Match("``") && sc.GetRelative(3) != ' ') { - sc.SetState(SCE_MARKDOWN_CODE2); - sc.Forward(); - } - else if (sc.ch == '`' && sc.chNext != ' ') { - sc.SetState(SCE_MARKDOWN_CODE); - } - // Strong - else if (sc.Match("**") && sc.GetRelative(2) != ' ') { - sc.SetState(SCE_MARKDOWN_STRONG1); - sc.Forward(); - } - else if (sc.Match("__") && sc.GetRelative(2) != ' ') { - sc.SetState(SCE_MARKDOWN_STRONG2); - sc.Forward(); - } - // Emphasis - else if (sc.ch == '*' && sc.chNext != ' ') - sc.SetState(SCE_MARKDOWN_EM1); - else if (sc.ch == '_' && sc.chNext != ' ') - sc.SetState(SCE_MARKDOWN_EM2); - // Strikeout - else if (sc.Match("~~") && sc.GetRelative(2) != ' ') { - sc.SetState(SCE_MARKDOWN_STRIKEOUT); - sc.Forward(); - } - // Beginning of line - else if (IsNewline(sc.ch)) - sc.SetState(SCE_MARKDOWN_LINE_BEGIN); - } - // Advance if not holding back the cursor for this iteration. - if (!freezeCursor) - sc.Forward(); - freezeCursor = false; - } - sc.Complete(); -} - -LexerModule lmMarkdown(SCLEX_MARKDOWN, ColorizeMarkdownDoc, "markdown"); diff --git a/src/LexMatlab.cxx b/src/LexMatlab.cxx deleted file mode 100644 index 4e467bd2f..000000000 --- a/src/LexMatlab.cxx +++ /dev/null @@ -1,236 +0,0 @@ -// Scintilla source code edit control -/** @file LexMatlab.cxx - ** Lexer for Matlab. - ** Written by José Fonseca - ** - ** Changes by Christoph Dalitz 2003/12/04: - ** - added support for Octave - ** - Strings can now be included both in single or double quotes - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static bool IsMatlabCommentChar(int c) { - return (c == '%') ; -} - -static bool IsOctaveCommentChar(int c) { - return (c == '%' || c == '#') ; -} - -static bool IsMatlabComment(Accessor &styler, int pos, int len) { - return len > 0 && IsMatlabCommentChar(styler[pos]) ; -} - -static bool IsOctaveComment(Accessor &styler, int pos, int len) { - return len > 0 && IsOctaveCommentChar(styler[pos]) ; -} - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static void ColouriseMatlabOctaveDoc( - unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler, - bool (*IsCommentChar)(int)) { - - WordList &keywords = *keywordlists[0]; - - styler.StartAt(startPos); - - bool transpose = false; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.state == SCE_MATLAB_OPERATOR) { - if (sc.chPrev == '.') { - if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' || sc.ch == '^') { - sc.ForwardSetState(SCE_MATLAB_DEFAULT); - transpose = false; - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_MATLAB_DEFAULT); - transpose = true; - } else { - sc.SetState(SCE_MATLAB_DEFAULT); - } - } else { - sc.SetState(SCE_MATLAB_DEFAULT); - } - } else if (sc.state == SCE_MATLAB_KEYWORD) { - if (!isalnum(sc.ch) && sc.ch != '_') { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords.InList(s)) { - sc.SetState(SCE_MATLAB_DEFAULT); - transpose = false; - } else { - sc.ChangeState(SCE_MATLAB_IDENTIFIER); - sc.SetState(SCE_MATLAB_DEFAULT); - transpose = true; - } - } - } else if (sc.state == SCE_MATLAB_NUMBER) { - if (!isdigit(sc.ch) && sc.ch != '.' - && !(sc.ch == 'e' || sc.ch == 'E') - && !((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E'))) { - sc.SetState(SCE_MATLAB_DEFAULT); - transpose = true; - } - } else if (sc.state == SCE_MATLAB_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_MATLAB_DEFAULT); - } - } else if (sc.state == SCE_MATLAB_DOUBLEQUOTESTRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_MATLAB_DEFAULT); - } - } else if (sc.state == SCE_MATLAB_COMMENT || sc.state == SCE_MATLAB_COMMAND) { - if (sc.atLineEnd) { - sc.SetState(SCE_MATLAB_DEFAULT); - transpose = false; - } - } - - if (sc.state == SCE_MATLAB_DEFAULT) { - if (IsCommentChar(sc.ch)) { - sc.SetState(SCE_MATLAB_COMMENT); - } else if (sc.ch == '!' && sc.chNext != '=' ) { - sc.SetState(SCE_MATLAB_COMMAND); - } else if (sc.ch == '\'') { - if (transpose) { - sc.SetState(SCE_MATLAB_OPERATOR); - } else { - sc.SetState(SCE_MATLAB_STRING); - } - } else if (sc.ch == '"') { - sc.SetState(SCE_MATLAB_DOUBLEQUOTESTRING); - } else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) { - sc.SetState(SCE_MATLAB_NUMBER); - } else if (isalpha(sc.ch)) { - sc.SetState(SCE_MATLAB_KEYWORD); - } else if (isoperator(static_cast(sc.ch)) || sc.ch == '@' || sc.ch == '\\') { - if (sc.ch == ')' || sc.ch == ']') { - transpose = true; - } else { - transpose = false; - } - sc.SetState(SCE_MATLAB_OPERATOR); - } else { - transpose = false; - } - } - } - sc.Complete(); -} - -static void ColouriseMatlabDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - ColouriseMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsMatlabCommentChar); -} - -static void ColouriseOctaveDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - ColouriseMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsOctaveCommentChar); -} - -static void FoldMatlabOctaveDoc(unsigned int startPos, int length, int, - WordList *[], Accessor &styler, - bool (*IsComment)(Accessor&, int, int)) { - - int endPos = startPos + length; - - // Backtrack to previous line in case need to fix its fold status - int lineCurrent = styler.GetLine(startPos); - if (startPos > 0) { - if (lineCurrent > 0) { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); - } - } - int spaceFlags = 0; - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsComment); - char chNext = styler[startPos]; - for (int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { - int lev = indentCurrent; - int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsComment); - if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { - // Only non whitespace lines can be headers - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { - // Line after is blank so check the next - maybe should continue further? - int spaceFlags2 = 0; - int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsComment); - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - } - } - indentCurrent = indentNext; - styler.SetLevel(lineCurrent, lev); - lineCurrent++; - } - } -} - -static void FoldMatlabDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - FoldMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsMatlabComment); -} - -static void FoldOctaveDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - FoldMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsOctaveComment); -} - -static const char * const matlabWordListDesc[] = { - "Keywords", - 0 -}; - -static const char * const octaveWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmMatlab(SCLEX_MATLAB, ColouriseMatlabDoc, "matlab", FoldMatlabDoc, matlabWordListDesc); - -LexerModule lmOctave(SCLEX_OCTAVE, ColouriseOctaveDoc, "octave", FoldOctaveDoc, octaveWordListDesc); diff --git a/src/LexMetapost.cxx b/src/LexMetapost.cxx deleted file mode 100644 index 6afc9d826..000000000 --- a/src/LexMetapost.cxx +++ /dev/null @@ -1,399 +0,0 @@ -// Scintilla source code edit control - -// File: LexMetapost.cxx - general context conformant metapost coloring scheme -// Author: Hans Hagen - PRAGMA ADE - Hasselt NL - www.pragma-ade.com -// Version: September 28, 2003 -// Modified by instanton: July 10, 2007 -// Folding based on keywordlists[] - -// Copyright: 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -// This lexer is derived from the one written for the texwork environment (1999++) which in -// turn is inspired on texedit (1991++) which finds its roots in wdt (1986). - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "StyleContext.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// val SCE_METAPOST_DEFAULT = 0 -// val SCE_METAPOST_SPECIAL = 1 -// val SCE_METAPOST_GROUP = 2 -// val SCE_METAPOST_SYMBOL = 3 -// val SCE_METAPOST_COMMAND = 4 -// val SCE_METAPOST_TEXT = 5 - -// Definitions in SciTEGlobal.properties: -// -// Metapost Highlighting -// -// # Default -// style.metapost.0=fore:#7F7F00 -// # Special -// style.metapost.1=fore:#007F7F -// # Group -// style.metapost.2=fore:#880000 -// # Symbol -// style.metapost.3=fore:#7F7F00 -// # Command -// style.metapost.4=fore:#008800 -// # Text -// style.metapost.5=fore:#000000 - -// lexer.tex.comment.process=0 - -// Auxiliary functions: - -static inline bool endOfLine(Accessor &styler, unsigned int i) { - return - (styler[i] == '\n') || ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')) ; -} - -static inline bool isMETAPOSTcomment(int ch) { - return - (ch == '%') ; -} - -static inline bool isMETAPOSTone(int ch) { - return - (ch == '[') || (ch == ']') || (ch == '(') || (ch == ')') || - (ch == ':') || (ch == '=') || (ch == '<') || (ch == '>') || - (ch == '{') || (ch == '}') || (ch == '\'') || (ch == '\"') ; -} - -static inline bool isMETAPOSTtwo(int ch) { - return - (ch == ';') || (ch == '$') || (ch == '@') || (ch == '#'); -} - -static inline bool isMETAPOSTthree(int ch) { - return - (ch == '.') || (ch == '-') || (ch == '+') || (ch == '/') || - (ch == '*') || (ch == ',') || (ch == '|') || (ch == '`') || - (ch == '!') || (ch == '?') || (ch == '^') || (ch == '&') || - (ch == '%') ; -} - -static inline bool isMETAPOSTidentifier(int ch) { - return - ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) || - (ch == '_') ; -} - -static inline bool isMETAPOSTnumber(int ch) { - return - (ch >= '0') && (ch <= '9') ; -} - -static inline bool isMETAPOSTstring(int ch) { - return - (ch == '\"') ; -} - -static inline bool isMETAPOSTcolon(int ch) { - return - (ch == ':') ; -} - -static inline bool isMETAPOSTequal(int ch) { - return - (ch == '=') ; -} - -static int CheckMETAPOSTInterface( - unsigned int startPos, - int length, - Accessor &styler, - int defaultInterface) { - - char lineBuffer[1024] ; - unsigned int linePos = 0 ; - - // some day we can make something lexer.metapost.mapping=(none,0)(metapost,1)(mp,1)(metafun,2)... - - if (styler.SafeGetCharAt(0) == '%') { - for (unsigned int i = 0; i < startPos + length; i++) { - lineBuffer[linePos++] = styler.SafeGetCharAt(i) ; - if (endOfLine(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { - lineBuffer[linePos] = '\0'; - if (strstr(lineBuffer, "interface=none")) { - return 0 ; - } else if (strstr(lineBuffer, "interface=metapost") || strstr(lineBuffer, "interface=mp")) { - return 1 ; - } else if (strstr(lineBuffer, "interface=metafun")) { - return 2 ; - } else if (styler.SafeGetCharAt(1) == 'D' && strstr(lineBuffer, "%D \\module")) { - // better would be to limit the search to just one line - return 2 ; - } else { - return defaultInterface ; - } - } - } - } - - return defaultInterface ; -} - -static void ColouriseMETAPOSTDoc( - unsigned int startPos, - int length, - int, - WordList *keywordlists[], - Accessor &styler) { - - styler.StartAt(startPos) ; - styler.StartSegment(startPos) ; - - bool processComment = styler.GetPropertyInt("lexer.metapost.comment.process", 0) == 1 ; - int defaultInterface = styler.GetPropertyInt("lexer.metapost.interface.default", 1) ; - - int currentInterface = CheckMETAPOSTInterface(startPos,length,styler,defaultInterface) ; - - // 0 no keyword highlighting - // 1 metapost keyword hightlighting - // 2+ metafun keyword hightlighting - - int extraInterface = 0 ; - - if (currentInterface != 0) { - extraInterface = currentInterface ; - } - - WordList &keywords = *keywordlists[0] ; - WordList &keywords2 = *keywordlists[extraInterface-1] ; - - StyleContext sc(startPos, length, SCE_METAPOST_TEXT, styler) ; - - char key[100] ; - - bool inTeX = false ; - bool inComment = false ; - bool inString = false ; - bool inClause = false ; - - bool going = sc.More() ; // needed because of a fuzzy end of file state - - for (; going; sc.Forward()) { - - if (! sc.More()) { going = false ; } // we need to go one behind the end of text - - if (inClause) { - sc.SetState(SCE_METAPOST_TEXT) ; - inClause = false ; - } - - if (inComment) { - if (sc.atLineEnd) { - sc.SetState(SCE_METAPOST_TEXT) ; - inTeX = false ; - inComment = false ; - inClause = false ; - inString = false ; // not correct but we want to stimulate one-lines - } - } else if (inString) { - if (isMETAPOSTstring(sc.ch)) { - sc.SetState(SCE_METAPOST_SPECIAL) ; - sc.ForwardSetState(SCE_METAPOST_TEXT) ; - inString = false ; - } else if (sc.atLineEnd) { - sc.SetState(SCE_METAPOST_TEXT) ; - inTeX = false ; - inComment = false ; - inClause = false ; - inString = false ; // not correct but we want to stimulate one-lines - } - } else { - if ((! isMETAPOSTidentifier(sc.ch)) && (sc.LengthCurrent() > 0)) { - if (sc.state == SCE_METAPOST_COMMAND) { - sc.GetCurrent(key, sizeof(key)) ; - if ((strcmp(key,"btex") == 0) || (strcmp(key,"verbatimtex") == 0)) { - sc.ChangeState(SCE_METAPOST_GROUP) ; - inTeX = true ; - } else if (inTeX) { - if (strcmp(key,"etex") == 0) { - sc.ChangeState(SCE_METAPOST_GROUP) ; - inTeX = false ; - } else { - sc.ChangeState(SCE_METAPOST_TEXT) ; - } - } else { - if (keywords && keywords.InList(key)) { - sc.ChangeState(SCE_METAPOST_COMMAND) ; - } else if (keywords2 && keywords2.InList(key)) { - sc.ChangeState(SCE_METAPOST_EXTRA) ; - } else { - sc.ChangeState(SCE_METAPOST_TEXT) ; - } - } - } - } - if (isMETAPOSTcomment(sc.ch)) { - if (! inTeX) { - sc.SetState(SCE_METAPOST_SYMBOL) ; - sc.ForwardSetState(SCE_METAPOST_DEFAULT) ; - inComment = ! processComment ; - } else { - sc.SetState(SCE_METAPOST_TEXT) ; - } - } else if (isMETAPOSTstring(sc.ch)) { - if (! inTeX) { - sc.SetState(SCE_METAPOST_SPECIAL) ; - if (! isMETAPOSTstring(sc.chNext)) { - sc.ForwardSetState(SCE_METAPOST_TEXT) ; - } - inString = true ; - } else { - sc.SetState(SCE_METAPOST_TEXT) ; - } - } else if (isMETAPOSTcolon(sc.ch)) { - if (! inTeX) { - if (! isMETAPOSTequal(sc.chNext)) { - sc.SetState(SCE_METAPOST_COMMAND) ; - inClause = true ; - } else { - sc.SetState(SCE_METAPOST_SPECIAL) ; - } - } else { - sc.SetState(SCE_METAPOST_TEXT) ; - } - } else if (isMETAPOSTone(sc.ch)) { - if (! inTeX) { - sc.SetState(SCE_METAPOST_SPECIAL) ; - } else { - sc.SetState(SCE_METAPOST_TEXT) ; - } - } else if (isMETAPOSTtwo(sc.ch)) { - if (! inTeX) { - sc.SetState(SCE_METAPOST_GROUP) ; - } else { - sc.SetState(SCE_METAPOST_TEXT) ; - } - } else if (isMETAPOSTthree(sc.ch)) { - if (! inTeX) { - sc.SetState(SCE_METAPOST_SYMBOL) ; - } else { - sc.SetState(SCE_METAPOST_TEXT) ; - } - } else if (isMETAPOSTidentifier(sc.ch)) { - if (sc.state != SCE_METAPOST_COMMAND) { - sc.SetState(SCE_METAPOST_TEXT) ; - sc.ChangeState(SCE_METAPOST_COMMAND) ; - } - } else if (isMETAPOSTnumber(sc.ch)) { - // rather redundant since for the moment we don't handle numbers - sc.SetState(SCE_METAPOST_TEXT) ; - } else if (sc.atLineEnd) { - sc.SetState(SCE_METAPOST_TEXT) ; - inTeX = false ; - inComment = false ; - inClause = false ; - inString = false ; - } else { - sc.SetState(SCE_METAPOST_TEXT) ; - } - } - - } - - sc.Complete(); - -} - -// Hooks info the system: - -static const char * const metapostWordListDesc[] = { - "MetaPost", - "MetaFun", - 0 -} ; - -static int classifyFoldPointMetapost(const char* s,WordList *keywordlists[]) { - WordList& keywordsStart=*keywordlists[3]; - WordList& keywordsStop1=*keywordlists[4]; - - if (keywordsStart.InList(s)) {return 1;} - else if (keywordsStop1.InList(s)) {return -1;} - return 0; - -} - -static int ParseMetapostWord(unsigned int pos, Accessor &styler, char *word) -{ - int length=0; - char ch=styler.SafeGetCharAt(pos); - *word=0; - - while(isMETAPOSTidentifier(ch) && isalpha(ch) && length<100){ - word[length]=ch; - length++; - ch=styler.SafeGetCharAt(pos+length); - } - word[length]=0; - return length; -} - -static void FoldMetapostDoc(unsigned int startPos, int length, int, WordList *keywordlists[], Accessor &styler) -{ - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos+length; - int visibleChars=0; - int lineCurrent=styler.GetLine(startPos); - int levelPrev=styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent=levelPrev; - char chNext=styler[startPos]; - - char buffer[100]=""; - - for (unsigned int i=startPos; i < endPos; i++) { - char ch=chNext; - chNext=styler.SafeGetCharAt(i+1); - char chPrev=styler.SafeGetCharAt(i-1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - if(i==0 || chPrev == '\r' || chPrev=='\n'|| chPrev==' '|| chPrev=='(' || chPrev=='$') - { - ParseMetapostWord(i, styler, buffer); - levelCurrent += classifyFoldPointMetapost(buffer,keywordlists); - } - - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - - if (!isspacechar(ch)) - visibleChars++; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); - -} - - -LexerModule lmMETAPOST(SCLEX_METAPOST, ColouriseMETAPOSTDoc, "metapost", FoldMetapostDoc, metapostWordListDesc); diff --git a/src/LexMySQL.cxx b/src/LexMySQL.cxx deleted file mode 100644 index e8496ceea..000000000 --- a/src/LexMySQL.cxx +++ /dev/null @@ -1,518 +0,0 @@ -/** - * Scintilla source code edit control - * @file LexMySQL.cxx - * Lexer for MySQL - * - * Improved by Mike Lischke - * Adopted from LexSQL.cxx by Anders Karlsson - * Original work by Neil Hodgson - * Copyright 1998-2005 by Neil Hodgson - * The License.txt file describes the conditions under which this software may be distributed. - */ - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static inline bool IsAWordStart(int ch) { - return (ch < 0x80) && (isalpha(ch) || ch == '_'); -} - -static inline bool IsADoxygenChar(int ch) { - return (islower(ch) || ch == '$' || ch == '@' || - ch == '\\' || ch == '&' || ch == '<' || - ch == '>' || ch == '#' || ch == '{' || - ch == '}' || ch == '[' || ch == ']'); -} - -static inline bool IsANumberChar(int ch) { - // Not exactly following number definition (several dots are seen as OK, etc.) - // but probably enough in most cases. - return (ch < 0x80) && - (isdigit(ch) || toupper(ch) == 'E' || - ch == '.' || ch == '-' || ch == '+'); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Check if the current content context represent a keyword and set the context state if so. - */ -static void CheckForKeyword(StyleContext& sc, WordList* keywordlists[]) -{ - int length = sc.LengthCurrent() + 1; // +1 for the next char - char* s = new char[length]; - sc.GetCurrentLowered(s, length); - if (keywordlists[0]->InList(s)) - sc.ChangeState(SCE_MYSQL_MAJORKEYWORD); - else - if (keywordlists[1]->InList(s)) - sc.ChangeState(SCE_MYSQL_KEYWORD); - else - if (keywordlists[2]->InList(s)) - sc.ChangeState(SCE_MYSQL_DATABASEOBJECT); - else - if (keywordlists[3]->InList(s)) - sc.ChangeState(SCE_MYSQL_FUNCTION); - else - if (keywordlists[5]->InList(s)) - sc.ChangeState(SCE_MYSQL_PROCEDUREKEYWORD); - else - if (keywordlists[6]->InList(s)) - sc.ChangeState(SCE_MYSQL_USER1); - else - if (keywordlists[7]->InList(s)) - sc.ChangeState(SCE_MYSQL_USER2); - else - if (keywordlists[8]->InList(s)) - sc.ChangeState(SCE_MYSQL_USER3); - delete [] s; -} - -//-------------------------------------------------------------------------------------------------- - -static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) -{ - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) - { - // Determine if the current state should terminate. - switch (sc.state) - { - case SCE_MYSQL_OPERATOR: - sc.SetState(SCE_MYSQL_DEFAULT); - break; - case SCE_MYSQL_NUMBER: - // We stop the number definition on non-numerical non-dot non-eE non-sign char. - if (!IsANumberChar(sc.ch)) - sc.SetState(SCE_MYSQL_DEFAULT); - break; - case SCE_MYSQL_IDENTIFIER: - // Switch from identifier to keyword state and open a new state for the new char. - if (!IsAWordChar(sc.ch)) - { - CheckForKeyword(sc, keywordlists); - - // Additional check for function keywords needed. - // A function name must be followed by an opening parenthesis. - if (sc.state == SCE_MYSQL_FUNCTION && sc.ch != '(') - sc.ChangeState(SCE_MYSQL_DEFAULT); - - sc.SetState(SCE_MYSQL_DEFAULT); - } - break; - case SCE_MYSQL_VARIABLE: - if (!IsAWordChar(sc.ch)) - sc.SetState(SCE_MYSQL_DEFAULT); - break; - case SCE_MYSQL_SYSTEMVARIABLE: - if (!IsAWordChar(sc.ch)) - { - int length = sc.LengthCurrent() + 1; - char* s = new char[length]; - sc.GetCurrentLowered(s, length); - - // Check for known system variables here. - if (keywordlists[4]->InList(&s[2])) - sc.ChangeState(SCE_MYSQL_KNOWNSYSTEMVARIABLE); - delete [] s; - - sc.SetState(SCE_MYSQL_DEFAULT); - } - break; - case SCE_MYSQL_QUOTEDIDENTIFIER: - if (sc.ch == '`') - { - if (sc.chNext == '`') - sc.Forward(); // Ignore it - else - sc.ForwardSetState(SCE_MYSQL_DEFAULT); - } - break; - case SCE_MYSQL_COMMENT: - case SCE_MYSQL_HIDDENCOMMAND: - if (sc.Match('*', '/')) - { - sc.Forward(); - sc.ForwardSetState(SCE_MYSQL_DEFAULT); - } - break; - case SCE_MYSQL_COMMENTLINE: - if (sc.atLineStart) - sc.SetState(SCE_MYSQL_DEFAULT); - break; - case SCE_MYSQL_SQSTRING: - if (sc.ch == '\\') - sc.Forward(); // Escape sequence - else - if (sc.ch == '\'') - { - // End of single quoted string reached? - if (sc.chNext == '\'') - sc.Forward(); - else - sc.ForwardSetState(SCE_MYSQL_DEFAULT); - } - break; - case SCE_MYSQL_DQSTRING: - if (sc.ch == '\\') - sc.Forward(); // Escape sequence - else - if (sc.ch == '\"') - { - // End of single quoted string reached? - if (sc.chNext == '\"') - sc.Forward(); - else - sc.ForwardSetState(SCE_MYSQL_DEFAULT); - } - break; - } - - // Determine if a new state should be entered. - if (sc.state == SCE_MYSQL_DEFAULT) - { - switch (sc.ch) - { - case '@': - if (sc.chNext == '@') - { - sc.SetState(SCE_MYSQL_SYSTEMVARIABLE); - sc.Forward(2); // Skip past @@. - } - else - if (IsAWordStart(sc.ch)) - { - sc.SetState(SCE_MYSQL_VARIABLE); - sc.Forward(); // Skip past @. - } - else - sc.SetState(SCE_MYSQL_OPERATOR); - break; - case '`': - sc.SetState(SCE_MYSQL_QUOTEDIDENTIFIER); - break; - case '#': - sc.SetState(SCE_MYSQL_COMMENTLINE); - break; - case '\'': - sc.SetState(SCE_MYSQL_SQSTRING); - break; - case '\"': - sc.SetState(SCE_MYSQL_DQSTRING); - break; - default: - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) - sc.SetState(SCE_MYSQL_NUMBER); - else - if (IsAWordStart(sc.ch)) - sc.SetState(SCE_MYSQL_IDENTIFIER); - else - if (sc.Match('/', '*')) - { - sc.SetState(SCE_MYSQL_COMMENT); - - // Skip comment introducer and check for hidden command. - sc.Forward(2); - if (sc.ch == '!') - { - sc.ChangeState(SCE_MYSQL_HIDDENCOMMAND); - sc.Forward(); - } - } - else - if (sc.Match("--")) - { - // Special MySQL single line comment. - sc.SetState(SCE_MYSQL_COMMENTLINE); - sc.Forward(2); - - // Check the third character too. It must be a space or EOL. - if (sc.ch != ' ' && sc.ch != '\n' && sc.ch != '\r') - sc.ChangeState(SCE_MYSQL_OPERATOR); - } - else - if (isoperator(static_cast(sc.ch))) - sc.SetState(SCE_MYSQL_OPERATOR); - } - } - } - - // Do a final check for keywords if we currently have an identifier, to highlight them - // also at the end of a line. - if (sc.state == SCE_MYSQL_IDENTIFIER) - { - CheckForKeyword(sc, keywordlists); - - // Additional check for function keywords needed. - // A function name must be followed by an opening parenthesis. - if (sc.state == SCE_MYSQL_FUNCTION && sc.ch != '(') - sc.ChangeState(SCE_MYSQL_DEFAULT); - } - - sc.Complete(); -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Helper function to determine if we have a foldable comment currently. - */ -static bool IsStreamCommentStyle(int style) -{ - return style == SCE_MYSQL_COMMENT; -} - -//-------------------------------------------------------------------------------------------------- - -/** - * Code copied from StyleContext and modified to work here. Should go into Accessor as a - * companion to Match()... - */ -bool MatchIgnoreCase(Accessor &styler, int currentPos, const char *s) -{ - for (int n = 0; *s; n++) - { - if (*s != tolower(styler.SafeGetCharAt(currentPos + n))) - return false; - s++; - } - return true; -} - -//-------------------------------------------------------------------------------------------------- - -// Store both the current line's fold level and the next lines in the -// level store to make it easy to pick up with each increment. -static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) -{ - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldOnlyBegin = styler.GetPropertyInt("fold.sql.only.begin", 0) != 0; - - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16; - int levelNext = levelCurrent; - - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - - bool endFound = false; - bool whenFound = false; - bool elseFound = false; - - char nextChar = styler.SafeGetCharAt(startPos); - for (unsigned int i = startPos; length > 0; i++, length--) - { - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - - char currentChar = nextChar; - nextChar = styler.SafeGetCharAt(i + 1); - bool atEOL = (currentChar == '\r' && nextChar != '\n') || (currentChar == '\n'); - - switch (style) - { - case SCE_MYSQL_COMMENT: - if (foldComment) - { - // Multiline comment style /* .. */. - if (IsStreamCommentStyle(style)) - { - // Increase level if we just start a foldable comment. - if (!IsStreamCommentStyle(stylePrev)) - levelNext++; - else - // If we are in the middle of a foldable comment check if it ends now. - // Don't end at the line end, though. - if (!IsStreamCommentStyle(styleNext) && !atEOL) - levelNext--; - } - } - break; - case SCE_MYSQL_COMMENTLINE: - if (foldComment) - { - // Not really a standard, but we add support for single line comments - // with special curly braces syntax as foldable comments too. - // MySQL needs -- comments to be followed by space or control char - if (styler.Match(i, "--")) - { - char chNext2 = styler.SafeGetCharAt(i + 2); - char chNext3 = styler.SafeGetCharAt(i + 3); - if (chNext2 == '{' || chNext3 == '{') - levelNext++; - else - if (chNext2 == '}' || chNext3 == '}') - levelNext--; - } - } - break; - case SCE_MYSQL_HIDDENCOMMAND: - if (style != stylePrev) - levelNext++; - else - if (style != styleNext) - levelNext--; - break; - case SCE_MYSQL_OPERATOR: - if (currentChar == '(') - levelNext++; - else - if (currentChar == ')') - levelNext--; - break; - case SCE_MYSQL_MAJORKEYWORD: - case SCE_MYSQL_KEYWORD: - case SCE_MYSQL_FUNCTION: - case SCE_MYSQL_PROCEDUREKEYWORD: - // Reserved and other keywords. - if (style != stylePrev) - { - bool beginFound = MatchIgnoreCase(styler, i, "begin"); - bool ifFound = MatchIgnoreCase(styler, i, "if"); - bool thenFound = MatchIgnoreCase(styler, i, "then"); - bool whileFound = MatchIgnoreCase(styler, i, "while"); - bool loopFound = MatchIgnoreCase(styler, i, "loop"); - bool repeatFound = MatchIgnoreCase(styler, i, "repeat"); - - if (!foldOnlyBegin && endFound && (ifFound || whileFound || loopFound)) - { - endFound = false; - levelNext--; - if (levelNext < SC_FOLDLEVELBASE) - levelNext = SC_FOLDLEVELBASE; - - // Note that "else" is special here. It may or may not be followed by an "if .. then", - // but in any case the level stays the same. When followed by an "if .. then" the level - // will be increased later, if not, then at eol. - } - else - if (!foldOnlyBegin && MatchIgnoreCase(styler, i, "else")) - { - levelNext--; - elseFound = true; - } - else - if (!foldOnlyBegin && thenFound) - { - if (whenFound) - whenFound = false; - else - levelNext++; - } - else - if (ifFound) - elseFound = false; - else - if (MatchIgnoreCase(styler, i, "when")) - whenFound = true; - else - { - if (beginFound) - levelNext++; - else - if (!foldOnlyBegin && (loopFound || repeatFound || whileFound)) - { - if (endFound) - endFound = false; - else - levelNext++; - } - else - if (MatchIgnoreCase(styler, i, "end")) - { - // Multiple "end" in a row are counted multiple times! - if (endFound) - { - levelNext--; - if (levelNext < SC_FOLDLEVELBASE) - levelNext = SC_FOLDLEVELBASE; - } - endFound = true; - whenFound = false; - } - } - } - break; - } - - // Handle the case of a trailing end without an if / while etc, as in the case of a begin. - if (endFound) - { - endFound = false; - levelNext--; - if (levelNext < SC_FOLDLEVELBASE) - levelNext = SC_FOLDLEVELBASE; - } - - if (atEOL) - { - if (elseFound) - { - levelNext++; - elseFound = false; - } - - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) - styler.SetLevel(lineCurrent, lev); - - lineCurrent++; - levelCurrent = levelNext; - visibleChars = 0; - endFound = false; - whenFound = false; - } - - if (!isspacechar(currentChar)) - visibleChars++; - } -} - -//-------------------------------------------------------------------------------------------------- - -static const char * const mysqlWordListDesc[] = { - "Major Keywords", - "Keywords", - "Database Objects", - "Functions", - "System Variables", - "Procedure keywords", - "User Keywords 1", - "User Keywords 2", - "User Keywords 3", - 0 -}; - -LexerModule lmMySQL(SCLEX_MYSQL, ColouriseMySQLDoc, "mysql", FoldMySQLDoc, mysqlWordListDesc); diff --git a/src/LexNimrod.cxx b/src/LexNimrod.cxx deleted file mode 100644 index 8c4d04360..000000000 --- a/src/LexNimrod.cxx +++ /dev/null @@ -1,430 +0,0 @@ -// Scintilla source code edit control -// Nimrod lexer -// (c) 2009 Andreas Rumpf -/** @file LexNimrod.cxx - ** Lexer for Nimrod. - **/ -// Copyright 1998-2002 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(int ch) { - return (ch >= 0x80) || isalnum(ch) || ch == '_'; -} - -static int tillEndOfTripleQuote(Accessor &styler, int pos, int max) { - /* search for """ */ - for (;;) { - if (styler.SafeGetCharAt(pos, '\0') == '\0') return pos; - if (pos >= max) return pos; - if (styler.Match(pos, "\"\"\"")) { - return pos + 2; - } - pos++; - } -} - -#define CR 13 /* use both because Scite allows changing the line ending */ -#define LF 10 - -static bool inline isNewLine(int ch) { - return ch == CR || ch == LF; -} - -static int scanString(Accessor &styler, int pos, int max, bool rawMode) { - for (;;) { - if (pos >= max) return pos; - char ch = styler.SafeGetCharAt(pos, '\0'); - if (ch == CR || ch == LF || ch == '\0') return pos; - if (ch == '"') return pos; - if (ch == '\\' && !rawMode) { - pos += 2; - } else { - pos++; - } - } -} - -static int scanChar(Accessor &styler, int pos, int max) { - for (;;) { - if (pos >= max) return pos; - char ch = styler.SafeGetCharAt(pos, '\0'); - if (ch == CR || ch == LF || ch == '\0') return pos; - if (ch == '\'' && !isalnum(styler.SafeGetCharAt(pos+1, '\0')) ) - return pos; - if (ch == '\\') { - pos += 2; - } else { - pos++; - } - } -} - -static int scanIdent(Accessor &styler, int pos, WordList &keywords) { - char buf[100]; /* copy to lowercase and ignore underscores */ - int i = 0; - - for (;;) { - char ch = styler.SafeGetCharAt(pos, '\0'); - if (!IsAWordChar(ch)) break; - if (ch != '_' && i < ((int)sizeof(buf))-1) { - buf[i] = static_cast(tolower(ch)); - i++; - } - pos++; - } - buf[i] = '\0'; - /* look for keyword */ - if (keywords.InList(buf)) { - styler.ColourTo(pos-1, SCE_P_WORD); - } else { - styler.ColourTo(pos-1, SCE_P_IDENTIFIER); - } - return pos; -} - -static int scanNumber(Accessor &styler, int pos) { - char ch, ch2; - ch = styler.SafeGetCharAt(pos, '\0'); - ch2 = styler.SafeGetCharAt(pos+1, '\0'); - if (ch == '0' && (ch2 == 'b' || ch2 == 'B')) { - /* binary number: */ - pos += 2; - for (;;) { - ch = styler.SafeGetCharAt(pos, '\0'); - if (ch == '_' || (ch >= '0' && ch <= '1')) ++pos; - else break; - } - } else if (ch == '0' && - (ch2 == 'o' || ch2 == 'O' || ch2 == 'c' || ch2 == 'C')) { - /* octal number: */ - pos += 2; - for (;;) { - ch = styler.SafeGetCharAt(pos, '\0'); - if (ch == '_' || (ch >= '0' && ch <= '7')) ++pos; - else break; - } - } else if (ch == '0' && (ch2 == 'x' || ch2 == 'X')) { - /* hexadecimal number: */ - pos += 2; - for (;;) { - ch = styler.SafeGetCharAt(pos, '\0'); - if (ch == '_' || (ch >= '0' && ch <= '9') - || (ch >= 'a' && ch <= 'f') - || (ch >= 'A' && ch <= 'F')) ++pos; - else break; - } - } else { - // skip decimal part: - for (;;) { - ch = styler.SafeGetCharAt(pos, '\0'); - if (ch == '_' || (ch >= '0' && ch <= '9')) ++pos; - else break; - } - ch2 = styler.SafeGetCharAt(pos+1, '\0'); - if (ch == '.' && ch2 >= '0' && ch2 <= '9') { - ++pos; // skip '.' - for (;;) { - ch = styler.SafeGetCharAt(pos, '\0'); - if (ch == '_' || (ch >= '0' && ch <= '9')) ++pos; - else break; - } - } - if (ch == 'e' || ch == 'E') { - ++pos; - ch = styler.SafeGetCharAt(pos, '\0'); - if (ch == '-' || ch == '+') ++pos; - for (;;) { - ch = styler.SafeGetCharAt(pos, '\0'); - if (ch == '_' || (ch >= '0' && ch <= '9')) ++pos; - else break; - } - } - } - if (ch == '\'') { - /* a type suffix: */ - pos++; - for (;;) { - ch = styler.SafeGetCharAt(pos); - if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') - || (ch >= 'a' && ch <= 'z') || ch == '_') ++pos; - else break; - } - } - styler.ColourTo(pos-1, SCE_P_NUMBER); - return pos; -} - -/* rewritten from scratch, because I couldn't get rid of the bugs... - (A character based approach sucks!) -*/ -static void ColouriseNimrodDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - int pos = startPos; - int max = startPos + length; - char ch; - WordList &keywords = *keywordlists[0]; - - styler.StartAt(startPos); - styler.StartSegment(startPos); - - switch (initStyle) { - /* check where we are: */ - case SCE_P_TRIPLEDOUBLE: - pos = tillEndOfTripleQuote(styler, pos, max); - styler.ColourTo(pos, SCE_P_TRIPLEDOUBLE); - pos++; - break; - default: /* nothing to do: */ - break; - } - while (pos < max) { - ch = styler.SafeGetCharAt(pos, '\0'); - switch (ch) { - case '\0': return; - case '#': { - bool doccomment = (styler.SafeGetCharAt(pos+1) == '#'); - while (pos < max && !isNewLine(styler.SafeGetCharAt(pos, LF))) pos++; - if (doccomment) - styler.ColourTo(pos, SCE_C_COMMENTLINEDOC); - else - styler.ColourTo(pos, SCE_P_COMMENTLINE); - } break; - case 'r': case 'R': { - if (styler.SafeGetCharAt(pos+1) == '"') { - pos = scanString(styler, pos+2, max, true); - styler.ColourTo(pos, SCE_P_STRING); - pos++; - } else { - pos = scanIdent(styler, pos, keywords); - } - } break; - case '"': - if (styler.Match(pos+1, "\"\"")) { - pos = tillEndOfTripleQuote(styler, pos+3, max); - styler.ColourTo(pos, SCE_P_TRIPLEDOUBLE); - } else { - pos = scanString(styler, pos+1, max, false); - styler.ColourTo(pos, SCE_P_STRING); - } - pos++; - break; - case '\'': - pos = scanChar(styler, pos+1, max); - styler.ColourTo(pos, SCE_P_CHARACTER); - pos++; - break; - default: // identifers, numbers, operators, whitespace - if (ch >= '0' && ch <= '9') { - pos = scanNumber(styler, pos); - } else if (IsAWordChar(ch)) { - pos = scanIdent(styler, pos, keywords); - } else if (ch == '`') { - pos++; - while (pos < max) { - ch = styler.SafeGetCharAt(pos, LF); - if (ch == '`') { - ++pos; - break; - } - if (ch == CR || ch == LF) break; - ++pos; - } - styler.ColourTo(pos, SCE_P_IDENTIFIER); - } else if (strchr("()[]{}:=;-\\/&%$!+<>|^?,.*~@", ch)) { - styler.ColourTo(pos, SCE_P_OPERATOR); - pos++; - } else { - styler.ColourTo(pos, SCE_P_DEFAULT); - pos++; - } - break; - } - } -} - -static bool IsCommentLine(int line, Accessor &styler) { - int pos = styler.LineStart(line); - int eol_pos = styler.LineStart(line + 1) - 1; - for (int i = pos; i < eol_pos; i++) { - char ch = styler[i]; - if (ch == '#') - return true; - else if (ch != ' ' && ch != '\t') - return false; - } - return false; -} - -static bool IsQuoteLine(int line, Accessor &styler) { - int style = styler.StyleAt(styler.LineStart(line)) & 31; - return ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE)); -} - - -static void FoldNimrodDoc(unsigned int startPos, int length, - int /*initStyle - unused*/, - WordList *[], Accessor &styler) { - const int maxPos = startPos + length; - const int maxLines = styler.GetLine(maxPos - 1); // Requested last line - const int docLines = styler.GetLine(styler.Length() - 1); // Available last line - const bool foldComment = styler.GetPropertyInt("fold.comment.nimrod") != 0; - const bool foldQuotes = styler.GetPropertyInt("fold.quotes.nimrod") != 0; - - // Backtrack to previous non-blank line so we can determine indent level - // for any white space lines (needed esp. within triple quoted strings) - // and so we can fix any preceding fold level (which is why we go back - // at least one line in all cases) - int spaceFlags = 0; - int lineCurrent = styler.GetLine(startPos); - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); - while (lineCurrent > 0) { - lineCurrent--; - indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); - if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) && - (!IsCommentLine(lineCurrent, styler)) && - (!IsQuoteLine(lineCurrent, styler))) - break; - } - int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; - - // Set up initial loop state - startPos = styler.LineStart(lineCurrent); - int prev_state = SCE_P_DEFAULT & 31; - if (lineCurrent >= 1) - prev_state = styler.StyleAt(startPos - 1) & 31; - int prevQuote = foldQuotes && ((prev_state == SCE_P_TRIPLE) || - (prev_state == SCE_P_TRIPLEDOUBLE)); - int prevComment = 0; - if (lineCurrent >= 1) - prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler); - - // Process all characters to end of requested range or end of any triple quote - // or comment that hangs over the end of the range. Cap processing in all cases - // to end of document (in case of unclosed quote or comment at end). - while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || - prevQuote || prevComment)) { - - // Gather info - int lev = indentCurrent; - int lineNext = lineCurrent + 1; - int indentNext = indentCurrent; - int quote = false; - if (lineNext <= docLines) { - // Information about next line is only available if not at end of document - indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); - int style = styler.StyleAt(styler.LineStart(lineNext)) & 31; - quote = foldQuotes && ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE)); - } - const int quote_start = (quote && !prevQuote); - const int quote_continue = (quote && prevQuote); - const int comment = foldComment && IsCommentLine(lineCurrent, styler); - const int comment_start = (comment && !prevComment && (lineNext <= docLines) && - IsCommentLine(lineNext, styler) && - (lev > SC_FOLDLEVELBASE)); - const int comment_continue = (comment && prevComment); - if ((!quote || !prevQuote) && !comment) - indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; - if (quote) - indentNext = indentCurrentLevel; - if (indentNext & SC_FOLDLEVELWHITEFLAG) - indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel; - - if (quote_start) { - // Place fold point at start of triple quoted string - lev |= SC_FOLDLEVELHEADERFLAG; - } else if (quote_continue || prevQuote) { - // Add level to rest of lines in the string - lev = lev + 1; - } else if (comment_start) { - // Place fold point at start of a block of comments - lev |= SC_FOLDLEVELHEADERFLAG; - } else if (comment_continue) { - // Add level to rest of lines in the block - lev = lev + 1; - } - - // Skip past any blank lines for next indent level info; we skip also - // comments (all comments, not just those starting in column 0) - // which effectively folds them into surrounding code rather - // than screwing up folding. - - while (!quote && - (lineNext < docLines) && - ((indentNext & SC_FOLDLEVELWHITEFLAG) || - (lineNext <= docLines && IsCommentLine(lineNext, styler)))) { - - lineNext++; - indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); - } - - const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK; - const int levelBeforeComments = - Platform::Maximum(indentCurrentLevel,levelAfterComments); - - // Now set all the indent levels on the lines we skipped - // Do this from end to start. Once we encounter one line - // which is indented more than the line after the end of - // the comment-block, use the level of the block before - - int skipLine = lineNext; - int skipLevel = levelAfterComments; - - while (--skipLine > lineCurrent) { - int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL); - - if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments) - skipLevel = levelBeforeComments; - - int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG; - - styler.SetLevel(skipLine, skipLevel | whiteFlag); - } - - // Set fold header on non-quote/non-comment line - if (!quote && !comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG) ) { - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < - (indentNext & SC_FOLDLEVELNUMBERMASK)) - lev |= SC_FOLDLEVELHEADERFLAG; - } - - // Keep track of triple quote and block comment state of previous line - prevQuote = quote; - prevComment = comment_start || comment_continue; - - // Set fold level for this line and move to next line - styler.SetLevel(lineCurrent, lev); - indentCurrent = indentNext; - lineCurrent = lineNext; - } - - // NOTE: Cannot set level of last line here because indentCurrent doesn't have - // header flag set; the loop above is crafted to take care of this case! - //styler.SetLevel(lineCurrent, indentCurrent); -} - -static const char * const nimrodWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmNimrod(SCLEX_NIMROD, ColouriseNimrodDoc, "nimrod", FoldNimrodDoc, - nimrodWordListDesc); diff --git a/src/LexNsis.cxx b/src/LexNsis.cxx deleted file mode 100644 index 43ddc4706..000000000 --- a/src/LexNsis.cxx +++ /dev/null @@ -1,655 +0,0 @@ -// Scintilla source code edit control -/** @file LexNsis.cxx - ** Lexer for NSIS - **/ -// Copyright 2003 - 2005 by Angelo Mandato -// Last Updated: 03/13/2005 -// The License.txt file describes the conditions under which this software may be distributed. -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "CharClassify.h" -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/* -// located in SciLexer.h -#define SCLEX_NSIS 43 - -#define SCE_NSIS_DEFAULT 0 -#define SCE_NSIS_COMMENT 1 -#define SCE_NSIS_STRINGDQ 2 -#define SCE_NSIS_STRINGLQ 3 -#define SCE_NSIS_STRINGRQ 4 -#define SCE_NSIS_FUNCTION 5 -#define SCE_NSIS_VARIABLE 6 -#define SCE_NSIS_LABEL 7 -#define SCE_NSIS_USERDEFINED 8 -#define SCE_NSIS_SECTIONDEF 9 -#define SCE_NSIS_SUBSECTIONDEF 10 -#define SCE_NSIS_IFDEFINEDEF 11 -#define SCE_NSIS_MACRODEF 12 -#define SCE_NSIS_STRINGVAR 13 -#define SCE_NSIS_NUMBER 14 -// ADDED for Scintilla v1.63 -#define SCE_NSIS_SECTIONGROUP 15 -#define SCE_NSIS_PAGEEX 16 -#define SCE_NSIS_FUNCTIONDEF 17 -#define SCE_NSIS_COMMENTBOX 18 -*/ - -static bool isNsisNumber(char ch) -{ - return (ch >= '0' && ch <= '9'); -} - -static bool isNsisChar(char ch) -{ - return (ch == '.' ) || (ch == '_' ) || isNsisNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); -} - -static bool isNsisLetter(char ch) -{ - return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); -} - -static bool NsisNextLineHasElse(unsigned int start, unsigned int end, Accessor &styler) -{ - int nNextLine = -1; - for( unsigned int i = start; i < end; i++ ) - { - char cNext = styler.SafeGetCharAt( i ); - if( cNext == '\n' ) - { - nNextLine = i+1; - break; - } - } - - if( nNextLine == -1 ) // We never found the next line... - return false; - - for( unsigned int firstChar = nNextLine; firstChar < end; firstChar++ ) - { - char cNext = styler.SafeGetCharAt( firstChar ); - if( cNext == ' ' ) - continue; - if( cNext == '\t' ) - continue; - if( cNext == '!' ) - { - if( styler.Match(firstChar, "!else") ) - return true; - } - break; - } - - return false; -} - -static int NsisCmp( const char *s1, const char *s2, bool bIgnoreCase ) -{ - if( bIgnoreCase ) - return CompareCaseInsensitive( s1, s2); - - return strcmp( s1, s2 ); -} - -static int calculateFoldNsis(unsigned int start, unsigned int end, int foldlevel, Accessor &styler, bool bElse, bool foldUtilityCmd ) -{ - int style = styler.StyleAt(end); - - // If the word is too long, it is not what we are looking for - if( end - start > 20 ) - return foldlevel; - - if( foldUtilityCmd ) - { - // Check the style at this point, if it is not valid, then return zero - if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF && - style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_IFDEFINEDEF && - style != SCE_NSIS_MACRODEF && style != SCE_NSIS_SECTIONGROUP && - style != SCE_NSIS_PAGEEX ) - return foldlevel; - } - else - { - if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF && - style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_SECTIONGROUP && - style != SCE_NSIS_PAGEEX ) - return foldlevel; - } - - int newFoldlevel = foldlevel; - bool bIgnoreCase = false; - if( styler.GetPropertyInt("nsis.ignorecase") == 1 ) - bIgnoreCase = true; - - char s[20]; // The key word we are looking for has atmost 13 characters - for (unsigned int i = 0; i < end - start + 1 && i < 19; i++) - { - s[i] = static_cast( styler[ start + i ] ); - s[i + 1] = '\0'; - } - - if( s[0] == '!' ) - { - if( NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifmacrodef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifmacrondef", bIgnoreCase ) == 0 || NsisCmp(s, "!if", bIgnoreCase ) == 0 || NsisCmp(s, "!macro", bIgnoreCase ) == 0 ) - newFoldlevel++; - else if( NsisCmp(s, "!endif", bIgnoreCase) == 0 || NsisCmp(s, "!macroend", bIgnoreCase ) == 0 ) - newFoldlevel--; - else if( bElse && NsisCmp(s, "!else", bIgnoreCase) == 0 ) - newFoldlevel++; - } - else - { - if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionGroup", bIgnoreCase ) == 0 || NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "SubSection", bIgnoreCase ) == 0 || NsisCmp(s, "PageEx", bIgnoreCase ) == 0 ) - newFoldlevel++; - else if( NsisCmp(s, "SectionGroupEnd", bIgnoreCase ) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "PageExEnd", bIgnoreCase ) == 0 ) - newFoldlevel--; - } - - return newFoldlevel; -} - -static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler ) -{ - bool bIgnoreCase = false; - if( styler.GetPropertyInt("nsis.ignorecase") == 1 ) - bIgnoreCase = true; - - bool bUserVars = false; - if( styler.GetPropertyInt("nsis.uservars") == 1 ) - bUserVars = true; - - char s[100]; - - WordList &Functions = *keywordLists[0]; - WordList &Variables = *keywordLists[1]; - WordList &Lables = *keywordLists[2]; - WordList &UserDefined = *keywordLists[3]; - - for (unsigned int i = 0; i < end - start + 1 && i < 99; i++) - { - if( bIgnoreCase ) - s[i] = static_cast( tolower(styler[ start + i ] ) ); - else - s[i] = static_cast( styler[ start + i ] ); - s[i + 1] = '\0'; - } - - // Check for special words... - if( NsisCmp(s, "!macro", bIgnoreCase ) == 0 || NsisCmp(s, "!macroend", bIgnoreCase) == 0 ) // Covers !macro and !macroend - return SCE_NSIS_MACRODEF; - - if( NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!endif", bIgnoreCase) == 0 ) // Covers !ifdef, !ifndef and !endif - return SCE_NSIS_IFDEFINEDEF; - - if( NsisCmp(s, "!if", bIgnoreCase ) == 0 || NsisCmp(s, "!else", bIgnoreCase ) == 0 ) // Covers !if and else - return SCE_NSIS_IFDEFINEDEF; - - if (NsisCmp(s, "!ifmacrodef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifmacrondef", bIgnoreCase ) == 0 ) // Covers !ifmacrodef and !ifnmacrodef - return SCE_NSIS_IFDEFINEDEF; - - if( NsisCmp(s, "SectionGroup", bIgnoreCase) == 0 || NsisCmp(s, "SectionGroupEnd", bIgnoreCase) == 0 ) // Covers SectionGroup and SectionGroupEnd - return SCE_NSIS_SECTIONGROUP; - - if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase) == 0 ) // Covers Section and SectionEnd - return SCE_NSIS_SECTIONDEF; - - if( NsisCmp(s, "SubSection", bIgnoreCase) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase) == 0 ) // Covers SubSection and SubSectionEnd - return SCE_NSIS_SUBSECTIONDEF; - - if( NsisCmp(s, "PageEx", bIgnoreCase) == 0 || NsisCmp(s, "PageExEnd", bIgnoreCase) == 0 ) // Covers PageEx and PageExEnd - return SCE_NSIS_PAGEEX; - - if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 ) // Covers Function and FunctionEnd - return SCE_NSIS_FUNCTIONDEF; - - if ( Functions.InList(s) ) - return SCE_NSIS_FUNCTION; - - if ( Variables.InList(s) ) - return SCE_NSIS_VARIABLE; - - if ( Lables.InList(s) ) - return SCE_NSIS_LABEL; - - if( UserDefined.InList(s) ) - return SCE_NSIS_USERDEFINED; - - if( strlen(s) > 3 ) - { - if( s[1] == '{' && s[strlen(s)-1] == '}' ) - return SCE_NSIS_VARIABLE; - } - - // See if the variable is a user defined variable - if( s[0] == '$' && bUserVars ) - { - bool bHasSimpleNsisChars = true; - for (unsigned int j = 1; j < end - start + 1 && j < 99; j++) - { - if( !isNsisChar( s[j] ) ) - { - bHasSimpleNsisChars = false; - break; - } - } - - if( bHasSimpleNsisChars ) - return SCE_NSIS_VARIABLE; - } - - // To check for numbers - if( isNsisNumber( s[0] ) ) - { - bool bHasSimpleNsisNumber = true; - for (unsigned int j = 1; j < end - start + 1 && j < 99; j++) - { - if( !isNsisNumber( s[j] ) ) - { - bHasSimpleNsisNumber = false; - break; - } - } - - if( bHasSimpleNsisNumber ) - return SCE_NSIS_NUMBER; - } - - return SCE_NSIS_DEFAULT; -} - -static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) -{ - int state = SCE_NSIS_DEFAULT; - if( startPos > 0 ) - state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox - - styler.StartAt( startPos ); - styler.GetLine( startPos ); - - unsigned int nLengthDoc = startPos + length; - styler.StartSegment( startPos ); - - char cCurrChar; - bool bVarInString = false; - bool bClassicVarInString = false; - - unsigned int i; - for( i = startPos; i < nLengthDoc; i++ ) - { - cCurrChar = styler.SafeGetCharAt( i ); - char cNextChar = styler.SafeGetCharAt(i+1); - - switch(state) - { - case SCE_NSIS_DEFAULT: - if( cCurrChar == ';' || cCurrChar == '#' ) // we have a comment line - { - styler.ColourTo(i-1, state ); - state = SCE_NSIS_COMMENT; - break; - } - if( cCurrChar == '"' ) - { - styler.ColourTo(i-1, state ); - state = SCE_NSIS_STRINGDQ; - bVarInString = false; - bClassicVarInString = false; - break; - } - if( cCurrChar == '\'' ) - { - styler.ColourTo(i-1, state ); - state = SCE_NSIS_STRINGRQ; - bVarInString = false; - bClassicVarInString = false; - break; - } - if( cCurrChar == '`' ) - { - styler.ColourTo(i-1, state ); - state = SCE_NSIS_STRINGLQ; - bVarInString = false; - bClassicVarInString = false; - break; - } - - // NSIS KeyWord,Function, Variable, UserDefined: - if( cCurrChar == '$' || isNsisChar(cCurrChar) || cCurrChar == '!' ) - { - styler.ColourTo(i-1,state); - state = SCE_NSIS_FUNCTION; - - // If it is a number, we must check and set style here first... - if( isNsisNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) ) - styler.ColourTo( i, SCE_NSIS_NUMBER); - - break; - } - - if( cCurrChar == '/' && cNextChar == '*' ) - { - styler.ColourTo(i-1,state); - state = SCE_NSIS_COMMENTBOX; - break; - } - - break; - case SCE_NSIS_COMMENT: - if( cNextChar == '\n' || cNextChar == '\r' ) - { - // Special case: - if( cCurrChar == '\\' ) - { - styler.ColourTo(i-2,state); - styler.ColourTo(i,SCE_NSIS_DEFAULT); - } - else - { - styler.ColourTo(i,state); - state = SCE_NSIS_DEFAULT; - } - } - break; - case SCE_NSIS_STRINGDQ: - case SCE_NSIS_STRINGLQ: - case SCE_NSIS_STRINGRQ: - - if( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' ) - break; // Ignore the next character, even if it is a quote of some sort - - if( cCurrChar == '"' && state == SCE_NSIS_STRINGDQ ) - { - styler.ColourTo(i,state); - state = SCE_NSIS_DEFAULT; - break; - } - - if( cCurrChar == '`' && state == SCE_NSIS_STRINGLQ ) - { - styler.ColourTo(i,state); - state = SCE_NSIS_DEFAULT; - break; - } - - if( cCurrChar == '\'' && state == SCE_NSIS_STRINGRQ ) - { - styler.ColourTo(i,state); - state = SCE_NSIS_DEFAULT; - break; - } - - if( cNextChar == '\r' || cNextChar == '\n' ) - { - int nCurLine = styler.GetLine(i+1); - int nBack = i; - // We need to check if the previous line has a \ in it... - bool bNextLine = false; - - while( nBack > 0 ) - { - if( styler.GetLine(nBack) != nCurLine ) - break; - - char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here - - if( cTemp == '\\' ) - { - bNextLine = true; - break; - } - if( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' ) - break; - - nBack--; - } - - if( bNextLine ) - { - styler.ColourTo(i+1,state); - } - if( bNextLine == false ) - { - styler.ColourTo(i,state); - state = SCE_NSIS_DEFAULT; - } - } - break; - - case SCE_NSIS_FUNCTION: - - // NSIS KeyWord: - if( cCurrChar == '$' ) - state = SCE_NSIS_DEFAULT; - else if( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) ) - state = SCE_NSIS_DEFAULT; - else if( (isNsisChar(cCurrChar) && !isNsisChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' ) - { - state = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler ); - styler.ColourTo( i, state); - state = SCE_NSIS_DEFAULT; - } - else if( !isNsisChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' ) - { - if( classifyWordNsis( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_NSIS_NUMBER ) - styler.ColourTo( i-1, SCE_NSIS_NUMBER ); - - state = SCE_NSIS_DEFAULT; - - if( cCurrChar == '"' ) - { - state = SCE_NSIS_STRINGDQ; - bVarInString = false; - bClassicVarInString = false; - } - else if( cCurrChar == '`' ) - { - state = SCE_NSIS_STRINGLQ; - bVarInString = false; - bClassicVarInString = false; - } - else if( cCurrChar == '\'' ) - { - state = SCE_NSIS_STRINGRQ; - bVarInString = false; - bClassicVarInString = false; - } - else if( cCurrChar == '#' || cCurrChar == ';' ) - { - state = SCE_NSIS_COMMENT; - } - } - break; - case SCE_NSIS_COMMENTBOX: - - if( styler.SafeGetCharAt(i-1) == '*' && cCurrChar == '/' ) - { - styler.ColourTo(i,state); - state = SCE_NSIS_DEFAULT; - } - break; - } - - if( state == SCE_NSIS_COMMENT || state == SCE_NSIS_COMMENTBOX ) - { - styler.ColourTo(i,state); - } - else if( state == SCE_NSIS_STRINGDQ || state == SCE_NSIS_STRINGLQ || state == SCE_NSIS_STRINGRQ ) - { - bool bIngoreNextDollarSign = false; - bool bUserVars = false; - if( styler.GetPropertyInt("nsis.uservars") == 1 ) - bUserVars = true; - - if( bVarInString && cCurrChar == '$' ) - { - bVarInString = false; - bIngoreNextDollarSign = true; - } - else if( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) ) - { - styler.ColourTo( i+1, SCE_NSIS_STRINGVAR); - bVarInString = false; - bIngoreNextDollarSign = false; - } - - // Covers "$INSTDIR and user vars like $MYVAR" - else if( bVarInString && !isNsisChar(cNextChar) ) - { - int nWordState = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler); - if( nWordState == SCE_NSIS_VARIABLE ) - styler.ColourTo( i, SCE_NSIS_STRINGVAR); - else if( bUserVars ) - styler.ColourTo( i, SCE_NSIS_STRINGVAR); - bVarInString = false; - } - // Covers "${TEST}..." - else if( bClassicVarInString && cNextChar == '}' ) - { - styler.ColourTo( i+1, SCE_NSIS_STRINGVAR); - bClassicVarInString = false; - } - - // Start of var in string - if( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' ) - { - styler.ColourTo( i-1, state); - bClassicVarInString = true; - bVarInString = false; - } - else if( !bIngoreNextDollarSign && cCurrChar == '$' ) - { - styler.ColourTo( i-1, state); - bVarInString = true; - bClassicVarInString = false; - } - } - } - - // Colourise remaining document - styler.ColourTo(nLengthDoc-1,state); -} - -static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) -{ - // No folding enabled, no reason to continue... - if( styler.GetPropertyInt("fold") == 0 ) - return; - - bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1; - bool foldUtilityCmd = styler.GetPropertyInt("nsis.foldutilcmd", 1) == 1; - bool blockComment = false; - - int lineCurrent = styler.GetLine(startPos); - unsigned int safeStartPos = styler.LineStart( lineCurrent ); - - bool bArg1 = true; - int nWordStart = -1; - - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelNext = levelCurrent; - int style = styler.StyleAt(safeStartPos); - if( style == SCE_NSIS_COMMENTBOX ) - { - if( styler.SafeGetCharAt(safeStartPos) == '/' && styler.SafeGetCharAt(safeStartPos+1) == '*' ) - levelNext++; - blockComment = true; - } - - for (unsigned int i = safeStartPos; i < startPos + length; i++) - { - char chCurr = styler.SafeGetCharAt(i); - style = styler.StyleAt(i); - if( blockComment && style != SCE_NSIS_COMMENTBOX ) - { - levelNext--; - blockComment = false; - } - else if( !blockComment && style == SCE_NSIS_COMMENTBOX ) - { - levelNext++; - blockComment = true; - } - - if( bArg1 && !blockComment) - { - if( nWordStart == -1 && (isNsisLetter(chCurr) || chCurr == '!') ) - { - nWordStart = i; - } - else if( isNsisLetter(chCurr) == false && nWordStart > -1 ) - { - int newLevel = calculateFoldNsis( nWordStart, i-1, levelNext, styler, foldAtElse, foldUtilityCmd ); - - if( newLevel == levelNext ) - { - if( foldAtElse && foldUtilityCmd ) - { - if( NsisNextLineHasElse(i, startPos + length, styler) ) - levelNext--; - } - } - else - levelNext = newLevel; - bArg1 = false; - } - } - - if( chCurr == '\n' ) - { - if( bArg1 && foldAtElse && foldUtilityCmd && !blockComment ) - { - if( NsisNextLineHasElse(i, startPos + length, styler) ) - levelNext--; - } - - // If we are on a new line... - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - if (levelUse < levelNext ) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) - styler.SetLevel(lineCurrent, lev); - - lineCurrent++; - levelCurrent = levelNext; - bArg1 = true; // New line, lets look at first argument again - nWordStart = -1; - } - } - - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) - styler.SetLevel(lineCurrent, lev); -} - -static const char * const nsisWordLists[] = { - "Functions", - "Variables", - "Lables", - "UserDefined", - 0, }; - - -LexerModule lmNsis(SCLEX_NSIS, ColouriseNsisDoc, "nsis", FoldNsisDoc, nsisWordLists); - diff --git a/src/LexOpal.cxx b/src/LexOpal.cxx deleted file mode 100644 index 46cf43f7c..000000000 --- a/src/LexOpal.cxx +++ /dev/null @@ -1,522 +0,0 @@ -// Scintilla source code edit control -/** @file LexOpal.cxx - ** Lexer for OPAL (functional language similar to Haskell) - ** Written by Sebastian Pipping - **/ - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "StyleContext.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -inline static void getRange( unsigned int start, unsigned int end, Accessor & styler, char * s, unsigned int len ) -{ - unsigned int i = 0; - while( ( i < end - start + 1 ) && ( i < len - 1 ) ) - { - s[i] = static_cast( styler[ start + i ] ); - i++; - } - s[ i ] = '\0'; -} - -inline bool HandleString( unsigned int & cur, unsigned int one_too_much, Accessor & styler ) -{ - char ch; - - // Wait for string to close - bool even_backslash_count = true; // Without gaps in between - cur++; // Skip initial quote - for( ; ; ) - { - if( cur >= one_too_much ) - { - styler.ColourTo( cur - 1, SCE_OPAL_STRING ); - return false; // STOP - } - - ch = styler.SafeGetCharAt( cur ); - if( ( ch == '\015' ) || ( ch == '\012' ) ) // Deny multi-line strings - { - styler.ColourTo( cur - 1, SCE_OPAL_STRING ); - styler.StartSegment( cur ); - return true; - } - else - { - if( even_backslash_count ) - { - if( ch == '"' ) - { - styler.ColourTo( cur, SCE_OPAL_STRING ); - cur++; - if( cur >= one_too_much ) - { - return false; // STOP - } - else - { - styler.StartSegment( cur ); - return true; - } - } - else if( ch == '\\' ) - { - even_backslash_count = false; - } - } - else - { - even_backslash_count = true; - } - } - - cur++; - } -} - -inline bool HandleCommentBlock( unsigned int & cur, unsigned int one_too_much, Accessor & styler, bool could_fail ) -{ - char ch; - - if( could_fail ) - { - cur++; - if( cur >= one_too_much ) - { - styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); - return false; // STOP - } - - ch = styler.SafeGetCharAt( cur ); - if( ch != '*' ) - { - styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); - styler.StartSegment( cur ); - return true; - } - } - - // Wait for comment close - cur++; - bool star_found = false; - for( ; ; ) - { - if( cur >= one_too_much ) - { - styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_BLOCK ); - return false; // STOP - } - - ch = styler.SafeGetCharAt( cur ); - if( star_found ) - { - if( ch == '/' ) - { - styler.ColourTo( cur, SCE_OPAL_COMMENT_BLOCK ); - cur++; - if( cur >= one_too_much ) - { - return false; // STOP - } - else - { - styler.StartSegment( cur ); - return true; - } - } - else if( ch != '*' ) - { - star_found = false; - } - } - else if( ch == '*' ) - { - star_found = true; - } - cur++; - } -} - -inline bool HandleCommentLine( unsigned int & cur, unsigned int one_too_much, Accessor & styler, bool could_fail ) -{ - char ch; - - if( could_fail ) - { - cur++; - if( cur >= one_too_much ) - { - styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); - return false; // STOP - } - - ch = styler.SafeGetCharAt( cur ); - if( ch != '-' ) - { - styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); - styler.StartSegment( cur ); - return true; - } - - cur++; - if( cur >= one_too_much ) - { - styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); - return false; // STOP - } - - ch = styler.SafeGetCharAt( cur ); - if( ( ch != ' ' ) && ( ch != '\t' ) ) - { - styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); - styler.StartSegment( cur ); - return true; - } - } - - // Wait for end of line - bool fifteen_found = false; - - for( ; ; ) - { - cur++; - - if( cur >= one_too_much ) - { - styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE ); - return false; // STOP - } - - ch = styler.SafeGetCharAt( cur ); - if( fifteen_found ) - { -/* - if( ch == '\012' ) - { - // One newline on Windows (015, 012) - } - else - { - // One newline on MAC (015) and another char - } -*/ - cur--; - styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE ); - styler.StartSegment( cur ); - return true; - } - else - { - if( ch == '\015' ) - { - fifteen_found = true; - } - else if( ch == '\012' ) - { - // One newline on Linux (012) - styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE ); - styler.StartSegment( cur ); - return true; - } - } - } -} - -inline bool HandlePar( unsigned int & cur, Accessor & styler ) -{ - styler.ColourTo( cur, SCE_OPAL_PAR ); - - cur++; - - styler.StartSegment( cur ); - return true; -} - -inline bool HandleSpace( unsigned int & cur, unsigned int one_too_much, Accessor & styler ) -{ - char ch; - - cur++; - for( ; ; ) - { - if( cur >= one_too_much ) - { - styler.ColourTo( cur - 1, SCE_OPAL_SPACE ); - return false; - } - - ch = styler.SafeGetCharAt( cur ); - switch( ch ) - { - case ' ': - case '\t': - case '\015': - case '\012': - cur++; - break; - - default: - styler.ColourTo( cur - 1, SCE_OPAL_SPACE ); - styler.StartSegment( cur ); - return true; - } - } -} - -inline bool HandleInteger( unsigned int & cur, unsigned int one_too_much, Accessor & styler ) -{ - char ch; - - for( ; ; ) - { - cur++; - if( cur >= one_too_much ) - { - styler.ColourTo( cur - 1, SCE_OPAL_INTEGER ); - return false; // STOP - } - - ch = styler.SafeGetCharAt( cur ); - if( !( isascii( ch ) && isdigit( ch ) ) ) - { - styler.ColourTo( cur - 1, SCE_OPAL_INTEGER ); - styler.StartSegment( cur ); - return true; - } - } -} - -inline bool HandleWord( unsigned int & cur, unsigned int one_too_much, Accessor & styler, WordList * keywordlists[] ) -{ - char ch; - const unsigned int beg = cur; - - cur++; - for( ; ; ) - { - ch = styler.SafeGetCharAt( cur ); - if( ( ch != '_' ) && ( ch != '-' ) && - !( isascii( ch ) && ( islower( ch ) || isupper( ch ) || isdigit( ch ) ) ) ) break; - - cur++; - if( cur >= one_too_much ) - { - break; - } - } - - const int ide_len = cur - beg + 1; - char * ide = new char[ ide_len ]; - getRange( beg, cur, styler, ide, ide_len ); - - WordList & keywords = *keywordlists[ 0 ]; - WordList & classwords = *keywordlists[ 1 ]; - - if( keywords.InList( ide ) ) // Keyword - { - delete [] ide; - - styler.ColourTo( cur - 1, SCE_OPAL_KEYWORD ); - if( cur >= one_too_much ) - { - return false; // STOP - } - else - { - styler.StartSegment( cur ); - return true; - } - } - else if( classwords.InList( ide ) ) // Sort - { - delete [] ide; - - styler.ColourTo( cur - 1, SCE_OPAL_SORT ); - if( cur >= one_too_much ) - { - return false; // STOP - } - else - { - styler.StartSegment( cur ); - return true; - } - } - else if( !strcmp( ide, "true" ) || !strcmp( ide, "false" ) ) // Bool const - { - delete [] ide; - - styler.ColourTo( cur - 1, SCE_OPAL_BOOL_CONST ); - if( cur >= one_too_much ) - { - return false; // STOP - } - else - { - styler.StartSegment( cur ); - return true; - } - } - else // Unknown keyword - { - delete [] ide; - - styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); - if( cur >= one_too_much ) - { - return false; // STOP - } - else - { - styler.StartSegment( cur ); - return true; - } - } - -} - -inline bool HandleSkip( unsigned int & cur, unsigned int one_too_much, Accessor & styler ) -{ - cur++; - styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); - if( cur >= one_too_much ) - { - return false; // STOP - } - else - { - styler.StartSegment( cur ); - return true; - } -} - -static void ColouriseOpalDoc( unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor & styler ) -{ - styler.StartAt( startPos ); - styler.StartSegment( startPos ); - - unsigned int & cur = startPos; - const unsigned int one_too_much = startPos + length; - - int state = initStyle; - - for( ; ; ) - { - switch( state ) - { - case SCE_OPAL_KEYWORD: - case SCE_OPAL_SORT: - if( !HandleWord( cur, one_too_much, styler, keywordlists ) ) return; - state = SCE_OPAL_DEFAULT; - break; - - case SCE_OPAL_INTEGER: - if( !HandleInteger( cur, one_too_much, styler ) ) return; - state = SCE_OPAL_DEFAULT; - break; - - case SCE_OPAL_COMMENT_BLOCK: - if( !HandleCommentBlock( cur, one_too_much, styler, false ) ) return; - state = SCE_OPAL_DEFAULT; - break; - - case SCE_OPAL_COMMENT_LINE: - if( !HandleCommentLine( cur, one_too_much, styler, false ) ) return; - state = SCE_OPAL_DEFAULT; - break; - - case SCE_OPAL_STRING: - if( !HandleString( cur, one_too_much, styler ) ) return; - state = SCE_OPAL_DEFAULT; - break; - - default: // SCE_OPAL_DEFAULT: - { - char ch = styler.SafeGetCharAt( cur ); - - switch( ch ) - { - // String - case '"': - if( !HandleString( cur, one_too_much, styler ) ) return; - break; - - // Comment block - case '/': - if( !HandleCommentBlock( cur, one_too_much, styler, true ) ) return; - break; - - // Comment line - case '-': - if( !HandleCommentLine( cur, one_too_much, styler, true ) ) return; - break; - - // Par - case '(': - case ')': - case '[': - case ']': - case '{': - case '}': - if( !HandlePar( cur, styler ) ) return; - break; - - // Whitespace - case ' ': - case '\t': - case '\015': - case '\012': - if( !HandleSpace( cur, one_too_much, styler ) ) return; - break; - - default: - { - // Integer - if( isascii( ch ) && isdigit( ch ) ) - { - if( !HandleInteger( cur, one_too_much, styler ) ) return; - } - - // Keyword - else if( isascii( ch ) && ( islower( ch ) || isupper( ch ) ) ) - { - if( !HandleWord( cur, one_too_much, styler, keywordlists ) ) return; - - } - - // Skip - else - { - if( !HandleSkip( cur, one_too_much, styler ) ) return; - } - } - } - - break; - } - } - } -} - -static const char * const opalWordListDesc[] = { - "Keywords", - "Sorts", - 0 -}; - -LexerModule lmOpal(SCLEX_OPAL, ColouriseOpalDoc, "opal", NULL, opalWordListDesc); diff --git a/src/LexOthers.cxx b/src/LexOthers.cxx deleted file mode 100644 index c8f6ca977..000000000 --- a/src/LexOthers.cxx +++ /dev/null @@ -1,1286 +0,0 @@ -// Scintilla source code edit control -/** @file LexOthers.cxx - ** Lexers for batch files, diff results, properties files, make files and error lists. - ** Also lexer for LaTeX documents. - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "CharClassify.h" -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static bool strstart(const char *haystack, const char *needle) { - return strncmp(haystack, needle, strlen(needle)) == 0; -} - -static bool Is0To9(char ch) { - return (ch >= '0') && (ch <= '9'); -} - -static bool Is1To9(char ch) { - return (ch >= '1') && (ch <= '9'); -} - -static bool IsAlphabetic(int ch) { - return isascii(ch) && isalpha(ch); -} - -static inline bool AtEOL(Accessor &styler, unsigned int i) { - return (styler[i] == '\n') || - ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); -} - -// Tests for BATCH Operators -static bool IsBOperator(char ch) { - return (ch == '=') || (ch == '+') || (ch == '>') || (ch == '<') || - (ch == '|') || (ch == '?') || (ch == '*'); -} - -// Tests for BATCH Separators -static bool IsBSeparator(char ch) { - return (ch == '\\') || (ch == '.') || (ch == ';') || - (ch == '\"') || (ch == '\'') || (ch == '/') || (ch == ')'); -} - -static void ColouriseBatchLine( - char *lineBuffer, - unsigned int lengthLine, - unsigned int startLine, - unsigned int endPos, - WordList *keywordlists[], - Accessor &styler) { - - unsigned int offset = 0; // Line Buffer Offset - unsigned int cmdLoc; // External Command / Program Location - char wordBuffer[81]; // Word Buffer - large to catch long paths - unsigned int wbl; // Word Buffer Length - unsigned int wbo; // Word Buffer Offset - also Special Keyword Buffer Length - WordList &keywords = *keywordlists[0]; // Internal Commands - WordList &keywords2 = *keywordlists[1]; // External Commands (optional) - - // CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords - // Toggling Regular Keyword Checking off improves readability - // Other Regular Keywords and External Commands / Programs might also benefit from toggling - // Need a more robust algorithm to properly toggle Regular Keyword Checking - bool continueProcessing = true; // Used to toggle Regular Keyword Checking - // Special Keywords are those that allow certain characters without whitespace after the command - // Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path= - // Special Keyword Buffer used to determine if the first n characters is a Keyword - char sKeywordBuffer[10]; // Special Keyword Buffer - bool sKeywordFound; // Exit Special Keyword for-loop if found - - // Skip initial spaces - while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { - offset++; - } - // Colorize Default Text - styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); - // Set External Command / Program Location - cmdLoc = offset; - - // Check for Fake Label (Comment) or Real Label - return if found - if (lineBuffer[offset] == ':') { - if (lineBuffer[offset + 1] == ':') { - // Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm - styler.ColourTo(endPos, SCE_BAT_COMMENT); - } else { - // Colorize Real Label - styler.ColourTo(endPos, SCE_BAT_LABEL); - } - return; - // Check for Drive Change (Drive Change is internal command) - return if found - } else if ((IsAlphabetic(lineBuffer[offset])) && - (lineBuffer[offset + 1] == ':') && - ((isspacechar(lineBuffer[offset + 2])) || - (((lineBuffer[offset + 2] == '\\')) && - (isspacechar(lineBuffer[offset + 3]))))) { - // Colorize Regular Keyword - styler.ColourTo(endPos, SCE_BAT_WORD); - return; - } - - // Check for Hide Command (@ECHO OFF/ON) - if (lineBuffer[offset] == '@') { - styler.ColourTo(startLine + offset, SCE_BAT_HIDE); - offset++; - } - // Skip next spaces - while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { - offset++; - } - - // Read remainder of line word-at-a-time or remainder-of-word-at-a-time - while (offset < lengthLine) { - if (offset > startLine) { - // Colorize Default Text - styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); - } - // Copy word from Line Buffer into Word Buffer - wbl = 0; - for (; offset < lengthLine && wbl < 80 && - !isspacechar(lineBuffer[offset]); wbl++, offset++) { - wordBuffer[wbl] = static_cast(tolower(lineBuffer[offset])); - } - wordBuffer[wbl] = '\0'; - wbo = 0; - - // Check for Comment - return if found - if (CompareCaseInsensitive(wordBuffer, "rem") == 0) { - styler.ColourTo(endPos, SCE_BAT_COMMENT); - return; - } - // Check for Separator - if (IsBSeparator(wordBuffer[0])) { - // Check for External Command / Program - if ((cmdLoc == offset - wbl) && - ((wordBuffer[0] == ':') || - (wordBuffer[0] == '\\') || - (wordBuffer[0] == '.'))) { - // Reset Offset to re-process remainder of word - offset -= (wbl - 1); - // Colorize External Command / Program - if (!keywords2) { - styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); - } else if (keywords2.InList(wordBuffer)) { - styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); - } else { - styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); - } - // Reset External Command / Program Location - cmdLoc = offset; - } else { - // Reset Offset to re-process remainder of word - offset -= (wbl - 1); - // Colorize Default Text - styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); - } - // Check for Regular Keyword in list - } else if ((keywords.InList(wordBuffer)) && - (continueProcessing)) { - // ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking - if ((CompareCaseInsensitive(wordBuffer, "echo") == 0) || - (CompareCaseInsensitive(wordBuffer, "goto") == 0) || - (CompareCaseInsensitive(wordBuffer, "prompt") == 0) || - (CompareCaseInsensitive(wordBuffer, "set") == 0)) { - continueProcessing = false; - } - // Identify External Command / Program Location for ERRORLEVEL, and EXIST - if ((CompareCaseInsensitive(wordBuffer, "errorlevel") == 0) || - (CompareCaseInsensitive(wordBuffer, "exist") == 0)) { - // Reset External Command / Program Location - cmdLoc = offset; - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Skip comparison - while ((cmdLoc < lengthLine) && - (!isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Identify External Command / Program Location for CALL, DO, LOADHIGH and LH - } else if ((CompareCaseInsensitive(wordBuffer, "call") == 0) || - (CompareCaseInsensitive(wordBuffer, "do") == 0) || - (CompareCaseInsensitive(wordBuffer, "loadhigh") == 0) || - (CompareCaseInsensitive(wordBuffer, "lh") == 0)) { - // Reset External Command / Program Location - cmdLoc = offset; - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - } - // Colorize Regular keyword - styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD); - // No need to Reset Offset - // Check for Special Keyword in list, External Command / Program, or Default Text - } else if ((wordBuffer[0] != '%') && - (wordBuffer[0] != '!') && - (!IsBOperator(wordBuffer[0])) && - (continueProcessing)) { - // Check for Special Keyword - // Affected Commands are in Length range 2-6 - // Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected - sKeywordFound = false; - for (unsigned int keywordLength = 2; keywordLength < wbl && keywordLength < 7 && !sKeywordFound; keywordLength++) { - wbo = 0; - // Copy Keyword Length from Word Buffer into Special Keyword Buffer - for (; wbo < keywordLength; wbo++) { - sKeywordBuffer[wbo] = static_cast(wordBuffer[wbo]); - } - sKeywordBuffer[wbo] = '\0'; - // Check for Special Keyword in list - if ((keywords.InList(sKeywordBuffer)) && - ((IsBOperator(wordBuffer[wbo])) || - (IsBSeparator(wordBuffer[wbo])))) { - sKeywordFound = true; - // ECHO requires no further Regular Keyword Checking - if (CompareCaseInsensitive(sKeywordBuffer, "echo") == 0) { - continueProcessing = false; - } - // Colorize Special Keyword as Regular Keyword - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_WORD); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - } - } - // Check for External Command / Program or Default Text - if (!sKeywordFound) { - wbo = 0; - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - // Read up to %, Operator or Separator - while ((wbo < wbl) && - (wordBuffer[wbo] != '%') && - (wordBuffer[wbo] != '!') && - (!IsBOperator(wordBuffer[wbo])) && - (!IsBSeparator(wordBuffer[wbo]))) { - wbo++; - } - // Reset External Command / Program Location - cmdLoc = offset - (wbl - wbo); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - // CHOICE requires no further Regular Keyword Checking - if (CompareCaseInsensitive(wordBuffer, "choice") == 0) { - continueProcessing = false; - } - // Check for START (and its switches) - What follows is External Command \ Program - if (CompareCaseInsensitive(wordBuffer, "start") == 0) { - // Reset External Command / Program Location - cmdLoc = offset; - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Reset External Command / Program Location if command switch detected - if (lineBuffer[cmdLoc] == '/') { - // Skip command switch - while ((cmdLoc < lengthLine) && - (!isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - } - } - // Colorize External Command / Program - if (!keywords2) { - styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); - } else if (keywords2.InList(wordBuffer)) { - styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); - } else { - styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); - } - // No need to Reset Offset - // Check for Default Text - } else { - // Read up to %, Operator or Separator - while ((wbo < wbl) && - (wordBuffer[wbo] != '%') && - (wordBuffer[wbo] != '!') && - (!IsBOperator(wordBuffer[wbo])) && - (!IsBSeparator(wordBuffer[wbo]))) { - wbo++; - } - // Colorize Default Text - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - } - } - // Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a) - } else if (wordBuffer[0] == '%') { - // Colorize Default Text - styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); - wbo++; - // Search to end of word for second % (can be a long path) - while ((wbo < wbl) && - (wordBuffer[wbo] != '%') && - (!IsBOperator(wordBuffer[wbo])) && - (!IsBSeparator(wordBuffer[wbo]))) { - wbo++; - } - // Check for Argument (%n) or (%*) - if (((Is0To9(wordBuffer[1])) || (wordBuffer[1] == '*')) && - (wordBuffer[wbo] != '%')) { - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - cmdLoc = offset - (wbl - 2); - } - // Colorize Argument - styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_IDENTIFIER); - // Reset Offset to re-process remainder of word - offset -= (wbl - 2); - // Check for Expanded Argument (%~...) / Variable (%%~...) - } else if (((wbl > 1) && (wordBuffer[1] == '~')) || - ((wbl > 2) && (wordBuffer[1] == '%') && (wordBuffer[2] == '~'))) { - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - cmdLoc = offset - (wbl - wbo); - } - // Colorize Expanded Argument / Variable - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - // Check for Environment Variable (%x...%) - } else if ((wordBuffer[1] != '%') && - (wordBuffer[wbo] == '%')) { - wbo++; - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - cmdLoc = offset - (wbl - wbo); - } - // Colorize Environment Variable - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - // Check for Local Variable (%%a) - } else if ( - (wbl > 2) && - (wordBuffer[1] == '%') && - (wordBuffer[2] != '%') && - (!IsBOperator(wordBuffer[2])) && - (!IsBSeparator(wordBuffer[2]))) { - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - cmdLoc = offset - (wbl - 3); - } - // Colorize Local Variable - styler.ColourTo(startLine + offset - 1 - (wbl - 3), SCE_BAT_IDENTIFIER); - // Reset Offset to re-process remainder of word - offset -= (wbl - 3); - } - // Check for Environment Variable (!x...!) - } else if (wordBuffer[0] == '!') { - // Colorize Default Text - styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); - wbo++; - // Search to end of word for second ! (can be a long path) - while ((wbo < wbl) && - (wordBuffer[wbo] != '!') && - (!IsBOperator(wordBuffer[wbo])) && - (!IsBSeparator(wordBuffer[wbo]))) { - wbo++; - } - if (wordBuffer[wbo] == '!') { - wbo++; - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - cmdLoc = offset - (wbl - wbo); - } - // Colorize Environment Variable - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - } - // Check for Operator - } else if (IsBOperator(wordBuffer[0])) { - // Colorize Default Text - styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); - // Check for Comparison Operator - if ((wordBuffer[0] == '=') && (wordBuffer[1] == '=')) { - // Identify External Command / Program Location for IF - cmdLoc = offset; - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Colorize Comparison Operator - styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_OPERATOR); - // Reset Offset to re-process remainder of word - offset -= (wbl - 2); - // Check for Pipe Operator - } else if (wordBuffer[0] == '|') { - // Reset External Command / Program Location - cmdLoc = offset - wbl + 1; - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Colorize Pipe Operator - styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); - // Reset Offset to re-process remainder of word - offset -= (wbl - 1); - // Check for Other Operator - } else { - // Check for > Operator - if (wordBuffer[0] == '>') { - // Turn Keyword and External Command / Program checking back on - continueProcessing = true; - } - // Colorize Other Operator - styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); - // Reset Offset to re-process remainder of word - offset -= (wbl - 1); - } - // Check for Default Text - } else { - // Read up to %, Operator or Separator - while ((wbo < wbl) && - (wordBuffer[wbo] != '%') && - (wordBuffer[wbo] != '!') && - (!IsBOperator(wordBuffer[wbo])) && - (!IsBSeparator(wordBuffer[wbo]))) { - wbo++; - } - // Colorize Default Text - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - } - // Skip next spaces - nothing happens if Offset was Reset - while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { - offset++; - } - } - // Colorize Default Text for remainder of line - currently not lexed - styler.ColourTo(endPos, SCE_BAT_DEFAULT); -} - -static void ColouriseBatchDoc( - unsigned int startPos, - int length, - int /*initStyle*/, - WordList *keywordlists[], - Accessor &styler) { - - char lineBuffer[1024]; - - styler.StartAt(startPos); - styler.StartSegment(startPos); - unsigned int linePos = 0; - unsigned int startLine = startPos; - for (unsigned int i = startPos; i < startPos + length; i++) { - lineBuffer[linePos++] = styler[i]; - if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { - // End of line (or of line buffer) met, colourise it - lineBuffer[linePos] = '\0'; - ColouriseBatchLine(lineBuffer, linePos, startLine, i, keywordlists, styler); - linePos = 0; - startLine = i + 1; - } - } - if (linePos > 0) { // Last line does not have ending characters - lineBuffer[linePos] = '\0'; - ColouriseBatchLine(lineBuffer, linePos, startLine, startPos + length - 1, - keywordlists, styler); - } -} - -static void ColouriseDiffLine(char *lineBuffer, int endLine, Accessor &styler) { - // It is needed to remember the current state to recognize starting - // comment lines before the first "diff " or "--- ". If a real - // difference starts then each line starting with ' ' is a whitespace - // otherwise it is considered a comment (Only in..., Binary file...) - if (0 == strncmp(lineBuffer, "diff ", 5)) { - styler.ColourTo(endLine, SCE_DIFF_COMMAND); - } else if (0 == strncmp(lineBuffer, "Index: ", 7)) { // For subversion's diff - styler.ColourTo(endLine, SCE_DIFF_COMMAND); - } else if (0 == strncmp(lineBuffer, "---", 3)) { - // In a context diff, --- appears in both the header and the position markers - if (lineBuffer[3] == ' ' && atoi(lineBuffer + 4) && !strchr(lineBuffer, '/')) - styler.ColourTo(endLine, SCE_DIFF_POSITION); - else if (lineBuffer[3] == '\r' || lineBuffer[3] == '\n') - styler.ColourTo(endLine, SCE_DIFF_POSITION); - else - styler.ColourTo(endLine, SCE_DIFF_HEADER); - } else if (0 == strncmp(lineBuffer, "+++ ", 4)) { - // I don't know of any diff where "+++ " is a position marker, but for - // consistency, do the same as with "--- " and "*** ". - if (atoi(lineBuffer+4) && !strchr(lineBuffer, '/')) - styler.ColourTo(endLine, SCE_DIFF_POSITION); - else - styler.ColourTo(endLine, SCE_DIFF_HEADER); - } else if (0 == strncmp(lineBuffer, "====", 4)) { // For p4's diff - styler.ColourTo(endLine, SCE_DIFF_HEADER); - } else if (0 == strncmp(lineBuffer, "***", 3)) { - // In a context diff, *** appears in both the header and the position markers. - // Also ******** is a chunk header, but here it's treated as part of the - // position marker since there is no separate style for a chunk header. - if (lineBuffer[3] == ' ' && atoi(lineBuffer+4) && !strchr(lineBuffer, '/')) - styler.ColourTo(endLine, SCE_DIFF_POSITION); - else if (lineBuffer[3] == '*') - styler.ColourTo(endLine, SCE_DIFF_POSITION); - else - styler.ColourTo(endLine, SCE_DIFF_HEADER); - } else if (0 == strncmp(lineBuffer, "? ", 2)) { // For difflib - styler.ColourTo(endLine, SCE_DIFF_HEADER); - } else if (lineBuffer[0] == '@') { - styler.ColourTo(endLine, SCE_DIFF_POSITION); - } else if (lineBuffer[0] >= '0' && lineBuffer[0] <= '9') { - styler.ColourTo(endLine, SCE_DIFF_POSITION); - } else if (lineBuffer[0] == '-' || lineBuffer[0] == '<') { - styler.ColourTo(endLine, SCE_DIFF_DELETED); - } else if (lineBuffer[0] == '+' || lineBuffer[0] == '>') { - styler.ColourTo(endLine, SCE_DIFF_ADDED); - } else if (lineBuffer[0] == '!') { - styler.ColourTo(endLine, SCE_DIFF_CHANGED); - } else if (lineBuffer[0] != ' ') { - styler.ColourTo(endLine, SCE_DIFF_COMMENT); - } else { - styler.ColourTo(endLine, SCE_DIFF_DEFAULT); - } -} - -static void ColouriseDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - char lineBuffer[1024]; - styler.StartAt(startPos); - styler.StartSegment(startPos); - unsigned int linePos = 0; - for (unsigned int i = startPos; i < startPos + length; i++) { - lineBuffer[linePos++] = styler[i]; - if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { - // End of line (or of line buffer) met, colourise it - lineBuffer[linePos] = '\0'; - ColouriseDiffLine(lineBuffer, i, styler); - linePos = 0; - } - } - if (linePos > 0) { // Last line does not have ending characters - ColouriseDiffLine(lineBuffer, startPos + length - 1, styler); - } -} - -static void FoldDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - int curLine = styler.GetLine(startPos); - int curLineStart = styler.LineStart(curLine); - int prevLevel = curLine > 0 ? styler.LevelAt(curLine - 1) : SC_FOLDLEVELBASE; - int nextLevel; - - do { - int lineType = styler.StyleAt(curLineStart); - if (lineType == SCE_DIFF_COMMAND) - nextLevel = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; - else if (lineType == SCE_DIFF_HEADER) - nextLevel = (SC_FOLDLEVELBASE + 1) | SC_FOLDLEVELHEADERFLAG; - else if (lineType == SCE_DIFF_POSITION && styler[curLineStart] != '-') - nextLevel = (SC_FOLDLEVELBASE + 2) | SC_FOLDLEVELHEADERFLAG; - else if (prevLevel & SC_FOLDLEVELHEADERFLAG) - nextLevel = (prevLevel & SC_FOLDLEVELNUMBERMASK) + 1; - else - nextLevel = prevLevel; - - if ((nextLevel & SC_FOLDLEVELHEADERFLAG) && (nextLevel == prevLevel)) - styler.SetLevel(curLine-1, prevLevel & ~SC_FOLDLEVELHEADERFLAG); - - styler.SetLevel(curLine, nextLevel); - prevLevel = nextLevel; - - curLineStart = styler.LineStart(++curLine); - } while (static_cast(startPos) + length > curLineStart); -} - -static void ColourisePoLine( - char *lineBuffer, - unsigned int lengthLine, - unsigned int startLine, - unsigned int endPos, - Accessor &styler) { - - unsigned int i = 0; - static unsigned int state = SCE_PO_DEFAULT; - unsigned int state_start = SCE_PO_DEFAULT; - - while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces - i++; - if (i < lengthLine) { - if (lineBuffer[i] == '#') { - // check if the comment contains any flags ("#, ") and - // then whether the flags contain "fuzzy" - if (strstart(lineBuffer, "#, ") && strstr(lineBuffer, "fuzzy")) - styler.ColourTo(endPos, SCE_PO_FUZZY); - else - styler.ColourTo(endPos, SCE_PO_COMMENT); - } else { - if (lineBuffer[0] == '"') { - // line continuation, use previous style - styler.ColourTo(endPos, state); - return; - // this implicitly also matches "msgid_plural" - } else if (strstart(lineBuffer, "msgid")) { - state_start = SCE_PO_MSGID; - state = SCE_PO_MSGID_TEXT; - } else if (strstart(lineBuffer, "msgstr")) { - state_start = SCE_PO_MSGSTR; - state = SCE_PO_MSGSTR_TEXT; - } else if (strstart(lineBuffer, "msgctxt")) { - state_start = SCE_PO_MSGCTXT; - state = SCE_PO_MSGCTXT_TEXT; - } - if (state_start != SCE_PO_DEFAULT) { - // find the next space - while ((i < lengthLine) && ! isspacechar(lineBuffer[i])) - i++; - styler.ColourTo(startLine + i - 1, state_start); - styler.ColourTo(startLine + i, SCE_PO_DEFAULT); - styler.ColourTo(endPos, state); - } - } - } else { - styler.ColourTo(endPos, SCE_PO_DEFAULT); - } -} - -static void ColourisePoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - char lineBuffer[1024]; - styler.StartAt(startPos); - styler.StartSegment(startPos); - unsigned int linePos = 0; - unsigned int startLine = startPos; - for (unsigned int i = startPos; i < startPos + length; i++) { - lineBuffer[linePos++] = styler[i]; - if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { - // End of line (or of line buffer) met, colourise it - lineBuffer[linePos] = '\0'; - ColourisePoLine(lineBuffer, linePos, startLine, i, styler); - linePos = 0; - startLine = i + 1; - } - } - if (linePos > 0) { // Last line does not have ending characters - ColourisePoLine(lineBuffer, linePos, startLine, startPos + length - 1, styler); - } -} - -static inline bool isassignchar(unsigned char ch) { - return (ch == '=') || (ch == ':'); -} - -static void ColourisePropsLine( - char *lineBuffer, - unsigned int lengthLine, - unsigned int startLine, - unsigned int endPos, - Accessor &styler, - bool allowInitialSpaces) { - - unsigned int i = 0; - if (allowInitialSpaces) { - while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces - i++; - } else { - if (isspacechar(lineBuffer[i])) // don't allow initial spaces - i = lengthLine; - } - - if (i < lengthLine) { - if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') { - styler.ColourTo(endPos, SCE_PROPS_COMMENT); - } else if (lineBuffer[i] == '[') { - styler.ColourTo(endPos, SCE_PROPS_SECTION); - } else if (lineBuffer[i] == '@') { - styler.ColourTo(startLine + i, SCE_PROPS_DEFVAL); - if (isassignchar(lineBuffer[i++])) - styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT); - styler.ColourTo(endPos, SCE_PROPS_DEFAULT); - } else { - // Search for the '=' character - while ((i < lengthLine) && !isassignchar(lineBuffer[i])) - i++; - if ((i < lengthLine) && isassignchar(lineBuffer[i])) { - styler.ColourTo(startLine + i - 1, SCE_PROPS_KEY); - styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT); - styler.ColourTo(endPos, SCE_PROPS_DEFAULT); - } else { - styler.ColourTo(endPos, SCE_PROPS_DEFAULT); - } - } - } else { - styler.ColourTo(endPos, SCE_PROPS_DEFAULT); - } -} - -static void ColourisePropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - char lineBuffer[1024]; - styler.StartAt(startPos); - styler.StartSegment(startPos); - unsigned int linePos = 0; - unsigned int startLine = startPos; - - // property lexer.props.allow.initial.spaces - // For properties files, set to 0 to style all lines that start with whitespace in the default style. - // This is not suitable for SciTE .properties files which use indentation for flow control but - // can be used for RFC2822 text where indentation is used for continuation lines. - bool allowInitialSpaces = styler.GetPropertyInt("lexer.props.allow.initial.spaces", 1) != 0; - - for (unsigned int i = startPos; i < startPos + length; i++) { - lineBuffer[linePos++] = styler[i]; - if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { - // End of line (or of line buffer) met, colourise it - lineBuffer[linePos] = '\0'; - ColourisePropsLine(lineBuffer, linePos, startLine, i, styler, allowInitialSpaces); - linePos = 0; - startLine = i + 1; - } - } - if (linePos > 0) { // Last line does not have ending characters - ColourisePropsLine(lineBuffer, linePos, startLine, startPos + length - 1, styler, allowInitialSpaces); - } -} - -// adaption by ksc, using the "} else {" trick of 1.53 -// 030721 -static void FoldPropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - bool headerPoint = false; - int lev; - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler[i+1]; - - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - if (style == SCE_PROPS_SECTION) { - headerPoint = true; - } - - if (atEOL) { - lev = SC_FOLDLEVELBASE; - - if (lineCurrent > 0) { - int levelPrevious = styler.LevelAt(lineCurrent - 1); - - if (levelPrevious & SC_FOLDLEVELHEADERFLAG) { - lev = SC_FOLDLEVELBASE + 1; - } else { - lev = levelPrevious & SC_FOLDLEVELNUMBERMASK; - } - } - - if (headerPoint) { - lev = SC_FOLDLEVELBASE; - } - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - - if (headerPoint) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - - lineCurrent++; - visibleChars = 0; - headerPoint = false; - } - if (!isspacechar(ch)) - visibleChars++; - } - - if (lineCurrent > 0) { - int levelPrevious = styler.LevelAt(lineCurrent - 1); - if (levelPrevious & SC_FOLDLEVELHEADERFLAG) { - lev = SC_FOLDLEVELBASE + 1; - } else { - lev = levelPrevious & SC_FOLDLEVELNUMBERMASK; - } - } else { - lev = SC_FOLDLEVELBASE; - } - int flagsNext = styler.LevelAt(lineCurrent); - styler.SetLevel(lineCurrent, lev | (flagsNext & ~SC_FOLDLEVELNUMBERMASK)); -} - -static void ColouriseMakeLine( - char *lineBuffer, - unsigned int lengthLine, - unsigned int startLine, - unsigned int endPos, - Accessor &styler) { - - unsigned int i = 0; - int lastNonSpace = -1; - unsigned int state = SCE_MAKE_DEFAULT; - bool bSpecial = false; - - // check for a tab character in column 0 indicating a command - bool bCommand = false; - if ((lengthLine > 0) && (lineBuffer[0] == '\t')) - bCommand = true; - - // Skip initial spaces - while ((i < lengthLine) && isspacechar(lineBuffer[i])) { - i++; - } - if (lineBuffer[i] == '#') { // Comment - styler.ColourTo(endPos, SCE_MAKE_COMMENT); - return; - } - if (lineBuffer[i] == '!') { // Special directive - styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR); - return; - } - while (i < lengthLine) { - if (lineBuffer[i] == '$' && lineBuffer[i + 1] == '(') { - styler.ColourTo(startLine + i - 1, state); - state = SCE_MAKE_IDENTIFIER; - } else if (state == SCE_MAKE_IDENTIFIER && lineBuffer[i] == ')') { - styler.ColourTo(startLine + i, state); - state = SCE_MAKE_DEFAULT; - } - - // skip identifier and target styling if this is a command line - if (!bSpecial && !bCommand) { - if (lineBuffer[i] == ':') { - if (((i + 1) < lengthLine) && (lineBuffer[i + 1] == '=')) { - // it's a ':=', so style as an identifier - if (lastNonSpace >= 0) - styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER); - styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); - styler.ColourTo(startLine + i + 1, SCE_MAKE_OPERATOR); - } else { - // We should check that no colouring was made since the beginning of the line, - // to avoid colouring stuff like /OUT:file - if (lastNonSpace >= 0) - styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_TARGET); - styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); - styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR); - } - bSpecial = true; // Only react to the first ':' of the line - state = SCE_MAKE_DEFAULT; - } else if (lineBuffer[i] == '=') { - if (lastNonSpace >= 0) - styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER); - styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); - styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR); - bSpecial = true; // Only react to the first '=' of the line - state = SCE_MAKE_DEFAULT; - } - } - if (!isspacechar(lineBuffer[i])) { - lastNonSpace = i; - } - i++; - } - if (state == SCE_MAKE_IDENTIFIER) { - styler.ColourTo(endPos, SCE_MAKE_IDEOL); // Error, variable reference not ended - } else { - styler.ColourTo(endPos, SCE_MAKE_DEFAULT); - } -} - -static void ColouriseMakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - char lineBuffer[1024]; - styler.StartAt(startPos); - styler.StartSegment(startPos); - unsigned int linePos = 0; - unsigned int startLine = startPos; - for (unsigned int i = startPos; i < startPos + length; i++) { - lineBuffer[linePos++] = styler[i]; - if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { - // End of line (or of line buffer) met, colourise it - lineBuffer[linePos] = '\0'; - ColouriseMakeLine(lineBuffer, linePos, startLine, i, styler); - linePos = 0; - startLine = i + 1; - } - } - if (linePos > 0) { // Last line does not have ending characters - ColouriseMakeLine(lineBuffer, linePos, startLine, startPos + length - 1, styler); - } -} - -static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLine, int &startValue) { - if (lineBuffer[0] == '>') { - // Command or return status - return SCE_ERR_CMD; - } else if (lineBuffer[0] == '<') { - // Diff removal, but not interested. Trapped to avoid hitting CTAG cases. - return SCE_ERR_DEFAULT; - } else if (lineBuffer[0] == '!') { - return SCE_ERR_DIFF_CHANGED; - } else if (lineBuffer[0] == '+') { - if (strstart(lineBuffer, "+++ ")) { - return SCE_ERR_DIFF_MESSAGE; - } else { - return SCE_ERR_DIFF_ADDITION; - } - } else if (lineBuffer[0] == '-') { - if (strstart(lineBuffer, "--- ")) { - return SCE_ERR_DIFF_MESSAGE; - } else { - return SCE_ERR_DIFF_DELETION; - } - } else if (strstart(lineBuffer, "cf90-")) { - // Absoft Pro Fortran 90/95 v8.2 error and/or warning message - return SCE_ERR_ABSF; - } else if (strstart(lineBuffer, "fortcom:")) { - // Intel Fortran Compiler v8.0 error/warning message - return SCE_ERR_IFORT; - } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) { - return SCE_ERR_PYTHON; - } else if (strstr(lineBuffer, " in ") && strstr(lineBuffer, " on line ")) { - return SCE_ERR_PHP; - } else if ((strstart(lineBuffer, "Error ") || - strstart(lineBuffer, "Warning ")) && - strstr(lineBuffer, " at (") && - strstr(lineBuffer, ") : ") && - (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) { - // Intel Fortran Compiler error/warning message - return SCE_ERR_IFC; - } else if (strstart(lineBuffer, "Error ")) { - // Borland error message - return SCE_ERR_BORLAND; - } else if (strstart(lineBuffer, "Warning ")) { - // Borland warning message - return SCE_ERR_BORLAND; - } else if (strstr(lineBuffer, "at line ") && - (strstr(lineBuffer, "at line ") < (lineBuffer + lengthLine)) && - strstr(lineBuffer, "file ") && - (strstr(lineBuffer, "file ") < (lineBuffer + lengthLine))) { - // Lua 4 error message - return SCE_ERR_LUA; - } else if (strstr(lineBuffer, " at ") && - (strstr(lineBuffer, " at ") < (lineBuffer + lengthLine)) && - strstr(lineBuffer, " line ") && - (strstr(lineBuffer, " line ") < (lineBuffer + lengthLine)) && - (strstr(lineBuffer, " at ") < (strstr(lineBuffer, " line ")))) { - // perl error message - return SCE_ERR_PERL; - } else if ((memcmp(lineBuffer, " at ", 6) == 0) && - strstr(lineBuffer, ":line ")) { - // A .NET traceback - return SCE_ERR_NET; - } else if (strstart(lineBuffer, "Line ") && - strstr(lineBuffer, ", file ")) { - // Essential Lahey Fortran error message - return SCE_ERR_ELF; - } else if (strstart(lineBuffer, "line ") && - strstr(lineBuffer, " column ")) { - // HTML tidy style: line 42 column 1 - return SCE_ERR_TIDY; - } else if (strstart(lineBuffer, "\tat ") && - strstr(lineBuffer, "(") && - strstr(lineBuffer, ".java:")) { - // Java stack back trace - return SCE_ERR_JAVA_STACK; - } else { - // Look for one of the following formats: - // GCC: :: - // Microsoft: () : - // Common: (): warning|error|note|remark|catastrophic|fatal - // Common: () warning|error|note|remark|catastrophic|fatal - // Microsoft: (,) - // CTags: \t - // Lua 5 traceback: \t:: - // Lua 5.1: : :: - bool initialTab = (lineBuffer[0] == '\t'); - bool initialColonPart = false; - enum { stInitial, - stGccStart, stGccDigit, stGcc, - stMsStart, stMsDigit, stMsBracket, stMsVc, stMsDigitComma, stMsDotNet, - stCtagsStart, stCtagsStartString, stCtagsStringDollar, stCtags, - stUnrecognized - } state = stInitial; - for (unsigned int i = 0; i < lengthLine; i++) { - char ch = lineBuffer[i]; - char chNext = ' '; - if ((i + 1) < lengthLine) - chNext = lineBuffer[i + 1]; - if (state == stInitial) { - if (ch == ':') { - // May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix) - if ((chNext != '\\') && (chNext != '/') && (chNext != ' ')) { - // This check is not completely accurate as may be on - // GTK+ with a file name that includes ':'. - state = stGccStart; - } else if (chNext == ' ') { // indicates a Lua 5.1 error message - initialColonPart = true; - } - } else if ((ch == '(') && Is1To9(chNext) && (!initialTab)) { - // May be Microsoft - // Check against '0' often removes phone numbers - state = stMsStart; - } else if ((ch == '\t') && (!initialTab)) { - // May be CTags - state = stCtagsStart; - } - } else if (state == stGccStart) { // : - state = Is1To9(ch) ? stGccDigit : stUnrecognized; - } else if (state == stGccDigit) { // : - if (ch == ':') { - state = stGcc; // :9.*: is GCC - startValue = i + 1; - break; - } else if (!Is0To9(ch)) { - state = stUnrecognized; - } - } else if (state == stMsStart) { // ( - state = Is0To9(ch) ? stMsDigit : stUnrecognized; - } else if (state == stMsDigit) { // ( - if (ch == ',') { - state = stMsDigitComma; - } else if (ch == ')') { - state = stMsBracket; - } else if ((ch != ' ') && !Is0To9(ch)) { - state = stUnrecognized; - } - } else if (state == stMsBracket) { // () - if ((ch == ' ') && (chNext == ':')) { - state = stMsVc; - } else if ((ch == ':' && chNext == ' ') || (ch == ' ')) { - // Possibly Delphi.. don't test against chNext as it's one of the strings below. - char word[512]; - unsigned int j, chPos; - unsigned numstep; - chPos = 0; - if (ch == ' ') - numstep = 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i. - else - numstep = 2; // otherwise add 2. - for (j = i + numstep; j < lengthLine && IsAlphabetic(lineBuffer[j]) && chPos < sizeof(word) - 1; j++) - word[chPos++] = lineBuffer[j]; - word[chPos] = 0; - if (!CompareCaseInsensitive(word, "error") || !CompareCaseInsensitive(word, "warning") || - !CompareCaseInsensitive(word, "fatal") || !CompareCaseInsensitive(word, "catastrophic") || - !CompareCaseInsensitive(word, "note") || !CompareCaseInsensitive(word, "remark")) { - state = stMsVc; - } else - state = stUnrecognized; - } else { - state = stUnrecognized; - } - } else if (state == stMsDigitComma) { // (, - if (ch == ')') { - state = stMsDotNet; - break; - } else if ((ch != ' ') && !Is0To9(ch)) { - state = stUnrecognized; - } - } else if (state == stCtagsStart) { - if ((lineBuffer[i - 1] == '\t') && - ((ch == '/' && lineBuffer[i + 1] == '^') || Is0To9(ch))) { - state = stCtags; - break; - } else if ((ch == '/') && (lineBuffer[i + 1] == '^')) { - state = stCtagsStartString; - } - } else if ((state == stCtagsStartString) && ((lineBuffer[i] == '$') && (lineBuffer[i + 1] == '/'))) { - state = stCtagsStringDollar; - break; - } - } - if (state == stGcc) { - return initialColonPart ? SCE_ERR_LUA : SCE_ERR_GCC; - } else if ((state == stMsVc) || (state == stMsDotNet)) { - return SCE_ERR_MS; - } else if ((state == stCtagsStringDollar) || (state == stCtags)) { - return SCE_ERR_CTAG; - } else { - return SCE_ERR_DEFAULT; - } - } -} - -static void ColouriseErrorListLine( - char *lineBuffer, - unsigned int lengthLine, - unsigned int endPos, - Accessor &styler, - bool valueSeparate) { - int startValue = -1; - int style = RecogniseErrorListLine(lineBuffer, lengthLine, startValue); - if (valueSeparate && (startValue >= 0)) { - styler.ColourTo(endPos - (lengthLine - startValue), style); - styler.ColourTo(endPos, SCE_ERR_VALUE); - } else { - styler.ColourTo(endPos, style); - } -} - -static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - char lineBuffer[10000]; - styler.StartAt(startPos); - styler.StartSegment(startPos); - unsigned int linePos = 0; - - // property lexer.errorlist.value.separate - // For lines in the output pane that are matches from Find in Files or GCC-style - // diagnostics, style the path and line number separately from the rest of the - // line with style 21 used for the rest of the line. - // This allows matched text to be more easily distinguished from its location. - bool valueSeparate = styler.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0; - for (unsigned int i = startPos; i < startPos + length; i++) { - lineBuffer[linePos++] = styler[i]; - if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { - // End of line (or of line buffer) met, colourise it - lineBuffer[linePos] = '\0'; - ColouriseErrorListLine(lineBuffer, linePos, i, styler, valueSeparate); - linePos = 0; - } - } - if (linePos > 0) { // Last line does not have ending characters - ColouriseErrorListLine(lineBuffer, linePos, startPos + length - 1, styler, valueSeparate); - } -} - -static int isSpecial(char s) { - return (s == '\\') || (s == ',') || (s == ';') || (s == '\'') || (s == ' ') || - (s == '\"') || (s == '`') || (s == '^') || (s == '~'); -} - -static int isTag(int start, Accessor &styler) { - char s[6]; - unsigned int i = 0, e = 1; - while (i < 5 && e) { - s[i] = styler[start + i]; - i++; - e = styler[start + i] != '{'; - } - s[i] = '\0'; - return (strcmp(s, "begin") == 0) || (strcmp(s, "end") == 0); -} - -static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) { - - styler.StartAt(startPos); - - int state = initStyle; - char chNext = styler[startPos]; - styler.StartSegment(startPos); - int lengthDoc = startPos + length; - - for (int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - i++; - continue; - } - switch (state) { - case SCE_L_DEFAULT : - switch (ch) { - case '\\' : - styler.ColourTo(i - 1, state); - if (isSpecial(styler[i + 1])) { - styler.ColourTo(i + 1, SCE_L_COMMAND); - i++; - chNext = styler.SafeGetCharAt(i + 1); - } else { - if (isTag(i + 1, styler)) - state = SCE_L_TAG; - else - state = SCE_L_COMMAND; - } - break; - case '$' : - styler.ColourTo(i - 1, state); - state = SCE_L_MATH; - if (chNext == '$') { - i++; - chNext = styler.SafeGetCharAt(i + 1); - } - break; - case '%' : - styler.ColourTo(i - 1, state); - state = SCE_L_COMMENT; - break; - } - break; - case SCE_L_COMMAND : - if (chNext == '[' || chNext == '{' || chNext == '}' || - chNext == ' ' || chNext == '\r' || chNext == '\n') { - styler.ColourTo(i, state); - state = SCE_L_DEFAULT; - i++; - chNext = styler.SafeGetCharAt(i + 1); - } - break; - case SCE_L_TAG : - if (ch == '}') { - styler.ColourTo(i, state); - state = SCE_L_DEFAULT; - } - break; - case SCE_L_MATH : - if (ch == '$') { - if (chNext == '$') { - i++; - chNext = styler.SafeGetCharAt(i + 1); - } - styler.ColourTo(i, state); - state = SCE_L_DEFAULT; - } - break; - case SCE_L_COMMENT : - if (ch == '\r' || ch == '\n') { - styler.ColourTo(i - 1, state); - state = SCE_L_DEFAULT; - } - } - } - styler.ColourTo(lengthDoc-1, state); -} - -static const char *const batchWordListDesc[] = { - "Internal Commands", - "External Commands", - 0 -}; - -static const char *const emptyWordListDesc[] = { - 0 -}; - -static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[], - Accessor &styler) { - // Null language means all style bytes are 0 so just mark the end - no need to fill in. - if (length > 0) { - styler.StartAt(startPos + length - 1); - styler.StartSegment(startPos + length - 1); - styler.ColourTo(startPos + length - 1, 0); - } -} - -LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", 0, batchWordListDesc); -LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", FoldDiffDoc, emptyWordListDesc); -LexerModule lmPo(SCLEX_PO, ColourisePoDoc, "po", 0, emptyWordListDesc); -LexerModule lmProps(SCLEX_PROPERTIES, ColourisePropsDoc, "props", FoldPropsDoc, emptyWordListDesc); -LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc); -LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", 0, emptyWordListDesc); -LexerModule lmLatex(SCLEX_LATEX, ColouriseLatexDoc, "latex", 0, emptyWordListDesc); -LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null"); diff --git a/src/LexPB.cxx b/src/LexPB.cxx deleted file mode 100644 index abc0ddc79..000000000 --- a/src/LexPB.cxx +++ /dev/null @@ -1,362 +0,0 @@ -// Scintilla source code edit control -// @file LexPB.cxx -// Lexer for PowerBasic by Roland Walter, roland@rowalt.de (for PowerBasic see www.powerbasic.com) -// -// Changes: -// 17.10.2003: Toggling of subs/functions now until next sub/function - this gives better results -// 29.10.2003: 1. Bug: Toggling didn't work for subs/functions added in editor -// 2. Own colors for PB constants and Inline Assembler SCE_B_CONSTANT and SCE_B_ASM -// 3. Several smaller syntax coloring improvements and speed optimizations -// 12.07.2004: 1. Toggling for macros added -// 2. Further folding speed optimitations (for people dealing with very large listings) -// -// Necessary changes for the PB lexer in Scintilla project: -// - In SciLexer.h and Scintilla.iface: -// -// #define SCLEX_POWERBASIC 51 //ID for PowerBasic lexer -// (...) -// #define SCE_B_DEFAULT 0 //in both VB and PB lexer -// #define SCE_B_COMMENT 1 //in both VB and PB lexer -// #define SCE_B_NUMBER 2 //in both VB and PB lexer -// #define SCE_B_KEYWORD 3 //in both VB and PB lexer -// #define SCE_B_STRING 4 //in both VB and PB lexer -// #define SCE_B_PREPROCESSOR 5 //VB lexer only, not in PB lexer -// #define SCE_B_OPERATOR 6 //in both VB and PB lexer -// #define SCE_B_IDENTIFIER 7 //in both VB and PB lexer -// #define SCE_B_DATE 8 //VB lexer only, not in PB lexer -// #define SCE_B_CONSTANT 13 //PB lexer only, not in VB lexer -// #define SCE_B_ASM 14 //PB lexer only, not in VB lexer - -// - Statement added to KeyWords.cxx: 'LINK_LEXER(lmPB);' -// - Statement added to scintilla_vc6.mak: '$(DIR_O)\LexPB.obj: ...\src\LexPB.cxx $(LEX_HEADERS)' -// -// Copyright for Scintilla: 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsTypeCharacter(const int ch) -{ - return ch == '%' || ch == '&' || ch == '@' || ch == '!' || ch == '#' || ch == '$' || ch == '?'; -} - -static inline bool IsAWordChar(const int ch) -{ - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); -} - -static inline bool IsAWordStart(const int ch) -{ - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -bool MatchUpperCase(Accessor &styler, int pos, const char *s) //Same as styler.Match() but uppercase comparison (a-z,A-Z and space only) -{ - char ch; - for (int i=0; *s; i++) - { - ch=styler.SafeGetCharAt(pos+i); - if (ch > 0x60) ch -= '\x20'; - if (*s != ch) return false; - s++; - } - return true; -} - -static void ColourisePBDoc(unsigned int startPos, int length, int initStyle,WordList *keywordlists[],Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - - styler.StartAt(startPos); - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - switch (sc.state) - { - case SCE_B_OPERATOR: - { - sc.SetState(SCE_B_DEFAULT); - break; - } - case SCE_B_KEYWORD: - { - if (!IsAWordChar(sc.ch)) - { - if (!IsTypeCharacter(sc.ch)) - { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords.InList(s)) - { - if (strcmp(s, "rem") == 0) - { - sc.ChangeState(SCE_B_COMMENT); - if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);} - } - else if (strcmp(s, "asm") == 0) - { - sc.ChangeState(SCE_B_ASM); - if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);} - } - else - { - sc.SetState(SCE_B_DEFAULT); - } - } - else - { - sc.ChangeState(SCE_B_IDENTIFIER); - sc.SetState(SCE_B_DEFAULT); - } - } - } - break; - } - case SCE_B_NUMBER: - { - if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_B_DEFAULT);} - break; - } - case SCE_B_STRING: - { - if (sc.ch == '\"'){sc.ForwardSetState(SCE_B_DEFAULT);} - break; - } - case SCE_B_CONSTANT: - { - if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_B_DEFAULT);} - break; - } - case SCE_B_COMMENT: - { - if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);} - break; - } - case SCE_B_ASM: - { - if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);} - break; - } - } //switch (sc.state) - - // Determine if a new state should be entered: - if (sc.state == SCE_B_DEFAULT) - { - if (sc.ch == '\'') {sc.SetState(SCE_B_COMMENT);} - else if (sc.ch == '\"') {sc.SetState(SCE_B_STRING);} - else if (sc.ch == '&' && tolower(sc.chNext) == 'h') {sc.SetState(SCE_B_NUMBER);} - else if (sc.ch == '&' && tolower(sc.chNext) == 'b') {sc.SetState(SCE_B_NUMBER);} - else if (sc.ch == '&' && tolower(sc.chNext) == 'o') {sc.SetState(SCE_B_NUMBER);} - else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {sc.SetState(SCE_B_NUMBER);} - else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_B_KEYWORD);} - else if (sc.ch == '%') {sc.SetState(SCE_B_CONSTANT);} - else if (sc.ch == '$') {sc.SetState(SCE_B_CONSTANT);} - else if (sc.ch == '#') {sc.SetState(SCE_B_KEYWORD);} - else if (sc.ch == '!') {sc.SetState(SCE_B_ASM);} - else if (isoperator(static_cast(sc.ch)) || (sc.ch == '\\')) {sc.SetState(SCE_B_OPERATOR);} - } - } //for (; sc.More(); sc.Forward()) - sc.Complete(); -} - -//The folding routine for PowerBasic toggles SUBs and FUNCTIONs only. This was exactly what I wanted, -//nothing more. I had worked with this kind of toggling for several years when I used the great good old -//GFA Basic which is dead now. After testing the feature of toggling FOR-NEXT loops, WHILE-WEND loops -//and so on too I found this is more disturbing then helping (for me). So if You think in another way -//you can (or must) write Your own toggling routine ;-) -static void FoldPBDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) -{ - // No folding enabled, no reason to continue... - if( styler.GetPropertyInt("fold") == 0 ) - return; - - unsigned int endPos = startPos + length; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelNext = levelCurrent; - char chNext = styler[startPos]; - - bool fNewLine=true; - bool fMightBeMultiLineMacro=false; - bool fBeginOfCommentFound=false; - for (unsigned int i = startPos; i < endPos; i++) - { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if (fNewLine) //Begin of a new line (The Sub/Function/Macro keywords may occur at begin of line only) - { - fNewLine=false; - fBeginOfCommentFound=false; - switch (ch) - { - case ' ': //Most lines start with space - so check this first, the code is the same as for 'default:' - case '\t': //Handle tab too - { - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - styler.SetLevel(lineCurrent, lev); - break; - } - case 'F': - case 'f': - { - switch (chNext) - { - case 'U': - case 'u': - { - if( MatchUpperCase(styler,i,"FUNCTION") ) - { - styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG); - levelNext=SC_FOLDLEVELBASE+1; - } - break; - } - } - break; - } - case 'S': - case 's': - { - switch (chNext) - { - case 'U': - case 'u': - { - if( MatchUpperCase(styler,i,"SUB") ) - { - styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG); - levelNext=SC_FOLDLEVELBASE+1; - } - break; - } - case 'T': - case 't': - { - if( MatchUpperCase(styler,i,"STATIC FUNCTION") ) - { - styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG); - levelNext=SC_FOLDLEVELBASE+1; - } - else if( MatchUpperCase(styler,i,"STATIC SUB") ) - { - styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG); - levelNext=SC_FOLDLEVELBASE+1; - } - break; - } - } - break; - } - case 'C': - case 'c': - { - switch (chNext) - { - case 'A': - case 'a': - { - if( MatchUpperCase(styler,i,"CALLBACK FUNCTION") ) - { - styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG); - levelNext=SC_FOLDLEVELBASE+1; - } - break; - } - } - break; - } - case 'M': - case 'm': - { - switch (chNext) - { - case 'A': - case 'a': - { - if( MatchUpperCase(styler,i,"MACRO") ) - { - fMightBeMultiLineMacro=true; //Set folder level at end of line, we have to check for single line macro - } - break; - } - } - break; - } - default: - { - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - styler.SetLevel(lineCurrent, lev); - break; - } - } //switch (ch) - } //if( fNewLine ) - - switch (ch) - { - case '=': //To test single line macros - { - if (fBeginOfCommentFound==false) - fMightBeMultiLineMacro=false; //The found macro is a single line macro only; - break; - } - case '\'': //A comment starts - { - fBeginOfCommentFound=true; - break; - } - case '\n': - { - if (fMightBeMultiLineMacro) //The current line is the begin of a multi line macro - { - fMightBeMultiLineMacro=false; - styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG); - levelNext=SC_FOLDLEVELBASE+1; - } - lineCurrent++; - levelCurrent = levelNext; - fNewLine=true; - break; - } - case '\r': - { - if (chNext != '\n') - { - lineCurrent++; - levelCurrent = levelNext; - fNewLine=true; - } - break; - } - } //switch (ch) - } //for (unsigned int i = startPos; i < endPos; i++) -} - -static const char * const pbWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmPB(SCLEX_POWERBASIC, ColourisePBDoc, "powerbasic", FoldPBDoc, pbWordListDesc); diff --git a/src/LexPLM.cxx b/src/LexPLM.cxx deleted file mode 100644 index 604850fbe..000000000 --- a/src/LexPLM.cxx +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright (c) 1990-2007, Scientific Toolworks, Inc. -// Author: Jason Haslam -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "StyleContext.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static void GetRange(unsigned int start, - unsigned int end, - Accessor &styler, - char *s, - unsigned int len) { - unsigned int i = 0; - while ((i < end - start + 1) && (i < len-1)) { - s[i] = static_cast(tolower(styler[start + i])); - i++; - } - s[i] = '\0'; -} - -static void ColourisePlmDoc(unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) -{ - unsigned int endPos = startPos + length; - int state = initStyle; - - styler.StartAt(startPos); - styler.StartSegment(startPos); - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = styler.SafeGetCharAt(i); - char chNext = styler.SafeGetCharAt(i + 1); - - if (state == SCE_PLM_DEFAULT) { - if (ch == '/' && chNext == '*') { - styler.ColourTo(i - 1, state); - state = SCE_PLM_COMMENT; - } else if (ch == '\'') { - styler.ColourTo(i - 1, state); - state = SCE_PLM_STRING; - } else if (isdigit(ch)) { - styler.ColourTo(i - 1, state); - state = SCE_PLM_NUMBER; - } else if (isalpha(ch)) { - styler.ColourTo(i - 1, state); - state = SCE_PLM_IDENTIFIER; - } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || - ch == '=' || ch == '<' || ch == '>' || ch == ':') { - styler.ColourTo(i - 1, state); - state = SCE_PLM_OPERATOR; - } else if (ch == '$') { - styler.ColourTo(i - 1, state); - state = SCE_PLM_CONTROL; - } - } else if (state == SCE_PLM_COMMENT) { - if (ch == '*' && chNext == '/') { - i++; - styler.ColourTo(i, state); - state = SCE_PLM_DEFAULT; - } - } else if (state == SCE_PLM_STRING) { - if (ch == '\'') { - if (chNext == '\'') { - i++; - } else { - styler.ColourTo(i, state); - state = SCE_PLM_DEFAULT; - } - } - } else if (state == SCE_PLM_NUMBER) { - if (!isdigit(ch) && !isalpha(ch) && ch != '$') { - i--; - styler.ColourTo(i, state); - state = SCE_PLM_DEFAULT; - } - } else if (state == SCE_PLM_IDENTIFIER) { - if (!isdigit(ch) && !isalpha(ch) && ch != '$') { - // Get the entire identifier. - char word[1024]; - int segmentStart = styler.GetStartSegment(); - GetRange(segmentStart, i - 1, styler, word, sizeof(word)); - - i--; - if (keywordlists[0]->InList(word)) - styler.ColourTo(i, SCE_PLM_KEYWORD); - else - styler.ColourTo(i, state); - state = SCE_PLM_DEFAULT; - } - } else if (state == SCE_PLM_OPERATOR) { - if (ch != '=' && ch != '>') { - i--; - styler.ColourTo(i, state); - state = SCE_PLM_DEFAULT; - } - } else if (state == SCE_PLM_CONTROL) { - if (ch == '\r' || ch == '\n') { - styler.ColourTo(i - 1, state); - state = SCE_PLM_DEFAULT; - } - } - } - styler.ColourTo(endPos - 1, state); -} - -static void FoldPlmDoc(unsigned int startPos, - int length, - int initStyle, - WordList *[], - Accessor &styler) -{ - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - int startKeyword = 0; - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - if (stylePrev != SCE_PLM_KEYWORD && style == SCE_PLM_KEYWORD) - startKeyword = i; - - if (style == SCE_PLM_KEYWORD && styleNext != SCE_PLM_KEYWORD) { - char word[1024]; - GetRange(startKeyword, i, styler, word, sizeof(word)); - - if (strcmp(word, "procedure") == 0 || strcmp(word, "do") == 0) - levelCurrent++; - else if (strcmp(word, "end") == 0) - levelCurrent--; - } - - if (foldComment) { - if (stylePrev != SCE_PLM_COMMENT && style == SCE_PLM_COMMENT) - levelCurrent++; - else if (stylePrev == SCE_PLM_COMMENT && style != SCE_PLM_COMMENT) - levelCurrent--; - } - - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - - if (!isspacechar(ch)) - visibleChars++; - } - - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char *const plmWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmPLM(SCLEX_PLM, ColourisePlmDoc, "PL/M", FoldPlmDoc, plmWordListDesc); diff --git a/src/LexPOV.cxx b/src/LexPOV.cxx deleted file mode 100644 index b845b2d47..000000000 --- a/src/LexPOV.cxx +++ /dev/null @@ -1,316 +0,0 @@ -// Scintilla source code edit control -/** @file LexPOV.cxx - ** Lexer for POV-Ray SDL (Persistance of Vision Raytracer, Scene Description Language). - ** Written by Philippe Lhoste but this is mostly a derivative of LexCPP... - **/ -// Copyright 1998-2005 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -// Some points that distinguish from a simple C lexer: -// Identifiers start only by a character. -// No line continuation character. -// Strings are limited to 256 characters. -// Directives are similar to preprocessor commands, -// but we match directive keywords and colorize incorrect ones. -// Block comments can be nested (code stolen from my code in LexLua). - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(int ch) { - return ch < 0x80 && (isalnum(ch) || ch == '_'); -} - -static inline bool IsAWordStart(int ch) { - return ch < 0x80 && isalpha(ch); -} - -static inline bool IsANumberChar(int ch) { - // Not exactly following number definition (several dots are seen as OK, etc.) - // but probably enough in most cases. - return (ch < 0x80) && - (isdigit(ch) || toupper(ch) == 'E' || - ch == '.' || ch == '-' || ch == '+'); -} - -static void ColourisePovDoc( - unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords1 = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - WordList &keywords6 = *keywordlists[5]; - WordList &keywords7 = *keywordlists[6]; - WordList &keywords8 = *keywordlists[7]; - - int currentLine = styler.GetLine(startPos); - // Initialize the block comment /* */ nesting level, if we are inside such a comment. - int blockCommentLevel = 0; - if (initStyle == SCE_POV_COMMENT) { - blockCommentLevel = styler.GetLineState(currentLine - 1); - } - - // Do not leak onto next line - if (initStyle == SCE_POV_STRINGEOL || initStyle == SCE_POV_COMMENTLINE) { - initStyle = SCE_POV_DEFAULT; - } - - short stringLen = 0; - - StyleContext sc(startPos, length, initStyle, styler); - - 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); - if (sc.state == SCE_POV_COMMENT) { - // Inside a block comment, we set the line state - styler.SetLineState(currentLine, blockCommentLevel); - } else { - // Reset the line state - styler.SetLineState(currentLine, 0); - } - } - - if (sc.atLineStart && (sc.state == SCE_POV_STRING)) { - // Prevent SCE_POV_STRINGEOL from leaking back to previous line - sc.SetState(SCE_POV_STRING); - } - - // Determine if the current state should terminate. - if (sc.state == SCE_POV_OPERATOR) { - sc.SetState(SCE_POV_DEFAULT); - } else if (sc.state == SCE_POV_NUMBER) { - // We stop the number definition on non-numerical non-dot non-eE non-sign char - if (!IsANumberChar(sc.ch)) { - sc.SetState(SCE_POV_DEFAULT); - } - } else if (sc.state == SCE_POV_IDENTIFIER) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if (keywords2.InList(s)) { - sc.ChangeState(SCE_POV_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_POV_WORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_POV_WORD4); - } else if (keywords5.InList(s)) { - sc.ChangeState(SCE_POV_WORD5); - } else if (keywords6.InList(s)) { - sc.ChangeState(SCE_POV_WORD6); - } else if (keywords7.InList(s)) { - sc.ChangeState(SCE_POV_WORD7); - } else if (keywords8.InList(s)) { - sc.ChangeState(SCE_POV_WORD8); - } - sc.SetState(SCE_POV_DEFAULT); - } - } else if (sc.state == SCE_POV_DIRECTIVE) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - char *p; - sc.GetCurrent(s, sizeof(s)); - p = s; - // Skip # and whitespace between # and directive word - do { - p++; - } while ((*p == ' ' || *p == '\t') && *p != '\0'); - if (!keywords1.InList(p)) { - sc.ChangeState(SCE_POV_BADDIRECTIVE); - } - sc.SetState(SCE_POV_DEFAULT); - } - } else if (sc.state == SCE_POV_COMMENT) { - if (sc.Match('/', '*')) { - blockCommentLevel++; - sc.Forward(); - } else if (sc.Match('*', '/') && blockCommentLevel > 0) { - blockCommentLevel--; - sc.Forward(); - if (blockCommentLevel == 0) { - sc.ForwardSetState(SCE_POV_DEFAULT); - } - } - } else if (sc.state == SCE_POV_COMMENTLINE) { - if (sc.atLineEnd) { - sc.ForwardSetState(SCE_POV_DEFAULT); - } - } else if (sc.state == SCE_POV_STRING) { - if (sc.ch == '\\') { - stringLen++; - if (strchr("abfnrtuv0'\"", sc.chNext)) { - // Compound characters are counted as one. - // Note: for Unicode chars \u, we shouldn't count the next 4 digits... - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_POV_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_POV_STRINGEOL); - sc.ForwardSetState(SCE_POV_DEFAULT); - } else { - stringLen++; - } - if (stringLen > 256) { - // Strings are limited to 256 chars - sc.SetState(SCE_POV_STRINGEOL); - } - } else if (sc.state == SCE_POV_STRINGEOL) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_C_DEFAULT); - } else if (sc.atLineEnd) { - sc.ForwardSetState(SCE_POV_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_POV_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_POV_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_POV_IDENTIFIER); - } else if (sc.Match('/', '*')) { - blockCommentLevel = 1; - sc.SetState(SCE_POV_COMMENT); - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match('/', '/')) { - sc.SetState(SCE_POV_COMMENTLINE); - } else if (sc.ch == '\"') { - sc.SetState(SCE_POV_STRING); - stringLen = 0; - } else if (sc.ch == '#') { - sc.SetState(SCE_POV_DIRECTIVE); - // Skip whitespace between # and directive word - do { - sc.Forward(); - } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); - if (sc.atLineEnd) { - sc.SetState(SCE_POV_DEFAULT); - } - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_POV_OPERATOR); - } - } - } - sc.Complete(); -} - -static void FoldPovDoc( - unsigned int startPos, - int length, - int initStyle, - WordList *[], - Accessor &styler) { - - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldDirective = styler.GetPropertyInt("fold.directive") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && (style == SCE_POV_COMMENT)) { - if (stylePrev != SCE_POV_COMMENT) { - levelCurrent++; - } else if ((styleNext != SCE_POV_COMMENT) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelCurrent--; - } - } - if (foldComment && (style == SCE_POV_COMMENTLINE)) { - if ((ch == '/') && (chNext == '/')) { - char chNext2 = styler.SafeGetCharAt(i + 2); - if (chNext2 == '{') { - levelCurrent++; - } else if (chNext2 == '}') { - levelCurrent--; - } - } - } - if (foldDirective && (style == SCE_POV_DIRECTIVE)) { - if (ch == '#') { - unsigned int j=i+1; - while ((j levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const povWordLists[] = { - "Language directives", - "Objects & CSG & Appearance", - "Types & Modifiers & Items", - "Predefined Identifiers", - "Predefined Functions", - "User defined 1", - "User defined 2", - "User defined 3", - 0, -}; - -LexerModule lmPOV(SCLEX_POV, ColourisePovDoc, "pov", FoldPovDoc, povWordLists); diff --git a/src/LexPS.cxx b/src/LexPS.cxx deleted file mode 100644 index 2edcff150..000000000 --- a/src/LexPS.cxx +++ /dev/null @@ -1,347 +0,0 @@ -// Scintilla source code edit control -/** @file LexPS.cxx - ** Lexer for PostScript - ** - ** Written by Nigel Hathaway . - ** The License.txt file describes the conditions under which this software may be distributed. - **/ - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsASelfDelimitingChar(const int ch) { - return (ch == '[' || ch == ']' || ch == '{' || ch == '}' || - ch == '/' || ch == '<' || ch == '>' || - ch == '(' || ch == ')' || ch == '%'); -} - -static inline bool IsAWhitespaceChar(const int ch) { - return (ch == ' ' || ch == '\t' || ch == '\r' || - ch == '\n' || ch == '\f' || ch == '\0'); -} - -static bool IsABaseNDigit(const int ch, const int base) { - int maxdig = '9'; - int letterext = -1; - - if (base <= 10) - maxdig = '0' + base - 1; - else - letterext = base - 11; - - return ((ch >= '0' && ch <= maxdig) || - (ch >= 'A' && ch <= ('A' + letterext)) || - (ch >= 'a' && ch <= ('a' + letterext))); -} - -static inline bool IsABase85Char(const int ch) { - return ((ch >= '!' && ch <= 'u') || ch == 'z'); -} - -static void ColourisePSDoc( - unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords1 = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - - StyleContext sc(startPos, length, initStyle, styler); - - bool tokenizing = styler.GetPropertyInt("ps.tokenize") != 0; - int pslevel = styler.GetPropertyInt("ps.level", 3); - int lineCurrent = styler.GetLine(startPos); - int nestTextCurrent = 0; - if (lineCurrent > 0 && initStyle == SCE_PS_TEXT) - nestTextCurrent = styler.GetLineState(lineCurrent - 1); - int numRadix = 0; - bool numHasPoint = false; - bool numHasExponent = false; - bool numHasSign = false; - - // Clear out existing tokenization - if (tokenizing && length > 0) { - styler.StartAt(startPos, static_cast(INDIC2_MASK)); - styler.ColourTo(startPos + length-1, 0); - styler.Flush(); - styler.StartAt(startPos); - styler.StartSegment(startPos); - } - - for (; sc.More(); sc.Forward()) { - if (sc.atLineStart) - lineCurrent = styler.GetLine(sc.currentPos); - - // Determine if the current state should terminate. - if (sc.state == SCE_PS_COMMENT || sc.state == SCE_PS_DSC_VALUE) { - if (sc.atLineEnd) { - sc.SetState(SCE_C_DEFAULT); - } - } else if (sc.state == SCE_PS_DSC_COMMENT) { - if (sc.ch == ':') { - sc.Forward(); - if (!sc.atLineEnd) - sc.SetState(SCE_PS_DSC_VALUE); - else - sc.SetState(SCE_C_DEFAULT); - } else if (sc.atLineEnd) { - sc.SetState(SCE_C_DEFAULT); - } else if (IsAWhitespaceChar(sc.ch) && sc.ch != '\r') { - sc.ChangeState(SCE_PS_COMMENT); - } - } else if (sc.state == SCE_PS_NUMBER) { - if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) { - if ((sc.chPrev == '+' || sc.chPrev == '-' || - sc.chPrev == 'E' || sc.chPrev == 'e') && numRadix == 0) - sc.ChangeState(SCE_PS_NAME); - sc.SetState(SCE_C_DEFAULT); - } else if (sc.ch == '#') { - if (numHasPoint || numHasExponent || numHasSign || numRadix != 0) { - sc.ChangeState(SCE_PS_NAME); - } else { - char szradix[5]; - sc.GetCurrent(szradix, 4); - numRadix = atoi(szradix); - if (numRadix < 2 || numRadix > 36) - sc.ChangeState(SCE_PS_NAME); - } - } else if ((sc.ch == 'E' || sc.ch == 'e') && numRadix == 0) { - if (numHasExponent) { - sc.ChangeState(SCE_PS_NAME); - } else { - numHasExponent = true; - if (sc.chNext == '+' || sc.chNext == '-') - sc.Forward(); - } - } else if (sc.ch == '.') { - if (numHasPoint || numHasExponent || numRadix != 0) { - sc.ChangeState(SCE_PS_NAME); - } else { - numHasPoint = true; - } - } else if (numRadix == 0) { - if (!IsABaseNDigit(sc.ch, 10)) - sc.ChangeState(SCE_PS_NAME); - } else { - if (!IsABaseNDigit(sc.ch, numRadix)) - sc.ChangeState(SCE_PS_NAME); - } - } else if (sc.state == SCE_PS_NAME || sc.state == SCE_PS_KEYWORD) { - if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if ((pslevel >= 1 && keywords1.InList(s)) || - (pslevel >= 2 && keywords2.InList(s)) || - (pslevel >= 3 && keywords3.InList(s)) || - keywords4.InList(s) || keywords5.InList(s)) { - sc.ChangeState(SCE_PS_KEYWORD); - } - sc.SetState(SCE_C_DEFAULT); - } - } else if (sc.state == SCE_PS_LITERAL || sc.state == SCE_PS_IMMEVAL) { - if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) - sc.SetState(SCE_C_DEFAULT); - } else if (sc.state == SCE_PS_PAREN_ARRAY || sc.state == SCE_PS_PAREN_DICT || - sc.state == SCE_PS_PAREN_PROC) { - sc.SetState(SCE_C_DEFAULT); - } else if (sc.state == SCE_PS_TEXT) { - if (sc.ch == '(') { - nestTextCurrent++; - } else if (sc.ch == ')') { - if (--nestTextCurrent == 0) - sc.ForwardSetState(SCE_PS_DEFAULT); - } else if (sc.ch == '\\') { - sc.Forward(); - } - } else if (sc.state == SCE_PS_HEXSTRING) { - if (sc.ch == '>') { - sc.ForwardSetState(SCE_PS_DEFAULT); - } else if (!IsABaseNDigit(sc.ch, 16) && !IsAWhitespaceChar(sc.ch)) { - sc.SetState(SCE_PS_HEXSTRING); - styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR); - } - } else if (sc.state == SCE_PS_BASE85STRING) { - if (sc.Match('~', '>')) { - sc.Forward(); - sc.ForwardSetState(SCE_PS_DEFAULT); - } else if (!IsABase85Char(sc.ch) && !IsAWhitespaceChar(sc.ch)) { - sc.SetState(SCE_PS_BASE85STRING); - styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_C_DEFAULT) { - unsigned int tokenpos = sc.currentPos; - - if (sc.ch == '[' || sc.ch == ']') { - sc.SetState(SCE_PS_PAREN_ARRAY); - } else if (sc.ch == '{' || sc.ch == '}') { - sc.SetState(SCE_PS_PAREN_PROC); - } else if (sc.ch == '/') { - if (sc.chNext == '/') { - sc.SetState(SCE_PS_IMMEVAL); - sc.Forward(); - } else { - sc.SetState(SCE_PS_LITERAL); - } - } else if (sc.ch == '<') { - if (sc.chNext == '<') { - sc.SetState(SCE_PS_PAREN_DICT); - sc.Forward(); - } else if (sc.chNext == '~') { - sc.SetState(SCE_PS_BASE85STRING); - sc.Forward(); - } else { - sc.SetState(SCE_PS_HEXSTRING); - } - } else if (sc.ch == '>' && sc.chNext == '>') { - sc.SetState(SCE_PS_PAREN_DICT); - sc.Forward(); - } else if (sc.ch == '>' || sc.ch == ')') { - sc.SetState(SCE_C_DEFAULT); - styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR); - } else if (sc.ch == '(') { - sc.SetState(SCE_PS_TEXT); - nestTextCurrent = 1; - } else if (sc.ch == '%') { - if (sc.chNext == '%' && sc.atLineStart) { - sc.SetState(SCE_PS_DSC_COMMENT); - sc.Forward(); - if (sc.chNext == '+') { - sc.Forward(); - sc.ForwardSetState(SCE_PS_DSC_VALUE); - } - } else { - sc.SetState(SCE_PS_COMMENT); - } - } else if ((sc.ch == '+' || sc.ch == '-' || sc.ch == '.') && - IsABaseNDigit(sc.chNext, 10)) { - sc.SetState(SCE_PS_NUMBER); - numRadix = 0; - numHasPoint = (sc.ch == '.'); - numHasExponent = false; - numHasSign = (sc.ch == '+' || sc.ch == '-'); - } else if ((sc.ch == '+' || sc.ch == '-') && sc.chNext == '.' && - IsABaseNDigit(sc.GetRelative(2), 10)) { - sc.SetState(SCE_PS_NUMBER); - numRadix = 0; - numHasPoint = false; - numHasExponent = false; - numHasSign = true; - } else if (IsABaseNDigit(sc.ch, 10)) { - sc.SetState(SCE_PS_NUMBER); - numRadix = 0; - numHasPoint = false; - numHasExponent = false; - numHasSign = false; - } else if (!IsAWhitespaceChar(sc.ch)) { - sc.SetState(SCE_PS_NAME); - } - - // Mark the start of tokens - if (tokenizing && sc.state != SCE_C_DEFAULT && sc.state != SCE_PS_COMMENT && - sc.state != SCE_PS_DSC_COMMENT && sc.state != SCE_PS_DSC_VALUE) { - styler.Flush(); - styler.StartAt(tokenpos, static_cast(INDIC2_MASK)); - styler.ColourTo(tokenpos, INDIC2_MASK); - styler.Flush(); - styler.StartAt(tokenpos); - styler.StartSegment(tokenpos); - } - } - - if (sc.atLineEnd) - styler.SetLineState(lineCurrent, nestTextCurrent); - } - - sc.Complete(); -} - -static void FoldPSDoc(unsigned int startPos, int length, int, WordList *[], - Accessor &styler) { - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelMinCurrent = levelCurrent; - int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); //mac?? - if ((style & 31) == SCE_PS_PAREN_PROC) { - if (ch == '{') { - // Measure the minimum before a '{' to allow - // folding on "} {" - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - levelNext++; - } else if (ch == '}') { - levelNext--; - } - } - if (atEOL) { - int levelUse = levelCurrent; - if (foldAtElse) { - levelUse = levelMinCurrent; - } - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - levelMinCurrent = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } -} - -static const char * const psWordListDesc[] = { - "PS Level 1 operators", - "PS Level 2 operators", - "PS Level 3 operators", - "RIP-specific operators", - "User-defined operators", - 0 -}; - -LexerModule lmPS(SCLEX_PS, ColourisePSDoc, "ps", FoldPSDoc, psWordListDesc); diff --git a/src/LexPascal.cxx b/src/LexPascal.cxx deleted file mode 100644 index 3dcf35ad5..000000000 --- a/src/LexPascal.cxx +++ /dev/null @@ -1,592 +0,0 @@ -// Scintilla source code edit control -/** @file LexPascal.cxx - ** Lexer for Pascal. - ** Written by Laurent le Tynevez - ** Updated by Simon Steele September 2002 - ** Updated by Mathias Rauen May 2003 (Delphi adjustments) - ** Completely rewritten by Marko Njezic October 2008 - **/ - -/* - -A few words about features of the new completely rewritten LexPascal... - -Generally speaking LexPascal tries to support all available Delphi features (up -to Delphi 2009 at this time), including .NET specific features. - -~ HIGHLIGHTING: - -If you enable "lexer.pascal.smart.highlighting" property, some keywords will -only be highlighted in appropriate context. As implemented those are keywords -related to property and DLL exports declarations (similar to how Delphi IDE -works). - -For example, keywords "read" and "write" will only be highlighted if they are in -property declaration: - -property MyProperty: boolean read FMyProperty write FMyProperty; - -~ FOLDING: - -Folding is supported in the following cases: - -- Folding of stream-like comments -- Folding of groups of consecutive line comments -- Folding of preprocessor blocks (the following preprocessor blocks are -supported: IF / IFEND; IFDEF, IFNDEF, IFOPT / ENDIF and REGION / ENDREGION -blocks), including nesting of preprocessor blocks up to 255 levels -- Folding of code blocks on appropriate keywords (the following code blocks are -supported: "begin, asm, record, try, case / end" blocks, class & object -declarations and interface declarations) - -Remarks: - -- Folding of code blocks tries to handle all special cases in which folding -should not occur. As implemented those are: - -1. Structure "record case / end" (there's only one "end" statement and "case" is -ignored as fold point) -2. Forward class declarations ("type TMyClass = class;") and object method -declarations ("TNotifyEvent = procedure(Sender: TObject) of object;") are -ignored as fold points -3. Simplified complete class declarations ("type TMyClass = class(TObject);") -are ignored as fold points -4. Every other situation when class keyword doesn't actually start class -declaration ("class procedure", "class function", "class of", "class var", -"class property" and "class operator") - -- Folding of code blocks inside preprocessor blocks is disabled (any comments -inside them will be folded fine) because there is no guarantee that complete -code block will be contained inside folded preprocessor block in which case -folded code block could end prematurely at the end of preprocessor block if -there is no closing statement inside. This was done in order to properly process -document that may contain something like this: - -type -{$IFDEF UNICODE} - TMyClass = class(UnicodeAncestor) -{$ELSE} - TMyClass = class(AnsiAncestor) -{$ENDIF} - private - ... - public - ... - published - ... -end; - -If class declarations were folded, then the second class declaration would end -at "$ENDIF" statement, first class statement would end at "end;" statement and -preprocessor "$IFDEF" block would go all the way to the end of document. -However, having in mind all this, if you want to enable folding of code blocks -inside preprocessor blocks, you can disable folding of preprocessor blocks by -changing "fold.preprocessor" property, in which case everything inside them -would be folded. - -~ KEYWORDS: - -The list of keywords that can be used in pascal.properties file (up to Delphi -2009): - -- Keywords: absolute abstract and array as asm assembler automated begin case -cdecl class const constructor deprecated destructor dispid dispinterface div do -downto dynamic else end except export exports external far file final -finalization finally for forward function goto if implementation in inherited -initialization inline interface is label library message mod near nil not object -of on or out overload override packed pascal platform private procedure program -property protected public published raise record register reintroduce repeat -resourcestring safecall sealed set shl shr static stdcall strict string then -threadvar to try type unit unsafe until uses var varargs virtual while with xor - -- Keywords related to the "smart highlithing" feature: add default implements -index name nodefault read readonly remove stored write writeonly - -- Keywords related to Delphi packages (in addition to all above): package -contains requires - -*/ - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "StyleContext.h" -#include "CharacterSet.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static void GetRangeLowered(unsigned int start, - unsigned int end, - Accessor &styler, - char *s, - unsigned int len) { - unsigned int i = 0; - while ((i < end - start + 1) && (i < len-1)) { - s[i] = static_cast(tolower(styler[start + i])); - i++; - } - s[i] = '\0'; -} - -static void GetForwardRangeLowered(unsigned int start, - CharacterSet &charSet, - Accessor &styler, - char *s, - unsigned int len) { - unsigned int i = 0; - while ((i < len-1) && charSet.Contains(styler.SafeGetCharAt(start + i))) { - s[i] = static_cast(tolower(styler.SafeGetCharAt(start + i))); - i++; - } - s[i] = '\0'; - -} - -enum { - stateInAsm = 0x1000, - stateInProperty = 0x2000, - stateInExport = 0x4000, - stateFoldInPreprocessor = 0x0100, - stateFoldInRecord = 0x0200, - stateFoldInPreprocessorLevelMask = 0x00FF, - stateFoldMaskAll = 0x0FFF -}; - -static void ClassifyPascalWord(WordList *keywordlists[], StyleContext &sc, int &curLineState, bool bSmartHighlighting) { - WordList& keywords = *keywordlists[0]; - - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords.InList(s)) { - if (curLineState & stateInAsm) { - if (strcmp(s, "end") == 0 && sc.GetRelative(-4) != '@') { - curLineState &= ~stateInAsm; - sc.ChangeState(SCE_PAS_WORD); - } else { - sc.ChangeState(SCE_PAS_ASM); - } - } else { - bool ignoreKeyword = false; - if (strcmp(s, "asm") == 0) { - curLineState |= stateInAsm; - } else if (bSmartHighlighting) { - if (strcmp(s, "property") == 0) { - curLineState |= stateInProperty; - } else if (strcmp(s, "exports") == 0) { - curLineState |= stateInExport; - } else if (!(curLineState & (stateInProperty | stateInExport)) && strcmp(s, "index") == 0) { - ignoreKeyword = true; - } else if (!(curLineState & stateInExport) && strcmp(s, "name") == 0) { - ignoreKeyword = true; - } else if (!(curLineState & stateInProperty) && - (strcmp(s, "read") == 0 || strcmp(s, "write") == 0 || - strcmp(s, "default") == 0 || strcmp(s, "nodefault") == 0 || - strcmp(s, "stored") == 0 || strcmp(s, "implements") == 0 || - strcmp(s, "readonly") == 0 || strcmp(s, "writeonly") == 0 || - strcmp(s, "add") == 0 || strcmp(s, "remove") == 0)) { - ignoreKeyword = true; - } - } - if (!ignoreKeyword) { - sc.ChangeState(SCE_PAS_WORD); - } - } - } else if (curLineState & stateInAsm) { - sc.ChangeState(SCE_PAS_ASM); - } - sc.SetState(SCE_PAS_DEFAULT); -} - -static void ColourisePascalDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - bool bSmartHighlighting = styler.GetPropertyInt("lexer.pascal.smart.highlighting", 1) != 0; - - CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true); - CharacterSet setNumber(CharacterSet::setDigits, ".-+eE"); - CharacterSet setHexNumber(CharacterSet::setDigits, "abcdefABCDEF"); - CharacterSet setOperator(CharacterSet::setNone, "#$&'()*+,-./:;<=>@[]^{}"); - - int curLine = styler.GetLine(startPos); - int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : 0; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - if (sc.atLineEnd) { - // Update the line state, so it can be seen by next line - curLine = styler.GetLine(sc.currentPos); - styler.SetLineState(curLine, curLineState); - } - - // Determine if the current state should terminate. - switch (sc.state) { - case SCE_PAS_NUMBER: - if (!setNumber.Contains(sc.ch) || (sc.ch == '.' && sc.chNext == '.')) { - sc.SetState(SCE_PAS_DEFAULT); - } else if (sc.ch == '-' || sc.ch == '+') { - if (sc.chPrev != 'E' && sc.chPrev != 'e') { - sc.SetState(SCE_PAS_DEFAULT); - } - } - break; - case SCE_PAS_IDENTIFIER: - if (!setWord.Contains(sc.ch)) { - ClassifyPascalWord(keywordlists, sc, curLineState, bSmartHighlighting); - } - break; - case SCE_PAS_HEXNUMBER: - if (!setHexNumber.Contains(sc.ch)) { - sc.SetState(SCE_PAS_DEFAULT); - } - break; - case SCE_PAS_COMMENT: - case SCE_PAS_PREPROCESSOR: - if (sc.ch == '}') { - sc.ForwardSetState(SCE_PAS_DEFAULT); - } - break; - case SCE_PAS_COMMENT2: - case SCE_PAS_PREPROCESSOR2: - if (sc.Match('*', ')')) { - sc.Forward(); - sc.ForwardSetState(SCE_PAS_DEFAULT); - } - break; - case SCE_PAS_COMMENTLINE: - if (sc.atLineStart) { - sc.SetState(SCE_PAS_DEFAULT); - } - break; - case SCE_PAS_STRING: - if (sc.atLineEnd) { - sc.ChangeState(SCE_PAS_STRINGEOL); - } else if (sc.ch == '\'' && sc.chNext == '\'') { - sc.Forward(); - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_PAS_DEFAULT); - } - break; - case SCE_PAS_STRINGEOL: - if (sc.atLineStart) { - sc.SetState(SCE_PAS_DEFAULT); - } - break; - case SCE_PAS_CHARACTER: - if (!setHexNumber.Contains(sc.ch) && sc.ch != '$') { - sc.SetState(SCE_PAS_DEFAULT); - } - break; - case SCE_PAS_OPERATOR: - if (bSmartHighlighting && sc.chPrev == ';') { - curLineState &= ~(stateInProperty | stateInExport); - } - sc.SetState(SCE_PAS_DEFAULT); - break; - case SCE_PAS_ASM: - sc.SetState(SCE_PAS_DEFAULT); - break; - } - - // Determine if a new state should be entered. - if (sc.state == SCE_PAS_DEFAULT) { - if (IsADigit(sc.ch) && !(curLineState & stateInAsm)) { - sc.SetState(SCE_PAS_NUMBER); - } else if (setWordStart.Contains(sc.ch)) { - sc.SetState(SCE_PAS_IDENTIFIER); - } else if (sc.ch == '$' && !(curLineState & stateInAsm)) { - sc.SetState(SCE_PAS_HEXNUMBER); - } else if (sc.Match('{', '$')) { - sc.SetState(SCE_PAS_PREPROCESSOR); - } else if (sc.ch == '{') { - sc.SetState(SCE_PAS_COMMENT); - } else if (sc.Match("(*$")) { - sc.SetState(SCE_PAS_PREPROCESSOR2); - } else if (sc.Match('(', '*')) { - sc.SetState(SCE_PAS_COMMENT2); - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match('/', '/')) { - sc.SetState(SCE_PAS_COMMENTLINE); - } else if (sc.ch == '\'') { - sc.SetState(SCE_PAS_STRING); - } else if (sc.ch == '#') { - sc.SetState(SCE_PAS_CHARACTER); - } else if (setOperator.Contains(sc.ch) && !(curLineState & stateInAsm)) { - sc.SetState(SCE_PAS_OPERATOR); - } else if (curLineState & stateInAsm) { - sc.SetState(SCE_PAS_ASM); - } - } - } - - if (sc.state == SCE_PAS_IDENTIFIER && setWord.Contains(sc.chPrev)) { - ClassifyPascalWord(keywordlists, sc, curLineState, bSmartHighlighting); - } - - sc.Complete(); -} - -static bool IsStreamCommentStyle(int style) { - return style == SCE_PAS_COMMENT || style == SCE_PAS_COMMENT2; -} - -static bool IsCommentLine(int line, Accessor &styler) { - int pos = styler.LineStart(line); - int eolPos = styler.LineStart(line + 1) - 1; - for (int i = pos; i < eolPos; i++) { - char ch = styler[i]; - char chNext = styler.SafeGetCharAt(i + 1); - int style = styler.StyleAt(i); - if (ch == '/' && chNext == '/' && style == SCE_PAS_COMMENTLINE) { - return true; - } else if (!IsASpaceOrTab(ch)) { - return false; - } - } - return false; -} - -static unsigned int GetFoldInPreprocessorLevelFlag(int lineFoldStateCurrent) { - return lineFoldStateCurrent & stateFoldInPreprocessorLevelMask; -} - -static void SetFoldInPreprocessorLevelFlag(int &lineFoldStateCurrent, unsigned int nestLevel) { - lineFoldStateCurrent &= ~stateFoldInPreprocessorLevelMask; - lineFoldStateCurrent |= nestLevel & stateFoldInPreprocessorLevelMask; -} - -static void ClassifyPascalPreprocessorFoldPoint(int &levelCurrent, int &lineFoldStateCurrent, - unsigned int startPos, Accessor &styler) { - CharacterSet setWord(CharacterSet::setAlpha); - - char s[11]; // Size of the longest possible keyword + one additional character + null - GetForwardRangeLowered(startPos, setWord, styler, s, sizeof(s)); - - unsigned int nestLevel = GetFoldInPreprocessorLevelFlag(lineFoldStateCurrent); - - if (strcmp(s, "if") == 0 || - strcmp(s, "ifdef") == 0 || - strcmp(s, "ifndef") == 0 || - strcmp(s, "ifopt") == 0 || - strcmp(s, "region") == 0) { - nestLevel++; - SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel); - lineFoldStateCurrent |= stateFoldInPreprocessor; - levelCurrent++; - } else if (strcmp(s, "endif") == 0 || - strcmp(s, "ifend") == 0 || - strcmp(s, "endregion") == 0) { - nestLevel--; - SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel); - if (nestLevel == 0) { - lineFoldStateCurrent &= ~stateFoldInPreprocessor; - } - levelCurrent--; - if (levelCurrent < SC_FOLDLEVELBASE) { - levelCurrent = SC_FOLDLEVELBASE; - } - } -} - -static unsigned int SkipWhiteSpace(unsigned int currentPos, unsigned int endPos, - Accessor &styler, bool includeChars = false) { - CharacterSet setWord(CharacterSet::setAlphaNum, "_"); - unsigned int j = currentPos + 1; - char ch = styler.SafeGetCharAt(j); - while ((j < endPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' || - IsStreamCommentStyle(styler.StyleAt(j)) || (includeChars && setWord.Contains(ch)))) { - j++; - ch = styler.SafeGetCharAt(j); - } - return j; -} - -static void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCurrent, - int startPos, unsigned int endPos, - unsigned int lastStart, unsigned int currentPos, Accessor &styler) { - char s[100]; - GetRangeLowered(lastStart, currentPos, styler, s, sizeof(s)); - - if (strcmp(s, "record") == 0) { - lineFoldStateCurrent |= stateFoldInRecord; - levelCurrent++; - } else if (strcmp(s, "begin") == 0 || - strcmp(s, "asm") == 0 || - strcmp(s, "try") == 0 || - (strcmp(s, "case") == 0 && !(lineFoldStateCurrent & stateFoldInRecord))) { - levelCurrent++; - } else if (strcmp(s, "class") == 0 || strcmp(s, "object") == 0) { - // "class" & "object" keywords require special handling... - bool ignoreKeyword = false; - unsigned int j = SkipWhiteSpace(currentPos, endPos, styler); - if (j < endPos) { - CharacterSet setWordStart(CharacterSet::setAlpha, "_"); - CharacterSet setWord(CharacterSet::setAlphaNum, "_"); - - if (styler.SafeGetCharAt(j) == ';') { - // Handle forward class declarations ("type TMyClass = class;") - // and object method declarations ("TNotifyEvent = procedure(Sender: TObject) of object;") - ignoreKeyword = true; - } else if (strcmp(s, "class") == 0) { - // "class" keyword has a few more special cases... - if (styler.SafeGetCharAt(j) == '(') { - // Handle simplified complete class declarations ("type TMyClass = class(TObject);") - j = SkipWhiteSpace(j, endPos, styler, true); - if (j < endPos && styler.SafeGetCharAt(j) == ')') { - j = SkipWhiteSpace(j, endPos, styler); - if (j < endPos && styler.SafeGetCharAt(j) == ';') { - ignoreKeyword = true; - } - } - } else if (setWordStart.Contains(styler.SafeGetCharAt(j))) { - char s2[11]; // Size of the longest possible keyword + one additional character + null - GetForwardRangeLowered(j, setWord, styler, s2, sizeof(s2)); - - if (strcmp(s2, "procedure") == 0 || - strcmp(s2, "function") == 0 || - strcmp(s2, "of") == 0 || - strcmp(s2, "var") == 0 || - strcmp(s2, "property") == 0 || - strcmp(s2, "operator") == 0) { - ignoreKeyword = true; - } - } - } - } - if (!ignoreKeyword) { - levelCurrent++; - } - } else if (strcmp(s, "interface") == 0) { - // "interface" keyword requires special handling... - bool ignoreKeyword = true; - int j = lastStart - 1; - char ch = styler.SafeGetCharAt(j); - while ((j >= startPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' || - IsStreamCommentStyle(styler.StyleAt(j)))) { - j--; - ch = styler.SafeGetCharAt(j); - } - if (j >= startPos && styler.SafeGetCharAt(j) == '=') { - ignoreKeyword = false; - } - if (!ignoreKeyword) { - levelCurrent++; - } - } else if (strcmp(s, "end") == 0) { - lineFoldStateCurrent &= ~stateFoldInRecord; - levelCurrent--; - if (levelCurrent < SC_FOLDLEVELBASE) { - levelCurrent = SC_FOLDLEVELBASE; - } - } -} - -static void FoldPascalDoc(unsigned int startPos, int length, int initStyle, WordList *[], - Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - int lineFoldStateCurrent = lineCurrent > 0 ? styler.GetLineState(lineCurrent - 1) & stateFoldMaskAll : 0; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - - int lastStart = 0; - CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true); - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - if (foldComment && IsStreamCommentStyle(style)) { - if (!IsStreamCommentStyle(stylePrev)) { - levelCurrent++; - } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelCurrent--; - } - } - if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) - { - if (!IsCommentLine(lineCurrent - 1, styler) - && IsCommentLine(lineCurrent + 1, styler)) - levelCurrent++; - else if (IsCommentLine(lineCurrent - 1, styler) - && !IsCommentLine(lineCurrent+1, styler)) - levelCurrent--; - } - if (foldPreprocessor) { - if (style == SCE_PAS_PREPROCESSOR && ch == '{' && chNext == '$') { - ClassifyPascalPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 2, styler); - } else if (style == SCE_PAS_PREPROCESSOR2 && ch == '(' && chNext == '*' - && styler.SafeGetCharAt(i + 2) == '$') { - ClassifyPascalPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 3, styler); - } - } - - if (stylePrev != SCE_PAS_WORD && style == SCE_PAS_WORD) - { - // Store last word start point. - lastStart = i; - } - if (stylePrev == SCE_PAS_WORD && !(lineFoldStateCurrent & stateFoldInPreprocessor)) { - if(setWord.Contains(ch) && !setWord.Contains(chNext)) { - ClassifyPascalWordFoldPoint(levelCurrent, lineFoldStateCurrent, startPos, endPos, lastStart, i, styler); - } - } - - if (!IsASpace(ch)) - visibleChars++; - - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - int newLineState = (styler.GetLineState(lineCurrent) & ~stateFoldMaskAll) | lineFoldStateCurrent; - styler.SetLineState(lineCurrent, newLineState); - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - } - - // If we didn't reach the EOL in previous loop, store line level and whitespace information. - // The rest will be filled in later... - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - styler.SetLevel(lineCurrent, lev); -} - -static const char * const pascalWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmPascal(SCLEX_PASCAL, ColourisePascalDoc, "pascal", FoldPascalDoc, pascalWordListDesc); diff --git a/src/LexPerl.cxx b/src/LexPerl.cxx deleted file mode 100644 index bca78f57c..000000000 --- a/src/LexPerl.cxx +++ /dev/null @@ -1,1305 +0,0 @@ -// Scintilla source code edit control -/** @file LexPerl.cxx - ** Lexer for Perl. - **/ -// Copyright 1998-2008 by Neil Hodgson -// Lexical analysis fixes by Kein-Hong Man -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "CharacterSet.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// Info for HERE document handling from perldata.pod (reformatted): -// ---------------------------------------------------------------- -// A line-oriented form of quoting is based on the shell ``here-doc'' syntax. -// Following a << you specify a string to terminate the quoted material, and -// all lines following the current line down to the terminating string are -// the value of the item. -// * The terminating string may be either an identifier (a word), or some -// quoted text. -// * If quoted, the type of quotes you use determines the treatment of the -// text, just as in regular quoting. -// * An unquoted identifier works like double quotes. -// * There must be no space between the << and the identifier. -// (If you put a space it will be treated as a null identifier, -// which is valid, and matches the first empty line.) -// (This is deprecated, -w warns of this syntax) -// * The terminating string must appear by itself (unquoted and -// with no surrounding whitespace) on the terminating line. - -#define HERE_DELIM_MAX 256 // maximum length of HERE doc delimiter - -#define PERLNUM_BINARY 1 // order is significant: 1-4 cannot have a dot -#define PERLNUM_HEX 2 -#define PERLNUM_OCTAL 3 -#define PERLNUM_FLOAT_EXP 4 // exponent part only -#define PERLNUM_DECIMAL 5 // 1-5 are numbers; 6-7 are strings -#define PERLNUM_VECTOR 6 -#define PERLNUM_V_VECTOR 7 -#define PERLNUM_BAD 8 - -#define BACK_NONE 0 // lookback state for bareword disambiguation: -#define BACK_OPERATOR 1 // whitespace/comments are insignificant -#define BACK_KEYWORD 2 // operators/keywords are needed for disambiguation - -static bool isPerlKeyword(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) -{ - // old-style keyword matcher; needed because GetCurrent() needs - // current segment to be committed, but we may abandon early... - char s[100]; - unsigned int i, len = end - start; - if (len > 30) { len = 30; } - for (i = 0; i < len; i++, start++) s[i] = styler[start]; - s[i] = '\0'; - return keywords.InList(s); -} - -static int disambiguateBareword(Accessor &styler, unsigned int bk, unsigned int fw, - int backFlag, unsigned int backPos, unsigned int endPos) -{ - // identifiers are recognized by Perl as barewords under some - // conditions, the following attempts to do the disambiguation - // by looking backward and forward; result in 2 LSB - int result = 0; - bool moreback = false; // true if passed newline/comments - bool brace = false; // true if opening brace found - // if BACK_NONE, neither operator nor keyword, so skip test - if (backFlag == BACK_NONE) - return result; - // first look backwards past whitespace/comments to set EOL flag - // (some disambiguation patterns must be on a single line) - if (backPos <= static_cast(styler.LineStart(styler.GetLine(bk)))) - moreback = true; - // look backwards at last significant lexed item for disambiguation - bk = backPos - 1; - int ch = static_cast(styler.SafeGetCharAt(bk)); - if (ch == '{' && !moreback) { - // {bareword: possible variable spec - brace = true; - } else if ((ch == '&' && styler.SafeGetCharAt(bk - 1) != '&') - // &bareword: subroutine call - || styler.Match(bk - 1, "->") - // ->bareword: part of variable spec - || styler.Match(bk - 2, "sub")) { - // sub bareword: subroutine declaration - // (implied BACK_KEYWORD, no keywords end in 'sub'!) - result |= 1; - } - // next, scan forward after word past tab/spaces only; - // if ch isn't one of '[{(,' we can skip the test - if ((ch == '{' || ch == '(' || ch == '['|| ch == ',') - && fw < endPos) { - while (ch = static_cast(styler.SafeGetCharAt(fw)), - IsASpaceOrTab(ch) && fw < endPos) { - fw++; - } - if ((ch == '}' && brace) - // {bareword}: variable spec - || styler.Match(fw, "=>")) { - // [{(, bareword=>: hash literal - result |= 2; - } - } - return result; -} - -static void skipWhitespaceComment(Accessor &styler, unsigned int &p) -{ - // when backtracking, we need to skip whitespace and comments - int style; - while ((p > 0) && (style = styler.StyleAt(p), - style == SCE_PL_DEFAULT || style == SCE_PL_COMMENTLINE)) - p--; -} - -static int styleBeforeBracePair(Accessor &styler, unsigned int bk) -{ - // backtrack to find open '{' corresponding to a '}', balanced - // return significant style to be tested for '/' disambiguation - int braceCount = 1; - if (bk == 0) - return SCE_PL_DEFAULT; - while (--bk > 0) { - if (styler.StyleAt(bk) == SCE_PL_OPERATOR) { - int bkch = static_cast(styler.SafeGetCharAt(bk)); - if (bkch == ';') { // early out - break; - } else if (bkch == '}') { - braceCount++; - } else if (bkch == '{') { - if (--braceCount == 0) break; - } - } - } - if (bk > 0 && braceCount == 0) { - // balanced { found, bk > 0, skip more whitespace/comments - bk--; - skipWhitespaceComment(styler, bk); - return styler.StyleAt(bk); - } - return SCE_PL_DEFAULT; -} - -static int styleCheckIdentifier(Accessor &styler, unsigned int bk) -{ - // backtrack to classify sub-styles of identifier under test - // return sub-style to be tested for '/' disambiguation - if (styler.SafeGetCharAt(bk) == '>') // inputsymbol, like - return 1; - // backtrack to check for possible "->" or "::" before identifier - while (bk > 0 && styler.StyleAt(bk) == SCE_PL_IDENTIFIER) { - bk--; - } - while (bk > 0) { - int bkstyle = styler.StyleAt(bk); - if (bkstyle == SCE_PL_DEFAULT - || bkstyle == SCE_PL_COMMENTLINE) { - // skip whitespace, comments - } else if (bkstyle == SCE_PL_OPERATOR) { - // test for "->" and "::" - if (styler.Match(bk - 1, "->") || styler.Match(bk - 1, "::")) - return 2; - } else - return 3; // bare identifier - bk--; - } - return 0; -} - -static int inputsymbolScan(Accessor &styler, unsigned int pos, unsigned int endPos) -{ - // looks forward for matching > on same line; a bit ugly - unsigned int fw = pos; - while (++fw < endPos) { - int fwch = static_cast(styler.SafeGetCharAt(fw)); - if (fwch == '\r' || fwch == '\n') { - return 0; - } else if (fwch == '>') { - if (styler.Match(fw - 2, "<=>")) // '<=>' case - return 0; - return fw - pos; - } - } - return 0; -} - -static int podLineScan(Accessor &styler, unsigned int &pos, unsigned int endPos) -{ - // forward scan the current line to classify line for POD style - int state = -1; - while (pos <= endPos) { - int ch = static_cast(styler.SafeGetCharAt(pos)); - if (ch == '\n' || ch == '\r' || pos >= endPos) { - if (ch == '\r' && styler.SafeGetCharAt(pos + 1) == '\n') pos++; - break; - } - if (IsASpaceOrTab(ch)) { // whitespace, take note - if (state == -1) - state = SCE_PL_DEFAULT; - } else if (state == SCE_PL_DEFAULT) { // verbatim POD line - state = SCE_PL_POD_VERB; - } else if (state != SCE_PL_POD_VERB) { // regular POD line - state = SCE_PL_POD; - } - pos++; - } - if (state == -1) - state = SCE_PL_DEFAULT; - return state; -} - -static bool styleCheckSubPrototype(Accessor &styler, unsigned int bk) -{ - // backtrack to identify if we're starting a subroutine prototype - // we also need to ignore whitespace/comments: - // 'sub' [whitespace|comment] [whitespace|comment] - styler.Flush(); - skipWhitespaceComment(styler, bk); - if (bk == 0 || styler.StyleAt(bk) != SCE_PL_IDENTIFIER) // check identifier - return false; - while (bk > 0 && (styler.StyleAt(bk) == SCE_PL_IDENTIFIER)) { - bk--; - } - skipWhitespaceComment(styler, bk); - if (bk < 2 || styler.StyleAt(bk) != SCE_PL_WORD // check "sub" keyword - || !styler.Match(bk - 2, "sub")) // assume suffix is unique! - return false; - return true; -} - -static bool isMatch(const char *sref, char *s) -{ - // match per-line delimiter - must kill trailing CR if CRLF - int i = strlen(s); - if (i != 0 && s[i - 1] == '\r') - s[i - 1] = '\0'; - return (strcmp(sref, s) == 0); -} - -static int actualNumStyle(int numberStyle) { - if (numberStyle == PERLNUM_VECTOR || numberStyle == PERLNUM_V_VECTOR) { - return SCE_PL_STRING; - } else if (numberStyle == PERLNUM_BAD) { - return SCE_PL_ERROR; - } - return SCE_PL_NUMBER; -} - -static int opposite(int ch) { - if (ch == '(') return ')'; - if (ch == '[') return ']'; - if (ch == '{') return '}'; - if (ch == '<') return '>'; - return ch; -} - -static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - - // keywords that forces /PATTERN/ at all times; should track vim's behaviour - WordList reWords; - reWords.Set("elsif if split while"); - - // charset classes - CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true); - CharacterSet setSingleCharOp(CharacterSet::setNone, "rwxoRWXOezsfdlpSbctugkTBMAC"); - // lexing of "%*,?!.~"); - CharacterSet setQDelim(CharacterSet::setNone, "qrwx"); - CharacterSet setModifiers(CharacterSet::setAlpha); - CharacterSet setPreferRE(CharacterSet::setNone, "*/<%"); - // setArray and setHash also accepts chars for special vars like $_, - // which are then truncated when the next char does not match setVar - CharacterSet setVar(CharacterSet::setAlphaNum, "#$_'", 0x80, true); - CharacterSet setArray(CharacterSet::setAlpha, "#$_+-", 0x80, true); - CharacterSet setHash(CharacterSet::setAlpha, "#$_!^+-", 0x80, true); - CharacterSet &setPOD = setModifiers; - CharacterSet setNonHereDoc(CharacterSet::setDigits, "=$@"); - CharacterSet setHereDocDelim(CharacterSet::setAlphaNum, "_"); - CharacterSet setSubPrototype(CharacterSet::setNone, "\\[$@%&*];"); - // for format identifiers - CharacterSet setFormatStart(CharacterSet::setAlpha, "_="); - CharacterSet &setFormat = setHereDocDelim; - - // Lexer for perl often has to backtrack to start of current style to determine - // which characters are being used as quotes, how deeply nested is the - // start position and what the termination string is for HERE documents. - - class HereDocCls { // Class to manage HERE doc sequence - public: - int State; // 0: '<<' encountered - // 1: collect the delimiter - // 2: here doc text (lines after the delimiter) - int Quote; // the char after '<<' - bool Quoted; // true if Quote in ('\'','"','`') - int DelimiterLength; // strlen(Delimiter) - char *Delimiter; // the Delimiter, 256: sizeof PL_tokenbuf - HereDocCls() { - State = 0; - Quote = 0; - Quoted = false; - DelimiterLength = 0; - Delimiter = new char[HERE_DELIM_MAX]; - Delimiter[0] = '\0'; - } - void Append(int ch) { - Delimiter[DelimiterLength++] = static_cast(ch); - Delimiter[DelimiterLength] = '\0'; - } - ~HereDocCls() { - delete []Delimiter; - } - }; - HereDocCls HereDoc; // TODO: FIFO for stacked here-docs - - class QuoteCls { // Class to manage quote pairs - public: - int Rep; - int Count; - int Up, Down; - QuoteCls() { - this->New(1); - } - void New(int r = 1) { - Rep = r; - Count = 0; - Up = '\0'; - Down = '\0'; - } - void Open(int u) { - Count++; - Up = u; - Down = opposite(Up); - } - }; - QuoteCls Quote; - - // additional state for number lexing - int numState = PERLNUM_DECIMAL; - int dotCount = 0; - - unsigned int endPos = startPos + length; - - // Backtrack to beginning of style if required... - // If in a long distance lexical state, backtrack to find quote characters. - // Includes strings (may be multi-line), numbers (additional state), format - // bodies, as well as POD sections. - if (initStyle == SCE_PL_HERE_Q - || initStyle == SCE_PL_HERE_QQ - || initStyle == SCE_PL_HERE_QX - || initStyle == SCE_PL_FORMAT - ) { - int delim = (initStyle == SCE_PL_FORMAT) ? SCE_PL_FORMAT_IDENT:SCE_PL_HERE_DELIM; - while ((startPos > 1) && (styler.StyleAt(startPos) != delim)) { - startPos--; - } - startPos = styler.LineStart(styler.GetLine(startPos)); - initStyle = styler.StyleAt(startPos - 1); - } - if (initStyle == SCE_PL_STRING_Q - || initStyle == SCE_PL_STRING_QQ - || initStyle == SCE_PL_STRING_QX - || initStyle == SCE_PL_STRING_QR - || initStyle == SCE_PL_STRING_QW - || initStyle == SCE_PL_REGEX - || initStyle == SCE_PL_REGSUBST - || initStyle == SCE_PL_STRING - || initStyle == SCE_PL_BACKTICKS - || initStyle == SCE_PL_CHARACTER - || initStyle == SCE_PL_NUMBER - || initStyle == SCE_PL_IDENTIFIER - || initStyle == SCE_PL_ERROR - || initStyle == SCE_PL_SUB_PROTOTYPE - ) { - while ((startPos > 1) && (styler.StyleAt(startPos - 1) == initStyle)) { - startPos--; - } - initStyle = SCE_PL_DEFAULT; - } else if (initStyle == SCE_PL_POD - || initStyle == SCE_PL_POD_VERB - ) { - // POD backtracking finds preceeding blank lines and goes back past them - int ln = styler.GetLine(startPos); - if (ln > 0) { - initStyle = styler.StyleAt(styler.LineStart(--ln)); - if (initStyle == SCE_PL_POD || initStyle == SCE_PL_POD_VERB) { - while (ln > 0 && styler.GetLineState(ln) == SCE_PL_DEFAULT) - ln--; - } - startPos = styler.LineStart(++ln); - initStyle = styler.StyleAt(startPos - 1); - } else { - startPos = 0; - initStyle = SCE_PL_DEFAULT; - } - } - - // backFlag, backPos are additional state to aid identifier corner cases. - // Look backwards past whitespace and comments in order to detect either - // operator or keyword. Later updated as we go along. - int backFlag = BACK_NONE; - unsigned int backPos = startPos; - if (backPos > 0) { - backPos--; - skipWhitespaceComment(styler, backPos); - if (styler.StyleAt(backPos) == SCE_PL_OPERATOR) - backFlag = BACK_OPERATOR; - else if (styler.StyleAt(backPos) == SCE_PL_WORD) - backFlag = BACK_KEYWORD; - backPos++; - } - - StyleContext sc(startPos, endPos - startPos, initStyle, styler, static_cast(STYLE_MAX)); - - for (; sc.More(); sc.Forward()) { - - // Determine if the current state should terminate. - switch (sc.state) { - case SCE_PL_OPERATOR: - sc.SetState(SCE_PL_DEFAULT); - backFlag = BACK_OPERATOR; - backPos = sc.currentPos; - break; - case SCE_PL_IDENTIFIER: // identifier, bareword, inputsymbol - if ((!setWord.Contains(sc.ch) && sc.ch != '\'') - || sc.Match('.', '.') - || sc.chPrev == '>') { // end of inputsymbol - sc.SetState(SCE_PL_DEFAULT); - } - break; - case SCE_PL_WORD: // keyword, plus special cases - if (!setWord.Contains(sc.ch)) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if ((strcmp(s, "__DATA__") == 0) || (strcmp(s, "__END__") == 0)) { - sc.ChangeState(SCE_PL_DATASECTION); - } else { - if ((strcmp(s, "format") == 0)) { - sc.SetState(SCE_PL_FORMAT_IDENT); - HereDoc.State = 0; - } else { - sc.SetState(SCE_PL_DEFAULT); - } - backFlag = BACK_KEYWORD; - backPos = sc.currentPos; - } - } - break; - case SCE_PL_SCALAR: - case SCE_PL_ARRAY: - case SCE_PL_HASH: - case SCE_PL_SYMBOLTABLE: - if (sc.Match(':', ':')) { // skip :: - sc.Forward(); - } else if (!setVar.Contains(sc.ch)) { - if (sc.LengthCurrent() == 1) { - // Special variable: $(, $_ etc. - sc.Forward(); - } - sc.SetState(SCE_PL_DEFAULT); - } - break; - case SCE_PL_NUMBER: - // if no early break, number style is terminated at "(go through)" - if (sc.ch == '.') { - if (sc.chNext == '.') { - // double dot is always an operator (go through) - } else if (numState <= PERLNUM_FLOAT_EXP) { - // non-decimal number or float exponent, consume next dot - sc.SetState(SCE_PL_OPERATOR); - break; - } else { // decimal or vectors allows dots - dotCount++; - if (numState == PERLNUM_DECIMAL) { - if (dotCount <= 1) // number with one dot in it - break; - if (IsADigit(sc.chNext)) { // really a vector - numState = PERLNUM_VECTOR; - break; - } - // number then dot (go through) - } else if (IsADigit(sc.chNext)) // vectors - break; - // vector then dot (go through) - } - } else if (sc.ch == '_') { - // permissive underscoring for number and vector literals - break; - } else if (numState == PERLNUM_DECIMAL) { - if (sc.ch == 'E' || sc.ch == 'e') { // exponent, sign - numState = PERLNUM_FLOAT_EXP; - if (sc.chNext == '+' || sc.chNext == '-') { - sc.Forward(); - } - break; - } else if (IsADigit(sc.ch)) - break; - // number then word (go through) - } else if (numState == PERLNUM_HEX) { - if (IsADigit(sc.ch, 16)) - break; - } else if (numState == PERLNUM_VECTOR || numState == PERLNUM_V_VECTOR) { - if (IsADigit(sc.ch)) // vector - break; - if (setWord.Contains(sc.ch) && dotCount == 0) { // change to word - sc.ChangeState(SCE_PL_IDENTIFIER); - break; - } - // vector then word (go through) - } else if (IsADigit(sc.ch)) { - if (numState == PERLNUM_FLOAT_EXP) { - break; - } else if (numState == PERLNUM_OCTAL) { - if (sc.ch <= '7') break; - } else if (numState == PERLNUM_BINARY) { - if (sc.ch <= '1') break; - } - // mark invalid octal, binary numbers (go through) - numState = PERLNUM_BAD; - break; - } - // complete current number or vector - sc.ChangeState(actualNumStyle(numState)); - sc.SetState(SCE_PL_DEFAULT); - break; - case SCE_PL_COMMENTLINE: - if (sc.atLineEnd) { - sc.SetState(SCE_PL_DEFAULT); - } - break; - case SCE_PL_HERE_DELIM: - if (HereDoc.State == 0) { // '<<' encountered - int delim_ch = sc.chNext; - int ws_skip = 0; - HereDoc.State = 1; // pre-init HERE doc class - HereDoc.Quote = sc.chNext; - HereDoc.Quoted = false; - HereDoc.DelimiterLength = 0; - HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; - if (IsASpaceOrTab(delim_ch)) { - // skip whitespace; legal only for quoted delimiters - unsigned int i = sc.currentPos + 1; - while ((i < endPos) && IsASpaceOrTab(delim_ch)) { - i++; - delim_ch = static_cast(styler.SafeGetCharAt(i)); - } - ws_skip = i - sc.currentPos - 1; - } - if (delim_ch == '\'' || delim_ch == '"' || delim_ch == '`') { - // a quoted here-doc delimiter; skip any whitespace - sc.Forward(ws_skip + 1); - HereDoc.Quote = delim_ch; - HereDoc.Quoted = true; - } else if ((ws_skip == 0 && setNonHereDoc.Contains(sc.chNext)) - || ws_skip > 0) { - // left shift << or <<= operator cases - // restore position if operator - sc.ChangeState(SCE_PL_OPERATOR); - sc.ForwardSetState(SCE_PL_DEFAULT); - backFlag = BACK_OPERATOR; - backPos = sc.currentPos; - HereDoc.State = 0; - } else { - // specially handle initial '\' for identifier - if (ws_skip == 0 && HereDoc.Quote == '\\') - sc.Forward(); - // an unquoted here-doc delimiter, no special handling - // (cannot be prefixed by spaces/tabs), or - // symbols terminates; deprecated zero-length delimiter - } - } else if (HereDoc.State == 1) { // collect the delimiter - backFlag = BACK_NONE; - if (HereDoc.Quoted) { // a quoted here-doc delimiter - if (sc.ch == HereDoc.Quote) { // closing quote => end of delimiter - sc.ForwardSetState(SCE_PL_DEFAULT); - } else if (!sc.atLineEnd) { - if (sc.Match('\\', static_cast(HereDoc.Quote))) { // escaped quote - sc.Forward(); - } - if (sc.ch != '\r') { // skip CR if CRLF - HereDoc.Append(sc.ch); - } - } - } else { // an unquoted here-doc delimiter - if (setHereDocDelim.Contains(sc.ch)) { - HereDoc.Append(sc.ch); - } else { - sc.SetState(SCE_PL_DEFAULT); - } - } - if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) { - sc.SetState(SCE_PL_ERROR); - HereDoc.State = 0; - } - } - break; - case SCE_PL_HERE_Q: - case SCE_PL_HERE_QQ: - case SCE_PL_HERE_QX: { - // also implies HereDoc.State == 2 - sc.Complete(); - while (!sc.atLineEnd) - sc.Forward(); - char s[HERE_DELIM_MAX]; - sc.GetCurrent(s, sizeof(s)); - if (isMatch(HereDoc.Delimiter, s)) { - sc.SetState(SCE_PL_DEFAULT); - backFlag = BACK_NONE; - HereDoc.State = 0; - } - } break; - case SCE_PL_POD: - case SCE_PL_POD_VERB: { - unsigned int fw = sc.currentPos; - int ln = styler.GetLine(fw); - if (sc.atLineStart && sc.Match("=cut")) { // end of POD - sc.SetState(SCE_PL_POD); - sc.Forward(4); - sc.SetState(SCE_PL_DEFAULT); - styler.SetLineState(ln, SCE_PL_POD); - break; - } - int pod = podLineScan(styler, fw, endPos); // classify POD line - styler.SetLineState(ln, pod); - if (pod == SCE_PL_DEFAULT) { - if (sc.state == SCE_PL_POD_VERB) { - unsigned int fw2 = fw; - while (fw2 <= endPos && pod == SCE_PL_DEFAULT) { - fw = fw2++; // penultimate line (last blank line) - pod = podLineScan(styler, fw2, endPos); - styler.SetLineState(styler.GetLine(fw2), pod); - } - if (pod == SCE_PL_POD) { // truncate verbatim POD early - sc.SetState(SCE_PL_POD); - } else - fw = fw2; - } else - pod = SCE_PL_POD; - } else { - if (pod == SCE_PL_POD_VERB // still part of current paragraph - && (styler.GetLineState(ln - 1) == SCE_PL_POD)) { - pod = SCE_PL_POD; - styler.SetLineState(ln, pod); - } else if (pod == SCE_PL_POD - && (styler.GetLineState(ln - 1) == SCE_PL_POD_VERB)) { - pod = SCE_PL_POD_VERB; - styler.SetLineState(ln, pod); - } - sc.SetState(pod); - } - sc.Forward(fw - sc.currentPos); // commit style - } break; - case SCE_PL_REGEX: - case SCE_PL_STRING_QR: - if (Quote.Rep <= 0) { - if (!setModifiers.Contains(sc.ch)) - sc.SetState(SCE_PL_DEFAULT); - } else if (!Quote.Up && !IsASpace(sc.ch)) { - Quote.Open(sc.ch); - } else if (sc.ch == '\\' && Quote.Up != '\\') { - sc.Forward(); - } else if (sc.ch == Quote.Down) { - Quote.Count--; - if (Quote.Count == 0) - Quote.Rep--; - } else if (sc.ch == Quote.Up) { - Quote.Count++; - } - break; - case SCE_PL_REGSUBST: - if (Quote.Rep <= 0) { - if (!setModifiers.Contains(sc.ch)) - sc.SetState(SCE_PL_DEFAULT); - } else if (!Quote.Up && !IsASpace(sc.ch)) { - Quote.Open(sc.ch); - } else if (sc.ch == '\\' && Quote.Up != '\\') { - sc.Forward(); - } else if (Quote.Count == 0 && Quote.Rep == 1) { - // We matched something like s(...) or tr{...}, Perl 5.10 - // appears to allow almost any character for use as the - // next delimiters. Whitespace and comments are accepted in - // between, but we'll limit to whitespace here. - // For '#', if no whitespace in between, it's a delimiter. - if (IsASpace(sc.ch)) { - // Keep going - } else if (sc.ch == '#' && IsASpaceOrTab(sc.chPrev)) { - sc.SetState(SCE_PL_DEFAULT); - } else { - Quote.Open(sc.ch); - } - } else if (sc.ch == Quote.Down) { - Quote.Count--; - if (Quote.Count == 0) - Quote.Rep--; - if (Quote.Up == Quote.Down) - Quote.Count++; - } else if (sc.ch == Quote.Up) { - Quote.Count++; - } - break; - case SCE_PL_STRING_Q: - case SCE_PL_STRING_QQ: - case SCE_PL_STRING_QX: - case SCE_PL_STRING_QW: - case SCE_PL_STRING: - case SCE_PL_CHARACTER: - case SCE_PL_BACKTICKS: - if (!Quote.Down && !IsASpace(sc.ch)) { - Quote.Open(sc.ch); - } else if (sc.ch == '\\' && Quote.Up != '\\') { - sc.Forward(); - } else if (sc.ch == Quote.Down) { - Quote.Count--; - if (Quote.Count == 0) - sc.ForwardSetState(SCE_PL_DEFAULT); - } else if (sc.ch == Quote.Up) { - Quote.Count++; - } - break; - case SCE_PL_SUB_PROTOTYPE: { - int i = 0; - // forward scan; must all be valid proto characters - while (setSubPrototype.Contains(sc.GetRelative(i))) - i++; - if (sc.GetRelative(i) == ')') { // valid sub prototype - sc.Forward(i); - sc.ForwardSetState(SCE_PL_DEFAULT); - } else { - // abandon prototype, restart from '(' - sc.ChangeState(SCE_PL_OPERATOR); - sc.SetState(SCE_PL_DEFAULT); - } - } break; - case SCE_PL_FORMAT: { - sc.Complete(); - while (!sc.atLineEnd) - sc.Forward(); - char s[10]; - sc.GetCurrent(s, sizeof(s)); - if (isMatch(".", s)) - sc.SetState(SCE_PL_DEFAULT); - } break; - case SCE_PL_ERROR: - break; - } - // Needed for specific continuation styles (one follows the other) - switch (sc.state) { - // continued from SCE_PL_WORD - case SCE_PL_FORMAT_IDENT: - // occupies HereDoc state 3 to avoid clashing with HERE docs - if (IsASpaceOrTab(sc.ch)) { // skip whitespace - sc.ChangeState(SCE_PL_DEFAULT); - while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) - sc.Forward(); - sc.SetState(SCE_PL_FORMAT_IDENT); - } - if (setFormatStart.Contains(sc.ch)) { // identifier or '=' - if (sc.ch != '=') { - do { - sc.Forward(); - } while (setFormat.Contains(sc.ch)); - } - while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) - sc.Forward(); - if (sc.ch == '=') { - sc.ForwardSetState(SCE_PL_DEFAULT); - HereDoc.State = 3; - } else { - // invalid indentifier; inexact fallback, but hey - sc.ChangeState(SCE_PL_IDENTIFIER); - sc.SetState(SCE_PL_DEFAULT); - } - } else { - sc.ChangeState(SCE_PL_DEFAULT); // invalid indentifier - } - backFlag = BACK_NONE; - break; - } - - // Must check end of HereDoc states here before default state is handled - if (HereDoc.State == 1 && sc.atLineEnd) { - // Begin of here-doc (the line after the here-doc delimiter): - // Lexically, the here-doc starts from the next line after the >>, but the - // first line of here-doc seem to follow the style of the last EOL sequence - int st_new = SCE_PL_HERE_QQ; - HereDoc.State = 2; - if (HereDoc.Quoted) { - if (sc.state == SCE_PL_HERE_DELIM) { - // Missing quote at end of string! We are stricter than perl. - // Colour here-doc anyway while marking this bit as an error. - sc.ChangeState(SCE_PL_ERROR); - } - switch (HereDoc.Quote) { - case '\'': st_new = SCE_PL_HERE_Q ; break; - case '"' : st_new = SCE_PL_HERE_QQ; break; - case '`' : st_new = SCE_PL_HERE_QX; break; - } - } else { - if (HereDoc.Quote == '\\') - st_new = SCE_PL_HERE_Q; - } - sc.SetState(st_new); - } - if (HereDoc.State == 3 && sc.atLineEnd) { - // Start of format body. - HereDoc.State = 0; - sc.SetState(SCE_PL_FORMAT); - } - - // Determine if a new state should be entered. - if (sc.state == SCE_PL_DEFAULT) { - if (IsADigit(sc.ch) || - (IsADigit(sc.chNext) && (sc.ch == '.' || sc.ch == 'v'))) { - sc.SetState(SCE_PL_NUMBER); - backFlag = BACK_NONE; - numState = PERLNUM_DECIMAL; - dotCount = 0; - if (sc.ch == '0') { // hex,bin,octal - if (sc.chNext == 'x') { - numState = PERLNUM_HEX; - } else if (sc.chNext == 'b') { - numState = PERLNUM_BINARY; - } else if (IsADigit(sc.chNext)) { - numState = PERLNUM_OCTAL; - } - if (numState != PERLNUM_DECIMAL) { - sc.Forward(); - } - } else if (sc.ch == 'v') { // vector - numState = PERLNUM_V_VECTOR; - } - } else if (setWord.Contains(sc.ch)) { - // if immediately prefixed by '::', always a bareword - sc.SetState(SCE_PL_WORD); - if (sc.chPrev == ':' && sc.GetRelative(-2) == ':') { - sc.ChangeState(SCE_PL_IDENTIFIER); - } - unsigned int bk = sc.currentPos; - unsigned int fw = sc.currentPos + 1; - // first check for possible quote-like delimiter - if (sc.ch == 's' && !setWord.Contains(sc.chNext)) { - sc.ChangeState(SCE_PL_REGSUBST); - Quote.New(2); - } else if (sc.ch == 'm' && !setWord.Contains(sc.chNext)) { - sc.ChangeState(SCE_PL_REGEX); - Quote.New(); - } else if (sc.ch == 'q' && !setWord.Contains(sc.chNext)) { - sc.ChangeState(SCE_PL_STRING_Q); - Quote.New(); - } else if (sc.ch == 'y' && !setWord.Contains(sc.chNext)) { - sc.ChangeState(SCE_PL_REGSUBST); - Quote.New(2); - } else if (sc.Match('t', 'r') && !setWord.Contains(sc.GetRelative(2))) { - sc.ChangeState(SCE_PL_REGSUBST); - Quote.New(2); - sc.Forward(); - fw++; - } else if (sc.ch == 'q' && setQDelim.Contains(sc.chNext) - && !setWord.Contains(sc.GetRelative(2))) { - if (sc.chNext == 'q') sc.ChangeState(SCE_PL_STRING_QQ); - else if (sc.chNext == 'x') sc.ChangeState(SCE_PL_STRING_QX); - else if (sc.chNext == 'r') sc.ChangeState(SCE_PL_STRING_QR); - else sc.ChangeState(SCE_PL_STRING_QW); // sc.chNext == 'w' - Quote.New(); - sc.Forward(); - fw++; - } else if (sc.ch == 'x' && (sc.chNext == '=' || // repetition - !setWord.Contains(sc.chNext) || - (IsADigit(sc.chPrev) && IsADigit(sc.chNext)))) { - sc.ChangeState(SCE_PL_OPERATOR); - } - // if potentially a keyword, scan forward and grab word, then check - // if it's really one; if yes, disambiguation test is performed - // otherwise it is always a bareword and we skip a lot of scanning - if (sc.state == SCE_PL_WORD) { - while (setWord.Contains(static_cast(styler.SafeGetCharAt(fw)))) - fw++; - if (!isPerlKeyword(styler.GetStartSegment(), fw, keywords, styler)) { - sc.ChangeState(SCE_PL_IDENTIFIER); - } - } - // if already SCE_PL_IDENTIFIER, then no ambiguity, skip this - // for quote-like delimiters/keywords, attempt to disambiguate - // to select for bareword, change state -> SCE_PL_IDENTIFIER - if (sc.state != SCE_PL_IDENTIFIER && bk > 0) { - if (disambiguateBareword(styler, bk, fw, backFlag, backPos, endPos)) - sc.ChangeState(SCE_PL_IDENTIFIER); - } - backFlag = BACK_NONE; - } else if (sc.ch == '#') { - sc.SetState(SCE_PL_COMMENTLINE); - } else if (sc.ch == '\"') { - sc.SetState(SCE_PL_STRING); - Quote.New(); - Quote.Open(sc.ch); - backFlag = BACK_NONE; - } else if (sc.ch == '\'') { - if (sc.chPrev == '&' && setWordStart.Contains(sc.chNext)) { - // Archaic call - sc.SetState(SCE_PL_IDENTIFIER); - } else { - sc.SetState(SCE_PL_CHARACTER); - Quote.New(); - Quote.Open(sc.ch); - } - backFlag = BACK_NONE; - } else if (sc.ch == '`') { - sc.SetState(SCE_PL_BACKTICKS); - Quote.New(); - Quote.Open(sc.ch); - backFlag = BACK_NONE; - } else if (sc.ch == '$') { - sc.SetState(SCE_PL_SCALAR); - if (sc.chNext == '{') { - sc.ForwardSetState(SCE_PL_OPERATOR); - } else if (IsASpace(sc.chNext)) { - sc.ForwardSetState(SCE_PL_DEFAULT); - } else { - sc.Forward(); - if (sc.Match('`', '`') || sc.Match(':', ':')) { - sc.Forward(); - } - } - backFlag = BACK_NONE; - } else if (sc.ch == '@') { - sc.SetState(SCE_PL_ARRAY); - if (setArray.Contains(sc.chNext)) { - // no special treatment - } else if (sc.chNext == ':' && sc.GetRelative(2) == ':') { - sc.Forward(2); - } else if (sc.chNext == '{' || sc.chNext == '[') { - sc.ForwardSetState(SCE_PL_OPERATOR); - } else { - sc.ChangeState(SCE_PL_OPERATOR); - } - backFlag = BACK_NONE; - } else if (setPreferRE.Contains(sc.ch)) { - // Explicit backward peeking to set a consistent preferRE for - // any slash found, so no longer need to track preferRE state. - // Find first previous significant lexed element and interpret. - // A few symbols shares this code for disambiguation. - bool preferRE = false; - bool isHereDoc = sc.Match('<', '<'); - bool hereDocSpace = false; // for: SCALAR [whitespace] '<<' - unsigned int bk = (sc.currentPos > 0) ? sc.currentPos - 1: 0; - unsigned int bkend; - sc.Complete(); - styler.Flush(); - if (styler.StyleAt(bk) == SCE_PL_DEFAULT) - hereDocSpace = true; - skipWhitespaceComment(styler, bk); - if (bk == 0) { - // avoid backward scanning breakage - preferRE = true; - } else { - int bkstyle = styler.StyleAt(bk); - int bkch = static_cast(styler.SafeGetCharAt(bk)); - switch(bkstyle) { - case SCE_PL_OPERATOR: - preferRE = true; - if (bkch == ')' || bkch == ']') { - preferRE = false; - } else if (bkch == '}') { - // backtrack by counting balanced brace pairs - // needed to test for variables like ${}, @{} etc. - bkstyle = styleBeforeBracePair(styler, bk); - if (bkstyle == SCE_PL_SCALAR - || bkstyle == SCE_PL_ARRAY - || bkstyle == SCE_PL_HASH - || bkstyle == SCE_PL_SYMBOLTABLE - || bkstyle == SCE_PL_OPERATOR) { - preferRE = false; - } - } else if (bkch == '+' || bkch == '-') { - if (bkch == static_cast(styler.SafeGetCharAt(bk - 1)) - && bkch != static_cast(styler.SafeGetCharAt(bk - 2))) - // exceptions for operators: unary suffixes ++, -- - preferRE = false; - } - break; - case SCE_PL_IDENTIFIER: - preferRE = true; - bkstyle = styleCheckIdentifier(styler, bk); - if ((bkstyle == 1) || (bkstyle == 2)) { - // inputsymbol or var with "->" or "::" before identifier - preferRE = false; - } else if (bkstyle == 3) { - // bare identifier, test cases follows: - if (sc.ch == '/') { - // if '/', /PATTERN/ unless digit/space immediately after '/' - // if '//', always expect defined-or operator to follow identifier - if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.chNext == '/') - preferRE = false; - } else if (sc.ch == '*' || sc.ch == '%') { - if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.Match('*', '*')) - preferRE = false; - } else if (sc.ch == '<') { - if (IsASpace(sc.chNext) || sc.chNext == '=') - preferRE = false; - } - } - break; - case SCE_PL_SCALAR: // for $var<< case: - if (isHereDoc && hereDocSpace) // if SCALAR whitespace '<<', *always* a HERE doc - preferRE = true; - break; - case SCE_PL_WORD: - preferRE = true; - // for HERE docs, always true - if (sc.ch == '/') { - // adopt heuristics similar to vim-style rules: - // keywords always forced as /PATTERN/: split, if, elsif, while - // everything else /PATTERN/ unless digit/space immediately after '/' - // for '//', defined-or favoured unless special keywords - bkend = bk + 1; - while (bk > 0 && styler.StyleAt(bk - 1) == SCE_PL_WORD) { - bk--; - } - if (isPerlKeyword(bk, bkend, reWords, styler)) - break; - if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.chNext == '/') - preferRE = false; - } else if (sc.ch == '*' || sc.ch == '%') { - if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.Match('*', '*')) - preferRE = false; - } else if (sc.ch == '<') { - if (IsASpace(sc.chNext) || sc.chNext == '=') - preferRE = false; - } - break; - // other styles uses the default, preferRE=false - case SCE_PL_POD: - case SCE_PL_HERE_Q: - case SCE_PL_HERE_QQ: - case SCE_PL_HERE_QX: - preferRE = true; - break; - } - } - backFlag = BACK_NONE; - if (isHereDoc) { // handle '<<', HERE doc - if (preferRE) { - sc.SetState(SCE_PL_HERE_DELIM); - HereDoc.State = 0; - } else { // << operator - sc.SetState(SCE_PL_OPERATOR); - sc.Forward(); - } - } else if (sc.ch == '*') { // handle '*', typeglob - if (preferRE) { - sc.SetState(SCE_PL_SYMBOLTABLE); - if (sc.chNext == ':' && sc.GetRelative(2) == ':') { - sc.Forward(2); - } else if (sc.chNext == '{') { - sc.ForwardSetState(SCE_PL_OPERATOR); - } else { - sc.Forward(); - } - } else { - sc.SetState(SCE_PL_OPERATOR); - if (sc.chNext == '*') // exponentiation - sc.Forward(); - } - } else if (sc.ch == '%') { // handle '%', hash - if (preferRE) { - sc.SetState(SCE_PL_HASH); - if (setHash.Contains(sc.chNext)) { - sc.Forward(); - } else if (sc.chNext == ':' && sc.GetRelative(2) == ':') { - sc.Forward(2); - } else if (sc.chNext == '{') { - sc.ForwardSetState(SCE_PL_OPERATOR); - } else { - sc.ChangeState(SCE_PL_OPERATOR); - } - } else { - sc.SetState(SCE_PL_OPERATOR); - } - } else if (sc.ch == '<') { // handle '<', inputsymbol - if (preferRE) { - // forward scan - int i = inputsymbolScan(styler, sc.currentPos, endPos); - if (i > 0) { - sc.SetState(SCE_PL_IDENTIFIER); - sc.Forward(i); - } else { - sc.SetState(SCE_PL_OPERATOR); - } - } else { - sc.SetState(SCE_PL_OPERATOR); - } - } else { // handle '/', regexp - if (preferRE) { - sc.SetState(SCE_PL_REGEX); - Quote.New(); - Quote.Open(sc.ch); - } else { // / and // operators - sc.SetState(SCE_PL_OPERATOR); - if (sc.chNext == '/') { - sc.Forward(); - } - } - } - } else if (sc.ch == '=' // POD - && setPOD.Contains(sc.chNext) - && sc.atLineStart) { - sc.SetState(SCE_PL_POD); - backFlag = BACK_NONE; - } else if (sc.ch == '-' && setWordStart.Contains(sc.chNext)) { // extended '-' cases - unsigned int bk = sc.currentPos; - unsigned int fw = 2; - if (setSingleCharOp.Contains(sc.chNext) && // file test operators - !setWord.Contains(sc.GetRelative(2))) { - sc.SetState(SCE_PL_WORD); - } else { - // nominally a minus and bareword; find extent of bareword - while (setWord.Contains(sc.GetRelative(fw))) - fw++; - sc.SetState(SCE_PL_OPERATOR); - } - // force to bareword for hash key => or {variable literal} cases - if (disambiguateBareword(styler, bk, bk + fw, backFlag, backPos, endPos) & 2) { - sc.ChangeState(SCE_PL_IDENTIFIER); - } - backFlag = BACK_NONE; - } else if (sc.ch == '(' && sc.currentPos > 0) { // '(' or subroutine prototype - sc.Complete(); - if (styleCheckSubPrototype(styler, sc.currentPos - 1)) { - sc.SetState(SCE_PL_SUB_PROTOTYPE); - backFlag = BACK_NONE; - } else { - sc.SetState(SCE_PL_OPERATOR); - } - } else if (setPerlOperator.Contains(sc.ch)) { // operators - sc.SetState(SCE_PL_OPERATOR); - if (sc.Match('.', '.')) { // .. and ... - sc.Forward(); - if (sc.chNext == '.') sc.Forward(); - } - } else if (sc.ch == 4 || sc.ch == 26) { // ^D and ^Z ends valid perl source - sc.SetState(SCE_PL_DATASECTION); - } else { - // keep colouring defaults - sc.Complete(); - } - } - } - sc.Complete(); -} - -static bool IsCommentLine(int line, Accessor &styler) { - int pos = styler.LineStart(line); - int eol_pos = styler.LineStart(line + 1) - 1; - for (int i = pos; i < eol_pos; i++) { - char ch = styler[i]; - int style = styler.StyleAt(i); - if (ch == '#' && style == SCE_PL_COMMENTLINE) - return true; - else if (!IsASpaceOrTab(ch)) - return false; - } - return false; -} - -static void FoldPerlDoc(unsigned int startPos, int length, int, WordList *[], - Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - // Custom folding of POD and packages - - // property fold.perl.pod - // Enable folding Pod blocks when using the Perl lexer. - bool foldPOD = styler.GetPropertyInt("fold.perl.pod", 1) != 0; - - // property fold.perl.package - // Enable folding packages when using the Perl lexer. - bool foldPackage = styler.GetPropertyInt("fold.perl.package", 1) != 0; - - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelPrev = styler.LevelAt(lineCurrent - 1) >> 16; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - char chPrev = styler.SafeGetCharAt(startPos - 1); - int styleNext = styler.StyleAt(startPos); - // Used at end of line to determine if the line was a package definition - bool isPackageLine = false; - bool isPodHeading = false; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - bool atLineStart = ((chPrev == '\r') || (chPrev == '\n')) || i == 0; - // Comment folding - if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) - { - if (!IsCommentLine(lineCurrent - 1, styler) - && IsCommentLine(lineCurrent + 1, styler)) - levelCurrent++; - else if (IsCommentLine(lineCurrent - 1, styler) - && !IsCommentLine(lineCurrent+1, styler)) - levelCurrent--; - } - if (style == SCE_PL_OPERATOR) { - if (ch == '{') { - levelCurrent++; - } else if (ch == '}') { - levelCurrent--; - } - } - // Custom POD folding - if (foldPOD && atLineStart) { - int stylePrevCh = (i) ? styler.StyleAt(i - 1):SCE_PL_DEFAULT; - if (style == SCE_PL_POD) { - if (stylePrevCh != SCE_PL_POD && stylePrevCh != SCE_PL_POD_VERB) - levelCurrent++; - else if (styler.Match(i, "=cut")) - levelCurrent--; - else if (styler.Match(i, "=head")) - isPodHeading = true; - } else if (style == SCE_PL_DATASECTION) { - if (ch == '=' && isascii(chNext) && isalpha(chNext) && levelCurrent == SC_FOLDLEVELBASE) - levelCurrent++; - else if (styler.Match(i, "=cut") && levelCurrent > SC_FOLDLEVELBASE) - levelCurrent--; - else if (styler.Match(i, "=head")) - isPodHeading = true; - // if package used or unclosed brace, level > SC_FOLDLEVELBASE! - // reset needed as level test is vs. SC_FOLDLEVELBASE - else if (styler.Match(i, "__END__")) - levelCurrent = SC_FOLDLEVELBASE; - } - } - // Custom package folding - if (foldPackage && atLineStart) { - if (style == SCE_PL_WORD && styler.Match(i, "package")) { - isPackageLine = true; - } - } - - if (atEOL) { - int lev = levelPrev; - if (isPodHeading) { - lev = levelPrev - 1; - lev |= SC_FOLDLEVELHEADERFLAG; - isPodHeading = false; - } - // Check if line was a package declaration - // because packages need "special" treatment - if (isPackageLine) { - lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; - levelCurrent = SC_FOLDLEVELBASE + 1; - isPackageLine = false; - } - lev |= levelCurrent << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - chPrev = ch; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const perlWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmPerl(SCLEX_PERL, ColourisePerlDoc, "perl", FoldPerlDoc, perlWordListDesc, 8); diff --git a/src/LexPowerPro.cxx b/src/LexPowerPro.cxx deleted file mode 100644 index 9320baf94..000000000 --- a/src/LexPowerPro.cxx +++ /dev/null @@ -1,600 +0,0 @@ -// Scintilla source code edit control -// @file LexPowerPro.cxx -// PowerPro utility, written by Bruce Switzer, is available from http://powerpro.webeddie.com -// PowerPro lexer is written by Christopher Bean (cbean@cb-software.net) -// -// Lexer code heavily borrowed from: -// LexAU3.cxx by Jos van der Zande -// LexCPP.cxx by Neil Hodgson -// LexVB.cxx by Neil Hodgson -// -// Changes: -// 2008-10-25 - Initial release -// 2008-10-26 - Changed how is hilighted in 'function ' so that -// local isFunction = "" and local functions = "" don't get falsely highlighted -// 2008-12-14 - Added bounds checking for szKeyword and szDo -// - Replaced SetOfCharacters with CharacterSet -// - Made sure that CharacterSet::Contains is passed only positive values -// - Made sure that the return value of Accessor::SafeGetCharAt is positive before -// passsing to functions that require positive values like isspacechar() -// - Removed unused visibleChars processing from ColourisePowerProDoc() -// - Fixed bug with folding logic where line continuations didn't end where -// they were supposed to -// - Moved all helper functions to the top of the file -// -// Copyright 1998-2005 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "CharacterSet.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsStreamCommentStyle(int style) { - return style == SCE_POWERPRO_COMMENTBLOCK; -} - -static bool IsContinuationLine(unsigned int szLine, Accessor &styler) -{ - int nsPos = styler.LineStart(szLine); - int nePos = styler.LineStart(szLine + 1) - 2; - while (nsPos < nePos) - { - int stylech = styler.StyleAt(nsPos); - if (!(stylech == SCE_POWERPRO_COMMENTBLOCK)) { - char ch = styler.SafeGetCharAt(nePos); - char chPrev = styler.SafeGetCharAt(nePos-1); - char chPrevPrev = styler.SafeGetCharAt(nePos-2); - if (ch > 0 && chPrev > 0 && chPrevPrev > 0 && !isspacechar(ch) && !isspacechar(chPrev) && !isspacechar(chPrevPrev) ) { - if (chPrevPrev == ';' && chPrev == ';' && ch == '+') - return true; - else - return false; - } - } - nePos--; // skip to next char - } - return false; -} - -// Routine to find first none space on the current line and return its Style -// needed for comment lines not starting on pos 1 -static int GetStyleFirstWord(unsigned int szLine, Accessor &styler) -{ - int nsPos = styler.LineStart(szLine); - int nePos = styler.LineStart(szLine+1) - 1; - char ch = styler.SafeGetCharAt(nsPos); - - while (ch > 0 && isspacechar(ch) && nsPos < nePos) - { - nsPos++; // skip to next char - ch = styler.SafeGetCharAt(nsPos); - - } - return styler.StyleAt(nsPos); -} - -//returns true if there is a function to highlight -//used to highlight in 'function ' -static bool HasFunction(Accessor &styler, unsigned int currentPos) { - - //check for presence of 'function ' - return (styler.SafeGetCharAt(currentPos) == ' ' - && tolower(styler.SafeGetCharAt(currentPos-1)) == 'n' - && tolower(styler.SafeGetCharAt(currentPos-2)) == 'o' - && tolower(styler.SafeGetCharAt(currentPos-3)) == 'i' - && tolower(styler.SafeGetCharAt(currentPos-4)) == 't' - && tolower(styler.SafeGetCharAt(currentPos-5)) == 'c' - && tolower(styler.SafeGetCharAt(currentPos-6)) == 'n' - && tolower(styler.SafeGetCharAt(currentPos-7)) == 'u' - && tolower(styler.SafeGetCharAt(currentPos-8)) == 'f' - //only allow 'function ' to appear at the beginning of a line - && (styler.SafeGetCharAt(currentPos-9) == '\n' - || styler.SafeGetCharAt(currentPos-9) == '\r' - || (styler.SafeGetCharAt(currentPos -9, '\0')) == '\0') //is the first line - ); -} - -static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler, bool caseSensitive) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - - //define the character sets - CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); - - StyleContext sc(startPos, length, initStyle, styler); - char s_save[100]; //for last line highlighting - - for (; sc.More(); sc.Forward()) { - - // ********************************************** - // save the total current word for eof processing - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - - if ((sc.ch > 0) && setWord.Contains(sc.ch)) - { - strcpy(s_save,s); - int tp = strlen(s_save); - if (tp < 99) { - s_save[tp] = static_cast(tolower(sc.ch)); - s_save[tp+1] = '\0'; - } - } - // ********************************************** - // - - if (sc.atLineStart) { - if (sc.state == SCE_POWERPRO_DOUBLEQUOTEDSTRING) { - // Prevent SCE_POWERPRO_STRINGEOL from leaking back to previous line which - // ends with a line continuation by locking in the state upto this position. - sc.SetState(SCE_POWERPRO_DOUBLEQUOTEDSTRING); - } - } - - // Determine if the current state should terminate. - switch (sc.state) { - case SCE_POWERPRO_OPERATOR: - sc.SetState(SCE_POWERPRO_DEFAULT); - break; - - case SCE_POWERPRO_NUMBER: - - if (!IsADigit(sc.ch)) - sc.SetState(SCE_POWERPRO_DEFAULT); - - break; - - case SCE_POWERPRO_IDENTIFIER: - //if ((sc.ch > 0) && !setWord.Contains(sc.ch) || (sc.ch == '.')) { // use this line if don't want to match keywords with . in them. ie: win.debug will match both win and debug so win debug will also be colorized - if ((sc.ch > 0) && !setWord.Contains(sc.ch)){ // || (sc.ch == '.')) { // use this line if you want to match keywords with a . ie: win.debug will only match win.debug neither win nor debug will be colorized separately - char s[1000]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); - } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - if (keywords.InList(s)) { - sc.ChangeState(SCE_POWERPRO_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_POWERPRO_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_POWERPRO_WORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_POWERPRO_WORD4); - } - sc.SetState(SCE_POWERPRO_DEFAULT); - } - break; - - case SCE_POWERPRO_LINECONTINUE: - if (sc.atLineStart) { - sc.SetState(SCE_POWERPRO_DEFAULT); - } else if (sc.Match('/', '*') || sc.Match('/', '/')) { - sc.SetState(SCE_POWERPRO_DEFAULT); - } - break; - - case SCE_POWERPRO_COMMENTBLOCK: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_POWERPRO_DEFAULT); - } - break; - - case SCE_POWERPRO_COMMENTLINE: - if (sc.atLineStart) { - sc.SetState(SCE_POWERPRO_DEFAULT); - } - break; - - case SCE_POWERPRO_DOUBLEQUOTEDSTRING: - if (sc.atLineEnd) { - sc.ChangeState(SCE_POWERPRO_STRINGEOL); - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_POWERPRO_DEFAULT); - } - break; - - case SCE_POWERPRO_SINGLEQUOTEDSTRING: - if (sc.atLineEnd) { - sc.ChangeState(SCE_POWERPRO_STRINGEOL); - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_POWERPRO_DEFAULT); - } - break; - - case SCE_POWERPRO_STRINGEOL: - if (sc.atLineStart) { - sc.SetState(SCE_POWERPRO_DEFAULT); - } - break; - - case SCE_POWERPRO_VERBATIM: - if (sc.ch == '\"') { - if (sc.chNext == '\"') { - sc.Forward(); - } else { - sc.ForwardSetState(SCE_POWERPRO_DEFAULT); - } - } - break; - - case SCE_POWERPRO_ALTQUOTE: - if (sc.ch == '#') { - if (sc.chNext == '#') { - sc.Forward(); - } else { - sc.ForwardSetState(SCE_POWERPRO_DEFAULT); - } - } - break; - - case SCE_POWERPRO_FUNCTION: - if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ' ' || sc.ch == '(') { - sc.SetState(SCE_POWERPRO_DEFAULT); - } - break; - } - - // Determine if a new state should be entered. - if (sc.state == SCE_POWERPRO_DEFAULT) { - if (sc.Match('?', '\"')) { - sc.SetState(SCE_POWERPRO_VERBATIM); - sc.Forward(); - } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_POWERPRO_NUMBER); - }else if (sc.Match('?','#')) { - if (sc.ch == '?' && sc.chNext == '#') { - sc.SetState(SCE_POWERPRO_ALTQUOTE); - sc.Forward(); - } - } else if (HasFunction(styler, sc.currentPos)) { //highlight in 'function ' - sc.SetState(SCE_POWERPRO_FUNCTION); - } else if (sc.ch == '@' && sc.atLineStart) { //alternate function definition [label] - sc.SetState(SCE_POWERPRO_FUNCTION); - } else if ((sc.ch > 0) && (setWordStart.Contains(sc.ch) || (sc.ch == '?'))) { - sc.SetState(SCE_POWERPRO_IDENTIFIER); - } else if (sc.Match(";;+")) { - sc.SetState(SCE_POWERPRO_LINECONTINUE); - } else if (sc.Match('/', '*')) { - sc.SetState(SCE_POWERPRO_COMMENTBLOCK); - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match('/', '/')) { - sc.SetState(SCE_POWERPRO_COMMENTLINE); - } else if (sc.atLineStart && sc.ch == ';') { //legacy comment that can only appear at the beginning of a line - sc.SetState(SCE_POWERPRO_COMMENTLINE); - } else if (sc.Match(";;")) { - sc.SetState(SCE_POWERPRO_COMMENTLINE); - } else if (sc.ch == '\"') { - sc.SetState(SCE_POWERPRO_DOUBLEQUOTEDSTRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_POWERPRO_SINGLEQUOTEDSTRING); - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_POWERPRO_OPERATOR); - } - } - } - - //************************************* - // Colourize the last word correctly - //************************************* - if (sc.state == SCE_POWERPRO_IDENTIFIER) - { - if (keywords.InList(s_save)) { - sc.ChangeState(SCE_POWERPRO_WORD); - sc.SetState(SCE_POWERPRO_DEFAULT); - } - else if (keywords2.InList(s_save)) { - sc.ChangeState(SCE_POWERPRO_WORD2); - sc.SetState(SCE_POWERPRO_DEFAULT); - } - else if (keywords3.InList(s_save)) { - sc.ChangeState(SCE_POWERPRO_WORD3); - sc.SetState(SCE_POWERPRO_DEFAULT); - } - else if (keywords4.InList(s_save)) { - sc.ChangeState(SCE_POWERPRO_WORD4); - sc.SetState(SCE_POWERPRO_DEFAULT); - } - else { - sc.SetState(SCE_POWERPRO_DEFAULT); - } - } - sc.Complete(); -} - -static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) -{ - //define the character sets - CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); - - bool isFoldingAll = true; //used to tell if we're recursively folding the whole document, or just a small piece (ie: if statement or 1 function) - int endPos = startPos + length; - int lastLine = styler.GetLine(styler.Length()); //used to help fold the last line correctly - - // get settings from the config files for folding comments and preprocessor lines - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldInComment = styler.GetPropertyInt("fold.comment") == 2; - bool foldCompact = true; - - // Backtrack to previous line in case need to fix its fold status - int lineCurrent = styler.GetLine(startPos); - if (startPos > 0) { - isFoldingAll = false; - if (lineCurrent > 0) { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); - } - } - // vars for style of previous/current/next lines - int style = GetStyleFirstWord(lineCurrent,styler); - int stylePrev = 0; - - // find the first previous line without continuation character at the end - while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || - (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); - } - if (lineCurrent > 0) { - stylePrev = GetStyleFirstWord(lineCurrent-1,styler); - } - // vars for getting first word to check for keywords - bool FirstWordStart = false; - bool FirstWordEnd = false; - - const unsigned int KEYWORD_MAX = 10; - char szKeyword[KEYWORD_MAX]=""; - unsigned int szKeywordlen = 0; - - char szDo[3]=""; - int szDolen = 0; - bool DoFoundLast = false; - - // var for indentlevel - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) { - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - } - int levelNext = levelCurrent; - - int visibleChars = 0; - int functionCount = 0; - - char chNext = styler.SafeGetCharAt(startPos); - char chPrev = '\0'; - char chPrevPrev = '\0'; - char chPrevPrevPrev = '\0'; - - for (int i = startPos; i < endPos; i++) { - - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if ((ch > 0) && setWord.Contains(ch)) { - visibleChars++; - } - - // get the syle for the current character neede to check in comment - int stylech = styler.StyleAt(i); - - // get first word for the line for indent check max 9 characters - if (FirstWordStart && (!(FirstWordEnd))) { - if ((ch > 0) && !setWord.Contains(ch)) { - FirstWordEnd = true; - } - else if (szKeywordlen < KEYWORD_MAX - 1) { - szKeyword[szKeywordlen++] = static_cast(tolower(ch)); - szKeyword[szKeywordlen] = '\0'; - } - } - - // start the capture of the first word - if (!(FirstWordStart)) { - if ((ch > 0) && (setWord.Contains(ch) || setWordStart.Contains(ch) || ch == ';' || ch == '/')) { - FirstWordStart = true; - if (szKeywordlen < KEYWORD_MAX - 1) { - szKeyword[szKeywordlen++] = static_cast(tolower(ch)); - szKeyword[szKeywordlen] = '\0'; - } - } - } - // only process this logic when not in comment section - if (stylech != SCE_POWERPRO_COMMENTLINE) { - if (DoFoundLast) { - if (DoFoundLast && (ch > 0) && setWord.Contains(ch)) { - DoFoundLast = false; - } - } - // find out if the word "do" is the last on a "if" line - if (FirstWordEnd && strcmp(szKeyword,"if") == 0) { - if (szDolen == 2) { - szDo[0] = szDo[1]; - szDo[1] = static_cast(tolower(ch)); - szDo[2] = '\0'; - if (strcmp(szDo,"do") == 0 ) { - DoFoundLast = true; - } - } - else if (szDolen < 2) { - szDo[szDolen++] = static_cast(tolower(ch)); - szDo[szDolen] = '\0'; - } - } - } - - // End of Line found so process the information - if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { - - // ************************** - // Folding logic for Keywords - // ************************** - - // if a keyword is found on the current line and the line doesn't end with ;;+ (continuation) - // and we are not inside a commentblock. - if (szKeywordlen > 0 && - (!(chPrev == '+' && chPrevPrev == ';' && chPrevPrevPrev ==';')) && - ((!(IsStreamCommentStyle(style)) || foldInComment)) ) { - - // only fold "if" last keyword is "then" (else its a one line if) - if (strcmp(szKeyword,"if") == 0 && DoFoundLast) { - levelNext++; - } - // create new fold for these words - if (strcmp(szKeyword,"for") == 0) { - levelNext++; - } - - //handle folding for functions/labels - //Note: Functions and labels don't have an explicit end like [end function] - // 1. functions/labels end at the start of another function - // 2. functions/labels end at the end of the file - if ((strcmp(szKeyword,"function") == 0) || (szKeywordlen > 0 && szKeyword[0] == '@')) { - if (isFoldingAll) { //if we're folding the whole document (recursivly by lua script) - - if (functionCount > 0) { - levelCurrent--; - } else { - levelNext++; - } - functionCount++; - - } else { //if just folding a small piece (by clicking on the minus sign next to the word) - levelCurrent--; - } - } - - // end the fold for these words before the current line - if (strcmp(szKeyword,"endif") == 0 || strcmp(szKeyword,"endfor") == 0) { - levelNext--; - levelCurrent--; - } - // end the fold for these words before the current line and Start new fold - if (strcmp(szKeyword,"else") == 0 || strcmp(szKeyword,"elseif") == 0 ) { - levelCurrent--; - } - } - // Preprocessor and Comment folding - int styleNext = GetStyleFirstWord(lineCurrent + 1,styler); - - // ********************************* - // Folding logic for Comment blocks - // ********************************* - if (foldComment && IsStreamCommentStyle(style)) { - // Start of a comment block - if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) { - levelNext++; - } - // fold till the last line for normal comment lines - else if (IsStreamCommentStyle(stylePrev) - && !(styleNext == SCE_POWERPRO_COMMENTLINE) - && stylePrev == SCE_POWERPRO_COMMENTLINE - && style == SCE_POWERPRO_COMMENTLINE) { - levelNext--; - } - // fold till the one but last line for Blockcomment lines - else if (IsStreamCommentStyle(stylePrev) - && !(styleNext == SCE_POWERPRO_COMMENTBLOCK) - && style == SCE_POWERPRO_COMMENTBLOCK) { - levelNext--; - levelCurrent--; - } - } - - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - - // reset values for the next line - lineCurrent++; - stylePrev = style; - style = styleNext; - levelCurrent = levelNext; - visibleChars = 0; - - // if the last characters are ;;+ then don't reset since the line continues on the next line. - if (chPrev == '+' && chPrevPrev == ';' && chPrevPrevPrev == ';') { - //do nothing - } else { - szKeywordlen = 0; - szDolen = 0; - FirstWordStart = false; - FirstWordEnd = false; - DoFoundLast = false; - //blank out keyword - for (unsigned int i = 0; i < KEYWORD_MAX; i++) { - szKeyword[i] = '\0'; - } - } - } - - // save the last processed characters - if ((ch > 0) && !isspacechar(ch)) { - chPrevPrevPrev = chPrevPrev; - chPrevPrev = chPrev; - chPrev = ch; - visibleChars++; - } - } - - //close folds on the last line - without this a 'phantom' - //fold can appear when an open fold is on the last line - //this can occur because functions and labels don't have an explicit end - if (lineCurrent >= lastLine) { - int lev = 0; - lev |= SC_FOLDLEVELWHITEFLAG; - styler.SetLevel(lineCurrent, lev); - } - -} - -static const char * const powerProWordLists[] = { - "Keyword list 1", - "Keyword list 2", - "Keyword list 3", - "Keyword list 4", - 0, - }; - -static void ColourisePowerProDocWrapper(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - ColourisePowerProDoc(startPos, length, initStyle, keywordlists, styler, false); -} - -LexerModule lmPowerPro(SCLEX_POWERPRO, ColourisePowerProDocWrapper, "powerpro", FoldPowerProDoc, powerProWordLists); diff --git a/src/LexPowerShell.cxx b/src/LexPowerShell.cxx deleted file mode 100644 index f2014ca8d..000000000 --- a/src/LexPowerShell.cxx +++ /dev/null @@ -1,198 +0,0 @@ -// Scintilla source code edit control -/** @file LexPowerShell.cxx - ** Lexer for PowerShell scripts. - **/ -// Copyright 2008 by Tim Gerundt -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// Extended to accept accented characters -static inline bool IsAWordChar(int ch) { - return ch >= 0x80 || isalnum(ch) || ch == '-'; -} - -static void ColourisePowerShellDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - - styler.StartAt(startPos); - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.state == SCE_POWERSHELL_COMMENT) { - if (sc.atLineEnd) { - sc.SetState(SCE_POWERSHELL_DEFAULT); - } - } else if (sc.state == SCE_POWERSHELL_COMMENTSTREAM) { - if (sc.ch == '>' && sc.chPrev == '#') { - sc.ForwardSetState(SCE_POWERSHELL_DEFAULT); - } - } else if (sc.state == SCE_POWERSHELL_STRING) { - // This is a doubles quotes string - if (sc.ch == '\"') { - sc.ForwardSetState(SCE_POWERSHELL_DEFAULT); - } - } else if (sc.state == SCE_POWERSHELL_CHARACTER) { - // This is a single quote string - if (sc.ch == '\'') { - sc.ForwardSetState(SCE_POWERSHELL_DEFAULT); - } - } else if (sc.state == SCE_POWERSHELL_NUMBER) { - if (!IsADigit(sc.ch)) { - sc.SetState(SCE_POWERSHELL_DEFAULT); - } - } else if (sc.state == SCE_POWERSHELL_VARIABLE) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_POWERSHELL_DEFAULT); - } - } else if (sc.state == SCE_POWERSHELL_OPERATOR) { - if (!isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_POWERSHELL_DEFAULT); - } - } else if (sc.state == SCE_POWERSHELL_IDENTIFIER) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - - if (keywords.InList(s)) { - sc.ChangeState(SCE_POWERSHELL_KEYWORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_POWERSHELL_CMDLET); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_POWERSHELL_ALIAS); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_POWERSHELL_FUNCTION); - } else if (keywords5.InList(s)) { - sc.ChangeState(SCE_POWERSHELL_USER1); - } - sc.SetState(SCE_POWERSHELL_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_POWERSHELL_DEFAULT) { - if (sc.ch == '#') { - sc.SetState(SCE_POWERSHELL_COMMENT); - } else if (sc.ch == '<' && sc.chNext == '#') { - sc.SetState(SCE_POWERSHELL_COMMENTSTREAM); - } else if (sc.ch == '\"') { - sc.SetState(SCE_POWERSHELL_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_POWERSHELL_CHARACTER); - } else if (sc.ch == '$') { - sc.SetState(SCE_POWERSHELL_VARIABLE); - } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_POWERSHELL_NUMBER); - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_POWERSHELL_OPERATOR); - } else if (IsAWordChar(sc.ch)) { - sc.SetState(SCE_POWERSHELL_IDENTIFIER); - } - } - } - sc.Complete(); -} - -// Store both the current line's fold level and the next lines in the -// level store to make it easy to pick up with each increment -// and to make it possible to fiddle the current level for "} else {". -static void FoldPowerShellDoc(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelMinCurrent = levelCurrent; - int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (style == SCE_POWERSHELL_OPERATOR) { - if (ch == '{') { - // Measure the minimum before a '{' to allow - // folding on "} else {" - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - levelNext++; - } else if (ch == '}') { - levelNext--; - } - } else if (foldComment && style == SCE_POWERSHELL_COMMENTSTREAM) { - if (stylePrev != SCE_POWERSHELL_COMMENTSTREAM) { - levelNext++; - } else if (styleNext != SCE_POWERSHELL_COMMENTSTREAM) { - levelNext--; - } - } - if (!IsASpace(ch)) - visibleChars++; - if (atEOL || (i == endPos-1)) { - int levelUse = levelCurrent; - if (foldAtElse) { - levelUse = levelMinCurrent; - } - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - levelMinCurrent = levelCurrent; - visibleChars = 0; - } - } -} - -static const char * const powershellWordLists[] = { - "Commands", - "Cmdlets", - "Aliases", - "Functions", - "User1", - 0 -}; - -LexerModule lmPowerShell(SCLEX_POWERSHELL, ColourisePowerShellDoc, "powershell", FoldPowerShellDoc, powershellWordLists); - diff --git a/src/LexProgress.cxx b/src/LexProgress.cxx deleted file mode 100644 index 9e1940e29..000000000 --- a/src/LexProgress.cxx +++ /dev/null @@ -1,279 +0,0 @@ -// Scintilla source code edit control -/** @file LexProgress.cxx - ** Lexer for Progress 4GL. - ** Based on LexCPP.cxx of Neil Hodgson - **/ -// Copyright 2006-2007 by Yuval Papish -// The License.txt file describes the conditions under which this software may be distributed. - -/** TODO: -WebSpeed support in html lexer -Support "end triggers" expression of the triggers phrase -Support more than 6 comments levels -**/ -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static inline bool IsAWordStart(int ch) { - return (ch < 0x80) && (isalpha(ch) || ch == '_'); -} - -enum SentenceStart { SetSentenceStart = 0xf, ResetSentenceStart = 0x10}; // true -> bit = 0 - -static void Colourise4glDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords1 = *keywordlists[0]; // regular keywords - WordList &keywords2 = *keywordlists[1]; // block opening keywords, only when SentenceStart - WordList &keywords3 = *keywordlists[2]; // block opening keywords - //WordList &keywords4 = *keywordlists[3]; // preprocessor keywords. Not implemented - - - int visibleChars = 0; - int mask; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.atLineStart) { - // Reset states to begining of colourise so no surprises - // if different sets of lines lexed. - visibleChars = 0; - } - - // Handle line continuation generically. - if ((sc.state & 0xf) < SCE_4GL_COMMENT1) { - if (sc.ch == '~') { - if (sc.chNext > ' ') { - // skip special char after ~ - sc.Forward(); - continue; - } - else { - // Skip whitespace between ~ and EOL - while (sc.More() && (sc.chNext == ' ' || sc.chNext == '\t') ) { - sc.Forward(); - } - if (sc.chNext == '\n' || sc.chNext == '\r') { - sc.Forward(); - if (sc.ch == '\r' && sc.chNext == '\n') { - sc.Forward(); - } - sc.Forward(); - continue; - } - } - } - } - // Determine if a new state should be terminated. - mask = sc.state & 0x10; - switch (sc.state & 0xf) { - case SCE_4GL_OPERATOR: - sc.SetState(SCE_4GL_DEFAULT | mask); - break; - case SCE_4GL_NUMBER: - if (!(IsADigit(sc.ch))) { - sc.SetState(SCE_4GL_DEFAULT | mask); - } - break; - case SCE_4GL_IDENTIFIER: - if (!IsAWordChar(sc.ch) && sc.ch != '-') { - char s[1000]; - sc.GetCurrentLowered(s, sizeof(s)); - if ((((sc.state & 0x10) == 0) && keywords2.InList(s)) || keywords3.InList(s)) { - sc.ChangeState(SCE_4GL_BLOCK | ResetSentenceStart); - } - else if (keywords1.InList(s)) { - if ((s[0] == 'e' && s[1] =='n' && s[2] == 'd' && !isalnum(s[3]) && s[3] != '-') || - (s[0] == 'f' && s[1] =='o' && s[2] == 'r' && s[3] == 'w' && s[4] =='a' && s[5] == 'r' && s[6] == 'd'&& !isalnum(s[7]))) { - sc.ChangeState(SCE_4GL_END | ResetSentenceStart); - } - else if ((s[0] == 'e' && s[1] =='l' && s[2] == 's' && s[3] == 'e') || - (s[0] == 't' && s[1] =='h' && s[2] == 'e' && s[3] == 'n')) { - sc.ChangeState(SCE_4GL_WORD & SetSentenceStart); - } - else { - sc.ChangeState(SCE_4GL_WORD | ResetSentenceStart); - } - } - sc.SetState(SCE_4GL_DEFAULT | (sc.state & 0x10)); - } - break; - case SCE_4GL_PREPROCESSOR: - if (sc.atLineStart) { - sc.SetState(SCE_4GL_DEFAULT & SetSentenceStart); - } - /* code removed to allow comments inside preprocessor - else if (sc.ch == '*' && sc.chNext == '/') { - sc.ForwardSetState(SCE_4GL_DEFAULT | sentenceStartState); } */ - break; - case SCE_4GL_STRING: - if (sc.ch == '\"') { - sc.ForwardSetState(SCE_4GL_DEFAULT | mask); - } - break; - case SCE_4GL_CHARACTER: - if (sc.ch == '\'') { - sc.ForwardSetState(SCE_4GL_DEFAULT | mask); - } - break; - default: - if ((sc.state & 0xf) >= SCE_4GL_COMMENT1) { - if (sc.ch == '*' && sc.chNext == '/') { - sc.Forward(); - if ((sc.state & 0xf) == SCE_4GL_COMMENT1) { - sc.ForwardSetState(SCE_4GL_DEFAULT | mask); - } - else - sc.SetState((sc.state & 0x1f) - 1); - } else if (sc.ch == '/' && sc.chNext == '*') { - sc.Forward(); - sc.SetState((sc.state & 0x1f) + 1); - } - } - } - - // Determine if a new state should be entered. - mask = sc.state & 0x10; - if ((sc.state & 0xf) == SCE_4GL_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_4GL_NUMBER | ResetSentenceStart); - } else if (IsAWordStart(sc.ch) || (sc.ch == '@')) { - sc.SetState(SCE_4GL_IDENTIFIER | mask); - } else if (sc.ch == '/' && sc.chNext == '*') { - sc.SetState(SCE_4GL_COMMENT1 | mask); - sc.Forward(); - } else if (sc.ch == '\"') { - sc.SetState(SCE_4GL_STRING | ResetSentenceStart); - } else if (sc.ch == '\'') { - sc.SetState(SCE_4GL_CHARACTER | ResetSentenceStart); - } else if (sc.ch == '&' && visibleChars == 0 && ((sc.state & 0x10) == 0)) { - sc.SetState(SCE_4GL_PREPROCESSOR | ResetSentenceStart); - // Skip whitespace between & and preprocessor word - do { - sc.Forward(); - } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); - // Handle syntactical line termination - } else if ((sc.ch == '.' || sc.ch == ':' || sc.ch == '}') && (sc.chNext == ' ' || sc.chNext == '\t' || sc.chNext == '\n' || sc.chNext == '\r')) { - sc.SetState(sc.state & SetSentenceStart); - } else if (isoperator(static_cast(sc.ch))) { - /* This code allows highlight of handles. Alas, it would cause the phrase "last-event:function" - to be recognized as a BlockBegin */ - - if (sc.ch == ':') - sc.SetState(SCE_4GL_OPERATOR & SetSentenceStart); - /* else */ - sc.SetState(SCE_4GL_OPERATOR | ResetSentenceStart); - } - } - - if (!IsASpace(sc.ch)) { - visibleChars++; - } - } - sc.Complete(); -} - -static bool IsStreamCommentStyle(int style) { - return (style & 0xf) >= SCE_4GL_COMMENT1 ; -} - -// Store both the current line's fold level and the next lines in the -// level store to make it easy to pick up with each increment -// and to make it possible to fiddle the current level for "} else {". -static void FoldNoBox4glDoc(unsigned int startPos, int length, int initStyle, - Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelMinCurrent = levelCurrent; - int levelNext = levelCurrent; - char chNext = static_cast(tolower(styler[startPos])); - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = static_cast(tolower(styler.SafeGetCharAt(i + 1))); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && IsStreamCommentStyle(style)) { - if (!IsStreamCommentStyle(stylePrev)) { - levelNext++; - } else if (!IsStreamCommentStyle(styleNext)) { // && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelNext--; - } - } - else if ((style & 0xf) == SCE_4GL_BLOCK && !isalnum(chNext)) { - levelNext++; - } - else if ((style & 0xf) == SCE_4GL_END && (ch == 'e' || ch == 'f')) { - levelNext--; - } - if (atEOL) { - int levelUse = levelCurrent; - if (foldAtElse) { - levelUse = levelMinCurrent; - } - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - levelMinCurrent = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } -} - -static void Fold4glDoc(unsigned int startPos, int length, int initStyle, WordList *[], - Accessor &styler) { - FoldNoBox4glDoc(startPos, length, initStyle, styler); -} - -static const char * const FglWordLists[] = { - "Primary keywords and identifiers", - "Secondary keywords and identifiers", - "Documentation comment keywords", - "Unused", - "Global classes and typedefs", - 0, - }; - -LexerModule lmProgress(SCLEX_PROGRESS, Colourise4glDoc, "progress", Fold4glDoc, FglWordLists); diff --git a/src/LexPython.cxx b/src/LexPython.cxx deleted file mode 100644 index b8921865c..000000000 --- a/src/LexPython.cxx +++ /dev/null @@ -1,569 +0,0 @@ -// Scintilla source code edit control -/** @file LexPython.cxx - ** Lexer for Python. - **/ -// Copyright 1998-2002 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/* kwCDef, kwCTypeName only used for Cython */ -enum kwType { kwOther, kwClass, kwDef, kwImport, kwCDef, kwCTypeName }; - -static const int indicatorWhitespace = 1; - -static bool IsPyComment(Accessor &styler, int pos, int len) { - return len > 0 && styler[pos] == '#'; -} - -enum literalsAllowed { litNone=0, litU=1, litB=2}; - -static bool IsPyStringTypeChar(int ch, literalsAllowed allowed) { - return - ((allowed & litB) && (ch == 'b' || ch == 'B')) || - ((allowed & litU) && (ch == 'u' || ch == 'U')); -} - -static bool IsPyStringStart(int ch, int chNext, int chNext2, literalsAllowed allowed) { - if (ch == '\'' || ch == '"') - return true; - if (IsPyStringTypeChar(ch, allowed)) { - if (chNext == '"' || chNext == '\'') - return true; - if ((chNext == 'r' || chNext == 'R') && (chNext2 == '"' || chNext2 == '\'')) - return true; - } - if ((ch == 'r' || ch == 'R') && (chNext == '"' || chNext == '\'')) - return true; - - return false; -} - -/* Return the state to use for the string starting at i; *nextIndex will be set to the first index following the quote(s) */ -static int GetPyStringState(Accessor &styler, int i, unsigned int *nextIndex, literalsAllowed allowed) { - char ch = styler.SafeGetCharAt(i); - char chNext = styler.SafeGetCharAt(i + 1); - - // Advance beyond r, u, or ur prefix (or r, b, or br in Python 3.0), but bail if there are any unexpected chars - if (ch == 'r' || ch == 'R') { - i++; - ch = styler.SafeGetCharAt(i); - chNext = styler.SafeGetCharAt(i + 1); - } else if (IsPyStringTypeChar(ch, allowed)) { - if (chNext == 'r' || chNext == 'R') - i += 2; - else - i += 1; - ch = styler.SafeGetCharAt(i); - chNext = styler.SafeGetCharAt(i + 1); - } - - if (ch != '"' && ch != '\'') { - *nextIndex = i + 1; - return SCE_P_DEFAULT; - } - - if (ch == chNext && ch == styler.SafeGetCharAt(i + 2)) { - *nextIndex = i + 3; - - if (ch == '"') - return SCE_P_TRIPLEDOUBLE; - else - return SCE_P_TRIPLE; - } else { - *nextIndex = i + 1; - - if (ch == '"') - return SCE_P_STRING; - else - return SCE_P_CHARACTER; - } -} - -static inline bool IsAWordChar(int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); -} - -static inline bool IsAWordStart(int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static void ColourisePyDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - int endPos = startPos + length; - - // Backtrack to previous line in case need to fix its tab whinging - int lineCurrent = styler.GetLine(startPos); - if (startPos > 0) { - if (lineCurrent > 0) { - lineCurrent--; - // Look for backslash-continued lines - while (lineCurrent > 0) { - int eolPos = styler.LineStart(lineCurrent) - 1; - int eolStyle = styler.StyleAt(eolPos); - if (eolStyle == SCE_P_STRING - || eolStyle == SCE_P_CHARACTER - || eolStyle == SCE_P_STRINGEOL) { - lineCurrent -= 1; - } else { - break; - } - } - startPos = styler.LineStart(lineCurrent); - } - initStyle = startPos == 0 ? SCE_P_DEFAULT : styler.StyleAt(startPos - 1); - } - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - - // property tab.timmy.whinge.level - // For Python code, checks whether indenting is consistent. - // The default, 0 turns off indentation checking, - // 1 checks whether each line is potentially inconsistent with the previous line, - // 2 checks whether any space characters occur before a tab character in the indentation, - // 3 checks whether any spaces are in the indentation, and - // 4 checks for any tab characters in the indentation. - // 1 is a good level to use. - const int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level"); - - // property lexer.python.literals.binary - // Set to 0 to not recognise Python 3 binary and octal literals: 0b1011 0o712. - bool base2or8Literals = styler.GetPropertyInt("lexer.python.literals.binary", 1) != 0; - - // property lexer.python.strings.u - // Set to 0 to not recognise Python Unicode literals u"x" as used before Python 3. - literalsAllowed allowedLiterals = (styler.GetPropertyInt("lexer.python.strings.u", 1)) ? litU : litNone; - - // property lexer.python.strings.b - // Set to 0 to not recognise Python 3 bytes literals b"x". - if (styler.GetPropertyInt("lexer.python.strings.b", 1)) - allowedLiterals = static_cast(allowedLiterals | litB); - - // property lexer.python.strings.over.newline - // Set to 1 to allow strings to span newline characters. - bool stringsOverNewline = styler.GetPropertyInt("lexer.python.strings.over.newline") != 0; - - initStyle = initStyle & 31; - if (initStyle == SCE_P_STRINGEOL) { - initStyle = SCE_P_DEFAULT; - } - - kwType kwLast = kwOther; - int spaceFlags = 0; - styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment); - bool base_n_number = false; - - StyleContext sc(startPos, endPos - startPos, initStyle, styler); - - bool indentGood = true; - int startIndicator = sc.currentPos; - bool inContinuedString = false; - - for (; sc.More(); sc.Forward()) { - - if (sc.atLineStart) { - styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment); - indentGood = true; - if (whingeLevel == 1) { - indentGood = (spaceFlags & wsInconsistent) == 0; - } else if (whingeLevel == 2) { - indentGood = (spaceFlags & wsSpaceTab) == 0; - } else if (whingeLevel == 3) { - indentGood = (spaceFlags & wsSpace) == 0; - } else if (whingeLevel == 4) { - indentGood = (spaceFlags & wsTab) == 0; - } - if (!indentGood) { - styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 0); - startIndicator = sc.currentPos; - } - } - - if (sc.atLineEnd) { - if ((sc.state == SCE_P_DEFAULT) || - (sc.state == SCE_P_TRIPLE) || - (sc.state == SCE_P_TRIPLEDOUBLE)) { - // Perform colourisation of white space and triple quoted strings at end of each line to allow - // tab marking to work inside white space and triple quoted strings - sc.SetState(sc.state); - } - lineCurrent++; - if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) { - if (inContinuedString || stringsOverNewline) { - inContinuedString = false; - } else { - sc.ChangeState(SCE_P_STRINGEOL); - sc.ForwardSetState(SCE_P_DEFAULT); - } - } - if (!sc.More()) - break; - } - - bool needEOLCheck = false; - - // Check for a state end - if (sc.state == SCE_P_OPERATOR) { - kwLast = kwOther; - sc.SetState(SCE_P_DEFAULT); - } else if (sc.state == SCE_P_NUMBER) { - if (!IsAWordChar(sc.ch) && - !(!base_n_number && ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) { - sc.SetState(SCE_P_DEFAULT); - } - } else if (sc.state == SCE_P_IDENTIFIER) { - if ((sc.ch == '.') || (!IsAWordChar(sc.ch))) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - int style = SCE_P_IDENTIFIER; - if ((kwLast == kwImport) && (strcmp(s, "as") == 0)) { - style = SCE_P_WORD; - } else if (keywords.InList(s)) { - style = SCE_P_WORD; - } else if (kwLast == kwClass) { - style = SCE_P_CLASSNAME; - } else if (kwLast == kwDef) { - style = SCE_P_DEFNAME; - } else if (kwLast == kwCDef) { - int pos = sc.currentPos; - unsigned char ch = styler.SafeGetCharAt(pos, '\0'); - while (ch != '\0') { - if (ch == '(') { - style = SCE_P_DEFNAME; - break; - } else if (ch == ':') { - style = SCE_P_CLASSNAME; - break; - } else if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') { - pos++; - ch = styler.SafeGetCharAt(pos, '\0'); - } else { - break; - } - } - } else if (keywords2.InList(s)) { - style = SCE_P_WORD2; - } - sc.ChangeState(style); - sc.SetState(SCE_P_DEFAULT); - if (style == SCE_P_WORD) { - if (0 == strcmp(s, "class")) - kwLast = kwClass; - else if (0 == strcmp(s, "def")) - kwLast = kwDef; - else if (0 == strcmp(s, "import")) - kwLast = kwImport; - else if (0 == strcmp(s, "cdef")) - kwLast = kwCDef; - else if (0 == strcmp(s, "cimport")) - kwLast = kwImport; - else if (kwLast != kwCDef) - kwLast = kwOther; - } else if (kwLast != kwCDef) { - kwLast = kwOther; - } - } - } else if ((sc.state == SCE_P_COMMENTLINE) || (sc.state == SCE_P_COMMENTBLOCK)) { - if (sc.ch == '\r' || sc.ch == '\n') { - sc.SetState(SCE_P_DEFAULT); - } - } else if (sc.state == SCE_P_DECORATOR) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_P_DEFAULT); - } - } else if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) { - if (sc.ch == '\\') { - if ((sc.chNext == '\r') && (sc.GetRelative(2) == '\n')) { - sc.Forward(); - } - if (sc.chNext == '\n' || sc.chNext == '\r') { - inContinuedString = true; - } else { - // Don't roll over the newline. - sc.Forward(); - } - } else if ((sc.state == SCE_P_STRING) && (sc.ch == '\"')) { - sc.ForwardSetState(SCE_P_DEFAULT); - needEOLCheck = true; - } else if ((sc.state == SCE_P_CHARACTER) && (sc.ch == '\'')) { - sc.ForwardSetState(SCE_P_DEFAULT); - needEOLCheck = true; - } - } else if (sc.state == SCE_P_TRIPLE) { - if (sc.ch == '\\') { - sc.Forward(); - } else if (sc.Match("\'\'\'")) { - sc.Forward(); - sc.Forward(); - sc.ForwardSetState(SCE_P_DEFAULT); - needEOLCheck = true; - } - } else if (sc.state == SCE_P_TRIPLEDOUBLE) { - if (sc.ch == '\\') { - sc.Forward(); - } else if (sc.Match("\"\"\"")) { - sc.Forward(); - sc.Forward(); - sc.ForwardSetState(SCE_P_DEFAULT); - needEOLCheck = true; - } - } - - if (!indentGood && !IsASpaceOrTab(sc.ch)) { - styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 1); - startIndicator = sc.currentPos; - indentGood = true; - } - - // One cdef line, clear kwLast only at end of line - if (kwLast == kwCDef && sc.atLineEnd) { - kwLast = kwOther; - } - - // State exit code may have moved on to end of line - if (needEOLCheck && sc.atLineEnd) { - lineCurrent++; - styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment); - if (!sc.More()) - break; - } - - // Check for a new state starting character - if (sc.state == SCE_P_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - if (sc.ch == '0' && (sc.chNext == 'x' || sc.chNext == 'X')) { - base_n_number = true; - sc.SetState(SCE_P_NUMBER); - } else if (sc.ch == '0' && - (sc.chNext == 'o' || sc.chNext == 'O' || sc.chNext == 'b' || sc.chNext == 'B')) { - if (base2or8Literals) { - base_n_number = true; - sc.SetState(SCE_P_NUMBER); - } else { - sc.SetState(SCE_P_NUMBER); - sc.ForwardSetState(SCE_P_IDENTIFIER); - } - } else { - base_n_number = false; - sc.SetState(SCE_P_NUMBER); - } - } else if ((isascii(sc.ch) && isoperator(static_cast(sc.ch))) || sc.ch == '`') { - sc.SetState(SCE_P_OPERATOR); - } else if (sc.ch == '#') { - sc.SetState(sc.chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE); - } else if (sc.ch == '@') { - sc.SetState(SCE_P_DECORATOR); - } else if (IsPyStringStart(sc.ch, sc.chNext, sc.GetRelative(2), allowedLiterals)) { - unsigned int nextIndex = 0; - sc.SetState(GetPyStringState(styler, sc.currentPos, &nextIndex, allowedLiterals)); - while (nextIndex > (sc.currentPos + 1) && sc.More()) { - sc.Forward(); - } - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_P_IDENTIFIER); - } - } - } - styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 0); - sc.Complete(); -} - -static bool IsCommentLine(int line, Accessor &styler) { - int pos = styler.LineStart(line); - int eol_pos = styler.LineStart(line + 1) - 1; - for (int i = pos; i < eol_pos; i++) { - char ch = styler[i]; - if (ch == '#') - return true; - else if (ch != ' ' && ch != '\t') - return false; - } - return false; -} - -static bool IsQuoteLine(int line, Accessor &styler) { - int style = styler.StyleAt(styler.LineStart(line)) & 31; - return ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE)); -} - - -static void FoldPyDoc(unsigned int startPos, int length, int /*initStyle - unused*/, - WordList *[], Accessor &styler) { - const int maxPos = startPos + length; - const int maxLines = styler.GetLine(maxPos - 1); // Requested last line - const int docLines = styler.GetLine(styler.Length() - 1); // Available last line - - // property fold.comment.python - // This option enables folding multi-line comments when using the Python lexer. - const bool foldComment = styler.GetPropertyInt("fold.comment.python") != 0; - - // property fold.quotes.python - // This option enables folding multi-line quoted strings when using the Python lexer. - const bool foldQuotes = styler.GetPropertyInt("fold.quotes.python") != 0; - - const bool foldCompact = styler.GetPropertyInt("fold.compact") != 0; - - // Backtrack to previous non-blank line so we can determine indent level - // for any white space lines (needed esp. within triple quoted strings) - // and so we can fix any preceding fold level (which is why we go back - // at least one line in all cases) - int spaceFlags = 0; - int lineCurrent = styler.GetLine(startPos); - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); - while (lineCurrent > 0) { - lineCurrent--; - indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); - if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) && - (!IsCommentLine(lineCurrent, styler)) && - (!IsQuoteLine(lineCurrent, styler))) - break; - } - int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; - - // Set up initial loop state - startPos = styler.LineStart(lineCurrent); - int prev_state = SCE_P_DEFAULT & 31; - if (lineCurrent >= 1) - prev_state = styler.StyleAt(startPos - 1) & 31; - int prevQuote = foldQuotes && ((prev_state == SCE_P_TRIPLE) || (prev_state == SCE_P_TRIPLEDOUBLE)); - int prevComment = 0; - if (lineCurrent >= 1) - prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler); - - // Process all characters to end of requested range or end of any triple quote - // or comment that hangs over the end of the range. Cap processing in all cases - // to end of document (in case of unclosed quote or comment at end). - while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevQuote || prevComment)) { - - // Gather info - int lev = indentCurrent; - int lineNext = lineCurrent + 1; - int indentNext = indentCurrent; - int quote = false; - if (lineNext <= docLines) { - // Information about next line is only available if not at end of document - indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); - int style = styler.StyleAt(styler.LineStart(lineNext)) & 31; - quote = foldQuotes && ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE)); - } - const int quote_start = (quote && !prevQuote); - const int quote_continue = (quote && prevQuote); - const int comment = foldComment && IsCommentLine(lineCurrent, styler); - const int comment_start = (comment && !prevComment && (lineNext <= docLines) && - IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE)); - const int comment_continue = (comment && prevComment); - if ((!quote || !prevQuote) && !comment) - indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; - if (quote) - indentNext = indentCurrentLevel; - if (indentNext & SC_FOLDLEVELWHITEFLAG) - indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel; - - if (quote_start) { - // Place fold point at start of triple quoted string - lev |= SC_FOLDLEVELHEADERFLAG; - } else if (quote_continue || prevQuote) { - // Add level to rest of lines in the string - lev = lev + 1; - } else if (comment_start) { - // Place fold point at start of a block of comments - lev |= SC_FOLDLEVELHEADERFLAG; - } else if (comment_continue) { - // Add level to rest of lines in the block - lev = lev + 1; - } - - // Skip past any blank lines for next indent level info; we skip also - // comments (all comments, not just those starting in column 0) - // which effectively folds them into surrounding code rather - // than screwing up folding. - - while (!quote && - (lineNext < docLines) && - ((indentNext & SC_FOLDLEVELWHITEFLAG) || - (lineNext <= docLines && IsCommentLine(lineNext, styler)))) { - - lineNext++; - indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); - } - - const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK; - const int levelBeforeComments = Platform::Maximum(indentCurrentLevel,levelAfterComments); - - // Now set all the indent levels on the lines we skipped - // Do this from end to start. Once we encounter one line - // which is indented more than the line after the end of - // the comment-block, use the level of the block before - - int skipLine = lineNext; - int skipLevel = levelAfterComments; - - while (--skipLine > lineCurrent) { - int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL); - - if (foldCompact) { - if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments) - skipLevel = levelBeforeComments; - - int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG; - - styler.SetLevel(skipLine, skipLevel | whiteFlag); - } else { - if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments && - !(skipLineIndent & SC_FOLDLEVELWHITEFLAG) && - !IsCommentLine(skipLine, styler)) - skipLevel = levelBeforeComments; - - styler.SetLevel(skipLine, skipLevel); - } - } - - // Set fold header on non-quote/non-comment line - if (!quote && !comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) - lev |= SC_FOLDLEVELHEADERFLAG; - } - - // Keep track of triple quote and block comment state of previous line - prevQuote = quote; - prevComment = comment_start || comment_continue; - - // Set fold level for this line and move to next line - styler.SetLevel(lineCurrent, lev); - indentCurrent = indentNext; - lineCurrent = lineNext; - } - - // NOTE: Cannot set level of last line here because indentCurrent doesn't have - // header flag set; the loop above is crafted to take care of this case! - //styler.SetLevel(lineCurrent, indentCurrent); -} - -static const char *const pythonWordListDesc[] = { - "Keywords", - "Highlighted identifiers", - 0 -}; - -LexerModule lmPython(SCLEX_PYTHON, ColourisePyDoc, "python", FoldPyDoc, - pythonWordListDesc); - diff --git a/src/LexR.cxx b/src/LexR.cxx deleted file mode 100644 index cabbf5788..000000000 --- a/src/LexR.cxx +++ /dev/null @@ -1,213 +0,0 @@ -// Scintilla source code edit control -/** @file Lexr.cxx - ** Lexer for R, S, SPlus Statistics Program (Heavily derived from CPP Lexer). - ** - **/ -// Copyright 1998-2002 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static inline bool IsAnOperator(const int ch) { - if (isascii(ch) && isalnum(ch)) - return false; - // '.' left out as it is used to make up numbers - if (ch == '-' || ch == '+' || ch == '!' || ch == '~' || - ch == '?' || ch == ':' || ch == '*' || ch == '/' || - ch == '^' || ch == '<' || ch == '>' || ch == '=' || - ch == '&' || ch == '|' || ch == '$' || ch == '(' || - ch == ')' || ch == '}' || ch == '{' || ch == '[' || - ch == ']') - return true; - return false; -} - -static void ColouriseRDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - - - // Do not leak onto next line - if (initStyle == SCE_R_INFIXEOL) - initStyle = SCE_R_DEFAULT; - - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.atLineStart && (sc.state == SCE_R_STRING)) { - // Prevent SCE_R_STRINGEOL from leaking back to previous line - sc.SetState(SCE_R_STRING); - } - - // Determine if the current state should terminate. - if (sc.state == SCE_R_OPERATOR) { - sc.SetState(SCE_R_DEFAULT); - } else if (sc.state == SCE_R_NUMBER) { - if (!IsADigit(sc.ch) && !(sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_R_DEFAULT); - } - } else if (sc.state == SCE_R_IDENTIFIER) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(SCE_R_KWORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_R_BASEKWORD); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_R_OTHERKWORD); - } - sc.SetState(SCE_R_DEFAULT); - } - } else if (sc.state == SCE_R_COMMENT) { - if (sc.ch == '\r' || sc.ch == '\n') { - sc.SetState(SCE_R_DEFAULT); - } - } else if (sc.state == SCE_R_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_R_DEFAULT); - } - } else if (sc.state == SCE_R_INFIX) { - if (sc.ch == '%') { - sc.ForwardSetState(SCE_R_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_R_INFIXEOL); - sc.ForwardSetState(SCE_R_DEFAULT); - } - }else if (sc.state == SCE_R_STRING2) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_R_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_R_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_R_NUMBER); - } else if (IsAWordStart(sc.ch) ) { - sc.SetState(SCE_R_IDENTIFIER); - } else if (sc.Match('#')) { - sc.SetState(SCE_R_COMMENT); - } else if (sc.ch == '\"') { - sc.SetState(SCE_R_STRING); - } else if (sc.ch == '%') { - sc.SetState(SCE_R_INFIX); - } else if (sc.ch == '\'') { - sc.SetState(SCE_R_STRING2); - } else if (IsAnOperator(sc.ch)) { - sc.SetState(SCE_R_OPERATOR); - } - } - } - sc.Complete(); -} - -// Store both the current line's fold level and the next lines in the -// level store to make it easy to pick up with each increment -// and to make it possible to fiddle the current level for "} else {". -static void FoldRDoc(unsigned int startPos, int length, int, WordList *[], - Accessor &styler) { - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelMinCurrent = levelCurrent; - int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (style == SCE_R_OPERATOR) { - if (ch == '{') { - // Measure the minimum before a '{' to allow - // folding on "} else {" - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - levelNext++; - } else if (ch == '}') { - levelNext--; - } - } - if (atEOL) { - int levelUse = levelCurrent; - if (foldAtElse) { - levelUse = levelMinCurrent; - } - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - levelMinCurrent = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } -} - - -static const char * const RWordLists[] = { - "Language Keywords", - "Base / Default package function", - "Other Package Functions", - "Unused", - "Unused", - 0, - }; - - - -LexerModule lmR(SCLEX_R, ColouriseRDoc, "r", FoldRDoc, RWordLists); diff --git a/src/LexRebol.cxx b/src/LexRebol.cxx deleted file mode 100644 index 7139b8dbd..000000000 --- a/src/LexRebol.cxx +++ /dev/null @@ -1,322 +0,0 @@ -// Scintilla source code edit control -/** @file LexRebol.cxx - ** Lexer for REBOL. - ** Written by Pascal Hurni, inspired from LexLua by Paul Winwood & Marcos E. Wurzius & Philippe Lhoste - ** - ** History: - ** 2005-04-07 First release. - ** 2005-04-10 Closing parens and brackets go now in default style - ** String and comment nesting should be more safe - **/ -// Copyright 2005 by Pascal Hurni -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "StyleContext.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (isalnum(ch) || ch == '?' || ch == '!' || ch == '.' || ch == '\'' || ch == '+' || ch == '-' || ch == '*' || ch == '&' || ch == '|' || ch == '=' || ch == '_' || ch == '~'); -} - -static inline bool IsAWordStart(const int ch, const int ch2) { - return ((ch == '+' || ch == '-' || ch == '.') && !isdigit(ch2)) || - (isalpha(ch) || ch == '?' || ch == '!' || ch == '\'' || ch == '*' || ch == '&' || ch == '|' || ch == '=' || ch == '_' || ch == '~'); -} - -static inline bool IsAnOperator(const int ch, const int ch2, const int ch3) { - // One char operators - if (IsASpaceOrTab(ch2)) { - return ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '<' || ch == '>' || ch == '=' || ch == '?'; - } - - // Two char operators - if (IsASpaceOrTab(ch3)) { - return (ch == '*' && ch2 == '*') || - (ch == '/' && ch2 == '/') || - (ch == '<' && (ch2 == '=' || ch2 == '>')) || - (ch == '>' && ch2 == '=') || - (ch == '=' && (ch2 == '=' || ch2 == '?')) || - (ch == '?' && ch2 == '?'); - } - - return false; -} - -static inline bool IsBinaryStart(const int ch, const int ch2, const int ch3, const int ch4) { - return (ch == '#' && ch2 == '{') || - (IsADigit(ch) && ch2 == '#' && ch3 == '{' ) || - (IsADigit(ch) && IsADigit(ch2) && ch3 == '#' && ch4 == '{' ); -} - - -static void ColouriseRebolDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - WordList &keywords6 = *keywordlists[5]; - WordList &keywords7 = *keywordlists[6]; - WordList &keywords8 = *keywordlists[7]; - - int currentLine = styler.GetLine(startPos); - // Initialize the braced string {.. { ... } ..} nesting level, if we are inside such a string. - int stringLevel = 0; - if (initStyle == SCE_REBOL_BRACEDSTRING || initStyle == SCE_REBOL_COMMENTBLOCK) { - stringLevel = styler.GetLineState(currentLine - 1); - } - - bool blockComment = initStyle == SCE_REBOL_COMMENTBLOCK; - int dotCount = 0; - - // Do not leak onto next line - if (initStyle == SCE_REBOL_COMMENTLINE) { - initStyle = SCE_REBOL_DEFAULT; - } - - StyleContext sc(startPos, length, initStyle, styler); - if (startPos == 0) { - sc.SetState(SCE_REBOL_PREFACE); - } - for (; sc.More(); sc.Forward()) { - - //--- What to do at line end ? - if (sc.atLineEnd) { - // Can be either inside a {} string or simply at eol - if (sc.state != SCE_REBOL_BRACEDSTRING && sc.state != SCE_REBOL_COMMENTBLOCK && - sc.state != SCE_REBOL_BINARY && sc.state != SCE_REBOL_PREFACE) - sc.SetState(SCE_REBOL_DEFAULT); - - // Update the line state, so it can be seen by next line - currentLine = styler.GetLine(sc.currentPos); - switch (sc.state) { - case SCE_REBOL_BRACEDSTRING: - case SCE_REBOL_COMMENTBLOCK: - // Inside a braced string, we set the line state - styler.SetLineState(currentLine, stringLevel); - break; - default: - // Reset the line state - styler.SetLineState(currentLine, 0); - break; - } - - // continue with next char - continue; - } - - //--- What to do on white-space ? - if (IsASpaceOrTab(sc.ch)) - { - // Return to default if any of these states - if (sc.state == SCE_REBOL_OPERATOR || sc.state == SCE_REBOL_CHARACTER || - sc.state == SCE_REBOL_NUMBER || sc.state == SCE_REBOL_PAIR || - sc.state == SCE_REBOL_TUPLE || sc.state == SCE_REBOL_FILE || - sc.state == SCE_REBOL_DATE || sc.state == SCE_REBOL_TIME || - sc.state == SCE_REBOL_MONEY || sc.state == SCE_REBOL_ISSUE || - sc.state == SCE_REBOL_URL || sc.state == SCE_REBOL_EMAIL) { - sc.SetState(SCE_REBOL_DEFAULT); - } - } - - //--- Specialize state ? - // URL, Email look like identifier - if (sc.state == SCE_REBOL_IDENTIFIER) - { - if (sc.ch == ':' && !IsASpace(sc.chNext)) { - sc.ChangeState(SCE_REBOL_URL); - } else if (sc.ch == '@') { - sc.ChangeState(SCE_REBOL_EMAIL); - } else if (sc.ch == '$') { - sc.ChangeState(SCE_REBOL_MONEY); - } - } - // Words look like identifiers - if (sc.state == SCE_REBOL_IDENTIFIER || (sc.state >= SCE_REBOL_WORD && sc.state <= SCE_REBOL_WORD8)) { - // Keywords ? - if (!IsAWordChar(sc.ch) || sc.Match('/')) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - blockComment = strcmp(s, "comment") == 0; - if (keywords8.InList(s)) { - sc.ChangeState(SCE_REBOL_WORD8); - } else if (keywords7.InList(s)) { - sc.ChangeState(SCE_REBOL_WORD7); - } else if (keywords6.InList(s)) { - sc.ChangeState(SCE_REBOL_WORD6); - } else if (keywords5.InList(s)) { - sc.ChangeState(SCE_REBOL_WORD5); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_REBOL_WORD4); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_REBOL_WORD3); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_REBOL_WORD2); - } else if (keywords.InList(s)) { - sc.ChangeState(SCE_REBOL_WORD); - } - // Keep same style if there are refinements - if (!sc.Match('/')) { - sc.SetState(SCE_REBOL_DEFAULT); - } - } - // special numbers - } else if (sc.state == SCE_REBOL_NUMBER) { - switch (sc.ch) { - case 'x': sc.ChangeState(SCE_REBOL_PAIR); - break; - case ':': sc.ChangeState(SCE_REBOL_TIME); - break; - case '-': - case '/': sc.ChangeState(SCE_REBOL_DATE); - break; - case '.': if (++dotCount >= 2) sc.ChangeState(SCE_REBOL_TUPLE); - break; - } - } - - //--- Determine if the current state should terminate - if (sc.state == SCE_REBOL_QUOTEDSTRING || sc.state == SCE_REBOL_CHARACTER) { - if (sc.ch == '^' && sc.chNext == '\"') { - sc.Forward(); - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_REBOL_DEFAULT); - } - } else if (sc.state == SCE_REBOL_BRACEDSTRING || sc.state == SCE_REBOL_COMMENTBLOCK) { - if (sc.ch == '}') { - if (--stringLevel == 0) { - sc.ForwardSetState(SCE_REBOL_DEFAULT); - } - } else if (sc.ch == '{') { - stringLevel++; - } - } else if (sc.state == SCE_REBOL_BINARY) { - if (sc.ch == '}') { - sc.ForwardSetState(SCE_REBOL_DEFAULT); - } - } else if (sc.state == SCE_REBOL_TAG) { - if (sc.ch == '>') { - sc.ForwardSetState(SCE_REBOL_DEFAULT); - } - } else if (sc.state == SCE_REBOL_PREFACE) { - if (sc.MatchIgnoreCase("rebol")) - { - int i; - for (i=5; IsASpaceOrTab(styler.SafeGetCharAt(sc.currentPos+i, 0)); i++); - if (sc.GetRelative(i) == '[') - sc.SetState(SCE_REBOL_DEFAULT); - } - } - - //--- Parens and bracket changes to default style when the current is a number - if (sc.state == SCE_REBOL_NUMBER || sc.state == SCE_REBOL_PAIR || sc.state == SCE_REBOL_TUPLE || - sc.state == SCE_REBOL_MONEY || sc.state == SCE_REBOL_ISSUE || sc.state == SCE_REBOL_EMAIL || - sc.state == SCE_REBOL_URL || sc.state == SCE_REBOL_DATE || sc.state == SCE_REBOL_TIME) { - if (sc.ch == '(' || sc.ch == '[' || sc.ch == ')' || sc.ch == ']') { - sc.SetState(SCE_REBOL_DEFAULT); - } - } - - //--- Determine if a new state should be entered. - if (sc.state == SCE_REBOL_DEFAULT) { - if (IsAnOperator(sc.ch, sc.chNext, sc.GetRelative(2))) { - sc.SetState(SCE_REBOL_OPERATOR); - } else if (IsBinaryStart(sc.ch, sc.chNext, sc.GetRelative(2), sc.GetRelative(3))) { - sc.SetState(SCE_REBOL_BINARY); - } else if (IsAWordStart(sc.ch, sc.chNext)) { - sc.SetState(SCE_REBOL_IDENTIFIER); - } else if (IsADigit(sc.ch) || sc.ch == '+' || sc.ch == '-' || /*Decimal*/ sc.ch == '.' || sc.ch == ',') { - dotCount = 0; - sc.SetState(SCE_REBOL_NUMBER); - } else if (sc.ch == '\"') { - sc.SetState(SCE_REBOL_QUOTEDSTRING); - } else if (sc.ch == '{') { - sc.SetState(blockComment ? SCE_REBOL_COMMENTBLOCK : SCE_REBOL_BRACEDSTRING); - ++stringLevel; - } else if (sc.ch == ';') { - sc.SetState(SCE_REBOL_COMMENTLINE); - } else if (sc.ch == '$') { - sc.SetState(SCE_REBOL_MONEY); - } else if (sc.ch == '%') { - sc.SetState(SCE_REBOL_FILE); - } else if (sc.ch == '<') { - sc.SetState(SCE_REBOL_TAG); - } else if (sc.ch == '#' && sc.chNext == '"') { - sc.SetState(SCE_REBOL_CHARACTER); - sc.Forward(); - } else if (sc.ch == '#' && sc.chNext != '"' && sc.chNext != '{' ) { - sc.SetState(SCE_REBOL_ISSUE); - } - } - } - sc.Complete(); -} - - -static void FoldRebolDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[], - Accessor &styler) { - unsigned int lengthDoc = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (style == SCE_REBOL_DEFAULT) { - if (ch == '[') { - levelCurrent++; - } else if (ch == ']') { - levelCurrent--; - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const rebolWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmREBOL(SCLEX_REBOL, ColouriseRebolDoc, "rebol", FoldRebolDoc, rebolWordListDesc); - diff --git a/src/LexRuby.cxx b/src/LexRuby.cxx deleted file mode 100644 index 8d6dc90b8..000000000 --- a/src/LexRuby.cxx +++ /dev/null @@ -1,1715 +0,0 @@ -// Scintilla source code edit control -/** @file LexRuby.cxx - ** Lexer for Ruby. - **/ -// Copyright 2001- by Clemens Wyss -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -//XXX Identical to Perl, put in common area -static inline bool isEOLChar(char ch) { - return (ch == '\r') || (ch == '\n'); -} - -#define isSafeASCII(ch) ((unsigned int)(ch) <= 127) -// This one's redundant, but makes for more readable code -#define isHighBitChar(ch) ((unsigned int)(ch) > 127) - -static inline bool isSafeAlpha(char ch) { - return (isSafeASCII(ch) && isalpha(ch)) || ch == '_'; -} - -static inline bool isSafeAlnum(char ch) { - return (isSafeASCII(ch) && isalnum(ch)) || ch == '_'; -} - -static inline bool isSafeAlnumOrHigh(char ch) { - return isHighBitChar(ch) || isalnum(ch) || ch == '_'; -} - -static inline bool isSafeDigit(char ch) { - return isSafeASCII(ch) && isdigit(ch); -} - -static inline bool isSafeWordcharOrHigh(char ch) { - // Error: scintilla's KeyWords.h includes '.' as a word-char - // we want to separate things that can take methods from the - // methods. - return isHighBitChar(ch) || isalnum(ch) || ch == '_'; -} - -static bool inline iswhitespace(char ch) { - return ch == ' ' || ch == '\t'; -} - -#define MAX_KEYWORD_LENGTH 200 - -#define STYLE_MASK 63 -#define actual_style(style) (style & STYLE_MASK) - -static bool followsDot(unsigned int pos, Accessor &styler) { - styler.Flush(); - for (; pos >= 1; --pos) { - int style = actual_style(styler.StyleAt(pos)); - char ch; - switch (style) { - case SCE_RB_DEFAULT: - ch = styler[pos]; - if (ch == ' ' || ch == '\t') { - //continue - } else { - return false; - } - break; - - case SCE_RB_OPERATOR: - return styler[pos] == '.'; - - default: - return false; - } - } - return false; -} - -// Forward declarations -static bool keywordIsAmbiguous(const char *prevWord); -static bool keywordDoStartsLoop(int pos, - Accessor &styler); -static bool keywordIsModifier(const char *word, - int pos, - Accessor &styler); - -static int ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) { - char s[MAX_KEYWORD_LENGTH]; - unsigned int i, j; - unsigned int lim = end - start + 1; // num chars to copy - if (lim >= MAX_KEYWORD_LENGTH) { - lim = MAX_KEYWORD_LENGTH - 1; - } - for (i = start, j = 0; j < lim; i++, j++) { - s[j] = styler[i]; - } - s[j] = '\0'; - int chAttr; - if (0 == strcmp(prevWord, "class")) - chAttr = SCE_RB_CLASSNAME; - else if (0 == strcmp(prevWord, "module")) - chAttr = SCE_RB_MODULE_NAME; - else if (0 == strcmp(prevWord, "def")) - chAttr = SCE_RB_DEFNAME; - else if (keywords.InList(s) && !followsDot(start - 1, styler)) { - if (keywordIsAmbiguous(s) - && keywordIsModifier(s, start, styler)) { - - // Demoted keywords are colored as keywords, - // but do not affect changes in indentation. - // - // Consider the word 'if': - // 1. <> : normal - // 2. <> : demoted - // 3. <> : normal: start a new indent level - // 4. <> : color as identifer, since it follows '.' - - chAttr = SCE_RB_WORD_DEMOTED; - } else { - chAttr = SCE_RB_WORD; - } - } else - chAttr = SCE_RB_IDENTIFIER; - styler.ColourTo(end, chAttr); - if (chAttr == SCE_RB_WORD) { - strcpy(prevWord, s); - } else { - prevWord[0] = 0; - } - return chAttr; -} - - -//XXX Identical to Perl, put in common area -static bool isMatch(Accessor &styler, int lengthDoc, int pos, const char *val) { - if ((pos + static_cast(strlen(val))) >= lengthDoc) { - return false; - } - while (*val) { - if (*val != styler[pos++]) { - return false; - } - val++; - } - return true; -} - -// Do Ruby better -- find the end of the line, work back, -// and then check for leading white space - -// Precondition: the here-doc target can be indented -static bool lookingAtHereDocDelim(Accessor &styler, - int pos, - int lengthDoc, - const char *HereDocDelim) -{ - if (!isMatch(styler, lengthDoc, pos, HereDocDelim)) { - return false; - } - while (--pos > 0) { - char ch = styler[pos]; - if (isEOLChar(ch)) { - return true; - } else if (ch != ' ' && ch != '\t') { - return false; - } - } - return false; -} - -//XXX Identical to Perl, put in common area -static char opposite(char ch) { - if (ch == '(') - return ')'; - if (ch == '[') - return ']'; - if (ch == '{') - return '}'; - if (ch == '<') - return '>'; - return ch; -} - -// Null transitions when we see we've reached the end -// and need to relex the curr char. - -static void redo_char(int &i, char &ch, char &chNext, char &chNext2, - int &state) { - i--; - chNext2 = chNext; - chNext = ch; - state = SCE_RB_DEFAULT; -} - -static void advance_char(int &i, char &ch, char &chNext, char &chNext2) { - i++; - ch = chNext; - chNext = chNext2; -} - -// precondition: startPos points to one after the EOL char -static bool currLineContainsHereDelims(int& startPos, - Accessor &styler) { - if (startPos <= 1) - return false; - - int pos; - for (pos = startPos - 1; pos > 0; pos--) { - char ch = styler.SafeGetCharAt(pos); - if (isEOLChar(ch)) { - // Leave the pointers where they are -- there are no - // here doc delims on the current line, even if - // the EOL isn't default style - - return false; - } else { - styler.Flush(); - if (actual_style(styler.StyleAt(pos)) == SCE_RB_HERE_DELIM) { - break; - } - } - } - if (pos == 0) { - return false; - } - // Update the pointers so we don't have to re-analyze the string - startPos = pos; - return true; -} - -// This class is used by the enter and exit methods, so it needs -// to be hoisted out of the function. - -class QuoteCls { - public: - int Count; - char Up; - char Down; - QuoteCls() { - this->New(); - } - void New() { - Count = 0; - Up = '\0'; - Down = '\0'; - } - void Open(char u) { - Count++; - Up = u; - Down = opposite(Up); - } - QuoteCls(const QuoteCls& q) { - // copy constructor -- use this for copying in - Count = q.Count; - Up = q.Up; - Down = q.Down; - } - QuoteCls& operator=(const QuoteCls& q) { // assignment constructor - if (this != &q) { - Count = q.Count; - Up = q.Up; - Down = q.Down; - } - return *this; - } - -}; - - -static void enterInnerExpression(int *p_inner_string_types, - int *p_inner_expn_brace_counts, - QuoteCls *p_inner_quotes, - int& inner_string_count, - int& state, - int& brace_counts, - QuoteCls curr_quote - ) { - p_inner_string_types[inner_string_count] = state; - state = SCE_RB_DEFAULT; - p_inner_expn_brace_counts[inner_string_count] = brace_counts; - brace_counts = 0; - p_inner_quotes[inner_string_count] = curr_quote; - ++inner_string_count; -} - -static void exitInnerExpression(int *p_inner_string_types, - int *p_inner_expn_brace_counts, - QuoteCls *p_inner_quotes, - int& inner_string_count, - int& state, - int& brace_counts, - QuoteCls& curr_quote - ) { - --inner_string_count; - state = p_inner_string_types[inner_string_count]; - brace_counts = p_inner_expn_brace_counts[inner_string_count]; - curr_quote = p_inner_quotes[inner_string_count]; -} - -static bool isEmptyLine(int pos, - Accessor &styler) { - int spaceFlags = 0; - int lineCurrent = styler.GetLine(pos); - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); - return (indentCurrent & SC_FOLDLEVELWHITEFLAG) != 0; -} - -static bool RE_CanFollowKeyword(const char *keyword) { - if (!strcmp(keyword, "and") - || !strcmp(keyword, "begin") - || !strcmp(keyword, "break") - || !strcmp(keyword, "case") - || !strcmp(keyword, "do") - || !strcmp(keyword, "else") - || !strcmp(keyword, "elsif") - || !strcmp(keyword, "if") - || !strcmp(keyword, "next") - || !strcmp(keyword, "return") - || !strcmp(keyword, "when") - || !strcmp(keyword, "unless") - || !strcmp(keyword, "until") - || !strcmp(keyword, "not") - || !strcmp(keyword, "or")) { - return true; - } - return false; -} - -// Look at chars up to but not including endPos -// Don't look at styles in case we're looking forward - -static int skipWhitespace(int startPos, - int endPos, - Accessor &styler) { - for (int i = startPos; i < endPos; i++) { - if (!iswhitespace(styler[i])) { - return i; - } - } - return endPos; -} - -// This routine looks for false positives like -// undef foo, << -// There aren't too many. -// -// iPrev points to the start of << - -static bool sureThisIsHeredoc(int iPrev, - Accessor &styler, - char *prevWord) { - - // Not so fast, since Ruby's so dynamic. Check the context - // to make sure we're OK. - int prevStyle; - int lineStart = styler.GetLine(iPrev); - int lineStartPosn = styler.LineStart(lineStart); - styler.Flush(); - - // Find the first word after some whitespace - int firstWordPosn = skipWhitespace(lineStartPosn, iPrev, styler); - if (firstWordPosn >= iPrev) { - // Have something like {^ <<} - //XXX Look at the first previous non-comment non-white line - // to establish the context. Not too likely though. - return true; - } else { - switch (prevStyle = styler.StyleAt(firstWordPosn)) { - case SCE_RB_WORD: - case SCE_RB_WORD_DEMOTED: - case SCE_RB_IDENTIFIER: - break; - default: - return true; - } - } - int firstWordEndPosn = firstWordPosn; - char *dst = prevWord; - for (;;) { - if (firstWordEndPosn >= iPrev || - styler.StyleAt(firstWordEndPosn) != prevStyle) { - *dst = 0; - break; - } - *dst++ = styler[firstWordEndPosn]; - firstWordEndPosn += 1; - } - //XXX Write a style-aware thing to regex scintilla buffer objects - if (!strcmp(prevWord, "undef") - || !strcmp(prevWord, "def") - || !strcmp(prevWord, "alias")) { - // These keywords are what we were looking for - return false; - } - return true; -} - -// Routine that saves us from allocating a buffer for the here-doc target -// targetEndPos points one past the end of the current target -static bool haveTargetMatch(int currPos, - int lengthDoc, - int targetStartPos, - int targetEndPos, - Accessor &styler) { - if (lengthDoc - currPos < targetEndPos - targetStartPos) { - return false; - } - int i, j; - for (i = targetStartPos, j = currPos; - i < targetEndPos && j < lengthDoc; - i++, j++) { - if (styler[i] != styler[j]) { - return false; - } - } - return true; -} - -// We need a check because the form -// [identifier] <<[target] -// is ambiguous. The Ruby lexer/parser resolves it by -// looking to see if [identifier] names a variable or a -// function. If it's the first, it's the start of a here-doc. -// If it's a var, it's an operator. This lexer doesn't -// maintain a symbol table, so it looks ahead to see what's -// going on, in cases where we have -// ^[white-space]*[identifier([.|::]identifier)*][white-space]*<<[target] -// -// If there's no occurrence of [target] on a line, assume we don't. - -// return true == yes, we have no heredocs - -static bool sureThisIsNotHeredoc(int lt2StartPos, - Accessor &styler) { - int prevStyle; - // Use full document, not just part we're styling - int lengthDoc = styler.Length(); - int lineStart = styler.GetLine(lt2StartPos); - int lineStartPosn = styler.LineStart(lineStart); - styler.Flush(); - const bool definitely_not_a_here_doc = true; - const bool looks_like_a_here_doc = false; - - // Find the first word after some whitespace - int firstWordPosn = skipWhitespace(lineStartPosn, lt2StartPos, styler); - if (firstWordPosn >= lt2StartPos) { - return definitely_not_a_here_doc; - } - prevStyle = styler.StyleAt(firstWordPosn); - // If we have '<<' following a keyword, it's not a heredoc - if (prevStyle != SCE_RB_IDENTIFIER) { - return definitely_not_a_here_doc; - } - int newStyle = prevStyle; - // Some compilers incorrectly warn about uninit newStyle - for (firstWordPosn += 1; firstWordPosn <= lt2StartPos; firstWordPosn += 1) { - // Inner loop looks at the name - for (; firstWordPosn <= lt2StartPos; firstWordPosn += 1) { - newStyle = styler.StyleAt(firstWordPosn); - if (newStyle != prevStyle) { - break; - } - } - // Do we have '::' or '.'? - if (firstWordPosn < lt2StartPos && newStyle == SCE_RB_OPERATOR) { - char ch = styler[firstWordPosn]; - if (ch == '.') { - // yes - } else if (ch == ':') { - if (styler.StyleAt(++firstWordPosn) != SCE_RB_OPERATOR) { - return definitely_not_a_here_doc; - } else if (styler[firstWordPosn] != ':') { - return definitely_not_a_here_doc; - } - } else { - break; - } - } else { - break; - } - } - // Skip next batch of white-space - firstWordPosn = skipWhitespace(firstWordPosn, lt2StartPos, styler); - if (firstWordPosn != lt2StartPos) { - // Have [[^ws[identifier]ws[*something_else*]ws<< - return definitely_not_a_here_doc; - } - // OK, now 'j' will point to the current spot moving ahead - int j = firstWordPosn + 1; - if (styler.StyleAt(j) != SCE_RB_OPERATOR || styler[j] != '<') { - // This shouldn't happen - return definitely_not_a_here_doc; - } - int nextLineStartPosn = styler.LineStart(lineStart + 1); - if (nextLineStartPosn >= lengthDoc) { - return definitely_not_a_here_doc; - } - j = skipWhitespace(j + 1, nextLineStartPosn, styler); - if (j >= lengthDoc) { - return definitely_not_a_here_doc; - } - bool allow_indent; - int target_start, target_end; - // From this point on no more styling, since we're looking ahead - if (styler[j] == '-') { - allow_indent = true; - j++; - } else { - allow_indent = false; - } - - // Allow for quoted targets. - char target_quote = 0; - switch (styler[j]) { - case '\'': - case '"': - case '`': - target_quote = styler[j]; - j += 1; - } - - if (isSafeAlnum(styler[j])) { - // Init target_end because some compilers think it won't - // be initialized by the time it's used - target_start = target_end = j; - j++; - } else { - return definitely_not_a_here_doc; - } - for (; j < lengthDoc; j++) { - if (!isSafeAlnum(styler[j])) { - if (target_quote && styler[j] != target_quote) { - // unquoted end - return definitely_not_a_here_doc; - } - - // And for now make sure that it's a newline - // don't handle arbitrary expressions yet - - target_end = j; - if (target_quote) { - // Now we can move to the character after the string delimiter. - j += 1; - } - j = skipWhitespace(j, lengthDoc, styler); - if (j >= lengthDoc) { - return definitely_not_a_here_doc; - } else { - char ch = styler[j]; - if (ch == '#' || isEOLChar(ch)) { - // This is OK, so break and continue; - break; - } else { - return definitely_not_a_here_doc; - } - } - } - } - - // Just look at the start of each line - int last_line = styler.GetLine(lengthDoc - 1); - // But don't go too far - if (last_line > lineStart + 50) { - last_line = lineStart + 50; - } - for (int line_num = lineStart + 1; line_num <= last_line; line_num++) { - if (allow_indent) { - j = skipWhitespace(styler.LineStart(line_num), lengthDoc, styler); - } else { - j = styler.LineStart(line_num); - } - // target_end is one past the end - if (haveTargetMatch(j, lengthDoc, target_start, target_end, styler)) { - // We got it - return looks_like_a_here_doc; - } - } - return definitely_not_a_here_doc; -} - -//todo: if we aren't looking at a stdio character, -// move to the start of the first line that is not in a -// multi-line construct - -static void synchronizeDocStart(unsigned int& startPos, - int &length, - int &initStyle, - Accessor &styler, - bool skipWhiteSpace=false) { - - styler.Flush(); - int style = actual_style(styler.StyleAt(startPos)); - switch (style) { - case SCE_RB_STDIN: - case SCE_RB_STDOUT: - case SCE_RB_STDERR: - // Don't do anything else with these. - return; - } - - int pos = startPos; - // Quick way to characterize each line - int lineStart; - for (lineStart = styler.GetLine(pos); lineStart > 0; lineStart--) { - // Now look at the style before the previous line's EOL - pos = styler.LineStart(lineStart) - 1; - if (pos <= 10) { - lineStart = 0; - break; - } - char ch = styler.SafeGetCharAt(pos); - char chPrev = styler.SafeGetCharAt(pos - 1); - if (ch == '\n' && chPrev == '\r') { - pos--; - } - if (styler.SafeGetCharAt(pos - 1) == '\\') { - // Continuation line -- keep going - } else if (actual_style(styler.StyleAt(pos)) != SCE_RB_DEFAULT) { - // Part of multi-line construct -- keep going - } else if (currLineContainsHereDelims(pos, styler)) { - // Keep going, with pos and length now pointing - // at the end of the here-doc delimiter - } else if (skipWhiteSpace && isEmptyLine(pos, styler)) { - // Keep going - } else { - break; - } - } - pos = styler.LineStart(lineStart); - length += (startPos - pos); - startPos = pos; - initStyle = SCE_RB_DEFAULT; -} - -static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - // Lexer for Ruby often has to backtrack to start of current style to determine - // which characters are being used as quotes, how deeply nested is the - // start position and what the termination string is for here documents - - WordList &keywords = *keywordlists[0]; - - class HereDocCls { - public: - int State; - // States - // 0: '<<' encountered - // 1: collect the delimiter - // 1b: text between the end of the delimiter and the EOL - // 2: here doc text (lines after the delimiter) - char Quote; // the char after '<<' - bool Quoted; // true if Quote in ('\'','"','`') - int DelimiterLength; // strlen(Delimiter) - char Delimiter[256]; // the Delimiter, limit of 256: from Perl - bool CanBeIndented; - HereDocCls() { - State = 0; - DelimiterLength = 0; - Delimiter[0] = '\0'; - CanBeIndented = false; - } - }; - HereDocCls HereDoc; - - QuoteCls Quote; - - int numDots = 0; // For numbers -- - // Don't start lexing in the middle of a num - - synchronizeDocStart(startPos, length, initStyle, styler, // ref args - false); - - bool preferRE = true; - int state = initStyle; - int lengthDoc = startPos + length; - - char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero - prevWord[0] = '\0'; - if (length == 0) - return; - - char chPrev = styler.SafeGetCharAt(startPos - 1); - char chNext = styler.SafeGetCharAt(startPos); - bool is_real_number = true; // Differentiate between constants and ?-sequences. - // Ruby uses a different mask because bad indentation is marked by oring with 32 - styler.StartAt(startPos, 127); - styler.StartSegment(startPos); - - static int q_states[] = {SCE_RB_STRING_Q, - SCE_RB_STRING_QQ, - SCE_RB_STRING_QR, - SCE_RB_STRING_QW, - SCE_RB_STRING_QW, - SCE_RB_STRING_QX}; - static const char* q_chars = "qQrwWx"; - - // In most cases a value of 2 should be ample for the code in the - // Ruby library, and the code the user is likely to enter. - // For example, - // fu_output_message "mkdir #{options[:mode] ? ('-m %03o ' % options[:mode]) : ''}#{list.join ' '}" - // if options[:verbose] - // from fileutils.rb nests to a level of 2 - // If the user actually hits a 6th occurrence of '#{' in a double-quoted - // string (including regex'es, %Q, %, %w, and other strings - // that interpolate), it will stay as a string. The problem with this - // is that quotes might flip, a 7th '#{' will look like a comment, - // and code-folding might be wrong. - - // If anyone runs into this problem, I recommend raising this - // value slightly higher to replacing the fixed array with a linked - // list. Keep in mind this code will be called everytime the lexer - // is invoked. - -#define INNER_STRINGS_MAX_COUNT 5 - // These vars track our instances of "...#{,,,%Q<..#{,,,}...>,,,}..." - int inner_string_types[INNER_STRINGS_MAX_COUNT]; - // Track # braces when we push a new #{ thing - int inner_expn_brace_counts[INNER_STRINGS_MAX_COUNT]; - QuoteCls inner_quotes[INNER_STRINGS_MAX_COUNT]; - int inner_string_count = 0; - int brace_counts = 0; // Number of #{ ... } things within an expression - - int i; - for (i = 0; i < INNER_STRINGS_MAX_COUNT; i++) { - inner_string_types[i] = 0; - inner_expn_brace_counts[i] = 0; - } - for (i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - char chNext2 = styler.SafeGetCharAt(i + 2); - - if (styler.IsLeadByte(ch)) { - chNext = chNext2; - chPrev = ' '; - i += 1; - continue; - } - - // skip on DOS/Windows - //No, don't, because some things will get tagged on, - // so we won't recognize keywords, for example -#if 0 - if (ch == '\r' && chNext == '\n') { - continue; - } -#endif - - if (HereDoc.State == 1 && isEOLChar(ch)) { - // Begin of here-doc (the line after the here-doc delimiter): - HereDoc.State = 2; - styler.ColourTo(i-1, state); - // Don't check for a missing quote, just jump into - // the here-doc state - state = SCE_RB_HERE_Q; - } - - // Regular transitions - if (state == SCE_RB_DEFAULT) { - if (isSafeDigit(ch)) { - styler.ColourTo(i - 1, state); - state = SCE_RB_NUMBER; - is_real_number = true; - numDots = 0; - } else if (isHighBitChar(ch) || iswordstart(ch)) { - styler.ColourTo(i - 1, state); - state = SCE_RB_WORD; - } else if (ch == '#') { - styler.ColourTo(i - 1, state); - state = SCE_RB_COMMENTLINE; - } else if (ch == '=') { - // =begin indicates the start of a comment (doc) block - if (i == 0 || (isEOLChar(chPrev) - && chNext == 'b' - && styler.SafeGetCharAt(i + 2) == 'e' - && styler.SafeGetCharAt(i + 3) == 'g' - && styler.SafeGetCharAt(i + 4) == 'i' - && styler.SafeGetCharAt(i + 5) == 'n' - && !isSafeWordcharOrHigh(styler.SafeGetCharAt(i + 6)))) { - styler.ColourTo(i - 1, state); - state = SCE_RB_POD; - } else { - styler.ColourTo(i - 1, state); - styler.ColourTo(i, SCE_RB_OPERATOR); - preferRE = true; - } - } else if (ch == '"') { - styler.ColourTo(i - 1, state); - state = SCE_RB_STRING; - Quote.New(); - Quote.Open(ch); - } else if (ch == '\'') { - styler.ColourTo(i - 1, state); - state = SCE_RB_CHARACTER; - Quote.New(); - Quote.Open(ch); - } else if (ch == '`') { - styler.ColourTo(i - 1, state); - state = SCE_RB_BACKTICKS; - Quote.New(); - Quote.Open(ch); - } else if (ch == '@') { - // Instance or class var - styler.ColourTo(i - 1, state); - if (chNext == '@') { - state = SCE_RB_CLASS_VAR; - advance_char(i, ch, chNext, chNext2); // pass by ref - } else { - state = SCE_RB_INSTANCE_VAR; - } - } else if (ch == '$') { - // Check for a builtin global - styler.ColourTo(i - 1, state); - // Recognize it bit by bit - state = SCE_RB_GLOBAL; - } else if (ch == '/' && preferRE) { - // Ambigous operator - styler.ColourTo(i - 1, state); - state = SCE_RB_REGEX; - Quote.New(); - Quote.Open(ch); - } else if (ch == '<' && chNext == '<' && chNext2 != '=') { - - // Recognise the '<<' symbol - either a here document or a binary op - styler.ColourTo(i - 1, state); - i++; - chNext = chNext2; - styler.ColourTo(i, SCE_RB_OPERATOR); - - if (! (strchr("\"\'`_-", chNext2) || isSafeAlpha(chNext2))) { - // It's definitely not a here-doc, - // based on Ruby's lexer/parser in the - // heredoc_identifier routine. - // Nothing else to do. - } else if (preferRE) { - if (sureThisIsHeredoc(i - 1, styler, prevWord)) { - state = SCE_RB_HERE_DELIM; - HereDoc.State = 0; - } - // else leave it in default state - } else { - if (sureThisIsNotHeredoc(i - 1, styler)) { - // leave state as default - // We don't have all the heuristics Perl has for indications - // of a here-doc, because '<<' is overloadable and used - // for so many other classes. - } else { - state = SCE_RB_HERE_DELIM; - HereDoc.State = 0; - } - } - preferRE = (state != SCE_RB_HERE_DELIM); - } else if (ch == ':') { - styler.ColourTo(i - 1, state); - if (chNext == ':') { - // Mark "::" as an operator, not symbol start - styler.ColourTo(i + 1, SCE_RB_OPERATOR); - advance_char(i, ch, chNext, chNext2); // pass by ref - state = SCE_RB_DEFAULT; - preferRE = false; - } else if (isSafeWordcharOrHigh(chNext)) { - state = SCE_RB_SYMBOL; - } else if (strchr("[*!~+-*/%=<>&^|", chNext)) { - // Do the operator analysis in-line, looking ahead - // Based on the table in pickaxe 2nd ed., page 339 - bool doColoring = true; - switch (chNext) { - case '[': - if (chNext2 == ']' ) { - char ch_tmp = styler.SafeGetCharAt(i + 3); - if (ch_tmp == '=') { - i += 3; - ch = ch_tmp; - chNext = styler.SafeGetCharAt(i + 1); - } else { - i += 2; - ch = chNext2; - chNext = ch_tmp; - } - } else { - doColoring = false; - } - break; - - case '*': - if (chNext2 == '*') { - i += 2; - ch = chNext2; - chNext = styler.SafeGetCharAt(i + 1); - } else { - advance_char(i, ch, chNext, chNext2); - } - break; - - case '!': - if (chNext2 == '=' || chNext2 == '~') { - i += 2; - ch = chNext2; - chNext = styler.SafeGetCharAt(i + 1); - } else { - advance_char(i, ch, chNext, chNext2); - } - break; - - case '<': - if (chNext2 == '<') { - i += 2; - ch = chNext2; - chNext = styler.SafeGetCharAt(i + 1); - } else if (chNext2 == '=') { - char ch_tmp = styler.SafeGetCharAt(i + 3); - if (ch_tmp == '>') { // <=> operator - i += 3; - ch = ch_tmp; - chNext = styler.SafeGetCharAt(i + 1); - } else { - i += 2; - ch = chNext2; - chNext = ch_tmp; - } - } else { - advance_char(i, ch, chNext, chNext2); - } - break; - - default: - // Simple one-character operators - advance_char(i, ch, chNext, chNext2); - break; - } - if (doColoring) { - styler.ColourTo(i, SCE_RB_SYMBOL); - state = SCE_RB_DEFAULT; - } - } else if (!preferRE) { - // Don't color symbol strings (yet) - // Just color the ":" and color rest as string - styler.ColourTo(i, SCE_RB_SYMBOL); - state = SCE_RB_DEFAULT; - } else { - styler.ColourTo(i, SCE_RB_OPERATOR); - state = SCE_RB_DEFAULT; - preferRE = true; - } - } else if (ch == '%') { - styler.ColourTo(i - 1, state); - bool have_string = false; - if (strchr(q_chars, chNext) && !isSafeWordcharOrHigh(chNext2)) { - Quote.New(); - const char *hit = strchr(q_chars, chNext); - if (hit != NULL) { - state = q_states[hit - q_chars]; - Quote.Open(chNext2); - i += 2; - ch = chNext2; - chNext = styler.SafeGetCharAt(i + 1); - have_string = true; - } - } else if (preferRE && !isSafeWordcharOrHigh(chNext)) { - // Ruby doesn't allow high bit chars here, - // but the editor host might - state = SCE_RB_STRING_QQ; - Quote.Open(chNext); - advance_char(i, ch, chNext, chNext2); // pass by ref - have_string = true; - } - if (!have_string) { - styler.ColourTo(i, SCE_RB_OPERATOR); - // stay in default - preferRE = true; - } - } else if (ch == '?') { - styler.ColourTo(i - 1, state); - if (iswhitespace(chNext) || chNext == '\n' || chNext == '\r') { - styler.ColourTo(i, SCE_RB_OPERATOR); - } else { - // It's the start of a character code escape sequence - // Color it as a number. - state = SCE_RB_NUMBER; - is_real_number = false; - } - } else if (isoperator(ch) || ch == '.') { - styler.ColourTo(i - 1, state); - styler.ColourTo(i, SCE_RB_OPERATOR); - // If we're ending an expression or block, - // assume it ends an object, and the ambivalent - // constructs are binary operators - // - // So if we don't have one of these chars, - // we aren't ending an object exp'n, and ops - // like : << / are unary operators. - - if (ch == '{') { - ++brace_counts; - preferRE = true; - } else if (ch == '}' && --brace_counts < 0 - && inner_string_count > 0) { - styler.ColourTo(i, SCE_RB_OPERATOR); - exitInnerExpression(inner_string_types, - inner_expn_brace_counts, - inner_quotes, - inner_string_count, - state, brace_counts, Quote); - } else { - preferRE = (strchr(")}].", ch) == NULL); - } - // Stay in default state - } else if (isEOLChar(ch)) { - // Make sure it's a true line-end, with no backslash - if ((ch == '\r' || (ch == '\n' && chPrev != '\r')) - && chPrev != '\\') { - // Assume we've hit the end of the statement. - preferRE = true; - } - } - } else if (state == SCE_RB_WORD) { - if (ch == '.' || !isSafeWordcharOrHigh(ch)) { - // Words include x? in all contexts, - // and = after either 'def' or a dot - // Move along until a complete word is on our left - - // Default accessor treats '.' as word-chars, - // but we don't for now. - - if (ch == '=' - && isSafeWordcharOrHigh(chPrev) - && (chNext == '(' - || strchr(" \t\n\r", chNext) != NULL) - && (!strcmp(prevWord, "def") - || followsDot(styler.GetStartSegment(), styler))) { - // = is a name only when being def'd -- Get it the next time - // This means that = is always lexed as - // , (op, =), - } else if ((ch == '?' || ch == '!') - && isSafeWordcharOrHigh(chPrev) - && !isSafeWordcharOrHigh(chNext)) { - // ? is a name -- Get it the next time - // But ? is always lexed as - // , (op, ?), - // Same with ! to indicate a method that - // modifies its target - } else if (isEOLChar(ch) - && isMatch(styler, lengthDoc, i - 7, "__END__")) { - styler.ColourTo(i, SCE_RB_DATASECTION); - state = SCE_RB_DATASECTION; - // No need to handle this state -- we'll just move to the end - preferRE = false; - } else { - int wordStartPos = styler.GetStartSegment(); - int word_style = ClassifyWordRb(wordStartPos, i - 1, keywords, styler, prevWord); - switch (word_style) { - case SCE_RB_WORD: - preferRE = RE_CanFollowKeyword(prevWord); - break; - - case SCE_RB_WORD_DEMOTED: - preferRE = true; - break; - - case SCE_RB_IDENTIFIER: - if (isMatch(styler, lengthDoc, wordStartPos, "print")) { - preferRE = true; - } else if (isEOLChar(ch)) { - preferRE = true; - } else { - preferRE = false; - } - break; - default: - preferRE = false; - } - if (ch == '.') { - // We might be redefining an operator-method - preferRE = false; - } - // And if it's the first - redo_char(i, ch, chNext, chNext2, state); // pass by ref - } - } - } else if (state == SCE_RB_NUMBER) { - if (!is_real_number) { - if (ch != '\\') { - styler.ColourTo(i, state); - state = SCE_RB_DEFAULT; - preferRE = false; - } else if (strchr("\\ntrfvaebs", chNext)) { - // Terminal escape sequence -- handle it next time - // Nothing more to do this time through the loop - } else if (chNext == 'C' || chNext == 'M') { - if (chNext2 != '-') { - // \C or \M ends the sequence -- handle it next time - } else { - // Move from abc?\C-x - // ^ - // to - // ^ - i += 2; - ch = chNext2; - chNext = styler.SafeGetCharAt(i + 1); - } - } else if (chNext == 'c') { - // Stay here, \c is a combining sequence - advance_char(i, ch, chNext, chNext2); // pass by ref - } else { - // ?\x, including ?\\ is final. - styler.ColourTo(i + 1, state); - state = SCE_RB_DEFAULT; - preferRE = false; - advance_char(i, ch, chNext, chNext2); - } - } else if (isSafeAlnumOrHigh(ch) || ch == '_') { - // Keep going - } else if (ch == '.' && ++numDots == 1) { - // Keep going - } else { - styler.ColourTo(i - 1, state); - redo_char(i, ch, chNext, chNext2, state); // pass by ref - preferRE = false; - } - } else if (state == SCE_RB_COMMENTLINE) { - if (isEOLChar(ch)) { - styler.ColourTo(i - 1, state); - state = SCE_RB_DEFAULT; - // Use whatever setting we had going into the comment - } - } else if (state == SCE_RB_HERE_DELIM) { - // See the comment for SCE_RB_HERE_DELIM in LexPerl.cxx - // Slightly different: if we find an immediate '-', - // the target can appear indented. - - if (HereDoc.State == 0) { // '<<' encountered - HereDoc.State = 1; - HereDoc.DelimiterLength = 0; - if (ch == '-') { - HereDoc.CanBeIndented = true; - advance_char(i, ch, chNext, chNext2); // pass by ref - } else { - HereDoc.CanBeIndented = false; - } - if (isEOLChar(ch)) { - // Bail out of doing a here doc if there's no target - state = SCE_RB_DEFAULT; - preferRE = false; - } else { - HereDoc.Quote = ch; - - if (ch == '\'' || ch == '"' || ch == '`') { - HereDoc.Quoted = true; - HereDoc.Delimiter[0] = '\0'; - } else { - HereDoc.Quoted = false; - HereDoc.Delimiter[0] = ch; - HereDoc.Delimiter[1] = '\0'; - HereDoc.DelimiterLength = 1; - } - } - } else if (HereDoc.State == 1) { // collect the delimiter - if (isEOLChar(ch)) { - // End the quote now, and go back for more - styler.ColourTo(i - 1, state); - state = SCE_RB_DEFAULT; - i--; - chNext = ch; - chNext2 = chNext; - preferRE = false; - } else if (HereDoc.Quoted) { - if (ch == HereDoc.Quote) { // closing quote => end of delimiter - styler.ColourTo(i, state); - state = SCE_RB_DEFAULT; - preferRE = false; - } else { - if (ch == '\\' && !isEOLChar(chNext)) { - advance_char(i, ch, chNext, chNext2); - } - HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch; - HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; - } - } else { // an unquoted here-doc delimiter - if (isSafeAlnumOrHigh(ch) || ch == '_') { - HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch; - HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; - } else { - styler.ColourTo(i - 1, state); - redo_char(i, ch, chNext, chNext2, state); - preferRE = false; - } - } - if (HereDoc.DelimiterLength >= static_cast(sizeof(HereDoc.Delimiter)) - 1) { - styler.ColourTo(i - 1, state); - state = SCE_RB_ERROR; - preferRE = false; - } - } - } else if (state == SCE_RB_HERE_Q) { - // Not needed: HereDoc.State == 2 - // Indentable here docs: look backwards - // Non-indentable: look forwards, like in Perl - // - // Why: so we can quickly resolve things like <<-" abc" - - if (!HereDoc.CanBeIndented) { - if (isEOLChar(chPrev) - && isMatch(styler, lengthDoc, i, HereDoc.Delimiter)) { - styler.ColourTo(i - 1, state); - i += HereDoc.DelimiterLength - 1; - chNext = styler.SafeGetCharAt(i + 1); - if (isEOLChar(chNext)) { - styler.ColourTo(i, SCE_RB_HERE_DELIM); - state = SCE_RB_DEFAULT; - HereDoc.State = 0; - preferRE = false; - } - // Otherwise we skipped through the here doc faster. - } - } else if (isEOLChar(chNext) - && lookingAtHereDocDelim(styler, - i - HereDoc.DelimiterLength + 1, - lengthDoc, - HereDoc.Delimiter)) { - styler.ColourTo(i - 1 - HereDoc.DelimiterLength, state); - styler.ColourTo(i, SCE_RB_HERE_DELIM); - state = SCE_RB_DEFAULT; - preferRE = false; - HereDoc.State = 0; - } - } else if (state == SCE_RB_CLASS_VAR - || state == SCE_RB_INSTANCE_VAR - || state == SCE_RB_SYMBOL) { - if (!isSafeWordcharOrHigh(ch)) { - styler.ColourTo(i - 1, state); - redo_char(i, ch, chNext, chNext2, state); // pass by ref - preferRE = false; - } - } else if (state == SCE_RB_GLOBAL) { - if (!isSafeWordcharOrHigh(ch)) { - // handle special globals here as well - if (chPrev == '$') { - if (ch == '-') { - // Include the next char, like $-a - advance_char(i, ch, chNext, chNext2); - } - styler.ColourTo(i, state); - state = SCE_RB_DEFAULT; - } else { - styler.ColourTo(i - 1, state); - redo_char(i, ch, chNext, chNext2, state); // pass by ref - } - preferRE = false; - } - } else if (state == SCE_RB_POD) { - // PODs end with ^=end\s, -- any whitespace can follow =end - if (strchr(" \t\n\r", ch) != NULL - && i > 5 - && isEOLChar(styler[i - 5]) - && isMatch(styler, lengthDoc, i - 4, "=end")) { - styler.ColourTo(i - 1, state); - state = SCE_RB_DEFAULT; - preferRE = false; - } - } else if (state == SCE_RB_REGEX || state == SCE_RB_STRING_QR) { - if (ch == '\\' && Quote.Up != '\\') { - // Skip one - advance_char(i, ch, chNext, chNext2); - } else if (ch == Quote.Down) { - Quote.Count--; - if (Quote.Count == 0) { - // Include the options - while (isSafeAlpha(chNext)) { - i++; - ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - } - styler.ColourTo(i, state); - state = SCE_RB_DEFAULT; - preferRE = false; - } - } else if (ch == Quote.Up) { - // Only if close quoter != open quoter - Quote.Count++; - - } else if (ch == '#' ) { - if (chNext == '{' - && inner_string_count < INNER_STRINGS_MAX_COUNT) { - // process #{ ... } - styler.ColourTo(i - 1, state); - styler.ColourTo(i + 1, SCE_RB_OPERATOR); - enterInnerExpression(inner_string_types, - inner_expn_brace_counts, - inner_quotes, - inner_string_count, - state, - brace_counts, - Quote); - preferRE = true; - // Skip one - advance_char(i, ch, chNext, chNext2); - } else { - //todo: distinguish comments from pound chars - // for now, handle as comment - styler.ColourTo(i - 1, state); - bool inEscape = false; - while (++i < lengthDoc) { - ch = styler.SafeGetCharAt(i); - if (ch == '\\') { - inEscape = true; - } else if (isEOLChar(ch)) { - // Comment inside a regex - styler.ColourTo(i - 1, SCE_RB_COMMENTLINE); - break; - } else if (inEscape) { - inEscape = false; // don't look at char - } else if (ch == Quote.Down) { - // Have the regular handler deal with this - // to get trailing modifiers. - i--; - ch = styler[i]; - break; - } - } - chNext = styler.SafeGetCharAt(i + 1); - chNext2 = styler.SafeGetCharAt(i + 2); - } - } - // Quotes of all kinds... - } else if (state == SCE_RB_STRING_Q || state == SCE_RB_STRING_QQ || - state == SCE_RB_STRING_QX || state == SCE_RB_STRING_QW || - state == SCE_RB_STRING || state == SCE_RB_CHARACTER || - state == SCE_RB_BACKTICKS) { - if (!Quote.Down && !isspacechar(ch)) { - Quote.Open(ch); - } else if (ch == '\\' && Quote.Up != '\\') { - //Riddle me this: Is it safe to skip *every* escaped char? - advance_char(i, ch, chNext, chNext2); - } else if (ch == Quote.Down) { - Quote.Count--; - if (Quote.Count == 0) { - styler.ColourTo(i, state); - state = SCE_RB_DEFAULT; - preferRE = false; - } - } else if (ch == Quote.Up) { - Quote.Count++; - } else if (ch == '#' && chNext == '{' - && inner_string_count < INNER_STRINGS_MAX_COUNT - && state != SCE_RB_CHARACTER - && state != SCE_RB_STRING_Q) { - // process #{ ... } - styler.ColourTo(i - 1, state); - styler.ColourTo(i + 1, SCE_RB_OPERATOR); - enterInnerExpression(inner_string_types, - inner_expn_brace_counts, - inner_quotes, - inner_string_count, - state, - brace_counts, - Quote); - preferRE = true; - // Skip one - advance_char(i, ch, chNext, chNext2); - } - } - - if (state == SCE_RB_ERROR) { - break; - } - chPrev = ch; - } - if (state == SCE_RB_WORD) { - // We've ended on a word, possibly at EOF, and need to - // classify it. - (void) ClassifyWordRb(styler.GetStartSegment(), lengthDoc - 1, keywords, styler, prevWord); - } else { - styler.ColourTo(lengthDoc - 1, state); - } -} - -// Helper functions for folding, disambiguation keywords -// Assert that there are no high-bit chars - -static void getPrevWord(int pos, - char *prevWord, - Accessor &styler, - int word_state) -{ - int i; - styler.Flush(); - for (i = pos - 1; i > 0; i--) { - if (actual_style(styler.StyleAt(i)) != word_state) { - i++; - break; - } - } - if (i < pos - MAX_KEYWORD_LENGTH) // overflow - i = pos - MAX_KEYWORD_LENGTH; - char *dst = prevWord; - for (; i <= pos; i++) { - *dst++ = styler[i]; - } - *dst = 0; -} - -static bool keywordIsAmbiguous(const char *prevWord) -{ - // Order from most likely used to least likely - // Lots of ways to do a loop in Ruby besides 'while/until' - if (!strcmp(prevWord, "if") - || !strcmp(prevWord, "do") - || !strcmp(prevWord, "while") - || !strcmp(prevWord, "unless") - || !strcmp(prevWord, "until")) { - return true; - } else { - return false; - } -} - -// Demote keywords in the following conditions: -// if, while, unless, until modify a statement -// do after a while or until, as a noise word (like then after if) - -static bool keywordIsModifier(const char *word, - int pos, - Accessor &styler) -{ - if (word[0] == 'd' && word[1] == 'o' && !word[2]) { - return keywordDoStartsLoop(pos, styler); - } - char ch; - int style = SCE_RB_DEFAULT; - int lineStart = styler.GetLine(pos); - int lineStartPosn = styler.LineStart(lineStart); - styler.Flush(); - while (--pos >= lineStartPosn) { - style = actual_style(styler.StyleAt(pos)); - if (style == SCE_RB_DEFAULT) { - if (iswhitespace(ch = styler[pos])) { - //continue - } else if (ch == '\r' || ch == '\n') { - // Scintilla's LineStart() and GetLine() routines aren't - // platform-independent, so if we have text prepared with - // a different system we can't rely on it. - return false; - } - } else { - break; - } - } - if (pos < lineStartPosn) { - return false; //XXX not quite right if the prev line is a continuation - } - // First things where the action is unambiguous - switch (style) { - case SCE_RB_DEFAULT: - case SCE_RB_COMMENTLINE: - case SCE_RB_POD: - case SCE_RB_CLASSNAME: - case SCE_RB_DEFNAME: - case SCE_RB_MODULE_NAME: - return false; - case SCE_RB_OPERATOR: - break; - case SCE_RB_WORD: - // Watch out for uses of 'else if' - //XXX: Make a list of other keywords where 'if' isn't a modifier - // and can appear legitimately - // Formulate this to avoid warnings from most compilers - if (strcmp(word, "if") == 0) { - char prevWord[MAX_KEYWORD_LENGTH + 1]; - getPrevWord(pos, prevWord, styler, SCE_RB_WORD); - return strcmp(prevWord, "else") != 0; - } - return true; - default: - return true; - } - // Assume that if the keyword follows an operator, - // usually it's a block assignment, like - // a << if x then y else z - - ch = styler[pos]; - switch (ch) { - case ')': - case ']': - case '}': - return true; - default: - return false; - } -} - -#define WHILE_BACKWARDS "elihw" -#define UNTIL_BACKWARDS "litnu" - -// Nothing fancy -- look to see if we follow a while/until somewhere -// on the current line - -static bool keywordDoStartsLoop(int pos, - Accessor &styler) -{ - char ch; - int style; - int lineStart = styler.GetLine(pos); - int lineStartPosn = styler.LineStart(lineStart); - styler.Flush(); - while (--pos >= lineStartPosn) { - style = actual_style(styler.StyleAt(pos)); - if (style == SCE_RB_DEFAULT) { - if ((ch = styler[pos]) == '\r' || ch == '\n') { - // Scintilla's LineStart() and GetLine() routines aren't - // platform-independent, so if we have text prepared with - // a different system we can't rely on it. - return false; - } - } else if (style == SCE_RB_WORD) { - // Check for while or until, but write the word in backwards - char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero - char *dst = prevWord; - int wordLen = 0; - int start_word; - for (start_word = pos; - start_word >= lineStartPosn && actual_style(styler.StyleAt(start_word)) == SCE_RB_WORD; - start_word--) { - if (++wordLen < MAX_KEYWORD_LENGTH) { - *dst++ = styler[start_word]; - } - } - *dst = 0; - // Did we see our keyword? - if (!strcmp(prevWord, WHILE_BACKWARDS) - || !strcmp(prevWord, UNTIL_BACKWARDS)) { - return true; - } - // We can move pos to the beginning of the keyword, and then - // accept another decrement, as we can never have two contiguous - // keywords: - // word1 word2 - // ^ - // <- move to start_word - // ^ - // <- loop decrement - // ^ # pointing to end of word1 is fine - pos = start_word; - } - } - return false; -} - -/* - * Folding Ruby - * - * The language is quite complex to analyze without a full parse. - * For example, this line shouldn't affect fold level: - * - * print "hello" if feeling_friendly? - * - * Neither should this: - * - * print "hello" \ - * if feeling_friendly? - * - * - * But this should: - * - * if feeling_friendly? #++ - * print "hello" \ - * print "goodbye" - * end #-- - * - * So we cheat, by actually looking at the existing indentation - * levels for each line, and just echoing it back. Like Python. - * Then if we get better at it, we'll take braces into consideration, - * which always affect folding levels. - - * How the keywords should work: - * No effect: - * __FILE__ __LINE__ BEGIN END alias and - * defined? false in nil not or self super then - * true undef - - * Always increment: - * begin class def do for module when { - * - * Always decrement: - * end } - * - * Increment if these start a statement - * if unless until while -- do nothing if they're modifiers - - * These end a block if there's no modifier, but don't bother - * break next redo retry return yield - * - * These temporarily de-indent, but re-indent - * case else elsif ensure rescue - * - * This means that the folder reflects indentation rather - * than setting it. The language-service updates indentation - * when users type return and finishes entering de-denters. - * - * Later offer to fold POD, here-docs, strings, and blocks of comments - */ - -static void FoldRbDoc(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) { - const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - - synchronizeDocStart(startPos, length, initStyle, styler, // ref args - false); - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = startPos == 0 ? 0 : (styler.LevelAt(lineCurrent) - & SC_FOLDLEVELNUMBERMASK - & ~SC_FOLDLEVELBASE); - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int stylePrev = startPos <= 1 ? SCE_RB_DEFAULT : styler.StyleAt(startPos - 1); - bool buffer_ends_with_eol = false; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (style == SCE_RB_COMMENTLINE) { - if (foldComment && stylePrev != SCE_RB_COMMENTLINE) { - if (chNext == '{') { - levelCurrent++; - } else if (chNext == '}' && levelCurrent > 0) { - levelCurrent--; - } - } - } else if (style == SCE_RB_OPERATOR) { - if (strchr("[{(", ch)) { - levelCurrent++; - } else if (strchr(")}]", ch)) { - // Don't decrement below 0 - if (levelCurrent > 0) - levelCurrent--; - } - } else if (style == SCE_RB_WORD && styleNext != SCE_RB_WORD) { - // Look at the keyword on the left and decide what to do - char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero - prevWord[0] = 0; - getPrevWord(i, prevWord, styler, SCE_RB_WORD); - if (!strcmp(prevWord, "end")) { - // Don't decrement below 0 - if (levelCurrent > 0) - levelCurrent--; - } else if ( !strcmp(prevWord, "if") - || !strcmp(prevWord, "def") - || !strcmp(prevWord, "class") - || !strcmp(prevWord, "module") - || !strcmp(prevWord, "begin") - || !strcmp(prevWord, "case") - || !strcmp(prevWord, "do") - || !strcmp(prevWord, "while") - || !strcmp(prevWord, "unless") - || !strcmp(prevWord, "until") - || !strcmp(prevWord, "for") - ) { - levelCurrent++; - } - } - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - styler.SetLevel(lineCurrent, lev|SC_FOLDLEVELBASE); - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - buffer_ends_with_eol = true; - } else if (!isspacechar(ch)) { - visibleChars++; - buffer_ends_with_eol = false; - } - stylePrev = style; - } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - if (!buffer_ends_with_eol) { - lineCurrent++; - int new_lev = levelCurrent; - if (visibleChars == 0 && foldCompact) - new_lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - new_lev |= SC_FOLDLEVELHEADERFLAG; - levelCurrent = new_lev; - } - styler.SetLevel(lineCurrent, levelCurrent|SC_FOLDLEVELBASE); -} - -static const char * const rubyWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmRuby(SCLEX_RUBY, ColouriseRbDoc, "ruby", FoldRbDoc, rubyWordListDesc); diff --git a/src/LexSML.cxx b/src/LexSML.cxx deleted file mode 100644 index a41b4c10d..000000000 --- a/src/LexSML.cxx +++ /dev/null @@ -1,221 +0,0 @@ -// Scintilla source code edit control -/** @file LexSML.cxx - ** Lexer for SML. - **/ -// Copyright 2009 by James Moffatt and Yuzhou Xin -// Modified from LexCaml.cxx by Robert Roessler Copyright 2005 -// The License.txt file describes the conditions under which this software may be distributed. - - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -inline int issml(int c) {return isalnum(c) || c == '_';} -inline int issmlf(int c) {return isalpha(c) || c == '_';} -inline int issmld(int c) {return isdigit(c) || c == '_';} - - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -void ColouriseSMLDoc( - unsigned int startPos, int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) -{ - StyleContext sc(startPos, length, initStyle, styler); - int nesting = 0; - if (sc.state < SCE_SML_STRING) - sc.state = SCE_SML_DEFAULT; - if (sc.state >= SCE_SML_COMMENT) - nesting = (sc.state & 0x0f) - SCE_SML_COMMENT; - - int chBase = 0, chToken = 0, chLit = 0; - WordList& keywords = *keywordlists[0]; - WordList& keywords2 = *keywordlists[1]; - WordList& keywords3 = *keywordlists[2]; - const int useMagic = styler.GetPropertyInt("lexer.caml.magic", 0); - - while (sc.More()) { - int state2 = -1; - int chColor = sc.currentPos - 1; - bool advance = true; - - switch (sc.state & 0x0f) { - case SCE_SML_DEFAULT: - chToken = sc.currentPos; - if (issmlf(sc.ch)) - state2 = SCE_SML_IDENTIFIER; - else if (sc.Match('`') && issmlf(sc.chNext)) - state2 = SCE_SML_TAGNAME; - else if (sc.Match('#')&&isdigit(sc.chNext)) - state2 = SCE_SML_LINENUM; - else if (sc.Match('#','\"')){ - state2 = SCE_SML_CHAR,chLit = 0; - sc.Forward(); - - } - else if (isdigit(sc.ch)) { - state2 = SCE_SML_NUMBER, chBase = 10; - if (sc.Match('0') && strchr("xX", sc.chNext)) - chBase = 16, sc.Forward();} - else if (sc.Match('\"')&&sc.chPrev!='#') - state2 = SCE_SML_STRING; - else if (sc.Match('(', '*')){ - state2 = SCE_SML_COMMENT, - sc.ch = ' ', - sc.Forward();} - else if (strchr("!~" - "=<>@^+-*/" - "()[];,:.#", sc.ch)) - state2 = SCE_SML_OPERATOR; - break; - - case SCE_SML_IDENTIFIER: - if (!(issml(sc.ch) || sc.Match('\''))) { - const int n = sc.currentPos - chToken; - if (n < 24) { - char t[24]; - for (int i = -n; i < 0; i++) - t[n + i] = static_cast(sc.GetRelative(i)); - t[n] = '\0'; - if ((n == 1 && sc.chPrev == '_') || keywords.InList(t)) - sc.ChangeState(SCE_SML_KEYWORD); - else if (keywords2.InList(t)) - sc.ChangeState(SCE_SML_KEYWORD2); - else if (keywords3.InList(t)) - sc.ChangeState(SCE_SML_KEYWORD3); - } - state2 = SCE_SML_DEFAULT, advance = false; - } - break; - - case SCE_SML_TAGNAME: - if (!(issml(sc.ch) || sc.Match('\''))) - state2 = SCE_SML_DEFAULT, advance = false; - break; - - case SCE_SML_LINENUM: - if (!isdigit(sc.ch)) - state2 = SCE_SML_DEFAULT, advance = false; - break; - - case SCE_SML_OPERATOR: { - const char* o = 0; - if (issml(sc.ch) || isspace(sc.ch) - || (o = strchr(")]};,\'\"`#", sc.ch),o) - || !strchr("!$%&*+-./:<=>?@^|~", sc.ch)) { - if (o && strchr(")]};,", sc.ch)) { - if ((sc.Match(')') && sc.chPrev == '(') - || (sc.Match(']') && sc.chPrev == '[')) - sc.ChangeState(SCE_SML_KEYWORD); - chColor++; - } else - advance = false; - state2 = SCE_SML_DEFAULT; - } - break; - } - - case SCE_SML_NUMBER: - if (issmld(sc.ch) || IsADigit(sc.ch, chBase)) - break; - if ((sc.Match('l') || sc.Match('L') || sc.Match('n')) - && (issmld(sc.chPrev) || IsADigit(sc.chPrev, chBase))) - break; - if (chBase == 10) { - if (sc.Match('.') && issmld(sc.chPrev)) - break; - if ((sc.Match('e') || sc.Match('E')) - && (issmld(sc.chPrev) || sc.chPrev == '.')) - break; - if ((sc.Match('+') || sc.Match('-')) - && (sc.chPrev == 'e' || sc.chPrev == 'E')) - break; - } - state2 = SCE_SML_DEFAULT, advance = false; - break; - - case SCE_SML_CHAR: - if (sc.Match('\\')) { - chLit = 1; - if (sc.chPrev == '\\') - sc.ch = ' '; - } else if ((sc.Match('\"') && sc.chPrev != '\\') || sc.atLineEnd) { - state2 = SCE_SML_DEFAULT; - chLit = 1; - if (sc.Match('\"')) - chColor++; - else - sc.ChangeState(SCE_SML_IDENTIFIER); - } else if (chLit < 1 && sc.currentPos - chToken >= 3) - sc.ChangeState(SCE_SML_IDENTIFIER), advance = false; - break; - - case SCE_SML_STRING: - if (sc.Match('\\') && sc.chPrev == '\\') - sc.ch = ' '; - else if (sc.Match('\"') && sc.chPrev != '\\') - state2 = SCE_SML_DEFAULT, chColor++; - break; - - case SCE_SML_COMMENT: - case SCE_SML_COMMENT1: - case SCE_SML_COMMENT2: - case SCE_SML_COMMENT3: - if (sc.Match('(', '*')) - state2 = sc.state + 1, chToken = sc.currentPos, - sc.ch = ' ', - sc.Forward(), nesting++; - else if (sc.Match(')') && sc.chPrev == '*') { - if (nesting) - state2 = (sc.state & 0x0f) - 1, chToken = 0, nesting--; - else - state2 = SCE_SML_DEFAULT; - chColor++; - } else if (useMagic && sc.currentPos - chToken == 4 - && sc.Match('c') && sc.chPrev == 'r' && sc.GetRelative(-2) == '@') - sc.state |= 0x10; - break; - } - - if (state2 >= 0) - styler.ColourTo(chColor, sc.state), sc.ChangeState(state2); - if (advance) - sc.Forward(); - } - - sc.Complete(); -} - -void FoldSMLDoc( - unsigned int, int, - int, - WordList *[], - Accessor &) -{ -} - -static const char * const SMLWordListDesc[] = { - "Keywords", - "Keywords2", - "Keywords3", - 0 -}; - -LexerModule lmSML(SCLEX_SML, ColouriseSMLDoc, "SML", FoldSMLDoc, SMLWordListDesc); - diff --git a/src/LexSQL.cxx b/src/LexSQL.cxx deleted file mode 100644 index 7a4335bd2..000000000 --- a/src/LexSQL.cxx +++ /dev/null @@ -1,357 +0,0 @@ -// Scintilla source code edit control -/** @file LexSQL.cxx - ** Lexer for SQL, including PL/SQL and SQL*Plus. - **/ -// Copyright 1998-2005 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static inline bool IsAWordStart(int ch) { - return (ch < 0x80) && (isalpha(ch) || ch == '_'); -} - -static inline bool IsADoxygenChar(int ch) { - return (islower(ch) || ch == '$' || ch == '@' || - ch == '\\' || ch == '&' || ch == '<' || - ch == '>' || ch == '#' || ch == '{' || - ch == '}' || ch == '[' || ch == ']'); -} - -static inline bool IsANumberChar(int ch) { - // Not exactly following number definition (several dots are seen as OK, etc.) - // but probably enough in most cases. - return (ch < 0x80) && - (isdigit(ch) || toupper(ch) == 'E' || - ch == '.' || ch == '-' || ch == '+'); -} - -static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords1 = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &kw_pldoc = *keywordlists[2]; - WordList &kw_sqlplus = *keywordlists[3]; - WordList &kw_user1 = *keywordlists[4]; - WordList &kw_user2 = *keywordlists[5]; - WordList &kw_user3 = *keywordlists[6]; - WordList &kw_user4 = *keywordlists[7]; - - StyleContext sc(startPos, length, initStyle, styler); - - // property sql.backslash.escapes - // Enables backslash as an escape character in SQL. - bool sqlBackslashEscapes = styler.GetPropertyInt("sql.backslash.escapes", 0) != 0; - - bool sqlBackticksIdentifier = styler.GetPropertyInt("lexer.sql.backticks.identifier", 0) != 0; - int styleBeforeDCKeyword = SCE_SQL_DEFAULT; - for (; sc.More(); sc.Forward()) { - // Determine if the current state should terminate. - switch (sc.state) { - case SCE_SQL_OPERATOR: - sc.SetState(SCE_SQL_DEFAULT); - break; - case SCE_SQL_NUMBER: - // We stop the number definition on non-numerical non-dot non-eE non-sign char - if (!IsANumberChar(sc.ch)) { - sc.SetState(SCE_SQL_DEFAULT); - } - break; - case SCE_SQL_IDENTIFIER: - if (!IsAWordChar(sc.ch)) { - int nextState = SCE_SQL_DEFAULT; - char s[1000]; - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords1.InList(s)) { - sc.ChangeState(SCE_SQL_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_SQL_WORD2); - } else if (kw_sqlplus.InListAbbreviated(s, '~')) { - sc.ChangeState(SCE_SQL_SQLPLUS); - if (strncmp(s, "rem", 3) == 0) { - nextState = SCE_SQL_SQLPLUS_COMMENT; - } else if (strncmp(s, "pro", 3) == 0) { - nextState = SCE_SQL_SQLPLUS_PROMPT; - } - } else if (kw_user1.InList(s)) { - sc.ChangeState(SCE_SQL_USER1); - } else if (kw_user2.InList(s)) { - sc.ChangeState(SCE_SQL_USER2); - } else if (kw_user3.InList(s)) { - sc.ChangeState(SCE_SQL_USER3); - } else if (kw_user4.InList(s)) { - sc.ChangeState(SCE_SQL_USER4); - } - sc.SetState(nextState); - } - break; - case SCE_SQL_QUOTEDIDENTIFIER: - if (sc.ch == 0x60) { - if (sc.chNext == 0x60) { - sc.Forward(); // Ignore it - } else { - sc.ForwardSetState(SCE_SQL_DEFAULT); - } - } - break; - case SCE_SQL_COMMENT: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_SQL_DEFAULT); - } - break; - case SCE_SQL_COMMENTDOC: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_SQL_DEFAULT); - } else if (sc.ch == '@' || sc.ch == '\\') { // Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_SQL_COMMENTDOC; - sc.SetState(SCE_SQL_COMMENTDOCKEYWORD); - } - } - break; - case SCE_SQL_COMMENTLINE: - case SCE_SQL_COMMENTLINEDOC: - case SCE_SQL_SQLPLUS_COMMENT: - case SCE_SQL_SQLPLUS_PROMPT: - if (sc.atLineStart) { - sc.SetState(SCE_SQL_DEFAULT); - } - break; - case SCE_SQL_COMMENTDOCKEYWORD: - if ((styleBeforeDCKeyword == SCE_SQL_COMMENTDOC) && sc.Match('*', '/')) { - sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR); - sc.Forward(); - sc.ForwardSetState(SCE_SQL_DEFAULT); - } else if (!IsADoxygenChar(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (!isspace(sc.ch) || !kw_pldoc.InList(s + 1)) { - sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR); - } - sc.SetState(styleBeforeDCKeyword); - } - break; - case SCE_SQL_CHARACTER: - if (sqlBackslashEscapes && sc.ch == '\\') { - sc.Forward(); - } else if (sc.ch == '\'') { - if (sc.chNext == '\"') { - sc.Forward(); - } else { - sc.ForwardSetState(SCE_SQL_DEFAULT); - } - } - break; - case SCE_SQL_STRING: - if (sc.ch == '\\') { - // Escape sequence - sc.Forward(); - } else if (sc.ch == '\"') { - if (sc.chNext == '\"') { - sc.Forward(); - } else { - sc.ForwardSetState(SCE_SQL_DEFAULT); - } - } - break; - } - - // Determine if a new state should be entered. - if (sc.state == SCE_SQL_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_SQL_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_SQL_IDENTIFIER); - } else if (sc.ch == 0x60 && sqlBackticksIdentifier) { - sc.SetState(SCE_SQL_QUOTEDIDENTIFIER); - } else if (sc.Match('/', '*')) { - if (sc.Match("/**") || sc.Match("/*!")) { // Support of Doxygen doc. style - sc.SetState(SCE_SQL_COMMENTDOC); - } else { - sc.SetState(SCE_SQL_COMMENT); - } - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match('-', '-')) { - // MySQL requires a space or control char after -- - // http://dev.mysql.com/doc/mysql/en/ansi-diff-comments.html - // Perhaps we should enforce that with proper property: -//~ } else if (sc.Match("-- ")) { - sc.SetState(SCE_SQL_COMMENTLINE); - } else if (sc.ch == '#') { - sc.SetState(SCE_SQL_COMMENTLINEDOC); - } else if (sc.ch == '\'') { - sc.SetState(SCE_SQL_CHARACTER); - } else if (sc.ch == '\"') { - sc.SetState(SCE_SQL_STRING); - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_SQL_OPERATOR); - } - } - } - sc.Complete(); -} - -static bool IsStreamCommentStyle(int style) { - return style == SCE_SQL_COMMENT || - style == SCE_SQL_COMMENTDOC || - style == SCE_SQL_COMMENTDOCKEYWORD || - style == SCE_SQL_COMMENTDOCKEYWORDERROR; -} - -// Store both the current line's fold level and the next lines in the -// level store to make it easy to pick up with each increment. -static void FoldSQLDoc(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldOnlyBegin = styler.GetPropertyInt("fold.sql.only.begin", 0) != 0; - - // property fold.sql.exists - // Enables "EXISTS" to end a fold as is started by "IF" in "DROP TABLE IF EXISTS". - bool foldSqlExists = styler.GetPropertyInt("fold.sql.exists", 1) != 0; - - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) { - levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16; - } - int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - bool endFound = false; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && IsStreamCommentStyle(style)) { - if (!IsStreamCommentStyle(stylePrev)) { - levelNext++; - } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelNext--; - } - } - if (foldComment && (style == SCE_SQL_COMMENTLINE)) { - // MySQL needs -- comments to be followed by space or control char - if ((ch == '-') && (chNext == '-')) { - char chNext2 = styler.SafeGetCharAt(i + 2); - char chNext3 = styler.SafeGetCharAt(i + 3); - if (chNext2 == '{' || chNext3 == '{') { - levelNext++; - } else if (chNext2 == '}' || chNext3 == '}') { - levelNext--; - } - } - } - if (style == SCE_SQL_OPERATOR) { - if (ch == '(') { - levelNext++; - } else if (ch == ')') { - levelNext--; - } - } - // If new keyword (cannot trigger on elseif or nullif, does less tests) - if (style == SCE_SQL_WORD && stylePrev != SCE_SQL_WORD) { - const int MAX_KW_LEN = 6; // Maximum length of folding keywords - char s[MAX_KW_LEN + 2]; - unsigned int j = 0; - for (; j < MAX_KW_LEN + 1; j++) { - if (!iswordchar(styler[i + j])) { - break; - } - s[j] = static_cast(tolower(styler[i + j])); - } - if (j == MAX_KW_LEN + 1) { - // Keyword too long, don't test it - s[0] = '\0'; - } else { - s[j] = '\0'; - } - if ((!foldOnlyBegin) && (strcmp(s, "if") == 0 || strcmp(s, "loop") == 0)) { - if (endFound) { - // ignore - endFound = false; - } else { - levelNext++; - } - } else if (strcmp(s, "begin") == 0) { - levelNext++; - } else if ((strcmp(s, "end") == 0) || -// // DROP TABLE IF EXISTS or CREATE TABLE IF NOT EXISTS - (foldSqlExists && (strcmp(s, "exists") == 0)) || -// // SQL Anywhere permits IF ... ELSE ... ENDIF -// // will only be active if "endif" appears in the -// // keyword list. - (strcmp(s, "endif") == 0)) { - endFound = true; - levelNext--; - if (levelNext < SC_FOLDLEVELBASE) { - levelNext = SC_FOLDLEVELBASE; - } - } - } - if (atEOL) { - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - visibleChars = 0; - endFound = false; - } - if (!isspacechar(ch)) { - visibleChars++; - } - } -} - -static const char * const sqlWordListDesc[] = { - "Keywords", - "Database Objects", - "PLDoc", - "SQL*Plus", - "User Keywords 1", - "User Keywords 2", - "User Keywords 3", - "User Keywords 4", - 0 -}; - -LexerModule lmSQL(SCLEX_SQL, ColouriseSQLDoc, "sql", FoldSQLDoc, sqlWordListDesc); diff --git a/src/LexScriptol.cxx b/src/LexScriptol.cxx deleted file mode 100644 index 76c38e6b6..000000000 --- a/src/LexScriptol.cxx +++ /dev/null @@ -1,408 +0,0 @@ -// Scintilla source code edit control -/** @file LexScriptol.cxx - ** Lexer for Scriptol. - **/ - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static void ClassifyWordSol(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) -{ - char s[100]; - bool wordIsNumber = isdigit(styler[start]) != 0; - for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) - { - s[i] = styler[start + i]; - s[i + 1] = '\0'; - } - char chAttr = SCE_SCRIPTOL_IDENTIFIER; - if (0 == strcmp(prevWord, "class")) chAttr = SCE_SCRIPTOL_CLASSNAME; - else if (wordIsNumber) chAttr = SCE_SCRIPTOL_NUMBER; - else if (keywords.InList(s)) chAttr = SCE_SCRIPTOL_KEYWORD; - else for (unsigned int i = 0; i < end - start + 1; i++) // test dotted idents - { - if (styler[start + i] == '.') - { - styler.ColourTo(start + i - 1, chAttr); - styler.ColourTo(start + i, SCE_SCRIPTOL_OPERATOR); - } - } - styler.ColourTo(end, chAttr); - strcpy(prevWord, s); -} - -static bool IsSolComment(Accessor &styler, int pos, int len) -{ - char c; - if(len > 0) - { - c = styler[pos]; - if(c == '`') return true; - if(len > 1) - { - if(c == '/') - { - c = styler[pos + 1]; - if(c == '/') return true; - if(c == '*') return true; - } - } - } - return false; -} - -static bool IsSolStringStart(char ch) -{ - if (ch == '\'' || ch == '"') return true; - return false; -} - -static bool IsSolWordStart(char ch) -{ - return (iswordchar(ch) && !IsSolStringStart(ch)); -} - - -static int GetSolStringState(Accessor &styler, int i, int *nextIndex) -{ - char ch = styler.SafeGetCharAt(i); - char chNext = styler.SafeGetCharAt(i + 1); - - if (ch != '\"' && ch != '\'') - { - *nextIndex = i + 1; - return SCE_SCRIPTOL_DEFAULT; - } - // ch is either single or double quotes in string - // code below seem non-sense but is here for future extensions - if (ch == chNext && ch == styler.SafeGetCharAt(i + 2)) - { - *nextIndex = i + 3; - if(ch == '\"') return SCE_SCRIPTOL_TRIPLE; - if(ch == '\'') return SCE_SCRIPTOL_TRIPLE; - return SCE_SCRIPTOL_STRING; - } - else - { - *nextIndex = i + 1; - if (ch == '"') return SCE_SCRIPTOL_STRING; - else return SCE_SCRIPTOL_STRING; - } -} - - -static void ColouriseSolDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) - { - - int lengthDoc = startPos + length; - char stringType = '\"'; - - if (startPos > 0) - { - int lineCurrent = styler.GetLine(startPos); - if (lineCurrent > 0) - { - startPos = styler.LineStart(lineCurrent-1); - if (startPos == 0) initStyle = SCE_SCRIPTOL_DEFAULT; - else initStyle = styler.StyleAt(startPos-1); - } - } - - styler.StartAt(startPos, 127); - - WordList &keywords = *keywordlists[0]; - - int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level"); - char prevWord[200]; - prevWord[0] = '\0'; - if (length == 0) return; - - int state = initStyle & 31; - - int nextIndex = 0; - char chPrev = ' '; - char chPrev2 = ' '; - char chNext = styler[startPos]; - styler.StartSegment(startPos); - bool atStartLine = true; - int spaceFlags = 0; - for (int i = startPos; i < lengthDoc; i++) - { - - if (atStartLine) - { - char chBad = static_cast(64); - char chGood = static_cast(0); - char chFlags = chGood; - - if (whingeLevel == 1) - { - chFlags = (spaceFlags & wsInconsistent) ? chBad : chGood; - } - else if (whingeLevel == 2) - { - chFlags = (spaceFlags & wsSpaceTab) ? chBad : chGood; - } - else if (whingeLevel == 3) - { - chFlags = (spaceFlags & wsSpace) ? chBad : chGood; - } - else if (whingeLevel == 4) - { - chFlags = (spaceFlags & wsTab) ? chBad : chGood; - } - styler.SetFlags(chFlags, static_cast(state)); - atStartLine = false; - } - - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) - { - if ((state == SCE_SCRIPTOL_DEFAULT) || - (state == SCE_SCRIPTOL_TRIPLE) || - (state == SCE_SCRIPTOL_COMMENTBLOCK)) - { - styler.ColourTo(i, state); - } - atStartLine = true; - } - - if (styler.IsLeadByte(ch)) - { - chNext = styler.SafeGetCharAt(i + 2); - chPrev = ' '; - chPrev2 = ' '; - i += 1; - continue; - } - - if (state == SCE_SCRIPTOL_STRINGEOL) - { - if (ch != '\r' && ch != '\n') - { - styler.ColourTo(i - 1, state); - state = SCE_SCRIPTOL_DEFAULT; - } - } - - if (state == SCE_SCRIPTOL_DEFAULT) - { - if (IsSolWordStart(ch)) - { - styler.ColourTo(i - 1, state); - state = SCE_SCRIPTOL_KEYWORD; - } - else if (ch == '`') - { - styler.ColourTo(i - 1, state); - state = SCE_SCRIPTOL_COMMENTLINE; - } - else if (ch == '/') - { - styler.ColourTo(i - 1, state); - if(chNext == '/') state = SCE_SCRIPTOL_CSTYLE; - if(chNext == '*') state = SCE_SCRIPTOL_COMMENTBLOCK; - } - - else if (IsSolStringStart(ch)) - { - styler.ColourTo(i - 1, state); - state = GetSolStringState(styler, i, &nextIndex); - if(state == SCE_SCRIPTOL_STRING) - { - stringType = ch; - } - if (nextIndex != i + 1) - { - i = nextIndex - 1; - ch = ' '; - chPrev = ' '; - chNext = styler.SafeGetCharAt(i + 1); - } - } - else if (isoperator(ch)) - { - styler.ColourTo(i - 1, state); - styler.ColourTo(i, SCE_SCRIPTOL_OPERATOR); - } - } - else if (state == SCE_SCRIPTOL_KEYWORD) - { - if (!iswordchar(ch)) - { - ClassifyWordSol(styler.GetStartSegment(), i - 1, keywords, styler, prevWord); - state = SCE_SCRIPTOL_DEFAULT; - if (ch == '`') - { - state = chNext == '`' ? SCE_SCRIPTOL_PERSISTENT : SCE_SCRIPTOL_COMMENTLINE; - } - else if (IsSolStringStart(ch)) - { - styler.ColourTo(i - 1, state); - state = GetSolStringState(styler, i, &nextIndex); - if (nextIndex != i + 1) - { - i = nextIndex - 1; - ch = ' '; - chPrev = ' '; - chNext = styler.SafeGetCharAt(i + 1); - } - } - else if (isoperator(ch)) - { - styler.ColourTo(i, SCE_SCRIPTOL_OPERATOR); - } - } - } - else - { - if (state == SCE_SCRIPTOL_COMMENTLINE || - state == SCE_SCRIPTOL_PERSISTENT || - state == SCE_SCRIPTOL_CSTYLE) - { - if (ch == '\r' || ch == '\n') - { - styler.ColourTo(i - 1, state); - state = SCE_SCRIPTOL_DEFAULT; - } - } - else if(state == SCE_SCRIPTOL_COMMENTBLOCK) - { - if(chPrev == '*' && ch == '/') - { - styler.ColourTo(i, state); - state = SCE_SCRIPTOL_DEFAULT; - } - } - else if ((state == SCE_SCRIPTOL_STRING) || - (state == SCE_SCRIPTOL_CHARACTER)) - { - if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) - { - styler.ColourTo(i - 1, state); - state = SCE_SCRIPTOL_STRINGEOL; - } - else if (ch == '\\') - { - if (chNext == '\"' || chNext == '\'' || chNext == '\\') - { - i++; - ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - } - } - else if ((ch == '\"') || (ch == '\'')) - { - // must match the entered quote type - if(ch == stringType) - { - styler.ColourTo(i, state); - state = SCE_SCRIPTOL_DEFAULT; - } - } - } - else if (state == SCE_SCRIPTOL_TRIPLE) - { - if ((ch == '\'' && chPrev == '\'' && chPrev2 == '\'') || - (ch == '\"' && chPrev == '\"' && chPrev2 == '\"')) - { - styler.ColourTo(i, state); - state = SCE_SCRIPTOL_DEFAULT; - } - } - - } - chPrev2 = chPrev; - chPrev = ch; - } - if (state == SCE_SCRIPTOL_KEYWORD) - { - ClassifyWordSol(styler.GetStartSegment(), - lengthDoc-1, keywords, styler, prevWord); - } - else - { - styler.ColourTo(lengthDoc-1, state); - } -} - -static void FoldSolDoc(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) - { - int lengthDoc = startPos + length; - - int lineCurrent = styler.GetLine(startPos); - if (startPos > 0) - { - if (lineCurrent > 0) - { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); - if (startPos == 0) - initStyle = SCE_SCRIPTOL_DEFAULT; - else - initStyle = styler.StyleAt(startPos-1); - } - } - int state = initStyle & 31; - int spaceFlags = 0; - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsSolComment); - if ((state == SCE_SCRIPTOL_TRIPLE)) - indentCurrent |= SC_FOLDLEVELWHITEFLAG; - char chNext = styler[startPos]; - for (int i = startPos; i < lengthDoc; i++) - { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styler.StyleAt(i) & 31; - - if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) - { - int lev = indentCurrent; - int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsSolComment); - if (style == SCE_SCRIPTOL_TRIPLE) - indentNext |= SC_FOLDLEVELWHITEFLAG; - if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) - { - // Only non whitespace lines can be headers - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) - { - lev |= SC_FOLDLEVELHEADERFLAG; - } - else if (indentNext & SC_FOLDLEVELWHITEFLAG) - { - // Line after is blank so check the next - maybe should continue further? - int spaceFlags2 = 0; - int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsSolComment); - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) - { - lev |= SC_FOLDLEVELHEADERFLAG; - } - } - } - indentCurrent = indentNext; - styler.SetLevel(lineCurrent, lev); - lineCurrent++; - } - } -} - -LexerModule lmScriptol(SCLEX_SCRIPTOL, ColouriseSolDoc, "scriptol", FoldSolDoc); diff --git a/src/LexSmalltalk.cxx b/src/LexSmalltalk.cxx deleted file mode 100644 index 265de3803..000000000 --- a/src/LexSmalltalk.cxx +++ /dev/null @@ -1,321 +0,0 @@ -// Scintilla source code edit control -/** @file LexSmalltalk.cxx - ** Lexer for Smalltalk language. - ** Written by Sergey Philippov, sphilippov-at-gmail-dot-com - **/ -// Copyright 1998-2002 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/* -| lexTable classificationBlock charClasses | -charClasses := #(#DecDigit #Letter #Special #Upper #BinSel). -lexTable := ByteArray new: 128. -classificationBlock := [ :charClass :chars | - | flag | - flag := 1 bitShift: (charClasses indexOf: charClass) - 1. - chars do: [ :char | lexTable at: char codePoint + 1 put: ((lexTable at: char codePoint + 1) bitOr: flag)]]. - -classificationBlock - value: #DecDigit value: '0123456789'; - value: #Letter value: '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - value: #Special value: '()[]{};.^:'; - value: #BinSel value: '~@%&*-+=|\/,<>?!'; - value: #Upper value: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. - -((String new: 500) streamContents: [ :stream | - stream crLf; nextPutAll: 'static int ClassificationTable[256] = {'. - lexTable keysAndValuesDo: [ :index :value | - ((index - 1) rem: 16) == 0 ifTrue: [ - stream crLf; tab] - ifFalse: [ - stream space]. - stream print: value. - index ~= 256 ifTrue: [ - stream nextPut: $,]]. - stream crLf; nextPutAll: '};'; crLf. - - charClasses keysAndValuesDo: [ :index :name | - stream - crLf; - nextPutAll: ( - ('static inline bool is<1s>(int ch) {return (ch > 0) && (ch %< 0x80) && ((ClassificationTable[ch] & <2p>) != 0);}') - expandMacrosWith: name with: (1 bitShift: (index - 1))) - ]]) edit -*/ - -// autogenerated {{{{ - -static int ClassificationTable[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 16, 0, 0, 0, 16, 16, 0, 4, 4, 16, 16, 16, 16, 4, 16, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 16, 16, 16, 16, - 16, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 16, 4, 4, 2, - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 16, 4, 16, 0, -}; - -static inline bool isDecDigit(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 1) != 0);} -static inline bool isLetter(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 2) != 0);} -static inline bool isSpecial(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 4) != 0);} -static inline bool isUpper(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 8) != 0);} -static inline bool isBinSel(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 16) != 0);} -// autogenerated }}}} - -static inline bool isAlphaNumeric(int ch) { - return isDecDigit(ch) || isLetter(ch); -} - -static inline bool isDigitOfRadix(int ch, int radix) -{ - if (isDecDigit(ch)) - return (ch - '0') < radix; - else if (!isUpper(ch)) - return false; - else - return (ch - 'A' + 10) < radix; -} - -static inline void skipComment(StyleContext& sc) -{ - while (sc.More() && sc.ch != '\"') - sc.Forward(); -} - -static inline void skipString(StyleContext& sc) -{ - while (sc.More()) { - if (sc.ch == '\'') { - if (sc.chNext != '\'') - return; - sc.Forward(); - } - sc.Forward(); - } -} - -static void handleHash(StyleContext& sc) -{ - if (isSpecial(sc.chNext)) { - sc.SetState(SCE_ST_SPECIAL); - return; - } - - sc.SetState(SCE_ST_SYMBOL); - sc.Forward(); - if (sc.ch == '\'') { - sc.Forward(); - skipString(sc); - } - else { - if (isLetter(sc.ch)) { - while (isAlphaNumeric(sc.chNext) || sc.chNext == ':') - sc.Forward(); - } - else if (isBinSel(sc.ch)) { - while (isBinSel(sc.chNext)) - sc.Forward(); - } - } -} - -static inline void handleSpecial(StyleContext& sc) -{ - if (sc.ch == ':' && sc.chNext == '=') { - sc.SetState(SCE_ST_ASSIGN); - sc.Forward(); - } - else { - if (sc.ch == '^') - sc.SetState(SCE_ST_RETURN); - else - sc.SetState(SCE_ST_SPECIAL); - } -} - -static inline void skipInt(StyleContext& sc, int radix) -{ - while (isDigitOfRadix(sc.chNext, radix)) - sc.Forward(); -} - -static void handleNumeric(StyleContext& sc) -{ - char num[256]; - int nl; - int radix; - - sc.SetState(SCE_ST_NUMBER); - num[0] = static_cast(sc.ch); - nl = 1; - while (isDecDigit(sc.chNext)) { - num[nl++] = static_cast(sc.chNext); - sc.Forward(); - if (nl+1 == sizeof(num)/sizeof(num[0])) // overrun check - break; - } - if (sc.chNext == 'r') { - num[nl] = 0; - if (num[0] == '-') - radix = atoi(num + 1); - else - radix = atoi(num); - sc.Forward(); - if (sc.chNext == '-') - sc.Forward(); - skipInt(sc, radix); - } - else - radix = 10; - if (sc.chNext != '.' || !isDigitOfRadix(sc.GetRelative(2), radix)) - return; - sc.Forward(); - skipInt(sc, radix); - if (sc.chNext == 's') { - // ScaledDecimal - sc.Forward(); - while (isDecDigit(sc.chNext)) - sc.Forward(); - return; - } - else if (sc.chNext != 'e' && sc.chNext != 'd' && sc.chNext != 'q') - return; - sc.Forward(); - if (sc.chNext == '+' || sc.chNext == '-') - sc.Forward(); - skipInt(sc, radix); -} - -static inline void handleBinSel(StyleContext& sc) -{ - sc.SetState(SCE_ST_BINARY); - while (isBinSel(sc.chNext)) - sc.Forward(); -} - -static void handleLetter(StyleContext& sc, WordList* specialSelectorList) -{ - char ident[256]; - int il; - int state; - bool doubleColonPresent; - - sc.SetState(SCE_ST_DEFAULT); - - ident[0] = static_cast(sc.ch); - il = 1; - while (isAlphaNumeric(sc.chNext)) { - ident[il++] = static_cast(sc.chNext); - sc.Forward(); - if (il+2 == sizeof(ident)/sizeof(ident[0])) // overrun check - break; - } - - if (sc.chNext == ':') { - doubleColonPresent = true; - ident[il++] = ':'; - sc.Forward(); - } - else - doubleColonPresent = false; - ident[il] = 0; - - if (specialSelectorList->InList(ident)) - state = SCE_ST_SPEC_SEL; - else if (doubleColonPresent) - state = SCE_ST_KWSEND; - else if (isUpper(ident[0])) - state = SCE_ST_GLOBAL; - else { - if (!strcmp(ident, "self")) - state = SCE_ST_SELF; - else if (!strcmp(ident, "super")) - state = SCE_ST_SUPER; - else if (!strcmp(ident, "nil")) - state = SCE_ST_NIL; - else if (!strcmp(ident, "true") || !strcmp(ident, "false")) - state = SCE_ST_BOOL; - else - state = SCE_ST_DEFAULT; - } - - sc.ChangeState(state); -} - -static void colorizeSmalltalkDoc(unsigned int startPos, int length, int initStyle, WordList *wordLists[], Accessor &styler) -{ - StyleContext sc(startPos, length, initStyle, styler); - - if (initStyle == SCE_ST_COMMENT) { - skipComment(sc); - if (sc.More()) - sc.Forward(); - } - else if (initStyle == SCE_ST_STRING) { - skipString(sc); - if (sc.More()) - sc.Forward(); - } - - for (; sc.More(); sc.Forward()) { - int ch; - - ch = sc.ch; - if (ch == '\"') { - sc.SetState(SCE_ST_COMMENT); - sc.Forward(); - skipComment(sc); - } - else if (ch == '\'') { - sc.SetState(SCE_ST_STRING); - sc.Forward(); - skipString(sc); - } - else if (ch == '#') - handleHash(sc); - else if (ch == '$') { - sc.SetState(SCE_ST_CHARACTER); - sc.Forward(); - } - else if (isSpecial(ch)) - handleSpecial(sc); - else if (isDecDigit(ch)) - handleNumeric(sc); - else if (isLetter(ch)) - handleLetter(sc, wordLists[0]); - else if (isBinSel(ch)) { - if (ch == '-' && isDecDigit(sc.chNext)) - handleNumeric(sc); - else - handleBinSel(sc); - } - else - sc.SetState(SCE_ST_DEFAULT); - } - sc.Complete(); -} - -static const char* const smalltalkWordListDesc[] = { - "Special selectors", - 0 -}; - -LexerModule lmSmalltalk(SCLEX_SMALLTALK, colorizeSmalltalkDoc, "smalltalk", NULL, smalltalkWordListDesc); diff --git a/src/LexSorcus.cxx b/src/LexSorcus.cxx deleted file mode 100644 index 1d8ba277a..000000000 --- a/src/LexSorcus.cxx +++ /dev/null @@ -1,205 +0,0 @@ -// Scintilla source code edit control -/** @file LexSorcus.cxx -** Lexer for SORCUS installation files -** Written by Eugen Bitter and Christoph Baumann at SORCUS Computer, Heidelberg Germany -** Based on the ASM Lexer by The Black Horus -**/ - -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - - -//each character a..z and A..Z + '_' can be part of a keyword -//additionally numbers that follow 'M' can be contained in a keyword -static inline bool IsSWordStart(const int ch, const int prev_ch) -{ - if (isalpha(ch) || (ch == '_') || ((isdigit(ch)) && (prev_ch == 'M'))) - return true; - - return false; -} - - -//only digits that are not preceded by 'M' count as a number -static inline bool IsSorcusNumber(const int ch, const int prev_ch) -{ - if ((isdigit(ch)) && (prev_ch != 'M')) - return true; - - return false; -} - - -//only = is a valid operator -static inline bool IsSorcusOperator(const int ch) -{ - if (ch == '=') - return true; - - return false; -} - - -static void ColouriseSorcusDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) -{ - - WordList &Command = *keywordlists[0]; - WordList &Parameter = *keywordlists[1]; - WordList &Constant = *keywordlists[2]; - - // Do not leak onto next line - if (initStyle == SCE_SORCUS_STRINGEOL) - initStyle = SCE_SORCUS_DEFAULT; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) - { - - // Prevent SCE_SORCUS_STRINGEOL from leaking back to previous line - if (sc.atLineStart && (sc.state == SCE_SORCUS_STRING)) - { - sc.SetState(SCE_SORCUS_STRING); - } - - // Determine if the current state should terminate. - if (sc.state == SCE_SORCUS_OPERATOR) - { - if (!IsSorcusOperator(sc.ch)) - { - sc.SetState(SCE_SORCUS_DEFAULT); - } - } - else if(sc.state == SCE_SORCUS_NUMBER) - { - if(!IsSorcusNumber(sc.ch, sc.chPrev)) - { - sc.SetState(SCE_SORCUS_DEFAULT); - } - } - else if (sc.state == SCE_SORCUS_IDENTIFIER) - { - if (!IsSWordStart(sc.ch, sc.chPrev)) - { - char s[100]; - - sc.GetCurrent(s, sizeof(s)); - - if (Command.InList(s)) - { - sc.ChangeState(SCE_SORCUS_COMMAND); - } - else if (Parameter.InList(s)) - { - sc.ChangeState(SCE_SORCUS_PARAMETER); - } - else if (Constant.InList(s)) - { - sc.ChangeState(SCE_SORCUS_CONSTANT); - } - - sc.SetState(SCE_SORCUS_DEFAULT); - } - } - else if (sc.state == SCE_SORCUS_COMMENTLINE ) - { - if (sc.atLineEnd) - { - sc.SetState(SCE_SORCUS_DEFAULT); - } - } - else if (sc.state == SCE_SORCUS_STRING) - { - if (sc.ch == '\"') - { - sc.ForwardSetState(SCE_SORCUS_DEFAULT); - } - else if (sc.atLineEnd) - { - sc.ChangeState(SCE_SORCUS_STRINGEOL); - sc.ForwardSetState(SCE_SORCUS_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_SORCUS_DEFAULT) - { - if ((sc.ch == ';') || (sc.ch == '\'')) - { - sc.SetState(SCE_SORCUS_COMMENTLINE); - } - else if (IsSWordStart(sc.ch, sc.chPrev)) - { - sc.SetState(SCE_SORCUS_IDENTIFIER); - } - else if (sc.ch == '\"') - { - sc.SetState(SCE_SORCUS_STRING); - } - else if (IsSorcusOperator(sc.ch)) - { - sc.SetState(SCE_SORCUS_OPERATOR); - } - else if (IsSorcusNumber(sc.ch, sc.chPrev)) - { - sc.SetState(SCE_SORCUS_NUMBER); - } - } - - } - sc.Complete(); -} - - -static const char* const SorcusWordListDesc[] = {"Command","Parameter", "Constant", 0}; - -LexerModule lmSorc(SCLEX_SORCUS, ColouriseSorcusDoc, "sorcins", 0, SorcusWordListDesc); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/LexSpecman.cxx b/src/LexSpecman.cxx deleted file mode 100644 index 093efae75..000000000 --- a/src/LexSpecman.cxx +++ /dev/null @@ -1,289 +0,0 @@ -// Scintilla source code edit control -/** @file LexSpecman.cxx - ** Lexer for Specman E language. - ** Written by Avi Yegudin, based on C++ lexer by Neil Hodgson - **/ -// Copyright 1998-2002 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''); -} - -static inline bool IsANumberChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '\''); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '`'); -} - -static void ColouriseSpecmanDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler, bool caseSensitive) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - - // Do not leak onto next line - if (initStyle == SCE_SN_STRINGEOL) - initStyle = SCE_SN_CODE; - - int visibleChars = 0; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.atLineStart && (sc.state == SCE_SN_STRING)) { - // Prevent SCE_SN_STRINGEOL from leaking back to previous line - sc.SetState(SCE_SN_STRING); - } - - // Handle line continuation generically. - if (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_SN_OPERATOR) { - sc.SetState(SCE_SN_CODE); - } else if (sc.state == SCE_SN_NUMBER) { - if (!IsANumberChar(sc.ch)) { - sc.SetState(SCE_SN_CODE); - } - } else if (sc.state == SCE_SN_IDENTIFIER) { - if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { - char s[100]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); - } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - if (keywords.InList(s)) { - sc.ChangeState(SCE_SN_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_SN_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_SN_WORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_SN_USER); - } - sc.SetState(SCE_SN_CODE); - } - } else if (sc.state == SCE_SN_PREPROCESSOR) { - if (IsASpace(sc.ch)) { - sc.SetState(SCE_SN_CODE); - } - } else if (sc.state == SCE_SN_DEFAULT) { - if (sc.Match('<', '\'')) { - sc.Forward(); - sc.ForwardSetState(SCE_SN_CODE); - } - } else if (sc.state == SCE_SN_COMMENTLINE || sc.state == SCE_SN_COMMENTLINEBANG) { - if (sc.atLineEnd) { - sc.SetState(SCE_SN_CODE); - visibleChars = 0; - } - } else if (sc.state == SCE_SN_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_SN_CODE); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_SN_STRINGEOL); - sc.ForwardSetState(SCE_SN_CODE); - visibleChars = 0; - } - } else if (sc.state == SCE_SN_SIGNAL) { - if (sc.atLineEnd) { - sc.ChangeState(SCE_SN_STRINGEOL); - sc.ForwardSetState(SCE_SN_CODE); - visibleChars = 0; - } else if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_SN_CODE); - } - } else if (sc.state == SCE_SN_REGEXTAG) { - if (!IsADigit(sc.ch)) { - sc.SetState(SCE_SN_CODE); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_SN_CODE) { - if (sc.ch == '$' && IsADigit(sc.chNext)) { - sc.SetState(SCE_SN_REGEXTAG); - sc.Forward(); - } else if (IsADigit(sc.ch)) { - sc.SetState(SCE_SN_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_SN_IDENTIFIER); - } else if (sc.Match('\'', '>')) { - sc.SetState(SCE_SN_DEFAULT); - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match('/', '/')) { - if (sc.Match("//!")) // Nice to have a different comment style - sc.SetState(SCE_SN_COMMENTLINEBANG); - else - sc.SetState(SCE_SN_COMMENTLINE); - } else if (sc.Match('-', '-')) { - if (sc.Match("--!")) // Nice to have a different comment style - sc.SetState(SCE_SN_COMMENTLINEBANG); - else - sc.SetState(SCE_SN_COMMENTLINE); - } else if (sc.ch == '\"') { - sc.SetState(SCE_SN_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_SN_SIGNAL); - } else if (sc.ch == '#' && visibleChars == 0) { - // Preprocessor commands are alone on their line - sc.SetState(SCE_SN_PREPROCESSOR); - // Skip whitespace between # and preprocessor word - do { - sc.Forward(); - } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); - if (sc.atLineEnd) { - sc.SetState(SCE_SN_CODE); - } - } else if (isoperator(static_cast(sc.ch)) || sc.ch == '@') { - sc.SetState(SCE_SN_OPERATOR); - } - } - - if (sc.atLineEnd) { - // Reset states to begining of colourise so no surprises - // if different sets of lines lexed. - visibleChars = 0; - } - if (!IsASpace(sc.ch)) { - visibleChars++; - } - } - sc.Complete(); -} - -// Store both the current line's fold level and the next lines in the -// level store to make it easy to pick up with each increment -// and to make it possible to fiddle the current level for "} else {". -static void FoldNoBoxSpecmanDoc(unsigned int startPos, int length, int, - Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelMinCurrent = levelCurrent; - int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - //int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && (style == SCE_SN_COMMENTLINE)) { - if (((ch == '/') && (chNext == '/')) || - ((ch == '-') && (chNext == '-'))) { - char chNext2 = styler.SafeGetCharAt(i + 2); - if (chNext2 == '{') { - levelNext++; - } else if (chNext2 == '}') { - levelNext--; - } - } - } - if (style == SCE_SN_OPERATOR) { - if (ch == '{') { - // Measure the minimum before a '{' to allow - // folding on "} else {" - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - levelNext++; - } else if (ch == '}') { - levelNext--; - } - } - if (atEOL) { - int levelUse = levelCurrent; - if (foldAtElse) { - levelUse = levelMinCurrent; - } - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - levelMinCurrent = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } -} - -static void FoldSpecmanDoc(unsigned int startPos, int length, int initStyle, WordList *[], - Accessor &styler) { - FoldNoBoxSpecmanDoc(startPos, length, initStyle, styler); -} - -static const char * const specmanWordLists[] = { - "Primary keywords and identifiers", - "Secondary keywords and identifiers", - "Sequence keywords and identifiers", - "User defined keywords and identifiers", - "Unused", - 0, - }; - -static void ColouriseSpecmanDocSensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - ColouriseSpecmanDoc(startPos, length, initStyle, keywordlists, styler, true); -} - - -LexerModule lmSpecman(SCLEX_SPECMAN, ColouriseSpecmanDocSensitive, "specman", FoldSpecmanDoc, specmanWordLists); diff --git a/src/LexSpice.cxx b/src/LexSpice.cxx deleted file mode 100644 index 6aa2e8fdc..000000000 --- a/src/LexSpice.cxx +++ /dev/null @@ -1,226 +0,0 @@ -// Scintilla source code edit control -/** @file LexSpice.cxx - ** Lexer for Spice - **/ -// Copyright 2006 by Fabien Proriol -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include - -#include - -#include "Platform.h" - -#include "Accessor.h" -#include "StyleContext.h" -#include "PropSet.h" -#include "KeyWords.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/* - * Interface - */ - -static void ColouriseDocument( - unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler); - -static const char * const spiceWordListDesc[] = { - "Keywords", // SPICE command - "Keywords2", // SPICE functions - "Keywords3", // SPICE params - 0 -}; - -LexerModule lmSpice(SCLEX_SPICE, ColouriseDocument, "spice", NULL, spiceWordListDesc); - -/* - * Implementation - */ - -static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute); -static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute); - -static inline bool IsDelimiterCharacter(int ch); -static inline bool IsNumberStartCharacter(int ch); -static inline bool IsNumberCharacter(int ch); -static inline bool IsSeparatorOrDelimiterCharacter(int ch); -static inline bool IsWordStartCharacter(int ch); -static inline bool IsWordCharacter(int ch); - -static void ColouriseComment(StyleContext& sc, bool&) { - sc.SetState(SCE_SPICE_COMMENTLINE); - while (!sc.atLineEnd) { - sc.Forward(); - } -} - -static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) { - apostropheStartsAttribute = sc.Match (')'); - sc.SetState(SCE_SPICE_DELIMITER); - sc.ForwardSetState(SCE_SPICE_DEFAULT); -} - -static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) { - apostropheStartsAttribute = true; - std::string number; - sc.SetState(SCE_SPICE_NUMBER); - // Get all characters up to a delimiter or a separator, including points, but excluding - // double points (ranges). - while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) { - number += static_cast(sc.ch); - sc.Forward(); - } - // Special case: exponent with sign - if ((sc.chPrev == 'e' || sc.chPrev == 'E') && - (sc.ch == '+' || sc.ch == '-')) { - number += static_cast(sc.ch); - sc.Forward (); - while (!IsSeparatorOrDelimiterCharacter(sc.ch)) { - number += static_cast(sc.ch); - sc.Forward(); - } - } - sc.SetState(SCE_SPICE_DEFAULT); -} - -static void ColouriseWhiteSpace(StyleContext& sc, bool& ) { - sc.SetState(SCE_SPICE_DEFAULT); - sc.ForwardSetState(SCE_SPICE_DEFAULT); -} - -static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute) { - apostropheStartsAttribute = true; - sc.SetState(SCE_SPICE_IDENTIFIER); - std::string word; - while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) { - word += static_cast(tolower(sc.ch)); - sc.Forward(); - } - if (keywords.InList(word.c_str())) { - sc.ChangeState(SCE_SPICE_KEYWORD); - if (word != "all") { - apostropheStartsAttribute = false; - } - } - else if (keywords2.InList(word.c_str())) { - sc.ChangeState(SCE_SPICE_KEYWORD2); - if (word != "all") { - apostropheStartsAttribute = false; - } - } - else if (keywords3.InList(word.c_str())) { - sc.ChangeState(SCE_SPICE_KEYWORD3); - if (word != "all") { - apostropheStartsAttribute = false; - } - } - sc.SetState(SCE_SPICE_DEFAULT); -} - -// -// ColouriseDocument -// -static void ColouriseDocument( - unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) { - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - StyleContext sc(startPos, length, initStyle, styler); - int lineCurrent = styler.GetLine(startPos); - bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0; - while (sc.More()) { - if (sc.atLineEnd) { - // Go to the next line - sc.Forward(); - lineCurrent++; - // Remember the line state for future incremental lexing - styler.SetLineState(lineCurrent, apostropheStartsAttribute); - // Don't continue any styles on the next line - sc.SetState(SCE_SPICE_DEFAULT); - } - // Comments - if ((sc.Match('*') && sc.atLineStart) || sc.Match('*','~')) { - ColouriseComment(sc, apostropheStartsAttribute); - // Whitespace - } else if (IsASpace(sc.ch)) { - ColouriseWhiteSpace(sc, apostropheStartsAttribute); - // Delimiters - } else if (IsDelimiterCharacter(sc.ch)) { - ColouriseDelimiter(sc, apostropheStartsAttribute); - // Numbers - } else if (IsADigit(sc.ch) || sc.ch == '#') { - ColouriseNumber(sc, apostropheStartsAttribute); - // Keywords or identifiers - } else { - ColouriseWord(sc, keywords, keywords2, keywords3, apostropheStartsAttribute); - } - } - sc.Complete(); -} - -static inline bool IsDelimiterCharacter(int ch) { - switch (ch) { - case '&': - case '\'': - case '(': - case ')': - case '*': - case '+': - case ',': - case '-': - case '.': - case '/': - case ':': - case ';': - case '<': - case '=': - case '>': - case '|': - return true; - default: - return false; - } -} - -static inline bool IsNumberCharacter(int ch) { - return IsNumberStartCharacter(ch) || - ch == '_' || - ch == '.' || - ch == '#' || - (ch >= 'a' && ch <= 'f') || - (ch >= 'A' && ch <= 'F'); -} - -static inline bool IsNumberStartCharacter(int ch) { - return IsADigit(ch); -} - -static inline bool IsSeparatorOrDelimiterCharacter(int ch) { - return IsASpace(ch) || IsDelimiterCharacter(ch); -} - -static inline bool IsWordCharacter(int ch) { - return IsWordStartCharacter(ch) || IsADigit(ch); -} - -static inline bool IsWordStartCharacter(int ch) { - return (isascii(ch) && isalpha(ch)) || ch == '_'; -} diff --git a/src/LexTACL.cxx b/src/LexTACL.cxx deleted file mode 100644 index b0c12440d..000000000 --- a/src/LexTACL.cxx +++ /dev/null @@ -1,397 +0,0 @@ -// Scintilla source code edit control -/** @file LexTAL.cxx - ** Lexer for TAL - ** Based on LexPascal.cxx - ** Written by Laurent le Tynevez - ** Updated by Simon Steele September 2002 - ** Updated by Mathias Rauen May 2003 (Delphi adjustments) - ** Updated by Rod Falck, Aug 2006 Converted to TACL - **/ - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "StyleContext.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -inline bool isTACLoperator(char ch) - { - return ch == '\'' || isoperator(ch); - } - -inline bool isTACLwordchar(char ch) - { - return ch == '#' || ch == '^' || ch == '|' || ch == '_' || iswordchar(ch); - } - -inline bool isTACLwordstart(char ch) - { - return ch == '#' || ch == '|' || ch == '_' || iswordstart(ch); - } - -static void getRange(unsigned int start, - unsigned int end, - Accessor &styler, - char *s, - unsigned int len) { - unsigned int i = 0; - while ((i < end - start + 1) && (i < len-1)) { - s[i] = static_cast(tolower(styler[start + i])); - i++; - } - s[i] = '\0'; -} - -static bool IsStreamCommentStyle(int style) { - return style == SCE_C_COMMENT || - style == SCE_C_COMMENTDOC || - style == SCE_C_COMMENTDOCKEYWORD || - style == SCE_C_COMMENTDOCKEYWORDERROR; -} - -static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr, bool bInAsm) { - if ((bInAsm) && (attr == SCE_C_OPERATOR || attr == SCE_C_NUMBER || attr == SCE_C_DEFAULT || attr == SCE_C_WORD || attr == SCE_C_IDENTIFIER)) { - styler.ColourTo(end, SCE_C_REGEX); - } else - styler.ColourTo(end, attr); -} - -// returns 1 if the item starts a class definition, and -1 if the word is "end", and 2 if the word is "asm" -static int classifyWordTACL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, bool bInAsm) { - int ret = 0; - - WordList& keywords = *keywordlists[0]; - WordList& builtins = *keywordlists[1]; - WordList& commands = *keywordlists[2]; - - char s[100]; - getRange(start, end, styler, s, sizeof(s)); - - char chAttr = SCE_C_IDENTIFIER; - if (isdigit(s[0]) || (s[0] == '.')) { - chAttr = SCE_C_NUMBER; - } - else { - if (s[0] == '#' || keywords.InList(s)) { - chAttr = SCE_C_WORD; - - if (strcmp(s, "asm") == 0) { - ret = 2; - } - else if (strcmp(s, "end") == 0) { - ret = -1; - } - } - else if (s[0] == '|' || builtins.InList(s)) { - chAttr = SCE_C_WORD2; - } - else if (commands.InList(s)) { - chAttr = SCE_C_UUID; - } - else if (strcmp(s, "comment") == 0) { - chAttr = SCE_C_COMMENTLINE; - ret = 3; - } - } - ColourTo(styler, end, chAttr, (bInAsm && ret != -1)); - return ret; -} - -static int classifyFoldPointTACL(const char* s) { - int lev = 0; - if (s[0] == '[') - lev=1; - else if (s[0] == ']') - lev=-1; - return lev; -} - -static void ColouriseTACLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - styler.StartAt(startPos); - - int state = initStyle; - if (state == SCE_C_CHARACTER) // Does not leak onto next line - state = SCE_C_DEFAULT; - char chPrev = ' '; - char chNext = styler[startPos]; - unsigned int lengthDoc = startPos + length; - - bool bInClassDefinition; - - int currentLine = styler.GetLine(startPos); - if (currentLine > 0) { - styler.SetLineState(currentLine, styler.GetLineState(currentLine-1)); - bInClassDefinition = (styler.GetLineState(currentLine) == 1); - } else { - styler.SetLineState(currentLine, 0); - bInClassDefinition = false; - } - - bool bInAsm = (state == SCE_C_REGEX); - if (bInAsm) - state = SCE_C_DEFAULT; - - styler.StartSegment(startPos); - int visibleChars = 0; - unsigned int i; - for (i = startPos; i < lengthDoc; i++) { - char ch = chNext; - - chNext = styler.SafeGetCharAt(i + 1); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { - // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) - // Avoid triggering two times on Dos/Win - // End of line - if (state == SCE_C_CHARACTER) { - ColourTo(styler, i, state, bInAsm); - state = SCE_C_DEFAULT; - } - visibleChars = 0; - currentLine++; - styler.SetLineState(currentLine, (bInClassDefinition ? 1 : 0)); - } - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - chPrev = ' '; - i += 1; - continue; - } - - if (state == SCE_C_DEFAULT) { - if (isTACLwordstart(ch)) { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_IDENTIFIER; - } else if (ch == '{') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_COMMENT; - } else if (ch == '{' && chNext == '*') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_COMMENTDOC; - } else if (ch == '=' && chNext == '=') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_COMMENTLINE; - } else if (ch == '"') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_STRING; - } else if (ch == '?' && visibleChars == 0) { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_PREPROCESSOR; - } else if (isTACLoperator(ch)) { - ColourTo(styler, i-1, state, bInAsm); - ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); - } - } else if (state == SCE_C_IDENTIFIER) { - if (!isTACLwordchar(ch)) { - int lStateChange = classifyWordTACL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm); - - if(lStateChange == 1) { - styler.SetLineState(currentLine, 1); - bInClassDefinition = true; - } else if(lStateChange == 2) { - bInAsm = true; - } else if(lStateChange == -1) { - styler.SetLineState(currentLine, 0); - bInClassDefinition = false; - bInAsm = false; - } - - if (lStateChange == 3) { - state = SCE_C_COMMENTLINE; - } - else { - state = SCE_C_DEFAULT; - chNext = styler.SafeGetCharAt(i + 1); - if (ch == '{') { - state = SCE_C_COMMENT; - } else if (ch == '{' && chNext == '*') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_COMMENTDOC; - } else if (ch == '=' && chNext == '=') { - state = SCE_C_COMMENTLINE; - } else if (ch == '"') { - state = SCE_C_STRING; - } else if (isTACLoperator(ch)) { - ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); - } - } - } - } else { - if (state == SCE_C_PREPROCESSOR) { - if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_COMMENT) { - if (ch == '}' || (ch == '\r' || ch == '\n') ) { - ColourTo(styler, i, state, bInAsm); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_COMMENTDOC) { - if (ch == '}' || (ch == '\r' || ch == '\n')) { - if (((i > styler.GetStartSegment() + 2) || ( - (initStyle == SCE_C_COMMENTDOC) && - (styler.GetStartSegment() == static_cast(startPos))))) { - ColourTo(styler, i, state, bInAsm); - state = SCE_C_DEFAULT; - } - } - } else if (state == SCE_C_COMMENTLINE) { - if (ch == '\r' || ch == '\n') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_STRING) { - if (ch == '"' || ch == '\r' || ch == '\n') { - ColourTo(styler, i, state, bInAsm); - state = SCE_C_DEFAULT; - } - } - } - if (!isspacechar(ch)) - visibleChars++; - chPrev = ch; - } - - // Process to end of document - if (state == SCE_C_IDENTIFIER) { - classifyWordTACL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm); - } - else - ColourTo(styler, lengthDoc - 1, state, bInAsm); -} - -static void FoldTACLDoc(unsigned int startPos, int length, int initStyle, WordList *[], - Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - bool section = false; - - int lastStart = 0; - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - if (stylePrev == SCE_C_DEFAULT && (style == SCE_C_WORD || style == SCE_C_PREPROCESSOR)) - { - // Store last word start point. - lastStart = i; - } - - if (stylePrev == SCE_C_WORD || stylePrev == SCE_C_PREPROCESSOR) { - if(isTACLwordchar(ch) && !isTACLwordchar(chNext)) { - char s[100]; - getRange(lastStart, i, styler, s, sizeof(s)); - if (stylePrev == SCE_C_PREPROCESSOR && strcmp(s, "?section") == 0) - { - section = true; - levelCurrent = 1; - levelPrev = 0; - } - else if (stylePrev == SCE_C_WORD) - levelCurrent += classifyFoldPointTACL(s); - } - } - - if (style == SCE_C_OPERATOR) { - if (ch == '[') { - levelCurrent++; - } else if (ch == ']') { - levelCurrent--; - } - } - if (foldComment && (style == SCE_C_COMMENTLINE)) { - if ((ch == '/') && (chNext == '/')) { - char chNext2 = styler.SafeGetCharAt(i + 2); - if (chNext2 == '{') { - levelCurrent++; - } else if (chNext2 == '}') { - levelCurrent--; - } - } - } - - if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { - if (ch == '{' && chNext == '$') { - unsigned int j=i+2; // skip {$ - while ((j levelPrev || section) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - section = false; - } - - if (!isspacechar(ch)) - visibleChars++; - } - - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const TACLWordListDesc[] = { - "Builtins", - "Labels", - "Commands", - 0 -}; - -LexerModule lmTACL(SCLEX_TACL, ColouriseTACLDoc, "TACL", FoldTACLDoc, TACLWordListDesc); diff --git a/src/LexTADS3.cxx b/src/LexTADS3.cxx deleted file mode 100644 index ee16a0ac0..000000000 --- a/src/LexTADS3.cxx +++ /dev/null @@ -1,904 +0,0 @@ -// Scintilla source code edit control -/** @file LexTADS3.cxx - ** Lexer for TADS3. - **/ -// Copyright 1998-2006 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -/* - * TADS3 is a language designed by Michael J. Roberts for the writing of text - * based games. TADS comes from Text Adventure Development System. It has good - * support for the processing and outputting of formatted text and much of a - * TADS program listing consists of strings. - * - * TADS has two types of strings, those enclosed in single quotes (') and those - * enclosed in double quotes ("). These strings have different symantics and - * can be given different highlighting if desired. - * - * There can be embedded within both types of strings html tags - * ( ), library directives ( <.directive> ), and message - * parameters ( {The doctor's/his} ). - * - * Double quoted strings can also contain interpolated expressions - * ( << rug.moved ? ' and a hole in the floor. ' : nil >> ). These expressions - * may themselves contain single or double quoted strings, although the double - * quoted strings may not contain interpolated expressions. - * - * These embedded constructs influence the output and formatting and are an - * important part of a program and require highlighting. - * - * LINKS - * http://www.tads.org/ - */ - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static const int T3_SINGLE_QUOTE = 1; -static const int T3_INT_EXPRESSION = 2; -static const int T3_INT_EXPRESSION_IN_TAG = 4; -static const int T3_HTML_SQUOTE = 8; - -static inline bool IsEOL(const int ch, const int chNext) { - return (ch == '\r' && chNext != '\n') || (ch == '\n'); -} - -/* - * Test the current character to see if it's the START of an EOL sequence; - * if so, skip ahead to the last character of the sequence and return true, - * and if not just return false. There are a few places where we want to - * check to see if a newline sequence occurs at a particular point, but - * where a caller expects a subroutine to stop only upon reaching the END - * of a newline sequence (in particular, CR-LF on Windows). That's why - * IsEOL() above only returns true on CR if the CR isn't followed by an LF - * - it doesn't want to admit that there's a newline until reaching the END - * of the sequence. We meet both needs by saying that there's a newline - * when we see the CR in a CR-LF, but skipping the CR before returning so - * that the caller's caller will see that we've stopped at the LF. - */ -static inline bool IsEOLSkip(StyleContext &sc) -{ - /* test for CR-LF */ - if (sc.ch == '\r' && sc.chNext == '\n') - { - /* got CR-LF - skip the CR and indicate that we're at a newline */ - sc.Forward(); - return true; - } - - /* - * in other cases, we have at most a 1-character newline, so do the - * normal IsEOL test - */ - return IsEOL(sc.ch, sc.chNext); -} - -static inline bool IsASpaceOrTab(const int ch) { - return ch == ' ' || ch == '\t'; -} - -static inline bool IsATADS3Operator(const int ch) { - return ch == '=' || ch == '{' || ch == '}' || ch == '(' || ch == ')' - || ch == '[' || ch == ']' || ch == ',' || ch == ':' || ch == ';' - || ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '%' - || ch == '?' || ch == '!' || ch == '<' || ch == '>' || ch == '|' - || ch == '@' || ch == '&' || ch == '~'; -} - -static inline bool IsAWordChar(const int ch) { - return isalnum(ch) || ch == '_'; -} - -static inline bool IsAWordStart(const int ch) { - return isalpha(ch) || ch == '_'; -} - -static inline bool IsAHexDigit(const int ch) { - int lch = tolower(ch); - return isdigit(lch) || lch == 'a' || lch == 'b' || lch == 'c' - || lch == 'd' || lch == 'e' || lch == 'f'; -} - -static inline bool IsAnHTMLChar(int ch) { - return isalnum(ch) || ch == '-' || ch == '_' || ch == '.'; -} - -static inline bool IsADirectiveChar(int ch) { - return isalnum(ch) || isspace(ch) || ch == '-' || ch == '/'; -} - -static inline bool IsANumberStart(StyleContext &sc) { - return isdigit(sc.ch) - || (!isdigit(sc.chPrev) && sc.ch == '.' && isdigit(sc.chNext)); -} - -inline static void ColouriseTADS3Operator(StyleContext &sc) { - int initState = sc.state; - int c = sc.ch; - sc.SetState(c == '{' || c == '}' ? SCE_T3_BRACE : SCE_T3_OPERATOR); - sc.ForwardSetState(initState); -} - -static void ColouriseTADSHTMLString(StyleContext &sc, int &lineState) { - int endState = sc.state; - int chQuote = sc.ch; - int chString = (lineState & T3_SINGLE_QUOTE) ? '\'' : '"'; - if (endState == SCE_T3_HTML_STRING) { - if (lineState&T3_SINGLE_QUOTE) { - endState = SCE_T3_S_STRING; - chString = '\''; - } else if (lineState&T3_INT_EXPRESSION) { - endState = SCE_T3_X_STRING; - chString = '"'; - } else { - endState = SCE_T3_HTML_DEFAULT; - chString = '"'; - } - chQuote = (lineState & T3_HTML_SQUOTE) ? '\'' : '"'; - } else { - sc.SetState(SCE_T3_HTML_STRING); - sc.Forward(); - } - if (chQuote == '"') - lineState &= ~T3_HTML_SQUOTE; - else - lineState |= T3_HTML_SQUOTE; - - while (sc.More()) { - if (IsEOL(sc.ch, sc.chNext)) { - return; - } - if (sc.ch == chQuote) { - sc.ForwardSetState(endState); - return; - } - if (sc.Match('\\', static_cast(chQuote))) { - sc.Forward(2); - sc.SetState(endState); - return; - } - if (sc.ch == chString) { - sc.SetState(SCE_T3_DEFAULT); - return; - } - - if (sc.Match('<', '<')) { - lineState |= T3_INT_EXPRESSION | T3_INT_EXPRESSION_IN_TAG; - sc.SetState(SCE_T3_X_DEFAULT); - sc.Forward(2); - return; - } - - if (sc.Match('\\', static_cast(chQuote)) - || sc.Match('\\', static_cast(chString)) - || sc.Match('\\', '\\')) { - sc.Forward(2); - } else { - sc.Forward(); - } - } -} - -static void ColouriseTADS3HTMLTagStart(StyleContext &sc) { - sc.SetState(SCE_T3_HTML_TAG); - sc.Forward(); - if (sc.ch == '/') { - sc.Forward(); - } - while (IsAnHTMLChar(sc.ch)) { - sc.Forward(); - } -} - -static void ColouriseTADS3HTMLTag(StyleContext &sc, int &lineState) { - int endState = sc.state; - int chQuote = '"'; - int chString = '\''; - switch (endState) { - case SCE_T3_S_STRING: - ColouriseTADS3HTMLTagStart(sc); - sc.SetState(SCE_T3_HTML_DEFAULT); - chQuote = '\''; - chString = '"'; - break; - case SCE_T3_D_STRING: - case SCE_T3_X_STRING: - ColouriseTADS3HTMLTagStart(sc); - sc.SetState(SCE_T3_HTML_DEFAULT); - break; - case SCE_T3_HTML_DEFAULT: - if (lineState&T3_SINGLE_QUOTE) { - endState = SCE_T3_S_STRING; - chQuote = '\''; - chString = '"'; - } else if (lineState&T3_INT_EXPRESSION) { - endState = SCE_T3_X_STRING; - } else { - endState = SCE_T3_D_STRING; - } - break; - } - - while (sc.More()) { - if (IsEOL(sc.ch, sc.chNext)) { - return; - } - if (sc.Match('/', '>')) { - sc.SetState(SCE_T3_HTML_TAG); - sc.Forward(2); - sc.SetState(endState); - return; - } - if (sc.ch == '>') { - sc.SetState(SCE_T3_HTML_TAG); - sc.ForwardSetState(endState); - return; - } - if (sc.ch == chQuote) { - sc.SetState(endState); - return; - } - if (sc.Match('\\', static_cast(chQuote))) { - sc.Forward(); - ColouriseTADSHTMLString(sc, lineState); - if (sc.state == SCE_T3_X_DEFAULT) - break; - } else if (sc.ch == chString) { - ColouriseTADSHTMLString(sc, lineState); - } else if (sc.ch == '=') { - ColouriseTADS3Operator(sc); - } else { - sc.Forward(); - } - } -} - -static void ColouriseTADS3Keyword(StyleContext &sc, - WordList *keywordlists[], unsigned int endPos) { - char s[250]; - WordList &keywords = *keywordlists[0]; - WordList &userwords1 = *keywordlists[1]; - WordList &userwords2 = *keywordlists[2]; - WordList &userwords3 = *keywordlists[3]; - int initState = sc.state; - sc.SetState(SCE_T3_IDENTIFIER); - while (sc.More() && (IsAWordChar(sc.ch))) { - sc.Forward(); - } - sc.GetCurrent(s, sizeof(s)); - if ( strcmp(s, "is") == 0 || strcmp(s, "not") == 0) { - // have to find if "in" is next - int n = 1; - while (n + sc.currentPos < endPos && IsASpaceOrTab(sc.GetRelative(n))) - n++; - if (sc.GetRelative(n) == 'i' && sc.GetRelative(n+1) == 'n') { - sc.Forward(n+2); - sc.ChangeState(SCE_T3_KEYWORD); - } - } else if (keywords.InList(s)) { - sc.ChangeState(SCE_T3_KEYWORD); - } else if (userwords3.InList(s)) { - sc.ChangeState(SCE_T3_USER3); - } else if (userwords2.InList(s)) { - sc.ChangeState(SCE_T3_USER2); - } else if (userwords1.InList(s)) { - sc.ChangeState(SCE_T3_USER1); - } - sc.SetState(initState); -} - -static void ColouriseTADS3MsgParam(StyleContext &sc, int &lineState) { - int endState = sc.state; - int chQuote = '"'; - switch (endState) { - case SCE_T3_S_STRING: - sc.SetState(SCE_T3_MSG_PARAM); - sc.Forward(); - chQuote = '\''; - break; - case SCE_T3_D_STRING: - case SCE_T3_X_STRING: - sc.SetState(SCE_T3_MSG_PARAM); - sc.Forward(); - break; - case SCE_T3_MSG_PARAM: - if (lineState&T3_SINGLE_QUOTE) { - endState = SCE_T3_S_STRING; - chQuote = '\''; - } else if (lineState&T3_INT_EXPRESSION) { - endState = SCE_T3_X_STRING; - } else { - endState = SCE_T3_D_STRING; - } - break; - } - while (sc.More() && sc.ch != '}' && sc.ch != chQuote) { - if (IsEOL(sc.ch, sc.chNext)) { - return; - } - if (sc.ch == '\\') { - sc.Forward(); - } - sc.Forward(); - } - if (sc.ch == chQuote) { - sc.SetState(endState); - } else { - sc.ForwardSetState(endState); - } -} - -static void ColouriseTADS3LibDirective(StyleContext &sc, int &lineState) { - int initState = sc.state; - int chQuote = '"'; - switch (initState) { - case SCE_T3_S_STRING: - sc.SetState(SCE_T3_LIB_DIRECTIVE); - sc.Forward(2); - chQuote = '\''; - break; - case SCE_T3_D_STRING: - sc.SetState(SCE_T3_LIB_DIRECTIVE); - sc.Forward(2); - break; - case SCE_T3_LIB_DIRECTIVE: - if (lineState&T3_SINGLE_QUOTE) { - initState = SCE_T3_S_STRING; - chQuote = '\''; - } else { - initState = SCE_T3_D_STRING; - } - break; - } - while (sc.More() && IsADirectiveChar(sc.ch)) { - if (IsEOL(sc.ch, sc.chNext)) { - return; - } - sc.Forward(); - }; - if (sc.ch == '>' || !sc.More()) { - sc.ForwardSetState(initState); - } else if (sc.ch == chQuote) { - sc.SetState(initState); - } else { - sc.ChangeState(initState); - sc.Forward(); - } -} - -static void ColouriseTADS3String(StyleContext &sc, int &lineState) { - int chQuote = sc.ch; - int endState = sc.state; - switch (sc.state) { - case SCE_T3_DEFAULT: - case SCE_T3_X_DEFAULT: - if (chQuote == '"') { - if (sc.state == SCE_T3_DEFAULT) { - sc.SetState(SCE_T3_D_STRING); - } else { - sc.SetState(SCE_T3_X_STRING); - } - lineState &= ~T3_SINGLE_QUOTE; - } else { - sc.SetState(SCE_T3_S_STRING); - lineState |= T3_SINGLE_QUOTE; - } - sc.Forward(); - break; - case SCE_T3_S_STRING: - chQuote = '\''; - endState = lineState&T3_INT_EXPRESSION ? - SCE_T3_X_DEFAULT : SCE_T3_DEFAULT; - break; - case SCE_T3_D_STRING: - chQuote = '"'; - endState = SCE_T3_DEFAULT; - break; - case SCE_T3_X_STRING: - chQuote = '"'; - endState = SCE_T3_X_DEFAULT; - break; - } - while (sc.More()) { - if (IsEOL(sc.ch, sc.chNext)) { - return; - } - if (sc.ch == chQuote) { - sc.ForwardSetState(endState); - return; - } - if (sc.state == SCE_T3_D_STRING && sc.Match('<', '<')) { - lineState |= T3_INT_EXPRESSION; - sc.SetState(SCE_T3_X_DEFAULT); - sc.Forward(2); - return; - } - if (sc.Match('\\', static_cast(chQuote)) - || sc.Match('\\', '\\')) { - sc.Forward(2); - } else if (sc.ch == '{') { - ColouriseTADS3MsgParam(sc, lineState); - } else if (sc.Match('<', '.')) { - ColouriseTADS3LibDirective(sc, lineState); - } else if (sc.ch == '<') { - ColouriseTADS3HTMLTag(sc, lineState); - if (sc.state == SCE_T3_X_DEFAULT) - return; - } else { - sc.Forward(); - } - } -} - -static void ColouriseTADS3Comment(StyleContext &sc, int endState) { - sc.SetState(SCE_T3_BLOCK_COMMENT); - while (sc.More()) { - if (IsEOL(sc.ch, sc.chNext)) { - return; - } - if (sc.Match('*', '/')) { - sc.Forward(2); - sc.SetState(endState); - return; - } - sc.Forward(); - } -} - -static void ColouriseToEndOfLine(StyleContext &sc, int initState, int endState) { - sc.SetState(initState); - while (sc.More()) { - if (sc.ch == '\\') { - sc.Forward(); - if (IsEOLSkip(sc)) { - return; - } - } - if (IsEOL(sc.ch, sc.chNext)) { - sc.SetState(endState); - return; - } - sc.Forward(); - } -} - -static void ColouriseTADS3Number(StyleContext &sc) { - int endState = sc.state; - bool inHexNumber = false; - bool seenE = false; - bool seenDot = sc.ch == '.'; - sc.SetState(SCE_T3_NUMBER); - if (sc.More()) { - sc.Forward(); - } - if (sc.chPrev == '0' && tolower(sc.ch) == 'x') { - inHexNumber = true; - sc.Forward(); - } - while (sc.More()) { - if (inHexNumber) { - if (!IsAHexDigit(sc.ch)) { - break; - } - } else if (!isdigit(sc.ch)) { - if (!seenE && tolower(sc.ch) == 'e') { - seenE = true; - seenDot = true; - if (sc.chNext == '+' || sc.chNext == '-') { - sc.Forward(); - } - } else if (!seenDot && sc.ch == '.') { - seenDot = true; - } else { - break; - } - } - sc.Forward(); - } - sc.SetState(endState); -} - -static void ColouriseTADS3Doc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - int visibleChars = 0; - int bracketLevel = 0; - int lineState = 0; - unsigned int endPos = startPos + length; - int lineCurrent = styler.GetLine(startPos); - if (lineCurrent > 0) { - lineState = styler.GetLineState(lineCurrent-1); - } - StyleContext sc(startPos, length, initStyle, styler); - - while (sc.More()) { - - if (IsEOL(sc.ch, sc.chNext)) { - styler.SetLineState(lineCurrent, lineState); - lineCurrent++; - visibleChars = 0; - sc.Forward(); - if (sc.ch == '\n') { - sc.Forward(); - } - } - - switch(sc.state) { - case SCE_T3_PREPROCESSOR: - case SCE_T3_LINE_COMMENT: - ColouriseToEndOfLine(sc, sc.state, lineState&T3_INT_EXPRESSION ? - SCE_T3_X_DEFAULT : SCE_T3_DEFAULT); - break; - case SCE_T3_S_STRING: - case SCE_T3_D_STRING: - case SCE_T3_X_STRING: - ColouriseTADS3String(sc, lineState); - visibleChars++; - break; - case SCE_T3_MSG_PARAM: - ColouriseTADS3MsgParam(sc, lineState); - break; - case SCE_T3_LIB_DIRECTIVE: - ColouriseTADS3LibDirective(sc, lineState); - break; - case SCE_T3_HTML_DEFAULT: - ColouriseTADS3HTMLTag(sc, lineState); - break; - case SCE_T3_HTML_STRING: - ColouriseTADSHTMLString(sc, lineState); - break; - case SCE_T3_BLOCK_COMMENT: - ColouriseTADS3Comment(sc, lineState&T3_INT_EXPRESSION ? - SCE_T3_X_DEFAULT : SCE_T3_DEFAULT); - break; - case SCE_T3_DEFAULT: - case SCE_T3_X_DEFAULT: - if (IsASpaceOrTab(sc.ch)) { - sc.Forward(); - } else if (sc.ch == '#' && visibleChars == 0) { - ColouriseToEndOfLine(sc, SCE_T3_PREPROCESSOR, sc.state); - } else if (sc.Match('/', '*')) { - ColouriseTADS3Comment(sc, sc.state); - visibleChars++; - } else if (sc.Match('/', '/')) { - ColouriseToEndOfLine(sc, SCE_T3_LINE_COMMENT, sc.state); - } else if (sc.ch == '"') { - bracketLevel = 0; - ColouriseTADS3String(sc, lineState); - visibleChars++; - } else if (sc.ch == '\'') { - ColouriseTADS3String(sc, lineState); - visibleChars++; - } else if (sc.state == SCE_T3_X_DEFAULT && bracketLevel == 0 - && sc.Match('>', '>')) { - sc.Forward(2); - sc.SetState(SCE_T3_D_STRING); - if (lineState & T3_INT_EXPRESSION_IN_TAG) - sc.SetState(SCE_T3_HTML_STRING); - lineState &= ~(T3_SINGLE_QUOTE|T3_INT_EXPRESSION - |T3_INT_EXPRESSION_IN_TAG); - } else if (IsATADS3Operator(sc.ch)) { - if (sc.state == SCE_T3_X_DEFAULT) { - if (sc.ch == '(') { - bracketLevel++; - } else if (sc.ch == ')' && bracketLevel > 0) { - bracketLevel--; - } - } - ColouriseTADS3Operator(sc); - visibleChars++; - } else if (IsANumberStart(sc)) { - ColouriseTADS3Number(sc); - visibleChars++; - } else if (IsAWordStart(sc.ch)) { - ColouriseTADS3Keyword(sc, keywordlists, endPos); - visibleChars++; - } else if (sc.Match("...")) { - sc.SetState(SCE_T3_IDENTIFIER); - sc.Forward(3); - sc.SetState(SCE_T3_DEFAULT); - } else { - sc.Forward(); - visibleChars++; - } - break; - default: - sc.SetState(SCE_T3_DEFAULT); - sc.Forward(); - } - } - sc.Complete(); -} - -/* - TADS3 has two styles of top level block (TLB). Eg - - // default style - silverKey : Key 'small silver key' 'small silver key' - "A small key glints in the sunlight. " - ; - - and - - silverKey : Key { - 'small silver key' - 'small silver key' - "A small key glints in the sunlight. " - } - - Some constructs mandate one or the other, but usually the author has may choose - either. - - T3_SEENSTART is used to indicate that a braceless TLB has been (potentially) - seen and is also used to match the closing ';' of the default style. - - T3_EXPECTINGIDENTIFIER and T3_EXPECTINGPUNCTUATION are used to keep track of - what characters may be seen without incrementing the block level. The general - pattern is identifier identifier, acceptable punctuation characters - are ':', ',', '(' and ')'. No attempt is made to ensure that punctuation - characters are syntactically correct, eg parentheses match. A ')' always - signifies the start of a block. We just need to check if it is followed by a - '{', in which case we let the brace handling code handle the folding level. - - expectingIdentifier == false && expectingIdentifier == false - Before the start of a TLB. - - expectingIdentifier == true && expectingIdentifier == true - Currently in an identifier. Will accept identifier or punctuation. - - expectingIdentifier == true && expectingIdentifier == false - Just seen a punctuation character & now waiting for an identifier to start. - - expectingIdentifier == false && expectingIdentifier == truee - We were in an identifier and have seen space. Now waiting to see a punctuation - character - - Space, comments & preprocessor directives are always acceptable and are - equivalent. -*/ - -static const int T3_SEENSTART = 1 << 12; -static const int T3_EXPECTINGIDENTIFIER = 1 << 13; -static const int T3_EXPECTINGPUNCTUATION = 1 << 14; - -static inline bool IsStringTransition(int s1, int s2) { - return s1 != s2 - && (s1 == SCE_T3_S_STRING || s1 == SCE_T3_X_STRING - || (s1 == SCE_T3_D_STRING && s2 != SCE_T3_X_DEFAULT)) - && s2 != SCE_T3_LIB_DIRECTIVE - && s2 != SCE_T3_MSG_PARAM - && s2 != SCE_T3_HTML_TAG - && s2 != SCE_T3_HTML_STRING; -} - -static inline bool IsATADS3Punctuation(const int ch) { - return ch == ':' || ch == ',' || ch == '(' || ch == ')'; -} - -static inline bool IsAnIdentifier(const int style) { - return style == SCE_T3_IDENTIFIER - || style == SCE_T3_USER1 - || style == SCE_T3_USER2 - || style == SCE_T3_USER3; -} - -static inline bool IsAnOperator(const int style) { - return style == SCE_T3_OPERATOR || SCE_T3_BRACE; -} - -static inline bool IsSpaceEquivalent(const int ch, const int style) { - return isspace(ch) - || style == SCE_T3_BLOCK_COMMENT - || style == SCE_T3_LINE_COMMENT - || style == SCE_T3_PREPROCESSOR; -} - -static char peekAhead(unsigned int startPos, unsigned int endPos, - Accessor &styler) { - for (unsigned int i = startPos; i < endPos; i++) { - int style = styler.StyleAt(i); - char ch = styler[i]; - if (!IsSpaceEquivalent(ch, style)) { - if (IsAnIdentifier(style)) { - return 'a'; - } - if (IsATADS3Punctuation(ch)) { - return ':'; - } - if (ch == '{') { - return '{'; - } - return '*'; - } - } - return ' '; -} - -static void FoldTADS3Doc(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) { - unsigned int endPos = startPos + length; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int seenStart = levelCurrent & T3_SEENSTART; - int expectingIdentifier = levelCurrent & T3_EXPECTINGIDENTIFIER; - int expectingPunctuation = levelCurrent & T3_EXPECTINGPUNCTUATION; - levelCurrent &= SC_FOLDLEVELNUMBERMASK; - int levelMinCurrent = levelCurrent; - int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - char ch = chNext; - int stylePrev = style; - bool redo = false; - for (unsigned int i = startPos; i < endPos; i++) { - if (redo) { - redo = false; - i--; - } else { - ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - } - bool atEOL = IsEOL(ch, chNext); - - if (levelNext == SC_FOLDLEVELBASE) { - if (IsSpaceEquivalent(ch, style)) { - if (expectingPunctuation) { - expectingIdentifier = 0; - } - if (style == SCE_T3_BLOCK_COMMENT) { - levelNext++; - } - } else if (ch == '{') { - levelNext++; - seenStart = 0; - } else if (ch == '\'' || ch == '"' || ch == '[') { - levelNext++; - if (seenStart) { - redo = true; - } - } else if (ch == ';') { - seenStart = 0; - expectingIdentifier = 0; - expectingPunctuation = 0; - } else if (expectingIdentifier && expectingPunctuation) { - if (IsATADS3Punctuation(ch)) { - if (ch == ')' && peekAhead(i+1, endPos, styler) != '{') { - levelNext++; - } else { - expectingPunctuation = 0; - } - } else if (!IsAnIdentifier(style)) { - levelNext++; - } - } else if (expectingIdentifier && !expectingPunctuation) { - if (!IsAnIdentifier(style)) { - levelNext++; - } else { - expectingPunctuation = T3_EXPECTINGPUNCTUATION; - } - } else if (!expectingIdentifier && expectingPunctuation) { - if (!IsATADS3Punctuation(ch)) { - levelNext++; - } else { - if (ch == ')' && peekAhead(i+1, endPos, styler) != '{') { - levelNext++; - } else { - expectingIdentifier = T3_EXPECTINGIDENTIFIER; - expectingPunctuation = 0; - } - } - } else if (!expectingIdentifier && !expectingPunctuation) { - if (IsAnIdentifier(style)) { - seenStart = T3_SEENSTART; - expectingIdentifier = T3_EXPECTINGIDENTIFIER; - expectingPunctuation = T3_EXPECTINGPUNCTUATION; - } - } - - if (levelNext != SC_FOLDLEVELBASE && style != SCE_T3_BLOCK_COMMENT) { - expectingIdentifier = 0; - expectingPunctuation = 0; - } - - } else if (levelNext == SC_FOLDLEVELBASE+1 && seenStart - && ch == ';' && IsAnOperator(style)) { - levelNext--; - seenStart = 0; - } else if (style == SCE_T3_BLOCK_COMMENT) { - if (stylePrev != SCE_T3_BLOCK_COMMENT) { - levelNext++; - } else if (styleNext != SCE_T3_BLOCK_COMMENT && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelNext--; - } - } else if (ch == '\'' || ch == '"') { - if (IsStringTransition(style, stylePrev)) { - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - levelNext++; - } else if (IsStringTransition(style, styleNext)) { - levelNext--; - } - } else if (IsAnOperator(style)) { - if (ch == '{' || ch == '[') { - // Measure the minimum before a '{' to allow - // folding on "} else {" - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - levelNext++; - } else if (ch == '}' || ch == ']') { - levelNext--; - } - } - - if (atEOL) { - if (seenStart && levelNext == SC_FOLDLEVELBASE) { - switch (peekAhead(i+1, endPos, styler)) { - case ' ': - case '{': - break; - case '*': - levelNext++; - break; - case 'a': - if (expectingPunctuation) { - levelNext++; - } - break; - case ':': - if (expectingIdentifier) { - levelNext++; - } - break; - } - if (levelNext != SC_FOLDLEVELBASE) { - expectingIdentifier = 0; - expectingPunctuation = 0; - } - } - int lev = levelMinCurrent | (levelNext | expectingIdentifier - | expectingPunctuation | seenStart) << 16; - if (levelMinCurrent < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - levelMinCurrent = levelCurrent; - } - } -} - -static const char * const tads3WordList[] = { - "TADS3 Keywords", - "User defined 1", - "User defined 2", - "User defined 3", - 0 -}; - -LexerModule lmTADS3(SCLEX_TADS3, ColouriseTADS3Doc, "tads3", FoldTADS3Doc, tads3WordList); diff --git a/src/LexTAL.cxx b/src/LexTAL.cxx deleted file mode 100644 index a76a296d6..000000000 --- a/src/LexTAL.cxx +++ /dev/null @@ -1,396 +0,0 @@ -// Scintilla source code edit control -/** @file LexTAL.cxx - ** Lexer for TAL - ** Based on LexPascal.cxx - ** Written by Laurent le Tynevez - ** Updated by Simon Steele September 2002 - ** Updated by Mathias Rauen May 2003 (Delphi adjustments) - ** Updated by Rod Falck, Aug 2006 Converted to TAL - **/ - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "StyleContext.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -inline bool isTALoperator(char ch) - { - return ch == '\'' || ch == '@' || ch == '#' || isoperator(ch); - } - -inline bool isTALwordchar(char ch) - { - return ch == '$' || ch == '^' || iswordchar(ch); - } - -inline bool isTALwordstart(char ch) - { - return ch == '$' || ch == '^' || iswordstart(ch); - } - -static void getRange(unsigned int start, - unsigned int end, - Accessor &styler, - char *s, - unsigned int len) { - unsigned int i = 0; - while ((i < end - start + 1) && (i < len-1)) { - s[i] = static_cast(tolower(styler[start + i])); - i++; - } - s[i] = '\0'; -} - -static bool IsStreamCommentStyle(int style) { - return style == SCE_C_COMMENT || - style == SCE_C_COMMENTDOC || - style == SCE_C_COMMENTDOCKEYWORD || - style == SCE_C_COMMENTDOCKEYWORDERROR; -} - -static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr, bool bInAsm) { - if ((bInAsm) && (attr == SCE_C_OPERATOR || attr == SCE_C_NUMBER || attr == SCE_C_DEFAULT || attr == SCE_C_WORD || attr == SCE_C_IDENTIFIER)) { - styler.ColourTo(end, SCE_C_REGEX); - } else - styler.ColourTo(end, attr); -} - -// returns 1 if the item starts a class definition, and -1 if the word is "end", and 2 if the word is "asm" -static int classifyWordTAL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, bool bInAsm) { - int ret = 0; - - WordList& keywords = *keywordlists[0]; - WordList& builtins = *keywordlists[1]; - WordList& nonreserved_keywords = *keywordlists[2]; - - char s[100]; - getRange(start, end, styler, s, sizeof(s)); - - char chAttr = SCE_C_IDENTIFIER; - if (isdigit(s[0]) || (s[0] == '.')) { - chAttr = SCE_C_NUMBER; - } - else { - if (keywords.InList(s)) { - chAttr = SCE_C_WORD; - - if (strcmp(s, "asm") == 0) { - ret = 2; - } - else if (strcmp(s, "end") == 0) { - ret = -1; - } - } - else if (s[0] == '$' || builtins.InList(s)) { - chAttr = SCE_C_WORD2; - } - else if (nonreserved_keywords.InList(s)) { - chAttr = SCE_C_UUID; - } - } - ColourTo(styler, end, chAttr, (bInAsm && ret != -1)); - return ret; -} - -static int classifyFoldPointTAL(const char* s) { - int lev = 0; - if (!(isdigit(s[0]) || (s[0] == '.'))) { - if (strcmp(s, "begin") == 0 || - strcmp(s, "block") == 0) { - lev=1; - } else if (strcmp(s, "end") == 0) { - lev=-1; - } - } - return lev; -} - -static void ColouriseTALDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - styler.StartAt(startPos); - - int state = initStyle; - if (state == SCE_C_CHARACTER) // Does not leak onto next line - state = SCE_C_DEFAULT; - char chPrev = ' '; - char chNext = styler[startPos]; - unsigned int lengthDoc = startPos + length; - - bool bInClassDefinition; - - int currentLine = styler.GetLine(startPos); - if (currentLine > 0) { - styler.SetLineState(currentLine, styler.GetLineState(currentLine-1)); - bInClassDefinition = (styler.GetLineState(currentLine) == 1); - } else { - styler.SetLineState(currentLine, 0); - bInClassDefinition = false; - } - - bool bInAsm = (state == SCE_C_REGEX); - if (bInAsm) - state = SCE_C_DEFAULT; - - styler.StartSegment(startPos); - int visibleChars = 0; - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - - chNext = styler.SafeGetCharAt(i + 1); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { - // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) - // Avoid triggering two times on Dos/Win - // End of line - if (state == SCE_C_CHARACTER) { - ColourTo(styler, i, state, bInAsm); - state = SCE_C_DEFAULT; - } - visibleChars = 0; - currentLine++; - styler.SetLineState(currentLine, (bInClassDefinition ? 1 : 0)); - } - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - chPrev = ' '; - i += 1; - continue; - } - - if (state == SCE_C_DEFAULT) { - if (isTALwordstart(ch)) { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_IDENTIFIER; - } else if (ch == '!' && chNext != '*') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_COMMENT; - } else if (ch == '!' && chNext == '*') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_COMMENTDOC; - } else if (ch == '-' && chNext == '-') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_COMMENTLINE; - } else if (ch == '"') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_STRING; - } else if (ch == '?' && visibleChars == 0) { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_PREPROCESSOR; - } else if (isTALoperator(ch)) { - ColourTo(styler, i-1, state, bInAsm); - ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); - } - } else if (state == SCE_C_IDENTIFIER) { - if (!isTALwordchar(ch)) { - int lStateChange = classifyWordTAL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm); - - if(lStateChange == 1) { - styler.SetLineState(currentLine, 1); - bInClassDefinition = true; - } else if(lStateChange == 2) { - bInAsm = true; - } else if(lStateChange == -1) { - styler.SetLineState(currentLine, 0); - bInClassDefinition = false; - bInAsm = false; - } - - state = SCE_C_DEFAULT; - chNext = styler.SafeGetCharAt(i + 1); - if (ch == '!' && chNext != '*') { - state = SCE_C_COMMENT; - } else if (ch == '!' && chNext == '*') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_COMMENTDOC; - } else if (ch == '-' && chNext == '-') { - state = SCE_C_COMMENTLINE; - } else if (ch == '"') { - state = SCE_C_STRING; - } else if (isTALoperator(ch)) { - ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); - } - } - } else { - if (state == SCE_C_PREPROCESSOR) { - if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_COMMENT) { - if (ch == '!' || (ch == '\r' || ch == '\n') ) { - ColourTo(styler, i, state, bInAsm); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_COMMENTDOC) { - if (ch == '!' || (ch == '\r' || ch == '\n')) { - if (((i > styler.GetStartSegment() + 2) || ( - (initStyle == SCE_C_COMMENTDOC) && - (styler.GetStartSegment() == static_cast(startPos))))) { - ColourTo(styler, i, state, bInAsm); - state = SCE_C_DEFAULT; - } - } - } else if (state == SCE_C_COMMENTLINE) { - if (ch == '\r' || ch == '\n') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_STRING) { - if (ch == '"') { - ColourTo(styler, i, state, bInAsm); - state = SCE_C_DEFAULT; - } - } - } - if (!isspacechar(ch)) - visibleChars++; - chPrev = ch; - } - ColourTo(styler, lengthDoc - 1, state, bInAsm); -} - -static void FoldTALDoc(unsigned int startPos, int length, int initStyle, WordList *[], - Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - bool was_end = false; - bool section = false; - - int lastStart = 0; - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - if (stylePrev == SCE_C_DEFAULT && (style == SCE_C_WORD || style == SCE_C_UUID || style == SCE_C_PREPROCESSOR)) - { - // Store last word start point. - lastStart = i; - } - - if (stylePrev == SCE_C_WORD || style == SCE_C_UUID || stylePrev == SCE_C_PREPROCESSOR) { - if(isTALwordchar(ch) && !isTALwordchar(chNext)) { - char s[100]; - getRange(lastStart, i, styler, s, sizeof(s)); - if (stylePrev == SCE_C_PREPROCESSOR && strcmp(s, "?section") == 0) - { - section = true; - levelCurrent = 1; - levelPrev = 0; - } - else if (stylePrev == SCE_C_WORD || stylePrev == SCE_C_UUID) - { - if (strcmp(s, "block") == 0) - { - // block keyword is ignored immediately after end keyword - if (!was_end) - levelCurrent++; - } - else - levelCurrent += classifyFoldPointTAL(s); - if (strcmp(s, "end") == 0) - { - was_end = true; - } - else - { - was_end = false; - } - } - } - } - - if (foldComment && (style == SCE_C_COMMENTLINE)) { - if ((ch == '/') && (chNext == '/')) { - char chNext2 = styler.SafeGetCharAt(i + 2); - if (chNext2 == '{') { - levelCurrent++; - } else if (chNext2 == '}') { - levelCurrent--; - } - } - } - - if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { - if (ch == '{' && chNext == '$') { - unsigned int j=i+2; // skip {$ - while ((j levelPrev || section) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - section = false; - } - - if (!isspacechar(ch)) - visibleChars++; - } - - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - -static const char * const TALWordListDesc[] = { - "Keywords", - "Builtins", - 0 -}; - -LexerModule lmTAL(SCLEX_TAL, ColouriseTALDoc, "TAL", FoldTALDoc, TALWordListDesc); diff --git a/src/LexTCL.cxx b/src/LexTCL.cxx deleted file mode 100644 index 3c175de2a..000000000 --- a/src/LexTCL.cxx +++ /dev/null @@ -1,366 +0,0 @@ -// Scintilla source code edit control -/** @file LexTCL.cxx - ** Lexer for TCL language. - **/ -// Copyright 1998-2001 by Andre Arpin -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// Extended to accept accented characters -static inline bool IsAWordChar(int ch) { - return ch >= 0x80 || - (isalnum(ch) || ch == '_' || ch ==':' || ch=='.'); // : name space separator -} - -static inline bool IsAWordStart(int ch) { - return ch >= 0x80 || (ch ==':' || isalpha(ch) || ch == '_'); -} - -static inline bool IsANumberChar(int ch) { - // Not exactly following number definition (several dots are seen as OK, etc.) - // but probably enough in most cases. - return (ch < 0x80) && - (IsADigit(ch, 0x10) || toupper(ch) == 'E' || - ch == '.' || ch == '-' || ch == '+'); -} - -static void ColouriseTCLDoc(unsigned int startPos, int length, int , WordList *keywordlists[], Accessor &styler) { -#define isComment(s) (s==SCE_TCL_COMMENT || s==SCE_TCL_COMMENTLINE || s==SCE_TCL_COMMENT_BOX || s==SCE_TCL_BLOCK_COMMENT) - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool commentLevel = false; - bool subBrace = false; // substitution begin with a brace ${.....} - enum tLineState {LS_DEFAULT, LS_OPEN_COMMENT, LS_OPEN_DOUBLE_QUOTE, LS_COMMENT_BOX, LS_MASK_STATE = 0xf, - LS_COMMAND_EXPECTED = 16, LS_BRACE_ONLY = 32 } lineState = LS_DEFAULT; - bool prevSlash = false; - int currentLevel = 0; - bool expected = 0; - bool subParen = 0; - - int currentLine = styler.GetLine(startPos); - if (currentLine > 0) - currentLine--; - length += startPos - styler.LineStart(currentLine); - // make sure lines overlap - startPos = styler.LineStart(currentLine); - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - WordList &keywords6 = *keywordlists[5]; - WordList &keywords7 = *keywordlists[6]; - WordList &keywords8 = *keywordlists[7]; - WordList &keywords9 = *keywordlists[8]; - - if (currentLine > 0) { - int ls = styler.GetLineState(currentLine - 1); - lineState = tLineState(ls & LS_MASK_STATE); - expected = LS_COMMAND_EXPECTED == tLineState(ls & LS_COMMAND_EXPECTED); - subBrace = LS_BRACE_ONLY == tLineState(ls & LS_BRACE_ONLY); - currentLevel = styler.LevelAt(currentLine - 1) >> 17; - commentLevel = (styler.LevelAt(currentLine - 1) >> 16) & 1; - } else - styler.SetLevel(0, SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG); - bool visibleChars = false; - - int previousLevel = currentLevel; - StyleContext sc(startPos, length, SCE_TCL_DEFAULT, styler); - for (; ; sc.Forward()) { -next: - if (sc.ch=='\r' && sc.chNext == '\n') // only ignore \r on PC process on the mac - continue; - bool atEnd = !sc.More(); // make sure we coloured the last word - if (lineState != LS_DEFAULT) { - sc.SetState(SCE_TCL_DEFAULT); - if (lineState == LS_OPEN_COMMENT) - sc.SetState(SCE_TCL_COMMENTLINE); - else if (lineState == LS_OPEN_DOUBLE_QUOTE) - sc.SetState(SCE_TCL_IN_QUOTE); - else if (lineState == LS_COMMENT_BOX && (sc.ch == '#' || (sc.ch == ' ' && sc.chNext=='#'))) - sc.SetState(SCE_TCL_COMMENT_BOX); - lineState = LS_DEFAULT; - } - if (subBrace) { // ${ overrides every thing even \ except } - if (sc.ch == '}') { - subBrace = false; - sc.SetState(SCE_TCL_OPERATOR); - sc.ForwardSetState(SCE_TCL_DEFAULT); - goto next; - } - else - sc.SetState(SCE_TCL_SUB_BRACE); - if (!sc.atLineEnd) - continue; - } else if (sc.state == SCE_TCL_DEFAULT || sc.state ==SCE_TCL_OPERATOR) { - expected &= isspacechar(static_cast(sc.ch)) || IsAWordStart(sc.ch) || sc.ch =='#'; - } else if (sc.state == SCE_TCL_SUBSTITUTION) { - switch(sc.ch) { - case '(': - subParen=true; - sc.SetState(SCE_TCL_OPERATOR); - sc.ForwardSetState(SCE_TCL_SUBSTITUTION); - continue; - case ')': - sc.SetState(SCE_TCL_OPERATOR); - subParen=false; - continue; - case '$': - continue; - case ',': - sc.SetState(SCE_TCL_OPERATOR); - if (subParen) - sc.ForwardSetState(SCE_TCL_SUBSTITUTION); - continue; - default : - // maybe spaces should be allowed ??? - if (!IsAWordChar(sc.ch)) { // probably the code is wrong - sc.SetState(SCE_TCL_DEFAULT); - subParen = 0; - } - break; - } - } else if (isComment(sc.state)) { - } else if (!IsAWordChar(sc.ch)) { - if ((sc.state == SCE_TCL_IDENTIFIER && expected) || sc.state == SCE_TCL_MODIFIER) { - char w[100]; - char *s=w; - sc.GetCurrent(w, sizeof(w)); - if (w[strlen(w)-1]=='\r') - w[strlen(w)-1]=0; - while(*s == ':') // ignore leading : like in ::set a 10 - ++s; - bool quote = sc.state == SCE_TCL_IN_QUOTE; - if (commentLevel || expected) { - if (keywords.InList(s)) { - sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD4); - } else if (sc.GetRelative(-static_cast(strlen(s))-1) == '{' && - keywords5.InList(s) && sc.ch == '}') { // {keyword} exactly no spaces - sc.ChangeState(SCE_TCL_EXPAND); - } - if (keywords6.InList(s)) { - sc.ChangeState(SCE_TCL_WORD5); - } else if (keywords7.InList(s)) { - sc.ChangeState(SCE_TCL_WORD6); - } else if (keywords8.InList(s)) { - sc.ChangeState(SCE_TCL_WORD7); - } else if (keywords9.InList(s)) { - sc.ChangeState(SCE_TCL_WORD8); - } - } - expected = false; - sc.SetState(quote ? SCE_TCL_IN_QUOTE : SCE_TCL_DEFAULT); - } else if (sc.state == SCE_TCL_MODIFIER || sc.state == SCE_TCL_IDENTIFIER) { - sc.SetState(SCE_TCL_DEFAULT); - } - } - if (atEnd) - break; - if (sc.atLineEnd) { - lineState = LS_DEFAULT; - currentLine = styler.GetLine(sc.currentPos); - if (foldComment && sc.state!=SCE_TCL_COMMENT && isComment(sc.state)) { - if (currentLevel == 0) { - ++currentLevel; - commentLevel = true; - } - } else { - if (visibleChars && commentLevel) { - --currentLevel; - --previousLevel; - commentLevel = false; - } - } - int flag = 0; - if (!visibleChars) - flag = SC_FOLDLEVELWHITEFLAG; - if (currentLevel > previousLevel) - flag = SC_FOLDLEVELHEADERFLAG; - styler.SetLevel(currentLine, flag + previousLevel + SC_FOLDLEVELBASE + (currentLevel << 17) + (commentLevel << 16)); - - // Update the line state, so it can be seen by next line - if (sc.state == SCE_TCL_IN_QUOTE) - lineState = LS_OPEN_DOUBLE_QUOTE; - else { - if (prevSlash) { - if (isComment(sc.state)) - lineState = LS_OPEN_COMMENT; - } else if (sc.state == SCE_TCL_COMMENT_BOX) - lineState = LS_COMMENT_BOX; - } - styler.SetLineState(currentLine, - (subBrace ? LS_BRACE_ONLY : 0) | - (expected ? LS_COMMAND_EXPECTED : 0) | lineState); - if (lineState == LS_COMMENT_BOX) - sc.ForwardSetState(SCE_TCL_COMMENT_BOX); - else if (lineState == LS_OPEN_DOUBLE_QUOTE) - sc.ForwardSetState(SCE_TCL_IN_QUOTE); - else - sc.ForwardSetState(SCE_TCL_DEFAULT); - prevSlash = false; - previousLevel = currentLevel; - goto next; - } - - if (prevSlash) { - prevSlash = false; - if (sc.ch == '#' && IsANumberChar(sc.chNext)) - sc.ForwardSetState(SCE_TCL_NUMBER); - continue; - } - prevSlash = sc.ch == '\\'; - if (isComment(sc.state)) - continue; - if (sc.atLineStart) { - visibleChars = false; - if (sc.state!=SCE_TCL_IN_QUOTE && !isComment(sc.state)) - { - sc.SetState(SCE_TCL_DEFAULT); - expected = IsAWordStart(sc.ch)|| isspacechar(static_cast(sc.ch)); - } - } - - switch (sc.state) { - case SCE_TCL_NUMBER: - if (!IsANumberChar(sc.ch)) - sc.SetState(SCE_TCL_DEFAULT); - break; - case SCE_TCL_IN_QUOTE: - if (sc.ch == '"') { - sc.ForwardSetState(SCE_TCL_DEFAULT); - visibleChars = true; // necessary if a " is the first and only character on a line - goto next; - } else if (sc.ch == '[' || sc.ch == ']' || sc.ch == '$') { - sc.SetState(SCE_TCL_OPERATOR); - expected = sc.ch == '['; - sc.ForwardSetState(SCE_TCL_IN_QUOTE); - goto next; - } - continue; - case SCE_TCL_OPERATOR: - sc.SetState(SCE_TCL_DEFAULT); - break; - } - - if (sc.ch == '#') { - if (visibleChars) { - if (sc.state != SCE_TCL_IN_QUOTE && expected) - sc.SetState(SCE_TCL_COMMENT); - } else { - sc.SetState(SCE_TCL_COMMENTLINE); - if (sc.chNext == '~') - sc.SetState(SCE_TCL_BLOCK_COMMENT); - if (sc.atLineStart && (sc.chNext == '#' || sc.chNext == '-')) - sc.SetState(SCE_TCL_COMMENT_BOX); - } - } - - if (!isspacechar(static_cast(sc.ch))) { - visibleChars = true; - } - - if (sc.ch == '\\') { - prevSlash = true; - continue; - } - - // Determine if a new state should be entered. - if (sc.state == SCE_TCL_DEFAULT) { - if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_TCL_IDENTIFIER); - } else if (IsADigit(sc.ch) && !IsAWordChar(sc.chPrev)) { - sc.SetState(SCE_TCL_NUMBER); - } else { - switch (sc.ch) { - case '\"': - sc.SetState(SCE_TCL_IN_QUOTE); - break; - case '{': - sc.SetState(SCE_TCL_OPERATOR); - expected = true; - ++currentLevel; - break; - case '}': - sc.SetState(SCE_TCL_OPERATOR); - --currentLevel; - break; - case '[': - expected = true; - case ']': - case '(': - case ')': - sc.SetState(SCE_TCL_OPERATOR); - break; - case ';': - expected = true; - break; - case '$': - subParen = 0; - if (sc.chNext != '{') { - sc.SetState(SCE_TCL_SUBSTITUTION); - } - else { - sc.SetState(SCE_TCL_OPERATOR); // $ - sc.Forward(); // { - sc.ForwardSetState(SCE_TCL_SUB_BRACE); - subBrace = true; - } - break; - case '#': - if ((isspacechar(static_cast(sc.chPrev))|| - isoperator(static_cast(sc.chPrev))) && IsADigit(sc.chNext,0x10)) - sc.SetState(SCE_TCL_NUMBER); - break; - case '-': - sc.SetState(IsADigit(sc.chNext)? SCE_TCL_NUMBER: SCE_TCL_MODIFIER); - break; - default: - if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_TCL_OPERATOR); - } - } - } - } - } - sc.Complete(); -} - -static const char * const tclWordListDesc[] = { - "TCL Keywords", - "TK Keywords", - "iTCL Keywords", - "tkCommands", - "expand" - "user1", - "user2", - "user3", - "user4", - 0 - }; - -// this code supports folding in the colourizer -LexerModule lmTCL(SCLEX_TCL, ColouriseTCLDoc, "tcl", 0, tclWordListDesc); diff --git a/src/LexTeX.cxx b/src/LexTeX.cxx deleted file mode 100644 index 62ade1d75..000000000 --- a/src/LexTeX.cxx +++ /dev/null @@ -1,494 +0,0 @@ -// Scintilla source code edit control - -// File: LexTeX.cxx - general context conformant tex coloring scheme -// Author: Hans Hagen - PRAGMA ADE - Hasselt NL - www.pragma-ade.com -// Version: September 28, 2003 - -// Copyright: 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -// This lexer is derived from the one written for the texwork environment (1999++) which in -// turn is inspired on texedit (1991++) which finds its roots in wdt (1986). - -// If you run into strange boundary cases, just tell me and I'll look into it. - - -// TeX Folding code added by instanton (soft_share@126.com) with borrowed code from VisualTeX source by Alex Romanenko. -// Version: June 22, 2007 - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" -#include "StyleContext.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// val SCE_TEX_DEFAULT = 0 -// val SCE_TEX_SPECIAL = 1 -// val SCE_TEX_GROUP = 2 -// val SCE_TEX_SYMBOL = 3 -// val SCE_TEX_COMMAND = 4 -// val SCE_TEX_TEXT = 5 - -// Definitions in SciTEGlobal.properties: -// -// TeX Highlighting -// -// # Default -// style.tex.0=fore:#7F7F00 -// # Special -// style.tex.1=fore:#007F7F -// # Group -// style.tex.2=fore:#880000 -// # Symbol -// style.tex.3=fore:#7F7F00 -// # Command -// style.tex.4=fore:#008800 -// # Text -// style.tex.5=fore:#000000 - -// lexer.tex.interface.default=0 -// lexer.tex.comment.process=0 - -// todo: lexer.tex.auto.if - -// Auxiliary functions: - -static inline bool endOfLine(Accessor &styler, unsigned int i) { - return - (styler[i] == '\n') || ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')) ; -} - -static inline bool isTeXzero(int ch) { - return - (ch == '%') ; -} - -static inline bool isTeXone(int ch) { - return - (ch == '[') || (ch == ']') || (ch == '=') || (ch == '#') || - (ch == '(') || (ch == ')') || (ch == '<') || (ch == '>') || - (ch == '"') ; -} - -static inline bool isTeXtwo(int ch) { - return - (ch == '{') || (ch == '}') || (ch == '$') ; -} - -static inline bool isTeXthree(int ch) { - return - (ch == '~') || (ch == '^') || (ch == '_') || (ch == '&') || - (ch == '-') || (ch == '+') || (ch == '\"') || (ch == '`') || - (ch == '/') || (ch == '|') || (ch == '%') ; -} - -static inline bool isTeXfour(int ch) { - return - (ch == '\\') ; -} - -static inline bool isTeXfive(int ch) { - return - ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) || - (ch == '@') || (ch == '!') || (ch == '?') ; -} - -static inline bool isTeXsix(int ch) { - return - (ch == ' ') ; -} - -static inline bool isTeXseven(int ch) { - return - (ch == '^') ; -} - -// Interface determination - -static int CheckTeXInterface( - unsigned int startPos, - int length, - Accessor &styler, - int defaultInterface) { - - char lineBuffer[1024] ; - unsigned int linePos = 0 ; - - // some day we can make something lexer.tex.mapping=(all,0)(nl,1)(en,2)... - - if (styler.SafeGetCharAt(0) == '%') { - for (unsigned int i = 0; i < startPos + length; i++) { - lineBuffer[linePos++] = styler.SafeGetCharAt(i) ; - if (endOfLine(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { - lineBuffer[linePos] = '\0'; - if (strstr(lineBuffer, "interface=all")) { - return 0 ; - } else if (strstr(lineBuffer, "interface=tex")) { - return 1 ; - } else if (strstr(lineBuffer, "interface=nl")) { - return 2 ; - } else if (strstr(lineBuffer, "interface=en")) { - return 3 ; - } else if (strstr(lineBuffer, "interface=de")) { - return 4 ; - } else if (strstr(lineBuffer, "interface=cz")) { - return 5 ; - } else if (strstr(lineBuffer, "interface=it")) { - return 6 ; - } else if (strstr(lineBuffer, "interface=ro")) { - return 7 ; - } else if (strstr(lineBuffer, "interface=latex")) { - // we will move latex cum suis up to 91+ when more keyword lists are supported - return 8 ; - } else if (styler.SafeGetCharAt(1) == 'D' && strstr(lineBuffer, "%D \\module")) { - // better would be to limit the search to just one line - return 3 ; - } else { - return defaultInterface ; - } - } - } - } - - return defaultInterface ; -} - -static void ColouriseTeXDoc( - unsigned int startPos, - int length, - int, - WordList *keywordlists[], - Accessor &styler) { - - styler.StartAt(startPos) ; - styler.StartSegment(startPos) ; - - bool processComment = styler.GetPropertyInt("lexer.tex.comment.process", 0) == 1 ; - bool useKeywords = styler.GetPropertyInt("lexer.tex.use.keywords", 1) == 1 ; - bool autoIf = styler.GetPropertyInt("lexer.tex.auto.if", 1) == 1 ; - int defaultInterface = styler.GetPropertyInt("lexer.tex.interface.default", 1) ; - - char key[100] ; - int k ; - bool newifDone = false ; - bool inComment = false ; - - int currentInterface = CheckTeXInterface(startPos,length,styler,defaultInterface) ; - - if (currentInterface == 0) { - useKeywords = false ; - currentInterface = 1 ; - } - - WordList &keywords = *keywordlists[currentInterface-1] ; - - StyleContext sc(startPos, length, SCE_TEX_TEXT, styler); - - bool going = sc.More() ; // needed because of a fuzzy end of file state - - for (; going; sc.Forward()) { - - if (! sc.More()) { going = false ; } // we need to go one behind the end of text - - if (inComment) { - if (sc.atLineEnd) { - sc.SetState(SCE_TEX_TEXT) ; - newifDone = false ; - inComment = false ; - } - } else { - if (! isTeXfive(sc.ch)) { - if (sc.state == SCE_TEX_COMMAND) { - if (sc.LengthCurrent() == 1) { // \ - if (isTeXseven(sc.ch) && isTeXseven(sc.chNext)) { - sc.Forward(2) ; // \^^ and \^^ - } - sc.ForwardSetState(SCE_TEX_TEXT) ; - } else { - sc.GetCurrent(key, sizeof(key)-1) ; - k = strlen(key) ; - memmove(key,key+1,k) ; // shift left over escape token - key[k] = '\0' ; - k-- ; - if (! keywords || ! useKeywords) { - sc.SetState(SCE_TEX_COMMAND) ; - newifDone = false ; - } else if (k == 1) { //\ - sc.SetState(SCE_TEX_COMMAND) ; - newifDone = false ; - } else if (keywords.InList(key)) { - sc.SetState(SCE_TEX_COMMAND) ; - newifDone = autoIf && (strcmp(key,"newif") == 0) ; - } else if (autoIf && ! newifDone && (key[0] == 'i') && (key[1] == 'f') && keywords.InList("if")) { - sc.SetState(SCE_TEX_COMMAND) ; - } else { - sc.ChangeState(SCE_TEX_TEXT) ; - sc.SetState(SCE_TEX_TEXT) ; - newifDone = false ; - } - } - } - if (isTeXzero(sc.ch)) { - sc.SetState(SCE_TEX_SYMBOL); - - if (!endOfLine(styler,sc.currentPos + 1)) - sc.ForwardSetState(SCE_TEX_DEFAULT) ; - - inComment = ! processComment ; - newifDone = false ; - } else if (isTeXseven(sc.ch) && isTeXseven(sc.chNext)) { - sc.SetState(SCE_TEX_TEXT) ; - sc.ForwardSetState(SCE_TEX_TEXT) ; - } else if (isTeXone(sc.ch)) { - sc.SetState(SCE_TEX_SPECIAL) ; - newifDone = false ; - } else if (isTeXtwo(sc.ch)) { - sc.SetState(SCE_TEX_GROUP) ; - newifDone = false ; - } else if (isTeXthree(sc.ch)) { - sc.SetState(SCE_TEX_SYMBOL) ; - newifDone = false ; - } else if (isTeXfour(sc.ch)) { - sc.SetState(SCE_TEX_COMMAND) ; - } else if (isTeXsix(sc.ch)) { - sc.SetState(SCE_TEX_TEXT) ; - } else if (sc.atLineEnd) { - sc.SetState(SCE_TEX_TEXT) ; - newifDone = false ; - inComment = false ; - } else { - sc.SetState(SCE_TEX_TEXT) ; - } - } else if (sc.state != SCE_TEX_COMMAND) { - sc.SetState(SCE_TEX_TEXT) ; - } - } - } - sc.ChangeState(SCE_TEX_TEXT) ; - sc.Complete(); - -} - - -static inline bool isNumber(int ch) { - return - (ch == '0') || (ch == '1') || (ch == '2') || - (ch == '3') || (ch == '4') || (ch == '5') || - (ch == '6') || (ch == '7') || (ch == '8') || (ch == '9'); -} - -static inline bool isWordChar(int ch) { - return ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')); -} - -static int ParseTeXCommand(unsigned int pos, Accessor &styler, char *command) -{ - int length=0; - char ch=styler.SafeGetCharAt(pos+1); - - if(ch==',' || ch==':' || ch==';' || ch=='%'){ - command[0]=ch; - command[1]=0; - return 1; - } - - // find end - while(isWordChar(ch) && !isNumber(ch) && ch!='_' && ch!='.' && length<100){ - command[length]=ch; - length++; - ch=styler.SafeGetCharAt(pos+length+1); - } - - command[length]='\0'; - if(!length) return 0; - return length+1; -} - -static int classifyFoldPointTeXPaired(const char* s) { - int lev=0; - if (!(isdigit(s[0]) || (s[0] == '.'))){ - if (strcmp(s, "begin")==0||strcmp(s,"FoldStart")==0|| - strcmp(s,"abstract")==0||strcmp(s,"unprotect")==0|| - strcmp(s,"title")==0||strncmp(s,"start",5)==0||strncmp(s,"Start",5)==0|| - strcmp(s,"documentclass")==0||strncmp(s,"if",2)==0 - ) - lev=1; - if (strcmp(s, "end")==0||strcmp(s,"FoldStop")==0|| - strcmp(s,"maketitle")==0||strcmp(s,"protect")==0|| - strncmp(s,"stop",4)==0||strncmp(s,"Stop",4)==0|| - strcmp(s,"fi")==0 - ) - lev=-1; - } - return lev; -} - -static int classifyFoldPointTeXUnpaired(const char* s) { - int lev=0; - if (!(isdigit(s[0]) || (s[0] == '.'))){ - if (strcmp(s,"part")==0|| - strcmp(s,"chapter")==0|| - strcmp(s,"section")==0|| - strcmp(s,"subsection")==0|| - strcmp(s,"subsubsection")==0|| - strcmp(s,"CJKfamily")==0|| - strcmp(s,"appendix")==0|| - strcmp(s,"Topic")==0||strcmp(s,"topic")==0|| - strcmp(s,"subject")==0||strcmp(s,"subsubject")==0|| - strcmp(s,"def")==0||strcmp(s,"gdef")==0||strcmp(s,"edef")==0|| - strcmp(s,"xdef")==0||strcmp(s,"framed")==0|| - strcmp(s,"frame")==0|| - strcmp(s,"foilhead")==0||strcmp(s,"overlays")==0||strcmp(s,"slide")==0 - ){ - lev=1; - } - } - return lev; -} - -static bool IsTeXCommentLine(int line, Accessor &styler) { - int pos = styler.LineStart(line); - int eol_pos = styler.LineStart(line + 1) - 1; - - int startpos = pos; - - while (startpos SC_FOLDLEVELBASE && ((ch == '\r' || ch=='\n') && (chNext == '\\'))) { - ParseTeXCommand(i+1, styler, buffer); - levelCurrent -= classifyFoldPointTeXUnpaired(buffer); - } - - char chNext2; - char chNext3; - char chNext4; - char chNext5; - chNext2=styler.SafeGetCharAt(i+2); - chNext3=styler.SafeGetCharAt(i+3); - chNext4=styler.SafeGetCharAt(i+4); - chNext5=styler.SafeGetCharAt(i+5); - - bool atEOfold = (ch == '%') && - (chNext == '%') && (chNext2=='}') && - (chNext3=='}')&& (chNext4=='-')&& (chNext5=='-'); - - bool atBOfold = (ch == '%') && - (chNext == '%') && (chNext2=='-') && - (chNext3=='-')&& (chNext4=='{')&& (chNext5=='{'); - - if(atBOfold){ - levelCurrent+=1; - } - - if(atEOfold){ - levelCurrent-=1; - } - - if(ch=='\\' && chNext=='['){ - levelCurrent+=1; - } - - if(ch=='\\' && chNext==']'){ - levelCurrent-=1; - } - - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - - if (foldComment && atEOL && IsTeXCommentLine(lineCurrent, styler)) - { - if (lineCurrent==0 && IsTeXCommentLine(lineCurrent + 1, styler) - ) - levelCurrent++; - else if (lineCurrent!=0 && !IsTeXCommentLine(lineCurrent - 1, styler) - && IsTeXCommentLine(lineCurrent + 1, styler) - ) - levelCurrent++; - else if (lineCurrent!=0 && IsTeXCommentLine(lineCurrent - 1, styler) && - !IsTeXCommentLine(lineCurrent+1, styler)) - levelCurrent--; - } - -//--------------------------------------------------------------------------------------------- - - if (atEOL) { - int lev = levelPrev; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; - } - - if (!isspacechar(ch)) - visibleChars++; - } - - // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); -} - - - - -static const char * const texWordListDesc[] = { - "TeX, eTeX, pdfTeX, Omega", - "ConTeXt Dutch", - "ConTeXt English", - "ConTeXt German", - "ConTeXt Czech", - "ConTeXt Italian", - "ConTeXt Romanian", - 0, -} ; - -LexerModule lmTeX(SCLEX_TEX, ColouriseTeXDoc, "tex", FoldTexDoc, texWordListDesc); diff --git a/src/LexVB.cxx b/src/LexVB.cxx deleted file mode 100644 index c57a9ac49..000000000 --- a/src/LexVB.cxx +++ /dev/null @@ -1,316 +0,0 @@ -// Scintilla source code edit control -/** @file LexVB.cxx - ** Lexer for Visual Basic and VBScript. - **/ -// Copyright 1998-2005 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// Internal state, highlighted as number -#define SCE_B_FILENUMBER SCE_B_DEFAULT+100 - - -static bool IsVBComment(Accessor &styler, int pos, int len) { - return len > 0 && styler[pos] == '\''; -} - -static inline bool IsTypeCharacter(int ch) { - return ch == '%' || ch == '&' || ch == '@' || ch == '!' || ch == '#' || ch == '$'; -} - -// Extended to accept accented characters -static inline bool IsAWordChar(int ch) { - return ch >= 0x80 || - (isalnum(ch) || ch == '.' || ch == '_'); -} - -static inline bool IsAWordStart(int ch) { - return ch >= 0x80 || - (isalpha(ch) || ch == '_'); -} - -static inline bool IsANumberChar(int ch) { - // Not exactly following number definition (several dots are seen as OK, etc.) - // but probably enough in most cases. - return (ch < 0x80) && - (isdigit(ch) || toupper(ch) == 'E' || - ch == '.' || ch == '-' || ch == '+'); -} - -static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler, bool vbScriptSyntax) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - - styler.StartAt(startPos); - - int visibleChars = 0; - int fileNbDigits = 0; - - // Do not leak onto next line - if (initStyle == SCE_B_STRINGEOL || initStyle == SCE_B_COMMENT || initStyle == SCE_B_PREPROCESSOR) { - initStyle = SCE_B_DEFAULT; - } - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.state == SCE_B_OPERATOR) { - sc.SetState(SCE_B_DEFAULT); - } else if (sc.state == SCE_B_IDENTIFIER) { - if (!IsAWordChar(sc.ch)) { - // In Basic (except VBScript), a variable name or a function name - // can end with a special character indicating the type of the value - // held or returned. - bool skipType = false; - if (!vbScriptSyntax && IsTypeCharacter(sc.ch)) { - sc.Forward(); // Skip it - skipType = true; - } - if (sc.ch == ']') { - sc.Forward(); - } - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (skipType) { - s[strlen(s) - 1] = '\0'; - } - if (strcmp(s, "rem") == 0) { - sc.ChangeState(SCE_B_COMMENT); - } else { - if (keywords.InList(s)) { - sc.ChangeState(SCE_B_KEYWORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_B_KEYWORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_B_KEYWORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_B_KEYWORD4); - } // Else, it is really an identifier... - sc.SetState(SCE_B_DEFAULT); - } - } - } else if (sc.state == SCE_B_NUMBER) { - // We stop the number definition on non-numerical non-dot non-eE non-sign char - // Also accepts A-F for hex. numbers - if (!IsANumberChar(sc.ch) && !(tolower(sc.ch) >= 'a' && tolower(sc.ch) <= 'f')) { - sc.SetState(SCE_B_DEFAULT); - } - } else if (sc.state == SCE_B_STRING) { - // VB doubles quotes to preserve them, so just end this string - // state now as a following quote will start again - if (sc.ch == '\"') { - if (sc.chNext == '\"') { - sc.Forward(); - } else { - if (tolower(sc.chNext) == 'c') { - sc.Forward(); - } - sc.ForwardSetState(SCE_B_DEFAULT); - } - } else if (sc.atLineEnd) { - visibleChars = 0; - sc.ChangeState(SCE_B_STRINGEOL); - sc.ForwardSetState(SCE_B_DEFAULT); - } - } else if (sc.state == SCE_B_COMMENT) { - if (sc.atLineEnd) { - visibleChars = 0; - sc.ForwardSetState(SCE_B_DEFAULT); - } - } else if (sc.state == SCE_B_PREPROCESSOR) { - if (sc.atLineEnd) { - visibleChars = 0; - sc.ForwardSetState(SCE_B_DEFAULT); - } - } else if (sc.state == SCE_B_FILENUMBER) { - if (IsADigit(sc.ch)) { - fileNbDigits++; - if (fileNbDigits > 3) { - sc.ChangeState(SCE_B_DATE); - } - } else if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ',') { - // Regular uses: Close #1; Put #1, ...; Get #1, ... etc. - // Too bad if date is format #27, Oct, 2003# or something like that... - // Use regular number state - sc.ChangeState(SCE_B_NUMBER); - sc.SetState(SCE_B_DEFAULT); - } else if (sc.ch == '#') { - sc.ChangeState(SCE_B_DATE); - sc.ForwardSetState(SCE_B_DEFAULT); - } else { - sc.ChangeState(SCE_B_DATE); - } - if (sc.state != SCE_B_FILENUMBER) { - fileNbDigits = 0; - } - } else if (sc.state == SCE_B_DATE) { - if (sc.atLineEnd) { - visibleChars = 0; - sc.ChangeState(SCE_B_STRINGEOL); - sc.ForwardSetState(SCE_B_DEFAULT); - } else if (sc.ch == '#') { - sc.ForwardSetState(SCE_B_DEFAULT); - } - } - - if (sc.state == SCE_B_DEFAULT) { - if (sc.ch == '\'') { - sc.SetState(SCE_B_COMMENT); - } else if (sc.ch == '\"') { - sc.SetState(SCE_B_STRING); - } else if (sc.ch == '#' && visibleChars == 0) { - // Preprocessor commands are alone on their line - sc.SetState(SCE_B_PREPROCESSOR); - } else if (sc.ch == '#') { - // It can be a date literal, ending with #, or a file number, from 1 to 511 - // The date literal depends on the locale, so anything can go between #'s. - // Can be #January 1, 1993# or #1 Jan 93# or #05/11/2003#, etc. - // So we set the FILENUMBER state, and switch to DATE if it isn't a file number - sc.SetState(SCE_B_FILENUMBER); - } else if (sc.ch == '&' && tolower(sc.chNext) == 'h') { - // Hexadecimal number - sc.SetState(SCE_B_NUMBER); - sc.Forward(); - } else if (sc.ch == '&' && tolower(sc.chNext) == 'o') { - // Octal number - sc.SetState(SCE_B_NUMBER); - sc.Forward(); - } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_B_NUMBER); - } else if (IsAWordStart(sc.ch) || (sc.ch == '[')) { - sc.SetState(SCE_B_IDENTIFIER); - } else if (isoperator(static_cast(sc.ch)) || (sc.ch == '\\')) { // Integer division - sc.SetState(SCE_B_OPERATOR); - } - } - - if (sc.atLineEnd) { - visibleChars = 0; - } - if (!IsASpace(sc.ch)) { - visibleChars++; - } - } - - if (sc.state == SCE_B_IDENTIFIER && !IsAWordChar(sc.ch)) { - // In Basic (except VBScript), a variable name or a function name - // can end with a special character indicating the type of the value - // held or returned. - bool skipType = false; - if (!vbScriptSyntax && IsTypeCharacter(sc.ch)) { - sc.Forward(); // Skip it - skipType = true; - } - if (sc.ch == ']') { - sc.Forward(); - } - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (skipType) { - s[strlen(s) - 1] = '\0'; - } - if (strcmp(s, "rem") == 0) { - sc.ChangeState(SCE_B_COMMENT); - } else { - if (keywords.InList(s)) { - sc.ChangeState(SCE_B_KEYWORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_B_KEYWORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_B_KEYWORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_B_KEYWORD4); - } // Else, it is really an identifier... - sc.SetState(SCE_B_DEFAULT); - } - } - - sc.Complete(); -} - -static void FoldVBDoc(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) { - int endPos = startPos + length; - - // Backtrack to previous line in case need to fix its fold status - int lineCurrent = styler.GetLine(startPos); - if (startPos > 0) { - if (lineCurrent > 0) { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); - } - } - int spaceFlags = 0; - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsVBComment); - char chNext = styler[startPos]; - for (int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { - int lev = indentCurrent; - int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsVBComment); - if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { - // Only non whitespace lines can be headers - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { - // Line after is blank so check the next - maybe should continue further? - int spaceFlags2 = 0; - int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsVBComment); - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - } - } - indentCurrent = indentNext; - styler.SetLevel(lineCurrent, lev); - lineCurrent++; - } - } -} - -static void ColouriseVBNetDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - ColouriseVBDoc(startPos, length, initStyle, keywordlists, styler, false); -} - -static void ColouriseVBScriptDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - ColouriseVBDoc(startPos, length, initStyle, keywordlists, styler, true); -} - -static const char * const vbWordListDesc[] = { - "Keywords", - "user1", - "user2", - "user3", - 0 -}; - -LexerModule lmVB(SCLEX_VB, ColouriseVBNetDoc, "vb", FoldVBDoc, vbWordListDesc); -LexerModule lmVBScript(SCLEX_VBSCRIPT, ColouriseVBScriptDoc, "vbscript", FoldVBDoc, vbWordListDesc); - diff --git a/src/LexVHDL.cxx b/src/LexVHDL.cxx deleted file mode 100644 index c0733ab82..000000000 --- a/src/LexVHDL.cxx +++ /dev/null @@ -1,476 +0,0 @@ -// Scintilla source code edit control -/** @file LexVHDL.cxx - ** Lexer for VHDL - ** Written by Phil Reid, - ** Based on: - ** - The Verilog Lexer by Avi Yegudin - ** - The Fortran Lexer by Chuan-jian Shen - ** - The C++ lexer by Neil Hodgson - **/ -// Copyright 1998-2002 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static void ColouriseVHDLDoc( - unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler); - - -/***************************************/ -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' ); -} - -/***************************************/ -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -/***************************************/ -inline bool IsABlank(unsigned int ch) { - return (ch == ' ') || (ch == 0x09) || (ch == 0x0b) ; -} - -/***************************************/ -static void ColouriseVHDLDoc( - unsigned int startPos, - int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) -{ - WordList &Keywords = *keywordlists[0]; - WordList &Operators = *keywordlists[1]; - WordList &Attributes = *keywordlists[2]; - WordList &Functions = *keywordlists[3]; - WordList &Packages = *keywordlists[4]; - WordList &Types = *keywordlists[5]; - WordList &User = *keywordlists[6]; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) - { - - // Determine if the current state should terminate. - if (sc.state == SCE_VHDL_OPERATOR) { - sc.SetState(SCE_VHDL_DEFAULT); - } else if (sc.state == SCE_VHDL_NUMBER) { - if (!IsAWordChar(sc.ch) && (sc.ch != '#')) { - sc.SetState(SCE_VHDL_DEFAULT); - } - } else if (sc.state == SCE_VHDL_IDENTIFIER) { - if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (Keywords.InList(s)) { - sc.ChangeState(SCE_VHDL_KEYWORD); - } else if (Operators.InList(s)) { - sc.ChangeState(SCE_VHDL_STDOPERATOR); - } else if (Attributes.InList(s)) { - sc.ChangeState(SCE_VHDL_ATTRIBUTE); - } else if (Functions.InList(s)) { - sc.ChangeState(SCE_VHDL_STDFUNCTION); - } else if (Packages.InList(s)) { - sc.ChangeState(SCE_VHDL_STDPACKAGE); - } else if (Types.InList(s)) { - sc.ChangeState(SCE_VHDL_STDTYPE); - } else if (User.InList(s)) { - sc.ChangeState(SCE_VHDL_USERWORD); - } - sc.SetState(SCE_VHDL_DEFAULT); - } - } else if (sc.state == SCE_VHDL_COMMENT || sc.state == SCE_V_COMMENTLINEBANG) { - if (sc.atLineEnd) { - sc.SetState(SCE_VHDL_DEFAULT); - } - } else if (sc.state == SCE_VHDL_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_VHDL_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_V_STRINGEOL); - sc.ForwardSetState(SCE_VHDL_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_VHDL_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_VHDL_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_VHDL_IDENTIFIER); - } else if (sc.Match('-', '-')) { - sc.SetState(SCE_VHDL_COMMENT); - sc.Forward(); - } else if (sc.Match('-', '-')) { - if (sc.Match("--!")) // Nice to have a different comment style - sc.SetState(SCE_VHDL_COMMENTLINEBANG); - else - sc.SetState(SCE_VHDL_COMMENT); - } else if (sc.ch == '\"') { - sc.SetState(SCE_VHDL_STRING); - } else if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_VHDL_OPERATOR); - } - } - } - sc.Complete(); -} -//============================================================================= -static bool IsCommentLine(int line, Accessor &styler) { - int pos = styler.LineStart(line); - int eol_pos = styler.LineStart(line + 1) - 1; - for (int i = pos; i < eol_pos; i++) { - char ch = styler[i]; - char chNext = styler[i+1]; - if ((ch == '-') && (chNext == '-')) - return true; - else if (ch != ' ' && ch != '\t') - return false; - } - return false; -} - -//============================================================================= -// Folding the code -static void FoldNoBoxVHDLDoc( - unsigned int startPos, - int length, - int, - Accessor &styler) -{ - // Decided it would be smarter to have the lexer have all keywords included. Therefore I - // don't check if the style for the keywords that I use to adjust the levels. - char words[] = - "architecture begin case component else elsif end entity generate loop package process record then " - "procedure function when"; - WordList keywords; - keywords.Set(words); - - bool foldComment = styler.GetPropertyInt("fold.comment", 1) != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldAtElse = styler.GetPropertyInt("fold.at.else", 1) != 0; - bool foldAtBegin = styler.GetPropertyInt("fold.at.Begin", 1) != 0; - bool foldAtParenthese = styler.GetPropertyInt("fold.at.Parenthese", 1) != 0; - //bool foldAtWhen = styler.GetPropertyInt("fold.at.When", 1) != 0; //< fold at when in case statements - - int visibleChars = 0; - unsigned int endPos = startPos + length; - - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if(lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - //int levelMinCurrent = levelCurrent; - int levelMinCurrentElse = levelCurrent; //< Used for folding at 'else' - int levelMinCurrentBegin = levelCurrent; //< Used for folding at 'begin' - int levelNext = levelCurrent; - - /***************************************/ - int lastStart = 0; - char prevWord[32] = ""; - - /***************************************/ - // Find prev word - // The logic for going up or down a level depends on a the previous keyword - // This code could be cleaned up. - int end = 0; - unsigned int j; - for(j = startPos; j>0; j--) - { - char ch = styler.SafeGetCharAt(j); - char chPrev = styler.SafeGetCharAt(j-1); - int style = styler.StyleAt(j); - int stylePrev = styler.StyleAt(j-1); - if ((stylePrev != SCE_VHDL_COMMENT) && (stylePrev != SCE_VHDL_STRING)) - { - if(IsAWordChar(chPrev) && !IsAWordChar(ch)) - { - end = j-1; - } - } - if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING)) - { - if(!IsAWordChar(chPrev) && IsAWordStart(ch) && (end != 0)) - { - char s[32]; - unsigned int k; - for(k=0; (k<31 ) && (k(tolower(styler[j+k])); - } - s[k] = '\0'; - - if(keywords.InList(s)) { - strcpy(prevWord, s); - break; - } - } - } - } - for(j=j+strlen(prevWord); j(tolower(styler[lastStart+k])); - } - s[k] = '\0'; - - if(keywords.InList(s)) - { - if ( - strcmp(s, "architecture") == 0 || - strcmp(s, "case") == 0 || - strcmp(s, "component") == 0 || - strcmp(s, "entity") == 0 || - strcmp(s, "generate") == 0 || - strcmp(s, "loop") == 0 || - strcmp(s, "package") ==0 || - strcmp(s, "process") == 0 || - strcmp(s, "record") == 0 || - strcmp(s, "then") == 0) - { - if (strcmp(prevWord, "end") != 0) - { - if (levelMinCurrentElse > levelNext) { - levelMinCurrentElse = levelNext; - } - levelNext++; - } - } else if ( - strcmp(s, "procedure") == 0 || - strcmp(s, "function") == 0) - { - if (strcmp(prevWord, "end") != 0) // check for "end procedure" etc. - { // This code checks to see if the procedure / function is a definition within a "package" - // rather than the actual code in the body. - int BracketLevel = 0; - for(int j=i+1; j levelNext) { - levelMinCurrentElse = levelNext; - } - levelNext++; - break; - } - if((BracketLevel == 0) && (LocalCh == ';')) - { - break; - } - } - } - - } else if (strcmp(s, "end") == 0) { - levelNext--; - } else if(strcmp(s, "elsif") == 0) { // elsif is followed by then so folding occurs correctly - levelNext--; - } else if (strcmp(s, "else") == 0) { - if(strcmp(prevWord, "when") != 0) // ignore a <= x when y else z; - { - levelMinCurrentElse = levelNext - 1; // VHDL else is all on its own so just dec. the min level - } - } else if( - ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "architecture") == 0)) || - ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "function") == 0)) || - ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "procedure") == 0))) - { - levelMinCurrentBegin = levelNext - 1; - } - //Platform::DebugPrintf("Line[%04d] Prev[%20s] Cur[%20s] Level[%x]\n", lineCurrent+1, prevWord, s, levelCurrent); - strcpy(prevWord, s); - } - } - } - if (atEOL) { - int levelUse = levelCurrent; - - if (foldAtElse && (levelMinCurrentElse < levelUse)) { - levelUse = levelMinCurrentElse; - } - if (foldAtBegin && (levelMinCurrentBegin < levelUse)) { - levelUse = levelMinCurrentBegin; - } - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - //Platform::DebugPrintf("Line[%04d] ---------------------------------------------------- Level[%x]\n", lineCurrent+1, levelCurrent); - lineCurrent++; - levelCurrent = levelNext; - //levelMinCurrent = levelCurrent; - levelMinCurrentElse = levelCurrent; - levelMinCurrentBegin = levelCurrent; - visibleChars = 0; - } - /***************************************/ - if (!isspacechar(ch)) visibleChars++; - } - - /***************************************/ -// Platform::DebugPrintf("Line[%04d] ---------------------------------------------------- Level[%x]\n", lineCurrent+1, levelCurrent); -} - -//============================================================================= -static void FoldVHDLDoc(unsigned int startPos, int length, int initStyle, WordList *[], - Accessor &styler) { - FoldNoBoxVHDLDoc(startPos, length, initStyle, styler); -} - -//============================================================================= -static const char * const VHDLWordLists[] = { - "Keywords", - "Operators", - "Attributes", - "Standard Functions", - "Standard Packages", - "Standard Types", - "User Words", - 0, - }; - - -LexerModule lmVHDL(SCLEX_VHDL, ColouriseVHDLDoc, "vhdl", FoldVHDLDoc, VHDLWordLists); - - -// Keyword: -// access after alias all architecture array assert attribute begin block body buffer bus case component -// configuration constant disconnect downto else elsif end entity exit file for function generate generic -// group guarded if impure in inertial inout is label library linkage literal loop map new next null of -// on open others out package port postponed procedure process pure range record register reject report -// return select severity shared signal subtype then to transport type unaffected units until use variable -// wait when while with -// -// Operators: -// abs and mod nand nor not or rem rol ror sla sll sra srl xnor xor -// -// Attributes: -// left right low high ascending image value pos val succ pred leftof rightof base range reverse_range -// length delayed stable quiet transaction event active last_event last_active last_value driving -// driving_value simple_name path_name instance_name -// -// Std Functions: -// now readline read writeline write endfile resolved to_bit to_bitvector to_stdulogic to_stdlogicvector -// to_stdulogicvector to_x01 to_x01z to_UX01 rising_edge falling_edge is_x shift_left shift_right rotate_left -// rotate_right resize to_integer to_unsigned to_signed std_match to_01 -// -// Std Packages: -// std ieee work standard textio std_logic_1164 std_logic_arith std_logic_misc std_logic_signed -// std_logic_textio std_logic_unsigned numeric_bit numeric_std math_complex math_real vital_primitives -// vital_timing -// -// Std Types: -// boolean bit character severity_level integer real time delay_length natural positive string bit_vector -// file_open_kind file_open_status line text side width std_ulogic std_ulogic_vector std_logic -// std_logic_vector X01 X01Z UX01 UX01Z unsigned signed -// - diff --git a/src/LexVerilog.cxx b/src/LexVerilog.cxx deleted file mode 100644 index 8b531bb7e..000000000 --- a/src/LexVerilog.cxx +++ /dev/null @@ -1,330 +0,0 @@ -// Scintilla source code edit control -/** @file LexVerilog.cxx - ** Lexer for Verilog. - ** Written by Avi Yegudin, based on C++ lexer by Neil Hodgson - **/ -// Copyright 1998-2002 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '$'); -} - -static void ColouriseVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - - // Do not leak onto next line - if (initStyle == SCE_V_STRINGEOL) - initStyle = SCE_V_DEFAULT; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.atLineStart && (sc.state == SCE_V_STRING)) { - // Prevent SCE_V_STRINGEOL from leaking back to previous line - sc.SetState(SCE_V_STRING); - } - - // Handle line continuation generically. - if (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_V_OPERATOR) { - sc.SetState(SCE_V_DEFAULT); - } else if (sc.state == SCE_V_NUMBER) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_V_DEFAULT); - } - } else if (sc.state == SCE_V_IDENTIFIER) { - if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(SCE_V_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_V_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_V_WORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_V_USER); - } - sc.SetState(SCE_V_DEFAULT); - } - } else if (sc.state == SCE_V_PREPROCESSOR) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_V_DEFAULT); - } - } else if (sc.state == SCE_V_COMMENT) { - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_V_DEFAULT); - } - } else if (sc.state == SCE_V_COMMENTLINE || sc.state == SCE_V_COMMENTLINEBANG) { - if (sc.atLineStart) { - sc.SetState(SCE_V_DEFAULT); - } - } else if (sc.state == SCE_V_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_V_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_V_STRINGEOL); - sc.ForwardSetState(SCE_V_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_V_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '\'') || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_V_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_V_IDENTIFIER); - } else if (sc.Match('/', '*')) { - sc.SetState(SCE_V_COMMENT); - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match('/', '/')) { - if (sc.Match("//!")) // Nice to have a different comment style - sc.SetState(SCE_V_COMMENTLINEBANG); - else - sc.SetState(SCE_V_COMMENTLINE); - } else if (sc.ch == '\"') { - sc.SetState(SCE_V_STRING); - } else if (sc.ch == '`') { - sc.SetState(SCE_V_PREPROCESSOR); - // Skip whitespace between ` and preprocessor word - do { - sc.Forward(); - } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); - if (sc.atLineEnd) { - sc.SetState(SCE_V_DEFAULT); - } - } else if (isoperator(static_cast(sc.ch)) || sc.ch == '@' || sc.ch == '#') { - sc.SetState(SCE_V_OPERATOR); - } - } - } - sc.Complete(); -} - -static bool IsStreamCommentStyle(int style) { - return style == SCE_V_COMMENT; -} - -static bool IsCommentLine(int line, Accessor &styler) { - int pos = styler.LineStart(line); - int eolPos = styler.LineStart(line + 1) - 1; - for (int i = pos; i < eolPos; i++) { - char ch = styler[i]; - char chNext = styler.SafeGetCharAt(i + 1); - int style = styler.StyleAt(i); - if (ch == '/' && chNext == '/' && - (style == SCE_V_COMMENTLINE || style == SCE_V_COMMENTLINEBANG)) { - return true; - } else if (!IsASpaceOrTab(ch)) { - return false; - } - } - return false; -} -// Store both the current line's fold level and the next lines in the -// level store to make it easy to pick up with each increment -// and to make it possible to fiddle the current level for "} else {". -static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle, - Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; - // Verilog specific folding options: - // fold_at_module - - // Generally used methodology in verilog code is - // one module per file, so folding at module definition is useless. - // fold_at_brace/parenthese - - // Folding of long port lists can be convenient. - bool foldAtModule = styler.GetPropertyInt("fold.verilog.flags", 0) != 0; - bool foldAtBrace = 1; - bool foldAtParenthese = 1; - - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelMinCurrent = levelCurrent; - int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && IsStreamCommentStyle(style)) { - if (!IsStreamCommentStyle(stylePrev)) { - levelNext++; - } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelNext--; - } - } - if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) - { - if (!IsCommentLine(lineCurrent - 1, styler) - && IsCommentLine(lineCurrent + 1, styler)) - levelNext++; - else if (IsCommentLine(lineCurrent - 1, styler) - && !IsCommentLine(lineCurrent+1, styler)) - levelNext--; - } - if (foldComment && (style == SCE_V_COMMENTLINE)) { - if ((ch == '/') && (chNext == '/')) { - char chNext2 = styler.SafeGetCharAt(i + 2); - if (chNext2 == '{') { - levelNext++; - } else if (chNext2 == '}') { - levelNext--; - } - } - } - if (foldPreprocessor && (style == SCE_V_PREPROCESSOR)) { - if (ch == '`') { - unsigned int j = i + 1; - while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { - j++; - } - if (styler.Match(j, "if")) { - levelNext++; - } else if (styler.Match(j, "end")) { - levelNext--; - } - } - } - if (style == SCE_V_OPERATOR) { - if (foldAtParenthese) { - if (ch == '(') { - levelNext++; - } else if (ch == ')') { - levelNext--; - } - } - } - if (style == SCE_V_OPERATOR) { - if (foldAtBrace) { - if (ch == '{') { - levelNext++; - } else if (ch == '}') { - levelNext--; - } - } - } - if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) { - unsigned int j = i; - if (styler.Match(j, "case") || - styler.Match(j, "casex") || - styler.Match(j, "casez") || - styler.Match(j, "function") || - styler.Match(j, "fork") || - styler.Match(j, "table") || - styler.Match(j, "task") || - styler.Match(j, "generate") || - styler.Match(j, "specify") || - styler.Match(j, "primitive") || - (styler.Match(j, "module") && foldAtModule) || - styler.Match(j, "begin")) { - levelNext++; - } else if (styler.Match(j, "endcase") || - styler.Match(j, "endfunction") || - styler.Match(j, "join") || - styler.Match(j, "endtask") || - styler.Match(j, "endgenerate") || - styler.Match(j, "endtable") || - styler.Match(j, "endspecify") || - styler.Match(j, "endprimitive") || - (styler.Match(j, "endmodule") && foldAtModule) || - (styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j+3)))) { - levelNext--; - } - } - if (atEOL) { - int levelUse = levelCurrent; - if (foldAtElse) { - levelUse = levelMinCurrent; - } - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - levelMinCurrent = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } -} - -static void FoldVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *[], - Accessor &styler) { - FoldNoBoxVerilogDoc(startPos, length, initStyle, styler); -} - -static const char * const verilogWordLists[] = { - "Primary keywords and identifiers", - "Secondary keywords and identifiers", - "System Tasks", - "User defined tasks and identifiers", - "Unused", - 0, - }; - - -LexerModule lmVerilog(SCLEX_VERILOG, ColouriseVerilogDoc, "verilog", FoldVerilogDoc, verilogWordLists); diff --git a/src/LexYAML.cxx b/src/LexYAML.cxx deleted file mode 100644 index 99f34da88..000000000 --- a/src/LexYAML.cxx +++ /dev/null @@ -1,314 +0,0 @@ -// Scintilla source code edit control -/** @file LexYAML.cxx - ** Lexer for YAML. - **/ -// Copyright 2003- by Sean O'Dell -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static const char * const yamlWordListDesc[] = { - "Keywords", - 0 -}; - -static inline bool AtEOL(Accessor &styler, unsigned int i) { - return (styler[i] == '\n') || - ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); -} - -static unsigned int SpaceCount(char* lineBuffer) { - if (lineBuffer == NULL) - return 0; - - char* headBuffer = lineBuffer; - - while (*headBuffer == ' ') - headBuffer++; - - return headBuffer - lineBuffer; -} - -#define YAML_STATE_BITSIZE 16 -#define YAML_STATE_MASK (0xFFFF0000) -#define YAML_STATE_DOCUMENT (1 << YAML_STATE_BITSIZE) -#define YAML_STATE_VALUE (2 << YAML_STATE_BITSIZE) -#define YAML_STATE_COMMENT (3 << YAML_STATE_BITSIZE) -#define YAML_STATE_TEXT_PARENT (4 << YAML_STATE_BITSIZE) -#define YAML_STATE_TEXT (5 << YAML_STATE_BITSIZE) - -static void ColouriseYAMLLine( - char *lineBuffer, - unsigned int currentLine, - unsigned int lengthLine, - unsigned int startLine, - unsigned int endPos, - WordList &keywords, - Accessor &styler) { - - unsigned int i = 0; - bool bInQuotes = false; - unsigned int indentAmount = SpaceCount(lineBuffer); - - if (currentLine > 0) { - int parentLineState = styler.GetLineState(currentLine - 1); - - if ((parentLineState&YAML_STATE_MASK) == YAML_STATE_TEXT || (parentLineState&YAML_STATE_MASK) == YAML_STATE_TEXT_PARENT) { - unsigned int parentIndentAmount = parentLineState&(~YAML_STATE_MASK); - if (indentAmount > parentIndentAmount) { - styler.SetLineState(currentLine, YAML_STATE_TEXT | parentIndentAmount); - styler.ColourTo(endPos, SCE_YAML_TEXT); - return; - } - } - } - styler.SetLineState(currentLine, 0); - if (strncmp(lineBuffer, "---", 3) == 0) { // Document marker - styler.SetLineState(currentLine, YAML_STATE_DOCUMENT); - styler.ColourTo(endPos, SCE_YAML_DOCUMENT); - return; - } - // Skip initial spaces - while ((i < lengthLine) && lineBuffer[i] == ' ') { // YAML always uses space, never TABS or anything else - i++; - } - if (lineBuffer[i] == '\t') { // if we skipped all spaces, and we are NOT inside a text block, this is wrong - styler.ColourTo(endPos, SCE_YAML_ERROR); - return; - } - if (lineBuffer[i] == '#') { // Comment - styler.SetLineState(currentLine, YAML_STATE_COMMENT); - styler.ColourTo(endPos, SCE_YAML_COMMENT); - return; - } - while (i < lengthLine) { - if (lineBuffer[i] == '\'' || lineBuffer[i] == '\"') { - bInQuotes = !bInQuotes; - } else if (lineBuffer[i] == ':' && !bInQuotes) { - styler.ColourTo(startLine + i - 1, SCE_YAML_IDENTIFIER); - styler.ColourTo(startLine + i, SCE_YAML_OPERATOR); - // Non-folding scalar - i++; - while ((i < lengthLine) && isspacechar(lineBuffer[i])) - i++; - unsigned int endValue = lengthLine - 1; - while ((endValue >= i) && isspacechar(lineBuffer[endValue])) - endValue--; - lineBuffer[endValue + 1] = '\0'; - if (lineBuffer[i] == '|' || lineBuffer[i] == '>') { - i++; - if (lineBuffer[i] == '+' || lineBuffer[i] == '-') - i++; - while ((i < lengthLine) && isspacechar(lineBuffer[i])) - i++; - if (lineBuffer[i] == '\0') { - styler.SetLineState(currentLine, YAML_STATE_TEXT_PARENT | indentAmount); - styler.ColourTo(endPos, SCE_YAML_DEFAULT); - return; - } else if (lineBuffer[i] == '#') { - styler.SetLineState(currentLine, YAML_STATE_TEXT_PARENT | indentAmount); - styler.ColourTo(startLine + i - 1, SCE_YAML_DEFAULT); - styler.ColourTo(endPos, SCE_YAML_COMMENT); - return; - } else { - styler.ColourTo(endPos, SCE_YAML_ERROR); - return; - } - } else if (lineBuffer[i] == '#') { - styler.ColourTo(startLine + i - 1, SCE_YAML_DEFAULT); - styler.ColourTo(endPos, SCE_YAML_COMMENT); - return; - } - styler.SetLineState(currentLine, YAML_STATE_VALUE); - if (lineBuffer[i] == '&' || lineBuffer[i] == '*') { - styler.ColourTo(endPos, SCE_YAML_REFERENCE); - return; - } - if (keywords.InList(&lineBuffer[i])) { // Convertible value (true/false, etc.) - styler.ColourTo(endPos, SCE_YAML_KEYWORD); - return; - } else { - unsigned int i2 = i; - while ((i < lengthLine) && lineBuffer[i]) { - if (!(isascii(lineBuffer[i]) && isdigit(lineBuffer[i])) && lineBuffer[i] != '-' && lineBuffer[i] != '.' && lineBuffer[i] != ',') { - styler.ColourTo(endPos, SCE_YAML_DEFAULT); - return; - } - i++; - } - if (i > i2) { - styler.ColourTo(endPos, SCE_YAML_NUMBER); - return; - } - } - break; // shouldn't get here, but just in case, the rest of the line is coloured the default - } - i++; - } - styler.ColourTo(endPos, SCE_YAML_DEFAULT); -} - -static void ColouriseYAMLDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) { - char lineBuffer[1024]; - styler.StartAt(startPos); - styler.StartSegment(startPos); - unsigned int linePos = 0; - unsigned int startLine = startPos; - unsigned int endPos = startPos + length; - unsigned int maxPos = styler.Length(); - unsigned int lineCurrent = styler.GetLine(startPos); - - for (unsigned int i = startPos; i < maxPos && i < endPos; i++) { - lineBuffer[linePos++] = styler[i]; - if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { - // End of line (or of line buffer) met, colourise it - lineBuffer[linePos] = '\0'; - ColouriseYAMLLine(lineBuffer, lineCurrent, linePos, startLine, i, *keywordLists[0], styler); - linePos = 0; - startLine = i + 1; - lineCurrent++; - } - } - if (linePos > 0) { // Last line does not have ending characters - ColouriseYAMLLine(lineBuffer, lineCurrent, linePos, startLine, startPos + length - 1, *keywordLists[0], styler); - } -} - -static bool IsCommentLine(int line, Accessor &styler) { - int pos = styler.LineStart(line); - if (styler[pos] == '#') - return true; - return false; -} - -static void FoldYAMLDoc(unsigned int startPos, int length, int /*initStyle - unused*/, - WordList *[], Accessor &styler) { - const int maxPos = startPos + length; - const int maxLines = styler.GetLine(maxPos - 1); // Requested last line - const int docLines = styler.GetLine(styler.Length() - 1); // Available last line - const bool foldComment = styler.GetPropertyInt("fold.comment.yaml") != 0; - - // Backtrack to previous non-blank line so we can determine indent level - // for any white space lines - // and so we can fix any preceding fold level (which is why we go back - // at least one line in all cases) - int spaceFlags = 0; - int lineCurrent = styler.GetLine(startPos); - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); - while (lineCurrent > 0) { - lineCurrent--; - indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); - if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) && - (!IsCommentLine(lineCurrent, styler))) - break; - } - int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; - - // Set up initial loop state - int prevComment = 0; - if (lineCurrent >= 1) - prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler); - - // Process all characters to end of requested range - // or comment that hangs over the end of the range. Cap processing in all cases - // to end of document (in case of unclosed comment at end). - while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevComment)) { - - // Gather info - int lev = indentCurrent; - int lineNext = lineCurrent + 1; - int indentNext = indentCurrent; - if (lineNext <= docLines) { - // Information about next line is only available if not at end of document - indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); - } - const int comment = foldComment && IsCommentLine(lineCurrent, styler); - const int comment_start = (comment && !prevComment && (lineNext <= docLines) && - IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE)); - const int comment_continue = (comment && prevComment); - if (!comment) - indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; - if (indentNext & SC_FOLDLEVELWHITEFLAG) - indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel; - - if (comment_start) { - // Place fold point at start of a block of comments - lev |= SC_FOLDLEVELHEADERFLAG; - } else if (comment_continue) { - // Add level to rest of lines in the block - lev = lev + 1; - } - - // Skip past any blank lines for next indent level info; we skip also - // comments (all comments, not just those starting in column 0) - // which effectively folds them into surrounding code rather - // than screwing up folding. - - while ((lineNext < docLines) && - ((indentNext & SC_FOLDLEVELWHITEFLAG) || - (lineNext <= docLines && IsCommentLine(lineNext, styler)))) { - - lineNext++; - indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); - } - - const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK; - const int levelBeforeComments = Platform::Maximum(indentCurrentLevel,levelAfterComments); - - // Now set all the indent levels on the lines we skipped - // Do this from end to start. Once we encounter one line - // which is indented more than the line after the end of - // the comment-block, use the level of the block before - - int skipLine = lineNext; - int skipLevel = levelAfterComments; - - while (--skipLine > lineCurrent) { - int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL); - - if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments) - skipLevel = levelBeforeComments; - - int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG; - - styler.SetLevel(skipLine, skipLevel | whiteFlag); - } - - // Set fold header on non-comment line - if (!comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG) ) { - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) - lev |= SC_FOLDLEVELHEADERFLAG; - } - - // Keep track of block comment state of previous line - prevComment = comment_start || comment_continue; - - // Set fold level for this line and move to next line - styler.SetLevel(lineCurrent, lev); - indentCurrent = indentNext; - lineCurrent = lineNext; - } - - // NOTE: Cannot set level of last line here because indentCurrent doesn't have - // header flag set; the loop above is crafted to take care of this case! - //styler.SetLevel(lineCurrent, indentCurrent); -} - -LexerModule lmYAML(SCLEX_YAML, ColouriseYAMLDoc, "yaml", FoldYAMLDoc, yamlWordListDesc); -- cgit v1.2.3