diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-07-21 08:33:44 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-08-15 10:04:27 +0900 |
| commit | 16bbc2e0d72f94f8061ba294d1776edfe5bf8a55 (patch) | |
| tree | dc5c02baa1fa3e6099414ac24b796a03b3e077a0 | |
| parent | 274e212c16bb354532e4a955e594a159cef61665 (diff) | |
| download | ducc-16bbc2e0d72f94f8061ba294d1776edfe5bf8a55.tar.gz ducc-16bbc2e0d72f94f8061ba294d1776edfe5bf8a55.tar.zst ducc-16bbc2e0d72f94f8061ba294d1776edfe5bf8a55.zip | |
feat: improve parse error messages
| -rw-r--r-- | main.c | 128 | ||||
| -rw-r--r-- | tests/059.sh | 17 |
2 files changed, 142 insertions, 3 deletions
@@ -556,6 +556,128 @@ struct Token { }; typedef struct Token Token; +const char* token_kind_stringify(TokenKind k) { + if (k == TokenKind_eof) + return "<eof>"; + else if (k == TokenKind_and) + return "&"; + else if (k == TokenKind_andand) + return "&&"; + else if (k == TokenKind_arrow) + return "->"; + else if (k == TokenKind_assign) + return "="; + else if (k == TokenKind_assign_add) + return "+="; + else if (k == TokenKind_assign_sub) + return "-="; + else if (k == TokenKind_brace_l) + return "{"; + else if (k == TokenKind_brace_r) + return "}"; + else if (k == TokenKind_bracket_l) + return "["; + else if (k == TokenKind_bracket_r) + return "]"; + else if (k == TokenKind_comma) + return ","; + else if (k == TokenKind_dot) + return "."; + else if (k == TokenKind_ellipsis) + return "..."; + else if (k == TokenKind_eq) + return "=="; + else if (k == TokenKind_ge) + return ">="; + else if (k == TokenKind_gt) + return ">"; + else if (k == TokenKind_ident) + return "<identifier>"; + else if (k == TokenKind_keyword_break) + return "break"; + else if (k == TokenKind_keyword_char) + return "char"; + else if (k == TokenKind_keyword_const) + return "const"; + else if (k == TokenKind_keyword_continue) + return "continue"; + else if (k == TokenKind_keyword_do) + return "do"; + else if (k == TokenKind_keyword_else) + return "else"; + else if (k == TokenKind_keyword_enum) + return "enum"; + else if (k == TokenKind_keyword_extern) + return "extern"; + else if (k == TokenKind_keyword_for) + return "for"; + else if (k == TokenKind_keyword_if) + return "if"; + else if (k == TokenKind_keyword_int) + return "int"; + else if (k == TokenKind_keyword_long) + return "long"; + else if (k == TokenKind_keyword_return) + return "return"; + else if (k == TokenKind_keyword_sizeof) + return "sizeof"; + else if (k == TokenKind_keyword_struct) + return "struct"; + else if (k == TokenKind_keyword_typeof) + return "typeof"; + else if (k == TokenKind_keyword_void) + return "void"; + else if (k == TokenKind_keyword_while) + return "while"; + else if (k == TokenKind_le) + return "le"; + else if (k == TokenKind_lt) + return "lt"; + else if (k == TokenKind_literal_int) + return "<integer>"; + else if (k == TokenKind_literal_str) + return "<string>"; + else if (k == TokenKind_minus) + return "-"; + else if (k == TokenKind_minusminus) + return "--"; + else if (k == TokenKind_ne) + return "!="; + else if (k == TokenKind_not) + return "!"; + else if (k == TokenKind_oror) + return "||"; + else if (k == TokenKind_paren_l) + return "("; + else if (k == TokenKind_paren_r) + return ")"; + else if (k == TokenKind_percent) + return "%"; + else if (k == TokenKind_plus) + return "+"; + else if (k == TokenKind_plusplus) + return "++"; + else if (k == TokenKind_semicolon) + return ";"; + else if (k == TokenKind_slash) + return "/"; + else if (k == TokenKind_star) + return "*"; + else + unreachable(); +} + +const char* token_stringify(Token* t) { + TokenKind k = t->kind; + if (k == TokenKind_ident || k == TokenKind_literal_int || k == TokenKind_literal_str) { + char* buf = calloc(t->raw.len + 1, sizeof(char)); + sprintf(buf, "%.*s (%s)", t->raw.len, t->raw.data, token_kind_stringify(k)); + return buf; + } else { + return token_kind_stringify(k); + } +} + struct Lexer { PpToken* src; int pos; @@ -1164,7 +1286,7 @@ Token* expect(Parser* p, int expected) { } char* buf = calloc(1024, sizeof(char)); - sprintf(buf, "expected %d, but got %d", expected, t->kind); + sprintf(buf, "expected '%s', but got '%s'", token_kind_stringify(expected), token_stringify(t)); fatal_error(buf); } @@ -1317,7 +1439,7 @@ AstNode* parse_primary_expr(Parser* p) { return e; } else { buf = calloc(1024, sizeof(char)); - sprintf(buf, "expected primary expression, but got %d", t->kind); + sprintf(buf, "expected primary expression, but got '%s'", token_stringify(t)); fatal_error(buf); } } @@ -1392,7 +1514,7 @@ Type* parse_type(Parser* p) { } if (!is_type_token(p, t)) { buf = calloc(1024, sizeof(char)); - sprintf(buf, "parse_type: unknown type, %d", t->kind); + sprintf(buf, "parse_type: expected type, but got '%s'", token_stringify(t)); fatal_error(buf); } Type* ty; diff --git a/tests/059.sh b/tests/059.sh new file mode 100644 index 0000000..18e9bd7 --- /dev/null +++ b/tests/059.sh @@ -0,0 +1,17 @@ +set -e + +cat <<'EOF' > expected +expected '{', but got '}' +EOF + +bash ../../test_compile_error.sh <<'EOF' +int main() } +EOF + +cat <<'EOF' > expected +expected '{', but got '123 (<integer>)' +EOF + +bash ../../test_compile_error.sh <<'EOF' +int main() 123 +EOF |
