summaryrefslogtreecommitdiff
path: root/parser.c
diff options
context:
space:
mode:
authorCarson Fleming <[email protected]>2026-03-27 11:27:08 -1000
committerCarson Fleming <[email protected]>2026-03-27 11:27:08 -1000
commit414a608c36b2d8f208ad0223219736d7582948ae (patch)
treeeeeb284023236a4ee53bb4a78608c3cd1e3992bb /parser.c
parentfca3bf239cfdf03c4479f5d0c14a21c1fd96ea3e (diff)
downloadccc-414a608c36b2d8f208ad0223219736d7582948ae.tar.gz
fix some stuff
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c101
1 files changed, 53 insertions, 48 deletions
diff --git a/parser.c b/parser.c
index 699f345..d4af5a0 100644
--- a/parser.c
+++ b/parser.c
@@ -33,6 +33,12 @@ static void unexpected_token(enum token_type expected) {
PARSER_PANIC("unexpected token");
}
+/* TODO: reorganize the lexer to make peek cheaper */
+static void peek_or_panic() {
+ if (!lexer_peek(&tok))
+ PARSER_PANIC("unexpected EOF");
+}
+
static void expect(enum token_type expected) {
if (!lexer_pop(&tok))
PARSER_PANIC("unexpected EOF");
@@ -40,46 +46,38 @@ static void expect(enum token_type expected) {
if (tok.type != expected) unexpected_token(expected);
}
-static void peek_or_panic() {
- if (!lexer_peek(&tok))
- PARSER_PANIC("unexpected EOF");
-}
+static void expect_kw(const char* kw) {
+ if (!lexer_pop(&tok))
+ PARSER_PANIC("unexpected EOF, expected %s", kw);
-/* "handle" indicates that we've peeked already */
-static void handle_expr(struct expr_node* p_node);
-static void handle_stmt(struct stmt_node* p_node);
+ if (tok.type != TK_IDENT)
+ PARSER_PANIC("unexpected token, expected %s", kw);
+
+ if (strcmp(kw, tok.data.ident) != 0)
+ PARSER_PANIC(
+ "unexpected identifier %s, expected %s", tok.data.ident, kw);
+
+ /* string won't go in the AST, discard it */
+ free(tok.data.ident);
+ tok.data.ident = NULL;
+}
-static void handle_type(struct type_node* p_node) {
+static void parse_type(struct type_node* p_node) {
/* TODO: need some concept of known types in scope */
/* TODO: modifiers, void rules, arrays, etc. */
/* TODO: struct, union, enum */
+ expect(TK_IDENT);
p_node->name = tok.data.ident;
peek_or_panic();
p_node->ptr_level = 0;
while (tok.type == TK_STAR) {
- p_node->ptr_level++;
expect(TK_STAR);
+ p_node->ptr_level++;
+ peek_or_panic();
}
}
-static void parse_return(struct return_node* p_node) {
- expect(TK_IDENT);
- if (strcmp(tok.data.ident, "return") != 0)
- PARSER_PANIC("unexpected token %s; expected: return", tok.data.ident);
-
- if (!lexer_peek(&tok))
- PARSER_PANIC("unexpected EOF in return statement");
-
- if (tok.type == TK_SEMI) {
- p_node->ret_val = NULL;
- return;
- }
-
- p_node->ret_val = protected_alloc(sizeof(struct expr_node));
- handle_expr(p_node->ret_val);
-}
-
static void parse_int_lit(struct int_lit_node* p_node) {
expect(TK_INT_LIT);
p_node->val = tok.data.int_lit;
@@ -90,7 +88,8 @@ static void parse_var_ref(struct var_ref_node* p_node) {
p_node->ident = tok.data.ident;
}
-static void handle_expr(struct expr_node* p_node) {
+static void parse_expr(struct expr_node* p_node) {
+ peek_or_panic();
switch (tok.type) {
case TK_SEMI:
p_node->type = EXPR_EMPTY;
@@ -108,31 +107,45 @@ static void handle_expr(struct expr_node* p_node) {
}
}
-static void handle_var_decl(struct var_decl_node* p_node) {
- handle_type(&p_node->type);
+static void parse_var_decl(struct var_decl_node* p_node) {
+ parse_type(&p_node->type);
expect(TK_IDENT);
p_node->ident = tok.data.ident;
}
+static void parse_stmt(struct stmt_node* p_node);
+
+static void parse_return(struct return_node* p_node) {
+ expect_kw("return");
+
+ peek_or_panic();
+ if (tok.type == TK_SEMI) {
+ p_node->ret_val = NULL;
+ return;
+ }
+
+ p_node->ret_val = protected_alloc(sizeof(struct expr_node));
+ parse_expr(p_node->ret_val);
+}
+
static void parse_group(struct group_node* p_node) {
expect(TK_LCURLY);
struct stmt_node** pp_node = &p_node->body_head;
for (;;) {
- if (!lexer_peek(&tok))
- PARSER_PANIC("unexpected EOF in statement group");
-
+ peek_or_panic();
if (tok.type == TK_RCURLY) break;
*pp_node = protected_alloc(sizeof(struct stmt_node));
- handle_stmt(*pp_node);
+ parse_stmt(*pp_node);
pp_node = &((*pp_node)->next);
}
expect(TK_RCURLY);
}
-static void handle_stmt(struct stmt_node* p_node) {
+static void parse_stmt(struct stmt_node* p_node) {
+ peek_or_panic();
switch (tok.type) {
case TK_LCURLY:
p_node->type = STMT_GROUP;
@@ -145,45 +158,37 @@ static void handle_stmt(struct stmt_node* p_node) {
break;
} else if (scope_get_type(scope, NULL, tok.data.ident)) {
p_node->type = STMT_VAR_DECL;
- handle_var_decl(&p_node->as._var_decl);
+ parse_var_decl(&p_node->as._var_decl);
break;
}
default:
p_node->type = STMT_EXPR;
- handle_expr(&p_node->as._expr);
+ parse_expr(&p_node->as._expr);
}
expect(TK_SEMI);
}
static void parse_arg_list(struct var_decl_node** pp_arg) {
for (;;) {
- expect(TK_IDENT);
-
*pp_arg = protected_alloc(sizeof(struct var_decl_node));
- handle_var_decl(*pp_arg);
+ parse_var_decl(*pp_arg);
pp_arg = &((*pp_arg)->next);
- if (!lexer_peek(&tok))
- PARSER_PANIC("unexpected EOF in argument list");
-
+ peek_or_panic();
if (tok.type == TK_RPAREN) break;
expect(TK_COMMA);
}
}
static void parse_fn_decl(struct fn_decl_node* p_node) {
- expect(TK_IDENT);
- handle_type(&p_node->return_type);
+ parse_type(&p_node->return_type);
expect(TK_IDENT);
p_node->name = tok.data.ident;
expect(TK_LPAREN);
- if (!lexer_peek(&tok))
- PARSER_PANIC("unexpected EOF in function declaration");
-
-
+ peek_or_panic();
if (tok.type != TK_RPAREN) parse_arg_list(&p_node->args_head);
expect(TK_RPAREN);