1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
// Scintilla source code edit control
/** @file LexForth.cxx
** Lexer for FORTH
**/
// Copyright 1998-2003 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 "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
using namespace Scintilla;
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(Sci_PositionU startPos, Sci_Position 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(Sci_PositionU, Sci_Position, 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);
|