summaryrefslogtreecommitdiff
path: root/src/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c138
1 files changed, 97 insertions, 41 deletions
diff --git a/src/parser.c b/src/parser.c
index b1e6a1f..4646de0 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -16,6 +16,7 @@
*/
#include <assert.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -30,83 +31,136 @@ parser_init(parser_t *parser, lexer_t *lexer)
assert(parser && "parser must be defined");
assert(lexer && "lexer must be defined");
parser->lexer = lexer;
+ parser->errors_len = 0;
}
-static token_t
-expected_token(parser_t *parser, token_kind_t kind)
+static bool
+expected_token(token_t *token, parser_t *parser, token_kind_t kind)
{
- token_t token;
- lexer_next_token(parser->lexer, &token);
-
- if (token.kind == TOKEN_EOF) {
- fprintf(
- stderr,
- "%s:%d:%d: [ERROR]: expected '%s' but got end of file\n",
- token.filepath, token.row + 1, token.col + 1,
+ lexer_next_token(parser->lexer, token);
+ parser_error_t error;
+
+ if (token->kind == TOKEN_EOF) {
+ error.token = *token;
+ sprintf(
+ error.message,
+ "expected '%s' but got end of file",
token_kind_to_str(kind)
);
- exit(EXIT_FAILURE);
+
+ parser->errors[parser->errors_len++] = error;
+ return false;
}
- if (token.kind != kind) {
- fprintf(
- stderr,
- "%s:%d:%d: [ERROR]: expected '%s' but got '%s'\n",
- token.filepath, token.row + 1, token.col + 1,
- token_kind_to_str(kind), token_kind_to_str(token.kind)
+ if (token->kind != kind) {
+ error.token = *token;
+ sprintf(
+ error.message,
+ "expected '%s' but got '%s'",
+ token_kind_to_str(kind), token_kind_to_str(token->kind)
);
- exit(EXIT_FAILURE);
+ parser->errors[parser->errors_len++] = error;
+ return false;
}
- return token;
+ return true;
+}
+
+static bool
+drop_expected_token(parser_t *parser, token_kind_t kind)
+{
+ token_t ignored_token;
+ return expected_token(&ignored_token, parser, kind);
}
-static type_t
-parser_parse_type(parser_t *parser)
+static bool
+parser_parse_type(type_t *type, parser_t *parser)
{
- token_t token = expected_token(parser, TOKEN_NAME);
+ token_t token;
+
+ if(!expected_token(&token, parser, TOKEN_NAME)) return false;
if (string_view_eq(token.value, string_view_from_str("i32"))) {
- return TYPE_I32;
+ *type = TYPE_I32;
+ return true;
}
- fprintf(stderr, "[ERROR]: expected type 'i32' but got '"SVFMT"'\n", SVARG(&token.value));
- exit(EXIT_FAILURE);
+ parser_error_t error;
+ error.token = token;
+
+ sprintf(
+ error.message,
+ "type '"SVFMT"' is not defined",
+ SVARG(&token.value)
+ );
+
+ parser->errors[parser->errors_len++] = error;
+ return false;
}
-void
+bool
parser_parse_return_stmt(parser_t *parser, ast_node_t *node)
{
- expected_token(parser, TOKEN_OCURLY);
- token_t return_keyword_token = expected_token(parser, TOKEN_NAME);
+ token_t return_keyword_token;
+
+ if (!drop_expected_token(parser, TOKEN_OCURLY)) return false;
+
+ if(!expected_token(&return_keyword_token, parser, TOKEN_NAME)) return false;
if (!string_view_eq(return_keyword_token.value, string_view_from_str("return"))) {
- // TODO: Add filename:row:col prefix to expected token exceptions
- fprintf(stderr, "[ERROR]: expected 'return' keyword but got '"SVFMT"'\n", SVARG(&return_keyword_token.value));
- exit(EXIT_FAILURE);
+ parser_error_t error;
+ error.token = return_keyword_token;
+
+ sprintf(
+ error.message,
+ "expected 'return' keyword but got '"SVFMT"'",
+ SVARG(&return_keyword_token.value)
+ );
+
+ parser->errors[parser->errors_len++] = error;
+ return false;
}
- token_t number_token = expected_token(parser, TOKEN_NUMBER);
- expected_token(parser, TOKEN_SEMICOLON);
- expected_token(parser, TOKEN_CCURLY);
+ token_t number_token;
+
+ if (!expected_token(&number_token, parser, TOKEN_NUMBER)) return false;
+
+ if (!drop_expected_token(parser, TOKEN_SEMICOLON)) return false;
+ if (!drop_expected_token(parser, TOKEN_CCURLY)) return false;
char number_as_str[number_token.value.size];
string_view_to_str(&number_token.value, number_as_str);
ast_node_init_return_stmt(node, atoi(number_as_str));
+ return true;
}
-void
+bool
parser_parse_function_declaration(parser_t *parser, ast_node_t *node)
{
- token_t func_name_token = expected_token(parser, TOKEN_NAME);
- expected_token(parser, TOKEN_OPAREN);
- expected_token(parser, TOKEN_CPAREN);
- expected_token(parser, TOKEN_COLON);
- type_t return_type = parser_parse_type(parser);
+ token_t func_name_token;
+
+ if (!expected_token(&func_name_token, parser, TOKEN_NAME)) {
+ return false;
+ }
+
+ if (!drop_expected_token(parser, TOKEN_OPAREN)) return false;
+ if (!drop_expected_token(parser, TOKEN_CPAREN)) return false;
+ if (!drop_expected_token(parser, TOKEN_COLON)) return false;
+
+ type_t return_type;
+
+ if(!parser_parse_type(&return_type, parser)) {
+ return false;
+ }
ast_node_t *return_node = ast_node_new();
- parser_parse_return_stmt(parser, return_node);
+
+ bool parsed_return = parser_parse_return_stmt(parser, return_node);
+
+ if (!parsed_return) {
+ return false;
+ }
ast_node_init_function_declaration(
node,
@@ -114,4 +168,6 @@ parser_parse_function_declaration(parser_t *parser, ast_node_t *node)
return_type,
return_node
);
+
+ return true;
}