*** empty log message ***
[anjuta-git-plugin.git] / scintilla / LexCLW.cxx
blobe5240776cc0d59656dad979d599333ff8998efa7
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.
8 #include <stdlib.h>
9 #include <string.h>
10 #include <ctype.h>
11 #include <stdio.h>
12 #include <stdarg.h>
14 #include "Platform.h"
16 #include "PropSet.h"
17 #include "Accessor.h"
18 #include "StyleContext.h"
19 #include "KeyWords.h"
20 #include "Scintilla.h"
21 #include "SciLexer.h"
23 static char MakeUpperCase(char ch) {
24 if (ch < 'a' || ch > 'z')
25 return ch;
26 else
27 return static_cast<char>(ch - 'a' + 'A');
30 static void MakeUpperCaseString(char *s) {
31 while (*s) {
32 *s = MakeUpperCase(*s);
33 s++;
37 // Is a label start character
38 inline bool IsALabelStart(const int iChar) {
39 return(isalpha(iChar) || iChar == '_');
42 // Is a label character
43 inline bool IsALabelCharacter(const int iChar) {
44 return(isalnum(iChar) || iChar == '_' || iChar == ':');
47 // Is the character is a ! and the the next character is not a !
48 inline bool IsACommentStart(StyleContext &scDoc) {
49 return(scDoc.ch == '!' && scDoc.chNext != '!');
52 // Is the character a Clarion hex character (ABCDEF)
53 inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) {
54 // Case insensitive.
55 if (!bCaseSensitive) {
56 if (strchr("ABCDEFabcdef", iChar) != NULL) {
57 return(true);
60 // Case sensitive
61 else {
62 if (strchr("ABCDEF", iChar) != NULL) {
63 return(true);
66 return(false);
69 // Is the character a Clarion base character (B=Binary, O=Octal, H=Hex)
70 inline 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);
78 // Case sensitive
79 else {
80 // If character is a numeric base character
81 if (strchr("BOH", iChar) != NULL) {
82 return(true);
85 return(false);
88 // Set the correct numeric constant state
89 inline bool SetNumericConstantState(StyleContext &scDoc) {
90 int iPoints = 0; // Point counter
91 char cNumericString[100]; // Numeric string buffer
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;
108 // If points found (can be more than one for improper formatted number
109 if (iPoints > 0) {
110 return(true);
112 // Else no points found
113 else {
114 return(false);
118 // Clarion Language Colouring Procedure
119 static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) {
121 int iParenthesesLevel=0; // Parenthese Level
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
131 StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler);
133 // lex source code
134 for (; scDoc.More(); scDoc.Forward())
137 // Determine if the current state should terminate.
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);
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);
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);
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);
171 // Terminate the label state and set to default state
172 scDoc.SetState(SCE_CLW_DEFAULT);
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);
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);
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);
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);
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);
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);
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);
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);
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);
234 // Terminate the keyword state and set to default state
235 scDoc.SetState(SCE_CLW_DEFAULT);
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();
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();
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++;
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);
271 // Else parenthese level is greater than zero
272 // still looking for matching parentheses
273 else {
274 // Decrement the parenthese level
275 iParenthesesLevel--;
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);
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);
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);
305 // Terminate the integer constant state and set to default state
306 scDoc.SetState(SCE_CLW_DEFAULT);
311 // Determine if a new state should be entered.
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);
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);
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);
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);
339 // else an invalid character in column 1
340 else {
341 // Set to error state
342 scDoc.SetState(SCE_CLW_ERROR);
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);
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);
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);
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);
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);
377 else {
378 // move to the next character and then set the state to comment.
379 scDoc.ForwardSetState(SCE_CLW_STRING);
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);
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);
404 // lexing complete
405 scDoc.Complete();
408 // Clarion Language Case Sensitive Colouring Procedure
409 static void ColouriseClwDocSensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
410 ColouriseClwDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true);
413 // Clarion Language Case Insensitive Colouring Procedure
414 static void ColouriseClwDocInsensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
415 ColouriseClwDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false);
418 // Clarion Language Folding Procedure
419 #ifdef FOLDING_IMPLEMENTED
420 static void FoldClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
423 #endif
425 // Word List Descriptions
426 static 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",
437 // Case Sensitive Clarion Language Lexer
438 LexerModule lmClw(SCLEX_CLW, ColouriseClwDocSensitive, "clw", NULL, rgWordListDescriptions);
440 // Case Insensitive Clarion Language Lexer
441 LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClwDocInsensitive, "clwnocase", NULL, rgWordListDescriptions);