1 | // Scintilla source code edit control |
2 | /** @file LexSorcus.cxx |
3 | ** Lexer for SORCUS installation files |
4 | ** Written by Eugen Bitter and Christoph Baumann at SORCUS Computer, Heidelberg Germany |
5 | ** Based on the ASM Lexer by The Black Horus |
6 | **/ |
7 | |
8 | // The License.txt file describes the conditions under which this software may be distributed. |
9 | |
10 | #include <stdlib.h> |
11 | #include <string.h> |
12 | #include <stdio.h> |
13 | #include <stdarg.h> |
14 | #include <assert.h> |
15 | #include <ctype.h> |
16 | |
17 | #include <string> |
18 | #include <string_view> |
19 | |
20 | #include "ILexer.h" |
21 | #include "Scintilla.h" |
22 | #include "SciLexer.h" |
23 | |
24 | #include "WordList.h" |
25 | #include "LexAccessor.h" |
26 | #include "Accessor.h" |
27 | #include "StyleContext.h" |
28 | #include "CharacterSet.h" |
29 | #include "LexerModule.h" |
30 | |
31 | using namespace Lexilla; |
32 | |
33 | |
34 | //each character a..z and A..Z + '_' can be part of a keyword |
35 | //additionally numbers that follow 'M' can be contained in a keyword |
36 | static inline bool IsSWordStart(const int ch, const int prev_ch) |
37 | { |
38 | if (isalpha(ch) || (ch == '_') || ((isdigit(ch)) && (prev_ch == 'M'))) |
39 | return true; |
40 | |
41 | return false; |
42 | } |
43 | |
44 | |
45 | //only digits that are not preceded by 'M' count as a number |
46 | static inline bool IsSorcusNumber(const int ch, const int prev_ch) |
47 | { |
48 | if ((isdigit(ch)) && (prev_ch != 'M')) |
49 | return true; |
50 | |
51 | return false; |
52 | } |
53 | |
54 | |
55 | //only = is a valid operator |
56 | static inline bool IsSorcusOperator(const int ch) |
57 | { |
58 | if (ch == '=') |
59 | return true; |
60 | |
61 | return false; |
62 | } |
63 | |
64 | |
65 | static void ColouriseSorcusDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], |
66 | Accessor &styler) |
67 | { |
68 | |
69 | WordList &Command = *keywordlists[0]; |
70 | WordList &Parameter = *keywordlists[1]; |
71 | WordList &Constant = *keywordlists[2]; |
72 | |
73 | // Do not leak onto next line |
74 | if (initStyle == SCE_SORCUS_STRINGEOL) |
75 | initStyle = SCE_SORCUS_DEFAULT; |
76 | |
77 | StyleContext sc(startPos, length, initStyle, styler); |
78 | |
79 | for (; sc.More(); sc.Forward()) |
80 | { |
81 | |
82 | // Prevent SCE_SORCUS_STRINGEOL from leaking back to previous line |
83 | if (sc.atLineStart && (sc.state == SCE_SORCUS_STRING)) |
84 | { |
85 | sc.SetState(SCE_SORCUS_STRING); |
86 | } |
87 | |
88 | // Determine if the current state should terminate. |
89 | if (sc.state == SCE_SORCUS_OPERATOR) |
90 | { |
91 | if (!IsSorcusOperator(sc.ch)) |
92 | { |
93 | sc.SetState(SCE_SORCUS_DEFAULT); |
94 | } |
95 | } |
96 | else if(sc.state == SCE_SORCUS_NUMBER) |
97 | { |
98 | if(!IsSorcusNumber(sc.ch, sc.chPrev)) |
99 | { |
100 | sc.SetState(SCE_SORCUS_DEFAULT); |
101 | } |
102 | } |
103 | else if (sc.state == SCE_SORCUS_IDENTIFIER) |
104 | { |
105 | if (!IsSWordStart(sc.ch, sc.chPrev)) |
106 | { |
107 | char s[100]; |
108 | |
109 | sc.GetCurrent(s, sizeof(s)); |
110 | |
111 | if (Command.InList(s)) |
112 | { |
113 | sc.ChangeState(SCE_SORCUS_COMMAND); |
114 | } |
115 | else if (Parameter.InList(s)) |
116 | { |
117 | sc.ChangeState(SCE_SORCUS_PARAMETER); |
118 | } |
119 | else if (Constant.InList(s)) |
120 | { |
121 | sc.ChangeState(SCE_SORCUS_CONSTANT); |
122 | } |
123 | |
124 | sc.SetState(SCE_SORCUS_DEFAULT); |
125 | } |
126 | } |
127 | else if (sc.state == SCE_SORCUS_COMMENTLINE ) |
128 | { |
129 | if (sc.atLineEnd) |
130 | { |
131 | sc.SetState(SCE_SORCUS_DEFAULT); |
132 | } |
133 | } |
134 | else if (sc.state == SCE_SORCUS_STRING) |
135 | { |
136 | if (sc.ch == '\"') |
137 | { |
138 | sc.ForwardSetState(SCE_SORCUS_DEFAULT); |
139 | } |
140 | else if (sc.atLineEnd) |
141 | { |
142 | sc.ChangeState(SCE_SORCUS_STRINGEOL); |
143 | sc.ForwardSetState(SCE_SORCUS_DEFAULT); |
144 | } |
145 | } |
146 | |
147 | // Determine if a new state should be entered. |
148 | if (sc.state == SCE_SORCUS_DEFAULT) |
149 | { |
150 | if ((sc.ch == ';') || (sc.ch == '\'')) |
151 | { |
152 | sc.SetState(SCE_SORCUS_COMMENTLINE); |
153 | } |
154 | else if (IsSWordStart(sc.ch, sc.chPrev)) |
155 | { |
156 | sc.SetState(SCE_SORCUS_IDENTIFIER); |
157 | } |
158 | else if (sc.ch == '\"') |
159 | { |
160 | sc.SetState(SCE_SORCUS_STRING); |
161 | } |
162 | else if (IsSorcusOperator(sc.ch)) |
163 | { |
164 | sc.SetState(SCE_SORCUS_OPERATOR); |
165 | } |
166 | else if (IsSorcusNumber(sc.ch, sc.chPrev)) |
167 | { |
168 | sc.SetState(SCE_SORCUS_NUMBER); |
169 | } |
170 | } |
171 | |
172 | } |
173 | sc.Complete(); |
174 | } |
175 | |
176 | |
177 | static const char* const SorcusWordListDesc[] = {"Command" ,"Parameter" , "Constant" , 0}; |
178 | |
179 | LexerModule lmSorc(SCLEX_SORCUS, ColouriseSorcusDoc, "sorcins" , 0, SorcusWordListDesc); |
180 | |
181 | |
182 | |
183 | |
184 | |
185 | |
186 | |
187 | |
188 | |
189 | |
190 | |
191 | |
192 | |
193 | |
194 | |
195 | |
196 | |
197 | |
198 | |
199 | |
200 | |
201 | |
202 | |
203 | |
204 | |
205 | |
206 | |
207 | |
208 | |
209 | |
210 | |