diff options
| author | Jad Altahan <xviyy@aol.com> | 2018-11-21 19:39:33 +1100 | 
|---|---|---|
| committer | Jad Altahan <xviyy@aol.com> | 2018-11-21 19:39:33 +1100 | 
| commit | a48306f317a02679b1b17f846733bc5148dc7a82 (patch) | |
| tree | 7e8bda2e6e13cbcc7f04e205018f21ce4cf6a84d | |
| parent | f6b876ef1f4c1621dc4822ace7673e45dd30ea0b (diff) | |
| download | scintilla-mirror-a48306f317a02679b1b17f846733bc5148dc7a82.tar.gz | |
Backport: Feature [feature-requests:#1242]. Add lexer for Nim
Backport of changeset 7173:3e6cf75864cc.
| -rw-r--r-- | cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj | 6 | ||||
| -rw-r--r-- | doc/ScintillaHistory.html | 8 | ||||
| -rw-r--r-- | include/SciLexer.h | 18 | ||||
| -rw-r--r-- | include/Scintilla.iface | 20 | ||||
| -rw-r--r-- | lexers/LexNim.cxx | 701 | ||||
| -rw-r--r-- | src/Catalogue.cxx | 1 | ||||
| -rw-r--r-- | win32/scintilla.mak | 3 | 
7 files changed, 756 insertions, 1 deletions
| diff --git a/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj b/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj index 80199d6c8..fc816550e 100644 --- a/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj +++ b/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj @@ -228,7 +228,8 @@  		8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };  		F437405F9F32C7DEFCA38C11 /* LexIndent.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 282E41F3B9E2BFEDD6A05BE7 /* LexIndent.cxx */; };  		FDC7442CAD70B9A67EF1639D /* LexSAS.cxx in Sources */ = {isa = PBXBuildFile; fileRef = A95147A1AB7CADB00DAFE724 /* LexSAS.cxx */; }; -		5F804AA6B60FE695863A39FE /* LexStata.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7623427695416AB1270EE023 /* LexStata.cxx +		5F804AA6B60FE695863A39FE /* LexStata.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7623427695416AB1270EE023 /* LexStata.cxx */; }; +		0ED84236A703D57578EBFD2F /* LexNim.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 47814937A6B72D2B0F065B61 /* LexNim.cxx */; };   		4D0C4365AB6DF998CD48B1FC /* LexLPeg.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 5EB3467789767C0ACE40A46A /* LexLPeg.cxx */; }; */; };  /* End PBXBuildFile section */ @@ -462,6 +463,7 @@  		D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };  		A95147A1AB7CADB00DAFE724 /* LexSAS.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexSAS.cxx; path = ../../lexers/LexSAS.cxx; sourceTree = SOURCE_ROOT; };  		7623427695416AB1270EE023 /* LexStata.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexStata.cxx; path = ../../lexers/LexStata.cxx; sourceTree = SOURCE_ROOT; }; +		47814937A6B72D2B0F065B61 /* LexNim.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexNim.cxx; path = ../../lexers/LexNim.cxx; sourceTree = SOURCE_ROOT; };  		5EB3467789767C0ACE40A46A /* LexLPeg.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexLPeg.cxx; path = ../../lexers/LexLPeg.cxx; sourceTree = SOURCE_ROOT; };  /* End PBXFileReference section */ @@ -625,6 +627,7 @@  				114B6EE811FA7526004FB6AB /* LexMPT.cxx */,  				114B6EE911FA7526004FB6AB /* LexMSSQL.cxx */,  				114B6EEA11FA7526004FB6AB /* LexMySQL.cxx */, +				47814937A6B72D2B0F065B61 /* LexNim.cxx */,  				114B6EEB11FA7526004FB6AB /* LexNimrod.cxx */,  				114B6EEC11FA7526004FB6AB /* LexNsis.cxx */,  				28B6470A1B54C0720009DC49 /* LexNull.cxx */, @@ -1124,6 +1127,7 @@  				3D994BD7A5EAC4FA5B3CFBDF /* LexMaxima.cxx in Sources */,  				FDC7442CAD70B9A67EF1639D /* LexSAS.cxx in Sources */,  				5F804AA6B60FE695863A39FE /* LexStata.cxx in Sources */, +				0ED84236A703D57578EBFD2F /* LexNim.cxx in Sources */,  			);  			runOnlyForDeploymentPostprocessing = 0;  		}; diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index 8b6a1d43c..0f70a53e4 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -528,6 +528,8 @@        </tr><tr>  	<td>maboroshin</td>  	<td>Gokul Krishnan</td> +      </tr><tr> +	<td>Jad Altahan</td>      </tr>      </table>      <p> @@ -546,6 +548,12 @@  	<li>  	Released 31 October 2018.  	</li> + 	<li> +	Added "nim" lexer (SCLEX_NIM) for the Nim language which was previously called Nimrod. +	For compatibility, the old "nimrod" lexer is still present but is deprecated and will be removed at the +	next major version. +	<a href="https://sourceforge.net/p/scintilla/feature-requests/1242/">Feature #1242.</a> +	</li>  	<li>  	On Cocoa, fix a crash that occurred when entering a dead key diacritic then a character  	that can not take that diacritic, such as option+e (acute accent) followed by g. diff --git a/include/SciLexer.h b/include/SciLexer.h index 0335bf4dd..4613e48de 100644 --- a/include/SciLexer.h +++ b/include/SciLexer.h @@ -138,6 +138,7 @@  #define SCLEX_MAXIMA 123  #define SCLEX_STATA 124  #define SCLEX_SAS 125 +#define SCLEX_NIM 126  #define SCLEX_LPEG 999  #define SCLEX_AUTOMATIC 1000  #define SCE_P_DEFAULT 0 @@ -1856,6 +1857,23 @@  #define SCE_SAS_BLOCK_KEYWORD 13  #define SCE_SAS_MACRO_FUNCTION 14  #define SCE_SAS_STATEMENT 15 +#define SCE_NIM_DEFAULT 0 +#define SCE_NIM_COMMENT 1 +#define SCE_NIM_COMMENTDOC 2 +#define SCE_NIM_COMMENTLINE 3 +#define SCE_NIM_COMMENTLINEDOC 4 +#define SCE_NIM_NUMBER 5 +#define SCE_NIM_STRING 6 +#define SCE_NIM_CHARACTER 7 +#define SCE_NIM_WORD 8 +#define SCE_NIM_TRIPLE 9 +#define SCE_NIM_TRIPLEDOUBLE 10 +#define SCE_NIM_BACKTICKS 11 +#define SCE_NIM_FUNCNAME 12 +#define SCE_NIM_STRINGEOL 13 +#define SCE_NIM_NUMERROR 14 +#define SCE_NIM_OPERATOR 15 +#define SCE_NIM_IDENTIFIER 16  /* --Autogenerated -- end of section automatically generated from Scintilla.iface */  #endif diff --git a/include/Scintilla.iface b/include/Scintilla.iface index 0281f92f5..7cbb20020 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -2955,6 +2955,7 @@ val SCLEX_INDENT=122  val SCLEX_MAXIMA=123  val SCLEX_STATA=124  val SCLEX_SAS=125 +val SCLEX_NIM=126  val SCLEX_LPEG=999  # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a @@ -4909,6 +4910,25 @@ val SCE_SAS_MACRO_KEYWORD=12  val SCE_SAS_BLOCK_KEYWORD=13  val SCE_SAS_MACRO_FUNCTION=14  val SCE_SAS_STATEMENT=15 +# Lexical states for SCLEX_NIM  +lex Nim=SCLEX_NIM SCE_NIM_ +val SCE_NIM_DEFAULT=0 +val SCE_NIM_COMMENT=1 +val SCE_NIM_COMMENTDOC=2 +val SCE_NIM_COMMENTLINE=3 +val SCE_NIM_COMMENTLINEDOC=4 +val SCE_NIM_NUMBER=5 +val SCE_NIM_STRING=6 +val SCE_NIM_CHARACTER=7 +val SCE_NIM_WORD=8 +val SCE_NIM_TRIPLE=9 +val SCE_NIM_TRIPLEDOUBLE=10 +val SCE_NIM_BACKTICKS=11 +val SCE_NIM_FUNCNAME=12 +val SCE_NIM_STRINGEOL=13 +val SCE_NIM_NUMERROR=14 +val SCE_NIM_OPERATOR=15 +val SCE_NIM_IDENTIFIER=16  # Events diff --git a/lexers/LexNim.cxx b/lexers/LexNim.cxx new file mode 100644 index 000000000..2cfc30eeb --- /dev/null +++ b/lexers/LexNim.cxx @@ -0,0 +1,701 @@ +// Scintilla source code edit control +/** @file LexNim.cxx +** Lexer for Nim +** Written by Jad Altahan (github.com/xv) +** Nim manual: https://nim-lang.org/docs/manual.html +**/ +// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include <string> +#include <map> +#include <algorithm> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "StringCopy.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "CharacterCategory.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "DefaultLexer.h" + +using namespace Scintilla; + +struct OptionsNim { +    bool fold; +    bool foldCompact; + +    OptionsNim() { +        fold = true; +        foldCompact = true; +    } +}; + +static const char *const nimWordListDesc[] = { +    "Keywords", +    0 +}; + +struct OptionSetNim : public OptionSet<OptionsNim> { +    OptionSetNim() { +        DefineProperty("fold", &OptionsNim::fold); +        DefineProperty("fold.compact", &OptionsNim::foldCompact); + +        DefineWordListSets(nimWordListDesc); +    } +}; + +LexicalClass lexicalClasses[] = { +    // Lexer Nim SCLEX_NIM SCE_NIM_: +    0,  "SCE_NIM_DEFAULT",        "default",              "White space", +    1,  "SCE_NIM_COMMENT",        "comment block",        "Block comment", +    2,  "SCE_NIM_COMMENTDOC",     "comment block doc",    "Block doc comment", +    3,  "SCE_NIM_COMMENTLINE",    "comment line",         "Line comment", +    4,  "SCE_NIM_COMMENTLINEDOC", "comment doc",          "Line doc comment", +    5,  "SCE_NIM_NUMBER",         "literal numeric",      "Number", +    6,  "SCE_NIM_STRING",         "literal string",       "String", +    7,  "SCE_NIM_CHARACTER",      "literal string",       "Single quoted string", +    8,  "SCE_NIM_WORD",           "keyword",              "Keyword", +    9,  "SCE_NIM_TRIPLE",         "literal string",       "Triple quotes", +    10, "SCE_NIM_TRIPLEDOUBLE",   "literal string",       "Triple double quotes", +    11, "SCE_NIM_BACKTICKS",      "operator definition",  "Identifiers", +    12, "SCE_NIM_FUNCNAME",       "identifier",           "Function name definition", +    13, "SCE_NIM_STRINGEOL",      "error literal string", "String is not closed", +    14, "SCE_NIM_NUMERROR",       "numeric error",        "Numeric format error", +    15, "SCE_NIM_OPERATOR",       "operator",             "Operators", +    16, "SCE_NIM_IDENTIFIER",     "identifier",           "Identifiers", +}; + +class LexerNim : public DefaultLexer { +    CharacterSet setWord; +    WordList keywords; +    OptionsNim options; +    OptionSetNim osNim; + +public: +    LexerNim() : +        DefaultLexer(lexicalClasses, ELEMENTS(lexicalClasses)), +        setWord(CharacterSet::setAlphaNum, "_", 0x80, true) { } + +    virtual ~LexerNim() { } + +    void SCI_METHOD Release() override { +        delete this; +    } + +    int SCI_METHOD Version() const override { +        return lvRelease4; +    } + +    const char * SCI_METHOD PropertyNames() override { +        return osNim.PropertyNames(); +    } + +    int SCI_METHOD PropertyType(const char *name) override { +        return osNim.PropertyType(name); +    } + +    const char * SCI_METHOD DescribeProperty(const char *name) override { +        return osNim.DescribeProperty(name); +    } + +    Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + +    const char * SCI_METHOD DescribeWordListSets() override { +        return osNim.DescribeWordListSets(); +    } + +    Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + +    void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; +    void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + +    void * SCI_METHOD PrivateCall(int, void *) override { +        return 0; +    } + +    int SCI_METHOD LineEndTypesSupported() override { +        return SC_LINE_END_TYPE_UNICODE; +    } + +    int SCI_METHOD PrimaryStyleFromStyle(int style) override { +        return style; +    } + +    static ILexer4 *LexerFactoryNim() { +        return new LexerNim(); +    } +}; + +Sci_Position SCI_METHOD LexerNim::PropertySet(const char *key, const char *val) { +    if (osNim.PropertySet(&options, key, val)) { +        return 0; +    } + +    return -1; +} + +Sci_Position SCI_METHOD LexerNim::WordListSet(int n, const char *wl) { +    WordList *wordListN = 0; + +    switch (n) { +        case 0: +            wordListN = &keywords; +            break; +    } + +    Sci_Position firstModification = -1; + +    if (wordListN) { +        WordList wlNew; +        wlNew.Set(wl); + +        if (*wordListN != wlNew) { +            wordListN->Set(wl); +            firstModification = 0; +        } +    } + +    return firstModification; +} + +enum NumType { +    Binary, +    Octal, +    Exponent, +    Hexadecimal, +    Decimal, +    FormatError +}; + +static int GetNumStyle(int numType) { +    if (numType == NumType::FormatError) { +        return SCE_NIM_NUMERROR; +    } + +    return SCE_NIM_NUMBER; +} + +static bool IsAWordChar(const int ch) { +    return ch < 0x80 && (isalnum(ch) || ch == '_' || ch == '.'); +} + +static int IsNumHex(StyleContext &sc) { +    return sc.chNext == 'x' || sc.chNext == 'X'; +} + +static int IsNumBinary(StyleContext &sc) { +    return sc.chNext == 'b' || sc.chNext == 'B'; +} + +static int IsNumOctal(StyleContext &sc) { +    return IsADigit(sc.chNext) +        || sc.chNext == 'o' +        || sc.chNext == 'c' || sc.chNext == 'C'; +} + +static bool IsNewline(const int ch) { +    return (ch == '\n' || ch == '\r'); +} + +static bool IsTripleLiteral(const int style) { +    return style == SCE_NIM_TRIPLE || style == SCE_NIM_TRIPLEDOUBLE; +} + +static bool IsLineComment(const int style) { +    return style == SCE_NIM_COMMENTLINE || style == SCE_NIM_COMMENTLINEDOC; +} + +static bool IsStreamComment(const int style) { +    return style == SCE_NIM_COMMENT || style == SCE_NIM_COMMENTDOC; +} + +void SCI_METHOD LexerNim::Lex(Sci_PositionU startPos, Sci_Position length, +                              int initStyle, IDocument *pAccess) { +    // No one likes a leaky string +    if (initStyle == SCE_NIM_STRINGEOL) { +        initStyle = SCE_NIM_DEFAULT; +    } + +    Accessor styler(pAccess, NULL); +    StyleContext sc(startPos, length, initStyle, styler); + +    // Nim supports nested block comments! +    Sci_Position lineCurrent = styler.GetLine(startPos); +    int commentNestLevel = lineCurrent > 0 ? styler.GetLineState(lineCurrent - 1) : 0; + +    int numType = NumType::Decimal; +    int decimalCount = 0; + +    bool funcNameExists = false; + +    for (; sc.More(); sc.Forward()) { +        if (sc.atLineStart) { +            if (sc.state == SCE_NIM_STRING) { +                sc.SetState(SCE_NIM_STRING); +            } + +            lineCurrent = styler.GetLine(sc.currentPos); +            styler.SetLineState(lineCurrent, commentNestLevel); +        } + +        // Handle string line continuation +        if (sc.ch == '\\' && (sc.chNext == '\n' || sc.chNext == '\r') && +           (sc.state == SCE_NIM_STRING || sc.state == SCE_NIM_CHARACTER)) { +            sc.Forward(); + +            if (sc.ch == '\r' && sc.chNext == '\n') { +                sc.Forward(); +            } + +            continue; +        } + +        switch (sc.state) { +            case SCE_NIM_OPERATOR: +                funcNameExists = false; +                sc.SetState(SCE_NIM_DEFAULT); +                break; +            case SCE_NIM_NUMBER: +                // For a type suffix, such as 0x80'u8 +                if (sc.ch == '\'') { +                    if (sc.chNext == 'i' || sc.chNext == 'u' || +                        sc.chNext == 'f' || sc.chNext == 'd') { +                        sc.Forward(2); +                    } +                } else if (sc.ch == '.') { +                    if (sc.chNext == '.') { +                        // Pass +                    } else if (numType <= NumType::Exponent) { +                        sc.SetState(SCE_NIM_OPERATOR); +                        break; +                    } else { +                        decimalCount++; + +                        if (numType == NumType::Decimal) { +                            if (decimalCount <= 1 && !IsAWordChar(sc.chNext)) { +                                break; +                            } +                        } else if (numType == NumType::Hexadecimal) { +                            if (decimalCount <= 1 && IsADigit(sc.chNext, 16)) { +                                break; +                            } + +                            sc.SetState(SCE_NIM_OPERATOR); +                            break; +                        } +                    } +                } else if (sc.ch == '_') { +                    break; +                } else if (numType == NumType::Decimal) { +                    if (sc.chPrev != '\'' && (sc.ch == 'e' || sc.ch == 'E')) { +                        numType = NumType::Exponent; + +                        if (sc.chNext == '-' || sc.chNext == '+') { +                            sc.Forward(); +                        } + +                        break; +                    } + +                    if (IsADigit(sc.ch)) { +                        break; +                    } +                } else if (numType == NumType::Hexadecimal) { +                    if (IsADigit(sc.ch, 16)) { +                        break; +                    } +                } else if (IsADigit(sc.ch)) { +                    if (numType == NumType::Exponent) { +                        break; +                    } + +                    if (numType == NumType::Octal) { +                        // Accept only 0-7 +                        if (sc.ch <= '7') { +                            break; +                        } +                    } else if (numType == NumType::Binary) { +                        // Accept only 0 and 1 +                        if (sc.ch <= '1') { +                            break; +                        } +                    } + +                    numType = NumType::FormatError; +                    break; +                } + +                sc.ChangeState(GetNumStyle(numType)); +                sc.SetState(SCE_NIM_DEFAULT); +                break; +            case SCE_NIM_IDENTIFIER: +                if (!IsAWordChar(sc.ch)) { +                    char s[100]; +                    sc.GetCurrent(s, sizeof(s)); +                    int style = SCE_NIM_IDENTIFIER; + +                    if (keywords.InList(s) && !funcNameExists) { +                        style = SCE_NIM_WORD; +                    } else if (funcNameExists) { +                        style = SCE_NIM_FUNCNAME; +                    } + +                    sc.ChangeState(style); +                    sc.SetState(SCE_NIM_DEFAULT); + +                    if (style == SCE_NIM_WORD) { +                        if (0 == strcmp(s, "proc")  +                            || 0 == strcmp(s, "func")  +                            || 0 == strcmp(s, "macro")  +                            || 0 == strcmp(s, "method")  +                            || 0 == strcmp(s, "template")  +                            || 0 == strcmp(s, "iterator")  +                            || 0 == strcmp(s, "converter")) { +                            funcNameExists = true; +                        } else { +                            funcNameExists = false; +                        } +                    } else { +                        funcNameExists = false; +                    } +                } +                break; +            case SCE_NIM_COMMENT: +                if (sc.Match(']', '#')) { +                    if (commentNestLevel > 0) { +                        commentNestLevel--; +                    } + +                    lineCurrent = styler.GetLine(sc.currentPos); +                    styler.SetLineState(lineCurrent, commentNestLevel); +                    sc.Forward(); + +                    if (commentNestLevel == 0) { +                        sc.ForwardSetState(SCE_NIM_DEFAULT); +                    } +                } else if (sc.Match('#', '[')) { +                    commentNestLevel++; +                    lineCurrent = styler.GetLine(sc.currentPos); +                    styler.SetLineState(lineCurrent, commentNestLevel); +                } +                break; +            case SCE_NIM_COMMENTDOC: +                if (sc.Match("]##")) { +                    if (commentNestLevel > 0) { +                        commentNestLevel--; +                    } + +                    lineCurrent = styler.GetLine(sc.currentPos); +                    styler.SetLineState(lineCurrent, commentNestLevel); +                    sc.Forward(2); + +                    if (commentNestLevel == 0) { +                        sc.ForwardSetState(SCE_NIM_DEFAULT); +                    } +                } else if (sc.Match("##[")) { +                    commentNestLevel++; +                    lineCurrent = styler.GetLine(sc.currentPos); +                    styler.SetLineState(lineCurrent, commentNestLevel); +                } +                break; +            case SCE_NIM_COMMENTLINE: +            case SCE_NIM_COMMENTLINEDOC: +                if (sc.atLineStart) { +                    sc.SetState(SCE_NIM_DEFAULT); +                } +                break; +            case SCE_NIM_STRING: +                if (sc.ch == '\\') { +                    if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { +                        sc.Forward(); +                    } +                } else if (sc.ch == '\"') { +                    sc.ForwardSetState(SCE_NIM_DEFAULT); +                } else if (sc.atLineEnd) { +                    sc.ChangeState(SCE_NIM_STRINGEOL); +                    sc.ForwardSetState(SCE_NIM_DEFAULT); +                } +                break; +            case SCE_NIM_CHARACTER: +                if (sc.ch == '\\') { +                    if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { +                        sc.Forward(); +                    } +                } else if (sc.ch == '\'') { +                    sc.ForwardSetState(SCE_NIM_DEFAULT); +                } else if (sc.atLineEnd) { +                    sc.ChangeState(SCE_NIM_STRINGEOL); +                    sc.ForwardSetState(SCE_NIM_DEFAULT); +                } +                break; +            case SCE_NIM_BACKTICKS: +                if (sc.ch == '`' || sc.atLineEnd) { +                    sc.ForwardSetState(SCE_NIM_DEFAULT); +                } +                break; +            case SCE_NIM_TRIPLEDOUBLE: +                if (sc.Match(R"(""")")) { +                    sc.Forward(2); +                    sc.ForwardSetState(SCE_NIM_DEFAULT); +                } +                break; +            case SCE_NIM_TRIPLE: +                if (sc.Match("'''")) { +                    sc.Forward(2); +                    sc.ForwardSetState(SCE_NIM_DEFAULT); +                } +                break; +        } + +        if (sc.state == SCE_NIM_DEFAULT) { +            // Number +            if (IsADigit(sc.ch) || (IsADigit(sc.chNext) && sc.ch == '.')) { +                sc.SetState(SCE_NIM_NUMBER); + +                numType = NumType::Decimal; +                decimalCount = 0; + +                if (sc.ch == '0') { +                    if (IsNumHex(sc)) { +                        numType = NumType::Hexadecimal; +                    } else if (IsNumBinary(sc)) { +                        numType = NumType::Binary; +                    } else if (IsNumOctal(sc)) { +                        numType = NumType::Octal; +                    } + +                    if (numType != NumType::Decimal) { +                        sc.Forward(); +                    } +                } +            } +            // Raw string +            else if ((sc.ch == 'r' || sc.ch == 'R') && sc.chNext == '\"') { +                sc.SetState(SCE_NIM_STRING); +                sc.Forward(); +            } +            // String and triple double literal +            else if (sc.ch == '\"') { +                if (sc.Match(R"(""")")) { +                    sc.SetState(SCE_NIM_TRIPLEDOUBLE); +                } else { +                    sc.SetState(SCE_NIM_STRING); +                } +            } +            // Charecter and triple literal +            else if (sc.ch == '\'') { +                if (sc.Match("'''")) { +                    sc.SetState(SCE_NIM_TRIPLE); +                } else { +                    sc.SetState(SCE_NIM_CHARACTER); +                } +            } +            // Operator definition +            else if (sc.ch == '`') { +                sc.SetState(SCE_NIM_BACKTICKS); + +                if (funcNameExists) { +                    funcNameExists = false; +                } +            } +            // Keyword +            else if (iswordstart(sc.ch)) { +                sc.SetState(SCE_NIM_IDENTIFIER); +            } +            // Comments +            else if (sc.ch == '#') { +                if (sc.Match("##[") || sc.Match("#[")) { +                    commentNestLevel++; +                    lineCurrent = styler.GetLine(sc.currentPos); +                    styler.SetLineState(lineCurrent, commentNestLevel); +                } + +                if (sc.Match("##[")) { +                    sc.SetState(SCE_NIM_COMMENTDOC); +                    sc.Forward(); +                } else if (sc.Match("#[")) { +                    sc.SetState(SCE_NIM_COMMENT); +                    sc.Forward(); +                } else if (sc.Match("##")) { +                    sc.SetState(SCE_NIM_COMMENTLINEDOC); +                } else { +                    sc.SetState(SCE_NIM_COMMENTLINE); +                } +            } +            // Operators +            else if (strchr("()[]{}:=;-\\/&%$!+<>|^?,.*~@", sc.ch)) { +                sc.SetState(SCE_NIM_OPERATOR); + +                // Ignore decimal coloring in input like: range[0..5] +                if (sc.Match('.', '.')) { +                    sc.Forward(); + +                    if (sc.chNext == '.') { +                        sc.Forward(); +                    } +                } +            } +        } + +        if (sc.atLineEnd) { +            funcNameExists = false; +        } +    } + +    sc.Complete(); +} + +// Adopted from Accessor.cxx +static int GetIndent(const Sci_Position line, Accessor &styler) { +    Sci_Position startPos = styler.LineStart(line); +    Sci_Position eolPos = styler.LineStart(line + 1) - 1; + +    char ch = styler[startPos]; +    int style = styler.StyleAt(startPos); + +    int indent = 0; +    bool inPrevPrefix = line > 0; +    Sci_Position posPrev = inPrevPrefix ? styler.LineStart(line - 1) : 0; + +    // No fold points inside block comments and triple literals +    while ((IsASpaceOrTab(ch)  +        || IsStreamComment(style)  +        || IsTripleLiteral(style)) && (startPos < eolPos)) { +        if (inPrevPrefix) { +            char chPrev = styler[posPrev++]; +            if (chPrev != ' ' && chPrev != '\t') { +                inPrevPrefix = false; +            } +        } + +        if (ch == '\t') { +            indent = (indent / 8 + 1) * 8; +        } else { +            indent++; +        } + +        startPos++; +        ch = styler[startPos]; +        style = styler.StyleAt(startPos); +    } + +    indent += SC_FOLDLEVELBASE; + +    if (styler.LineStart(line) == styler.Length()  +        || IsASpaceOrTab(ch)  +        || IsNewline(ch)  +        || IsLineComment(style)) { +        return indent | SC_FOLDLEVELWHITEFLAG; +    } else { +        return indent; +    } +} + +static int IndentAmount(const Sci_Position line, Accessor &styler) { +    const int indent = GetIndent(line, styler); +    const int indentLevel = indent & SC_FOLDLEVELNUMBERMASK; +    return indentLevel <= SC_FOLDLEVELBASE ? indent : indentLevel | (indent & ~SC_FOLDLEVELNUMBERMASK); +} + +void SCI_METHOD LexerNim::Fold(Sci_PositionU startPos, Sci_Position length, int, IDocument *pAccess) { +    if (!options.fold) { +        return; +    } + +    Accessor styler(pAccess, NULL); + +    const Sci_Position docLines = styler.GetLine(styler.Length()); +    const Sci_Position maxPos = startPos + length; +    const Sci_Position maxLines = styler.GetLine(maxPos == styler.Length() ? maxPos : maxPos - 1); + +    Sci_Position lineCurrent = styler.GetLine(startPos); +    int indentCurrent = IndentAmount(lineCurrent, styler); + +    while (lineCurrent > 0) { +        lineCurrent--; +        indentCurrent = IndentAmount(lineCurrent, styler); + +        if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { +            break; +        } +    } + +    int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; +    indentCurrent = indentCurrentLevel | (indentCurrent & ~SC_FOLDLEVELNUMBERMASK); + +    while (lineCurrent <= docLines && lineCurrent <= maxLines) { +        Sci_Position lineNext = lineCurrent + 1; +        int indentNext = indentCurrent; +        int lev = indentCurrent; + +        if (lineNext <= docLines) { +            indentNext = IndentAmount(lineNext, styler); +        } + +        if (indentNext & SC_FOLDLEVELWHITEFLAG) { +            indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel; +        } + +        while (lineNext < docLines && (indentNext & SC_FOLDLEVELWHITEFLAG)) { +            lineNext++; +            indentNext = IndentAmount(lineNext, styler); +        } + +        const int indentNextLevel = indentNext & SC_FOLDLEVELNUMBERMASK; +        indentNext = indentNextLevel | (indentNext & ~SC_FOLDLEVELNUMBERMASK); + +        const int levelBeforeComments = std::max(indentCurrentLevel, indentNextLevel); + +        Sci_Position skipLine = lineNext; +        int skipLevel = indentNextLevel; + +        while (--skipLine > lineCurrent) { +            int skipLineIndent = IndentAmount(skipLine, styler); + +            if (options.foldCompact) { +                if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > indentNextLevel) { +                    skipLevel = levelBeforeComments; +                } + +                int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG; +                styler.SetLevel(skipLine, skipLevel | whiteFlag); +            } else { +                if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > indentNextLevel && +                   !(skipLineIndent & SC_FOLDLEVELWHITEFLAG)) { +                    skipLevel = levelBeforeComments; +                } + +                styler.SetLevel(skipLine, skipLevel); +            } +        } + +        if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { +            if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { +                lev |= SC_FOLDLEVELHEADERFLAG; +            } +        } + +        styler.SetLevel(lineCurrent, options.foldCompact ? lev : lev & ~SC_FOLDLEVELWHITEFLAG); + +        indentCurrent = indentNext; +        indentCurrentLevel = indentNextLevel; +        lineCurrent = lineNext; +    } +} + +LexerModule lmNim(SCLEX_NIM, LexerNim::LexerFactoryNim, "nim", nimWordListDesc); diff --git a/src/Catalogue.cxx b/src/Catalogue.cxx index 2a42d9f99..b7b722a51 100644 --- a/src/Catalogue.cxx +++ b/src/Catalogue.cxx @@ -143,6 +143,7 @@ int Scintilla_LinkLexers() {  	LINK_LEXER(lmModula);  	LINK_LEXER(lmMSSQL);  	LINK_LEXER(lmMySQL); +	LINK_LEXER(lmNim);  	LINK_LEXER(lmNimrod);  	LINK_LEXER(lmNncrontab);  	LINK_LEXER(lmNsis); diff --git a/win32/scintilla.mak b/win32/scintilla.mak index 2c1e38311..de4256b56 100644 --- a/win32/scintilla.mak +++ b/win32/scintilla.mak @@ -168,6 +168,7 @@ LEXOBJS=\  	$(DIR_O)\LexMPT.obj \  	$(DIR_O)\LexMSSQL.obj \  	$(DIR_O)\LexMySQL.obj \ +	$(DIR_O)\LexNim.obj \  	$(DIR_O)\LexNimrod.obj \  	$(DIR_O)\LexNsis.obj \  	$(DIR_O)\LexNull.obj \ @@ -659,6 +660,8 @@ $(DIR_O)\LexMSSQL.obj: ..\lexers\LexMSSQL.cxx $(LEX_HEADERS)  $(DIR_O)\LexMySQL.obj: ..\lexers\LexMySQL.cxx $(LEX_HEADERS) +$(DIR_O)\LexNim.obj: ..\lexers\LexNim.cxx $(LEX_HEADERS) +  $(DIR_O)\LexNimrod.obj: ..\lexers\LexNimrod.cxx $(LEX_HEADERS)  $(DIR_O)\LexNsis.obj: ..\lexers\LexNsis.cxx $(LEX_HEADERS) | 
