⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lextads3.cxx

📁 非常好用的可移植的多平台C/C++源代码编辑器
💻 CXX
📖 第 1 页 / 共 2 页
字号:
// Scintilla source code edit control
/** @file LexTADS3.cxx
 ** Lexer for TADS3.
 **/
/* Copyright 2005 by Michael Cartmell
 * Parts copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
 * In particular FoldTADS3Doc is derived from FoldCppDoc
 * 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.
 *
 * Because strings, html tags, library directives, message parameters, and
 * interpolated expressions may span multiple lines it is necessary to have
 * multiple states for a single construct so that the surrounding context can be
 * known.  This is important if scanning starts part way through a source file.
 *
 * States that have a Single quoted string context have _S_ in the name
 * States that have a Double quoted string context have _D_ in the name
 * States that have an interpolated eXpression context have _X_ in the name
 * eg SCE_T3_X_S_MSG_PARAM is a message parameter in a single quoted string
 * that is part of an interpolated expression.
 * "You see << isKnown? '{iobj/him} lying' : 'nothing' >> on the ground. "
 *                       ----------
 *
 * LINKS
 * http://www.tads.org/
 */

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static unsigned int endPos;

static inline bool IsEOL(const int ch) {
	return ch == '\r' || ch == '\n';
}

static inline bool IsASpaceOrTab(const int ch) {
	return ch == ' ' || ch == '\t';
}

static inline bool IsATADS3Operator(const int ch) {
	return 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 IsABracket(const int ch) {
	return ch == '{' || ch == '[' || ch == '('
		|| ch == '}' || ch == ']' || ch == ')';
}

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;
	sc.SetState(SCE_T3_OPERATOR);
	sc.ForwardSetState(initState);
}

inline static void ColouriseTADS3Bracket(StyleContext &sc) {
	int initState = sc.state;
	sc.SetState(SCE_T3_BRACKET);
	sc.ForwardSetState(initState);
}

static void ColouriseTADSHTMLString(StyleContext &sc) {
	int initState = sc.state;
	int chQuote = sc.ch;
	int chString = chQuote == '"'? '\'': '"';
	sc.SetState(SCE_T3_HTML_STRING);
	sc.Forward();

	while (sc.More()) {
		if (sc.Match('\\', static_cast<char>(chQuote))
			|| sc.Match('\\', static_cast<char>(chString))) {
			sc.Forward(2);
		} else if (sc.ch == chQuote || IsEOL(sc.ch)) {
			sc.ForwardSetState(initState);
			return;
		} else if (sc.ch == chString) {
			sc.SetState(initState);
			return;
		}
		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 initState = sc.state;
	int chQuote = '\'';
	int chString = '"';
	switch (initState) {
		case SCE_T3_S_STRING:
			ColouriseTADS3HTMLTagStart(sc);
			sc.SetState(SCE_T3_S_H_DEFAULT);
			break;
		case SCE_T3_D_STRING:
			ColouriseTADS3HTMLTagStart(sc);
			sc.SetState(SCE_T3_S_H_DEFAULT);
			chQuote = '"';
			chString = '\'';
			break;
		case SCE_T3_X_S_STRING:
			ColouriseTADS3HTMLTagStart(sc);
			sc.SetState(SCE_T3_X_S_H_DEFAULT);
			break;
		case SCE_T3_X_D_STRING:
			ColouriseTADS3HTMLTagStart(sc);
			sc.SetState(SCE_T3_X_D_H_DEFAULT);
			chQuote = '"';
			chString = '\'';
			break;
		case SCE_T3_S_H_DEFAULT:
			initState = SCE_T3_S_STRING;
			break;
		case SCE_T3_D_H_DEFAULT:
			initState = SCE_T3_D_STRING;
			chQuote = '"';
			chString = '\'';
			break;
		case SCE_T3_X_S_H_DEFAULT:
			initState = SCE_T3_X_S_STRING;
			break;
		case SCE_T3_X_D_H_DEFAULT:
			initState = SCE_T3_X_D_STRING;
			chQuote = '"';
			chString = '\'';
			break;
	}

	while (sc.More()) {
		if (sc.Match('/', '>')) {
			sc.SetState(SCE_T3_HTML_TAG);
			sc.Forward(2);
			sc.SetState(initState);
			return;
		} else if (sc.ch == '>') {
			sc.SetState(SCE_T3_HTML_TAG);
			sc.ForwardSetState(initState);
			return;
		} else if (sc.ch == chQuote) {
			sc.SetState(initState);
			return;
		}
		if (sc.ch == chString) {
			ColouriseTADSHTMLString(sc);
		} else if (sc.ch == '=') {
			ColouriseTADS3Operator(sc);
		} else {
			sc.Forward();
		}
	}
}

static void ColouriseTADS3Keyword(StyleContext &sc,
										 WordList *keywordlists[]) {
	static char s[250];
	WordList &keywords = *keywordlists[0];
	WordList &userwords1 = *keywordlists[1];
	WordList &userwords2 = *keywordlists[2];
	int initState = sc.state;
	sc.SetState(SCE_T3_KEYWORD);
	while (sc.More() && (IsAWordChar(sc.ch) || sc.ch == '.')) {
		sc.Forward();
	}
	sc.GetCurrent(s, sizeof(s));
	if (userwords1.InList(s)) {
		sc.ChangeState(SCE_T3_USER1);
	} else if (userwords2.InList(s)) {
		sc.ChangeState(SCE_T3_USER2);
	} else if (keywords.InList(s)) {
		// state already correct
	} else if ( strcmp(s, "is") == 0 || strcmp(s, "not") == 0) {
		// have to find if "in" is next
		int 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);
		} else {
			sc.ChangeState(initState);
		}
	} else {
		sc.ChangeState(initState);
	}

	sc.SetState(initState);
}

