diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2021-01-31 20:39:36 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2021-01-31 20:39:36 -0500 |
commit | 442e0b92a09689cd75e2d20608572a279bef5390 (patch) | |
tree | 67d5e2a79ffcb1413ed10b49f70a185fef55ef68 /syntax.c | |
parent | 68b3e3928e1bd05ebbb56810ae8b7a68ff5f12b0 (diff) |
more syntax highlighting
Diffstat (limited to 'syntax.c')
-rw-r--r-- | syntax.c | 71 |
1 files changed, 64 insertions, 7 deletions
@@ -52,6 +52,8 @@ static void syntax_highlight_c(SyntaxStateC *state, char32_t *line, u32 line_len // are there 1/2 characters left in the line? bool has_1_char = i + 1 < line_len; + bool dealt_with = false; + switch (line[i]) { case '#': if (!in_single_line_comment && !in_multi_line_comment) @@ -87,17 +89,72 @@ static void syntax_highlight_c(SyntaxStateC *state, char32_t *line, u32 line_len if (in_preprocessor && in_string) in_string = false; break; + default: { + // split keywords by starting letter to speed this up + static char const *const all_keywords[][10] = { + ['a'] = {"auto"}, + ['b'] = {"break", "bool"}, + ['c'] = {"case", "char", "const", "continue", "char8_t", "char16_t", "char32_t"}, + ['d'] = {"default", "do", "double"}, + ['e'] = {"else", "enum", "extern"}, + ['f'] = {"float", "for"}, + ['g'] = {"goto"}, + ['i'] = {"if", "inline", "int", "int8_t", "int16_t", "int32_t", "int64_t"}, + ['l'] = {"long"}, + ['r'] = {"register", "restrict", "return"}, + ['s'] = {"short", "signed", "sizeof", "static", "struct", "switch"}, + ['t'] = {"typedef"}, + ['u'] = {"union", "unsigned", "uint8_t", "uint16_t", "uint32_t", "uint64_t"}, + ['v'] = {"void", "volatile"}, + ['w'] = {"while", "wchar_t", "wint_t"}, + ['_'] = {"_Alignas", "_Alignof", "_Atomic", "_Bool", "_Complex", "_Generic", + "_Imaginary", "_Noreturn", "_Static_assert", "_Thread_local"}, + }; + + char const *const *keywords = line[i] < arr_count(all_keywords) ? all_keywords[line[i]] : NULL; + if (char_types && keywords && !in_single_line_comment && !in_multi_line_comment && !in_string && !in_preprocessor) { + // keywords don't matter for advancing the state + for (size_t k = 0; keywords[k]; ++k) { + bool matches = true; + char const *keyword = keywords[k]; + size_t keyword_len = strlen(keyword); + if (i + keyword_len <= line_len) { + // make sure we don't catch "print" as containing the keyword "int" + bool separated = (i == 0 || !is32_ident(line[i-1])) && (i + keyword_len == line_len || !is32_ident(line[i + keyword_len])); + if (separated) { + char32_t *p = &line[i]; + // check if `p` starts with `keyword` + for (char const *q = keyword; *q; ++p, ++q) { + if (*p != (char32_t)*q) { + matches = false; + break; + } + } + if (matches) { + for (size_t c = 0; keyword[c]; ++c) { + char_types[i++] = SYNTAX_KEYWORD; + } + --i; // we'll increment i from the for loop + dealt_with = true; + break; + } + } + } + } + + } + } break; } if (line[i] != '\\') backslashes = 0; - if (in_single_line_comment || in_multi_line_comment_now) - type = SYNTAX_COMMENT; - else if (in_string_now) - type = SYNTAX_STRING; - else if (in_preprocessor) - type = SYNTAX_PREPROCESSOR; + if (char_types && !dealt_with) { + if (in_single_line_comment || in_multi_line_comment_now) + type = SYNTAX_COMMENT; + else if (in_string_now) + type = SYNTAX_STRING; + else if (in_preprocessor) + type = SYNTAX_PREPROCESSOR; - if (char_types) { char_types[i] = type; } } |