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
|
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
|
#define AST_H
|
||||||
|
|
||||||
#include "collection.h"
|
#include "collection.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int line;
|
int line;
|
||||||
@ -92,6 +93,7 @@ struct AstDeclar {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
AstExpr_Ident,
|
||||||
AstExpr_Str,
|
AstExpr_Str,
|
||||||
AstExpr_Call,
|
AstExpr_Call,
|
||||||
} AstExprTy;
|
} AstExprTy;
|
||||||
@ -100,6 +102,7 @@ struct AstExpr {
|
|||||||
AstExprTy ty;
|
AstExprTy ty;
|
||||||
Loc loc;
|
Loc loc;
|
||||||
union {
|
union {
|
||||||
|
char* ident;
|
||||||
char* str_val;
|
char* str_val;
|
||||||
struct {
|
struct {
|
||||||
AstExpr* expr;
|
AstExpr* expr;
|
||||||
@ -108,17 +111,37 @@ struct AstExpr {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
void ast_stmt_block_print(FILE* f, const AstStmtBlock* node, int depth);
|
||||||
ARRAY_FIELD(char, string);
|
void ast_stmt_print(FILE* f, const AstStmt* node, int depth);
|
||||||
Arena* arena;
|
void ast_decl_print(FILE* f, const AstDecl* node, int depth);
|
||||||
int depth;
|
void ast_declar_print(FILE* f, const AstDeclar* node, int depth);
|
||||||
} AstStringifier;
|
void ast_expr_print(FILE* f, const AstExpr* node, int depth);
|
||||||
|
|
||||||
void ast_stringifier_init(AstStringifier* s, Arena* arena);
|
typedef struct AstVisitor AstVisitor;
|
||||||
void ast_stmt_block_to_string(AstStringifier* s, const AstStmtBlock* node);
|
|
||||||
void ast_stmt_to_string(AstStringifier* s, const AstStmt* node);
|
typedef enum {
|
||||||
void ast_decl_to_string(AstStringifier* s, const AstDecl* node);
|
AstVisitor_Continue,
|
||||||
void ast_declar_to_string(AstStringifier* s, const AstDeclar* node);
|
AstVisitor_Break,
|
||||||
void ast_expr_to_string(AstStringifier* s, const AstExpr* node);
|
} 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
|
#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 "ast.h"
|
||||||
#include "collection.h"
|
#include "collection.h"
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
#include "resolve.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -77,22 +78,19 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
Parser* parser = parser_new(&tokstream, &ast_arena);
|
Parser* parser = parser_new(&tokstream, &ast_arena);
|
||||||
|
|
||||||
|
Resolver* resolver = resolver_new();
|
||||||
|
|
||||||
AstStmt* stmt;
|
AstStmt* stmt;
|
||||||
while (!parser_done(parser)) {
|
while (!parser_done(parser)) {
|
||||||
stmt = parser_parse_stmt(parser);
|
stmt = parser_parse_stmt(parser);
|
||||||
|
|
||||||
Arena s_arena;
|
ast_stmt_print(stdout, stmt, 0);
|
||||||
arena_init(&s_arena, 4096);
|
|
||||||
AstStringifier s = { };
|
|
||||||
ast_stringifier_init(&s, &s_arena);
|
|
||||||
|
|
||||||
ast_stmt_to_string(&s, stmt);
|
printf("\n");
|
||||||
|
|
||||||
printf("%s\n", s.string);
|
|
||||||
|
|
||||||
arena_deinit(&s_arena);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resolver_free(resolver);
|
||||||
|
|
||||||
parser_free(parser);
|
parser_free(parser);
|
||||||
|
|
||||||
preproc_free(preproc);
|
preproc_free(preproc);
|
||||||
|
|||||||
152
parse.c
152
parse.c
@ -25,21 +25,6 @@ typedef struct {
|
|||||||
ARRAY_FIELD(KwNode, nodes);
|
ARRAY_FIELD(KwNode, nodes);
|
||||||
} KwMatcher;
|
} 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(
|
static KwNodeOpt* kwmatcher_create_path(
|
||||||
KwMatcher* m, size_t node_idx, const char* kw)
|
KwMatcher* m, size_t node_idx, const char* kw)
|
||||||
{
|
{
|
||||||
@ -60,12 +45,7 @@ static KwNodeOpt* kwmatcher_create_path(
|
|||||||
ARRAY_FIELD_INIT(opts),
|
ARRAY_FIELD_INIT(opts),
|
||||||
.idx = new_idx,
|
.idx = new_idx,
|
||||||
};
|
};
|
||||||
arena_array_push(&m->arena,
|
ARENA_ARRAY_FIELD_PUSH(&m->arena, m, nodes, &new_node);
|
||||||
(void**)&m->nodes,
|
|
||||||
&m->nodes_cap,
|
|
||||||
&m->nodes_size,
|
|
||||||
&new_node,
|
|
||||||
sizeof(new_node));
|
|
||||||
// might have been relocated
|
// might have been relocated
|
||||||
node = &m->nodes[node_idx];
|
node = &m->nodes[node_idx];
|
||||||
|
|
||||||
@ -74,12 +54,7 @@ static KwNodeOpt* kwmatcher_create_path(
|
|||||||
.is_term = false,
|
.is_term = false,
|
||||||
.val = new_idx,
|
.val = new_idx,
|
||||||
};
|
};
|
||||||
arena_array_push(&m->arena,
|
ARENA_ARRAY_FIELD_PUSH(&m->arena, node, opts, &new_opt);
|
||||||
(void**)&node->opts,
|
|
||||||
&node->opts_cap,
|
|
||||||
&node->opts_size,
|
|
||||||
&new_opt,
|
|
||||||
sizeof(new_opt));
|
|
||||||
|
|
||||||
opt = &node->opts[node->opts_size - 1];
|
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_init(&m->arena, 512);
|
||||||
|
|
||||||
arena_array_push(&m->arena,
|
ARENA_ARRAY_FIELD_PUSH(&m->arena, m, nodes, (&(KwNode) { .idx = 0 }));
|
||||||
(void**)&(m)->nodes,
|
|
||||||
&(m)->nodes_cap,
|
|
||||||
&(m)->nodes_size,
|
|
||||||
(&(KwNode) { .idx = 0 }),
|
|
||||||
sizeof(*(&(KwNode) { .idx = 0 })));
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
TokTy ty;
|
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) {
|
for (size_t i = 0; i < sizeof(kws) / sizeof(kws[0]); ++i) {
|
||||||
kwmatcher_add(m, kws[i].kw, kws[i].ty);
|
kwmatcher_add(m, kws[i].kw, kws[i].ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
kw_tree_print(m, &m->nodes[0], 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kwmatcher_deinit(KwMatcher* m)
|
static void kwmatcher_deinit(KwMatcher* m)
|
||||||
@ -165,12 +133,10 @@ static Tok kwmatcher_next(KwMatcher* m)
|
|||||||
if (tok.ty != Tok_Ident)
|
if (tok.ty != Tok_Ident)
|
||||||
goto exit;
|
goto exit;
|
||||||
TokTy ty = kwmatcher_match(m, tok.text);
|
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;
|
tok.ty = ty;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
printf(" - %s(%s) %d:%d\n",
|
printf(" - %-10s %-10s %d:%d\n",
|
||||||
tokty_str(tok.ty),
|
tokty_str(tok.ty),
|
||||||
tok.text,
|
tok.text,
|
||||||
tok.loc.line,
|
tok.loc.line,
|
||||||
@ -178,16 +144,20 @@ exit:
|
|||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef enum : unsigned int {
|
||||||
|
ParserFlags_ParsingTypedef = 1 << 0,
|
||||||
|
} ParserFlags;
|
||||||
|
|
||||||
struct Parser {
|
struct Parser {
|
||||||
KwMatcher kwmatcher;
|
KwMatcher kwmatcher;
|
||||||
Arena* arena;
|
Arena* arena;
|
||||||
Arena sym_arena;
|
Arena sym_arena;
|
||||||
|
|
||||||
Syms* ord_ns;
|
Syms* syms;
|
||||||
Syms* label_ns;
|
|
||||||
Syms* tag_ns;
|
|
||||||
|
|
||||||
Tok curr;
|
Tok curr;
|
||||||
|
|
||||||
|
ParserFlags flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser* parser_new(TokStream* tokstream, Arena* arena)
|
Parser* parser_new(TokStream* tokstream, Arena* arena)
|
||||||
@ -199,11 +169,11 @@ Parser* parser_new(TokStream* tokstream, Arena* arena)
|
|||||||
.arena = arena,
|
.arena = arena,
|
||||||
.sym_arena = { },
|
.sym_arena = { },
|
||||||
|
|
||||||
.ord_ns = syms_new(),
|
.syms = syms_new(),
|
||||||
.label_ns = syms_new(),
|
|
||||||
.tag_ns = syms_new(),
|
|
||||||
|
|
||||||
.curr = { },
|
.curr = { },
|
||||||
|
|
||||||
|
.flags = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
kwmatcher_init(&p->kwmatcher, tokstream);
|
kwmatcher_init(&p->kwmatcher, tokstream);
|
||||||
@ -215,6 +185,7 @@ Parser* parser_new(TokStream* tokstream, Arena* arena)
|
|||||||
void parser_free(Parser* p)
|
void parser_free(Parser* p)
|
||||||
{
|
{
|
||||||
kwmatcher_deinit(&p->kwmatcher);
|
kwmatcher_deinit(&p->kwmatcher);
|
||||||
|
syms_free(p->syms);
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +210,8 @@ DEFINE_NEW(AstExpr, expr)
|
|||||||
DEFINE_NEW(AstStmtBlock, stmt_block)
|
DEFINE_NEW(AstStmtBlock, stmt_block)
|
||||||
|
|
||||||
static AstStmtBlock* parse_stmt_block(Parser* p);
|
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 AstDeclar* parse_declar(Parser* p);
|
||||||
static AstSpec parse_decl_spec(Parser* p);
|
static AstSpec parse_decl_spec(Parser* p);
|
||||||
static AstExpr* parse_expr(Parser* p);
|
static AstExpr* parse_expr(Parser* p);
|
||||||
@ -248,17 +220,13 @@ static AstStmtBlock* parse_stmt_block(Parser* p)
|
|||||||
{
|
{
|
||||||
Loc loc = p->curr.loc;
|
Loc loc = p->curr.loc;
|
||||||
assert(p->curr.ty == '{');
|
assert(p->curr.ty == '{');
|
||||||
|
step(p);
|
||||||
|
|
||||||
ARRAY_VAR(AstStmt*, stmts);
|
ARRAY_VAR(AstStmt*, stmts);
|
||||||
|
|
||||||
while (p->curr.ty != Tok_Eof && p->curr.ty != '}') {
|
while (p->curr.ty != Tok_Eof && p->curr.ty != '}') {
|
||||||
AstStmt* stmt = parser_parse_stmt(p);
|
AstStmt* stmt = parse_stmt(p);
|
||||||
arena_array_push(p->arena,
|
ARENA_ARRAY_VAR_PUSH(p->arena, stmts, &stmt);
|
||||||
(void**)&stmts,
|
|
||||||
&stmts_cap,
|
|
||||||
&stmts_size,
|
|
||||||
(&stmt),
|
|
||||||
sizeof(*(&stmt)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->curr.ty != '}') {
|
if (p->curr.ty != '}') {
|
||||||
@ -292,7 +260,7 @@ static bool is_defty_ident(Parser* p, Tok tok)
|
|||||||
{
|
{
|
||||||
if (tok.ty != Tok_Ident)
|
if (tok.ty != Tok_Ident)
|
||||||
return false;
|
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;
|
return sym && sym->ty == Sym_Typedef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +269,7 @@ static AstStmt* parse_stmt(Parser* p)
|
|||||||
Loc loc = p->curr.loc;
|
Loc loc = p->curr.loc;
|
||||||
|
|
||||||
if (is_decl_start_kw(p->curr.ty) || is_defty_ident(p, p->curr)) {
|
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 != ';') {
|
if (!decl->function_body && p->curr.ty != ';') {
|
||||||
fprintf(
|
fprintf(
|
||||||
@ -320,6 +288,12 @@ static AstStmt* parse_stmt(Parser* p)
|
|||||||
|
|
||||||
AstExpr* expr = parse_expr(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,
|
return new_stmt(p,
|
||||||
(AstStmt) {
|
(AstStmt) {
|
||||||
.ty = AstStmt_Expr,
|
.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;
|
Loc loc = p->curr.loc;
|
||||||
|
|
||||||
AstSpec spec = parse_decl_spec(p);
|
AstSpec spec = parse_decl_spec(p);
|
||||||
|
|
||||||
|
if (spec & AstSpec_Typedef) {
|
||||||
|
p->flags |= ParserFlags_ParsingTypedef;
|
||||||
|
}
|
||||||
|
|
||||||
ARRAY_VAR(AstDeclar*, declars);
|
ARRAY_VAR(AstDeclar*, declars);
|
||||||
|
|
||||||
AstDeclar* first = parse_declar(p);
|
AstDeclar* first = parse_declar(p);
|
||||||
|
|
||||||
ARENA_ARRAY_VAR_PUSH(p->arena, declars, &first);
|
ARENA_ARRAY_VAR_PUSH(p->arena, declars, &first);
|
||||||
|
|
||||||
if (first->ty == AstDeclar_Function && p->curr.ty == '{') {
|
AstStmtBlock* function_body = nullptr;
|
||||||
AstStmtBlock* block = parse_stmt_block(p);
|
bool multi_allowed = !is_param;
|
||||||
return new_decl(p,
|
|
||||||
(AstDecl) {
|
if (!is_param && first->ty == AstDeclar_Function && p->curr.ty == '{') {
|
||||||
.spec = spec,
|
function_body = parse_stmt_block(p);
|
||||||
.declars = declars,
|
multi_allowed = false;
|
||||||
.declars_cap = declars_cap,
|
|
||||||
.declars_size = declars_size,
|
|
||||||
.function_body = block,
|
|
||||||
.loc = loc,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (p->curr.ty == ',') {
|
while (multi_allowed && p->curr.ty == ',') {
|
||||||
step(p);
|
step(p);
|
||||||
|
|
||||||
AstDeclar* declar = parse_declar(p);
|
AstDeclar* declar = parse_declar(p);
|
||||||
|
|
||||||
array_push((void**)&declars,
|
ARENA_ARRAY_VAR_PUSH(p->arena, declars, &declar);
|
||||||
&declars_cap,
|
|
||||||
&declars_size,
|
|
||||||
(&declar),
|
|
||||||
sizeof(*(&declar)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p->flags &= ~ParserFlags_ParsingTypedef;
|
||||||
|
|
||||||
return new_decl(p,
|
return new_decl(p,
|
||||||
(AstDecl) {
|
(AstDecl) {
|
||||||
.spec = spec,
|
.spec = spec,
|
||||||
.declars = declars,
|
.declars = declars,
|
||||||
.declars_cap = declars_cap,
|
.declars_cap = declars_cap,
|
||||||
.declars_size = declars_size,
|
.declars_size = declars_size,
|
||||||
.function_body = nullptr,
|
.function_body = function_body,
|
||||||
.loc = loc,
|
.loc = loc,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -461,13 +432,16 @@ static AstDeclar* parse_declar_l3(Parser* p)
|
|||||||
|
|
||||||
ARRAY_VAR(AstDecl*, params);
|
ARRAY_VAR(AstDecl*, params);
|
||||||
|
|
||||||
while (true) {
|
if (p->curr.ty != Tok_Eof && p->curr.ty != ')') {
|
||||||
AstDecl* d = parse_decl(p);
|
AstDecl* d = parse_decl(p, true);
|
||||||
ARENA_ARRAY_VAR_PUSH(p->arena, params, &d);
|
ARENA_ARRAY_VAR_PUSH(p->arena, params, &d);
|
||||||
|
|
||||||
if (p->curr.ty != ',')
|
while (p->curr.ty == ',') {
|
||||||
break;
|
step(p);
|
||||||
step(p);
|
|
||||||
|
d = parse_decl(p, true);
|
||||||
|
ARENA_ARRAY_VAR_PUSH(p->arena, params, &d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->curr.ty != ')') {
|
if (p->curr.ty != ')') {
|
||||||
@ -502,7 +476,7 @@ static AstDeclar* parse_declar_l4(Parser* p)
|
|||||||
step(p);
|
step(p);
|
||||||
return new_declar(p,
|
return new_declar(p,
|
||||||
(AstDeclar) {
|
(AstDeclar) {
|
||||||
.ty = AstDeclar_Array,
|
.ty = AstDeclar_Ident,
|
||||||
.loc = loc,
|
.loc = loc,
|
||||||
.ident = ident,
|
.ident = ident,
|
||||||
});
|
});
|
||||||
@ -535,7 +509,7 @@ static AstSpec parse_decl_spec(Parser* p)
|
|||||||
while (true) {
|
while (true) {
|
||||||
switch (p->curr.ty) {
|
switch (p->curr.ty) {
|
||||||
case Tok_Ident: {
|
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)
|
if (!sym || sym->ty != Sym_Typedef)
|
||||||
break;
|
break;
|
||||||
spec |= AstSpec_DefTy;
|
spec |= AstSpec_DefTy;
|
||||||
@ -580,7 +554,6 @@ static AstExpr* parse_expr_1(Parser* p)
|
|||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
if (p->curr.ty == '(') {
|
if (p->curr.ty == '(') {
|
||||||
step(p);
|
|
||||||
|
|
||||||
ARRAY_VAR(AstExpr*, args);
|
ARRAY_VAR(AstExpr*, args);
|
||||||
|
|
||||||
@ -588,7 +561,7 @@ static AstExpr* parse_expr_1(Parser* p)
|
|||||||
do {
|
do {
|
||||||
step(p);
|
step(p);
|
||||||
AstExpr* arg = parse_expr(p);
|
AstExpr* arg = parse_expr(p);
|
||||||
ARRAY_VAR_PUSH(args, &arg);
|
ARENA_ARRAY_VAR_PUSH(p->arena, args, &arg);
|
||||||
} while (p->curr.ty == ',');
|
} 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] == '"');
|
assert(src[0] == '"' && src[src_len - 1] == '"');
|
||||||
|
|
||||||
src -= 1;
|
src += 1;
|
||||||
src_len -= 2;
|
src_len -= 2;
|
||||||
|
|
||||||
for (size_t i = 0; i < src_len; ++i) {
|
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;
|
dest_i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dest)
|
||||||
|
dest[dest_i] = '\0';
|
||||||
return dest_i;
|
return dest_i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -670,6 +645,17 @@ static AstExpr* parse_expr_2(Parser* p)
|
|||||||
{
|
{
|
||||||
Loc loc = p->curr.loc;
|
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) {
|
if (p->curr.ty == Tok_Str) {
|
||||||
size_t unescaped_len = unescape_string(nullptr, p->curr.text);
|
size_t unescaped_len = unescape_string(nullptr, p->curr.text);
|
||||||
char* unescaped_str = arena_alloc(p->arena, unescaped_len + 1);
|
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