aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cup/ast.c71
-rw-r--r--cup/ast.h71
2 files changed, 142 insertions, 0 deletions
diff --git a/cup/ast.c b/cup/ast.c
new file mode 100644
index 0000000..2f3d94d
--- /dev/null
+++ b/cup/ast.c
@@ -0,0 +1,71 @@
+#include "ast.h"
+#include <assert.h>
+#include <stdio.h>
+
+char *data_type_to_str(DataType type)
+{
+ switch (type)
+ {
+ case TYPE_NONE: return "void";
+ case TYPE_INT: return "int";
+ default: assert(false && "Unreachable");
+ }
+}
+
+char *node_type_to_str(NodeType type)
+{
+ switch (type)
+ {
+ #define ENUM_TOKEN(t, name) case t: return name;
+ ENUM_AST_TYPES(ENUM_TOKEN)
+ #undef ENUM_TOKEN
+ default: assert(false && "Unreachable");
+ }
+}
+
+static void do_print_ast(Node *node, int depth)
+{
+ for (int i = 0; i < depth; i++) {
+ printf(" ");
+ }
+ if (node->type == AST_PROGRAM) {
+ for (int i = 0; i < node->block.num_children; i++) {
+ do_print_ast(node->block.children[i], depth);
+ }
+ } else if (node->type == AST_BLOCK) {
+ printf("{\n");
+ for (int i = 0; i < node->block.num_children; i++) {
+ do_print_ast(node->block.children[i], depth + 1);
+ }
+ for (int i = 0; i < depth; i++) {
+ printf(" ");
+ }
+ printf("}\n");
+ } else if (node->type == AST_FUNC) {
+ printf("fn %s()", node->func.name);
+ if (node->func.return_type.type != TYPE_NONE) {
+ // FIXME: Print return type properly
+ Type t = node->func.return_type;
+ printf(" -> %s", data_type_to_str(t.type));
+ for (int i = 0; i < t.indirection; i++) {
+ printf("*");
+ }
+
+ }
+ printf("\n");
+ do_print_ast(node->func.body, depth + 1);
+ } else if (node->type == AST_LITERAL) {
+ printf("(literal %d)\n", node->literal.as_int);
+ } else if (node->type == AST_RETURN) {
+ printf("return\n");
+ do_print_ast(node->unary_expr, depth + 1);
+ } else {
+ printf("(unknown)\n");
+ }
+}
+
+
+void print_ast(Node *node)
+{
+ do_print_ast(node, 0);
+} \ No newline at end of file
diff --git a/cup/ast.h b/cup/ast.h
new file mode 100644
index 0000000..6170489
--- /dev/null
+++ b/cup/ast.h
@@ -0,0 +1,71 @@
+#pragma once
+
+#include <stdbool.h>
+
+#define ENUM_AST_TYPES(F) \
+ F(OP_PLUS, "+") \
+ F(OP_MINUS, "-") \
+ F(OP_MUL, "*") \
+ F(OP_DIV, "/") \
+ F(AST_LITERAL, "literal") \
+ F(AST_RETURN, "return") \
+ F(AST_FUNC, "func") \
+ F(AST_PROGRAM, "program") \
+ F(AST_BLOCK, "block statements") \
+
+
+typedef enum {
+#define DEFINE_ENUM(name, str) name,
+ ENUM_AST_TYPES(DEFINE_ENUM)
+#undef DEFINE_ENUM
+} NodeType;
+
+char *node_type_to_str(NodeType type);
+
+typedef enum {
+ TYPE_NONE,
+ TYPE_INT,
+} DataType;
+
+char *data_type_to_str(DataType type);
+
+typedef struct {
+ DataType type;
+ // 0 = value, 1 = pointer, 2 = double pointer, ...
+ int indirection;
+} Type;
+
+typedef struct ast_node Node;
+typedef struct ast_node {
+ NodeType type;
+
+ union {
+ // Binary expr
+ struct {
+ Node *left;
+ Node *right;
+ } binary;
+ // Unary expr
+ Node *unary_expr;
+ // Function definition
+ struct {
+ char *name;
+ Type return_type;
+ Node *body;
+ // TODO: Arguments / etc?
+ } func;
+ // Block of statements
+ struct {
+ Node **children;
+ int num_children;
+ } block;
+ struct {
+ Type type;
+ union {
+ int as_int;
+ };
+ } literal;
+ };
+} Node;
+
+void print_ast(Node *node); \ No newline at end of file