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

📄 lexruby.cxx

📁 最强源代码编辑控件
💻 CXX
📖 第 1 页 / 共 5 页
字号:
	bool preferRE = true;
    int state = initStyle;
	int lengthDoc = startPos + length;

	char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero
	prevWord[0] = '\0';
	if (length == 0)
		return;

	char chPrev = styler.SafeGetCharAt(startPos - 1);
	char chNext = styler.SafeGetCharAt(startPos);
	bool is_real_number = true;   // Differentiate between constants and ?-sequences.
	// Ruby uses a different mask because bad indentation is marked by oring with 32
	styler.StartAt(startPos, 127);
	styler.StartSegment(startPos);

    static int q_states[] = {SCE_RB_STRING_Q,
                             SCE_RB_STRING_QQ,
                             SCE_RB_STRING_QR,
                             SCE_RB_STRING_QW,
                             SCE_RB_STRING_QW,
                             SCE_RB_STRING_QX};
    static const char* q_chars = "qQrwWx";

    // In most cases a value of 2 should be ample for the code in the
    // Ruby library, and the code the user is likely to enter.
    // For example,
    // fu_output_message "mkdir #{options[:mode] ? ('-m %03o ' % options[:mode]) : ''}#{list.join ' '}"
    //     if options[:verbose]
    // from fileutils.rb nests to a level of 2
    // If the user actually hits a 6th occurrence of '#{' in a double-quoted
    // string (including regex'es, %Q, %<sym>, %w, and other strings
    // that interpolate), it will stay as a string.  The problem with this
    // is that quotes might flip, a 7th '#{' will look like a comment,
    // and code-folding might be wrong.

    // If anyone runs into this problem, I recommend raising this
    // value slightly higher to replacing the fixed array with a linked
    // list.  Keep in mind this code will be called everytime the lexer
    // is invoked.