static void ColouriseTADS3MsgParam(StyleContext &sc) {
	int initState = sc.state;
	int chQuote = '"';
	switch (initState) {
		case SCE_T3_S_STRING:
			sc.SetState(SCE_T3_S_MSG_PARAM);
			sc.Forward();
			chQuote = '\'';
			break;
		case SCE_T3_D_STRING:
			sc.SetState(SCE_T3_D_MSG_PARAM);
			sc.Forward();
			break;
		case SCE_T3_X_S_STRING:
			sc.SetState(SCE_T3_X_S_MSG_PARAM);
			sc.Forward();
			chQuote = '\'';
			break;
		case SCE_T3_X_D_STRING:
			sc.SetState(SCE_T3_X_D_MSG_PARAM);
			sc.Forward();
			break;
		case SCE_T3_S_MSG_PARAM:
			initState = SCE_T3_S_STRING;
			chQuote = '\'';
			break;
		case SCE_T3_D_MSG_PARAM:
			initState = SCE_T3_D_STRING;
			break;
		case SCE_T3_X_S_MSG_PARAM:
			initState = SCE_T3_X_S_STRING;
			chQuote = '\'';
			break;
		case SCE_T3_X_D_MSG_PARAM:
			initState = SCE_T3_X_D_STRING;
			break;
	}
	while (sc.More() && sc.ch != '}' && sc.ch != chQuote) {
		if (sc.ch == '\\') {
			sc.Forward();
		}
		sc.Forward();
	}
	if (sc.ch == chQuote) {
		sc.SetState(initState);
	} else {
		sc.ForwardSetState(initState);
	}
}

