diff options
| -rw-r--r-- | cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj | 4 | ||||
| -rw-r--r-- | doc/ScintillaHistory.html | 4 | ||||
| -rw-r--r-- | include/SciLexer.h | 12 | ||||
| -rw-r--r-- | include/Scintilla.iface | 14 | ||||
| -rw-r--r-- | lexers/LexCIL.cxx | 404 | ||||
| -rw-r--r-- | src/Catalogue.cxx | 1 | ||||
| -rw-r--r-- | win32/scintilla.mak | 3 | 
7 files changed, 442 insertions, 0 deletions
| diff --git a/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj b/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj index 837ebbde3..f71b15253 100644 --- a/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj +++ b/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj @@ -230,6 +230,7 @@  		FDC7442CAD70B9A67EF1639D /* LexSAS.cxx in Sources */ = {isa = PBXBuildFile; fileRef = A95147A1AB7CADB00DAFE724 /* LexSAS.cxx */; };  		5F804AA6B60FE695863A39FE /* LexStata.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7623427695416AB1270EE023 /* LexStata.cxx */; };  		0ED84236A703D57578EBFD2F /* LexNim.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 47814937A6B72D2B0F065B61 /* LexNim.cxx */; };  +		00724A59981D34F11A3D162F /* LexCIL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 577F46B88F633198B56D088D /* LexCIL.cxx */; };  /* End PBXBuildFile section */  /* Begin PBXFileReference section */ @@ -463,6 +464,7 @@  		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; }; +		577F46B88F633198B56D088D /* LexCIL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCIL.cxx; path = ../../lexers/LexCIL.cxx; sourceTree = SOURCE_ROOT; };  /* End PBXFileReference section */  /* Begin PBXFrameworksBuildPhase section */ @@ -577,6 +579,7 @@  				28FDA42019B6967B00BE27D7 /* LexBibTeX.cxx */,  				114B6EC911FA7526004FB6AB /* LexBullant.cxx */,  				114B6ECA11FA7526004FB6AB /* LexCaml.cxx */, +				577F46B88F633198B56D088D /* LexCIL.cxx */,  				114B6ECB11FA7526004FB6AB /* LexCLW.cxx */,  				114B6ECC11FA7526004FB6AB /* LexCmake.cxx */,  				114B6ECD11FA7526004FB6AB /* LexCOBOL.cxx */, @@ -1124,6 +1127,7 @@  				FDC7442CAD70B9A67EF1639D /* LexSAS.cxx in Sources */,  				5F804AA6B60FE695863A39FE /* LexStata.cxx in Sources */,  				0ED84236A703D57578EBFD2F /* LexNim.cxx in Sources */, +				00724A59981D34F11A3D162F /* LexCIL.cxx in Sources */,  			);  			runOnlyForDeploymentPostprocessing = 0;  		}; diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index 2ffc6d613..f02c79503 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -572,6 +572,10 @@  	<a href="https://sourceforge.net/p/scintilla/feature-requests/1264/">Feature #1624</a>.  	</li>   	<li> +	Lexer added for .NET's Common Intermediate Language CIL. +	<a href="https://sourceforge.net/p/scintilla/feature-requests/1265/">Feature #1265</a>. +	</li> + 	<li>  	The C++ lexer, with styling.within.preprocessor on, now interprets "(" in preprocessor "#if("  	as an operator instead of part of the directive. This improves folding as well which could become  	unbalanced. diff --git a/include/SciLexer.h b/include/SciLexer.h index 7a71679a7..0230f8a2f 100644 --- a/include/SciLexer.h +++ b/include/SciLexer.h @@ -139,6 +139,7 @@  #define SCLEX_STATA 124  #define SCLEX_SAS 125  #define SCLEX_NIM 126 +#define SCLEX_CIL 127  #define SCLEX_AUTOMATIC 1000  #define SCE_P_DEFAULT 0  #define SCE_P_COMMENTLINE 1 @@ -1873,6 +1874,17 @@  #define SCE_NIM_NUMERROR 14  #define SCE_NIM_OPERATOR 15  #define SCE_NIM_IDENTIFIER 16 +#define SCE_CIL_DEFAULT 0 +#define SCE_CIL_COMMENT 1 +#define SCE_CIL_COMMENTLINE 2 +#define SCE_CIL_WORD 3 +#define SCE_CIL_WORD2 4 +#define SCE_CIL_WORD3 5 +#define SCE_CIL_STRING 6 +#define SCE_CIL_LABEL 7 +#define SCE_CIL_OPERATOR 8 +#define SCE_CIL_IDENTIFIER 9 +#define SCE_CIL_STRINGEOL 10  /* --Autogenerated -- end of section automatically generated from Scintilla.iface */  #endif diff --git a/include/Scintilla.iface b/include/Scintilla.iface index 8faae600e..aed70e7f3 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -2952,6 +2952,7 @@ val SCLEX_MAXIMA=123  val SCLEX_STATA=124  val SCLEX_SAS=125  val SCLEX_NIM=126 +val SCLEX_CIL=127  # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a  # value assigned in sequence from SCLEX_AUTOMATIC+1. @@ -4924,6 +4925,19 @@ val SCE_NIM_STRINGEOL=13  val SCE_NIM_NUMERROR=14  val SCE_NIM_OPERATOR=15  val SCE_NIM_IDENTIFIER=16 +# Lexical states for SCLEX_CIL +lex CIL=SCLEX_CIL SCE_CIL_ +val SCE_CIL_DEFAULT=0 +val SCE_CIL_COMMENT=1 +val SCE_CIL_COMMENTLINE=2 +val SCE_CIL_WORD=3 +val SCE_CIL_WORD2=4 +val SCE_CIL_WORD3=5 +val SCE_CIL_STRING=6 +val SCE_CIL_LABEL=7 +val SCE_CIL_OPERATOR=8 +val SCE_CIL_IDENTIFIER=9 +val SCE_CIL_STRINGEOL=10  # Events diff --git a/lexers/LexCIL.cxx b/lexers/LexCIL.cxx new file mode 100644 index 000000000..6d5307666 --- /dev/null +++ b/lexers/LexCIL.cxx @@ -0,0 +1,404 @@ +// Scintilla source code edit control +/** @file LexCIL.cxx + ** Lexer for Common Intermediate Language + ** Written by Jad Altahan (github.com/xv) + ** CIL manual: https://www.ecma-international.org/publications/standards/Ecma-335.htm + **/ +// 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; + +namespace { +    // Use an unnamed namespace to protect the functions and classes from name conflicts + +bool IsAWordChar(const int ch) { +    return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.'); +} + +bool IsOperator(const int ch) { +    if ((ch < 0x80) && (isalnum(ch))) +        return false; + +    if (strchr("!%&*+-/<=>@^|~()[]{}", ch)) { +        return true; +    } + +    return false; +} + +constexpr bool IsStreamCommentStyle(const int style) noexcept { +    return style == SCE_CIL_COMMENT; +} + +struct OptionsCIL { +    bool fold; +    bool foldComment; +    bool foldCommentMultiline; +    bool foldCompact; + +    OptionsCIL() { +        fold = true; +        foldComment = false; +        foldCommentMultiline = true; +        foldCompact = true; +    } +}; + +static const char *const cilWordListDesc[] = { +    "Primary CIL keywords", +    "Metadata", +    "Opcode instructions", +    0 +}; + +struct OptionSetCIL : public OptionSet<OptionsCIL> { +    OptionSetCIL() { +        DefineProperty("fold", &OptionsCIL::fold); +        DefineProperty("fold.comment", &OptionsCIL::foldComment); + +        DefineProperty("fold.cil.comment.multiline", &OptionsCIL::foldCommentMultiline, +            "Set this property to 0 to disable folding multi-line comments when fold.comment=1."); + +        DefineProperty("fold.compact", &OptionsCIL::foldCompact); + +        DefineWordListSets(cilWordListDesc); +    } +}; + +LexicalClass lexicalClasses[] = { +    // Lexer CIL SCLEX_CIL SCE_CIL_: +    0,  "SCE_CIL_DEFAULT",     "default",              "White space", +    1,  "SCE_CIL_COMMENT",     "comment",              "Multi-line comment", +    2,  "SCE_CIL_COMMENTLINE", "comment line",         "Line comment", +    3,  "SCE_CIL_WORD",        "keyword",              "Keyword 1", +    4,  "SCE_CIL_WORD2",       "keyword",              "Keyword 2", +    5,  "SCE_CIL_WORD3",       "keyword",              "Keyword 3", +    6,  "SCE_CIL_STRING",      "literal string",       "Double quoted string", +    7,  "SCE_CIL_LABEL",       "label",                "Code label", +    8,  "SCE_CIL_OPERATOR",    "operator",             "Operators", +    9,  "SCE_CIL_STRINGEOL",   "error literal string", "String is not closed", +    10, "SCE_CIL_IDENTIFIER",  "identifier",           "Identifiers", +}; + +} + +class LexerCIL : public DefaultLexer { +    WordList keywords, keywords2, keywords3; +    OptionsCIL options; +    OptionSetCIL osCIL; + +public: +    LexerCIL() : DefaultLexer(lexicalClasses, ELEMENTS(lexicalClasses)) { } + +    virtual ~LexerCIL() { } + +    void SCI_METHOD Release() override { +        delete this; +    } + +    int SCI_METHOD Version() const override { +        return lvRelease4; +    } + +    const char * SCI_METHOD PropertyNames() override { +        return osCIL.PropertyNames(); +    } + +    int SCI_METHOD PropertyType(const char *name) override { +        return osCIL.PropertyType(name); +    } + +    const char * SCI_METHOD DescribeProperty(const char *name) override { +        return osCIL.DescribeProperty(name); +    } + +    Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + +    const char * SCI_METHOD DescribeWordListSets() override { +        return osCIL.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 *LexerFactoryCIL() { +        return new LexerCIL(); +    } +}; + +Sci_Position SCI_METHOD LexerCIL::PropertySet(const char *key, const char *val) { +    if (osCIL.PropertySet(&options, key, val)) { +        return 0; +    } + +    return -1; +} + +Sci_Position SCI_METHOD LexerCIL::WordListSet(int n, const char *wl) { +    WordList *wordListN = 0; + +    switch (n) { +        case 0: +            wordListN = &keywords; +            break; +        case 1: +            wordListN = &keywords2; +            break; +        case 2: +            wordListN = &keywords3; +            break; +    } + +    Sci_Position firstModification = -1; + +    if (wordListN) { +        WordList wlNew; +        wlNew.Set(wl); + +        if (*wordListN != wlNew) { +            wordListN->Set(wl); +            firstModification = 0; +        } +    } + +    return firstModification; +} + +void SCI_METHOD LexerCIL::Lex(Sci_PositionU startPos, Sci_Position length, +                              int initStyle, IDocument *pAccess) { +    if (initStyle == SCE_CIL_STRINGEOL) { +        initStyle = SCE_CIL_DEFAULT; +    } + +    Accessor styler(pAccess, NULL); +    StyleContext sc(startPos, length, initStyle, styler); + +    bool identAtLineStart = false, // Checks if an identifier is at line start (ignoring spaces) +         canStyleLabels = false;   // Checks if conditions are met to style SCE_CIL_LABEL + +    for (; sc.More(); sc.Forward()) { +        if (sc.atLineStart) { +            if (sc.state == SCE_CIL_STRING) { +                sc.SetState(SCE_CIL_STRING); +            } + +            identAtLineStart = true; +        } + +        // Handle string line continuation +        if (sc.ch == '\\' && (sc.chNext == '\n' || sc.chNext == '\r') && +           (sc.state == SCE_CIL_STRING)) { +            sc.Forward(); + +            if (sc.ch == '\r' && sc.chNext == '\n') { +                sc.Forward(); +            } + +            continue; +        } + +        switch (sc.state) { +            case SCE_CIL_OPERATOR: +                sc.SetState(SCE_CIL_DEFAULT); +                break; +            case SCE_CIL_IDENTIFIER: +                if (!IsAWordChar(sc.ch)) { +                    if (canStyleLabels && (sc.ch == ':' && sc.chNext != ':')) { +                        sc.ChangeState(SCE_CIL_LABEL); +                        sc.ForwardSetState(SCE_CIL_DEFAULT); +                    } else { +                        char kwSize[100]; +                        sc.GetCurrent(kwSize, sizeof(kwSize)); +                        int style = SCE_CIL_IDENTIFIER; + +                        if (keywords.InList(kwSize)) { +                            style = SCE_CIL_WORD; +                        } else if (keywords2.InList(kwSize)) { +                            style = SCE_CIL_WORD2; +                        } else if (keywords3.InList(kwSize)) { +                            style = SCE_CIL_WORD3; +                        } + +                        sc.ChangeState(style); +                        sc.SetState(SCE_CIL_DEFAULT); +                    } +                } +                break; +            case SCE_CIL_COMMENT: +                if (sc.Match('*', '/')) { +                    sc.Forward(); +                    sc.ForwardSetState(SCE_CIL_DEFAULT); +                } +                break; +            case SCE_CIL_COMMENTLINE: +                if (sc.atLineStart) { +                    sc.SetState(SCE_CIL_DEFAULT); +                } +                break; +            case SCE_CIL_STRING: +                if (sc.ch == '\\') { +                    if (sc.chNext == '"' || sc.chNext == '\\') { +                        sc.Forward(); +                    } +                } else if (sc.ch == '"') { +                    sc.ForwardSetState(SCE_CIL_DEFAULT); +                } else if (sc.atLineEnd) { +                    sc.ChangeState(SCE_CIL_STRINGEOL); +                    sc.ForwardSetState(SCE_CIL_DEFAULT); +                } +                break; +        } + +        if (sc.state == SCE_CIL_DEFAULT) { +            // String +            if (sc.ch == '"') { +                sc.SetState(SCE_CIL_STRING); +            } +            // Keyword +            else if (IsAWordChar(sc.ch)) { +                // Allow setting SCE_CIL_LABEL style only if the label is the +                // first token in the line and does not start with a dot or a digit +                canStyleLabels = identAtLineStart && !(sc.ch == '.' || IsADigit(sc.ch)); +                sc.SetState(SCE_CIL_IDENTIFIER); +            } +            // Multi-line comment +            else if (sc.Match('/', '*')) { +                sc.SetState(SCE_CIL_COMMENT); +                sc.Forward(); +            } +            // Line comment +            else if (sc.Match('/', '/')) { +                sc.SetState(SCE_CIL_COMMENTLINE); +            } +            // Operators +            else if (IsOperator(sc.ch)) { +                sc.SetState(SCE_CIL_OPERATOR); +            } +        } + +        if (!IsASpace(sc.ch)) { +            identAtLineStart = false; +        } +    } + +    sc.Complete(); +} + +void SCI_METHOD LexerCIL::Fold(Sci_PositionU startPos, Sci_Position length,  +                               int initStyle, IDocument *pAccess) { +    if (!options.fold) { +        return; +    } + +    LexAccessor styler(pAccess); + +    const Sci_PositionU endPos = startPos + length; +    Sci_Position lineCurrent = styler.GetLine(startPos); + +    int levelCurrent = SC_FOLDLEVELBASE; +    if (lineCurrent > 0) +        levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16; +     +    int style = initStyle; +    int styleNext = styler.StyleAt(startPos); +    int levelNext = levelCurrent; +    int visibleChars = 0; + +    char chNext = styler[startPos]; + +    for (Sci_PositionU i = startPos; i < endPos; i++) { +        const char ch = chNext; +        int stylePrev = style; + +        chNext = styler.SafeGetCharAt(i + 1); +        style = styleNext; +        styleNext = styler.StyleAt(i + 1); + +        const bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + +        if (options.foldComment &&  +            options.foldCommentMultiline && IsStreamCommentStyle(style)) { +            if (!IsStreamCommentStyle(stylePrev)) { +                levelNext++; +            } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { +                levelNext--; +            } +        } + +        if (style == SCE_CIL_OPERATOR) { +            if (ch == '{') { +                levelNext++; +            } else if (ch == '}') { +                levelNext--; +            } +        } + +        if (!IsASpace(ch)) { +            visibleChars++; +        } + +        if (atEOL || (i == endPos - 1)) { +            int lev = levelCurrent | levelNext << 16; +            if (visibleChars == 0 && options.foldCompact) +                lev |= SC_FOLDLEVELWHITEFLAG; +            if (levelCurrent < levelNext) +                lev |= SC_FOLDLEVELHEADERFLAG; +            if (lev != styler.LevelAt(lineCurrent)) { +                styler.SetLevel(lineCurrent, lev); +            } +             +            lineCurrent++; +            levelCurrent = levelNext; +             +            if (options.foldCompact && +                i == static_cast<Sci_PositionU>(styler.Length() - 1)) { +                styler.SetLevel(lineCurrent, lev | SC_FOLDLEVELWHITEFLAG); +            } + +            visibleChars = 0; +        } +    } +} + +LexerModule lmCIL(SCLEX_CIL, LexerCIL::LexerFactoryCIL, "cil", cilWordListDesc);
\ No newline at end of file diff --git a/src/Catalogue.cxx b/src/Catalogue.cxx index a5a61ea8c..ab951435e 100644 --- a/src/Catalogue.cxx +++ b/src/Catalogue.cxx @@ -90,6 +90,7 @@ int Scintilla_LinkLexers() {  	LINK_LEXER(lmBlitzBasic);  	LINK_LEXER(lmBullant);  	LINK_LEXER(lmCaml); +	LINK_LEXER(lmCIL);  	LINK_LEXER(lmClw);  	LINK_LEXER(lmClwNoCase);  	LINK_LEXER(lmCmake); diff --git a/win32/scintilla.mak b/win32/scintilla.mak index d225e7131..fd95ddce6 100644 --- a/win32/scintilla.mak +++ b/win32/scintilla.mak @@ -120,6 +120,7 @@ LEXOBJS=\  	$(DIR_O)\LexBibTeX.obj \  	$(DIR_O)\LexBullant.obj \  	$(DIR_O)\LexCaml.obj \ +	$(DIR_O)\LexCIL.obj \  	$(DIR_O)\LexCLW.obj \  	$(DIR_O)\LexCmake.obj \  	$(DIR_O)\LexCOBOL.obj \ @@ -563,6 +564,8 @@ $(DIR_O)\LexBullant.obj: ..\lexers\LexBullant.cxx $(LEX_HEADERS)  $(DIR_O)\LexCaml.obj: ..\lexers\LexCaml.cxx $(LEX_HEADERS) +$(DIR_O)\LexCIL.obj: ..\lexers\LexCIL.cxx $(LEX_HEADERS) +  $(DIR_O)\LexCLW.obj: ..\lexers\LexCLW.cxx $(LEX_HEADERS)  $(DIR_O)\LexCmake.obj: ..\lexers\LexCmake.cxx $(LEX_HEADERS) | 