#define INNER_STRINGS_MAX_COUNT 5
    // These vars track our instances of "...#{,,,%Q<..#{,,,}...>,,,}..."
    int inner_string_types[INNER_STRINGS_MAX_COUNT];
    // Track # braces when we push a new #{ thing
    int inner_expn_brace_counts[INNER_STRINGS_MAX_COUNT];
    QuoteCls inner_quotes[INNER_STRINGS_MAX_COUNT];
    int inner_string_count = 0;
    int brace_counts = 0;   // Number of #{ ... } things within an expression

    int i;
	for (i = 0; i < INNER_STRINGS_MAX_COUNT; i++) {
        inner_string_types[i] = 0;
        inner_expn_brace_counts[i] = 0;
    }
	for (i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		char chNext2 = styler.SafeGetCharAt(i + 2);

        if (styler.IsLeadByte(ch)) {
			chNext = chNext2;
			chPrev = ' ';
			i += 1;
			continue;
		}
		
        // skip on DOS/Windows
        //No, don't, because some things will get tagged on,
        // so we won't recognize keywords, for example
#if 0
		if (ch == '\r' && chNext == '\n') {
	    	continue;
        }
#endif
            
        if (HereDoc.State == 1 && isEOLChar(ch)) {
			// Begin of here-doc (the line after the here-doc delimiter):
			HereDoc.State = 2;
			styler.ColourTo(i-1, state);
            // Don't check for a missing quote, just jump into
            // the here-doc state
            state = SCE_RB_HERE_Q;
        }

        // Regular transitions
		if (state == SCE_RB_DEFAULT) {
            if (isSafeDigit(ch)) {
            	styler.ColourTo(i - 1, state);
				state = SCE_RB_NUMBER;
                is_real_number = true;
                numDots = 0;
            } else if (isHighBitChar(ch) || iswordstart(ch)) {
            	styler.ColourTo(i - 1, state);
				state = SCE_RB_WORD;
			} else if (ch == '#') {
				styler.ColourTo(i - 1, state);
				state = SCE_RB_COMMENTLINE;
			} else if (ch == '=') {
				// =begin indicates the start of a comment (doc) block
                if (i == 0 || isEOLChar(chPrev)
                    && chNext == 'b'
                    && styler.SafeGetCharAt(i + 2) == 'e'
                    && styler.SafeGetCharAt(i + 3) == 'g'
                    && styler.SafeGetCharAt(i + 4) == 'i'
                    && styler.SafeGetCharAt(i + 5) == 'n'
                    && !isSafeWordcharOrHigh(styler.SafeGetCharAt(i + 6))) {
                    styler.ColourTo(i - 1, state);
                    state = SCE_RB_POD;
				} else {
					styler.ColourTo(i - 1, state);
					styler.ColourTo(i, SCE_RB_OPERATOR);
					preferRE = true;
				}
			} else if (ch == '"') {
				styler.ColourTo(i - 1, state);
				state = SCE_RB_STRING;
				Quote.New();
				Quote.Open(ch);
			} else if (ch == '\'') {
                styler.ColourTo(i - 1, state);
                state = SCE_RB_CHARACTER;
                Quote.New();
                Quote.Open(ch);
			} else if (ch == '`') {
				styler.ColourTo(i - 1, state);
				state = SCE_RB_BACKTICKS;
				Quote.New();
				Quote.Open(ch);
			} else if (ch == '@') {
                // Instance or class var
				styler.ColourTo(i - 1, state);
                if (chNext == '@') {
                    state = SCE_RB_CLASS_VAR;
                    advance_char(i, ch, chNext, chNext2); // pass by ref
                } else {
                    state = SCE_RB_INSTANCE_VAR;
                }
			} else if (ch == '$') {
                // Check for a builtin global
				styler.ColourTo(i - 1, state);
                // Recognize it bit by bit
                state = SCE_RB_GLOBAL;
            } else if (ch == '/' && preferRE) {
                // Ambigous operator
				styler.ColourTo(i - 1, state);
				state = SCE_RB_REGEX;
                Quote.New();
                Quote.Open(ch);
			} else if (ch == '<' && chNext == '<' && chNext2 != '=') {

                // Recognise the '<<' symbol - either a here document or a binary op
				styler.ColourTo(i - 1, state);
                i++;
                chNext = chNext2;
				styler.ColourTo(i, SCE_RB_OPERATOR);

                if (! (strchr("\"\'`_-", chNext2) || isSafeAlpha(chNext2))) {
                    // It's definitely not a here-doc,
                    // based on Ruby's lexer/parser in the
                    // heredoc_identifier routine.
                    // Nothing else to do.
                } else if (preferRE) {
                    if (sureThisIsHeredoc(i - 1, styler, prevWord)) {
                        state = SCE_RB_HERE_DELIM;
                        HereDoc.State = 0;
                    }
                    // else leave it in default state
                } else {
                    if (sureThisIsNotHeredoc(i - 1, styler)) {
                        // leave state as default
                        // We don't have all the heuristics Perl has for indications
                        // of a here-doc, because '<<' is overloadable and used
                        // for so many other classes.
                    } else {
                        state = SCE_RB_HERE_DELIM;
                        HereDoc.State = 0;
                    }
                }
                preferRE = (state != SCE_RB_HERE_DELIM);
            } else if (ch == ':') {
				styler.ColourTo(i - 1, state);
                if (chNext == ':') {
                    // Mark "::" as an operator, not symbol start
                    styler.ColourTo(i + 1, SCE_RB_OPERATOR);
                    advance_char(i, ch, chNext, chNext2); // pass by ref
                    state = SCE_RB_DEFAULT;
					preferRE = false;
                } else if (isSafeWordcharOrHigh(chNext)) {
					state = SCE_RB_SYMBOL;
                } else if (strchr("[*!~+-*/%=<>&^|", chNext)) {
                    // Do the operator analysis in-line, looking ahead
                    // Based on the table in pickaxe 2nd ed., page 339
                    bool doColoring = true;
                    switch (chNext) {
                    case '[':
                        if (chNext2 == ']' ) {
                            char ch_tmp = styler.SafeGetCharAt(i + 3);
                            if (ch_tmp == '=') {
                                i += 3;
                                ch = ch_tmp;
                                chNext = styler.SafeGetCharAt(i + 1);
                            } else {
                                i += 2;
                                ch = chNext2;
                                chNext = ch_tmp;
                            }
                        } else {
                            doColoring = false;
                        }
                        break;

                    case '*':
                        if (chNext2 == '*') {
                            i += 2;
                            ch = chNext2;
                            chNext = styler.SafeGetCharAt(i + 1);
                        } else {
                            advance_char(i, ch, chNext, chNext2);
                        }
                        break;

                    case '!':
                        if (chNext2 == '=' || chNext2 == '~') {
                            i += 2;
                            ch = chNext2;
                            chNext = styler.SafeGetCharAt(i + 1);
                        } else {
                            advance_char(i, ch, chNext, chNext2);
                        }
                        break;

                    case '<':
                        if (chNext2 == '<') {
                            i += 2;
                            ch = chNext2;
                            chNext = styler.SafeGetCharAt(i + 1);
                        } else if (chNext2 == '=') {
                            char ch_tmp = styler.SafeGetCharAt(i + 3);
                            if (ch_tmp == '>') {  // <=> operator
                                i += 3;
                                ch = ch_tmp;
                                chNext = styler.SafeGetCharAt(i + 1);
                            } else {
                                i += 2;
                                ch = chNext2;
                                chNext = ch_tmp;
                            }
                        } else {
                            advance_char(i, ch, chNext, chNext2);
                        }
                        break;

                    default:
                        // Simple one-character operators
                        advance_char(i, ch, chNext, chNext2);
                        break;
                    }
                    if (doColoring) {
                        styler.ColourTo(i, SCE_RB_SYMBOL);
                        state = SCE_RB_DEFAULT;
                    }
				} else if (!preferRE) {
					// Don't color symbol strings (yet)
					// Just color the ":" and color rest as string
					styler.ColourTo(i, SCE_RB_SYMBOL);
					state = SCE_RB_DEFAULT;
                } else {
                    styler.ColourTo(i, SCE_RB_OPERATOR);
                    state = SCE_RB_DEFAULT;
                    preferRE = true;
                }
            } else if (ch == '%') {
                styler.ColourTo(i - 1, state);
                bool have_string = false;
                if (strchr(q_chars, chNext) && !isSafeWordcharOrHigh(chNext2)) {
                    Quote.New();
                    const char *hit = strchr(q_chars, chNext);
                    if (hit != NULL) {
                        state = q_states[hit - q_chars];
                        Quote.Open(chNext2);
                        i += 2;
                        ch = chNext2;
						chNext = styler.SafeGetCharAt(i + 1);
                        have_string = true;
                    }
                } else if (preferRE && !isSafeWordcharOrHigh(chNext)) {
                    // Ruby doesn't allow high bit chars here,
                    // but the editor host might
                    state = SCE_RB_STRING_QQ;
                    Quote.Open(chNext);
                    advance_char(i, ch, chNext, chNext2); // pass by ref
                    have_string = true;
                }
                if (!have_string) {
                    styler.ColourTo(i, SCE_RB_OPERATOR);
                    // stay in default
                    preferRE = true;
                }
            } else if (ch == '?') {
                styler.ColourTo(i - 1, state);
                if (iswhitespace(chNext) || chNext == '\n' || chNext == '\r') {
                    styler.ColourTo(i, SCE_RB_OPERATOR);
                } else {
                    // It's the start of a character code escape sequence
                    // Color it as a number.
                    state = SCE_RB_NUMBER;
                    is_real_number = false;
                }
            } else if (isoperator(ch) || ch == '.') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_RB_OPERATOR);
                // If we're ending an expression or block,
                // assume it ends an object, and the ambivalent
                // constructs are binary operators
                //
                // So if we don't have one of these chars,
                // we aren't ending an object exp'n, and ops
                // like : << / are unary operators.
                
                if (ch == '{') {
                    ++brace_counts;
                    preferRE = true;
                } else if (ch == '}' && --brace_counts < 0
                           && inner_string_count > 0) {
                    styler.ColourTo(i, SCE_RB_OPERATOR);
                    exitInnerExpression(inner_string_types,
                                        inner_expn_brace_counts,
                                        inner_quotes,
                                        inner_string_count,
                                        state, brace_counts, Quote);
                } else {
                    preferRE = (strchr(")}].", ch) == NULL);
                }
                // Stay in default state
            } else if (isEOLChar(ch)) {
                // Make sure it's a true line-end, with no backslash
                if ((ch == '\r' || (ch == '\n' && chPrev != '\r'))
                    && chPrev != '\\') {
                    // Assume we've hit the end of the statement.
                    preferRE = true;
                }
            }

⌨️ 快捷键说明

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