3 #include <ctype.h> // IWYU pragma: export
4 #include <stdio.h> // IWYU pragma: export
5 #include <stdlib.h> // IWYU pragma: export
6 #include <string.h> // IWYU pragma: export
8 #include "../stdlib/files.h" // IWYU pragma: export
9 #include "../stdlib/print.h" // IWYU pragma: export
10 #include "../stdlib/stacktrace.h" // IWYU pragma: export
11 #include "../stdlib/stdlib.h" // IWYU pragma: export
12 #include "context.h" // IWYU pragma: export
13 #include "utils.h" // IWYU pragma: export
16 // Print a parse error and exit (or use the on_err longjmp)
18 #define parser_err(ctx, start, end, ...) \
20 if (USE_COLOR) fputs("\x1b[31;1;7m", stderr); \
21 fprint_inline(stderr, (ctx)->file->relative_filename, ":", get_line_number((ctx)->file, (start)), ".", \
22 get_line_column((ctx)->file, (start)), ": ", __VA_ARGS__); \
23 if (USE_COLOR) fputs(" \x1b[m", stderr); \
24 fputs("\n\n", stderr); \
25 highlight_error((ctx)->file, (start), (end), "\x1b[31;1;7m", 2, USE_COLOR); \
26 fputs("\n", stderr); \
27 if (getenv("TOMO_STACKTRACE")) print_stacktrace(stderr, 1); \
28 if ((ctx)->on_err) longjmp(*((ctx)->on_err), 1); \
34 // Expect a string (potentially after whitespace) and emit a parser error if it's not there
36 #define expect_str(ctx, start, pos, target, ...) \
39 if (!match(pos, target)) { \
40 if (USE_COLOR) fputs("\x1b[31;1;7m", stderr); \
41 parser_err(ctx, start, *pos, __VA_ARGS__); \
43 char _lastchar = target[strlen(target) - 1]; \
44 if (isalpha(_lastchar) || isdigit(_lastchar) || _lastchar == '_') { \
45 if (is_xid_continue_next(*pos)) { \
46 if (USE_COLOR) fputs("\x1b[31;1;7m", stderr); \
47 parser_err(ctx, start, *pos, __VA_ARGS__); \
53 // Helper for matching closing parens with good error messages
55 #define expect_closing(ctx, pos, close_str, ...) \
57 const char *_start = *pos; \
59 if (!match(pos, (close_str))) { \
60 const char *_eol = strchr(*pos, '\n'); \
61 const char *_next = strstr(*pos, (close_str)); \
62 const char *_end = _eol < _next ? _eol : _next; \
63 if (USE_COLOR) fputs("\x1b[31;1;7m", stderr); \
64 parser_err(ctx, _start, _end, __VA_ARGS__); \
68 #define expect(ctx, start, pos, parser, ...) \
70 const char **_pos = pos; \
72 __typeof(parser(ctx, *_pos)) _result = parser(ctx, *_pos); \
74 if (USE_COLOR) fputs("\x1b[31;1;7m", stderr); \
75 parser_err(ctx, start, *_pos, __VA_ARGS__); \
77 *_pos = _result->end; \
81 #define optional(ctx, pos, parser) \
83 const char **_pos = pos; \
85 __typeof(parser(ctx, *_pos)) _result = parser(ctx, *_pos); \
86 if (_result) *_pos = _result->end; \