static void ColouriseErlangDoc()

in ext/scintilla/lexers/LexErlang.cxx [77:499]


static void ColouriseErlangDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
								WordList *keywordlists[], Accessor &styler) {

	StyleContext sc(startPos, length, initStyle, styler);
	WordList &reservedWords = *keywordlists[0];
	WordList &erlangBIFs = *keywordlists[1];
	WordList &erlangPreproc = *keywordlists[2];
	WordList &erlangModulesAtt = *keywordlists[3];
	WordList &erlangDoc = *keywordlists[4];
	WordList &erlangDocMacro = *keywordlists[5];
	int radix_digits = 0;
	int exponent_digits = 0;
	atom_parse_state_t parse_state = STATE_NULL;
	atom_parse_state_t old_parse_state = STATE_NULL;
	bool to_late_to_comment = false;
	char cur[100];
	int old_style = SCE_ERLANG_DEFAULT;

	styler.StartAt(startPos);

	for (; sc.More(); sc.Forward()) {
		int style = SCE_ERLANG_DEFAULT;
		if (STATE_NULL != parse_state) {

			switch (parse_state) {

				case STATE_NULL : sc.SetState(SCE_ERLANG_DEFAULT); break;

			/* COMMENTS ------------------------------------------------------*/
				case COMMENT : {
					if (sc.ch != '%') {
						to_late_to_comment = true;
					} else if (!to_late_to_comment && sc.ch == '%') {
						// Switch to comment level 2 (Function)
						sc.ChangeState(SCE_ERLANG_COMMENT_FUNCTION);
						old_style = SCE_ERLANG_COMMENT_FUNCTION;
						parse_state = COMMENT_FUNCTION;
						sc.Forward();
					}
				}
				// V--- Falling through!
				// Falls through.
				case COMMENT_FUNCTION : {
					if (sc.ch != '%') {
						to_late_to_comment = true;
					} else if (!to_late_to_comment && sc.ch == '%') {
						// Switch to comment level 3 (Module)
						sc.ChangeState(SCE_ERLANG_COMMENT_MODULE);
						old_style = SCE_ERLANG_COMMENT_MODULE;
						parse_state = COMMENT_MODULE;
						sc.Forward();
					}
				}
				// V--- Falling through!
				// Falls through.
				case COMMENT_MODULE : {
					if (parse_state != COMMENT) {
						// Search for comment documentation
						if (sc.chNext == '@') {
							old_parse_state = parse_state;
							parse_state = ('{' == sc.ch)
											? COMMENT_DOC_MACRO
											: COMMENT_DOC;
							sc.ForwardSetState(sc.state);
						}
					}

					// All comments types fall here.
					if (sc.atLineEnd) {
						to_late_to_comment = false;
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

				case COMMENT_DOC :
				// V--- Falling through!
				case COMMENT_DOC_MACRO : {

					if (!isalnum(sc.ch)) {
						// Try to match documentation comment
						sc.GetCurrent(cur, sizeof(cur));

						if (parse_state == COMMENT_DOC_MACRO
							&& erlangDocMacro.InList(cur)) {
								sc.ChangeState(SCE_ERLANG_COMMENT_DOC_MACRO);
								while (sc.ch != '}' && !sc.atLineEnd)
									sc.Forward();
						} else if (erlangDoc.InList(cur)) {
							sc.ChangeState(SCE_ERLANG_COMMENT_DOC);
						} else {
							sc.ChangeState(old_style);
						}

						// Switch back to old state
						sc.SetState(old_style);
						parse_state = old_parse_state;
					}

					if (sc.atLineEnd) {
						to_late_to_comment = false;
						sc.ChangeState(old_style);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* -------------------------------------------------------------- */
			/* Atoms ---------------------------------------------------------*/
				case ATOM_UNQUOTED : {
					if ('@' == sc.ch){
						parse_state = NODE_NAME_UNQUOTED;
					} else if (sc.ch == ':') {
						// Searching for module name
						if (sc.chNext == ' ') {
							// error
							sc.ChangeState(SCE_ERLANG_UNKNOWN);
							parse_state = STATE_NULL;
						} else {
							sc.Forward();
							if (isalnum(sc.ch))  {
								sc.GetCurrent(cur, sizeof(cur));
								sc.ChangeState(SCE_ERLANG_MODULES);
								sc.SetState(SCE_ERLANG_MODULES);
							}
						}
					} else if (!IsAWordChar(sc.ch)) {

						sc.GetCurrent(cur, sizeof(cur));
						if (reservedWords.InList(cur)) {
							style = SCE_ERLANG_KEYWORD;
						} else if (erlangBIFs.InList(cur)
									&& strcmp(cur,"erlang:")){
							style = SCE_ERLANG_BIFS;
						} else if (sc.ch == '(' || '/' == sc.ch){
							style = SCE_ERLANG_FUNCTION_NAME;
						} else {
							style = SCE_ERLANG_ATOM;
						}

						sc.ChangeState(style);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}

				} break;

				case ATOM_QUOTED : {
					if ( '@' == sc.ch ){
						parse_state = NODE_NAME_QUOTED;
					} else if ('\'' == sc.ch && '\\' != sc.chPrev) {
						sc.ChangeState(SCE_ERLANG_ATOM);
						sc.ForwardSetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* -------------------------------------------------------------- */
			/* Node names ----------------------------------------------------*/
				case NODE_NAME_UNQUOTED : {
					if ('@' == sc.ch) {
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					} else if (!IsAWordChar(sc.ch)) {
						sc.ChangeState(SCE_ERLANG_NODE_NAME);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

				case NODE_NAME_QUOTED : {
					if ('@' == sc.ch) {
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					} else if ('\'' == sc.ch && '\\' != sc.chPrev) {
						sc.ChangeState(SCE_ERLANG_NODE_NAME_QUOTED);
						sc.ForwardSetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* -------------------------------------------------------------- */
			/* Records -------------------------------------------------------*/
				case RECORD_START : {
					if ('\'' == sc.ch) {
						parse_state = RECORD_QUOTED;
					} else if (isalpha(sc.ch) && islower(sc.ch)) {
						parse_state = RECORD_UNQUOTED;
					} else { // error
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

				case RECORD_UNQUOTED : {
					if (!IsAWordChar(sc.ch)) {
						sc.ChangeState(SCE_ERLANG_RECORD);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

				case RECORD_QUOTED : {
					if ('\'' == sc.ch && '\\' != sc.chPrev) {
						sc.ChangeState(SCE_ERLANG_RECORD_QUOTED);
						sc.ForwardSetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* -------------------------------------------------------------- */
			/* Macros --------------------------------------------------------*/
				case MACRO_START : {
					if ('\'' == sc.ch) {
						parse_state = MACRO_QUOTED;
					} else if (isalpha(sc.ch)) {
						parse_state = MACRO_UNQUOTED;
					} else { // error
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

				case MACRO_UNQUOTED : {
					if (!IsAWordChar(sc.ch)) {
						sc.ChangeState(SCE_ERLANG_MACRO);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

				case MACRO_QUOTED : {
					if ('\'' == sc.ch && '\\' != sc.chPrev) {
						sc.ChangeState(SCE_ERLANG_MACRO_QUOTED);
						sc.ForwardSetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* -------------------------------------------------------------- */
			/* Numerics ------------------------------------------------------*/
			/* Simple integer */
				case NUMERAL_START : {
					if (isdigit(sc.ch)) {
						radix_digits *= 10;
						radix_digits += sc.ch - '0'; // Assuming ASCII here!
					} else if ('#' == sc.ch) {
						if (2 > radix_digits || 36 < radix_digits) {
							sc.SetState(SCE_ERLANG_DEFAULT);
							parse_state = STATE_NULL;
						} else {
							parse_state = NUMERAL_BASE_VALUE;
						}
					} else if ('.' == sc.ch && isdigit(sc.chNext)) {
						radix_digits = 0;
						parse_state = NUMERAL_FLOAT;
					} else if ('e' == sc.ch || 'E' == sc.ch) {
						exponent_digits = 0;
						parse_state = NUMERAL_EXPONENT;
					} else {
						radix_digits = 0;
						sc.ChangeState(SCE_ERLANG_NUMBER);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* Integer in other base than 10 (x#yyy) */
				case NUMERAL_BASE_VALUE : {
					if (!is_radix(radix_digits,sc.ch)) {
						radix_digits = 0;

						if (!isalnum(sc.ch))
							sc.ChangeState(SCE_ERLANG_NUMBER);

						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* Float (x.yyy) */
				case NUMERAL_FLOAT : {
					if ('e' == sc.ch || 'E' == sc.ch) {
						exponent_digits = 0;
						parse_state = NUMERAL_EXPONENT;
					} else if (!isdigit(sc.ch)) {
						sc.ChangeState(SCE_ERLANG_NUMBER);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* Exponent, either integer or float (xEyy, x.yyEzzz) */
				case NUMERAL_EXPONENT : {
					if (('-' == sc.ch || '+' == sc.ch)
							&& (isdigit(sc.chNext))) {
						sc.Forward();
					} else if (!isdigit(sc.ch)) {
						if (0 < exponent_digits)
							sc.ChangeState(SCE_ERLANG_NUMBER);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					} else {
						++exponent_digits;
					}
				} break;

			/* -------------------------------------------------------------- */
			/* Preprocessor --------------------------------------------------*/
				case PREPROCESSOR : {
					if (!IsAWordChar(sc.ch)) {

						sc.GetCurrent(cur, sizeof(cur));
						if (erlangPreproc.InList(cur)) {
							style = SCE_ERLANG_PREPROC;
						} else if (erlangModulesAtt.InList(cur)) {
							style = SCE_ERLANG_MODULES_ATT;
						}

						sc.ChangeState(style);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			}

		} /* End of : STATE_NULL != parse_state */
		else
		{
			switch (sc.state) {
				case SCE_ERLANG_VARIABLE : {
					if (!IsAWordChar(sc.ch))
						sc.SetState(SCE_ERLANG_DEFAULT);
				} break;
				case SCE_ERLANG_STRING : {
					 if (sc.ch == '\"' && sc.chPrev != '\\')
						sc.ForwardSetState(SCE_ERLANG_DEFAULT);
				} break;
				case SCE_ERLANG_COMMENT : {
					 if (sc.atLineEnd)
						sc.SetState(SCE_ERLANG_DEFAULT);
				} break;
				case SCE_ERLANG_CHARACTER : {
					if (sc.chPrev == '\\') {
						sc.ForwardSetState(SCE_ERLANG_DEFAULT);
					} else if (sc.ch != '\\') {
						sc.ForwardSetState(SCE_ERLANG_DEFAULT);
					}
				} break;
				case SCE_ERLANG_OPERATOR : {
					if (sc.chPrev == '.') {
						if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\'
							|| sc.ch == '^') {
							sc.ForwardSetState(SCE_ERLANG_DEFAULT);
						} else if (sc.ch == '\'') {
							sc.ForwardSetState(SCE_ERLANG_DEFAULT);
						} else {
							sc.SetState(SCE_ERLANG_DEFAULT);
						}
					} else {
						sc.SetState(SCE_ERLANG_DEFAULT);
					}
				} break;
			}
		}

		if (sc.state == SCE_ERLANG_DEFAULT) {
			bool no_new_state = false;

			switch (sc.ch) {
				case '\"' : sc.SetState(SCE_ERLANG_STRING); break;
				case '$' : sc.SetState(SCE_ERLANG_CHARACTER); break;
				case '%' : {
					parse_state = COMMENT;
					sc.SetState(SCE_ERLANG_COMMENT);
				} break;
				case '#' : {
					parse_state = RECORD_START;
					sc.SetState(SCE_ERLANG_UNKNOWN);
				} break;
				case '?' : {
					parse_state = MACRO_START;
					sc.SetState(SCE_ERLANG_UNKNOWN);
				} break;
				case '\'' : {
					parse_state = ATOM_QUOTED;
					sc.SetState(SCE_ERLANG_UNKNOWN);
				} break;
				case '+' :
				case '-' : {
					if (IsADigit(sc.chNext)) {
						parse_state = NUMERAL_START;
						radix_digits = 0;
						sc.SetState(SCE_ERLANG_UNKNOWN);
					} else if (sc.ch != '+') {
						parse_state = PREPROCESSOR;
						sc.SetState(SCE_ERLANG_UNKNOWN);
					}
				} break;
				default : no_new_state = true;
			}

			if (no_new_state) {
				if (isdigit(sc.ch)) {
					parse_state = NUMERAL_START;
					radix_digits = sc.ch - '0';
					sc.SetState(SCE_ERLANG_UNKNOWN);
				} else if (isupper(sc.ch) || '_' == sc.ch) {
					sc.SetState(SCE_ERLANG_VARIABLE);
				} else if (isalpha(sc.ch)) {
					parse_state = ATOM_UNQUOTED;
					sc.SetState(SCE_ERLANG_UNKNOWN);
				} else if (isoperator(static_cast<char>(sc.ch))
							|| sc.ch == '\\') {
					sc.SetState(SCE_ERLANG_OPERATOR);
				}
			}
		}

	}
	sc.Complete();
}