| 1 | U | 1 | U | // Scintilla source code edit control |
|
|
| 3 | U | 3 | U | ** Lexer for Clarion. |
|
| | | 4 | A | ** 2004/12/17 Updated Lexer |
|
| 5 | C | // Copyright 2003 by Ron Schofield <ron@schofieldcomputer.com> | | 6 | C | // Copyright 2003-2004 by Ron Schofield <ron@schofieldcomputer.com> |
| 6 | U | 7 | U | // The License.txt file describes the conditions under which this software may be distributed. |
|
|
|
|
| 10 | R | #include <ctype.h> | | |
|
| 12 | U | 12 | U | #include <stdarg.h> |
|
| | | 13 | A | #include <ctype.h> |
|
| 14 | U | 15 | U | #include "Platform.h" |
|
|
| 4 skipped lines |
| 20 | U | 21 | U | #include "Scintilla.h" |
|
| 21 | U | 22 | U | #include "SciLexer.h" |
|
|
| | | 24 | C | // Is an end of line character |
| | | 25 | C | inline bool IsEOL(const int ch) { |
| | | 26 | C | |
| | | 27 | C | return(ch == '\n'); |
| | | 28 | C | } |
| | | 29 | C | |
| | | 30 | C | // Convert character to uppercase |
| 23 | C | static char MakeUpperCase(char ch) { | | 31 | C | static char CharacterUpper(char chChar) { |
| | | 32 | C | |
| 24 | C | if (ch < 'a' || ch > 'z') | | 33 | C | if (chChar < 'a' || chChar > 'z') { |
| 25 | C | return ch; | | 34 | C | return(chChar); |
| | | 35 | C | } |
| 26 | C | else | | 36 | C | else { |
| 27 | C | return static_cast<char>(ch - 'a' + 'A'); | | 37 | C | return(static_cast<char>(chChar - 'a' + 'A')); |
| | | 38 | C | } |
|
|
| | | 41 | C | // Convert string to uppercase |
| 30 | C | static void MakeUpperCaseString(char *s) { | | 42 | C | static void StringUpper(char *szString) { |
| | | 43 | C | |
| 31 | C | while (*s) { | | 44 | C | while (*szString) { |
| 32 | C | *s = MakeUpperCase(*s); | | 45 | C | *szString = CharacterUpper(*szString); |
| 33 | C | s++; | | 46 | C | szString++; |
|
|
|
| 37 | U | 50 | U | // Is a label start character |
|
| 38 | U | 51 | U | inline bool IsALabelStart(const int iChar) { |
|
| | | 52 | A | |
| 39 | U | 53 | U | return(isalpha(iChar) || iChar == '_'); |
|
|
|
| 42 | U | 56 | U | // Is a label character |
|
| 43 | U | 57 | U | inline bool IsALabelCharacter(const int iChar) { |
|
| | | 58 | C | |
| 44 | C | return(isalnum(iChar) || iChar == '_' || iChar == ':'); | | 59 | C | return(isalnum(iChar) || iChar == '_' || iChar == ':'); |
|
|
| 47 | C | // Is the character is a ! and the the next character is not a ! | | 62 | C | // Is the character is a ! and the the next character is not a ! |
| 48 | C | inline bool IsACommentStart(StyleContext &scDoc) { | | 63 | C | inline bool IsACommentStart(const int iChar) { |
| | | 64 | C | |
| 49 | C | return(scDoc.ch == '!' && scDoc.chNext != '!'); | | 65 | C | return(iChar == '!'); |
|
|
| 52 | U | 68 | U | // Is the character a Clarion hex character (ABCDEF) |
|
| 53 | U | 69 | U | inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) { |
|
| | | 70 | A | |
| 54 | U | 71 | U | // Case insensitive. |
|
| 55 | U | 72 | U | if (!bCaseSensitive) { |
|
| 56 | U | 73 | U | if (strchr("ABCDEFabcdef", iChar) != NULL) { |
|
| 11 skipped lines |
|
| 69 | U | 86 | U | // Is the character a Clarion base character (B=Binary, O=Octal, H=Hex) |
|
| 70 | U | 87 | U | inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) { |
|
| | | 88 | A | |
| 71 | U | 89 | U | // Case insensitive. |
|
| 72 | U | 90 | U | if (!bCaseSensitive) { |
|
| 73 | U | 91 | U | // If character is a numeric base character |
|
| 13 skipped lines |
|
| 88 | U | 106 | U | // Set the correct numeric constant state |
|
| 89 | U | 107 | U | inline bool SetNumericConstantState(StyleContext &scDoc) { |
|
| | | 108 | A | |
| 90 | U | 109 | U | int iPoints = 0;// Point counter |
|
| 91 | C | char cNumericString[100]; // Numeric string buffer | | 110 | C | char cNumericString[512]; // Numeric string buffer |
|
| 93 | U | 112 | U | // Buffer the current numberic string |
|
| 94 | U | 113 | U | scDoc.GetCurrent(cNumericString, sizeof(cNumericString)); |
|
| 8 skipped lines |
|
|
|
| 106 | C | } | | 125 | C | } |
|
| 108 | U | 127 | U | // If points found (can be more than one for improper formatted number |
|
| 109 | U | 128 | U | if (iPoints > 0) { |
|
| 5 skipped lines |
|
|
|
| | | 137 | A | // Get the next word in uppercase from the current position (keyword lookahead) |
| | | 138 | A | inline bool GetNextWordUpper(Accessor &styler, unsigned int uiStartPos, int iLength, char *cWord) { |
| | | 139 | A | |
| | | 140 | A | unsigned int iIndex = 0;// Buffer Index |
| | | 141 | A | |
| 22 skipped lines |
| | | 164 | A | // Return success |
| | | 165 | A | return(true); |
| | | 166 | A | } |
| | | 167 | A | } |
| | | 168 | A | |
| 118 | U | 169 | U | // Clarion Language Colouring Procedure |
|
| 119 | C | static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) { | | 170 | C | static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) { |
| | | 171 | C | |
| | | 172 | C | int iParenthesesLevel = 0; // Parenthese Level |
| | | 173 | C | int iColumn1Label = false; // Label starts in Column 1 |
| | | 174 | C | |
| | | 175 | C | WordList &wlClarionKeywords = *wlKeywords[0]; // Clarion Keywords |
| | | 176 | C | WordList &wlCompilerDirectives = *wlKeywords[1];// Compiler Directives |
| | | 177 | C | WordList &wlRuntimeExpressions = *wlKeywords[2];// Runtime Expressions |
| | | 178 | C | WordList &wlBuiltInProcsFuncs = *wlKeywords[3]; // Builtin Procedures and Functions |
| | | 179 | C | WordList &wlStructsDataTypes = *wlKeywords[4]; // Structures and Data Types |
| | | 180 | C | WordList &wlAttributes = *wlKeywords[5];// Procedure Attributes |
| | | 181 | C | WordList &wlStandardEquates = *wlKeywords[6]; // Standard Equates |
| | | 182 | C | WordList &wlLabelReservedWords = *wlKeywords[7];// Clarion Reserved Keywords (Labels) |
| | | 183 | C | WordList &wlProcLabelReservedWords = *wlKeywords[8];// Clarion Reserved Keywords (Procedure Labels) |
|
| 121 | C | int iParenthesesLevel=0;// Parenthese Level | | 185 | C | const char wlProcReservedKeywordList[] = |
| | | 186 | C | "PROCEDURE FUNCTION"; |
| | | 187 | C | WordList wlProcReservedKeywords; |
| | | 188 | C | wlProcReservedKeywords.Set(wlProcReservedKeywordList); |
|
| 123 | C | WordList &wlClarionKeywords = *wlKeywords[0]; // Clarion Keywords | | 190 | C | const char wlCompilerKeywordList[] = |
| 124 | C | WordList &wlCompilerDirectives = *wlKeywords[1];// Compiler Directives | | 191 | C | "COMPILE OMIT"; |
| 125 | C | WordList &wlBuiltInProcsFuncs = *wlKeywords[2]; // Builtin Procedures and Functions | | 192 | C | WordList wlCompilerKeywords; |
| 126 | C | WordList &wlStructsDataTypes = *wlKeywords[3]; // Structures and Data Types | | 193 | C | wlCompilerKeywords.Set(wlCompilerKeywordList); |
| 127 | C | WordList &wlAttributes = *wlKeywords[4];// Procedure Attributes | | 194 | C | |
| 128 | C | WordList &wlStandardEquates = *wlKeywords[5]; // Standard Equates | | 195 | C | const char wlLegacyStatementsList[] = |
| | | 196 | C | "BOF EOF FUNCTION POINTER SHARE"; |
| 129 | C | WordList &wlReservedWords = *wlKeywords[6]; // Clarion Reserved Keywords | | 197 | C | WordList wlLegacyStatements; |
| | | 198 | C | wlLegacyStatements.Set(wlLegacyStatementsList); |
|
| 131 | U | 200 | U | StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler); |
|
|
| 10 skipped lines |
| 143 | U | 212 | U | if (!IsALabelCharacter(scDoc.ch)) { |
|
| 144 | U | 213 | U | // If the character is a . (dot syntax) |
|
| 145 | U | 214 | U | if (scDoc.ch == '.') { |
|
| | | 215 | A | // Turn off column 1 label flag as label now cannot be reserved work |
| | | 216 | A | iColumn1Label = false; |
| 146 | U | 217 | U | // Uncolour the . (dot) to default state, move forward one character, |
|
| 147 | U | 218 | U | // and change back to the label state. |
|
| 148 | U | 219 | U | scDoc.SetState(SCE_CLW_DEFAULT); |
|
| 149 | U | 220 | U | scDoc.Forward(); |
|
| 150 | U | 221 | U | scDoc.SetState(SCE_CLW_LABEL); |
|
|
| 152 | C | // Else terminate the label state | | 223 | C | // Else check label |
|
| 154 | C | char cLabel[100]; // Label buffer | | 225 | C | char cLabel[512]; // Label buffer |
| 155 | U | 226 | U | // Buffer the current label string |
|
| 156 | U | 227 | U | scDoc.GetCurrent(cLabel,sizeof(cLabel)); |
|
| 157 | U | 228 | U | // If case insensitive, convert string to UPPERCASE to match passed keywords. |
|
| 158 | U | 229 | U | if (!bCaseSensitive) { |
|
| 159 | C | MakeUpperCaseString(cLabel); | | 230 | C | StringUpper(cLabel); |
|
| | | 232 | C | // Else if UPPERCASE label string is in the Clarion compiler keyword list |
| | | 233 | C | if (wlCompilerKeywords.InList(cLabel) && iColumn1Label){ |
| | | 234 | C | // change the label to error state |
| | | 235 | C | scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); |
| | | 236 | C | } |
| 161 | C | // If label string is in the Clarion reserved keyword list | | 237 | C | // Else if UPPERCASE label string is in the Clarion reserved keyword list |
| 162 | C | if (wlReservedWords.InList(cLabel)){ | | 238 | C | else if (wlLabelReservedWords.InList(cLabel) && iColumn1Label){ |
| 163 | C | // change to error state | | 239 | C | // change the label to error state |
| 164 | U | 240 | U | scDoc.ChangeState(SCE_CLW_ERROR); |
|
|
| | | 242 | A | // Else if UPPERCASE label string is |
| | | 243 | A | else if (wlProcLabelReservedWords.InList(cLabel) && iColumn1Label) { |
| | | 244 | A | char cWord[512];// Word buffer |
| | | 245 | A | // Get the next word from the current position |
| | | 246 | A | if (GetNextWordUpper(accStyler,scDoc.currentPos,uiStartPos+iLength,cWord)) { |
| 2 skipped lines |
| | | 249 | A | // Change the label to error state |
| | | 250 | A | scDoc.ChangeState(SCE_CLW_ERROR); |
| | | 251 | A | } |
| | | 252 | A | } |
| | | 253 | A | } |
| 166 | U | 254 | U | // Else if label string is in the compiler directive keyword list |
|
| 167 | U | 255 | U | else if (wlCompilerDirectives.InList(cLabel)) { |
|
| 168 | U | 256 | U | // change the state to compiler directive state |
|
| 8 skipped lines |
| 177 | U | 265 | U | else if (scDoc.state == SCE_CLW_KEYWORD) { |
|
| 178 | U | 266 | U | // If character is : (colon) |
|
| 179 | U | 267 | U | if (scDoc.ch == ':') { |
|
| 180 | C | char cEquate[100]; // Equate buffer | | 268 | C | char cEquate[512]; // Equate buffer |
| 181 | U | 269 | U | // Move forward to include : (colon) in buffer |
|
| 182 | U | 270 | U | scDoc.Forward(); |
|
| 183 | U | 271 | U | // Buffer the equate string |
|
| 184 | U | 272 | U | scDoc.GetCurrent(cEquate,sizeof(cEquate)); |
|
| 185 | U | 273 | U | // If case insensitive, convert string to UPPERCASE to match passed keywords. |
|
| 186 | U | 274 | U | if (!bCaseSensitive) { |
|
| 187 | C | MakeUpperCaseString(cEquate); | | 275 | C | StringUpper(cEquate); |
|
| 189 | U | 277 | U | // If statement string is in the equate list |
|
| 190 | U | 278 | U | if (wlStandardEquates.InList(cEquate)) { |
|
| 3 skipped lines |
|
| 195 | U | 283 | U | // If the character is not a valid label character |
|
| 196 | U | 284 | U | else if (!IsALabelCharacter(scDoc.ch)) { |
|
| 197 | C | char cStatement[100]; // Statement buffer | | 285 | C | char cStatement[512]; // Statement buffer |
| 198 | U | 286 | U | // Buffer the statement string |
|
| 199 | U | 287 | U | scDoc.GetCurrent(cStatement,sizeof(cStatement)); |
|
| 200 | U | 288 | U | // If case insensitive, convert string to UPPERCASE to match passed keywords. |
|
| 201 | U | 289 | U | if (!bCaseSensitive) { |
|
| 202 | C | MakeUpperCaseString(cStatement); | | 290 | C | StringUpper(cStatement); |
|
| 204 | U | 292 | U | // If statement string is in the Clarion keyword list |
|
| 205 | U | 293 | U | if (wlClarionKeywords.InList(cStatement)) { |
|
| 206 | C | // Set to the Clarion keyword state | | 294 | C | // Change the statement string to the Clarion keyword state |
| 207 | U | 295 | U | scDoc.ChangeState(SCE_CLW_KEYWORD); |
|
|
| 209 | U | 297 | U | // Else if statement string is in the compiler directive keyword list |
|
| 210 | U | 298 | U | else if (wlCompilerDirectives.InList(cStatement)) { |
|
| 211 | C | // Set to the compiler directive state | | 299 | C | // Change the statement string to the compiler directive state |
| 212 | U | 300 | U | scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE); |
|
|
| | | 302 | A | // Else if statement string is in the runtime expressions keyword list |
| | | 303 | A | else if (wlRuntimeExpressions.InList(cStatement)) { |
| | | 304 | A | // Change the statement string to the runtime expressions state |
| | | 305 | A | scDoc.ChangeState(SCE_CLW_RUNTIME_EXPRESSIONS); |
| | | 306 | A | } |
| 214 | U | 307 | U | // Else if statement string is in the builtin procedures and functions keyword list |
|
| 215 | U | 308 | U | else if (wlBuiltInProcsFuncs.InList(cStatement)) { |
|
| 216 | C | // Set to the builtin procedures and functions state | | 309 | C | // Change the statement string to the builtin procedures and functions state |
| 217 | U | 310 | U | scDoc.ChangeState(SCE_CLW_BUILTIN_PROCEDURES_FUNCTION); |
|
|
| 219 | U | 312 | U | // Else if statement string is in the tructures and data types keyword list |
|
| 220 | U | 313 | U | else if (wlStructsDataTypes.InList(cStatement)) { |
|
| 221 | C | // Set to the structures and data types state | | 314 | C | // Change the statement string to the structures and data types state |
| 222 | U | 315 | U | scDoc.ChangeState(SCE_CLW_STRUCTURE_DATA_TYPE); |
|
|
| 224 | U | 317 | U | // Else if statement string is in the procedure attribute keyword list |
|
| 225 | U | 318 | U | else if (wlAttributes.InList(cStatement)) { |
|
| 226 | C | // Set to the procedure attribute state | | 319 | C | // Change the statement string to the procedure attribute state |
| 227 | U | 320 | U | scDoc.ChangeState(SCE_CLW_ATTRIBUTE); |
|
|
| 229 | U | 322 | U | // Else if statement string is in the standard equate keyword list |
|
| 230 | U | 323 | U | else if (wlStandardEquates.InList(cStatement)) { |
|
| 231 | C | // Set to the standard equate state | | 324 | C | // Change the statement string to the standard equate state |
| 232 | U | 325 | U | scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE); |
|
|
| | | 327 | A | // Else if statement string is in the deprecated or legacy keyword list |
| | | 328 | A | else if (wlLegacyStatements.InList(cStatement)) { |
| | | 329 | A | // Change the statement string to the standard equate state |
| | | 330 | A | scDoc.ChangeState(SCE_CLW_DEPRECATED); |
| | | 331 | A | } |
| | | 332 | A | // Else the statement string doesn't match any work list |
| | | 333 | A | else { |
| | | 334 | A | // Change the statement string to the default state |
| | | 335 | A | scDoc.ChangeState(SCE_CLW_DEFAULT); |
| | | 336 | A | } |
| 234 | U | 337 | U | // Terminate the keyword state and set to default state |
|
| 235 | U | 338 | U | scDoc.SetState(SCE_CLW_DEFAULT); |
|
|
| 24 skipped lines |
| 261 | U | 364 | U | // Increment the parenthese level |
|
| 262 | U | 365 | U | iParenthesesLevel++; |
|
|
| 264 | C | // Else if the character is a ) (close parenthese) | | 367 | C | // Else if the character is a ) (close parenthese) |
| 265 | U | 368 | U | else if (scDoc.ch == ')') { |
|
| 266 | U | 369 | U | // If the parenthese level is set to zero |
|
| 267 | U | 370 | U | // parentheses matched |
|
| 268 | U | 371 | U | if (!iParenthesesLevel) { |
|
| 269 | U | 372 | U | scDoc.SetState(SCE_CLW_DEFAULT); |
|
| 270 | C | } | | 373 | C | } |
| 271 | U | 374 | U | // Else parenthese level is greater than zero |
|
| 272 | U | 375 | U | // still looking for matching parentheses |
|
|
| 18 skipped lines |
| 292 | U | 395 | U | || IsAHexCharacter(scDoc.ch, bCaseSensitive) |
|
| 293 | U | 396 | U | || scDoc.ch == '.' |
|
| 294 | U | 397 | U | || IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) { |
|
| 295 | C | // If the number was a real | | 398 | C | // If the number was a real |
| 296 | U | 399 | U | if (SetNumericConstantState(scDoc)) { |
|
| 297 | U | 400 | U | // Colour the matched string to the real constant state |
|
| 298 | U | 401 | U | scDoc.ChangeState(SCE_CLW_REAL_CONSTANT); |
|
| 14 skipped lines |
|
| 314 | U | 417 | U | // Beginning of Line Handling |
|
| 315 | U | 418 | U | if (scDoc.atLineStart) { |
|
| | | 419 | A | // Reset the column 1 label flag |
| | | 420 | A | iColumn1Label = false; |
| 316 | U | 421 | U | // If column 1 character is a label start character |
|
| 317 | U | 422 | U | if (IsALabelStart(scDoc.ch)) { |
|
| | | 423 | A | // Label character is found in column 1 |
| | | 424 | A | // so set column 1 label flag and clear last column 1 label |
| | | 425 | A | iColumn1Label = true; |
| 318 | U | 426 | U | // Set the state to label |
|
| 319 | U | 427 | U | scDoc.SetState(SCE_CLW_LABEL); |
|
|
| 2 skipped lines |
| 323 | U | 431 | U | // Set to default state |
|
| 324 | U | 432 | U | scDoc.SetState(SCE_CLW_DEFAULT); |
|
|
| 326 | C | // else if the start of a comment or is an * (asterisk) | | 434 | C | // else if comment start (!) or is an * (asterisk) |
| 327 | C | else if (IsACommentStart(scDoc) || scDoc.ch == '*' ) { | | 435 | C | else if (IsACommentStart(scDoc.ch) || scDoc.ch == '*' ) { |
| 328 | U | 436 | U | // then set the state to comment. |
|
| 329 | U | 437 | U | scDoc.SetState(SCE_CLW_COMMENT); |
|
|
| 18 skipped lines |
|
| 350 | U | 458 | U | // Default Handling |
|
|
| 352 | C | // If in default state | | 460 | C | // If in default state |
|