diff options
| author | nyamatongwe <unknown> | 2010-07-13 21:16:48 +1000 | 
|---|---|---|
| committer | nyamatongwe <unknown> | 2010-07-13 21:16:48 +1000 | 
| commit | fd7c21165bbc5200aa24ef89560a8bb40fd37255 (patch) | |
| tree | b5cdec307f1b412f0527eb826a14b806b58cf006 /lexers/LexPB.cxx | |
| parent | d47313970ebf3736afffec781f2f9030fa3c8e1a (diff) | |
| download | scintilla-mirror-fd7c21165bbc5200aa24ef89560a8bb40fd37255.tar.gz | |
Moved lexers into lexers directory.
Diffstat (limited to 'lexers/LexPB.cxx')
| -rw-r--r-- | lexers/LexPB.cxx | 362 | 
1 files changed, 362 insertions, 0 deletions
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 <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <stdarg.h> + +#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<char>(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);  | 
