diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bootstrap/errors.c | 33 | ||||
-rw-r--r-- | src/bootstrap/lexer.c | 52 | ||||
-rwxr-xr-x | src/bootstrap/main.c | 55 |
3 files changed, 116 insertions, 24 deletions
diff --git a/src/bootstrap/errors.c b/src/bootstrap/errors.c new file mode 100644 index 0000000..fcb629a --- /dev/null +++ b/src/bootstrap/errors.c | |||
@@ -0,0 +1,33 @@ | |||
1 | typedef enum ErrorType { | ||
2 | ERR_TYPE_LEXER, | ||
3 | ERR_TYPE_PARSER, | ||
4 | ERR_TYPE_RUNTIME, | ||
5 | } ErrorType; | ||
6 | |||
7 | typedef enum ErrorValue { | ||
8 | ERR_UNKNOWN = 0, | ||
9 | ERR_UNMATCHED_STRING, | ||
10 | } ErrorValue; | ||
11 | |||
12 | typedef struct Error { | ||
13 | ErrorType type; | ||
14 | ErrorValue value; | ||
15 | size_t line; | ||
16 | size_t col; | ||
17 | } Error; | ||
18 | |||
19 | static const char* error_msgs[] = { | ||
20 | [ERR_UNKNOWN] = "error: something unexpected happened", | ||
21 | [ERR_UNMATCHED_STRING] = "error: unmatched string delimiter", | ||
22 | }; | ||
23 | |||
24 | #define ERR_MAX_NUMBER 16 | ||
25 | static Error errors[ERR_MAX_NUMBER]; | ||
26 | static size_t errors_n = 0; | ||
27 | |||
28 | void | ||
29 | error_push(Error error) { | ||
30 | if (errors_n < ERR_MAX_NUMBER) { | ||
31 | errors[errors_n++] = error; | ||
32 | } | ||
33 | } | ||
diff --git a/src/bootstrap/lexer.c b/src/bootstrap/lexer.c index 1add4dc..49431d0 100644 --- a/src/bootstrap/lexer.c +++ b/src/bootstrap/lexer.c | |||
@@ -134,6 +134,28 @@ skip_whitespace(Scanner *scanner) { | |||
134 | } | 134 | } |
135 | } | 135 | } |
136 | 136 | ||
137 | bool | ||
138 | is_delimiter(char c) { | ||
139 | switch (c) { | ||
140 | case EOF: | ||
141 | case '\0': | ||
142 | case ';': | ||
143 | case '"': | ||
144 | case '\'': | ||
145 | case '(': | ||
146 | case ')': | ||
147 | case ' ': | ||
148 | case '\f': | ||
149 | case '\n': | ||
150 | case '\r': | ||
151 | case '\t': | ||
152 | case '\v': { | ||
153 | return true; | ||
154 | } break; | ||
155 | } | ||
156 | return false; | ||
157 | } | ||
158 | |||
137 | TokenType | 159 | TokenType |
138 | find_primitive_type(StringView value) { | 160 | find_primitive_type(StringView value) { |
139 | bool is_fixnum = true; | 161 | bool is_fixnum = true; |
@@ -159,28 +181,6 @@ find_primitive_type(StringView value) { | |||
159 | return TOKEN_SYMBOL; | 181 | return TOKEN_SYMBOL; |
160 | } | 182 | } |
161 | 183 | ||
162 | bool | ||
163 | is_delimiter(char c) { | ||
164 | switch (c) { | ||
165 | case EOF: | ||
166 | case '\0': | ||
167 | case ';': | ||
168 | case '"': | ||
169 | case '\'': | ||
170 | case '(': | ||
171 | case ')': | ||
172 | case ' ': | ||
173 | case '\f': | ||
174 | case '\n': | ||
175 | case '\r': | ||
176 | case '\t': | ||
177 | case '\v': { | ||
178 | return true; | ||
179 | } break; | ||
180 | } | ||
181 | return false; | ||
182 | } | ||
183 | |||
184 | Tokens | 184 | Tokens |
185 | tokenize(const StringView *sv) { | 185 | tokenize(const StringView *sv) { |
186 | Tokens tokens = (Tokens){0}; | 186 | Tokens tokens = (Tokens){0}; |
@@ -214,7 +214,13 @@ tokenize(const StringView *sv) { | |||
214 | n++; | 214 | n++; |
215 | } | 215 | } |
216 | if (!found) { | 216 | if (!found) { |
217 | // TODO: Report error: couldn't find the closing quotes. | 217 | error_push((Error){ |
218 | .type = ERR_TYPE_LEXER, | ||
219 | .value = ERR_UNMATCHED_STRING, | ||
220 | .line = line, | ||
221 | .col = col, | ||
222 | }); | ||
223 | return tokens; | ||
218 | } | 224 | } |
219 | Token token = (Token){ | 225 | Token token = (Token){ |
220 | .value = (StringView){ | 226 | .value = (StringView){ |
diff --git a/src/bootstrap/main.c b/src/bootstrap/main.c index 113ee48..dadc887 100755 --- a/src/bootstrap/main.c +++ b/src/bootstrap/main.c | |||
@@ -5,11 +5,18 @@ | |||
5 | 5 | ||
6 | #include "string_view.c" | 6 | #include "string_view.c" |
7 | #include "read_line.c" | 7 | #include "read_line.c" |
8 | #include "errors.c" | ||
8 | #include "lexer.c" | 9 | #include "lexer.c" |
9 | 10 | ||
10 | void | 11 | void |
11 | process_source(const StringView *source) { | 12 | process_source(const StringView *source) { |
12 | Tokens tokens = tokenize(source); | 13 | Tokens tokens = tokenize(source); |
14 | if (errors_n != 0) { | ||
15 | if (tokens.buf != NULL) { | ||
16 | free(tokens.buf); | ||
17 | } | ||
18 | return; | ||
19 | } | ||
13 | 20 | ||
14 | // Print tokens. | 21 | // Print tokens. |
15 | for (size_t i = 0; i < tokens.size; i++) { | 22 | for (size_t i = 0; i < tokens.size; i++) { |
@@ -17,7 +24,9 @@ process_source(const StringView *source) { | |||
17 | print_token(tok); | 24 | print_token(tok); |
18 | } | 25 | } |
19 | 26 | ||
20 | free(tokens.buf); | 27 | if (tokens.buf != NULL) { |
28 | free(tokens.buf); | ||
29 | } | ||
21 | } | 30 | } |
22 | 31 | ||
23 | #define REPL_PROMPT "bdl> " | 32 | #define REPL_PROMPT "bdl> " |
@@ -32,6 +41,24 @@ run_repl(void) { | |||
32 | return; | 41 | return; |
33 | } | 42 | } |
34 | process_source(&sv); | 43 | process_source(&sv); |
44 | |||
45 | // Check if there were any errors. | ||
46 | if (errors_n != 0) { | ||
47 | for (size_t i = 0; i < errors_n; i++) { | ||
48 | Error err = errors[i]; | ||
49 | for (size_t j = 0; j < err.col + sizeof(REPL_PROMPT) - 2; j++) { | ||
50 | putchar(' '); | ||
51 | } | ||
52 | printf("|\n"); | ||
53 | for (size_t j = 0; j < err.col + sizeof(REPL_PROMPT) - 2; j++) { | ||
54 | putchar(' '); | ||
55 | } | ||
56 | printf("%s\n", error_msgs[err.value]); | ||
57 | } | ||
58 | errors_n = 0; | ||
59 | continue; | ||
60 | } | ||
61 | |||
35 | if (sv.n != 0) { | 62 | if (sv.n != 0) { |
36 | printf("\n"); | 63 | printf("\n"); |
37 | } | 64 | } |
@@ -62,6 +89,19 @@ run_file(char *file_name) { | |||
62 | 89 | ||
63 | process_source(&sv); | 90 | process_source(&sv); |
64 | 91 | ||
92 | // Check if there were any errors. | ||
93 | if (errors_n != 0) { | ||
94 | for (size_t i = 0; i < errors_n; i++) { | ||
95 | Error err = errors[i]; | ||
96 | printf("%s", file_name); | ||
97 | if (err.line != 0) { | ||
98 | printf(":%ld:%ld", err.line, err.col); | ||
99 | } | ||
100 | printf("%s\n", error_msgs[err.value]); | ||
101 | } | ||
102 | errors_n = 0; | ||
103 | } | ||
104 | |||
65 | free(source); | 105 | free(source); |
66 | fclose(file); | 106 | fclose(file); |
67 | } | 107 | } |
@@ -91,6 +131,19 @@ run_stdin(void) { | |||
91 | 131 | ||
92 | process_source(&sv); | 132 | process_source(&sv); |
93 | 133 | ||
134 | // Check if there were any errors. | ||
135 | if (errors_n != 0) { | ||
136 | for (size_t i = 0; i < errors_n; i++) { | ||
137 | Error err = errors[i]; | ||
138 | printf("stdin"); | ||
139 | if (err.line != 0) { | ||
140 | printf(":%ld:%ld: ", err.line, err.col); | ||
141 | } | ||
142 | printf("%s\n", error_msgs[err.value]); | ||
143 | } | ||
144 | errors_n = 0; | ||
145 | } | ||
146 | |||
94 | free(source); | 147 | free(source); |
95 | } | 148 | } |
96 | 149 | ||