]>
Commit | Line | Data |
---|---|---|
8e54aaed RD |
1 | // Scintilla source code edit control |
2 | /** @file LexClw.cxx | |
3 | ** Lexer for Clarion. | |
1e9bafca | 4 | ** 2004/12/17 Updated Lexer |
8e54aaed | 5 | **/ |
1e9bafca | 6 | // Copyright 2003-2004 by Ron Schofield <ron@schofieldcomputer.com> |
8e54aaed RD |
7 | // The License.txt file describes the conditions under which this software may be distributed. |
8 | ||
9 | #include <stdlib.h> | |
10 | #include <string.h> | |
8e54aaed RD |
11 | #include <stdio.h> |
12 | #include <stdarg.h> | |
1dcf666d | 13 | #include <assert.h> |
1e9bafca | 14 | #include <ctype.h> |
8e54aaed | 15 | |
1dcf666d RD |
16 | #include "ILexer.h" |
17 | #include "Scintilla.h" | |
18 | #include "SciLexer.h" | |
8e54aaed | 19 | |
1dcf666d RD |
20 | #include "WordList.h" |
21 | #include "LexAccessor.h" | |
8e54aaed RD |
22 | #include "Accessor.h" |
23 | #include "StyleContext.h" | |
1dcf666d RD |
24 | #include "CharacterSet.h" |
25 | #include "LexerModule.h" | |
8e54aaed | 26 | |
7e0c58e9 RD |
27 | #ifdef SCI_NAMESPACE |
28 | using namespace Scintilla; | |
29 | #endif | |
30 | ||
1e9bafca RD |
31 | // Is an end of line character |
32 | inline bool IsEOL(const int ch) { | |
33 | ||
34 | return(ch == '\n'); | |
35 | } | |
36 | ||
37 | // Convert character to uppercase | |
38 | static char CharacterUpper(char chChar) { | |
39 | ||
40 | if (chChar < 'a' || chChar > 'z') { | |
41 | return(chChar); | |
42 | } | |
43 | else { | |
44 | return(static_cast<char>(chChar - 'a' + 'A')); | |
45 | } | |
8e54aaed RD |
46 | } |
47 | ||
1e9bafca RD |
48 | // Convert string to uppercase |
49 | static void StringUpper(char *szString) { | |
50 | ||
51 | while (*szString) { | |
52 | *szString = CharacterUpper(*szString); | |
53 | szString++; | |
8e54aaed RD |
54 | } |
55 | } | |
56 | ||
57 | // Is a label start character | |
58 | inline bool IsALabelStart(const int iChar) { | |
1e9bafca | 59 | |
8e54aaed RD |
60 | return(isalpha(iChar) || iChar == '_'); |
61 | } | |
62 | ||
63 | // Is a label character | |
64 | inline bool IsALabelCharacter(const int iChar) { | |
1e9bafca | 65 | |
1dcf666d | 66 | return(isalnum(iChar) || iChar == '_' || iChar == ':'); |
8e54aaed RD |
67 | } |
68 | ||
1dcf666d | 69 | // Is the character is a ! and the the next character is not a ! |
1e9bafca RD |
70 | inline bool IsACommentStart(const int iChar) { |
71 | ||
72 | return(iChar == '!'); | |
8e54aaed RD |
73 | } |
74 | ||
75 | // Is the character a Clarion hex character (ABCDEF) | |
76 | inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) { | |
1e9bafca | 77 | |
8e54aaed RD |
78 | // Case insensitive. |
79 | if (!bCaseSensitive) { | |
80 | if (strchr("ABCDEFabcdef", iChar) != NULL) { | |
81 | return(true); | |
82 | } | |
83 | } | |
84 | // Case sensitive | |
85 | else { | |
86 | if (strchr("ABCDEF", iChar) != NULL) { | |
87 | return(true); | |
88 | } | |
89 | } | |
90 | return(false); | |
91 | } | |
92 | ||
93 | // Is the character a Clarion base character (B=Binary, O=Octal, H=Hex) | |
94 | inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) { | |
1e9bafca | 95 | |
8e54aaed RD |
96 | // Case insensitive. |
97 | if (!bCaseSensitive) { | |
98 | // If character is a numeric base character | |
99 | if (strchr("BOHboh", iChar) != NULL) { | |
100 | return(true); | |
101 | } | |
102 | } | |
103 | // Case sensitive | |
104 | else { | |
105 | // If character is a numeric base character | |
106 | if (strchr("BOH", iChar) != NULL) { | |
107 | return(true); | |
108 | } | |
109 | } | |
110 | return(false); | |
111 | } | |
112 | ||
113 | // Set the correct numeric constant state | |
114 | inline bool SetNumericConstantState(StyleContext &scDoc) { | |
1e9bafca | 115 | |
8e54aaed | 116 | int iPoints = 0; // Point counter |
1e9bafca | 117 | char cNumericString[512]; // Numeric string buffer |
8e54aaed RD |
118 | |
119 | // Buffer the current numberic string | |
120 | scDoc.GetCurrent(cNumericString, sizeof(cNumericString)); | |
121 | // Loop through the string until end of string (NULL termination) | |
122 | for (int iIndex = 0; cNumericString[iIndex] != '\0'; iIndex++) { | |
123 | // Depending on the character | |
124 | switch (cNumericString[iIndex]) { | |
125 | // Is a . (point) | |
126 | case '.' : | |
127 | // Increment point counter | |
128 | iPoints++; | |
129 | break; | |
130 | default : | |
131 | break; | |
1dcf666d | 132 | } |
8e54aaed RD |
133 | } |
134 | // If points found (can be more than one for improper formatted number | |
135 | if (iPoints > 0) { | |
136 | return(true); | |
137 | } | |
138 | // Else no points found | |
139 | else { | |
140 | return(false); | |
141 | } | |
142 | } | |
143 | ||
1e9bafca RD |
144 | // Get the next word in uppercase from the current position (keyword lookahead) |
145 | inline bool GetNextWordUpper(Accessor &styler, unsigned int uiStartPos, int iLength, char *cWord) { | |
146 | ||
147 | unsigned int iIndex = 0; // Buffer Index | |
148 | ||
149 | // Loop through the remaining string from the current position | |
150 | for (int iOffset = uiStartPos; iOffset < iLength; iOffset++) { | |
151 | // Get the character from the buffer using the offset | |
152 | char cCharacter = styler[iOffset]; | |
153 | if (IsEOL(cCharacter)) { | |
154 | break; | |
155 | } | |
156 | // If the character is alphabet character | |
157 | if (isalpha(cCharacter)) { | |
158 | // Add UPPERCASE character to the word buffer | |
159 | cWord[iIndex++] = CharacterUpper(cCharacter); | |
160 | } | |
161 | } | |
162 | // Add null termination | |
163 | cWord[iIndex] = '\0'; | |
164 | // If no word was found | |
165 | if (iIndex == 0) { | |
166 | // Return failure | |
167 | return(false); | |
168 | } | |
169 | // Else word was found | |
170 | else { | |
171 | // Return success | |
172 | return(true); | |
173 | } | |
174 | } | |
175 | ||
8e54aaed | 176 | // Clarion Language Colouring Procedure |
1e9bafca RD |
177 | static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) { |
178 | ||
179 | int iParenthesesLevel = 0; // Parenthese Level | |
180 | int iColumn1Label = false; // Label starts in Column 1 | |
181 | ||
182 | WordList &wlClarionKeywords = *wlKeywords[0]; // Clarion Keywords | |
183 | WordList &wlCompilerDirectives = *wlKeywords[1]; // Compiler Directives | |
184 | WordList &wlRuntimeExpressions = *wlKeywords[2]; // Runtime Expressions | |
185 | WordList &wlBuiltInProcsFuncs = *wlKeywords[3]; // Builtin Procedures and Functions | |
186 | WordList &wlStructsDataTypes = *wlKeywords[4]; // Structures and Data Types | |
187 | WordList &wlAttributes = *wlKeywords[5]; // Procedure Attributes | |
188 | WordList &wlStandardEquates = *wlKeywords[6]; // Standard Equates | |
189 | WordList &wlLabelReservedWords = *wlKeywords[7]; // Clarion Reserved Keywords (Labels) | |
190 | WordList &wlProcLabelReservedWords = *wlKeywords[8]; // Clarion Reserved Keywords (Procedure Labels) | |
8e54aaed | 191 | |
1dcf666d | 192 | const char wlProcReservedKeywordList[] = |
1e9bafca RD |
193 | "PROCEDURE FUNCTION"; |
194 | WordList wlProcReservedKeywords; | |
195 | wlProcReservedKeywords.Set(wlProcReservedKeywordList); | |
8e54aaed | 196 | |
1dcf666d | 197 | const char wlCompilerKeywordList[] = |
1e9bafca RD |
198 | "COMPILE OMIT"; |
199 | WordList wlCompilerKeywords; | |
200 | wlCompilerKeywords.Set(wlCompilerKeywordList); | |
201 | ||
202 | const char wlLegacyStatementsList[] = | |
203 | "BOF EOF FUNCTION POINTER SHARE"; | |
204 | WordList wlLegacyStatements; | |
205 | wlLegacyStatements.Set(wlLegacyStatementsList); | |
8e54aaed RD |
206 | |
207 | StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler); | |
208 | ||
209 | // lex source code | |
210 | for (; scDoc.More(); scDoc.Forward()) | |
211 | { | |
212 | // | |
213 | // Determine if the current state should terminate. | |
214 | // | |
215 | ||
216 | // Label State Handling | |
217 | if (scDoc.state == SCE_CLW_LABEL) { | |
218 | // If the character is not a valid label | |
219 | if (!IsALabelCharacter(scDoc.ch)) { | |
220 | // If the character is a . (dot syntax) | |
221 | if (scDoc.ch == '.') { | |
1e9bafca RD |
222 | // Turn off column 1 label flag as label now cannot be reserved work |
223 | iColumn1Label = false; | |
8e54aaed RD |
224 | // Uncolour the . (dot) to default state, move forward one character, |
225 | // and change back to the label state. | |
226 | scDoc.SetState(SCE_CLW_DEFAULT); | |
227 | scDoc.Forward(); | |
228 | scDoc.SetState(SCE_CLW_LABEL); | |
229 | } | |
1e9bafca | 230 | // Else check label |
8e54aaed | 231 | else { |
1e9bafca | 232 | char cLabel[512]; // Label buffer |
8e54aaed RD |
233 | // Buffer the current label string |
234 | scDoc.GetCurrent(cLabel,sizeof(cLabel)); | |
235 | // If case insensitive, convert string to UPPERCASE to match passed keywords. | |
236 | if (!bCaseSensitive) { | |
1e9bafca | 237 | StringUpper(cLabel); |
8e54aaed | 238 | } |
1e9bafca RD |
239 | // Else if UPPERCASE label string is in the Clarion compiler keyword list |
240 | if (wlCompilerKeywords.InList(cLabel) && iColumn1Label){ | |
241 | // change the label to error state | |
242 | scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); | |
243 | } | |
244 | // Else if UPPERCASE label string is in the Clarion reserved keyword list | |
245 | else if (wlLabelReservedWords.InList(cLabel) && iColumn1Label){ | |
246 | // change the label to error state | |
8e54aaed RD |
247 | scDoc.ChangeState(SCE_CLW_ERROR); |
248 | } | |
1dcf666d | 249 | // Else if UPPERCASE label string is |
1e9bafca RD |
250 | else if (wlProcLabelReservedWords.InList(cLabel) && iColumn1Label) { |
251 | char cWord[512]; // Word buffer | |
252 | // Get the next word from the current position | |
253 | if (GetNextWordUpper(accStyler,scDoc.currentPos,uiStartPos+iLength,cWord)) { | |
254 | // If the next word is a procedure reserved word | |
255 | if (wlProcReservedKeywords.InList(cWord)) { | |
256 | // Change the label to error state | |
257 | scDoc.ChangeState(SCE_CLW_ERROR); | |
258 | } | |
259 | } | |
260 | } | |
8e54aaed RD |
261 | // Else if label string is in the compiler directive keyword list |
262 | else if (wlCompilerDirectives.InList(cLabel)) { | |
263 | // change the state to compiler directive state | |
264 | scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); | |
265 | } | |
266 | // Terminate the label state and set to default state | |
267 | scDoc.SetState(SCE_CLW_DEFAULT); | |
268 | } | |
269 | } | |
270 | } | |
271 | // Keyword State Handling | |
272 | else if (scDoc.state == SCE_CLW_KEYWORD) { | |
273 | // If character is : (colon) | |
274 | if (scDoc.ch == ':') { | |
1e9bafca | 275 | char cEquate[512]; // Equate buffer |
8e54aaed RD |
276 | // Move forward to include : (colon) in buffer |
277 | scDoc.Forward(); | |
278 | // Buffer the equate string | |
279 | scDoc.GetCurrent(cEquate,sizeof(cEquate)); | |
280 | // If case insensitive, convert string to UPPERCASE to match passed keywords. | |
281 | if (!bCaseSensitive) { | |
1e9bafca | 282 | StringUpper(cEquate); |
8e54aaed RD |
283 | } |
284 | // If statement string is in the equate list | |
285 | if (wlStandardEquates.InList(cEquate)) { | |
286 | // Change to equate state | |
287 | scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE); | |
288 | } | |
289 | } | |
290 | // If the character is not a valid label character | |
291 | else if (!IsALabelCharacter(scDoc.ch)) { | |
1e9bafca | 292 | char cStatement[512]; // Statement buffer |
8e54aaed RD |
293 | // Buffer the statement string |
294 | scDoc.GetCurrent(cStatement,sizeof(cStatement)); | |
295 | // If case insensitive, convert string to UPPERCASE to match passed keywords. | |
296 | if (!bCaseSensitive) { | |
1e9bafca | 297 | StringUpper(cStatement); |
8e54aaed RD |
298 | } |
299 | // If statement string is in the Clarion keyword list | |
300 | if (wlClarionKeywords.InList(cStatement)) { | |
1e9bafca | 301 | // Change the statement string to the Clarion keyword state |
8e54aaed RD |
302 | scDoc.ChangeState(SCE_CLW_KEYWORD); |
303 | } | |
304 | // Else if statement string is in the compiler directive keyword list | |
305 | else if (wlCompilerDirectives.InList(cStatement)) { | |
1e9bafca | 306 | // Change the statement string to the compiler directive state |
8e54aaed RD |
307 | scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); |
308 | } | |
1e9bafca RD |
309 | // Else if statement string is in the runtime expressions keyword list |
310 | else if (wlRuntimeExpressions.InList(cStatement)) { | |
311 | // Change the statement string to the runtime expressions state | |
312 | scDoc.ChangeState(SCE_CLW_RUNTIME_EXPRESSIONS); | |
313 | } | |
8e54aaed RD |
314 | // Else if statement string is in the builtin procedures and functions keyword list |
315 | else if (wlBuiltInProcsFuncs.InList(cStatement)) { | |
1e9bafca | 316 | // Change the statement string to the builtin procedures and functions state |
8e54aaed RD |
317 | scDoc.ChangeState(SCE_CLW_BUILTIN_PROCEDURES_FUNCTION); |
318 | } | |
319 | // Else if statement string is in the tructures and data types keyword list | |
320 | else if (wlStructsDataTypes.InList(cStatement)) { | |
1e9bafca | 321 | // Change the statement string to the structures and data types state |
8e54aaed RD |
322 | scDoc.ChangeState(SCE_CLW_STRUCTURE_DATA_TYPE); |
323 | } | |
324 | // Else if statement string is in the procedure attribute keyword list | |
325 | else if (wlAttributes.InList(cStatement)) { | |
1e9bafca | 326 | // Change the statement string to the procedure attribute state |
8e54aaed RD |
327 | scDoc.ChangeState(SCE_CLW_ATTRIBUTE); |
328 | } | |
329 | // Else if statement string is in the standard equate keyword list | |
330 | else if (wlStandardEquates.InList(cStatement)) { | |
1e9bafca | 331 | // Change the statement string to the standard equate state |
8e54aaed RD |
332 | scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE); |
333 | } | |
1e9bafca RD |
334 | // Else if statement string is in the deprecated or legacy keyword list |
335 | else if (wlLegacyStatements.InList(cStatement)) { | |
336 | // Change the statement string to the standard equate state | |
337 | scDoc.ChangeState(SCE_CLW_DEPRECATED); | |
338 | } | |
339 | // Else the statement string doesn't match any work list | |
340 | else { | |
341 | // Change the statement string to the default state | |
342 | scDoc.ChangeState(SCE_CLW_DEFAULT); | |
343 | } | |
8e54aaed RD |
344 | // Terminate the keyword state and set to default state |
345 | scDoc.SetState(SCE_CLW_DEFAULT); | |
346 | } | |
347 | } | |
348 | // String State Handling | |
349 | else if (scDoc.state == SCE_CLW_STRING) { | |
350 | // If the character is an ' (single quote) | |
351 | if (scDoc.ch == '\'') { | |
352 | // Set the state to default and move forward colouring | |
353 | // the ' (single quote) as default state | |
354 | // terminating the string state | |
355 | scDoc.SetState(SCE_CLW_DEFAULT); | |
356 | scDoc.Forward(); | |
357 | } | |
358 | // If the next character is an ' (single quote) | |
359 | if (scDoc.chNext == '\'') { | |
360 | // Move forward one character and set to default state | |
361 | // colouring the next ' (single quote) as default state | |
362 | // terminating the string state | |
363 | scDoc.ForwardSetState(SCE_CLW_DEFAULT); | |
364 | scDoc.Forward(); | |
365 | } | |
366 | } | |
367 | // Picture String State Handling | |
368 | else if (scDoc.state == SCE_CLW_PICTURE_STRING) { | |
369 | // If the character is an ( (open parenthese) | |
370 | if (scDoc.ch == '(') { | |
371 | // Increment the parenthese level | |
372 | iParenthesesLevel++; | |
373 | } | |
1dcf666d | 374 | // Else if the character is a ) (close parenthese) |
8e54aaed RD |
375 | else if (scDoc.ch == ')') { |
376 | // If the parenthese level is set to zero | |
377 | // parentheses matched | |
378 | if (!iParenthesesLevel) { | |
379 | scDoc.SetState(SCE_CLW_DEFAULT); | |
1dcf666d | 380 | } |
8e54aaed RD |
381 | // Else parenthese level is greater than zero |
382 | // still looking for matching parentheses | |
383 | else { | |
384 | // Decrement the parenthese level | |
385 | iParenthesesLevel--; | |
386 | } | |
387 | } | |
388 | } | |
389 | // Standard Equate State Handling | |
390 | else if (scDoc.state == SCE_CLW_STANDARD_EQUATE) { | |
391 | if (!isalnum(scDoc.ch)) { | |
392 | scDoc.SetState(SCE_CLW_DEFAULT); | |
393 | } | |
394 | } | |
395 | // Integer Constant State Handling | |
396 | else if (scDoc.state == SCE_CLW_INTEGER_CONSTANT) { | |
397 | // If the character is not a digit (0-9) | |
398 | // or character is not a hexidecimal character (A-F) | |
399 | // or character is not a . (point) | |
400 | // or character is not a numberic base character (B,O,H) | |
401 | if (!(isdigit(scDoc.ch) | |
402 | || IsAHexCharacter(scDoc.ch, bCaseSensitive) | |
403 | || scDoc.ch == '.' | |
404 | || IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) { | |
1dcf666d | 405 | // If the number was a real |
8e54aaed RD |
406 | if (SetNumericConstantState(scDoc)) { |
407 | // Colour the matched string to the real constant state | |
408 | scDoc.ChangeState(SCE_CLW_REAL_CONSTANT); | |
409 | } | |
410 | // Else the number was an integer | |
411 | else { | |
412 | // Colour the matched string to an integer constant state | |
413 | scDoc.ChangeState(SCE_CLW_INTEGER_CONSTANT); | |
414 | } | |
415 | // Terminate the integer constant state and set to default state | |
416 | scDoc.SetState(SCE_CLW_DEFAULT); | |
417 | } | |
418 | } | |
419 | ||
420 | // | |
421 | // Determine if a new state should be entered. | |
422 | // | |
423 | ||
424 | // Beginning of Line Handling | |
425 | if (scDoc.atLineStart) { | |
1e9bafca RD |
426 | // Reset the column 1 label flag |
427 | iColumn1Label = false; | |
8e54aaed RD |
428 | // If column 1 character is a label start character |
429 | if (IsALabelStart(scDoc.ch)) { | |
1e9bafca RD |
430 | // Label character is found in column 1 |
431 | // so set column 1 label flag and clear last column 1 label | |
432 | iColumn1Label = true; | |
8e54aaed RD |
433 | // Set the state to label |
434 | scDoc.SetState(SCE_CLW_LABEL); | |
435 | } | |
436 | // else if character is a space or tab | |
437 | else if (IsASpace(scDoc.ch)){ | |
438 | // Set to default state | |
439 | scDoc.SetState(SCE_CLW_DEFAULT); | |
440 | } | |
1e9bafca RD |
441 | // else if comment start (!) or is an * (asterisk) |
442 | else if (IsACommentStart(scDoc.ch) || scDoc.ch == '*' ) { | |
8e54aaed RD |
443 | // then set the state to comment. |
444 | scDoc.SetState(SCE_CLW_COMMENT); | |
445 | } | |
446 | // else the character is a ? (question mark) | |
447 | else if (scDoc.ch == '?') { | |
448 | // Change to the compiler directive state, move forward, | |
449 | // colouring the ? (question mark), change back to default state. | |
450 | scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); | |
451 | scDoc.Forward(); | |
452 | scDoc.SetState(SCE_CLW_DEFAULT); | |
453 | } | |
454 | // else an invalid character in column 1 | |
455 | else { | |
456 | // Set to error state | |
457 | scDoc.SetState(SCE_CLW_ERROR); | |
458 | } | |
459 | } | |
460 | // End of Line Handling | |
461 | else if (scDoc.atLineEnd) { | |
462 | // Reset to the default state at the end of each line. | |
463 | scDoc.SetState(SCE_CLW_DEFAULT); | |
464 | } | |
465 | // Default Handling | |
466 | else { | |
1dcf666d | 467 | // If in default state |
8e54aaed RD |
468 | if (scDoc.state == SCE_CLW_DEFAULT) { |
469 | // If is a letter could be a possible statement | |
470 | if (isalpha(scDoc.ch)) { | |
471 | // Set the state to Clarion Keyword and verify later | |
472 | scDoc.SetState(SCE_CLW_KEYWORD); | |
473 | } | |
474 | // else is a number | |
475 | else if (isdigit(scDoc.ch)) { | |
476 | // Set the state to Integer Constant and verify later | |
477 | scDoc.SetState(SCE_CLW_INTEGER_CONSTANT); | |
478 | } | |
479 | // else if the start of a comment or a | (line continuation) | |
1e9bafca | 480 | else if (IsACommentStart(scDoc.ch) || scDoc.ch == '|') { |
8e54aaed RD |
481 | // then set the state to comment. |
482 | scDoc.SetState(SCE_CLW_COMMENT); | |
1dcf666d | 483 | } |
8e54aaed RD |
484 | // else if the character is a ' (single quote) |
485 | else if (scDoc.ch == '\'') { | |
1dcf666d | 486 | // If the character is also a ' (single quote) |
8e54aaed RD |
487 | // Embedded Apostrophe |
488 | if (scDoc.chNext == '\'') { | |
489 | // Move forward colouring it as default state | |
490 | scDoc.ForwardSetState(SCE_CLW_DEFAULT); | |
491 | } | |
492 | else { | |
493 | // move to the next character and then set the state to comment. | |
494 | scDoc.ForwardSetState(SCE_CLW_STRING); | |
495 | } | |
1dcf666d | 496 | } |
1e9bafca | 497 | // else the character is an @ (ampersand) |
8e54aaed RD |
498 | else if (scDoc.ch == '@') { |
499 | // Case insensitive. | |
500 | if (!bCaseSensitive) { | |
501 | // If character is a valid picture token character | |
502 | if (strchr("DEKNPSTdeknpst", scDoc.chNext) != NULL) { | |
503 | // Set to the picture string state | |
504 | scDoc.SetState(SCE_CLW_PICTURE_STRING); | |
505 | } | |
506 | } | |
507 | // Case sensitive | |
508 | else { | |
509 | // If character is a valid picture token character | |
510 | if (strchr("DEKNPST", scDoc.chNext) != NULL) { | |
511 | // Set the picture string state | |
512 | scDoc.SetState(SCE_CLW_PICTURE_STRING); | |
513 | } | |
514 | } | |
1dcf666d | 515 | } |
8e54aaed RD |
516 | } |
517 | } | |
518 | } | |
519 | // lexing complete | |
520 | scDoc.Complete(); | |
521 | } | |
522 | ||
523 | // Clarion Language Case Sensitive Colouring Procedure | |
1e9bafca RD |
524 | static void ColouriseClarionDocSensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) { |
525 | ||
526 | ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true); | |
8e54aaed RD |
527 | } |
528 | ||
529 | // Clarion Language Case Insensitive Colouring Procedure | |
1e9bafca RD |
530 | static void ColouriseClarionDocInsensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) { |
531 | ||
532 | ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false); | |
533 | } | |
534 | ||
535 | // Fill Buffer | |
536 | ||
537 | static void FillBuffer(unsigned int uiStart, unsigned int uiEnd, Accessor &accStyler, char *szBuffer, unsigned int uiLength) { | |
538 | ||
539 | unsigned int uiPos = 0; | |
540 | ||
541 | while ((uiPos < uiEnd - uiStart + 1) && (uiPos < uiLength-1)) { | |
542 | szBuffer[uiPos] = static_cast<char>(toupper(accStyler[uiStart + uiPos])); | |
543 | uiPos++; | |
544 | } | |
545 | szBuffer[uiPos] = '\0'; | |
546 | } | |
547 | ||
548 | // Classify Clarion Fold Point | |
549 | ||
550 | static int ClassifyClarionFoldPoint(int iLevel, const char* szString) { | |
551 | ||
552 | if (!(isdigit(szString[0]) || (szString[0] == '.'))) { | |
553 | if (strcmp(szString, "PROCEDURE") == 0) { | |
554 | // iLevel = SC_FOLDLEVELBASE + 1; | |
555 | } | |
556 | else if (strcmp(szString, "MAP") == 0 || | |
557 | strcmp(szString,"ACCEPT") == 0 || | |
558 | strcmp(szString,"BEGIN") == 0 || | |
559 | strcmp(szString,"CASE") == 0 || | |
560 | strcmp(szString,"EXECUTE") == 0 || | |
561 | strcmp(szString,"IF") == 0 || | |
562 | strcmp(szString,"ITEMIZE") == 0 || | |
563 | strcmp(szString,"INTERFACE") == 0 || | |
564 | strcmp(szString,"JOIN") == 0 || | |
565 | strcmp(szString,"LOOP") == 0 || | |
566 | strcmp(szString,"MODULE") == 0 || | |
567 | strcmp(szString,"RECORD") == 0) { | |
568 | iLevel++; | |
569 | } | |
570 | else if (strcmp(szString, "APPLICATION") == 0 || | |
571 | strcmp(szString, "CLASS") == 0 || | |
572 | strcmp(szString, "DETAIL") == 0 || | |
573 | strcmp(szString, "FILE") == 0 || | |
574 | strcmp(szString, "FOOTER") == 0 || | |
575 | strcmp(szString, "FORM") == 0 || | |
576 | strcmp(szString, "GROUP") == 0 || | |
577 | strcmp(szString, "HEADER") == 0 || | |
578 | strcmp(szString, "INTERFACE") == 0 || | |
579 | strcmp(szString, "MENU") == 0 || | |
580 | strcmp(szString, "MENUBAR") == 0 || | |
581 | strcmp(szString, "OLE") == 0 || | |
582 | strcmp(szString, "OPTION") == 0 || | |
583 | strcmp(szString, "QUEUE") == 0 || | |
584 | strcmp(szString, "REPORT") == 0 || | |
585 | strcmp(szString, "SHEET") == 0 || | |
586 | strcmp(szString, "TAB") == 0 || | |
587 | strcmp(szString, "TOOLBAR") == 0 || | |
588 | strcmp(szString, "VIEW") == 0 || | |
589 | strcmp(szString, "WINDOW") == 0) { | |
590 | iLevel++; | |
591 | } | |
592 | else if (strcmp(szString, "END") == 0 || | |
593 | strcmp(szString, "UNTIL") == 0 || | |
594 | strcmp(szString, "WHILE") == 0) { | |
595 | iLevel--; | |
596 | } | |
597 | } | |
598 | return(iLevel); | |
8e54aaed RD |
599 | } |
600 | ||
601 | // Clarion Language Folding Procedure | |
1e9bafca RD |
602 | static void FoldClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *[], Accessor &accStyler) { |
603 | ||
604 | unsigned int uiEndPos = uiStartPos + iLength; | |
605 | int iLineCurrent = accStyler.GetLine(uiStartPos); | |
606 | int iLevelPrev = accStyler.LevelAt(iLineCurrent) & SC_FOLDLEVELNUMBERMASK; | |
607 | int iLevelCurrent = iLevelPrev; | |
608 | char chNext = accStyler[uiStartPos]; | |
609 | int iStyle = iInitStyle; | |
610 | int iStyleNext = accStyler.StyleAt(uiStartPos); | |
611 | int iVisibleChars = 0; | |
612 | int iLastStart = 0; | |
613 | ||
614 | for (unsigned int uiPos = uiStartPos; uiPos < uiEndPos; uiPos++) { | |
615 | ||
616 | char chChar = chNext; | |
617 | chNext = accStyler.SafeGetCharAt(uiPos + 1); | |
618 | int iStylePrev = iStyle; | |
619 | iStyle = iStyleNext; | |
620 | iStyleNext = accStyler.StyleAt(uiPos + 1); | |
621 | bool bEOL = (chChar == '\r' && chNext != '\n') || (chChar == '\n'); | |
1dcf666d | 622 | |
1e9bafca RD |
623 | if (iStylePrev == SCE_CLW_DEFAULT) { |
624 | if (iStyle == SCE_CLW_KEYWORD || iStyle == SCE_CLW_STRUCTURE_DATA_TYPE) { | |
625 | // Store last word start point. | |
626 | iLastStart = uiPos; | |
627 | } | |
628 | } | |
629 | ||
630 | if (iStylePrev == SCE_CLW_KEYWORD || iStylePrev == SCE_CLW_STRUCTURE_DATA_TYPE) { | |
631 | if(iswordchar(chChar) && !iswordchar(chNext)) { | |
632 | char chBuffer[100]; | |
633 | FillBuffer(iLastStart, uiPos, accStyler, chBuffer, sizeof(chBuffer)); | |
634 | iLevelCurrent = ClassifyClarionFoldPoint(iLevelCurrent,chBuffer); | |
635 | // if ((iLevelCurrent == SC_FOLDLEVELBASE + 1) && iLineCurrent > 1) { | |
636 | // accStyler.SetLevel(iLineCurrent-1,SC_FOLDLEVELBASE); | |
637 | // iLevelPrev = SC_FOLDLEVELBASE; | |
638 | // } | |
639 | } | |
640 | } | |
641 | ||
642 | if (bEOL) { | |
643 | int iLevel = iLevelPrev; | |
644 | if ((iLevelCurrent > iLevelPrev) && (iVisibleChars > 0)) | |
645 | iLevel |= SC_FOLDLEVELHEADERFLAG; | |
646 | if (iLevel != accStyler.LevelAt(iLineCurrent)) { | |
647 | accStyler.SetLevel(iLineCurrent,iLevel); | |
648 | } | |
649 | iLineCurrent++; | |
650 | iLevelPrev = iLevelCurrent; | |
651 | iVisibleChars = 0; | |
652 | } | |
1dcf666d | 653 | |
1e9bafca RD |
654 | if (!isspacechar(chChar)) |
655 | iVisibleChars++; | |
656 | } | |
8e54aaed | 657 | |
1e9bafca RD |
658 | // Fill in the real level of the next line, keeping the current flags |
659 | // as they will be filled in later. | |
660 | int iFlagsNext = accStyler.LevelAt(iLineCurrent) & ~SC_FOLDLEVELNUMBERMASK; | |
661 | accStyler.SetLevel(iLineCurrent, iLevelPrev | iFlagsNext); | |
8e54aaed | 662 | } |
8e54aaed RD |
663 | |
664 | // Word List Descriptions | |
665 | static const char * const rgWordListDescriptions[] = { | |
666 | "Clarion Keywords", | |
667 | "Compiler Directives", | |
668 | "Built-in Procedures and Functions", | |
1e9bafca | 669 | "Runtime Expressions", |
8e54aaed RD |
670 | "Structure and Data Types", |
671 | "Attributes", | |
672 | "Standard Equates", | |
1e9bafca RD |
673 | "Reserved Words (Labels)", |
674 | "Reserved Words (Procedure Labels)", | |
8e54aaed RD |
675 | 0, |
676 | }; | |
677 | ||
678 | // Case Sensitive Clarion Language Lexer | |
1e9bafca | 679 | LexerModule lmClw(SCLEX_CLW, ColouriseClarionDocSensitive, "clarion", FoldClarionDoc, rgWordListDescriptions); |
8e54aaed RD |
680 | |
681 | // Case Insensitive Clarion Language Lexer | |
1e9bafca | 682 | LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClarionDocInsensitive, "clarionnocase", FoldClarionDoc, rgWordListDescriptions); |