2009-04-24 23:35:41 +00:00
|
|
|
// Scintilla source code edit control
|
|
|
|
/** @file LexClw.cxx
|
|
|
|
** Lexer for Clarion.
|
|
|
|
** 2004/12/17 Updated Lexer
|
|
|
|
**/
|
|
|
|
// Copyright 2003-2004 by Ron Schofield <ron@schofieldcomputer.com>
|
|
|
|
// The License.txt file describes the conditions under which this software may be distributed.
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
2010-08-21 23:59:56 +00:00
|
|
|
#include <assert.h>
|
2009-04-24 23:35:41 +00:00
|
|
|
#include <ctype.h>
|
|
|
|
|
2010-08-21 23:59:56 +00:00
|
|
|
#include "ILexer.h"
|
|
|
|
#include "Scintilla.h"
|
|
|
|
#include "SciLexer.h"
|
2009-04-24 23:35:41 +00:00
|
|
|
|
2010-08-21 23:59:56 +00:00
|
|
|
#include "WordList.h"
|
|
|
|
#include "LexAccessor.h"
|
2009-04-24 23:35:41 +00:00
|
|
|
#include "Accessor.h"
|
|
|
|
#include "StyleContext.h"
|
2010-08-21 23:59:56 +00:00
|
|
|
#include "CharacterSet.h"
|
|
|
|
#include "LexerModule.h"
|
2009-04-24 23:35:41 +00:00
|
|
|
|
|
|
|
using namespace Scintilla;
|
|
|
|
|
|
|
|
// Is an end of line character
|
|
|
|
inline bool IsEOL(const int ch) {
|
|
|
|
|
|
|
|
return(ch == '\n');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Convert character to uppercase
|
|
|
|
static char CharacterUpper(char chChar) {
|
|
|
|
|
|
|
|
if (chChar < 'a' || chChar > 'z') {
|
|
|
|
return(chChar);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return(static_cast<char>(chChar - 'a' + 'A'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Convert string to uppercase
|
|
|
|
static void StringUpper(char *szString) {
|
|
|
|
|
|
|
|
while (*szString) {
|
|
|
|
*szString = CharacterUpper(*szString);
|
|
|
|
szString++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is a label start character
|
|
|
|
inline bool IsALabelStart(const int iChar) {
|
|
|
|
|
|
|
|
return(isalpha(iChar) || iChar == '_');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is a label character
|
|
|
|
inline bool IsALabelCharacter(const int iChar) {
|
|
|
|
|
2010-08-21 23:59:56 +00:00
|
|
|
return(isalnum(iChar) || iChar == '_' || iChar == ':');
|
2009-04-24 23:35:41 +00:00
|
|
|
}
|
|
|
|
|
2010-08-21 23:59:56 +00:00
|
|
|
// Is the character is a ! and the the next character is not a !
|
2009-04-24 23:35:41 +00:00
|
|
|
inline bool IsACommentStart(const int iChar) {
|
|
|
|
|
|
|
|
return(iChar == '!');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is the character a Clarion hex character (ABCDEF)
|
|
|
|
inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) {
|
|
|
|
|
|
|
|
// Case insensitive.
|
|
|
|
if (!bCaseSensitive) {
|
|
|
|
if (strchr("ABCDEFabcdef", iChar) != NULL) {
|
|
|
|
return(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Case sensitive
|
|
|
|
else {
|
|
|
|
if (strchr("ABCDEF", iChar) != NULL) {
|
|
|
|
return(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is the character a Clarion base character (B=Binary, O=Octal, H=Hex)
|
|
|
|
inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) {
|
|
|
|
|
|
|
|
// Case insensitive.
|
|
|
|
if (!bCaseSensitive) {
|
|
|
|
// If character is a numeric base character
|
|
|
|
if (strchr("BOHboh", iChar) != NULL) {
|
|
|
|
return(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Case sensitive
|
|
|
|
else {
|
|
|
|
// If character is a numeric base character
|
|
|
|
if (strchr("BOH", iChar) != NULL) {
|
|
|
|
return(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the correct numeric constant state
|
|
|
|
inline bool SetNumericConstantState(StyleContext &scDoc) {
|
|
|
|
|
|
|
|
int iPoints = 0; // Point counter
|
|
|
|
char cNumericString[512]; // Numeric string buffer
|
|
|
|
|
|
|
|
// Buffer the current numberic string
|
|
|
|
scDoc.GetCurrent(cNumericString, sizeof(cNumericString));
|
|
|
|
// Loop through the string until end of string (NULL termination)
|
|
|
|
for (int iIndex = 0; cNumericString[iIndex] != '\0'; iIndex++) {
|
|
|
|
// Depending on the character
|
|
|
|
switch (cNumericString[iIndex]) {
|
|
|
|
// Is a . (point)
|
|
|
|
case '.' :
|
|
|
|
// Increment point counter
|
|
|
|
iPoints++;
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
break;
|
2010-08-21 23:59:56 +00:00
|
|
|
}
|
2009-04-24 23:35:41 +00:00
|
|
|
}
|
|
|
|
// If points found (can be more than one for improper formatted number
|
|
|
|
if (iPoints > 0) {
|
|
|
|
return(true);
|
|
|
|
}
|
|
|
|
// Else no points found
|
|
|
|
else {
|
|
|
|
return(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the next word in uppercase from the current position (keyword lookahead)
|
2019-05-04 18:14:48 +00:00
|
|
|
inline bool GetNextWordUpper(Accessor &styler, Sci_PositionU uiStartPos, Sci_Position iLength, char *cWord) {
|
2009-04-24 23:35:41 +00:00
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
Sci_PositionU iIndex = 0; // Buffer Index
|
2009-04-24 23:35:41 +00:00
|
|
|
|
|
|
|
// Loop through the remaining string from the current position
|
2019-05-04 18:14:48 +00:00
|
|
|
for (Sci_Position iOffset = uiStartPos; iOffset < iLength; iOffset++) {
|
2009-04-24 23:35:41 +00:00
|
|
|
// Get the character from the buffer using the offset
|
|
|
|
char cCharacter = styler[iOffset];
|
|
|
|
if (IsEOL(cCharacter)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// If the character is alphabet character
|
|
|
|
if (isalpha(cCharacter)) {
|
|
|
|
// Add UPPERCASE character to the word buffer
|
|
|
|
cWord[iIndex++] = CharacterUpper(cCharacter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Add null termination
|
|
|
|
cWord[iIndex] = '\0';
|
|
|
|
// If no word was found
|
|
|
|
if (iIndex == 0) {
|
|
|
|
// Return failure
|
|
|
|
return(false);
|
|
|
|
}
|
|
|
|
// Else word was found
|
|
|
|
else {
|
|
|
|
// Return success
|
|
|
|
return(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clarion Language Colouring Procedure
|
2019-05-04 18:14:48 +00:00
|
|
|
static void ColouriseClarionDoc(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) {
|
2009-04-24 23:35:41 +00:00
|
|
|
|
|
|
|
int iParenthesesLevel = 0; // Parenthese Level
|
|
|
|
int iColumn1Label = false; // Label starts in Column 1
|
|
|
|
|
|
|
|
WordList &wlClarionKeywords = *wlKeywords[0]; // Clarion Keywords
|
|
|
|
WordList &wlCompilerDirectives = *wlKeywords[1]; // Compiler Directives
|
|
|
|
WordList &wlRuntimeExpressions = *wlKeywords[2]; // Runtime Expressions
|
|
|
|
WordList &wlBuiltInProcsFuncs = *wlKeywords[3]; // Builtin Procedures and Functions
|
|
|
|
WordList &wlStructsDataTypes = *wlKeywords[4]; // Structures and Data Types
|
|
|
|
WordList &wlAttributes = *wlKeywords[5]; // Procedure Attributes
|
|
|
|
WordList &wlStandardEquates = *wlKeywords[6]; // Standard Equates
|
|
|
|
WordList &wlLabelReservedWords = *wlKeywords[7]; // Clarion Reserved Keywords (Labels)
|
|
|
|
WordList &wlProcLabelReservedWords = *wlKeywords[8]; // Clarion Reserved Keywords (Procedure Labels)
|
|
|
|
|
2010-08-21 23:59:56 +00:00
|
|
|
const char wlProcReservedKeywordList[] =
|
2009-04-24 23:35:41 +00:00
|
|
|
"PROCEDURE FUNCTION";
|
|
|
|
WordList wlProcReservedKeywords;
|
|
|
|
wlProcReservedKeywords.Set(wlProcReservedKeywordList);
|
|
|
|
|
2010-08-21 23:59:56 +00:00
|
|
|
const char wlCompilerKeywordList[] =
|
2009-04-24 23:35:41 +00:00
|
|
|
"COMPILE OMIT";
|
|
|
|
WordList wlCompilerKeywords;
|
|
|
|
wlCompilerKeywords.Set(wlCompilerKeywordList);
|
|
|
|
|
|
|
|
const char wlLegacyStatementsList[] =
|
|
|
|
"BOF EOF FUNCTION POINTER SHARE";
|
|
|
|
WordList wlLegacyStatements;
|
|
|
|
wlLegacyStatements.Set(wlLegacyStatementsList);
|
|
|
|
|
|
|
|
StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler);
|
|
|
|
|
|
|
|
// lex source code
|
|
|
|
for (; scDoc.More(); scDoc.Forward())
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Determine if the current state should terminate.
|
|
|
|
//
|
|
|
|
|
|
|
|
// Label State Handling
|
|
|
|
if (scDoc.state == SCE_CLW_LABEL) {
|
|
|
|
// If the character is not a valid label
|
|
|
|
if (!IsALabelCharacter(scDoc.ch)) {
|
|
|
|
// If the character is a . (dot syntax)
|
|
|
|
if (scDoc.ch == '.') {
|
|
|
|
// Turn off column 1 label flag as label now cannot be reserved work
|
|
|
|
iColumn1Label = false;
|
|
|
|
// Uncolour the . (dot) to default state, move forward one character,
|
|
|
|
// and change back to the label state.
|
|
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
|
|
scDoc.Forward();
|
|
|
|
scDoc.SetState(SCE_CLW_LABEL);
|
|
|
|
}
|
|
|
|
// Else check label
|
|
|
|
else {
|
|
|
|
char cLabel[512]; // Label buffer
|
|
|
|
// Buffer the current label string
|
|
|
|
scDoc.GetCurrent(cLabel,sizeof(cLabel));
|
|
|
|
// If case insensitive, convert string to UPPERCASE to match passed keywords.
|
|
|
|
if (!bCaseSensitive) {
|
|
|
|
StringUpper(cLabel);
|
|
|
|
}
|
|
|
|
// Else if UPPERCASE label string is in the Clarion compiler keyword list
|
|
|
|
if (wlCompilerKeywords.InList(cLabel) && iColumn1Label){
|
|
|
|
// change the label to error state
|
|
|
|
scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
|
|
|
|
}
|
|
|
|
// Else if UPPERCASE label string is in the Clarion reserved keyword list
|
|
|
|
else if (wlLabelReservedWords.InList(cLabel) && iColumn1Label){
|
|
|
|
// change the label to error state
|
|
|
|
scDoc.ChangeState(SCE_CLW_ERROR);
|
|
|
|
}
|
2010-08-21 23:59:56 +00:00
|
|
|
// Else if UPPERCASE label string is
|
2009-04-24 23:35:41 +00:00
|
|
|
else if (wlProcLabelReservedWords.InList(cLabel) && iColumn1Label) {
|
|
|
|
char cWord[512]; // Word buffer
|
|
|
|
// Get the next word from the current position
|
|
|
|
if (GetNextWordUpper(accStyler,scDoc.currentPos,uiStartPos+iLength,cWord)) {
|
|
|
|
// If the next word is a procedure reserved word
|
|
|
|
if (wlProcReservedKeywords.InList(cWord)) {
|
|
|
|
// Change the label to error state
|
|
|
|
scDoc.ChangeState(SCE_CLW_ERROR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Else if label string is in the compiler directive keyword list
|
|
|
|
else if (wlCompilerDirectives.InList(cLabel)) {
|
|
|
|
// change the state to compiler directive state
|
|
|
|
scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
|
|
|
|
}
|
|
|
|
// Terminate the label state and set to default state
|
|
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Keyword State Handling
|
|
|
|
else if (scDoc.state == SCE_CLW_KEYWORD) {
|
|
|
|
// If character is : (colon)
|
|
|
|
if (scDoc.ch == ':') {
|
|
|
|
char cEquate[512]; // Equate buffer
|
|
|
|
// Move forward to include : (colon) in buffer
|
|
|
|
scDoc.Forward();
|
|
|
|
// Buffer the equate string
|
|
|
|
scDoc.GetCurrent(cEquate,sizeof(cEquate));
|
|
|
|
// If case insensitive, convert string to UPPERCASE to match passed keywords.
|
|
|
|
if (!bCaseSensitive) {
|
|
|
|
StringUpper(cEquate);
|
|
|
|
}
|
|
|
|
// If statement string is in the equate list
|
|
|
|
if (wlStandardEquates.InList(cEquate)) {
|
|
|
|
// Change to equate state
|
|
|
|
scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If the character is not a valid label character
|
|
|
|
else if (!IsALabelCharacter(scDoc.ch)) {
|
|
|
|
char cStatement[512]; // Statement buffer
|
|
|
|
// Buffer the statement string
|
|
|
|
scDoc.GetCurrent(cStatement,sizeof(cStatement));
|
|
|
|
// If case insensitive, convert string to UPPERCASE to match passed keywords.
|
|
|
|
if (!bCaseSensitive) {
|
|
|
|
StringUpper(cStatement);
|
|
|
|
}
|
|
|
|
// If statement string is in the Clarion keyword list
|
|
|
|
if (wlClarionKeywords.InList(cStatement)) {
|
|
|
|
// Change the statement string to the Clarion keyword state
|
|
|
|
scDoc.ChangeState(SCE_CLW_KEYWORD);
|
|
|
|
}
|
|
|
|
// Else if statement string is in the compiler directive keyword list
|
|
|
|
else if (wlCompilerDirectives.InList(cStatement)) {
|
|
|
|
// Change the statement string to the compiler directive state
|
|
|
|
scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
|
|
|
|
}
|
|
|
|
// Else if statement string is in the runtime expressions keyword list
|
|
|
|
else if (wlRuntimeExpressions.InList(cStatement)) {
|
|
|
|
// Change the statement string to the runtime expressions state
|
|
|
|
scDoc.ChangeState(SCE_CLW_RUNTIME_EXPRESSIONS);
|
|
|
|
}
|
|
|
|
// Else if statement string is in the builtin procedures and functions keyword list
|
|
|
|
else if (wlBuiltInProcsFuncs.InList(cStatement)) {
|
|
|
|
// Change the statement string to the builtin procedures and functions state
|
|
|
|
scDoc.ChangeState(SCE_CLW_BUILTIN_PROCEDURES_FUNCTION);
|
|
|
|
}
|
|
|
|
// Else if statement string is in the tructures and data types keyword list
|
|
|
|
else if (wlStructsDataTypes.InList(cStatement)) {
|
|
|
|
// Change the statement string to the structures and data types state
|
|
|
|
scDoc.ChangeState(SCE_CLW_STRUCTURE_DATA_TYPE);
|
|
|
|
}
|
|
|
|
// Else if statement string is in the procedure attribute keyword list
|
|
|
|
else if (wlAttributes.InList(cStatement)) {
|
|
|
|
// Change the statement string to the procedure attribute state
|
|
|
|
scDoc.ChangeState(SCE_CLW_ATTRIBUTE);
|
|
|
|
}
|
|
|
|
// Else if statement string is in the standard equate keyword list
|
|
|
|
else if (wlStandardEquates.InList(cStatement)) {
|
|
|
|
// Change the statement string to the standard equate state
|
|
|
|
scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
|
|
|
|
}
|
|
|
|
// Else if statement string is in the deprecated or legacy keyword list
|
|
|
|
else if (wlLegacyStatements.InList(cStatement)) {
|
|
|
|
// Change the statement string to the standard equate state
|
|
|
|
scDoc.ChangeState(SCE_CLW_DEPRECATED);
|
|
|
|
}
|
|
|
|
// Else the statement string doesn't match any work list
|
|
|
|
else {
|
|
|
|
// Change the statement string to the default state
|
|
|
|
scDoc.ChangeState(SCE_CLW_DEFAULT);
|
|
|
|
}
|
|
|
|
// Terminate the keyword state and set to default state
|
|
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// String State Handling
|
|
|
|
else if (scDoc.state == SCE_CLW_STRING) {
|
|
|
|
// If the character is an ' (single quote)
|
|
|
|
if (scDoc.ch == '\'') {
|
|
|
|
// Set the state to default and move forward colouring
|
|
|
|
// the ' (single quote) as default state
|
|
|
|
// terminating the string state
|
|
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
|
|
scDoc.Forward();
|
|
|
|
}
|
|
|
|
// If the next character is an ' (single quote)
|
|
|
|
if (scDoc.chNext == '\'') {
|
|
|
|
// Move forward one character and set to default state
|
|
|
|
// colouring the next ' (single quote) as default state
|
|
|
|
// terminating the string state
|
|
|
|
scDoc.ForwardSetState(SCE_CLW_DEFAULT);
|
|
|
|
scDoc.Forward();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Picture String State Handling
|
|
|
|
else if (scDoc.state == SCE_CLW_PICTURE_STRING) {
|
|
|
|
// If the character is an ( (open parenthese)
|
|
|
|
if (scDoc.ch == '(') {
|
|
|
|
// Increment the parenthese level
|
|
|
|
iParenthesesLevel++;
|
|
|
|
}
|
2010-08-21 23:59:56 +00:00
|
|
|
// Else if the character is a ) (close parenthese)
|
2009-04-24 23:35:41 +00:00
|
|
|
else if (scDoc.ch == ')') {
|
|
|
|
// If the parenthese level is set to zero
|
|
|
|
// parentheses matched
|
|
|
|
if (!iParenthesesLevel) {
|
|
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
2010-08-21 23:59:56 +00:00
|
|
|
}
|
2009-04-24 23:35:41 +00:00
|
|
|
// Else parenthese level is greater than zero
|
|
|
|
// still looking for matching parentheses
|
|
|
|
else {
|
|
|
|
// Decrement the parenthese level
|
|
|
|
iParenthesesLevel--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Standard Equate State Handling
|
|
|
|
else if (scDoc.state == SCE_CLW_STANDARD_EQUATE) {
|
|
|
|
if (!isalnum(scDoc.ch)) {
|
|
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Integer Constant State Handling
|
|
|
|
else if (scDoc.state == SCE_CLW_INTEGER_CONSTANT) {
|
|
|
|
// If the character is not a digit (0-9)
|
|
|
|
// or character is not a hexidecimal character (A-F)
|
|
|
|
// or character is not a . (point)
|
|
|
|
// or character is not a numberic base character (B,O,H)
|
|
|
|
if (!(isdigit(scDoc.ch)
|
|
|
|
|| IsAHexCharacter(scDoc.ch, bCaseSensitive)
|
|
|
|
|| scDoc.ch == '.'
|
|
|
|
|| IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) {
|
2010-08-21 23:59:56 +00:00
|
|
|
// If the number was a real
|
2009-04-24 23:35:41 +00:00
|
|
|
if (SetNumericConstantState(scDoc)) {
|
|
|
|
// Colour the matched string to the real constant state
|
|
|
|
scDoc.ChangeState(SCE_CLW_REAL_CONSTANT);
|
|
|
|
}
|
|
|
|
// Else the number was an integer
|
|
|
|
else {
|
|
|
|
// Colour the matched string to an integer constant state
|
|
|
|
scDoc.ChangeState(SCE_CLW_INTEGER_CONSTANT);
|
|
|
|
}
|
|
|
|
// Terminate the integer constant state and set to default state
|
|
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Determine if a new state should be entered.
|
|
|
|
//
|
|
|
|
|
|
|
|
// Beginning of Line Handling
|
|
|
|
if (scDoc.atLineStart) {
|
|
|
|
// Reset the column 1 label flag
|
|
|
|
iColumn1Label = false;
|
|
|
|
// If column 1 character is a label start character
|
|
|
|
if (IsALabelStart(scDoc.ch)) {
|
|
|
|
// Label character is found in column 1
|
|
|
|
// so set column 1 label flag and clear last column 1 label
|
|
|
|
iColumn1Label = true;
|
|
|
|
// Set the state to label
|
|
|
|
scDoc.SetState(SCE_CLW_LABEL);
|
|
|
|
}
|
|
|
|
// else if character is a space or tab
|
|
|
|
else if (IsASpace(scDoc.ch)){
|
|
|
|
// Set to default state
|
|
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
|
|
}
|
|
|
|
// else if comment start (!) or is an * (asterisk)
|
|
|
|
else if (IsACommentStart(scDoc.ch) || scDoc.ch == '*' ) {
|
|
|
|
// then set the state to comment.
|
|
|
|
scDoc.SetState(SCE_CLW_COMMENT);
|
|
|
|
}
|
|
|
|
// else the character is a ? (question mark)
|
|
|
|
else if (scDoc.ch == '?') {
|
|
|
|
// Change to the compiler directive state, move forward,
|
|
|
|
// colouring the ? (question mark), change back to default state.
|
|
|
|
scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
|
|
|
|
scDoc.Forward();
|
|
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
|
|
}
|
|
|
|
// else an invalid character in column 1
|
|
|
|
else {
|
|
|
|
// Set to error state
|
|
|
|
scDoc.SetState(SCE_CLW_ERROR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// End of Line Handling
|
|
|
|
else if (scDoc.atLineEnd) {
|
|
|
|
// Reset to the default state at the end of each line.
|
|
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
|
|
}
|
|
|
|
// Default Handling
|
|
|
|
else {
|
2010-08-21 23:59:56 +00:00
|
|
|
// If in default state
|
2009-04-24 23:35:41 +00:00
|
|
|
if (scDoc.state == SCE_CLW_DEFAULT) {
|
|
|
|
// If is a letter could be a possible statement
|
|
|
|
if (isalpha(scDoc.ch)) {
|
|
|
|
// Set the state to Clarion Keyword and verify later
|
|
|
|
scDoc.SetState(SCE_CLW_KEYWORD);
|
|
|
|
}
|
|
|
|
// else is a number
|
|
|
|
else if (isdigit(scDoc.ch)) {
|
|
|
|
// Set the state to Integer Constant and verify later
|
|
|
|
scDoc.SetState(SCE_CLW_INTEGER_CONSTANT);
|
|
|
|
}
|
|
|
|
// else if the start of a comment or a | (line continuation)
|
|
|
|
else if (IsACommentStart(scDoc.ch) || scDoc.ch == '|') {
|
|
|
|
// then set the state to comment.
|
|
|
|
scDoc.SetState(SCE_CLW_COMMENT);
|
2010-08-21 23:59:56 +00:00
|
|
|
}
|
2009-04-24 23:35:41 +00:00
|
|
|
// else if the character is a ' (single quote)
|
|
|
|
else if (scDoc.ch == '\'') {
|
2010-08-21 23:59:56 +00:00
|
|
|
// If the character is also a ' (single quote)
|
2009-04-24 23:35:41 +00:00
|
|
|
// Embedded Apostrophe
|
|
|
|
if (scDoc.chNext == '\'') {
|
|
|
|
// Move forward colouring it as default state
|
|
|
|
scDoc.ForwardSetState(SCE_CLW_DEFAULT);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// move to the next character and then set the state to comment.
|
|
|
|
scDoc.ForwardSetState(SCE_CLW_STRING);
|
|
|
|
}
|
2010-08-21 23:59:56 +00:00
|
|
|
}
|
2009-04-24 23:35:41 +00:00
|
|
|
// else the character is an @ (ampersand)
|
|
|
|
else if (scDoc.ch == '@') {
|
|
|
|
// Case insensitive.
|
|
|
|
if (!bCaseSensitive) {
|
|
|
|
// If character is a valid picture token character
|
|
|
|
if (strchr("DEKNPSTdeknpst", scDoc.chNext) != NULL) {
|
|
|
|
// Set to the picture string state
|
|
|
|
scDoc.SetState(SCE_CLW_PICTURE_STRING);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Case sensitive
|
|
|
|
else {
|
|
|
|
// If character is a valid picture token character
|
|
|
|
if (strchr("DEKNPST", scDoc.chNext) != NULL) {
|
|
|
|
// Set the picture string state
|
|
|
|
scDoc.SetState(SCE_CLW_PICTURE_STRING);
|
|
|
|
}
|
|
|
|
}
|
2010-08-21 23:59:56 +00:00
|
|
|
}
|
2009-04-24 23:35:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// lexing complete
|
|
|
|
scDoc.Complete();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clarion Language Case Sensitive Colouring Procedure
|
2019-05-04 18:14:48 +00:00
|
|
|
static void ColouriseClarionDocSensitive(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
|
2009-04-24 23:35:41 +00:00
|
|
|
|
|
|
|
ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clarion Language Case Insensitive Colouring Procedure
|
2019-05-04 18:14:48 +00:00
|
|
|
static void ColouriseClarionDocInsensitive(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
|
2009-04-24 23:35:41 +00:00
|
|
|
|
|
|
|
ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fill Buffer
|
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
static void FillBuffer(Sci_PositionU uiStart, Sci_PositionU uiEnd, Accessor &accStyler, char *szBuffer, Sci_PositionU uiLength) {
|
2009-04-24 23:35:41 +00:00
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
Sci_PositionU uiPos = 0;
|
2009-04-24 23:35:41 +00:00
|
|
|
|
|
|
|
while ((uiPos < uiEnd - uiStart + 1) && (uiPos < uiLength-1)) {
|
|
|
|
szBuffer[uiPos] = static_cast<char>(toupper(accStyler[uiStart + uiPos]));
|
|
|
|
uiPos++;
|
|
|
|
}
|
|
|
|
szBuffer[uiPos] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
// Classify Clarion Fold Point
|
|
|
|
|
|
|
|
static int ClassifyClarionFoldPoint(int iLevel, const char* szString) {
|
|
|
|
|
|
|
|
if (!(isdigit(szString[0]) || (szString[0] == '.'))) {
|
|
|
|
if (strcmp(szString, "PROCEDURE") == 0) {
|
|
|
|
// iLevel = SC_FOLDLEVELBASE + 1;
|
|
|
|
}
|
|
|
|
else if (strcmp(szString, "MAP") == 0 ||
|
|
|
|
strcmp(szString,"ACCEPT") == 0 ||
|
|
|
|
strcmp(szString,"BEGIN") == 0 ||
|
|
|
|
strcmp(szString,"CASE") == 0 ||
|
|
|
|
strcmp(szString,"EXECUTE") == 0 ||
|
|
|
|
strcmp(szString,"IF") == 0 ||
|
|
|
|
strcmp(szString,"ITEMIZE") == 0 ||
|
|
|
|
strcmp(szString,"INTERFACE") == 0 ||
|
|
|
|
strcmp(szString,"JOIN") == 0 ||
|
|
|
|
strcmp(szString,"LOOP") == 0 ||
|
|
|
|
strcmp(szString,"MODULE") == 0 ||
|
|
|
|
strcmp(szString,"RECORD") == 0) {
|
|
|
|
iLevel++;
|
|
|
|
}
|
|
|
|
else if (strcmp(szString, "APPLICATION") == 0 ||
|
|
|
|
strcmp(szString, "CLASS") == 0 ||
|
|
|
|
strcmp(szString, "DETAIL") == 0 ||
|
|
|
|
strcmp(szString, "FILE") == 0 ||
|
|
|
|
strcmp(szString, "FOOTER") == 0 ||
|
|
|
|
strcmp(szString, "FORM") == 0 ||
|
|
|
|
strcmp(szString, "GROUP") == 0 ||
|
|
|
|
strcmp(szString, "HEADER") == 0 ||
|
|
|
|
strcmp(szString, "INTERFACE") == 0 ||
|
|
|
|
strcmp(szString, "MENU") == 0 ||
|
|
|
|
strcmp(szString, "MENUBAR") == 0 ||
|
|
|
|
strcmp(szString, "OLE") == 0 ||
|
|
|
|
strcmp(szString, "OPTION") == 0 ||
|
|
|
|
strcmp(szString, "QUEUE") == 0 ||
|
|
|
|
strcmp(szString, "REPORT") == 0 ||
|
|
|
|
strcmp(szString, "SHEET") == 0 ||
|
|
|
|
strcmp(szString, "TAB") == 0 ||
|
|
|
|
strcmp(szString, "TOOLBAR") == 0 ||
|
|
|
|
strcmp(szString, "VIEW") == 0 ||
|
|
|
|
strcmp(szString, "WINDOW") == 0) {
|
|
|
|
iLevel++;
|
|
|
|
}
|
|
|
|
else if (strcmp(szString, "END") == 0 ||
|
|
|
|
strcmp(szString, "UNTIL") == 0 ||
|
|
|
|
strcmp(szString, "WHILE") == 0) {
|
|
|
|
iLevel--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(iLevel);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clarion Language Folding Procedure
|
2019-05-04 18:14:48 +00:00
|
|
|
static void FoldClarionDoc(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *[], Accessor &accStyler) {
|
2009-04-24 23:35:41 +00:00
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
Sci_PositionU uiEndPos = uiStartPos + iLength;
|
|
|
|
Sci_Position iLineCurrent = accStyler.GetLine(uiStartPos);
|
2009-04-24 23:35:41 +00:00
|
|
|
int iLevelPrev = accStyler.LevelAt(iLineCurrent) & SC_FOLDLEVELNUMBERMASK;
|
|
|
|
int iLevelCurrent = iLevelPrev;
|
|
|
|
char chNext = accStyler[uiStartPos];
|
|
|
|
int iStyle = iInitStyle;
|
|
|
|
int iStyleNext = accStyler.StyleAt(uiStartPos);
|
|
|
|
int iVisibleChars = 0;
|
2019-05-04 18:14:48 +00:00
|
|
|
Sci_Position iLastStart = 0;
|
2009-04-24 23:35:41 +00:00
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
for (Sci_PositionU uiPos = uiStartPos; uiPos < uiEndPos; uiPos++) {
|
2009-04-24 23:35:41 +00:00
|
|
|
|
|
|
|
char chChar = chNext;
|
|
|
|
chNext = accStyler.SafeGetCharAt(uiPos + 1);
|
|
|
|
int iStylePrev = iStyle;
|
|
|
|
iStyle = iStyleNext;
|
|
|
|
iStyleNext = accStyler.StyleAt(uiPos + 1);
|
|
|
|
bool bEOL = (chChar == '\r' && chNext != '\n') || (chChar == '\n');
|
2010-08-21 23:59:56 +00:00
|
|
|
|
2009-04-24 23:35:41 +00:00
|
|
|
if (iStylePrev == SCE_CLW_DEFAULT) {
|
|
|
|
if (iStyle == SCE_CLW_KEYWORD || iStyle == SCE_CLW_STRUCTURE_DATA_TYPE) {
|
|
|
|
// Store last word start point.
|
|
|
|
iLastStart = uiPos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iStylePrev == SCE_CLW_KEYWORD || iStylePrev == SCE_CLW_STRUCTURE_DATA_TYPE) {
|
|
|
|
if(iswordchar(chChar) && !iswordchar(chNext)) {
|
|
|
|
char chBuffer[100];
|
|
|
|
FillBuffer(iLastStart, uiPos, accStyler, chBuffer, sizeof(chBuffer));
|
|
|
|
iLevelCurrent = ClassifyClarionFoldPoint(iLevelCurrent,chBuffer);
|
|
|
|
// if ((iLevelCurrent == SC_FOLDLEVELBASE + 1) && iLineCurrent > 1) {
|
|
|
|
// accStyler.SetLevel(iLineCurrent-1,SC_FOLDLEVELBASE);
|
|
|
|
// iLevelPrev = SC_FOLDLEVELBASE;
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bEOL) {
|
|
|
|
int iLevel = iLevelPrev;
|
|
|
|
if ((iLevelCurrent > iLevelPrev) && (iVisibleChars > 0))
|
|
|
|
iLevel |= SC_FOLDLEVELHEADERFLAG;
|
|
|
|
if (iLevel != accStyler.LevelAt(iLineCurrent)) {
|
|
|
|
accStyler.SetLevel(iLineCurrent,iLevel);
|
|
|
|
}
|
|
|
|
iLineCurrent++;
|
|
|
|
iLevelPrev = iLevelCurrent;
|
|
|
|
iVisibleChars = 0;
|
|
|
|
}
|
2010-08-21 23:59:56 +00:00
|
|
|
|
2009-04-24 23:35:41 +00:00
|
|
|
if (!isspacechar(chChar))
|
|
|
|
iVisibleChars++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fill in the real level of the next line, keeping the current flags
|
|
|
|
// as they will be filled in later.
|
|
|
|
int iFlagsNext = accStyler.LevelAt(iLineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
|
|
|
|
accStyler.SetLevel(iLineCurrent, iLevelPrev | iFlagsNext);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Word List Descriptions
|
|
|
|
static const char * const rgWordListDescriptions[] = {
|
|
|
|
"Clarion Keywords",
|
|
|
|
"Compiler Directives",
|
|
|
|
"Built-in Procedures and Functions",
|
|
|
|
"Runtime Expressions",
|
|
|
|
"Structure and Data Types",
|
|
|
|
"Attributes",
|
|
|
|
"Standard Equates",
|
|
|
|
"Reserved Words (Labels)",
|
|
|
|
"Reserved Words (Procedure Labels)",
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Case Sensitive Clarion Language Lexer
|
|
|
|
LexerModule lmClw(SCLEX_CLW, ColouriseClarionDocSensitive, "clarion", FoldClarionDoc, rgWordListDescriptions);
|
|
|
|
|
|
|
|
// Case Insensitive Clarion Language Lexer
|
|
|
|
LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClarionDocInsensitive, "clarionnocase", FoldClarionDoc, rgWordListDescriptions);
|