117 lines
2.7 KiB
C

#include "ast.h"
struct Parser {
Token* tokens;
int current;
}
Token peek(Parser* p);
Token advance(Parser* p);
bool match(Parser* p, TokenKind kind);
bool expect(Parser* p, TokenKind kind, const char* error);
bool is_at_end(Parser* p);
List<ASTNode> parse_program(Parser* p) {
List<ASTNode> nodes;
while (!is_at_end(p)) {
nodes.append(parse_toplevel(p));
}
return nodes;
}
ASTNode parse_toplevel(Parser* p) {
if (match(p, KW_FN)) return parse_function(p);
if (match(p, KW_TYPEDEF)) return parse_typedef(p);
if (match(p, KW_STRUCT)) return parse_struct(p);
error("Unexpected top-level declaration");
}
ASTNode parse_function(Parser* p) {
ASTNode node;
node.kind = NODE_FUNCTION;
FunctionNode fn;
// Qualifiers (optional)
while (match(p, KW_STATIC) || match(p, KW_EXPORT) || match(p, KW_INLINE) || match(p, KW_EXTERN) || match(p, KW_ASM)) {
switch (previous(p).kind) {
case KW_STATIC: fn.is_static = true; break;
case KW_EXPORT: fn.is_export = true; break;
case KW_INLINE: fn.is_inline = true; break;
case KW_EXTERN: fn.is_extern = true; break;
case KW_ASM: fn.is_asm = true; break;
}
}
// Return type
fn.return_type = expect_identifier(p);
// Name
fn.name = expect_identifier(p);
// Parameters
expect(p, TOKEN_LPAREN, "Expected '(' after function name");
while (!match(p, TOKEN_RPAREN)) {
fn.params.append(parse_var_decl(p));
if (!match(p, TOKEN_RPAREN)) expect(p, TOKEN_COMMA, "Expected ',' between parameters");
}
// Body or semicolon (extern only)
if (fn.is_extern) {
expect(p, TOKEN_SEMICOLON, "Expected ';' after extern declaration");
fn.body = NULL;
} else {
fn.body = parse_block(p);
}
node.fn = fn;
return node;
}
VarDeclNode parse_var_decl(Parser* p) {
VarDeclNode var;
var.type = expect_identifier(p);
var.name = expect_identifier(p);
if (match(p, TOKEN_ASSIGN)) {
var.init = parse_expression(p);
}
return var;
}
ASTNode parse_struct(Parser* p) {
expect(p, KW_STRUCT, "Expected 'struct'");
String name = expect_identifier(p);
expect(p, TOKEN_LBRACE, "Expected '{' for struct definition");
List<VarDeclNode> fields;
while (!match(p, TOKEN_RBRACE)) {
fields.append(parse_var_decl(p));
expect(p, TOKEN_SEMICOLON, "Expected ';' after struct field");
}
StructNode str = { .name = name, .fields = fields };
ASTNode node = { .kind = NODE_STRUCT, .str = str };
return node;
}
BlockNode parse_block(Parser* p) {
BlockNode block;
expect(p, TOKEN_LBRACE, "Expected '{'");
while (!match(p, TOKEN_RBRACE)) {
block.statements.append(parse_statement(p));
}
return block;
}
ExprNode* parse_expression(Parser* p);
ExprNode* parse_primary(Parser* p);
ExprNode* parse_binary(Parser* p, int min_prec);
ExprNode* parse_call(Parser* p, ExprNode* callee);