summaryrefslogtreecommitdiff
path: root/syntax.c
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-07-22 14:54:07 -0400
committerpommicket <pommicket@gmail.com>2022-07-22 14:54:07 -0400
commit35b1b0129e8791a9412173acf3756606d0cc397d (patch)
tree6e631f6382cabf4ad2522bf4386828aaabae3347 /syntax.c
parent47a65f608f485af32d2df12be489146ad67839e1 (diff)
go syntax highlighting
also :goto-line now clamps numbers < 1 and > nlines instead of rejecting them
Diffstat (limited to 'syntax.c')
-rw-r--r--syntax.c147
1 files changed, 146 insertions, 1 deletions
diff --git a/syntax.c b/syntax.c
index 99aae45..e26560d 100644
--- a/syntax.c
+++ b/syntax.c
@@ -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;
}
}