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"
26 using namespace Scintilla
;
28 static inline bool IsAWordStart(int ch
) {
29 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_' || ch
== '.');
32 static inline bool IsANumChar(int ch
) {
33 return (ch
< 0x80) && (isxdigit(ch
) || ch
== '.' || ch
== 'e' || ch
== 'E' );
36 static inline bool IsASpaceChar(int ch
) {
37 return (ch
< 0x80) && isspace(ch
);
40 static void ColouriseForthDoc(Sci_PositionU startPos
, Sci_Position length
, int initStyle
, WordList
*keywordLists
[],
43 WordList
&control
= *keywordLists
[0];
44 WordList
&keyword
= *keywordLists
[1];
45 WordList
&defword
= *keywordLists
[2];
46 WordList
&preword1
= *keywordLists
[3];
47 WordList
&preword2
= *keywordLists
[4];
48 WordList
&strings
= *keywordLists
[5];
50 StyleContext
sc(startPos
, length
, initStyle
, styler
);
52 for (; sc
.More(); sc
.Forward())
54 // Determine if the current state should terminate.
55 if (sc
.state
== SCE_FORTH_COMMENT
) {
57 sc
.SetState(SCE_FORTH_DEFAULT
);
59 }else if (sc
.state
== SCE_FORTH_COMMENT_ML
) {
61 sc
.ForwardSetState(SCE_FORTH_DEFAULT
);
63 }else if (sc
.state
== SCE_FORTH_IDENTIFIER
|| sc
.state
== SCE_FORTH_NUMBER
) {
64 // handle numbers here too, because what we thought was a number might
65 // turn out to be a keyword e.g. 2DUP
66 if (IsASpaceChar(sc
.ch
) ) {
68 sc
.GetCurrentLowered(s
, sizeof(s
));
69 int newState
= sc
.state
== SCE_FORTH_NUMBER
? SCE_FORTH_NUMBER
: SCE_FORTH_DEFAULT
;
70 if (control
.InList(s
)) {
71 sc
.ChangeState(SCE_FORTH_CONTROL
);
72 } else if (keyword
.InList(s
)) {
73 sc
.ChangeState(SCE_FORTH_KEYWORD
);
74 } else if (defword
.InList(s
)) {
75 sc
.ChangeState(SCE_FORTH_DEFWORD
);
76 } else if (preword1
.InList(s
)) {
77 sc
.ChangeState(SCE_FORTH_PREWORD1
);
78 } else if (preword2
.InList(s
)) {
79 sc
.ChangeState(SCE_FORTH_PREWORD2
);
80 } else if (strings
.InList(s
)) {
81 sc
.ChangeState(SCE_FORTH_STRING
);
82 newState
= SCE_FORTH_STRING
;
84 sc
.SetState(newState
);
86 if (sc
.state
== SCE_FORTH_NUMBER
) {
87 if (IsASpaceChar(sc
.ch
)) {
88 sc
.SetState(SCE_FORTH_DEFAULT
);
89 } else if (!IsANumChar(sc
.ch
)) {
90 sc
.ChangeState(SCE_FORTH_IDENTIFIER
);
93 }else if (sc
.state
== SCE_FORTH_STRING
) {
95 sc
.ForwardSetState(SCE_FORTH_DEFAULT
);
97 }else if (sc
.state
== SCE_FORTH_LOCALE
) {
99 sc
.ForwardSetState(SCE_FORTH_DEFAULT
);
101 }else if (sc
.state
== SCE_FORTH_DEFWORD
) {
102 if (IsASpaceChar(sc
.ch
)) {
103 sc
.SetState(SCE_FORTH_DEFAULT
);
107 // Determine if a new state should be entered.
108 if (sc
.state
== SCE_FORTH_DEFAULT
) {
110 sc
.SetState(SCE_FORTH_COMMENT
);
111 } else if (sc
.ch
== '(' &&
112 (sc
.atLineStart
|| IsASpaceChar(sc
.chPrev
)) &&
113 (sc
.atLineEnd
|| IsASpaceChar(sc
.chNext
))) {
114 sc
.SetState(SCE_FORTH_COMMENT_ML
);
115 } else if ( (sc
.ch
== '$' && (IsASCII(sc
.chNext
) && isxdigit(sc
.chNext
))) ) {
116 // number starting with $ is a hex number
117 sc
.SetState(SCE_FORTH_NUMBER
);
118 while(sc
.More() && IsASCII(sc
.chNext
) && isxdigit(sc
.chNext
))
120 } else if ( (sc
.ch
== '%' && (IsASCII(sc
.chNext
) && (sc
.chNext
== '0' || sc
.chNext
== '1'))) ) {
121 // number starting with % is binary
122 sc
.SetState(SCE_FORTH_NUMBER
);
123 while(sc
.More() && IsASCII(sc
.chNext
) && (sc
.chNext
== '0' || sc
.chNext
== '1'))
125 } else if ( IsASCII(sc
.ch
) &&
126 (isxdigit(sc
.ch
) || ((sc
.ch
== '.' || sc
.ch
== '-') && IsASCII(sc
.chNext
) && isxdigit(sc
.chNext
)) )
128 sc
.SetState(SCE_FORTH_NUMBER
);
129 } else if (IsAWordStart(sc
.ch
)) {
130 sc
.SetState(SCE_FORTH_IDENTIFIER
);
131 } else if (sc
.ch
== '{') {
132 sc
.SetState(SCE_FORTH_LOCALE
);
133 } else if (sc
.ch
== ':' && IsASCII(sc
.chNext
) && isspace(sc
.chNext
)) {
134 // highlight word definitions e.g. : GCD ( n n -- n ) ..... ;
136 sc
.SetState(SCE_FORTH_DEFWORD
);
137 while(sc
.More() && IsASCII(sc
.chNext
) && isspace(sc
.chNext
))
139 } else if (sc
.ch
== ';' &&
140 (sc
.atLineStart
|| IsASpaceChar(sc
.chPrev
)) &&
141 (sc
.atLineEnd
|| IsASpaceChar(sc
.chNext
)) ) {
142 // mark the ';' that ends a word
143 sc
.SetState(SCE_FORTH_DEFWORD
);
144 sc
.ForwardSetState(SCE_FORTH_DEFAULT
);
152 static void FoldForthDoc(Sci_PositionU
, Sci_Position
, int, WordList
*[],
156 static const char * const forthWordLists
[] = {
160 "prewords with one argument",
161 "prewords with two arguments",
162 "string definition keywords",
166 LexerModule
lmForth(SCLEX_FORTH
, ColouriseForthDoc
, "forth", FoldForthDoc
, forthWordLists
);