static void ColouriseTADS3LibDirective(StyleContext &sc) {
	int initState = sc.state;
	int chQuote = '"';
	switch (initState) {
		case SCE_T3_S_STRING:
			sc.SetState(SCE_T3_S_LIB_DIRECTIVE);
			sc.Forward(2);
			chQuote = '\'';
			break;
		case SCE_T3_D_STRING:
			sc.SetState(SCE_T3_D_LIB_DIRECTIVE);
			sc.Forward(2);
			break;
		case SCE_T3_X_S_STRING:
			sc.SetState(SCE_T3_X_S_LIB_DIRECTIVE);
			sc.Forward(2);
			chQuote = '\'';
			break;
		case SCE_T3_X_D_STRING:
			sc.SetState(SCE_T3_X_D_LIB_DIRECTIVE);
			sc.Forward(2);
			break;
		case SCE_T3_S_LIB_DIRECTIVE:
			initState = SCE_T3_S_STRING;
			chQuote = '\'';
			break;
		case SCE_T3_D_LIB_DIRECTIVE:
			initState = SCE_T3_D_STRING;
			break;
		case SCE_T3_X_S_LIB_DIRECTIVE:
			initState = SCE_T3_X_S_STRING;
			chQuote = '\'';
			break;
		case SCE_T3_X_D_LIB_DIRECTIVE:
			initState = SCE_T3_X_D_STRING;
			break;
	}
	while (sc.More() && IsADirectiveChar(sc.ch)) {
		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 chQuote = sc.ch;
	int initState = sc.state;
	switch (sc.state) {
		case SCE_T3_DEFAULT:
			if (chQuote == '"') {
				sc.SetState(SCE_T3_D_STRING);
			} else {
				sc.SetState(SCE_T3_S_STRING);
			}
			sc.Forward();
			break;
		case SCE_T3_X_DEFAULT:
			if (chQuote == '"') {
				sc.SetState(SCE_T3_X_D_STRING);
			} else {
				sc.SetState(SCE_T3_X_S_STRING);
			}
			sc.Forward();
			break;
		case SCE_T3_S_STRING:
			chQuote = '\'';
			initState = SCE_T3_DEFAULT;
			break;
		case SCE_T3_D_STRING:
			chQuote = '"';
			initState = SCE_T3_DEFAULT;
			break;
		case SCE_T3_X_S_STRING:
			chQuote = '\'';
			initState = SCE_T3_X_DEFAULT;
			break;
		case SCE_T3_X_D_STRING:
			chQuote = '"';
			initState = SCE_T3_X_DEFAULT;
			break;
	}
	while (sc.More()) {
		if (sc.Match('\\', static_cast<char>(chQuote))) {
			sc.Forward(2);
		}
		if (sc.ch == chQuote) {
			sc.ForwardSetState(initState);
			return;
		}
		if (sc.ch == '{') {
			ColouriseTADS3MsgParam(sc);
		} else if (sc.state == SCE_T3_D_STRING && sc.Match('<', '<')) {
			sc.SetState(SCE_T3_X_DEFAULT);
			sc.Forward(2);
			return;
		} else if (sc.Match('<', '.')) {
			ColouriseTADS3LibDirective(sc);
		} else if (sc.ch == '<') {
			ColouriseTADS3HTMLTag(sc);
		} else {
			sc.Forward();
		}
	}
}

static void ColouriseTADS3Comment(StyleContext &sc, const int initState,
								  const int endState) {
	if (sc.state != initState) {
		sc.SetState(initState);
	}
	for (; sc.More(); sc.Forward()) {
		if (sc.Match('*', '/')) {
			sc.Forward(2);
			sc.SetState(endState);
			return;
		}
	}
}

static void ColouriseToEndOfLine(StyleContext &sc, const int initState,
								 const int endState) {
	if (sc.state != initState) {
		sc.SetState(initState);
	}
	for (; sc.More(); sc.Forward()) {
		if (sc.ch == '\\') {
			if (IsEOL(sc.chNext)) {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}
		if (IsEOL(sc.ch)) {
			sc.SetState(endState);
			return;
		}
	}
}

static void ColouriseTADS3Number(StyleContext &sc) {
	int initState = sc.state;
	bool inHexNumber = false;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -