1 // Scintilla source code edit control
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.
16 #include "Scintilla.h"
20 #include "LexAccessor.h"
22 #include "StyleContext.h"
23 #include "CharacterSet.h"
24 #include "LexerModule.h"
27 using namespace Scintilla
;
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
[],
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
) {
59 sc
.SetState(SCE_FORTH_DEFAULT
);
61 }else if (sc
.state
== SCE_FORTH_COMMENT_ML
) {
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
) ) {
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
) {
97 sc
.ForwardSetState(SCE_FORTH_DEFAULT
);
99 }else if (sc
.state
== SCE_FORTH_LOCALE
) {
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
) {
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
))
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'))
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 ) ..... ;
138 sc
.SetState(SCE_FORTH_DEFWORD
);
139 while(sc
.More() && IsASCII(sc
.chNext
) && isspace(sc
.chNext
))
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
);
154 static void FoldForthDoc(unsigned int, int, int, WordList
*[],
158 static const char * const forthWordLists
[] = {
162 "prewords with one argument",
163 "prewords with two arguments",
164 "string definition keywords",
168 LexerModule
lmForth(SCLEX_FORTH
, ColouriseForthDoc
, "forth", FoldForthDoc
, forthWordLists
);