From ab7d5d484b911f454f35567ed2f1a1a2dac167f7 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Tue, 12 Oct 2021 17:25:08 +0200 Subject: Add new error values --- src/bootstrap/errors.c | 8 +++ src/bootstrap/parser.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 src/bootstrap/parser.c diff --git a/src/bootstrap/errors.c b/src/bootstrap/errors.c index fcb629a..87752e6 100644 --- a/src/bootstrap/errors.c +++ b/src/bootstrap/errors.c @@ -7,6 +7,10 @@ typedef enum ErrorType { typedef enum ErrorValue { ERR_UNKNOWN = 0, ERR_UNMATCHED_STRING, + ERR_UNBALANCED_PAREN, + ERR_NOT_IMPLEMENTED, + ERR_EOF_REACHED, + ERR_UNKNOWN_TOKEN, } ErrorValue; typedef struct Error { @@ -19,6 +23,10 @@ typedef struct Error { static const char* error_msgs[] = { [ERR_UNKNOWN] = "error: something unexpected happened", [ERR_UNMATCHED_STRING] = "error: unmatched string delimiter", + [ERR_UNBALANCED_PAREN] = "error: unbalanced parentheses", + [ERR_NOT_IMPLEMENTED] = "error: not implemented", + [ERR_EOF_REACHED] = "error: EOF reached", + [ERR_UNKNOWN_TOKEN] = "error: unknown token", }; #define ERR_MAX_NUMBER 16 diff --git a/src/bootstrap/parser.c b/src/bootstrap/parser.c new file mode 100644 index 0000000..c84c6c6 --- /dev/null +++ b/src/bootstrap/parser.c @@ -0,0 +1,149 @@ +typedef struct Visitor { + Tokens tokens; + size_t current; +} Visitor; + +Token +peek_token(const Visitor *visitor) { + return visitor->tokens.buf[visitor->current]; +} + +Token +next_token(Visitor *visitor) { + return visitor->tokens.buf[visitor->current++]; +} + +bool +has_next_token(const Visitor *visitor) { + return visitor->current < visitor->tokens.size; +} + +Object * +parse_fixnum(Token tok) { + ssize_t num = 0; + int sign = 1; + for (size_t i = 0; i < tok.value.n; i++) { + char c = tok.value.start[i]; + if (c == '-') { + sign = -1; + continue; + } + num = num * 10 + (c - '0'); + } + return make_fixnum(num * sign); +} + +Object * parse_tree(Visitor *vs); + +Object * +parse_list(Visitor *vs) { + Token tok = peek_token(vs); + if (tok.type == TOKEN_EOF) { + error_push((Error){ + .type = ERR_TYPE_PARSER, + .value = ERR_UNBALANCED_PAREN, + .line = tok.line, + .col = tok.column, + }); + return obj_err; + } + Object *next_obj = parse_tree(vs); + if (next_obj == obj_err) { + return obj_err; + } + Object *root = make_pair(next_obj, obj_nil); + Object *list = root; + while (has_next_token(vs)) { + Token tok = peek_token(vs); + if (tok.type == TOKEN_RPAREN) { + next_token(vs); + break; + } + if (tok.type == TOKEN_EOF) { + error_push((Error){ + .type = ERR_TYPE_PARSER, + .value = ERR_UNBALANCED_PAREN, + .line = tok.line, + .col = tok.column, + }); + free_objects(root); + return obj_err; + } + next_obj = parse_tree(vs); + if (next_obj == obj_err) { + free_objects(root); + return obj_err; + } + list->cdr = make_pair(next_obj, obj_nil); + list = list->cdr; + } + return root; +} + +Object * +parse_tree(Visitor *vs) { + Token tok = next_token(vs); + switch (tok.type) { + case TOKEN_FIXNUM: { + return parse_fixnum(tok); + } break; + case TOKEN_TRUE: { + return obj_true; + } break; + case TOKEN_FALSE: { + return obj_false; + } break; + case TOKEN_RPAREN: { + error_push((Error){ + .type = ERR_TYPE_PARSER, + .value = ERR_UNBALANCED_PAREN, + .line = tok.line, + .col = tok.column, + }); + return obj_err; + } break; + case TOKEN_QUOTE: { + // TODO: Implement. + error_push((Error){ + .type = ERR_TYPE_PARSER, + .value = ERR_NOT_IMPLEMENTED, + .line = tok.line, + .col = tok.column, + }); + return obj_err; + } break; + case TOKEN_LPAREN: { + return parse_list(vs); + } break; + case TOKEN_STRING: { + Object *obj = make_string(); + append_string(obj, tok.value); + return obj; + } break; + case TOKEN_SYMBOL: { + return make_symbol(tok.value); + } break; + case TOKEN_EOF: { + error_push((Error){ + .type = ERR_TYPE_PARSER, + .value = ERR_EOF_REACHED, + .line = tok.line, + .col = tok.column, + }); + return obj_err; + } break; + case TOKEN_NIL: { + return obj_nil; + } break; + default: { + break; + } break; + } + error_push((Error){ + .type = ERR_TYPE_PARSER, + .value = ERR_EOF_REACHED, + .line = tok.line, + .col = tok.column, + }); + return obj_err; +} -- cgit v1.2.1