370 lines
9.7 KiB
C
370 lines
9.7 KiB
C
#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]);
|
|
if (node->function_body)
|
|
ast_stmt_block_visit(v, node->function_body);
|
|
}
|
|
|
|
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->function.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;
|
|
}
|
|
}
|