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

📄 lexruby.cxx

📁 robocup rcssserver 运行防真机器人足球比赛所用的服务器端
💻 CXX
📖 第 1 页 / 共 4 页
字号:
// Scintilla source code edit control/** @file LexRuby.cxx ** Lexer for Ruby. **/// Copyright 2001- by Clemens Wyss <wys@helbling.ch>// The License.txt file describes the conditions under which this software may be distributed.#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 "KeyWords.h"#include "Scintilla.h"#include "SciLexer.h"#ifdef SCI_NAMESPACEusing namespace Scintilla;#endif//XXX Identical to Perl, put in common areastatic inline bool isEOLChar(char ch) {	return (ch == '\r') || (ch == '\n');}#define isSafeASCII(ch) ((unsigned int)(ch) <= 127)// This one's redundant, but makes for more readable code#define isHighBitChar(ch) ((unsigned int)(ch) > 127)static inline bool isSafeAlpha(char ch) {    return (isSafeASCII(ch) && isalpha(ch)) || ch == '_';}static inline bool isSafeAlnum(char ch) {    return (isSafeASCII(ch) && isalnum(ch)) || ch == '_';}static inline bool isSafeAlnumOrHigh(char ch) {    return isHighBitChar(ch) || isalnum(ch) || ch == '_';}static inline bool isSafeDigit(char ch) {    return isSafeASCII(ch) && isdigit(ch);}static inline bool isSafeWordcharOrHigh(char ch) {    return isHighBitChar(ch) || iswordchar(ch);}static bool inline iswhitespace(char ch) {	return ch == ' ' || ch == '\t';}#define MAX_KEYWORD_LENGTH 200#define STYLE_MASK 63#define actual_style(style) (style & STYLE_MASK)static bool followsDot(unsigned int pos, Accessor &styler) {    styler.Flush();    for (; pos >= 1; --pos) {        int style = actual_style(styler.StyleAt(pos));        char ch;        switch (style) {            case SCE_RB_DEFAULT:                ch = styler[pos];                if (ch == ' ' || ch == '\t') {                    //continue                } else {                    return false;                }                break;                            case SCE_RB_OPERATOR:                return styler[pos] == '.';            default:                return false;        }    }    return false;}// Forward declarationsstatic bool keywordIsAmbiguous(const char *prevWord);static bool keywordDoStartsLoop(int pos,                                Accessor &styler);static bool keywordIsModifier(const char *word,                              int pos,                              Accessor &styler);static int ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) {	char s[100];    unsigned int i, j;	unsigned int lim = end - start + 1; // num chars to copy	if (lim >= MAX_KEYWORD_LENGTH) {		lim = MAX_KEYWORD_LENGTH - 1;	}	for (i = start, j = 0; j < lim; i++, j++) {		s[j] = styler[i];	}    s[j] = '\0';	int chAttr;	if (0 == strcmp(prevWord, "class"))		chAttr = SCE_RB_CLASSNAME;	else if (0 == strcmp(prevWord, "module"))		chAttr = SCE_RB_MODULE_NAME;	else if (0 == strcmp(prevWord, "def"))		chAttr = SCE_RB_DEFNAME;    else if (keywords.InList(s) && !followsDot(start - 1, styler)) {        if (keywordIsAmbiguous(s)            && keywordIsModifier(s, start, styler)) {                        // Demoted keywords are colored as keywords,            // but do not affect changes in indentation.            //            // Consider the word 'if':            // 1. <<if test ...>> : normal            // 2. <<stmt if test>> : demoted            // 3. <<lhs = if ...>> : normal: start a new indent level            // 4. <<obj.if = 10>> : color as identifer, since it follows '.'                        chAttr = SCE_RB_WORD_DEMOTED;        } else {            chAttr = SCE_RB_WORD;        }	} else        chAttr = SCE_RB_IDENTIFIER;	styler.ColourTo(end, chAttr);	if (chAttr == SCE_RB_WORD) {		strcpy(prevWord, s);	} else {		prevWord[0] = 0;	}    return chAttr;}//XXX Identical to Perl, put in common areastatic bool isMatch(Accessor &styler, int lengthDoc, int pos, const char *val) {	if ((pos + static_cast<int>(strlen(val))) >= lengthDoc) {		return false;	}	while (*val) {		if (*val != styler[pos++]) {			return false;		}		val++;	}	return true;}// Do Ruby better -- find the end of the line, work back,// and then check for leading white space// Precondition: the here-doc target can be indentedstatic bool lookingAtHereDocDelim(Accessor	   &styler,                                  int 			pos,                                  int 			lengthDoc,                                  const char   *HereDocDelim){    if (!isMatch(styler, lengthDoc, pos, HereDocDelim)) {        return false;    }    while (--pos > 0) {        char ch = styler[pos];        if (isEOLChar(ch)) {            return true;        } else if (ch != ' ' && ch != '\t') {            return false;        }    }    return false;}//XXX Identical to Perl, put in common areastatic char opposite(char ch) {	if (ch == '(')		return ')';	if (ch == '[')		return ']';	if (ch == '{')		return '}';	if (ch == '<')		return '>';	return ch;}// Null transitions when we see we've reached the end// and need to relex the curr char.static void redo_char(int &i, char &ch, char &chNext, char &chNext2,                      int &state) {    i--;    chNext2 = chNext;    chNext = ch;    state = SCE_RB_DEFAULT;}static void advance_char(int &i, char &ch, char &chNext, char &chNext2) {    i++;    ch = chNext;    chNext = chNext2;}// precondition: startPos points to one after the EOL charstatic bool currLineContainsHereDelims(int& startPos,                                       Accessor &styler) {    if (startPos <= 1)        return false;    int pos;    for (pos = startPos - 1; pos > 0; pos--) {        char ch = styler.SafeGetCharAt(pos);        if (isEOLChar(ch)) {            // Leave the pointers where they are -- there are no            // here doc delims on the current line, even if            // the EOL isn't default style                        return false;        } else {            styler.Flush();            if (actual_style(styler.StyleAt(pos)) == SCE_RB_HERE_DELIM) {                break;            }        }    }    if (pos == 0) {        return false;    }    // Update the pointers so we don't have to re-analyze the string    startPos = pos;    return true;}static bool isEmptyLine(int pos,                        Accessor &styler) {	int spaceFlags = 0;	int lineCurrent = styler.GetLine(pos);	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);    return (indentCurrent & SC_FOLDLEVELWHITEFLAG) != 0;}static bool RE_CanFollowKeyword(const char *keyword) {    if (!strcmp(keyword, "and")        || !strcmp(keyword, "begin")        || !strcmp(keyword, "break")        || !strcmp(keyword, "case")        || !strcmp(keyword, "do")        || !strcmp(keyword, "else")        || !strcmp(keyword, "elsif")        || !strcmp(keyword, "if")        || !strcmp(keyword, "next")        || !strcmp(keyword, "return")        || !strcmp(keyword, "when")        || !strcmp(keyword, "unless")        || !strcmp(keyword, "until")        || !strcmp(keyword, "not")        || !strcmp(keyword, "or")) {        return true;    }    return false;}// Look at chars up to but not including endPos// Don't look at styles in case we're looking forwardstatic int skipWhitespace(int startPos,                           int endPos,                           Accessor &styler) {    for (int i = startPos; i < endPos; i++) {        if (!iswhitespace(styler[i])) {            return i;        }    }    return endPos;}    // This routine looks for false positives like// undef foo, <<// There aren't too many.//// iPrev points to the start of <<static bool sureThisIsHeredoc(int iPrev,                               Accessor &styler,                              char *prevWord) {                        // Not so fast, since Ruby's so dynamic.  Check the context    // to make sure we're OK.    int prevStyle;    int lineStart = styler.GetLine(iPrev);    int lineStartPosn = styler.LineStart(lineStart);    styler.Flush();    // Find the first word after some whitespace    int firstWordPosn = skipWhitespace(lineStartPosn, iPrev, styler);    if (firstWordPosn >= iPrev) {        // Have something like {^     <<}		//XXX Look at the first previous non-comment non-white line		// to establish the context.  Not too likely though.        return true;    } else {        switch (prevStyle = styler.StyleAt(firstWordPosn)) {        case SCE_RB_WORD:        case SCE_RB_WORD_DEMOTED:        case SCE_RB_IDENTIFIER:            break;        default:            return true;        }    }    int firstWordEndPosn = firstWordPosn;    char *dst = prevWord;    for (;;) {        if (firstWordEndPosn >= iPrev ||            styler.StyleAt(firstWordEndPosn) != prevStyle) {            *dst = 0;            break;        }        *dst++ = styler[firstWordEndPosn];        firstWordEndPosn += 1;    }    //XXX Write a style-aware thing to regex scintilla buffer objects    if (!strcmp(prevWord, "undef")        || !strcmp(prevWord, "def")        || !strcmp(prevWord, "alias")) {        // These keywords are what we were looking for        return false;    }    return true;}// Routine that saves us from allocating a buffer for the here-doc target// targetEndPos points one past the end of the current targetstatic bool haveTargetMatch(int currPos,                            int lengthDoc,                            int targetStartPos,                            int targetEndPos,                            Accessor &styler) {    if (lengthDoc - currPos < targetEndPos - targetStartPos) {        return false;    }    int i, j;    for (i = targetStartPos, j = currPos;         i < targetEndPos && j < lengthDoc;         i++, j++) {        if (styler[i] != styler[j]) {            return false;        }    }    return true;}// We need a check because the form// [identifier] <<[target]// is ambiguous.  The Ruby lexer/parser resolves it by// looking to see if [identifier] names a variable or a// function.  If it's the first, it's the start of a here-doc.// If it's a var, it's an operator.  This lexer doesn't// maintain a symbol table, so it looks ahead to see what's// going on, in cases where we have// ^[white-space]*[identifier([.|::]identifier)*][white-space]*<<[target]//// If there's no occurrence of [target] on a line, assume we don't.// return true == yes, we have no heredocsstatic bool sureThisIsNotHeredoc(int lt2StartPos,                                 Accessor &styler) {    int prevStyle;     // Use full document, not just part we're styling    int lengthDoc = styler.Length();    int lineStart = styler.GetLine(lt2StartPos);    int lineStartPosn = styler.LineStart(lineStart);    styler.Flush();    const bool definitely_not_a_here_doc = true;    const bool looks_like_a_here_doc = false;        // Find the first word after some whitespace

⌨️ 快捷键说明

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