diff options
author | Bad Diode <bd@badd10de.dev> | 2022-02-12 16:21:19 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2022-02-12 16:21:19 +0100 |
commit | c4765a539ee01625dd310a02f0be16ec9a64e2e4 (patch) | |
tree | 47129b3c5677d2a91cfed0c398ec9528aa44af1c /src | |
parent | 5af70ecc0c8eafa7d6d31e16576cb4cf0713f5cc (diff) | |
download | bdl-c4765a539ee01625dd310a02f0be16ec9a64e2e4.tar.gz bdl-c4765a539ee01625dd310a02f0be16ec9a64e2e4.zip |
Make keywords a static array for ease of lex
Diffstat (limited to 'src')
-rw-r--r-- | src/lexer.c | 62 | ||||
-rw-r--r-- | src/main.c | 3 |
2 files changed, 36 insertions, 29 deletions
diff --git a/src/lexer.c b/src/lexer.c index 80ef3ad..5175b1c 100644 --- a/src/lexer.c +++ b/src/lexer.c | |||
@@ -27,6 +27,26 @@ static const char* token_str[] = { | |||
27 | [TOKEN_EOF] = "TOKEN_EOF", | 27 | [TOKEN_EOF] = "TOKEN_EOF", |
28 | }; | 28 | }; |
29 | 29 | ||
30 | typedef struct Keyword { | ||
31 | char *str; | ||
32 | size_t n; | ||
33 | TokenType token; | ||
34 | } Keyword; | ||
35 | |||
36 | #define KEYWORD(STR,TOK) {(STR), sizeof(STR) - 1, (TOK)} | ||
37 | |||
38 | static const Keyword keywords[] = { | ||
39 | KEYWORD("nil", TOKEN_NIL), | ||
40 | KEYWORD("true", TOKEN_TRUE), | ||
41 | KEYWORD("false", TOKEN_FALSE), | ||
42 | KEYWORD("lambda", TOKEN_LAMBDA), | ||
43 | KEYWORD("if", TOKEN_IF), | ||
44 | KEYWORD("def", TOKEN_DEF), | ||
45 | KEYWORD("set!", TOKEN_SET), | ||
46 | KEYWORD("fun", TOKEN_FUN), | ||
47 | KEYWORD("struct", TOKEN_STRUCT), | ||
48 | }; | ||
49 | |||
30 | void | 50 | void |
31 | print_token(Token tok) { | 51 | print_token(Token tok) { |
32 | printf("[%4ld:%-4ld] ", tok.line, tok.col); | 52 | printf("[%4ld:%-4ld] ", tok.line, tok.col); |
@@ -121,11 +141,12 @@ is_delimiter(char c) { | |||
121 | return false; | 141 | return false; |
122 | } | 142 | } |
123 | 143 | ||
124 | #define TOKEN_IS_KEYWORD(VAL, KEYWORD) \ | ||
125 | sv_equal(&(VAL), &(StringView){(KEYWORD), sizeof(KEYWORD) - 1}) | ||
126 | |||
127 | size_t | 144 | size_t |
128 | scan_number_token(Scanner *scanner) { | 145 | scan_number_token(Scanner *scanner) { |
146 | // TODO: This looks like more a parsing problem than lexer, | ||
147 | // consider moving it there. If starts with `-` and there is no | ||
148 | // delimiter after, or if it starts with a number, it is | ||
149 | // TOKEN_NUMBER. | ||
129 | char first = scan_next(scanner); | 150 | char first = scan_next(scanner); |
130 | char second = scan_peek(scanner); | 151 | char second = scan_peek(scanner); |
131 | size_t n = 1; | 152 | size_t n = 1; |
@@ -183,16 +204,12 @@ scan_number_token(Scanner *scanner) { | |||
183 | 204 | ||
184 | TokenType | 205 | TokenType |
185 | find_token_type(const StringView value) { | 206 | find_token_type(const StringView value) { |
186 | if (TOKEN_IS_KEYWORD(value, "nil")) { return TOKEN_NIL; } | 207 | for (size_t i = 0; i < sizeof(keywords) / sizeof(Keyword); i++) { |
187 | if (TOKEN_IS_KEYWORD(value, "true")) { return TOKEN_TRUE; } | 208 | StringView keyword = (StringView){keywords[i].str, keywords[i].n}; |
188 | if (TOKEN_IS_KEYWORD(value, "false")) { return TOKEN_FALSE; } | 209 | if (sv_equal(&value, &keyword)) { |
189 | if (TOKEN_IS_KEYWORD(value, "lambda")) { return TOKEN_LAMBDA; } | 210 | return keywords[i].token; |
190 | if (TOKEN_IS_KEYWORD(value, "if")) { return TOKEN_IF; } | 211 | } |
191 | if (TOKEN_IS_KEYWORD(value, "def")) { return TOKEN_DEF; } | 212 | } |
192 | if (TOKEN_IS_KEYWORD(value, "set!")) { return TOKEN_SET; } | ||
193 | if (TOKEN_IS_KEYWORD(value, "fun")) { return TOKEN_FUN; } | ||
194 | if (TOKEN_IS_KEYWORD(value, "struct")) { return TOKEN_STRUCT; } | ||
195 | |||
196 | return TOKEN_SYMBOL; | 213 | return TOKEN_SYMBOL; |
197 | } | 214 | } |
198 | 215 | ||
@@ -267,19 +284,12 @@ tokenize(const StringView *sv) { | |||
267 | break; | 284 | break; |
268 | } | 285 | } |
269 | size_t n = 1; | 286 | size_t n = 1; |
270 | if (c == '-' && !is_delimiter(scan_peek(&scanner))) { | 287 | bool is_number = c == '-' && !is_delimiter(scan_peek(&scanner)); |
271 | n += scan_number_token(&scanner); | 288 | is_number = is_number || (c >= '0' && c <= '9'); |
272 | token.value = (StringView){ | 289 | if (is_number) { |
273 | .start = &sv->start[offset], | 290 | while (!is_delimiter(scan_peek(&scanner))) { |
274 | .n = n, | 291 | c = scan_next(&scanner); |
275 | }; | 292 | n++; |
276 | token.type = TOKEN_NUMBER; | ||
277 | } else if (c >= '0' && c <= '9') { | ||
278 | scan_rewind(&scanner); | ||
279 | n = scan_number_token(&scanner); | ||
280 | if (n == 0) { | ||
281 | push_error(ERR_TYPE_LEXER, ERR_MALFORMED_NUMBER, line, col); | ||
282 | return tokens; | ||
283 | } | 293 | } |
284 | token.value = (StringView){ | 294 | token.value = (StringView){ |
285 | .start = &sv->start[offset], | 295 | .start = &sv->start[offset], |
@@ -27,9 +27,6 @@ process_source(const StringView *source, const char *file_name) { | |||
27 | Token *tokens = tokenize(source); | 27 | Token *tokens = tokenize(source); |
28 | print_tokens(tokens); | 28 | print_tokens(tokens); |
29 | check_errors(file_name); | 29 | check_errors(file_name); |
30 | // if (errors.n != 0) { | ||
31 | // exit(EXIT_FAILURE); | ||
32 | // } | ||
33 | 30 | ||
34 | // // Parser. | 31 | // // Parser. |
35 | // Program program = parse(tokens, &errors); | 32 | // Program program = parse(tokens, &errors); |