initial parse

This commit is contained in:
sfja 2026-10-01 23:55:04 +02:00
parent 9bf5fc06db
commit ac95ee12b9
9 changed files with 586 additions and 387 deletions

View File

@ -1,5 +1,5 @@
larpcc: main.c lex.c preproc.c collection.c parse.c syms.c ast_str.c
larpcc: main.c lex.c preproc.c collection.c parse.c syms.c ast_print.c resolve.c
gcc $^ -o $@ -std=c23 -pedantic -Wall -Wextra -g -fsanitize=address -Werror=switch

45
ast.h
View File

@ -2,6 +2,7 @@
#define AST_H
#include "collection.h"
#include <stdio.h>
typedef struct {
int line;
@ -92,6 +93,7 @@ struct AstDeclar {
};
typedef enum {
AstExpr_Ident,
AstExpr_Str,
AstExpr_Call,
} AstExprTy;
@ -100,6 +102,7 @@ struct AstExpr {
AstExprTy ty;
Loc loc;
union {
char* ident;
char* str_val;
struct {
AstExpr* expr;
@ -108,17 +111,37 @@ struct AstExpr {
};
};
typedef struct {
ARRAY_FIELD(char, string);
Arena* arena;
int depth;
} AstStringifier;
void ast_stmt_block_print(FILE* f, const AstStmtBlock* node, int depth);
void ast_stmt_print(FILE* f, const AstStmt* node, int depth);
void ast_decl_print(FILE* f, const AstDecl* node, int depth);
void ast_declar_print(FILE* f, const AstDeclar* node, int depth);
void ast_expr_print(FILE* f, const AstExpr* node, int depth);
void ast_stringifier_init(AstStringifier* s, Arena* arena);
void ast_stmt_block_to_string(AstStringifier* s, const AstStmtBlock* node);
void ast_stmt_to_string(AstStringifier* s, const AstStmt* node);
void ast_decl_to_string(AstStringifier* s, const AstDecl* node);
void ast_declar_to_string(AstStringifier* s, const AstDeclar* node);
void ast_expr_to_string(AstStringifier* s, const AstExpr* node);
typedef struct AstVisitor AstVisitor;
typedef enum {
AstVisitor_Continue,
AstVisitor_Break,
} AstVisitorResult;
struct AstVisitor {
AstVisitorResult (*visit_stmt_block)(AstVisitor* v, AstStmtBlock* node);
AstVisitorResult (*visit_stmt)(AstVisitor* v, AstStmt* node);
AstVisitorResult (*visit_decl)(AstVisitor* v, AstDecl* node);
AstVisitorResult (*visit_declar)(AstVisitor* v, AstDeclar* node);
AstVisitorResult (*visit_expr)(AstVisitor* v, AstExpr* node);
void* op;
};
void ast_stmt_block_visit(AstVisitor* v, AstStmtBlock* node);
void ast_stmt_block_visit_body(AstVisitor* v, AstStmtBlock* node);
void ast_stmt_visit(AstVisitor* v, AstStmt* node);
void ast_stmt_visit_body(AstVisitor* v, AstStmt* node);
void ast_decl_visit(AstVisitor* v, AstDecl* node);
void ast_decl_visit_body(AstVisitor* v, AstDecl* node);
void ast_declar_visit(AstVisitor* v, AstDeclar* node);
void ast_declar_visit_body(AstVisitor* v, AstDeclar* node);
void ast_expr_visit(AstVisitor* v, AstExpr* node);
void ast_expr_visit_body(AstVisitor* v, AstExpr* node);
#endif

368
ast_print.c Normal file
View File

@ -0,0 +1,368 @@
#include "ast.h"
#include "collection.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
static void indent(FILE* f, int depth)
{
for (int i = 0; i < depth; ++i) {
fprintf(f, " ");
}
}
void ast_stmt_block_print(FILE* f, const AstStmtBlock* node, int depth)
{
fprintf(f, "StmtBlock %d:%d {\n", node->loc.line, node->loc.col);
indent(f, depth + 1);
fprintf(f, "stmts: [");
if (node->stmts_size) {
fprintf(f, "\n");
for (size_t i = 0; i < node->stmts_size; ++i) {
indent(f, depth + 2);
ast_stmt_print(f, node->stmts[i], depth + 2);
fprintf(f, ",\n");
}
indent(f, depth + 1);
}
fprintf(f, "],\n");
indent(f, depth);
fprintf(f, "}");
}
void ast_stmt_print(FILE* f, const AstStmt* node, int depth)
{
switch (node->ty) {
case AstStmt_Decl: {
fprintf(f, "Stmt::Decl %d:%d {\n", node->loc.line, node->loc.col);
indent(f, depth + 1);
fprintf(f, "decl: ");
ast_decl_print(f, node->decl, depth + 1);
fprintf(f, ",\n");
indent(f, depth);
fprintf(f, "}");
break;
}
case AstStmt_Expr: {
fprintf(f, "Stmt::Expr %d:%d {\n", node->loc.line, node->loc.col);
indent(f, depth + 1);
fprintf(f, "expr: ");
ast_expr_print(f, node->expr, depth + 1);
fprintf(f, ",\n");
indent(f, depth);
fprintf(f, "}");
break;
}
}
}
static void spec_print(FILE* f, AstSpec spec)
{
struct {
AstSpec specifier;
const char* ident;
} spec_idents[] = {
{ AstSpec_Int, "int" },
{ AstSpec_Char, "char" },
{ AstSpec_Unsigned, "unsigned" },
{ AstSpec_Static, "static" },
{ AstSpec_Const, "const" },
{ AstSpec_Inline, "inline" },
{ AstSpec_Typedef, "typedef" },
{ AstSpec_Enum, "enum" },
{ AstSpec_Struct, "struct" },
{ AstSpec_Union, "union" },
};
bool first = true;
for (size_t i = 0; i < sizeof(spec_idents) / sizeof(spec_idents[0]); ++i) {
if (spec & spec_idents[i].specifier) {
if (!first)
fprintf(f, " ");
first = false;
fprintf(f, "%s", spec_idents[i].ident);
}
}
}
void ast_decl_print(FILE* f, const AstDecl* node, int depth)
{
fprintf(f, "Decl %d:%d {\n", node->loc.line, node->loc.col);
indent(f, depth + 1);
fprintf(f, "spec: [");
spec_print(f, node->spec);
fprintf(f, "],\n");
if (node->spec & AstSpec_DefTy) {
assert(node->type_ident);
indent(f, depth + 1);
fprintf(f, "type_ident: \"%s\",\n", node->type_ident);
}
indent(f, depth + 1);
fprintf(f, "declars: [");
if (node->declars_size) {
fprintf(f, "\n");
for (size_t i = 0; i < node->declars_size; ++i) {
indent(f, depth + 2);
ast_declar_print(f, node->declars[i], depth + 2);
fprintf(f, ",\n");
}
indent(f, depth + 1);
}
fprintf(f, "],\n");
if (node->function_body) {
indent(f, depth + 1);
fprintf(f, "function_body: ");
ast_stmt_block_print(f, node->function_body, depth + 1);
fprintf(f, ",\n");
}
indent(f, depth);
fprintf(f, "}");
}
void ast_declar_print(FILE* f, const AstDeclar* node, int depth)
{
switch (node->ty) {
case AstDeclar_Ident: {
fprintf(
f, "Declar::Ident %d:%d {\n", node->loc.line, node->loc.col);
indent(f, depth + 1);
fprintf(f, "ident: \"%s\",\n", node->ident);
break;
}
case AstDeclar_Pointer: {
fprintf(
f, "Declar::Pointer %d:%d {\n", node->loc.line, node->loc.col);
indent(f, depth + 1);
fprintf(f, "declar: ");
ast_declar_print(f, node->pointer.declar, depth + 1);
fprintf(f, ",\n");
indent(f, depth + 1);
fprintf(f, "spec: [");
spec_print(f, node->pointer.spec);
fprintf(f, "],\n");
break;
}
case AstDeclar_Array: {
fprintf(
f, "Declar::Array %d:%d {\n", node->loc.line, node->loc.col);
indent(f, depth + 1);
fprintf(f, "declar: ");
ast_declar_print(f, node->array.declar, depth + 1);
fprintf(f, ",\n");
indent(f, depth + 1);
fprintf(f, "expr: ");
ast_expr_print(f, node->array.expr, depth + 1);
fprintf(f, ",\n");
break;
}
case AstDeclar_Function: {
fprintf(
f, "Declar::Function %d:%d {\n", node->loc.line, node->loc.col);
indent(f, depth + 1);
fprintf(f, "declar: ");
ast_declar_print(f, node->array.declar, depth + 1);
fprintf(f, ",\n");
indent(f, depth + 1);
fprintf(f, "params: [");
if (node->function.params_size) {
fprintf(f, "\n");
for (size_t i = 0; i < node->function.params_size; ++i) {
indent(f, depth + 2);
ast_decl_print(f, node->function.params[i], depth + 2);
fprintf(f, ",\n");
}
indent(f, depth + 1);
fprintf(f, "],\n");
} else {
fprintf(f, "],\n");
}
break;
}
}
if (node->init_expr) {
indent(f, depth + 2);
fprintf(f, "decl: ");
ast_expr_print(f, node->init_expr, depth + 2);
fprintf(f, ",\n");
}
indent(f, depth);
fprintf(f, "}");
}
void ast_expr_print(FILE* f, const AstExpr* node, int depth)
{
switch (node->ty) {
case AstExpr_Ident: {
fprintf(f, "Expr::Ident %d:%d {\n", node->loc.line, node->loc.col);
indent(f, depth + 1);
fprintf(f, "ident: \"%s\",\n", node->ident);
indent(f, depth);
fprintf(f, "}");
break;
}
case AstExpr_Str: {
fprintf(f, "Expr::Str %d:%d {\n", node->loc.line, node->loc.col);
indent(f, depth + 1);
fprintf(f, "str_val: \"%s\",\n", node->str_val);
indent(f, depth);
fprintf(f, "}");
break;
}
case AstExpr_Call: {
fprintf(f, "Expr::Call %d:%d {\n", node->loc.line, node->loc.col);
indent(f, depth + 1);
fprintf(f, "expr: ");
ast_expr_print(f, node->call.expr, depth + 1);
fprintf(f, ",\n");
indent(f, depth + 1);
fprintf(f, "args: [");
if (node->call.args_size) {
fprintf(f, "\n");
for (size_t i = 0; i < node->call.args_size; ++i) {
indent(f, depth + 2);
ast_expr_print(f, node->call.args[i], depth + 2);
fprintf(f, ",\n");
}
indent(f, depth + 1);
}
fprintf(f, ",]\n");
indent(f, depth);
fprintf(f, "}");
break;
}
}
}
void ast_stmt_block_visit(AstVisitor* v, AstStmtBlock* node)
{
if (v->visit_stmt_block && v->visit_stmt_block(v, node) == AstVisitor_Break)
return;
ast_stmt_block_visit_body(v, node);
}
void ast_stmt_block_visit_body(AstVisitor* v, AstStmtBlock* node)
{
for (size_t i = 0; i < node->stmts_size; ++i) {
ast_stmt_visit(v, node->stmts[i]);
}
}
void ast_stmt_visit(AstVisitor* v, AstStmt* node)
{
if (v->visit_stmt && v->visit_stmt(v, node) == AstVisitor_Break)
return;
ast_stmt_visit_body(v, node);
}
void ast_stmt_visit_body(AstVisitor* v, AstStmt* node)
{
switch (node->ty) {
case AstStmt_Decl:
ast_decl_visit(v, node->decl);
break;
case AstStmt_Expr:
ast_expr_visit(v, node->expr);
break;
}
}
void ast_decl_visit(AstVisitor* v, AstDecl* node)
{
if (v->visit_decl && v->visit_decl(v, node) == AstVisitor_Break)
return;
ast_decl_visit_body(v, node);
}
void ast_decl_visit_body(AstVisitor* v, AstDecl* node)
{
for (size_t i = 0; i < node->declars_size; ++i)
ast_declar_visit(v, node->declars[i]);
}
void ast_declar_visit(AstVisitor* v, AstDeclar* node)
{
if (v->visit_declar && v->visit_declar(v, node) == AstVisitor_Break)
return;
ast_declar_visit_body(v, node);
}
void ast_declar_visit_body(AstVisitor* v, AstDeclar* node)
{
switch (node->ty) {
case AstDeclar_Ident:
break;
case AstDeclar_Pointer:
ast_declar_visit(v, node->pointer.declar);
break;
case AstDeclar_Array:
ast_declar_visit(v, node->array.declar);
ast_expr_visit(v, node->array.expr);
break;
case AstDeclar_Function:
ast_declar_visit(v, node->pointer.declar);
for (size_t i = 0; i < node->function.params_size; ++i)
ast_decl_visit(v, node->function.params[i]);
break;
}
}
void ast_expr_visit(AstVisitor* v, AstExpr* node)
{
if (v->visit_expr && v->visit_expr(v, node) == AstVisitor_Break)
return;
ast_expr_visit_body(v, node);
}
void ast_expr_visit_body(AstVisitor* v, AstExpr* node)
{
switch (node->ty) {
case AstExpr_Ident:
break;
case AstExpr_Str:
break;
case AstExpr_Call:
ast_expr_visit(v, node->call.expr);
for (size_t i = 0; i < node->call.args_size; ++i)
ast_expr_visit(v, node->call.args[i]);
break;
}
}

283
ast_str.c
View File

@ -1,283 +0,0 @@
#include "ast.h"
#include "collection.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
static void push(AstStringifier* s, const char* str)
{
for (; *str; ++str) {
arena_array_push(s->arena,
(void**)&s->string,
&s->string_cap,
&s->string_size,
(void*)str,
sizeof(*str));
}
char ch = '\0';
arena_array_push(s->arena,
(void**)&s->string,
&s->string_cap,
&s->string_size,
(void*)&ch,
sizeof(ch));
s->string_size -= 1;
}
#define pushf(S, ...) \
do { \
size_t len = snprintf(nullptr, 0, __VA_ARGS__); \
char* buf = calloc(len + 1, 1); \
snprintf(buf, len + 1, __VA_ARGS__); \
push(S, buf); \
free(buf); \
} while (false)
static void indent(AstStringifier* s)
{
for (int i = 0; i < s->depth; ++i) {
push(s, " ");
}
}
void ast_stringifier_init(AstStringifier* s, Arena* arena)
{
*s = (AstStringifier) {
ARRAY_FIELD_INIT(string),
.arena = arena,
.depth = 0,
};
}
void ast_stmt_block_to_string(AstStringifier* s, const AstStmtBlock* node)
{
pushf(s, "StmtBlock %d:%d {\n", node->loc.line, node->loc.col);
s->depth += 1;
indent(s);
push(s, "stmts: [");
if (node->stmts_size) {
s->depth += 1;
push(s, "\n");
for (size_t i = 0; i < node->stmts_size; ++i) {
indent(s);
ast_stmt_to_string(s, node->stmts[i]);
push(s, ",\n");
}
s->depth -= 1;
indent(s);
}
push(s, "],");
s->depth -= 1;
indent(s);
push(s, "}");
}
void ast_stmt_to_string(AstStringifier* s, const AstStmt* node)
{
switch (node->ty) {
case AstStmt_Decl: {
pushf(s, "Stmt::Decl %d:%d {\n", node->loc.line, node->loc.col);
s->depth += 1;
indent(s);
push(s, "decl: ");
ast_decl_to_string(s, node->decl);
push(s, ",\n");
s->depth -= 1;
indent(s);
push(s, "}");
break;
}
case AstStmt_Expr: {
pushf(s, "Stmt::Expr %d:%d {\n", node->loc.line, node->loc.col);
s->depth += 1;
indent(s);
push(s, "expr: ");
ast_expr_to_string(s, node->expr);
push(s, ",\n");
s->depth -= 1;
indent(s);
push(s, "}");
break;
}
}
}
static void spec_to_string(AstStringifier* s, AstSpec spec)
{
struct {
AstSpec specifier;
const char* ident;
} spec_idents[] = {
{ AstSpec_Int, "int" },
{ AstSpec_Char, "char" },
{ AstSpec_Unsigned, "unsigned" },
{ AstSpec_Static, "static" },
{ AstSpec_Const, "const" },
{ AstSpec_Inline, "inline" },
{ AstSpec_Typedef, "typedef" },
{ AstSpec_Enum, "enum" },
{ AstSpec_Struct, "struct" },
{ AstSpec_Union, "union" },
};
bool first = true;
for (size_t i = 0; i < sizeof(spec_idents) / sizeof(spec_idents[0]); ++i) {
if (spec & spec_idents[i].specifier) {
if (!first)
push(s, " ");
first = false;
push(s, spec_idents[i].ident);
}
}
}
void ast_decl_to_string(AstStringifier* s, const AstDecl* node)
{
pushf(s, "Decl %d:%d {\n", node->loc.line, node->loc.col);
s->depth += 1;
indent(s);
push(s, "spec: [");
spec_to_string(s, node->spec);
push(s, "],\n");
if (node->spec & AstSpec_DefTy) {
assert(node->type_ident);
indent(s);
pushf(s, "type_ident: \"%s\",\n", node->type_ident);
}
indent(s);
push(s, "declars: [");
if (node->declars_size) {
push(s, "\n");
s->depth += 1;
for (size_t i = 0; i < node->declars_size; ++i) {
indent(s);
ast_declar_to_string(s, node->declars[i]);
push(s, ",\n");
}
s->depth -= 1;
indent(s);
push(s, "],\n");
} else {
push(s, "],\n");
}
if (node->function_body) {
indent(s);
push(s, "function_body: ");
ast_stmt_block_to_string(s, node->function_body);
push(s, ",\n");
}
s->depth -= 1;
indent(s);
push(s, "}");
}
void ast_declar_to_string(AstStringifier* s, const AstDeclar* node)
{
switch (node->ty) {
case AstDeclar_Ident: {
pushf(s, "Declar::Ident %d:%d {\n", node->loc.line, node->loc.col);
s->depth += 1;
indent(s);
pushf(s, "ident: \"%s\",\n", node->ident);
break;
}
case AstDeclar_Pointer: {
pushf(
s, "Declar::Pointer %d:%d {\n", node->loc.line, node->loc.col);
s->depth += 1;
indent(s);
push(s, "declar: ");
ast_declar_to_string(s, node->pointer.declar);
push(s, ",\n");
indent(s);
push(s, "spec: [");
spec_to_string(s, node->pointer.spec);
push(s, "],\n");
break;
}
case AstDeclar_Array: {
pushf(s, "Declar::Array %d:%d {\n", node->loc.line, node->loc.col);
s->depth += 1;
indent(s);
push(s, "declar: ");
ast_declar_to_string(s, node->array.declar);
push(s, ",\n");
indent(s);
push(s, "expr: ");
ast_expr_to_string(s, node->array.expr);
push(s, ",\n");
break;
}
case AstDeclar_Function: {
pushf(
s, "Declar::Function %d:%d {\n", node->loc.line, node->loc.col);
s->depth += 1;
indent(s);
push(s, "declar: ");
ast_declar_to_string(s, node->array.declar);
push(s, ",\n");
indent(s);
push(s, "params: [");
if (node->function.params_size) {
push(s, "\n");
s->depth += 1;
for (size_t i = 0; i < node->function.params_size; ++i) {
indent(s);
ast_decl_to_string(s, node->function.params[i]);
push(s, ",\n");
}
s->depth -= 1;
indent(s);
push(s, "],\n");
} else {
push(s, "],\n");
}
break;
}
}
if (node->init_expr) {
indent(s);
push(s, "decl: ");
ast_expr_to_string(s, node->init_expr);
push(s, ",\n");
}
s->depth -= 1;
indent(s);
push(s, "}");
}
void ast_expr_to_string(AstStringifier* s, const AstExpr* node)
{
push(s, "<expr>");
}

16
main.c
View File

@ -1,6 +1,7 @@
#include "ast.h"
#include "collection.h"
#include "parse.h"
#include "resolve.h"
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
@ -77,22 +78,19 @@ int main(int argc, char* argv[])
Parser* parser = parser_new(&tokstream, &ast_arena);
Resolver* resolver = resolver_new();
AstStmt* stmt;
while (!parser_done(parser)) {
stmt = parser_parse_stmt(parser);
Arena s_arena;
arena_init(&s_arena, 4096);
AstStringifier s = { };
ast_stringifier_init(&s, &s_arena);
ast_stmt_print(stdout, stmt, 0);
ast_stmt_to_string(&s, stmt);
printf("%s\n", s.string);
arena_deinit(&s_arena);
printf("\n");
}
resolver_free(resolver);
parser_free(parser);
preproc_free(preproc);

152
parse.c
View File

@ -25,21 +25,6 @@ typedef struct {
ARRAY_FIELD(KwNode, nodes);
} KwMatcher;
static void kw_tree_print(KwMatcher* m, KwNode* node, int depth)
{
for (size_t i = 0; i < node->opts_size; ++i) {
for (int i = 0; i < depth; ++i)
printf(" ");
printf("%c", node->opts[i].ch);
if (node->opts[i].is_term) {
printf(" = %s\n", tokty_str(node->opts[i].val));
} else {
printf("\n");
kw_tree_print(m, &m->nodes[node->opts[i].val], depth + 1);
}
}
}
static KwNodeOpt* kwmatcher_create_path(
KwMatcher* m, size_t node_idx, const char* kw)
{
@ -60,12 +45,7 @@ static KwNodeOpt* kwmatcher_create_path(
ARRAY_FIELD_INIT(opts),
.idx = new_idx,
};
arena_array_push(&m->arena,
(void**)&m->nodes,
&m->nodes_cap,
&m->nodes_size,
&new_node,
sizeof(new_node));
ARENA_ARRAY_FIELD_PUSH(&m->arena, m, nodes, &new_node);
// might have been relocated
node = &m->nodes[node_idx];
@ -74,12 +54,7 @@ static KwNodeOpt* kwmatcher_create_path(
.is_term = false,
.val = new_idx,
};
arena_array_push(&m->arena,
(void**)&node->opts,
&node->opts_cap,
&node->opts_size,
&new_opt,
sizeof(new_opt));
ARENA_ARRAY_FIELD_PUSH(&m->arena, node, opts, &new_opt);
opt = &node->opts[node->opts_size - 1];
}
@ -131,12 +106,7 @@ static void kwmatcher_init(KwMatcher* m, TokStream* tokstream)
arena_init(&m->arena, 512);
arena_array_push(&m->arena,
(void**)&(m)->nodes,
&(m)->nodes_cap,
&(m)->nodes_size,
(&(KwNode) { .idx = 0 }),
sizeof(*(&(KwNode) { .idx = 0 })));
ARENA_ARRAY_FIELD_PUSH(&m->arena, m, nodes, (&(KwNode) { .idx = 0 }));
struct {
TokTy ty;
@ -150,8 +120,6 @@ static void kwmatcher_init(KwMatcher* m, TokStream* tokstream)
for (size_t i = 0; i < sizeof(kws) / sizeof(kws[0]); ++i) {
kwmatcher_add(m, kws[i].kw, kws[i].ty);
}
kw_tree_print(m, &m->nodes[0], 0);
}
static void kwmatcher_deinit(KwMatcher* m)
@ -165,12 +133,10 @@ static Tok kwmatcher_next(KwMatcher* m)
if (tok.ty != Tok_Ident)
goto exit;
TokTy ty = kwmatcher_match(m, tok.text);
if (ty != Tok_Ident)
printf("info: matched '%s' on line %d\n", tok.text, tok.loc.line);
tok.ty = ty;
exit:
printf(" - %s(%s) %d:%d\n",
printf(" - %-10s %-10s %d:%d\n",
tokty_str(tok.ty),
tok.text,
tok.loc.line,
@ -178,16 +144,20 @@ exit:
return tok;
}
typedef enum : unsigned int {
ParserFlags_ParsingTypedef = 1 << 0,
} ParserFlags;
struct Parser {
KwMatcher kwmatcher;
Arena* arena;
Arena sym_arena;
Syms* ord_ns;
Syms* label_ns;
Syms* tag_ns;
Syms* syms;
Tok curr;
ParserFlags flags;
};
Parser* parser_new(TokStream* tokstream, Arena* arena)
@ -199,11 +169,11 @@ Parser* parser_new(TokStream* tokstream, Arena* arena)
.arena = arena,
.sym_arena = { },
.ord_ns = syms_new(),
.label_ns = syms_new(),
.tag_ns = syms_new(),
.syms = syms_new(),
.curr = { },
.flags = 0,
};
kwmatcher_init(&p->kwmatcher, tokstream);
@ -215,6 +185,7 @@ Parser* parser_new(TokStream* tokstream, Arena* arena)
void parser_free(Parser* p)
{
kwmatcher_deinit(&p->kwmatcher);
syms_free(p->syms);
free(p);
}
@ -239,7 +210,8 @@ DEFINE_NEW(AstExpr, expr)
DEFINE_NEW(AstStmtBlock, stmt_block)
static AstStmtBlock* parse_stmt_block(Parser* p);
static AstDecl* parse_decl(Parser* p);
static AstStmt* parse_stmt(Parser* p);
static AstDecl* parse_decl(Parser* p, bool is_param);
static AstDeclar* parse_declar(Parser* p);
static AstSpec parse_decl_spec(Parser* p);
static AstExpr* parse_expr(Parser* p);
@ -248,17 +220,13 @@ static AstStmtBlock* parse_stmt_block(Parser* p)
{
Loc loc = p->curr.loc;
assert(p->curr.ty == '{');
step(p);
ARRAY_VAR(AstStmt*, stmts);
while (p->curr.ty != Tok_Eof && p->curr.ty != '}') {
AstStmt* stmt = parser_parse_stmt(p);
arena_array_push(p->arena,
(void**)&stmts,
&stmts_cap,
&stmts_size,
(&stmt),
sizeof(*(&stmt)));
AstStmt* stmt = parse_stmt(p);
ARENA_ARRAY_VAR_PUSH(p->arena, stmts, &stmt);
}
if (p->curr.ty != '}') {
@ -292,7 +260,7 @@ static bool is_defty_ident(Parser* p, Tok tok)
{
if (tok.ty != Tok_Ident)
return false;
Sym* sym = syms_get(p->ord_ns, tok.text);
Sym* sym = syms_get(p->syms, tok.text);
return sym && sym->ty == Sym_Typedef;
}
@ -301,7 +269,7 @@ static AstStmt* parse_stmt(Parser* p)
Loc loc = p->curr.loc;
if (is_decl_start_kw(p->curr.ty) || is_defty_ident(p, p->curr)) {
AstDecl* decl = parse_decl(p);
AstDecl* decl = parse_decl(p, false);
if (!decl->function_body && p->curr.ty != ';') {
fprintf(
@ -320,6 +288,12 @@ static AstStmt* parse_stmt(Parser* p)
AstExpr* expr = parse_expr(p);
if (p->curr.ty != ';') {
fprintf(stderr, "error: expected ';' on line %d\n", p->curr.loc.line);
exit(1);
}
step(p);
return new_stmt(p,
(AstStmt) {
.ty = AstStmt_Expr,
@ -328,50 +302,47 @@ static AstStmt* parse_stmt(Parser* p)
});
}
static AstDecl* parse_decl(Parser* p)
static AstDecl* parse_decl(Parser* p, bool is_param)
{
Loc loc = p->curr.loc;
AstSpec spec = parse_decl_spec(p);
if (spec & AstSpec_Typedef) {
p->flags |= ParserFlags_ParsingTypedef;
}
ARRAY_VAR(AstDeclar*, declars);
AstDeclar* first = parse_declar(p);
ARENA_ARRAY_VAR_PUSH(p->arena, declars, &first);
if (first->ty == AstDeclar_Function && p->curr.ty == '{') {
AstStmtBlock* block = parse_stmt_block(p);
return new_decl(p,
(AstDecl) {
.spec = spec,
.declars = declars,
.declars_cap = declars_cap,
.declars_size = declars_size,
.function_body = block,
.loc = loc,
});
AstStmtBlock* function_body = nullptr;
bool multi_allowed = !is_param;
if (!is_param && first->ty == AstDeclar_Function && p->curr.ty == '{') {
function_body = parse_stmt_block(p);
multi_allowed = false;
}
while (p->curr.ty == ',') {
while (multi_allowed && p->curr.ty == ',') {
step(p);
AstDeclar* declar = parse_declar(p);
array_push((void**)&declars,
&declars_cap,
&declars_size,
(&declar),
sizeof(*(&declar)));
ARENA_ARRAY_VAR_PUSH(p->arena, declars, &declar);
}
p->flags &= ~ParserFlags_ParsingTypedef;
return new_decl(p,
(AstDecl) {
.spec = spec,
.declars = declars,
.declars_cap = declars_cap,
.declars_size = declars_size,
.function_body = nullptr,
.function_body = function_body,
.loc = loc,
});
}
@ -461,13 +432,16 @@ static AstDeclar* parse_declar_l3(Parser* p)
ARRAY_VAR(AstDecl*, params);
while (true) {
AstDecl* d = parse_decl(p);
if (p->curr.ty != Tok_Eof && p->curr.ty != ')') {
AstDecl* d = parse_decl(p, true);
ARENA_ARRAY_VAR_PUSH(p->arena, params, &d);
if (p->curr.ty != ',')
break;
step(p);
while (p->curr.ty == ',') {
step(p);
d = parse_decl(p, true);
ARENA_ARRAY_VAR_PUSH(p->arena, params, &d);
}
}
if (p->curr.ty != ')') {
@ -502,7 +476,7 @@ static AstDeclar* parse_declar_l4(Parser* p)
step(p);
return new_declar(p,
(AstDeclar) {
.ty = AstDeclar_Array,
.ty = AstDeclar_Ident,
.loc = loc,
.ident = ident,
});
@ -535,7 +509,7 @@ static AstSpec parse_decl_spec(Parser* p)
while (true) {
switch (p->curr.ty) {
case Tok_Ident: {
Sym* sym = syms_get(p->ord_ns, p->curr.text);
Sym* sym = syms_get(p->syms, p->curr.text);
if (!sym || sym->ty != Sym_Typedef)
break;
spec |= AstSpec_DefTy;
@ -580,7 +554,6 @@ static AstExpr* parse_expr_1(Parser* p)
while (true) {
if (p->curr.ty == '(') {
step(p);
ARRAY_VAR(AstExpr*, args);
@ -588,7 +561,7 @@ static AstExpr* parse_expr_1(Parser* p)
do {
step(p);
AstExpr* arg = parse_expr(p);
ARRAY_VAR_PUSH(args, &arg);
ARENA_ARRAY_VAR_PUSH(p->arena, args, &arg);
} while (p->curr.ty == ',');
}
@ -626,7 +599,7 @@ static size_t unescape_string(char* dest, const char* src)
assert(src[0] == '"' && src[src_len - 1] == '"');
src -= 1;
src += 1;
src_len -= 2;
for (size_t i = 0; i < src_len; ++i) {
@ -663,6 +636,8 @@ static size_t unescape_string(char* dest, const char* src)
dest_i += 1;
}
if (dest)
dest[dest_i] = '\0';
return dest_i;
}
@ -670,6 +645,17 @@ static AstExpr* parse_expr_2(Parser* p)
{
Loc loc = p->curr.loc;
if (p->curr.ty == Tok_Ident) {
char* ident = arena_strdup(p->arena, p->curr.text);
step(p);
return new_expr(p,
(AstExpr) {
.ty = AstExpr_Ident,
.loc = loc,
.ident = ident,
});
}
if (p->curr.ty == Tok_Str) {
size_t unescaped_len = unescape_string(nullptr, p->curr.text);
char* unescaped_str = arena_alloc(p->arena, unescaped_len + 1);

93
resolve.c Normal file
View File

@ -0,0 +1,93 @@
#include "resolve.h"
#include "ast.h"
#include "syms.h"
#include <stdio.h>
#include <stdlib.h>
struct Resolver {
Syms* ord_syms;
Syms* tag_syms;
Syms* label_syms;
bool in_typedef;
};
Resolver* resolver_new()
{
Resolver* r = malloc(sizeof(Resolver));
*r = (Resolver) {
.ord_syms = syms_new(),
.tag_syms = syms_new(),
.label_syms = syms_new(),
.in_typedef = false,
};
return r;
}
void resolver_free(Resolver* r)
{
syms_free(r->ord_syms);
syms_free(r->tag_syms);
syms_free(r->label_syms);
free(r);
}
static AstVisitorResult visit_stmt_block(AstVisitor* v, AstStmtBlock* node)
{
Resolver* r = v->op;
syms_push_scope(r->ord_syms);
ast_stmt_block_visit_body(v, node);
syms_pop_scope(r->ord_syms);
return AstVisitor_Break;
}
static AstVisitorResult visit_stmt(AstVisitor* v, AstStmt* node)
{
}
static AstVisitorResult visit_decl(AstVisitor* v, AstDecl* node)
{
Resolver* r = v->op;
}
static AstVisitorResult visit_declar(AstVisitor* v, AstDeclar* node)
{
Resolver* r = v->op;
if (node->ty == AstDeclar_Function) {
syms_push_scope(r->ord_syms);
ast_declar_visit_body(v, node);
syms_pop_scope(r->ord_syms);
return AstVisitor_Break;
}
if (node->ty == AstDeclar_Ident) { }
}
static AstVisitorResult visit_expr(AstVisitor* v, AstExpr* node)
{
}
void resolver_resolve_top_stmt(Resolver* r, AstStmt* stmt)
{
if (stmt->ty != AstStmt_Decl) {
fprintf(
stderr, "error: expected declaration on line %d\n", stmt->loc.line);
exit(1);
}
AstVisitor v = {
.visit_stmt_block = visit_stmt_block,
.visit_stmt = visit_stmt,
.visit_decl = visit_decl,
.visit_declar = visit_declar,
.visit_expr = visit_expr,
.op = r,
};
visit_stmt(&v, stmt);
}

13
resolve.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef RES_H
#define RES_H
#include "ast.h"
typedef struct Resolver Resolver;
Resolver* resolver_new();
void resolver_free(Resolver* r);
void resolver_resolve_top_stmt(Resolver* r, AstStmt* stmt);
#endif

1
syms.c
View File

@ -22,6 +22,7 @@ Syms* syms_new()
void syms_free(Syms* s)
{
free(s->maps);
free(s);
}