chore: bump scintilla and lexilla version
This commit is contained in:
904
3rdparty/lexilla545/lexilla/lexers/LexTADS3.cxx
vendored
Normal file
904
3rdparty/lexilla545/lexilla/lexers/LexTADS3.cxx
vendored
Normal file
@ -0,0 +1,904 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file LexTADS3.cxx
|
||||
** Lexer for TADS3.
|
||||
**/
|
||||
// Copyright 1998-2006 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
/*
|
||||
* TADS3 is a language designed by Michael J. Roberts for the writing of text
|
||||
* based games. TADS comes from Text Adventure Development System. It has good
|
||||
* support for the processing and outputting of formatted text and much of a
|
||||
* TADS program listing consists of strings.
|
||||
*
|
||||
* TADS has two types of strings, those enclosed in single quotes (') and those
|
||||
* enclosed in double quotes ("). These strings have different symantics and
|
||||
* can be given different highlighting if desired.
|
||||
*
|
||||
* There can be embedded within both types of strings html tags
|
||||
* ( <tag key=value> ), library directives ( <.directive> ), and message
|
||||
* parameters ( {The doctor's/his} ).
|
||||
*
|
||||
* Double quoted strings can also contain interpolated expressions
|
||||
* ( << rug.moved ? ' and a hole in the floor. ' : nil >> ). These expressions
|
||||
* may themselves contain single or double quoted strings, although the double
|
||||
* quoted strings may not contain interpolated expressions.
|
||||
*
|
||||
* These embedded constructs influence the output and formatting and are an
|
||||
* important part of a program and require highlighting.
|
||||
*
|
||||
* LINKS
|
||||
* http://www.tads.org/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
#include "SciLexer.h"
|
||||
|
||||
#include "WordList.h"
|
||||
#include "LexAccessor.h"
|
||||
#include "Accessor.h"
|
||||
#include "StyleContext.h"
|
||||
#include "CharacterSet.h"
|
||||
#include "LexerModule.h"
|
||||
|
||||
using namespace Lexilla;
|
||||
|
||||
static const int T3_SINGLE_QUOTE = 1;
|
||||
static const int T3_INT_EXPRESSION = 2;
|
||||
static const int T3_INT_EXPRESSION_IN_TAG = 4;
|
||||
static const int T3_HTML_SQUOTE = 8;
|
||||
|
||||
static inline bool IsEOL(const int ch, const int chNext) {
|
||||
return (ch == '\r' && chNext != '\n') || (ch == '\n');
|
||||
}
|
||||
|
||||
/*
|
||||
* Test the current character to see if it's the START of an EOL sequence;
|
||||
* if so, skip ahead to the last character of the sequence and return true,
|
||||
* and if not just return false. There are a few places where we want to
|
||||
* check to see if a newline sequence occurs at a particular point, but
|
||||
* where a caller expects a subroutine to stop only upon reaching the END
|
||||
* of a newline sequence (in particular, CR-LF on Windows). That's why
|
||||
* IsEOL() above only returns true on CR if the CR isn't followed by an LF
|
||||
* - it doesn't want to admit that there's a newline until reaching the END
|
||||
* of the sequence. We meet both needs by saying that there's a newline
|
||||
* when we see the CR in a CR-LF, but skipping the CR before returning so
|
||||
* that the caller's caller will see that we've stopped at the LF.
|
||||
*/
|
||||
static inline bool IsEOLSkip(StyleContext &sc)
|
||||
{
|
||||
/* test for CR-LF */
|
||||
if (sc.ch == '\r' && sc.chNext == '\n')
|
||||
{
|
||||
/* got CR-LF - skip the CR and indicate that we're at a newline */
|
||||
sc.Forward();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* in other cases, we have at most a 1-character newline, so do the
|
||||
* normal IsEOL test
|
||||
*/
|
||||
return IsEOL(sc.ch, sc.chNext);
|
||||
}
|
||||
|
||||
static inline bool IsATADS3Operator(const int ch) {
|
||||
return ch == '=' || ch == '{' || ch == '}' || ch == '(' || ch == ')'
|
||||
|| ch == '[' || ch == ']' || ch == ',' || ch == ':' || ch == ';'
|
||||
|| ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '%'
|
||||
|| ch == '?' || ch == '!' || ch == '<' || ch == '>' || ch == '|'
|
||||
|| ch == '@' || ch == '&' || ch == '~';
|
||||
}
|
||||
|
||||
static inline bool IsAWordChar(const int ch) {
|
||||
return isalnum(ch) || ch == '_';
|
||||
}
|
||||
|
||||
static inline bool IsAWordStart(const int ch) {
|
||||
return isalpha(ch) || ch == '_';
|
||||
}
|
||||
|
||||
static inline bool IsAHexDigit(const int ch) {
|
||||
int lch = tolower(ch);
|
||||
return isdigit(lch) || lch == 'a' || lch == 'b' || lch == 'c'
|
||||
|| lch == 'd' || lch == 'e' || lch == 'f';
|
||||
}
|
||||
|
||||
static inline bool IsAnHTMLChar(int ch) {
|
||||
return isalnum(ch) || ch == '-' || ch == '_' || ch == '.';
|
||||
}
|
||||
|
||||
static inline bool IsADirectiveChar(int ch) {
|
||||
return isalnum(ch) || isspace(ch) || ch == '-' || ch == '/';
|
||||
}
|
||||
|
||||
static inline bool IsANumberStart(StyleContext &sc) {
|
||||
return isdigit(sc.ch)
|
||||
|| (!isdigit(sc.chPrev) && sc.ch == '.' && isdigit(sc.chNext));
|
||||
}
|
||||
|
||||
inline static void ColouriseTADS3Operator(StyleContext &sc) {
|
||||
int initState = sc.state;
|
||||
int c = sc.ch;
|
||||
sc.SetState(c == '{' || c == '}' ? SCE_T3_BRACE : SCE_T3_OPERATOR);
|
||||
sc.ForwardSetState(initState);
|
||||
}
|
||||
|
||||
static void ColouriseTADSHTMLString(StyleContext &sc, int &lineState) {
|
||||
int endState = sc.state;
|
||||
int chQuote = sc.ch;
|
||||
int chString = (lineState & T3_SINGLE_QUOTE) ? '\'' : '"';
|
||||
if (endState == SCE_T3_HTML_STRING) {
|
||||
if (lineState&T3_SINGLE_QUOTE) {
|
||||
endState = SCE_T3_S_STRING;
|
||||
chString = '\'';
|
||||
} else if (lineState&T3_INT_EXPRESSION) {
|
||||
endState = SCE_T3_X_STRING;
|
||||
chString = '"';
|
||||
} else {
|
||||
endState = SCE_T3_HTML_DEFAULT;
|
||||
chString = '"';
|
||||
}
|
||||
chQuote = (lineState & T3_HTML_SQUOTE) ? '\'' : '"';
|
||||
} else {
|
||||
sc.SetState(SCE_T3_HTML_STRING);
|
||||
sc.Forward();
|
||||
}
|
||||
if (chQuote == '"')
|
||||
lineState &= ~T3_HTML_SQUOTE;
|
||||
else
|
||||
lineState |= T3_HTML_SQUOTE;
|
||||
|
||||
while (sc.More()) {
|
||||
if (IsEOL(sc.ch, sc.chNext)) {
|
||||
return;
|
||||
}
|
||||
if (sc.ch == chQuote) {
|
||||
sc.ForwardSetState(endState);
|
||||
return;
|
||||
}
|
||||
if (sc.Match('\\', static_cast<char>(chQuote))) {
|
||||
sc.Forward(2);
|
||||
sc.SetState(endState);
|
||||
return;
|
||||
}
|
||||
if (sc.ch == chString) {
|
||||
sc.SetState(SCE_T3_DEFAULT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sc.Match('<', '<')) {
|
||||
lineState |= T3_INT_EXPRESSION | T3_INT_EXPRESSION_IN_TAG;
|
||||
sc.SetState(SCE_T3_X_DEFAULT);
|
||||
sc.Forward(2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sc.Match('\\', static_cast<char>(chQuote))
|
||||
|| sc.Match('\\', static_cast<char>(chString))
|
||||
|| sc.Match('\\', '\\')) {
|
||||
sc.Forward(2);
|
||||
} else {
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ColouriseTADS3HTMLTagStart(StyleContext &sc) {
|
||||
sc.SetState(SCE_T3_HTML_TAG);
|
||||
sc.Forward();
|
||||
if (sc.ch == '/') {
|
||||
sc.Forward();
|
||||
}
|
||||
while (IsAnHTMLChar(sc.ch)) {
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
|
||||
static void ColouriseTADS3HTMLTag(StyleContext &sc, int &lineState) {
|
||||
int endState = sc.state;
|
||||
int chQuote = '"';
|
||||
int chString = '\'';
|
||||
switch (endState) {
|
||||
case SCE_T3_S_STRING:
|
||||
ColouriseTADS3HTMLTagStart(sc);
|
||||
sc.SetState(SCE_T3_HTML_DEFAULT);
|
||||
chQuote = '\'';
|
||||
chString = '"';
|
||||
break;
|
||||
case SCE_T3_D_STRING:
|
||||
case SCE_T3_X_STRING:
|
||||
ColouriseTADS3HTMLTagStart(sc);
|
||||
sc.SetState(SCE_T3_HTML_DEFAULT);
|
||||
break;
|
||||
case SCE_T3_HTML_DEFAULT:
|
||||
if (lineState&T3_SINGLE_QUOTE) {
|
||||
endState = SCE_T3_S_STRING;
|
||||
chQuote = '\'';
|
||||
chString = '"';
|
||||
} else if (lineState&T3_INT_EXPRESSION) {
|
||||
endState = SCE_T3_X_STRING;
|
||||
} else {
|
||||
endState = SCE_T3_D_STRING;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
while (sc.More()) {
|
||||
if (IsEOL(sc.ch, sc.chNext)) {
|
||||
return;
|
||||
}
|
||||
if (sc.Match('/', '>')) {
|
||||
sc.SetState(SCE_T3_HTML_TAG);
|
||||
sc.Forward(2);
|
||||
sc.SetState(endState);
|
||||
return;
|
||||
}
|
||||
if (sc.ch == '>') {
|
||||
sc.SetState(SCE_T3_HTML_TAG);
|
||||
sc.ForwardSetState(endState);
|
||||
return;
|
||||
}
|
||||
if (sc.ch == chQuote) {
|
||||
sc.SetState(endState);
|
||||
return;
|
||||
}
|
||||
if (sc.Match('\\', static_cast<char>(chQuote))) {
|
||||
sc.Forward();
|
||||
ColouriseTADSHTMLString(sc, lineState);
|
||||
if (sc.state == SCE_T3_X_DEFAULT)
|
||||
break;
|
||||
} else if (sc.ch == chString) {
|
||||
ColouriseTADSHTMLString(sc, lineState);
|
||||
} else if (sc.ch == '=') {
|
||||
ColouriseTADS3Operator(sc);
|
||||
} else {
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ColouriseTADS3Keyword(StyleContext &sc,
|
||||
WordList *keywordlists[], Sci_PositionU endPos) {
|
||||
char s[250];
|
||||
WordList &keywords = *keywordlists[0];
|
||||
WordList &userwords1 = *keywordlists[1];
|
||||
WordList &userwords2 = *keywordlists[2];
|
||||
WordList &userwords3 = *keywordlists[3];
|
||||
int initState = sc.state;
|
||||
sc.SetState(SCE_T3_IDENTIFIER);
|
||||
while (sc.More() && (IsAWordChar(sc.ch))) {
|
||||
sc.Forward();
|
||||
}
|
||||
sc.GetCurrent(s, sizeof(s));
|
||||
if ( strcmp(s, "is") == 0 || strcmp(s, "not") == 0) {
|
||||
// have to find if "in" is next
|
||||
Sci_Position n = 1;
|
||||
while (n + sc.currentPos < endPos && IsASpaceOrTab(sc.GetRelative(n)))
|
||||
n++;
|
||||
if (sc.GetRelative(n) == 'i' && sc.GetRelative(n+1) == 'n') {
|
||||
sc.Forward(n+2);
|
||||
sc.ChangeState(SCE_T3_KEYWORD);
|
||||
}
|
||||
} else if (keywords.InList(s)) {
|
||||
sc.ChangeState(SCE_T3_KEYWORD);
|
||||
} else if (userwords3.InList(s)) {
|
||||
sc.ChangeState(SCE_T3_USER3);
|
||||
} else if (userwords2.InList(s)) {
|
||||
sc.ChangeState(SCE_T3_USER2);
|
||||
} else if (userwords1.InList(s)) {
|
||||
sc.ChangeState(SCE_T3_USER1);
|
||||
}
|
||||
sc.SetState(initState);
|
||||
}
|
||||
|
||||
static void ColouriseTADS3MsgParam(StyleContext &sc, int &lineState) {
|
||||
int endState = sc.state;
|
||||
int chQuote = '"';
|
||||
switch (endState) {
|
||||
case SCE_T3_S_STRING:
|
||||
sc.SetState(SCE_T3_MSG_PARAM);
|
||||
sc.Forward();
|
||||
chQuote = '\'';
|
||||
break;
|
||||
case SCE_T3_D_STRING:
|
||||
case SCE_T3_X_STRING:
|
||||
sc.SetState(SCE_T3_MSG_PARAM);
|
||||
sc.Forward();
|
||||
break;
|
||||
case SCE_T3_MSG_PARAM:
|
||||
if (lineState&T3_SINGLE_QUOTE) {
|
||||
endState = SCE_T3_S_STRING;
|
||||
chQuote = '\'';
|
||||
} else if (lineState&T3_INT_EXPRESSION) {
|
||||
endState = SCE_T3_X_STRING;
|
||||
} else {
|
||||
endState = SCE_T3_D_STRING;
|
||||
}
|
||||
break;
|
||||
}
|
||||
while (sc.More() && sc.ch != '}' && sc.ch != chQuote) {
|
||||
if (IsEOL(sc.ch, sc.chNext)) {
|
||||
return;
|
||||
}
|
||||
if (sc.ch == '\\') {
|
||||
sc.Forward();
|
||||
}
|
||||
sc.Forward();
|
||||
}
|
||||
if (sc.ch == chQuote) {
|
||||
sc.SetState(endState);
|
||||
} else {
|
||||
sc.ForwardSetState(endState);
|
||||
}
|
||||
}
|
||||
|
||||
static void ColouriseTADS3LibDirective(StyleContext &sc, int &lineState) {
|
||||
int initState = sc.state;
|
||||
int chQuote = '"';
|
||||
switch (initState) {
|
||||
case SCE_T3_S_STRING:
|
||||
sc.SetState(SCE_T3_LIB_DIRECTIVE);
|
||||
sc.Forward(2);
|
||||
chQuote = '\'';
|
||||
break;
|
||||
case SCE_T3_D_STRING:
|
||||
sc.SetState(SCE_T3_LIB_DIRECTIVE);
|
||||
sc.Forward(2);
|
||||
break;
|
||||
case SCE_T3_LIB_DIRECTIVE:
|
||||
if (lineState&T3_SINGLE_QUOTE) {
|
||||
initState = SCE_T3_S_STRING;
|
||||
chQuote = '\'';
|
||||
} else {
|
||||
initState = SCE_T3_D_STRING;
|
||||
}
|
||||
break;
|
||||
}
|
||||
while (sc.More() && IsADirectiveChar(sc.ch)) {
|
||||
if (IsEOL(sc.ch, sc.chNext)) {
|
||||
return;
|
||||
}
|
||||
sc.Forward();
|
||||
};
|
||||
if (sc.ch == '>' || !sc.More()) {
|
||||
sc.ForwardSetState(initState);
|
||||
} else if (sc.ch == chQuote) {
|
||||
sc.SetState(initState);
|
||||
} else {
|
||||
sc.ChangeState(initState);
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
|
||||
static void ColouriseTADS3String(StyleContext &sc, int &lineState) {
|
||||
int chQuote = sc.ch;
|
||||
int endState = sc.state;
|
||||
switch (sc.state) {
|
||||
case SCE_T3_DEFAULT:
|
||||
case SCE_T3_X_DEFAULT:
|
||||
if (chQuote == '"') {
|
||||
if (sc.state == SCE_T3_DEFAULT) {
|
||||
sc.SetState(SCE_T3_D_STRING);
|
||||
} else {
|
||||
sc.SetState(SCE_T3_X_STRING);
|
||||
}
|
||||
lineState &= ~T3_SINGLE_QUOTE;
|
||||
} else {
|
||||
sc.SetState(SCE_T3_S_STRING);
|
||||
lineState |= T3_SINGLE_QUOTE;
|
||||
}
|
||||
sc.Forward();
|
||||
break;
|
||||
case SCE_T3_S_STRING:
|
||||
chQuote = '\'';
|
||||
endState = lineState&T3_INT_EXPRESSION ?
|
||||
SCE_T3_X_DEFAULT : SCE_T3_DEFAULT;
|
||||
break;
|
||||
case SCE_T3_D_STRING:
|
||||
chQuote = '"';
|
||||
endState = SCE_T3_DEFAULT;
|
||||
break;
|
||||
case SCE_T3_X_STRING:
|
||||
chQuote = '"';
|
||||
endState = SCE_T3_X_DEFAULT;
|
||||
break;
|
||||
}
|
||||
while (sc.More()) {
|
||||
if (IsEOL(sc.ch, sc.chNext)) {
|
||||
return;
|
||||
}
|
||||
if (sc.ch == chQuote) {
|
||||
sc.ForwardSetState(endState);
|
||||
return;
|
||||
}
|
||||
if (sc.state == SCE_T3_D_STRING && sc.Match('<', '<')) {
|
||||
lineState |= T3_INT_EXPRESSION;
|
||||
sc.SetState(SCE_T3_X_DEFAULT);
|
||||
sc.Forward(2);
|
||||
return;
|
||||
}
|
||||
if (sc.Match('\\', static_cast<char>(chQuote))
|
||||
|| sc.Match('\\', '\\')) {
|
||||
sc.Forward(2);
|
||||
} else if (sc.ch == '{') {
|
||||
ColouriseTADS3MsgParam(sc, lineState);
|
||||
} else if (sc.Match('<', '.')) {
|
||||
ColouriseTADS3LibDirective(sc, lineState);
|
||||
} else if (sc.ch == '<') {
|
||||
ColouriseTADS3HTMLTag(sc, lineState);
|
||||
if (sc.state == SCE_T3_X_DEFAULT)
|
||||
return;
|
||||
} else {
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ColouriseTADS3Comment(StyleContext &sc, int endState) {
|
||||
sc.SetState(SCE_T3_BLOCK_COMMENT);
|
||||
while (sc.More()) {
|
||||
if (IsEOL(sc.ch, sc.chNext)) {
|
||||
return;
|
||||
}
|
||||
if (sc.Match('*', '/')) {
|
||||
sc.Forward(2);
|
||||
sc.SetState(endState);
|
||||
return;
|
||||
}
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
|
||||
static void ColouriseToEndOfLine(StyleContext &sc, int initState, int endState) {
|
||||
sc.SetState(initState);
|
||||
while (sc.More()) {
|
||||
if (sc.ch == '\\') {
|
||||
sc.Forward();
|
||||
if (IsEOLSkip(sc)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (IsEOL(sc.ch, sc.chNext)) {
|
||||
sc.SetState(endState);
|
||||
return;
|
||||
}
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
|
||||
static void ColouriseTADS3Number(StyleContext &sc) {
|
||||
int endState = sc.state;
|
||||
bool inHexNumber = false;
|
||||
bool seenE = false;
|
||||
bool seenDot = sc.ch == '.';
|
||||
sc.SetState(SCE_T3_NUMBER);
|
||||
if (sc.More()) {
|
||||
sc.Forward();
|
||||
}
|
||||
if (sc.chPrev == '0' && tolower(sc.ch) == 'x') {
|
||||
inHexNumber = true;
|
||||
sc.Forward();
|
||||
}
|
||||
while (sc.More()) {
|
||||
if (inHexNumber) {
|
||||
if (!IsAHexDigit(sc.ch)) {
|
||||
break;
|
||||
}
|
||||
} else if (!isdigit(sc.ch)) {
|
||||
if (!seenE && tolower(sc.ch) == 'e') {
|
||||
seenE = true;
|
||||
seenDot = true;
|
||||
if (sc.chNext == '+' || sc.chNext == '-') {
|
||||
sc.Forward();
|
||||
}
|
||||
} else if (!seenDot && sc.ch == '.') {
|
||||
seenDot = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
sc.Forward();
|
||||
}
|
||||
sc.SetState(endState);
|
||||
}
|
||||
|
||||
static void ColouriseTADS3Doc(Sci_PositionU startPos, Sci_Position length, int initStyle,
|
||||
WordList *keywordlists[], Accessor &styler) {
|
||||
int visibleChars = 0;
|
||||
int bracketLevel = 0;
|
||||
int lineState = 0;
|
||||
Sci_PositionU endPos = startPos + length;
|
||||
Sci_Position lineCurrent = styler.GetLine(startPos);
|
||||
if (lineCurrent > 0) {
|
||||
lineState = styler.GetLineState(lineCurrent-1);
|
||||
}
|
||||
StyleContext sc(startPos, length, initStyle, styler);
|
||||
|
||||
while (sc.More()) {
|
||||
|
||||
if (IsEOL(sc.ch, sc.chNext)) {
|
||||
styler.SetLineState(lineCurrent, lineState);
|
||||
lineCurrent++;
|
||||
visibleChars = 0;
|
||||
sc.Forward();
|
||||
if (sc.ch == '\n') {
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
|
||||
switch(sc.state) {
|
||||
case SCE_T3_PREPROCESSOR:
|
||||
case SCE_T3_LINE_COMMENT:
|
||||
ColouriseToEndOfLine(sc, sc.state, lineState&T3_INT_EXPRESSION ?
|
||||
SCE_T3_X_DEFAULT : SCE_T3_DEFAULT);
|
||||
break;
|
||||
case SCE_T3_S_STRING:
|
||||
case SCE_T3_D_STRING:
|
||||
case SCE_T3_X_STRING:
|
||||
ColouriseTADS3String(sc, lineState);
|
||||
visibleChars++;
|
||||
break;
|
||||
case SCE_T3_MSG_PARAM:
|
||||
ColouriseTADS3MsgParam(sc, lineState);
|
||||
break;
|
||||
case SCE_T3_LIB_DIRECTIVE:
|
||||
ColouriseTADS3LibDirective(sc, lineState);
|
||||
break;
|
||||
case SCE_T3_HTML_DEFAULT:
|
||||
ColouriseTADS3HTMLTag(sc, lineState);
|
||||
break;
|
||||
case SCE_T3_HTML_STRING:
|
||||
ColouriseTADSHTMLString(sc, lineState);
|
||||
break;
|
||||
case SCE_T3_BLOCK_COMMENT:
|
||||
ColouriseTADS3Comment(sc, lineState&T3_INT_EXPRESSION ?
|
||||
SCE_T3_X_DEFAULT : SCE_T3_DEFAULT);
|
||||
break;
|
||||
case SCE_T3_DEFAULT:
|
||||
case SCE_T3_X_DEFAULT:
|
||||
if (IsASpaceOrTab(sc.ch)) {
|
||||
sc.Forward();
|
||||
} else if (sc.ch == '#' && visibleChars == 0) {
|
||||
ColouriseToEndOfLine(sc, SCE_T3_PREPROCESSOR, sc.state);
|
||||
} else if (sc.Match('/', '*')) {
|
||||
ColouriseTADS3Comment(sc, sc.state);
|
||||
visibleChars++;
|
||||
} else if (sc.Match('/', '/')) {
|
||||
ColouriseToEndOfLine(sc, SCE_T3_LINE_COMMENT, sc.state);
|
||||
} else if (sc.ch == '"') {
|
||||
bracketLevel = 0;
|
||||
ColouriseTADS3String(sc, lineState);
|
||||
visibleChars++;
|
||||
} else if (sc.ch == '\'') {
|
||||
ColouriseTADS3String(sc, lineState);
|
||||
visibleChars++;
|
||||
} else if (sc.state == SCE_T3_X_DEFAULT && bracketLevel == 0
|
||||
&& sc.Match('>', '>')) {
|
||||
sc.Forward(2);
|
||||
sc.SetState(SCE_T3_D_STRING);
|
||||
if (lineState & T3_INT_EXPRESSION_IN_TAG)
|
||||
sc.SetState(SCE_T3_HTML_STRING);
|
||||
lineState &= ~(T3_SINGLE_QUOTE|T3_INT_EXPRESSION
|
||||
|T3_INT_EXPRESSION_IN_TAG);
|
||||
} else if (IsATADS3Operator(sc.ch)) {
|
||||
if (sc.state == SCE_T3_X_DEFAULT) {
|
||||
if (sc.ch == '(') {
|
||||
bracketLevel++;
|
||||
} else if (sc.ch == ')' && bracketLevel > 0) {
|
||||
bracketLevel--;
|
||||
}
|
||||
}
|
||||
ColouriseTADS3Operator(sc);
|
||||
visibleChars++;
|
||||
} else if (IsANumberStart(sc)) {
|
||||
ColouriseTADS3Number(sc);
|
||||
visibleChars++;
|
||||
} else if (IsAWordStart(sc.ch)) {
|
||||
ColouriseTADS3Keyword(sc, keywordlists, endPos);
|
||||
visibleChars++;
|
||||
} else if (sc.Match("...")) {
|
||||
sc.SetState(SCE_T3_IDENTIFIER);
|
||||
sc.Forward(3);
|
||||
sc.SetState(SCE_T3_DEFAULT);
|
||||
} else {
|
||||
sc.Forward();
|
||||
visibleChars++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sc.SetState(SCE_T3_DEFAULT);
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
sc.Complete();
|
||||
}
|
||||
|
||||
/*
|
||||
TADS3 has two styles of top level block (TLB). Eg
|
||||
|
||||
// default style
|
||||
silverKey : Key 'small silver key' 'small silver key'
|
||||
"A small key glints in the sunlight. "
|
||||
;
|
||||
|
||||
and
|
||||
|
||||
silverKey : Key {
|
||||
'small silver key'
|
||||
'small silver key'
|
||||
"A small key glints in the sunlight. "
|
||||
}
|
||||
|
||||
Some constructs mandate one or the other, but usually the author has may choose
|
||||
either.
|
||||
|
||||
T3_SEENSTART is used to indicate that a braceless TLB has been (potentially)
|
||||
seen and is also used to match the closing ';' of the default style.
|
||||
|
||||
T3_EXPECTINGIDENTIFIER and T3_EXPECTINGPUNCTUATION are used to keep track of
|
||||
what characters may be seen without incrementing the block level. The general
|
||||
pattern is identifier <punc> identifier, acceptable punctuation characters
|
||||
are ':', ',', '(' and ')'. No attempt is made to ensure that punctuation
|
||||
characters are syntactically correct, eg parentheses match. A ')' always
|
||||
signifies the start of a block. We just need to check if it is followed by a
|
||||
'{', in which case we let the brace handling code handle the folding level.
|
||||
|
||||
expectingIdentifier == false && expectingIdentifier == false
|
||||
Before the start of a TLB.
|
||||
|
||||
expectingIdentifier == true && expectingIdentifier == true
|
||||
Currently in an identifier. Will accept identifier or punctuation.
|
||||
|
||||
expectingIdentifier == true && expectingIdentifier == false
|
||||
Just seen a punctuation character & now waiting for an identifier to start.
|
||||
|
||||
expectingIdentifier == false && expectingIdentifier == truee
|
||||
We were in an identifier and have seen space. Now waiting to see a punctuation
|
||||
character
|
||||
|
||||
Space, comments & preprocessor directives are always acceptable and are
|
||||
equivalent.
|
||||
*/
|
||||
|
||||
static const int T3_SEENSTART = 1 << 12;
|
||||
static const int T3_EXPECTINGIDENTIFIER = 1 << 13;
|
||||
static const int T3_EXPECTINGPUNCTUATION = 1 << 14;
|
||||
|
||||
static inline bool IsStringTransition(int s1, int s2) {
|
||||
return s1 != s2
|
||||
&& (s1 == SCE_T3_S_STRING || s1 == SCE_T3_X_STRING
|
||||
|| (s1 == SCE_T3_D_STRING && s2 != SCE_T3_X_DEFAULT))
|
||||
&& s2 != SCE_T3_LIB_DIRECTIVE
|
||||
&& s2 != SCE_T3_MSG_PARAM
|
||||
&& s2 != SCE_T3_HTML_TAG
|
||||
&& s2 != SCE_T3_HTML_STRING;
|
||||
}
|
||||
|
||||
static inline bool IsATADS3Punctuation(const int ch) {
|
||||
return ch == ':' || ch == ',' || ch == '(' || ch == ')';
|
||||
}
|
||||
|
||||
static inline bool IsAnIdentifier(const int style) {
|
||||
return style == SCE_T3_IDENTIFIER
|
||||
|| style == SCE_T3_USER1
|
||||
|| style == SCE_T3_USER2
|
||||
|| style == SCE_T3_USER3;
|
||||
}
|
||||
|
||||
static inline bool IsAnOperator(const int style) {
|
||||
return style == SCE_T3_OPERATOR || style == SCE_T3_BRACE;
|
||||
}
|
||||
|
||||
static inline bool IsSpaceEquivalent(const int ch, const int style) {
|
||||
return isspace(ch)
|
||||
|| style == SCE_T3_BLOCK_COMMENT
|
||||
|| style == SCE_T3_LINE_COMMENT
|
||||
|| style == SCE_T3_PREPROCESSOR;
|
||||
}
|
||||
|
||||
static char peekAhead(Sci_PositionU startPos, Sci_PositionU endPos,
|
||||
Accessor &styler) {
|
||||
for (Sci_PositionU i = startPos; i < endPos; i++) {
|
||||
int style = styler.StyleAt(i);
|
||||
char ch = styler[i];
|
||||
if (!IsSpaceEquivalent(ch, style)) {
|
||||
if (IsAnIdentifier(style)) {
|
||||
return 'a';
|
||||
}
|
||||
if (IsATADS3Punctuation(ch)) {
|
||||
return ':';
|
||||
}
|
||||
if (ch == '{') {
|
||||
return '{';
|
||||
}
|
||||
return '*';
|
||||
}
|
||||
}
|
||||
return ' ';
|
||||
}
|
||||
|
||||
static void FoldTADS3Doc(Sci_PositionU startPos, Sci_Position length, int initStyle,
|
||||
WordList *[], Accessor &styler) {
|
||||
Sci_PositionU endPos = startPos + length;
|
||||
Sci_Position lineCurrent = styler.GetLine(startPos);
|
||||
int levelCurrent = SC_FOLDLEVELBASE;
|
||||
if (lineCurrent > 0)
|
||||
levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
|
||||
int seenStart = levelCurrent & T3_SEENSTART;
|
||||
int expectingIdentifier = levelCurrent & T3_EXPECTINGIDENTIFIER;
|
||||
int expectingPunctuation = levelCurrent & T3_EXPECTINGPUNCTUATION;
|
||||
levelCurrent &= SC_FOLDLEVELNUMBERMASK;
|
||||
int levelMinCurrent = levelCurrent;
|
||||
int levelNext = levelCurrent;
|
||||
char chNext = styler[startPos];
|
||||
int styleNext = styler.StyleAt(startPos);
|
||||
int style = initStyle;
|
||||
char ch = chNext;
|
||||
int stylePrev = style;
|
||||
bool redo = false;
|
||||
for (Sci_PositionU i = startPos; i < endPos; i++) {
|
||||
if (redo) {
|
||||
redo = false;
|
||||
i--;
|
||||
} else {
|
||||
ch = chNext;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
stylePrev = style;
|
||||
style = styleNext;
|
||||
styleNext = styler.StyleAt(i + 1);
|
||||
}
|
||||
bool atEOL = IsEOL(ch, chNext);
|
||||
|
||||
if (levelNext == SC_FOLDLEVELBASE) {
|
||||
if (IsSpaceEquivalent(ch, style)) {
|
||||
if (expectingPunctuation) {
|
||||
expectingIdentifier = 0;
|
||||
}
|
||||
if (style == SCE_T3_BLOCK_COMMENT) {
|
||||
levelNext++;
|
||||
}
|
||||
} else if (ch == '{') {
|
||||
levelNext++;
|
||||
seenStart = 0;
|
||||
} else if (ch == '\'' || ch == '"' || ch == '[') {
|
||||
levelNext++;
|
||||
if (seenStart) {
|
||||
redo = true;
|
||||
}
|
||||
} else if (ch == ';') {
|
||||
seenStart = 0;
|
||||
expectingIdentifier = 0;
|
||||
expectingPunctuation = 0;
|
||||
} else if (expectingIdentifier && expectingPunctuation) {
|
||||
if (IsATADS3Punctuation(ch)) {
|
||||
if (ch == ')' && peekAhead(i+1, endPos, styler) != '{') {
|
||||
levelNext++;
|
||||
} else {
|
||||
expectingPunctuation = 0;
|
||||
}
|
||||
} else if (!IsAnIdentifier(style)) {
|
||||
levelNext++;
|
||||
}
|
||||
} else if (expectingIdentifier && !expectingPunctuation) {
|
||||
if (!IsAnIdentifier(style)) {
|
||||
levelNext++;
|
||||
} else {
|
||||
expectingPunctuation = T3_EXPECTINGPUNCTUATION;
|
||||
}
|
||||
} else if (!expectingIdentifier && expectingPunctuation) {
|
||||
if (!IsATADS3Punctuation(ch)) {
|
||||
levelNext++;
|
||||
} else {
|
||||
if (ch == ')' && peekAhead(i+1, endPos, styler) != '{') {
|
||||
levelNext++;
|
||||
} else {
|
||||
expectingIdentifier = T3_EXPECTINGIDENTIFIER;
|
||||
expectingPunctuation = 0;
|
||||
}
|
||||
}
|
||||
} else if (!expectingIdentifier && !expectingPunctuation) {
|
||||
if (IsAnIdentifier(style)) {
|
||||
seenStart = T3_SEENSTART;
|
||||
expectingIdentifier = T3_EXPECTINGIDENTIFIER;
|
||||
expectingPunctuation = T3_EXPECTINGPUNCTUATION;
|
||||
}
|
||||
}
|
||||
|
||||
if (levelNext != SC_FOLDLEVELBASE && style != SCE_T3_BLOCK_COMMENT) {
|
||||
expectingIdentifier = 0;
|
||||
expectingPunctuation = 0;
|
||||
}
|
||||
|
||||
} else if (levelNext == SC_FOLDLEVELBASE+1 && seenStart
|
||||
&& ch == ';' && IsAnOperator(style)) {
|
||||
levelNext--;
|
||||
seenStart = 0;
|
||||
} else if (style == SCE_T3_BLOCK_COMMENT) {
|
||||
if (stylePrev != SCE_T3_BLOCK_COMMENT) {
|
||||
levelNext++;
|
||||
} else if (styleNext != SCE_T3_BLOCK_COMMENT && !atEOL) {
|
||||
// Comments don't end at end of line and the next character may be unstyled.
|
||||
levelNext--;
|
||||
}
|
||||
} else if (ch == '\'' || ch == '"') {
|
||||
if (IsStringTransition(style, stylePrev)) {
|
||||
if (levelMinCurrent > levelNext) {
|
||||
levelMinCurrent = levelNext;
|
||||
}
|
||||
levelNext++;
|
||||
} else if (IsStringTransition(style, styleNext)) {
|
||||
levelNext--;
|
||||
}
|
||||
} else if (IsAnOperator(style)) {
|
||||
if (ch == '{' || ch == '[') {
|
||||
// Measure the minimum before a '{' to allow
|
||||
// folding on "} else {"
|
||||
if (levelMinCurrent > levelNext) {
|
||||
levelMinCurrent = levelNext;
|
||||
}
|
||||
levelNext++;
|
||||
} else if (ch == '}' || ch == ']') {
|
||||
levelNext--;
|
||||
}
|
||||
}
|
||||
|
||||
if (atEOL) {
|
||||
if (seenStart && levelNext == SC_FOLDLEVELBASE) {
|
||||
switch (peekAhead(i+1, endPos, styler)) {
|
||||
case ' ':
|
||||
case '{':
|
||||
break;
|
||||
case '*':
|
||||
levelNext++;
|
||||
break;
|
||||
case 'a':
|
||||
if (expectingPunctuation) {
|
||||
levelNext++;
|
||||
}
|
||||
break;
|
||||
case ':':
|
||||
if (expectingIdentifier) {
|
||||
levelNext++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (levelNext != SC_FOLDLEVELBASE) {
|
||||
expectingIdentifier = 0;
|
||||
expectingPunctuation = 0;
|
||||
}
|
||||
}
|
||||
int lev = levelMinCurrent | (levelNext | expectingIdentifier
|
||||
| expectingPunctuation | seenStart) << 16;
|
||||
if (levelMinCurrent < levelNext)
|
||||
lev |= SC_FOLDLEVELHEADERFLAG;
|
||||
if (lev != styler.LevelAt(lineCurrent)) {
|
||||
styler.SetLevel(lineCurrent, lev);
|
||||
}
|
||||
lineCurrent++;
|
||||
levelCurrent = levelNext;
|
||||
levelMinCurrent = levelCurrent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char * const tads3WordList[] = {
|
||||
"TADS3 Keywords",
|
||||
"User defined 1",
|
||||
"User defined 2",
|
||||
"User defined 3",
|
||||
0
|
||||
};
|
||||
|
||||
extern const LexerModule lmTADS3(SCLEX_TADS3, ColouriseTADS3Doc, "tads3", FoldTADS3Doc, tads3WordList);
|
Reference in New Issue
Block a user