void SCI_METHOD LexerLaTeX::Lex()

in ext/scintilla/lexers/LexLaTeX.cxx [186:461]


void SCI_METHOD LexerLaTeX::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) {
	// startPos is assumed to be the first character of a line
	Accessor styler(pAccess, &props);
	styler.StartAt(startPos);
	int mode = getMode(styler.GetLine(startPos) - 1);
	int state = initStyle;
	if (state == SCE_L_ERROR || state == SCE_L_SHORTCMD || state == SCE_L_SPECIAL)   // should not happen
		latexStateReset(mode, state);

	char chNext = styler.SafeGetCharAt(startPos);
	char chVerbatimDelim = '\0';
	styler.StartSegment(startPos);
	Sci_Position lengthDoc = startPos + length;

	for (Sci_Position i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if (styler.IsLeadByte(ch)) {
			i++;
			chNext = styler.SafeGetCharAt(i + 1);
			continue;
		}

		if (ch == '\r' || ch == '\n')
			setMode(styler.GetLine(i), mode);

		switch (state) {
		case SCE_L_DEFAULT :
			switch (ch) {
			case '\\' :
				styler.ColourTo(i - 1, state);
				if (latexIsLetter(chNext)) {
					state = SCE_L_COMMAND;
				} else if (latexIsSpecial(chNext)) {
					styler.ColourTo(i + 1, SCE_L_SPECIAL);
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
				} else if (chNext == '\r' || chNext == '\n') {
					styler.ColourTo(i, SCE_L_ERROR);
				} else if (IsASCII(chNext)) {
					styler.ColourTo(i + 1, SCE_L_SHORTCMD);
					if (chNext == '(') {
						mode = 1;
						state = SCE_L_MATH;
					} else if (chNext == '[') {
						mode = 2;
						state = SCE_L_MATH2;
					}
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
				}
				break;
			case '$' :
				styler.ColourTo(i - 1, state);
				if (chNext == '$') {
					styler.ColourTo(i + 1, SCE_L_SHORTCMD);
					mode = 2;
					state = SCE_L_MATH2;
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
				} else {
					styler.ColourTo(i, SCE_L_SHORTCMD);
					mode = 1;
					state = SCE_L_MATH;
				}
				break;
			case '%' :
				styler.ColourTo(i - 1, state);
				state = SCE_L_COMMENT;
				break;
			}
			break;
		// These 3 will never be reached.
		case SCE_L_ERROR:
		case SCE_L_SPECIAL:
		case SCE_L_SHORTCMD:
			break;
		case SCE_L_COMMAND :
			if (!latexIsLetter(chNext)) {
				styler.ColourTo(i, state);
				if (latexNextNotBlankIs(i + 1, styler, '[' )) {
					state = SCE_L_CMDOPT;
				} else if (latexLastWordIs(i, styler, "\\begin")) {
					state = SCE_L_TAG;
				} else if (latexLastWordIs(i, styler, "\\end")) {
					state = SCE_L_TAG2;
				} else if (latexLastWordIs(i, styler, "\\verb") && chNext != '*' && chNext != ' ') {
					chVerbatimDelim = chNext;
					state = SCE_L_VERBATIM;
				} else {
					latexStateReset(mode, state);
				}
			}
			break;
		case SCE_L_CMDOPT :
			if (ch == ']') {
				styler.ColourTo(i, state);
				latexStateReset(mode, state);
			}
			break;
		case SCE_L_TAG :
			if (latexIsTagValid(i, lengthDoc, styler)) {
				styler.ColourTo(i, state);
				latexStateReset(mode, state);
				if (latexLastWordIs(i, styler, "{verbatim}")) {
					state = SCE_L_VERBATIM;
				} else if (latexLastWordIs(i, styler, "{comment}")) {
					state = SCE_L_COMMENT2;
				} else if (latexLastWordIs(i, styler, "{math}") && mode == 0) {
					mode = 1;
					state = SCE_L_MATH;
				} else if (latexLastWordIsMathEnv(i, styler) && mode == 0) {
					mode = 2;
					state = SCE_L_MATH2;
				}
			} else {
				styler.ColourTo(i, SCE_L_ERROR);
				latexStateReset(mode, state);
				ch = styler.SafeGetCharAt(i);
				if (ch == '\r' || ch == '\n') setMode(styler.GetLine(i), mode);
			}
			chNext = styler.SafeGetCharAt(i+1);
			break;
		case SCE_L_TAG2 :
			if (latexIsTagValid(i, lengthDoc, styler)) {
				styler.ColourTo(i, state);
				latexStateReset(mode, state);
			} else {
				styler.ColourTo(i, SCE_L_ERROR);
				latexStateReset(mode, state);
				ch = styler.SafeGetCharAt(i);
				if (ch == '\r' || ch == '\n') setMode(styler.GetLine(i), mode);
			}
			chNext = styler.SafeGetCharAt(i+1);
			break;
		case SCE_L_MATH :
			switch (ch) {
			case '\\' :
				styler.ColourTo(i - 1, state);
				if (latexIsLetter(chNext)) {
					Sci_Position match = i + 3;
					if (latexLastWordIs(match, styler, "\\end")) {
						match++;
						if (latexIsTagValid(match, lengthDoc, styler)) {
							if (latexLastWordIs(match, styler, "{math}"))
								mode = 0;
						}
					}
					state = SCE_L_COMMAND;
				} else if (latexIsSpecial(chNext)) {
					styler.ColourTo(i + 1, SCE_L_SPECIAL);
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
				} else if (chNext == '\r' || chNext == '\n') {
					styler.ColourTo(i, SCE_L_ERROR);
				} else if (IsASCII(chNext)) {
					if (chNext == ')') {
						mode = 0;
						state = SCE_L_DEFAULT;
					}
					styler.ColourTo(i + 1, SCE_L_SHORTCMD);
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
				}
				break;
			case '$' :
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_L_SHORTCMD);
				mode = 0;
				state = SCE_L_DEFAULT;
				break;
			case '%' :
				styler.ColourTo(i - 1, state);
				state = SCE_L_COMMENT;
				break;
			}
			break;
		case SCE_L_MATH2 :
			switch (ch) {
			case '\\' :
				styler.ColourTo(i - 1, state);
				if (latexIsLetter(chNext)) {
					Sci_Position match = i + 3;
					if (latexLastWordIs(match, styler, "\\end")) {
						match++;
						if (latexIsTagValid(match, lengthDoc, styler)) {
							if (latexLastWordIsMathEnv(match, styler))
								mode = 0;
						}
					}
					state = SCE_L_COMMAND;
				} else if (latexIsSpecial(chNext)) {
					styler.ColourTo(i + 1, SCE_L_SPECIAL);
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
				} else if (chNext == '\r' || chNext == '\n') {
					styler.ColourTo(i, SCE_L_ERROR);
				} else if (IsASCII(chNext)) {
					if (chNext == ']') {
						mode = 0;
						state = SCE_L_DEFAULT;
					}
					styler.ColourTo(i + 1, SCE_L_SHORTCMD);
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
				}
				break;
			case '$' :
				styler.ColourTo(i - 1, state);
				if (chNext == '$') {
					styler.ColourTo(i + 1, SCE_L_SHORTCMD);
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
					mode = 0;
					state = SCE_L_DEFAULT;
				} else { // This may not be an error, e.g. \begin{equation}\text{$a$}\end{equation}
					styler.ColourTo(i, SCE_L_SHORTCMD);
				}
				break;
			case '%' :
				styler.ColourTo(i - 1, state);
				state = SCE_L_COMMENT;
				break;
			}
			break;
		case SCE_L_COMMENT :
			if (ch == '\r' || ch == '\n') {
				styler.ColourTo(i - 1, state);
				latexStateReset(mode, state);
			}
			break;
		case SCE_L_COMMENT2 :
			if (ch == '\\') {
				Sci_Position match = i + 3;
				if (latexLastWordIs(match, styler, "\\end")) {
					match++;
					if (latexIsTagValid(match, lengthDoc, styler)) {
						if (latexLastWordIs(match, styler, "{comment}")) {
							styler.ColourTo(i - 1, state);
							state = SCE_L_COMMAND;
						}
					}
				}
			}
			break;
		case SCE_L_VERBATIM :
			if (ch == '\\') {
				Sci_Position match = i + 3;
				if (latexLastWordIs(match, styler, "\\end")) {
					match++;
					if (latexIsTagValid(match, lengthDoc, styler)) {
						if (latexLastWordIs(match, styler, "{verbatim}")) {
							styler.ColourTo(i - 1, state);
							state = SCE_L_COMMAND;
						}
					}
				}
			} else if (chNext == chVerbatimDelim) {
				styler.ColourTo(i + 1, state);
				latexStateReset(mode, state);
				chVerbatimDelim = '\0';
				i++;
				chNext = styler.SafeGetCharAt(i + 1);
			} else if (chVerbatimDelim != '\0' && (ch == '\n' || ch == '\r')) {
				styler.ColourTo(i, SCE_L_ERROR);
				latexStateReset(mode, state);
				chVerbatimDelim = '\0';
			}
			break;
		}
	}
	if (lengthDoc == styler.Length()) truncModes(styler.GetLine(lengthDoc - 1));
	styler.ColourTo(lengthDoc - 1, state);
	styler.Flush();
}