Reference: LexPB.cxx

Category: Controls - Scintilla

Date: 03-28-2012

Return to Index


 
'This is presented only as a reference. It is pulled directly from
'the Scintilla distribution.
 
'Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
 
// 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 '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);
 
'gbs_00672
'Date: 03-10-2012


created by gbSnippets
http://www.garybeene.com/sw/gbsnippets.htm