initial parse
This commit is contained in:
parent
9bf5fc06db
commit
ac95ee12b9
2
Makefile
2
Makefile
@ -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
45
ast.h
@ -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
368
ast_print.c
Normal 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
283
ast_str.c
@ -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
16
main.c
@ -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
152
parse.c
@ -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
93
resolve.c
Normal 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
13
resolve.h
Normal 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
|
||||
Loading…
x
Reference in New Issue
Block a user