]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/stc/scintilla/src/LexCLW.cxx
Updated wxSTC's copy of Scintilla to version 1.61
[wxWidgets.git] / contrib / src / stc / scintilla / src / LexCLW.cxx
CommitLineData
8e54aaed
RD
1// Scintilla source code edit control
2/** @file LexClw.cxx
3 ** Lexer for Clarion.
4 **/
5// Copyright 2003 by Ron Schofield <ron@schofieldcomputer.com>
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
23static char MakeUpperCase(char ch) {
24 if (ch < 'a' || ch > 'z')
25 return ch;
26 else
27 return static_cast<char>(ch - 'a' + 'A');
28}
29
30static void MakeUpperCaseString(char *s) {
31 while (*s) {
32 *s = MakeUpperCase(*s);
33 s++;
34 }
35}
36
37// Is a label start character
38inline bool IsALabelStart(const int iChar) {
39 return(isalpha(iChar) || iChar == '_');
40}
41
42// Is a label character
43inline bool IsALabelCharacter(const int iChar) {
44 return(isalnum(iChar) || iChar == '_' || iChar == ':');
45}
46
47// Is the character is a ! and the the next character is not a !
48inline bool IsACommentStart(StyleContext &scDoc) {
49 return(scDoc.ch == '!' && scDoc.chNext != '!');
50}
51
52// Is the character a Clarion hex character (ABCDEF)
53inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) {
54 // Case insensitive.
55 if (!bCaseSensitive) {
56 if (strchr("ABCDEFabcdef", iChar) != NULL) {
57 return(true);
58 }
59 }
60 // Case sensitive
61 else {
62 if (strchr("ABCDEF", iChar) != NULL) {
63 return(true);
64 }
65 }
66 return(false);
67}
68
69// Is the character a Clarion base character (B=Binary, O=Octal, H=Hex)
70inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) {
71 // Case insensitive.
72 if (!bCaseSensitive) {
73 // If character is a numeric base character
74 if (strchr("BOHboh", iChar) != NULL) {
75 return(true);
76 }
77 }
78 // Case sensitive
79 else {
80 // If character is a numeric base character
81 if (strchr("BOH", iChar) != NULL) {
82 return(true);
83 }
84 }
85 return(false);
86}
87
88// Set the correct numeric constant state
89inline bool SetNumericConstantState(StyleContext &scDoc) {
90 int iPoints = 0; // Point counter
91 char cNumericString[100]; // Numeric string buffer
92
93 // Buffer the current numberic string
94 scDoc.GetCurrent(cNumericString, sizeof(cNumericString));
95 // Loop through the string until end of string (NULL termination)
96 for (int iIndex = 0; cNumericString[iIndex] != '\0'; iIndex++) {
97 // Depending on the character
98 switch (cNumericString[iIndex]) {
99 // Is a . (point)
100 case '.' :
101 // Increment point counter
102 iPoints++;
103 break;
104 default :
105 break;
106 }
107 }
108 // If points found (can be more than one for improper formatted number
109 if (iPoints > 0) {
110 return(true);
111 }
112 // Else no points found
113 else {
114 return(false);
115 }
116}
117
118// Clarion Language Colouring Procedure
119static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) {
120
121 int iParenthesesLevel=0; // Parenthese Level
122
123 WordList &wlClarionKeywords = *wlKeywords[0]; // Clarion Keywords
124 WordList &wlCompilerDirectives = *wlKeywords[1]; // Compiler Directives
125 WordList &wlBuiltInProcsFuncs = *wlKeywords[2]; // Builtin Procedures and Functions
126 WordList &wlStructsDataTypes = *wlKeywords[3]; // Structures and Data Types
127 WordList &wlAttributes = *wlKeywords[4]; // Procedure Attributes
128 WordList &wlStandardEquates = *wlKeywords[5]; // Standard Equates
129 WordList &wlReservedWords = *wlKeywords[6]; // Clarion Reserved Keywords
130
131 StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler);
132
133 // lex source code
134 for (; scDoc.More(); scDoc.Forward())
135 {
136 //
137 // Determine if the current state should terminate.
138 //
139
140 // Label State Handling
141 if (scDoc.state == SCE_CLW_LABEL) {
142 // If the character is not a valid label
143 if (!IsALabelCharacter(scDoc.ch)) {
144 // If the character is a . (dot syntax)
145 if (scDoc.ch == '.') {
146 // Uncolour the . (dot) to default state, move forward one character,
147 // and change back to the label state.
148 scDoc.SetState(SCE_CLW_DEFAULT);
149 scDoc.Forward();
150 scDoc.SetState(SCE_CLW_LABEL);
151 }
152 // Else terminate the label state
153 else {
154 char cLabel[100]; // Label buffer
155 // Buffer the current label string
156 scDoc.GetCurrent(cLabel,sizeof(cLabel));
157 // If case insensitive, convert string to UPPERCASE to match passed keywords.
158 if (!bCaseSensitive) {
159 MakeUpperCaseString(cLabel);
160 }
161 // If label string is in the Clarion reserved keyword list
162 if (wlReservedWords.InList(cLabel)){
163 // change to error state
164 scDoc.ChangeState(SCE_CLW_ERROR);
165 }
166 // Else if label string is in the compiler directive keyword list
167 else if (wlCompilerDirectives.InList(cLabel)) {
168 // change the state to compiler directive state
169 scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
170 }
171 // Terminate the label state and set to default state
172 scDoc.SetState(SCE_CLW_DEFAULT);
173 }
174 }
175 }
176 // Keyword State Handling
177 else if (scDoc.state == SCE_CLW_KEYWORD) {
178 // If character is : (colon)
179 if (scDoc.ch == ':') {
180 char cEquate[100]; // Equate buffer
181 // Move forward to include : (colon) in buffer
182 scDoc.Forward();
183 // Buffer the equate string
184 scDoc.GetCurrent(cEquate,sizeof(cEquate));
185 // If case insensitive, convert string to UPPERCASE to match passed keywords.
186 if (!bCaseSensitive) {
187 MakeUpperCaseString(cEquate);
188 }
189 // If statement string is in the equate list
190 if (wlStandardEquates.InList(cEquate)) {
191 // Change to equate state
192 scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
193 }
194 }
195 // If the character is not a valid label character
196 else if (!IsALabelCharacter(scDoc.ch)) {
197 char cStatement[100]; // Statement buffer
198 // Buffer the statement string
199 scDoc.GetCurrent(cStatement,sizeof(cStatement));
200 // If case insensitive, convert string to UPPERCASE to match passed keywords.
201 if (!bCaseSensitive) {
202 MakeUpperCaseString(cStatement);
203 }
204 // If statement string is in the Clarion keyword list
205 if (wlClarionKeywords.InList(cStatement)) {
206 // Set to the Clarion keyword state
207 scDoc.ChangeState(SCE_CLW_KEYWORD);
208 }
209 // Else if statement string is in the compiler directive keyword list
210 else if (wlCompilerDirectives.InList(cStatement)) {
211 // Set to the compiler directive state
212 scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
213 }
214 // Else if statement string is in the builtin procedures and functions keyword list
215 else if (wlBuiltInProcsFuncs.InList(cStatement)) {
216 // Set to the builtin procedures and functions state
217 scDoc.ChangeState(SCE_CLW_BUILTIN_PROCEDURES_FUNCTION);
218 }
219 // Else if statement string is in the tructures and data types keyword list
220 else if (wlStructsDataTypes.InList(cStatement)) {
221 // Set to the structures and data types state
222 scDoc.ChangeState(SCE_CLW_STRUCTURE_DATA_TYPE);
223 }
224 // Else if statement string is in the procedure attribute keyword list
225 else if (wlAttributes.InList(cStatement)) {
226 // Set to the procedure attribute state
227 scDoc.ChangeState(SCE_CLW_ATTRIBUTE);
228 }
229 // Else if statement string is in the standard equate keyword list
230 else if (wlStandardEquates.InList(cStatement)) {
231 // Set to the standard equate state
232 scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
233 }
234 // Terminate the keyword state and set to default state
235 scDoc.SetState(SCE_CLW_DEFAULT);
236 }
237 }
238 // String State Handling
239 else if (scDoc.state == SCE_CLW_STRING) {
240 // If the character is an ' (single quote)
241 if (scDoc.ch == '\'') {
242 // Set the state to default and move forward colouring
243 // the ' (single quote) as default state
244 // terminating the string state
245 scDoc.SetState(SCE_CLW_DEFAULT);
246 scDoc.Forward();
247 }
248 // If the next character is an ' (single quote)
249 if (scDoc.chNext == '\'') {
250 // Move forward one character and set to default state
251 // colouring the next ' (single quote) as default state
252 // terminating the string state
253 scDoc.ForwardSetState(SCE_CLW_DEFAULT);
254 scDoc.Forward();
255 }
256 }
257 // Picture String State Handling
258 else if (scDoc.state == SCE_CLW_PICTURE_STRING) {
259 // If the character is an ( (open parenthese)
260 if (scDoc.ch == '(') {
261 // Increment the parenthese level
262 iParenthesesLevel++;
263 }
264 // Else if the character is a ) (close parenthese)
265 else if (scDoc.ch == ')') {
266 // If the parenthese level is set to zero
267 // parentheses matched
268 if (!iParenthesesLevel) {
269 scDoc.SetState(SCE_CLW_DEFAULT);
270 }
271 // Else parenthese level is greater than zero
272 // still looking for matching parentheses
273 else {
274 // Decrement the parenthese level
275 iParenthesesLevel--;
276 }
277 }
278 }
279 // Standard Equate State Handling
280 else if (scDoc.state == SCE_CLW_STANDARD_EQUATE) {
281 if (!isalnum(scDoc.ch)) {
282 scDoc.SetState(SCE_CLW_DEFAULT);
283 }
284 }
285 // Integer Constant State Handling
286 else if (scDoc.state == SCE_CLW_INTEGER_CONSTANT) {
287 // If the character is not a digit (0-9)
288 // or character is not a hexidecimal character (A-F)
289 // or character is not a . (point)
290 // or character is not a numberic base character (B,O,H)
291 if (!(isdigit(scDoc.ch)
292 || IsAHexCharacter(scDoc.ch, bCaseSensitive)
293 || scDoc.ch == '.'
294 || IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) {
295 // If the number was a real
296 if (SetNumericConstantState(scDoc)) {
297 // Colour the matched string to the real constant state
298 scDoc.ChangeState(SCE_CLW_REAL_CONSTANT);
299 }
300 // Else the number was an integer
301 else {
302 // Colour the matched string to an integer constant state
303 scDoc.ChangeState(SCE_CLW_INTEGER_CONSTANT);
304 }
305 // Terminate the integer constant state and set to default state
306 scDoc.SetState(SCE_CLW_DEFAULT);
307 }
308 }
309
310 //
311 // Determine if a new state should be entered.
312 //
313
314 // Beginning of Line Handling
315 if (scDoc.atLineStart) {
316 // If column 1 character is a label start character
317 if (IsALabelStart(scDoc.ch)) {
318 // Set the state to label
319 scDoc.SetState(SCE_CLW_LABEL);
320 }
321 // else if character is a space or tab
322 else if (IsASpace(scDoc.ch)){
323 // Set to default state
324 scDoc.SetState(SCE_CLW_DEFAULT);
325 }
326 // else if the start of a comment or is an * (asterisk)
327 else if (IsACommentStart(scDoc) || scDoc.ch == '*' ) {
328 // then set the state to comment.
329 scDoc.SetState(SCE_CLW_COMMENT);
330 }
331 // else the character is a ? (question mark)
332 else if (scDoc.ch == '?') {
333 // Change to the compiler directive state, move forward,
334 // colouring the ? (question mark), change back to default state.
335 scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
336 scDoc.Forward();
337 scDoc.SetState(SCE_CLW_DEFAULT);
338 }
339 // else an invalid character in column 1
340 else {
341 // Set to error state
342 scDoc.SetState(SCE_CLW_ERROR);
343 }
344 }
345 // End of Line Handling
346 else if (scDoc.atLineEnd) {
347 // Reset to the default state at the end of each line.
348 scDoc.SetState(SCE_CLW_DEFAULT);
349 }
350 // Default Handling
351 else {
352 // If in default state
353 if (scDoc.state == SCE_CLW_DEFAULT) {
354 // If is a letter could be a possible statement
355 if (isalpha(scDoc.ch)) {
356 // Set the state to Clarion Keyword and verify later
357 scDoc.SetState(SCE_CLW_KEYWORD);
358 }
359 // else is a number
360 else if (isdigit(scDoc.ch)) {
361 // Set the state to Integer Constant and verify later
362 scDoc.SetState(SCE_CLW_INTEGER_CONSTANT);
363 }
364 // else if the start of a comment or a | (line continuation)
365 else if (IsACommentStart(scDoc) || scDoc.ch == '|') {
366 // then set the state to comment.
367 scDoc.SetState(SCE_CLW_COMMENT);
368 }
369 // else if the character is a ' (single quote)
370 else if (scDoc.ch == '\'') {
371 // If the character is also a ' (single quote)
372 // Embedded Apostrophe
373 if (scDoc.chNext == '\'') {
374 // Move forward colouring it as default state
375 scDoc.ForwardSetState(SCE_CLW_DEFAULT);
376 }
377 else {
378 // move to the next character and then set the state to comment.
379 scDoc.ForwardSetState(SCE_CLW_STRING);
380 }
381 }
382 // else the character is an @ (apersand)
383 else if (scDoc.ch == '@') {
384 // Case insensitive.
385 if (!bCaseSensitive) {
386 // If character is a valid picture token character
387 if (strchr("DEKNPSTdeknpst", scDoc.chNext) != NULL) {
388 // Set to the picture string state
389 scDoc.SetState(SCE_CLW_PICTURE_STRING);
390 }
391 }
392 // Case sensitive
393 else {
394 // If character is a valid picture token character
395 if (strchr("DEKNPST", scDoc.chNext) != NULL) {
396 // Set the picture string state
397 scDoc.SetState(SCE_CLW_PICTURE_STRING);
398 }
399 }
400 }
401 }
402 }
403 }
404 // lexing complete
405 scDoc.Complete();
406}
407
408// Clarion Language Case Sensitive Colouring Procedure
409static void ColouriseClwDocSensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
410 ColouriseClwDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true);
411}
412
413// Clarion Language Case Insensitive Colouring Procedure
414static void ColouriseClwDocInsensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
415 ColouriseClwDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false);
416}
417
418// Clarion Language Folding Procedure
419#ifdef FOLDING_IMPLEMENTED
420static void FoldClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
421
422}
423#endif
424
425// Word List Descriptions
426static const char * const rgWordListDescriptions[] = {
427 "Clarion Keywords",
428 "Compiler Directives",
429 "Built-in Procedures and Functions",
430 "Structure and Data Types",
431 "Attributes",
432 "Standard Equates",
433 "Reserved Words",
434 0,
435};
436
437// Case Sensitive Clarion Language Lexer
438LexerModule lmClw(SCLEX_CLW, ColouriseClwDocSensitive, "clw", NULL, rgWordListDescriptions);
439
440// Case Insensitive Clarion Language Lexer
441LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClwDocInsensitive, "clwnocase", NULL, rgWordListDescriptions);