Update Scintilla to version 3.4.1
[geany-mirror.git] / scintilla / lexers / LexForth.cxx
blob7b41aaf8e767fec941ce2d53632e19aa22c09dad
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.
8 #include <stdlib.h>
9 #include <string.h>
10 #include <stdio.h>
11 #include <stdarg.h>
12 #include <assert.h>
13 #include <ctype.h>
15 #include "ILexer.h"
16 #include "Scintilla.h"
17 #include "SciLexer.h"
19 #include "WordList.h"
20 #include "LexAccessor.h"
21 #include "Accessor.h"
22 #include "StyleContext.h"
23 #include "CharacterSet.h"
24 #include "LexerModule.h"
26 #ifdef SCI_NAMESPACE
27 using namespace Scintilla;
28 #endif
30 static inline bool IsAWordStart(int ch) {
31 return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
34 static inline bool IsANumChar(int ch) {
35 return (ch < 0x80) && (isxdigit(ch) || ch == '.' || ch == 'e' || ch == 'E' );
38 static inline bool IsASpaceChar(int ch) {
39 return (ch < 0x80) && isspace(ch);
42 static void ColouriseForthDoc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[],
43 Accessor &styler) {
45 WordList &control = *keywordLists[0];
46 WordList &keyword = *keywordLists[1];
47 WordList &defword = *keywordLists[2];
48 WordList &preword1 = *keywordLists[3];
49 WordList &preword2 = *keywordLists[4];
50 WordList &strings = *keywordLists[5];
52 StyleContext sc(startPos, length, initStyle, styler);
54 for (; sc.More(); sc.Forward())
56 // Determine if the current state should terminate.
57 if (sc.state == SCE_FORTH_COMMENT) {
58 if (sc.atLineEnd) {
59 sc.SetState(SCE_FORTH_DEFAULT);
61 }else if (sc.state == SCE_FORTH_COMMENT_ML) {
62 if (sc.ch == ')') {
63 sc.ForwardSetState(SCE_FORTH_DEFAULT);
65 }else if (sc.state == SCE_FORTH_IDENTIFIER || sc.state == SCE_FORTH_NUMBER) {
66 // handle numbers here too, because what we thought was a number might
67 // turn out to be a keyword e.g. 2DUP
68 if (IsASpaceChar(sc.ch) ) {
69 char s[100];
70 sc.GetCurrentLowered(s, sizeof(s));
71 int newState = sc.state == SCE_FORTH_NUMBER ? SCE_FORTH_NUMBER : SCE_FORTH_DEFAULT;
72 if (control.InList(s)) {
73 sc.ChangeState(SCE_FORTH_CONTROL);
74 } else if (keyword.InList(s)) {
75 sc.ChangeState(SCE_FORTH_KEYWORD);
76 } else if (defword.InList(s)) {
77 sc.ChangeState(SCE_FORTH_DEFWORD);
78 } else if (preword1.InList(s)) {
79 sc.ChangeState(SCE_FORTH_PREWORD1);
80 } else if (preword2.InList(s)) {
81 sc.ChangeState(SCE_FORTH_PREWORD2);
82 } else if (strings.InList(s)) {
83 sc.ChangeState(SCE_FORTH_STRING);
84 newState = SCE_FORTH_STRING;
86 sc.SetState(newState);
88 if (sc.state == SCE_FORTH_NUMBER) {
89 if (IsASpaceChar(sc.ch)) {
90 sc.SetState(SCE_FORTH_DEFAULT);
91 } else if (!IsANumChar(sc.ch)) {
92 sc.ChangeState(SCE_FORTH_IDENTIFIER);
95 }else if (sc.state == SCE_FORTH_STRING) {
96 if (sc.ch == '\"') {
97 sc.ForwardSetState(SCE_FORTH_DEFAULT);
99 }else if (sc.state == SCE_FORTH_LOCALE) {
100 if (sc.ch == '}') {
101 sc.ForwardSetState(SCE_FORTH_DEFAULT);
103 }else if (sc.state == SCE_FORTH_DEFWORD) {
104 if (IsASpaceChar(sc.ch)) {
105 sc.SetState(SCE_FORTH_DEFAULT);
109 // Determine if a new state should be entered.
110 if (sc.state == SCE_FORTH_DEFAULT) {
111 if (sc.ch == '\\'){
112 sc.SetState(SCE_FORTH_COMMENT);
113 } else if (sc.ch == '(' &&
114 (sc.atLineStart || IsASpaceChar(sc.chPrev)) &&
115 (sc.atLineEnd || IsASpaceChar(sc.chNext))) {
116 sc.SetState(SCE_FORTH_COMMENT_ML);
117 } else if ( (sc.ch == '$' && (IsASCII(sc.chNext) && isxdigit(sc.chNext))) ) {
118 // number starting with $ is a hex number
119 sc.SetState(SCE_FORTH_NUMBER);
120 while(sc.More() && IsASCII(sc.chNext) && isxdigit(sc.chNext))
121 sc.Forward();
122 } else if ( (sc.ch == '%' && (IsASCII(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))) ) {
123 // number starting with % is binary
124 sc.SetState(SCE_FORTH_NUMBER);
125 while(sc.More() && IsASCII(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))
126 sc.Forward();
127 } else if ( IsASCII(sc.ch) &&
128 (isxdigit(sc.ch) || ((sc.ch == '.' || sc.ch == '-') && IsASCII(sc.chNext) && isxdigit(sc.chNext)) )
130 sc.SetState(SCE_FORTH_NUMBER);
131 } else if (IsAWordStart(sc.ch)) {
132 sc.SetState(SCE_FORTH_IDENTIFIER);
133 } else if (sc.ch == '{') {
134 sc.SetState(SCE_FORTH_LOCALE);
135 } else if (sc.ch == ':' && IsASCII(sc.chNext) && isspace(sc.chNext)) {
136 // highlight word definitions e.g. : GCD ( n n -- n ) ..... ;
137 // ^ ^^^
138 sc.SetState(SCE_FORTH_DEFWORD);
139 while(sc.More() && IsASCII(sc.chNext) && isspace(sc.chNext))
140 sc.Forward();
141 } else if (sc.ch == ';' &&
142 (sc.atLineStart || IsASpaceChar(sc.chPrev)) &&
143 (sc.atLineEnd || IsASpaceChar(sc.chNext)) ) {
144 // mark the ';' that ends a word
145 sc.SetState(SCE_FORTH_DEFWORD);
146 sc.ForwardSetState(SCE_FORTH_DEFAULT);
151 sc.Complete();
154 static void FoldForthDoc(unsigned int, int, int, WordList *[],
155 Accessor &) {
158 static const char * const forthWordLists[] = {
159 "control keywords",
160 "keywords",
161 "definition words",
162 "prewords with one argument",
163 "prewords with two arguments",
164 "string definition keywords",
168 LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth", FoldForthDoc, forthWordLists);