diff options
Diffstat (limited to 'syntax.c')
-rw-r--r-- | syntax.c | 147 |
1 files changed, 146 insertions, 1 deletions
@@ -1169,7 +1169,7 @@ static void syntax_highlight_javascript(SyntaxState *state, char32_t const *line static void syntax_highlight_java(SyntaxState *state_ptr, char32_t const *line, u32 line_len, SyntaxCharType *char_types) { SyntaxState state = *state_ptr; bool in_string = false; - bool in_multiline_comment = (state & SYNTAX_STATE_CPP_MULTI_LINE_COMMENT) != 0; + bool in_multiline_comment = (state & SYNTAX_STATE_JAVA_MULTILINE_COMMENT) != 0; bool in_char = false; bool in_number = false; @@ -1291,6 +1291,148 @@ static void syntax_highlight_java(SyntaxState *state_ptr, char32_t const *line, ); } + +static void syntax_highlight_go(SyntaxState *state_ptr, char32_t const *line, u32 line_len, SyntaxCharType *char_types) { + SyntaxState state = *state_ptr; + bool string_is_raw = (state & SYNTAX_STATE_GO_RAW_STRING) != 0; + bool in_string = string_is_raw; + bool in_multiline_comment = (state & SYNTAX_STATE_GO_MULTILINE_COMMENT) != 0; + bool in_char = false; + bool in_number = false; + + int backslashes = 0; + for (u32 i = 0; i < line_len; ++i) { + + // are there 1/2 characters left in the line? + bool has_1_char = i + 1 < line_len; + + bool dealt_with = false; + + char32_t c = line[i]; + + switch (c) { + case '\\': + ++backslashes; + break; + case '/': + if (!in_multiline_comment && !in_string && !in_char && has_1_char) { + if (line[i + 1] == '/') { + if (char_types) memset(&char_types[i], SYNTAX_COMMENT, line_len - i); + i = line_len - 1; + dealt_with = true; + } else if (line[i + 1] == '*') { + in_multiline_comment = true; // /* + } + } else if (in_multiline_comment) { + if (i > 0 && line[i - 1] == '*') { + // */ + in_multiline_comment = false; + if (char_types) { + dealt_with = true; + char_types[i] = SYNTAX_COMMENT; + } + } + } + break; + case '"': + if (in_string && !string_is_raw && backslashes % 2 == 0) { + in_string = false; + if (char_types) { + dealt_with = true; + char_types[i] = SYNTAX_STRING; + } + } else if (!in_multiline_comment && !in_char) { + in_string = true; + string_is_raw = false; + } + break; + case '`': + if (in_string && string_is_raw) { + // end of raw string + in_string = false; + string_is_raw = false; + if (char_types) char_types[i] = SYNTAX_STRING; + dealt_with = true; + } else if (!in_string && !in_multiline_comment && !in_char) { + // start of raw string + in_string = true; + string_is_raw = true; + } + break; + case '\'': + if (in_char && backslashes % 2 == 0) { + in_char = false; + if (char_types) { + dealt_with = true; + char_types[i] = SYNTAX_CHARACTER; + } + } else if (!in_multiline_comment && !in_string) { + in_char = true; + } + break; + case ANY_DIGIT: + // a number! + if (char_types && !in_multiline_comment && !in_string && !in_number && !in_char) { + in_number = true; + if (i) { + if (line[i - 1] == '.') { + // support .6, for example + char_types[i - 1] = SYNTAX_CONSTANT; + } else if (is32_ident(line[i - 1])) { + // actually, this isn't a number. it's something like a*6* or u3*2*. + in_number = false; + } + } + } + break; + default: { + if ((i && is32_ident(line[i - 1])) || !is32_ident(c)) + break; // can't be a keyword on its own. + + // keywords don't matter for advancing the state + if (char_types && !in_multiline_comment && !in_number && !in_string && !in_char) { + u32 keyword_len = syntax_keyword_len(LANG_GO, line, i, line_len); + Keyword const *keyword = syntax_keyword_lookup(syntax_all_keywords_go, arr_count(syntax_all_keywords_go), + &line[i], keyword_len); + + + if (keyword) { + SyntaxCharType type = keyword->type; + for (size_t j = 0; j < keyword_len; ++j) { + char_types[i++] = type; + } + --i; // we'll increment i from the for loop + dealt_with = true; + break; + } + } + } break; + } + if (c != '\\') backslashes = 0; + if (in_number && !syntax_number_continues(line, line_len, i)) { + in_number = false; + } + + if (char_types && !dealt_with) { + SyntaxCharType type = SYNTAX_NORMAL; + if (in_multiline_comment) + type = SYNTAX_COMMENT; + else if (in_string) + type = SYNTAX_STRING; + else if (in_char) + type = SYNTAX_CHARACTER; + else if (in_number) + type = SYNTAX_CONSTANT; + + char_types[i] = type; + } + } + *state_ptr = (SyntaxState)( + (in_multiline_comment * SYNTAX_STATE_GO_MULTILINE_COMMENT) + | ((in_string && string_is_raw) * SYNTAX_STATE_GO_RAW_STRING) + ); +} + // This is the main syntax highlighting function. It will determine which colors to use for each character. // Rather than returning colors, it returns a character type (e.g. comment) which can be converted to a color. // To highlight multiple lines, start out with a zeroed SyntaxState, and pass a pointer to it each time. @@ -1331,6 +1473,9 @@ void syntax_highlight(SyntaxState *state, Language lang, char32_t const *line, u case LANG_JAVA: syntax_highlight_java(state, line, line_len, char_types); break; + case LANG_GO: + syntax_highlight_go(state, line, line_len, char_types); + break; case LANG_COUNT: assert(0); break; } } |