Files
cval/src/parse.c
yenru0 9c94663045 minor implementation
basic expr parsing (not complex like compound, lambda)
2025-11-25 23:29:57 +09:00

246 lines
5.8 KiB
C

#include "parse.h"
#include <stdlib.h>
static void parser_next(Parser *parser);
static bool parser_expect(Parser *parser, TokenType type);
Parser *parser_new(Lexer *lexer) {
Parser *parser = malloc(sizeof(Parser));
if (parser == NULL) {
return NULL;
}
parser->lexer = lexer;
parser->flag_error = 0;
parser_next(parser);
parser_next(parser);
return parser;
}
void parser_free(Parser *parser) {
free(parser);
}
static void parser_next(Parser *parser) {
parser->current = parser->peek;
parser->peek = lexer_next_token(parser->lexer);
}
static bool parser_expect(Parser *parser, TokenType type) {
if (parser->current.type == type) {
parser_next(parser);
return true;
} else {
parser->flag_error = 1;
return false;
}
}
/*
IMPL. PARSER PARSE FUNCTIONS
*/
ASTNode *parser_parse_program(Parser *parser) {
ASTNode *root = ast_node_program();
while (parser->current.type == VAL) {
ASTNode *defn_node = parser_parse_defn(parser);
if (defn_node == NULL) {
ast_node_free(root);
parser->flag_error = 1;
return NULL;
}
ast_node_add_child(root, defn_node);
}
return root;
}
ASTNode *parser_parse_defn(Parser *parser) {
Token val_tok = parser->current;
if (!parser_expect(parser, VAL)) {// must start with VAL
return NULL;
}
ASTNode *type_node = parser_parse_type(parser);
if (type_node == NULL) {
return NULL;
}
if (parser->current.type != ID) {
parser->flag_error = 1;
return NULL;
}
Token id_tok = parser->current;
ASTNode *id_node = ast_node_id(id_tok);
parser_next(parser);
ASTNode *expr_node = NULL;
if (parser->current.type != SEMI) {
expr_node = parser_parse_expr(parser);
if (expr_node == NULL) {
parser->flag_error = 1;
return NULL;
}
}
if (!parser_expect(parser, SEMI)) {
return NULL;
}
ASTNode *defn_node = ast_node_defn(val_tok, type_node, id_node, expr_node);
return defn_node;
}
/*
PARSING TYPE
*/
ASTNode *parser_parse_type(Parser *parser) {
ASTNode *type_node = NULL;
if (parser->current.type == ID) {
type_node = parser_parse_type_simple(parser);
} else if (parser->current.type == LBRACK) {
type_node = parser_parse_type_complex(parser);
} else {
parser->flag_error = 1;
return NULL;
}
return type_node;
}
ASTNode *parser_parse_type_simple(Parser *parser) {
Token token = parser->current;
if (!parser_expect(parser, ID)) {
return NULL;
}
ASTNode *type_node = ast_node_type_simple(token);
while (parser->current.type == STAR) {
Token star_tok = parser->current;
parser_next(parser);
ASTNode *type_star = ast_node_type_star(star_tok);
ast_node_add_child(type_node, type_star);
}
return type_node;
}
ASTNode *parser_parse_type_complex(Parser *parser) {
Token tok = parser->current;
parser_next(parser);
ASTNode *types[256];
ASTNode *type_ret = NULL;
size_t cnt = 0;
ASTNode *ret = NULL;
while (parser->current.type != RBRACK && parser->current.type != ARROW) {
ASTNode *type = parser_parse_type(parser);
if (type == NULL) {
return NULL;
}
types[cnt++] = type;
}
if (parser->current.type == ARROW) {
parser_next(parser);
if (parser->current.type != RBRACK) {
type_ret = parser_parse_type(parser);
if (type_ret == NULL) return NULL;
} else {
type_ret = ast_node_type_void(parser);
}
ASTNode *type_param = ast_node_type_param();
for (size_t i = 0; i < cnt; i++) {
ast_node_add_child(type_param, types[i]);
}
ASTNode *type_out = ast_node_type_out();
ast_node_add_child(type_out, type_ret);
ret = ast_node_type_complex(tok, type_param, type_out);
} else if (parser->current.type == RBRACK) {
if (cnt >= 2) {
parser->flag_error = 1;// too many args
return NULL;
}
if (cnt == 1) {
ret = types[0];
} else {
ret = ast_node_type_void(parser);
}
} else {
parser->flag_error = 1;
return NULL;
}
parser_next(parser);
return ret;
}
/*
PARSING EXPR
*/
ASTNode *parser_parse_expr(Parser *parser) {
ASTNode *atoms[256];
size_t cnt = 1;
ASTNode *atom_head = parser_parse_atom(parser);
if (atom_head == NULL) {
parser->flag_error = 1;
return NULL;
}
atoms[0] = atom_head;
ASTNode *atom;
while (true) {
atom = parser_parse_atom(parser);
if (atom == NULL) {
break;
}
atoms[cnt] = atom;
cnt++;
}
ASTNode *node = ast_node_expr(atom_head->token);
for (size_t i = 0; i < cnt; i++) {
ast_node_add_child(node, atoms[i]);
}
return node;
}
ASTNode *parser_parse_atom(Parser *parser) {
if (parser->current.type == NUM) {
Token num_tok = parser->current;
parser_next(parser);
return ast_node_num(num_tok);
} else if (parser->current.type == ID) {
Token id_tok = parser->current;
parser_next(parser);
return ast_node_id(id_tok);
} else if (parser->current.type == STRING_LITERAL) {
Token str_tok = parser->current;
parser_next(parser);
return ast_node_str(str_tok);
} else if (parser->current.type == STAR) {
Token star_tok = parser->current;
parser_next(parser);
return ast_node_star(star_tok);
} else if (parser->current.type == ANDREF) {
Token andref_tok = parser->current;
parser_next(parser);
return ast_node_andref(andref_tok);
}
else {
return NULL;
}
}