diff options
author | Flavian Kaufmann <flavian@flaviankaufmann.ch> | 2025-05-22 11:32:03 +0200 |
---|---|---|
committer | Flavian Kaufmann <flavian@flaviankaufmann.ch> | 2025-05-22 11:32:03 +0200 |
commit | be21cdaa9f408535379360b401089c8e2335e818 (patch) | |
tree | c271335e930e3da3244c69503980581a340c3cf2 /src | |
parent | fba0e505aaa067d3e19849536aa0142ab6fe187d (diff) | |
download | imp-be21cdaa9f408535379360b401089c8e2335e818.tar.gz imp-be21cdaa9f408535379360b401089c8e2335e818.zip |
print ast
Diffstat (limited to 'src')
-rw-r--r-- | src/driver.c | 13 | ||||
-rw-r--r-- | src/interpreter.c | 154 |
2 files changed, 163 insertions, 4 deletions
diff --git a/src/driver.c b/src/driver.c index c9ac098..8902a55 100644 --- a/src/driver.c +++ b/src/driver.c @@ -21,17 +21,22 @@ static int interpret_file(const char *path) { int main(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "i:h")) != -1) { - switch (opt){ + while ((opt = getopt(argc, argv, "i:a:h")) != -1) { + switch (opt) { case 'i': interpret_file(optarg); return EXIT_SUCCESS; + case 'a': + print_ast_file(optarg); + return EXIT_SUCCESS; case 'h': default: fprintf(stderr, - "Usage: %s [-i program.imp]\n" + "Usage: %s [ARGS]\n" + " (no args) start REPL\n" " -i <program.imp> interpret program and exit\n" - " (no args) start REPL\n", + " -a <program.imp> print ast\n" + " -h print this message\n", argv[0]); return (opt == 'h') ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/src/interpreter.c b/src/interpreter.c index 8bcc6f4..2de5b63 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -97,6 +97,143 @@ void context_print_proc_table(Context *context) { hashmap_keys_iter_free(iter); } +void ast_print(ASTNode *node, int depth) { + int indent = depth * 2; + switch (node->type) { + case NT_SKIP: { + printf("%*sSKIP\n", indent, ""); + break; + } + case NT_ASSIGN: { + printf("%*sASSIGN %s=%d\n", indent, "", + node->u.d_assign.var->u.d_var.name, + node->u.d_assign.aexp->u.d_int.val); + break; + } + case NT_SEQ: { + ast_print(node->u.d_seq.stm1, depth); + printf("%*sSEQ\n", indent, ""); + ast_print(node->u.d_seq.stm2, depth); + break; + } + case NT_IF: { + printf("%*sIF (", indent, ""); + ast_print(node->u.d_if.bexp, 0); + printf(")\n"); + ast_print(node->u.d_if.stm1, depth + 1); + printf("%*sELSE\n", indent, ""); + ast_print(node->u.d_if.stm2, depth + 1); + break; + } + case NT_WHILE: { + printf("%*sWHILE (", indent, ""); + ast_print(node->u.d_while.bexp, 0); + printf(")\n"); + ast_print(node->u.d_while.stm, depth + 1); + break; + } + case NT_INT: { + printf("%d", node->u.d_int.val); + break; + } + case NT_VAR: { + printf("%s", node->u.d_var.name); + break; + } + case NT_AOP: { + printf("("); + ast_print(node->u.d_aop.aexp1, 0); + switch (node->u.d_aop.aop) { + case AOP_ADD: printf(" + "); break; + case AOP_SUB: printf(" - "); break; + case AOP_MUL: printf(" * "); break; + default: assert(0); + } + ast_print(node->u.d_aop.aexp2, 0); + printf(")"); + break; + } + case NT_BOP: { + printf("("); + ast_print(node->u.d_bop.bexp1, 0); + switch (node->u.d_bop.bop) { + case BOP_AND: printf(" && "); break; + case BOP_OR: printf(" || "); break; + default: assert(0); + } + ast_print(node->u.d_bop.bexp2, 0); + printf(")"); + break; + } + case NT_NOT: { + printf("!"); + ast_print(node->u.d_not.bexp, 0); + break; + } + case NT_ROP: { + printf("("); + ast_print(node->u.d_rop.aexp1, 0); + switch (node->u.d_rop.rop) { + case ROP_EQ: printf(" == "); break; + case ROP_NE: printf(" != "); break; + case ROP_LT: printf(" < "); break; + case ROP_LE: printf(" <= "); break; + case ROP_GT: printf(" > "); break; + case ROP_GE: printf(" >= "); break; + default: assert(0); + } + ast_print(node->u.d_rop.aexp2, 0); + printf(")"); + break; + } + case NT_LET: { + printf("%*sLET %s = ", indent, "", node->u.d_let.var->u.d_var.name); + ast_print(node->u.d_let.aexp, 0); + printf("\n"); + ast_print(node->u.d_let.stm, depth + 1); + break; + } + case NT_PROCDECL: { + printf("%*sPROC %s(", indent, "", node->u.d_procdecl.name); + ASTNodeList *args = node->u.d_procdecl.args; + while (args) { + printf("%s", args->node->u.d_var.name); + args = args->next; + if (args) printf(", "); + } + printf("; "); + ASTNodeList *vargs = node->u.d_procdecl.vargs; + while (vargs) { + printf("%s", vargs->node->u.d_var.name); + vargs = vargs->next; + if (vargs) printf(", "); + } + printf(")\n"); + ast_print(node->u.d_procdecl.stm, depth + 1); + break; + } + case NT_PROCCALL: { + printf("%*sCALL %s(", indent, "", node->u.d_proccall.name); + ASTNodeList *args = node->u.d_proccall.args; + while (args) { + printf("%s", args->node->u.d_var.name); + args = args->next; + if (args) printf(", "); + } + printf("; "); + ASTNodeList *vargs = node->u.d_proccall.vargs; + while (vargs) { + printf("%s", vargs->node->u.d_var.name); + vargs = vargs->next; + if (vargs) printf(", "); + } + printf(")\n"); + break; + } + default: assert(0); + } +} + static int eval_aexpr(Context *context, ASTNode *node) { switch (node->type) { case NT_INT: return node->u.d_int.val; @@ -278,4 +415,21 @@ int interp_str (Context *context, const char *str) { } yy_delete_buffer(buf); return 0; +} + +int print_ast_file (const char *path) { + yyin = fopen(path, "r"); + if (!yyin) { + return -1; + } + yyrestart(yyin); + if (yyparse()) { + ast_free(ast_root); + fclose(yyin); + return -1; + } + ast_print(ast_root, 0); + ast_free(ast_root); + fclose(yyin); + return 0; }
\ No newline at end of file |