]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexForth.cxx
e52543fa552da9e9b1a6c396a08a439981f5a089
[wxWidgets.git] / src / stc / scintilla / src / LexForth.cxx
1 // Scintilla source code edit control
2 /** @file LexForth.cxx
3 ** Lexer for FORTH
4 **/
5 // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
7
8 #include <stdlib.h>
9 #include <string.h>
10 #include <ctype.h>
11 #include <stdio.h>
12 #include <stdarg.h>
13
14 #include "Platform.h"
15
16 #include "PropSet.h"
17 #include "Accessor.h"
18 #include "StyleContext.h"
19 #include "KeyWords.h"
20 #include "Scintilla.h"
21 #include "SciLexer.h"
22
23 #ifdef SCI_NAMESPACE
24 using namespace Scintilla;
25 #endif
26
27 static inline bool IsAWordChar(int ch) {
28 return (ch < 0x80) && (isalnum(ch) || ch == '.' ||
29 ch == '_' || ch == '?' || ch == '"' || ch == '@' ||
30 ch == '!' || ch == '[' || ch == ']' || ch == '/' ||
31 ch == '+' || ch == '-' || ch == '*' || ch == '<' ||
32 ch == '>' || ch == '=' || ch == ';' || ch == '(' ||
33 ch == ')' );
34 }
35
36 static inline bool IsAWordStart(int ch) {
37 return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
38 }
39
40 static inline bool IsANumChar(int ch) {
41 return (ch < 0x80) && (isxdigit(ch) || ch == '.' || ch == 'e' || ch == 'E' );
42 }
43
44 static inline bool IsASpaceChar(int ch) {
45 return (ch < 0x80) && isspace(ch);
46 }
47
48 static void ColouriseForthDoc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[],
49 Accessor &styler) {
50
51 WordList &control = *keywordLists[0];
52 WordList &keyword = *keywordLists[1];
53 WordList &defword = *keywordLists[2];
54 WordList &preword1 = *keywordLists[3];
55 WordList &preword2 = *keywordLists[4];
56 WordList &strings = *keywordLists[5];
57
58 StyleContext sc(startPos, length, initStyle, styler);
59
60 for (; sc.More(); sc.Forward())
61 {
62 // Determine if the current state should terminate.
63 if (sc.state == SCE_FORTH_COMMENT) {
64 if (sc.atLineEnd) {
65 sc.SetState(SCE_FORTH_DEFAULT);
66 }
67 }else if (sc.state == SCE_FORTH_COMMENT_ML) {
68 if (sc.ch == ')') {
69 sc.ForwardSetState(SCE_FORTH_DEFAULT);
70 }
71 }else if (sc.state == SCE_FORTH_IDENTIFIER || sc.state == SCE_FORTH_NUMBER) {
72 // handle numbers here too, because what we thought was a number might
73 // turn out to be a keyword e.g. 2DUP
74 if (IsASpaceChar(sc.ch) ) {
75 char s[100];
76 sc.GetCurrentLowered(s, sizeof(s));
77 int newState = sc.state == SCE_FORTH_NUMBER ? SCE_FORTH_NUMBER : SCE_FORTH_DEFAULT;
78 if (control.InList(s)) {
79 sc.ChangeState(SCE_FORTH_CONTROL);
80 } else if (keyword.InList(s)) {
81 sc.ChangeState(SCE_FORTH_KEYWORD);
82 } else if (defword.InList(s)) {
83 sc.ChangeState(SCE_FORTH_DEFWORD);
84 } else if (preword1.InList(s)) {
85 sc.ChangeState(SCE_FORTH_PREWORD1);
86 } else if (preword2.InList(s)) {
87 sc.ChangeState(SCE_FORTH_PREWORD2);
88 } else if (strings.InList(s)) {
89 sc.ChangeState(SCE_FORTH_STRING);
90 newState = SCE_FORTH_STRING;
91 }
92 sc.SetState(newState);
93 }
94 if (sc.state == SCE_FORTH_NUMBER) {
95 if (IsASpaceChar(sc.ch)) {
96 sc.SetState(SCE_FORTH_DEFAULT);
97 } else if (!IsANumChar(sc.ch)) {
98 sc.ChangeState(SCE_FORTH_IDENTIFIER);
99 }
100 }
101 }else if (sc.state == SCE_FORTH_STRING) {
102 if (sc.ch == '\"') {
103 sc.ForwardSetState(SCE_FORTH_DEFAULT);
104 }
105 }else if (sc.state == SCE_FORTH_LOCALE) {
106 if (sc.ch == '}') {
107 sc.ForwardSetState(SCE_FORTH_DEFAULT);
108 }
109 }else if (sc.state == SCE_FORTH_DEFWORD) {
110 if (IsASpaceChar(sc.ch)) {
111 sc.SetState(SCE_FORTH_DEFAULT);
112 }
113 }
114
115 // Determine if a new state should be entered.
116 if (sc.state == SCE_FORTH_DEFAULT) {
117 if (sc.ch == '\\'){
118 sc.SetState(SCE_FORTH_COMMENT);
119 } else if (sc.ch == '(' &&
120 (sc.atLineStart || IsASpaceChar(sc.chPrev)) &&
121 (sc.atLineEnd || IsASpaceChar(sc.chNext))) {
122 sc.SetState(SCE_FORTH_COMMENT_ML);
123 } else if ( (sc.ch == '$' && (isascii(sc.chNext) && isxdigit(sc.chNext))) ) {
124 // number starting with $ is a hex number
125 sc.SetState(SCE_FORTH_NUMBER);
126 while(sc.More() && isascii(sc.chNext) && isxdigit(sc.chNext))
127 sc.Forward();
128 } else if ( (sc.ch == '%' && (isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))) ) {
129 // number starting with % is binary
130 sc.SetState(SCE_FORTH_NUMBER);
131 while(sc.More() && isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))
132 sc.Forward();
133 } else if ( isascii(sc.ch) &&
134 (isxdigit(sc.ch) || ((sc.ch == '.' || sc.ch == '-') && isascii(sc.chNext) && isxdigit(sc.chNext)) )
135 ){
136 sc.SetState(SCE_FORTH_NUMBER);
137 } else if (IsAWordStart(sc.ch)) {
138 sc.SetState(SCE_FORTH_IDENTIFIER);
139 } else if (sc.ch == '{') {
140 sc.SetState(SCE_FORTH_LOCALE);
141 } else if (sc.ch == ':' && isascii(sc.chNext) && isspace(sc.chNext)) {
142 // highlight word definitions e.g. : GCD ( n n -- n ) ..... ;
143 // ^ ^^^
144 sc.SetState(SCE_FORTH_DEFWORD);
145 while(sc.More() && isascii(sc.chNext) && isspace(sc.chNext))
146 sc.Forward();
147 } else if (sc.ch == ';' &&
148 (sc.atLineStart || IsASpaceChar(sc.chPrev)) &&
149 (sc.atLineEnd || IsASpaceChar(sc.chNext)) ) {
150 // mark the ';' that ends a word
151 sc.SetState(SCE_FORTH_DEFWORD);
152 sc.ForwardSetState(SCE_FORTH_DEFAULT);
153 }
154 }
155
156 }
157 sc.Complete();
158 }
159
160 static void FoldForthDoc(unsigned int, int, int, WordList *[],
161 Accessor &) {
162 }
163
164 static const char * const forthWordLists[] = {
165 "control keywords",
166 "keywords",
167 "definition words",
168 "prewords with one argument",
169 "prewords with two arguments",
170 "string definition keywords",
171 0,
172 };
173
174 LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth", FoldForthDoc, forthWordLists);
175
176