aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2022-04-08 08:25:48 -0300
committerBad Diode <bd@badd10de.dev>2022-04-08 08:25:48 -0300
commit55ecfb3b7713172f76ddbff022fa4d6a80d0661a (patch)
tree6a6baae20d67824d5f79b801b27f58cc967a3ba1 /src
parent9f934cbc0f0fd60a6938ac1c4c84edc270de94ca (diff)
downloadbdl-55ecfb3b7713172f76ddbff022fa4d6a80d0661a.tar.gz
bdl-55ecfb3b7713172f76ddbff022fa4d6a80d0661a.zip
Add initial implementation of AST vizualization
Diffstat (limited to 'src')
-rw-r--r--src/lexer.c72
-rw-r--r--src/main.c6
-rw-r--r--src/nodes.c3
-rw-r--r--src/nodes.h1
-rw-r--r--src/parser.c2
-rw-r--r--src/viz.c152
6 files changed, 196 insertions, 40 deletions
diff --git a/src/lexer.c b/src/lexer.c
index b4dcaf5..a6d7c74 100644
--- a/src/lexer.c
+++ b/src/lexer.c
@@ -2,42 +2,42 @@
2#include "errors.h" 2#include "errors.h"
3 3
4static const char* token_str[] = { 4static const char* token_str[] = {
5 [TOKEN_UNKNOWN] = "TOKEN_UNKNOWN", 5 [TOKEN_UNKNOWN] = "UNKNOWN",
6 [TOKEN_LPAREN] = "TOKEN_LPAREN", 6 [TOKEN_LPAREN] = "LPAREN",
7 [TOKEN_RPAREN] = "TOKEN_RPAREN", 7 [TOKEN_RPAREN] = "RPAREN",
8 [TOKEN_LSQUARE] = "TOKEN_LSQUARE", 8 [TOKEN_LSQUARE] = "LSQUARE",
9 [TOKEN_RSQUARE] = "TOKEN_RSQUARE", 9 [TOKEN_RSQUARE] = "RSQUARE",
10 [TOKEN_LCURLY] = "TOKEN_LCURLY", 10 [TOKEN_LCURLY] = "LCURLY",
11 [TOKEN_RCURLY] = "TOKEN_RCURLY", 11 [TOKEN_RCURLY] = "RCURLY",
12 [TOKEN_NUMBER] = "TOKEN_NUMBER", 12 [TOKEN_NUMBER] = "NUMBER",
13 [TOKEN_SYMBOL] = "TOKEN_SYMBOL", 13 [TOKEN_SYMBOL] = "SYMBOL",
14 [TOKEN_STRING] = "TOKEN_STRING", 14 [TOKEN_STRING] = "STRING",
15 [TOKEN_NIL] = "TOKEN_NIL", 15 [TOKEN_NIL] = "NIL",
16 [TOKEN_TRUE] = "TOKEN_TRUE", 16 [TOKEN_TRUE] = "TRUE",
17 [TOKEN_FALSE] = "TOKEN_FALSE", 17 [TOKEN_FALSE] = "FALSE",
18 [TOKEN_LAMBDA] = "TOKEN_LAMBDA", 18 [TOKEN_LAMBDA] = "LAMBDA",
19 [TOKEN_IF] = "TOKEN_IF", 19 [TOKEN_IF] = "IF",
20 [TOKEN_DEF] = "TOKEN_DEF", 20 [TOKEN_DEF] = "DEF",
21 [TOKEN_SET] = "TOKEN_SET", 21 [TOKEN_SET] = "SET",
22 [TOKEN_FUN] = "TOKEN_FUN", 22 [TOKEN_FUN] = "FUN",
23 [TOKEN_STRUCT] = "TOKEN_STRUCT", 23 [TOKEN_STRUCT] = "STRUCT",
24 [TOKEN_ADD] = "TOKEN_ADD", 24 [TOKEN_ADD] = "ADD",
25 [TOKEN_SUB] = "TOKEN_SUB", 25 [TOKEN_SUB] = "SUB",
26 [TOKEN_MUL] = "TOKEN_MUL", 26 [TOKEN_MUL] = "MUL",
27 [TOKEN_DIV] = "TOKEN_DIV", 27 [TOKEN_DIV] = "DIV",
28 [TOKEN_MOD] = "TOKEN_MOD", 28 [TOKEN_MOD] = "MOD",
29 [TOKEN_NOT] = "TOKEN_NOT", 29 [TOKEN_NOT] = "NOT",
30 [TOKEN_AND] = "TOKEN_AND", 30 [TOKEN_AND] = "AND",
31 [TOKEN_OR] = "TOKEN_OR", 31 [TOKEN_OR] = "OR",
32 [TOKEN_EQ] = "TOKEN_EQ", 32 [TOKEN_EQ] = "EQ",
33 [TOKEN_LT] = "TOKEN_LT", 33 [TOKEN_LT] = "LT",
34 [TOKEN_GT] = "TOKEN_GT", 34 [TOKEN_GT] = "GT",
35 [TOKEN_LE] = "TOKEN_LE", 35 [TOKEN_LE] = "LE",
36 [TOKEN_GE] = "TOKEN_GE", 36 [TOKEN_GE] = "GE",
37 [TOKEN_COLON] = "TOKEN_COLON", 37 [TOKEN_COLON] = "COLON",
38 [TOKEN_DOT] = "TOKEN_DOT", 38 [TOKEN_DOT] = "DOT",
39 [TOKEN_AT] = "TOKEN_AT", 39 [TOKEN_AT] = "AT",
40 [TOKEN_EOF] = "TOKEN_EOF", 40 [TOKEN_EOF] = "EOF",
41}; 41};
42 42
43typedef struct Keyword { 43typedef struct Keyword {
diff --git a/src/main.c b/src/main.c
index 961905f..a0d26d0 100644
--- a/src/main.c
+++ b/src/main.c
@@ -9,8 +9,7 @@
9#include "lexer.c" 9#include "lexer.c"
10#include "nodes.c" 10#include "nodes.c"
11#include "parser.c" 11#include "parser.c"
12// #include "ir.h" 12#include "viz.c"
13// #include "compiler.h"
14 13
15void 14void
16init(void) { 15init(void) {
@@ -29,8 +28,9 @@ process_source(const StringView *source, const char *file_name) {
29 check_errors(file_name); 28 check_errors(file_name);
30 29
31 // Parser. 30 // Parser.
32 parse(tokens); 31 ParseTree *parse_tree = parse(tokens);
33 check_errors(file_name); 32 check_errors(file_name);
33 viz_ast(parse_tree);
34} 34}
35 35
36void 36void
diff --git a/src/nodes.c b/src/nodes.c
index 5689d18..35d123a 100644
--- a/src/nodes.c
+++ b/src/nodes.c
@@ -1,10 +1,13 @@
1#include "nodes.h" 1#include "nodes.h"
2 2
3static size_t node_gen_id = 0;
4
3Node * 5Node *
4alloc_node(NodeType type) { 6alloc_node(NodeType type) {
5 // TODO: Use a bump allocator? 7 // TODO: Use a bump allocator?
6 // TODO: Free memory! 8 // TODO: Free memory!
7 Node *node = malloc(sizeof(Node)); 9 Node *node = malloc(sizeof(Node));
10 node->id = node_gen_id++;
8 node->type = type; 11 node->type = type;
9 node->line = 0; 12 node->line = 0;
10 node->col = 0; 13 node->col = 0;
diff --git a/src/nodes.h b/src/nodes.h
index 853495a..be6f7df 100644
--- a/src/nodes.h
+++ b/src/nodes.h
@@ -24,6 +24,7 @@ typedef enum TypeClass {
24} TypeClass; 24} TypeClass;
25 25
26typedef struct Node { 26typedef struct Node {
27 size_t id;
27 NodeType type; 28 NodeType type;
28 size_t line; 29 size_t line;
29 size_t col; 30 size_t col;
diff --git a/src/parser.c b/src/parser.c
index cf7aebb..0594d2c 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -54,7 +54,7 @@ parse_number(Parser *parser) {
54 if (c == '+') { 54 if (c == '+') {
55 c = sv_next(&tok.value); 55 c = sv_next(&tok.value);
56 } 56 }
57 if (c == '0') { 57 if (c == '0' && sv_peek(&tok.value) != '\0') {
58 c = sv_next(&tok.value); 58 c = sv_next(&tok.value);
59 if (c == 'x') { 59 if (c == 'x') {
60 base = 16; 60 base = 16;
diff --git a/src/viz.c b/src/viz.c
new file mode 100644
index 0000000..d409472
--- /dev/null
+++ b/src/viz.c
@@ -0,0 +1,152 @@
1static const char* node_str[] = {
2 [NODE_BUILTIN] = "BUILTIN",
3 [NODE_NUMBER] = "NUMBER",
4 [NODE_BOOL] = "BOOL",
5 [NODE_STRING] = "STRING",
6 [NODE_SYMBOL] = "SYMBOL",
7 [NODE_TYPE] = "TYPE",
8 [NODE_DEF] = "DEF",
9 [NODE_SET] = "SET",
10 [NODE_FUN] = "FUN",
11 [NODE_BLOCK] = "BLOCK",
12 [NODE_IF] = "IF",
13};
14
15void
16viz_node(Node *node) {
17 if (node == NULL) {
18 return;
19 }
20 printf("%zu [width=2.5,shape=Mrecord,label=\"", node->id);
21 printf("<top> %s -- [%4ld:%-4ld] ", node_str[node->type], node->line, node->col);
22 switch (node->type) {
23 case NODE_NUMBER: {
24 printf("| Value: ");
25 if (node->number.negative) {
26 printf("-");
27 }
28 if (node->number.fractional != 0) {
29 printf("%zu.%zu", node->number.integral, node->number.fractional);
30 } else {
31 printf("%zu", node->number.integral);
32 }
33 printf("\"];\n");
34 } break;
35 case NODE_SYMBOL:
36 case NODE_TYPE:
37 case NODE_STRING: {
38 printf(" | Value: ");
39 sv_write(&node->string);
40 printf("\"];\n");
41 } break;
42 case NODE_BOOL: {
43 printf(" | Value: ");
44 if (node->boolean) {
45 printf("true");
46 } else {
47 printf("false");
48 }
49 printf("\"];\n");
50 } break;
51 case NODE_BUILTIN: {
52 printf(" | Name: %s", token_str[node->builtin.type]);
53 printf(" | <args> Args: ");
54 printf("\"];\n");
55 size_t n_args = array_size(node->builtin.args);
56 for (size_t i = 0; i < n_args; ++i) {
57 viz_node(node->builtin.args[i]);
58 printf("%zu:args:e->%zu:top:w;\n", node->id, node->builtin.args[i]->id);
59 }
60 } break;
61 case NODE_DEF: {
62 printf(" | Name: ");
63 sv_write(&node->def.symbol->string);
64 printf(" | Type: ");
65 sv_write(&node->def.type->string);
66 printf(" | <val> Expr: ");
67 printf("\"];\n");
68 viz_node(node->def.value);
69 printf("%zu:val:e->%zu:top:w;\n", node->id, node->def.value->id);
70 } break;
71 case NODE_SET: {
72 printf(" | Name: ");
73 sv_write(&node->set.symbol->string);
74 printf(" | <val> Expr: ");
75 printf("\"];\n");
76 viz_node(node->set.value);
77 printf("%zu:val:e->%zu:top:w;\n", node->id, node->def.value->id);
78 } break;
79 case NODE_BLOCK: {
80 printf(" | <expr> Exprs: ");
81 printf("\"];\n");
82 size_t n_expr = array_size(node->block.expr);
83 for (size_t i = 0; i < n_expr; ++i) {
84 viz_node(node->block.expr[i]);
85 printf("%zu:expr:e->%zu:top:w;\n", node->id, node->block.expr[i]->id);
86 }
87 } break;
88 case NODE_IF: {
89 printf(" | <cond> Cond: ");
90 printf(" | <t> ExprTrue:");
91 if (node->ifexpr.expr_false != NULL) {
92 printf(" | <f> ExprFalse: ");
93 }
94 printf("\"];\n");
95 viz_node(node->ifexpr.cond);
96 printf("%zu:cond:e->%zu:top:w;\n", node->id, node->ifexpr.cond->id);
97 viz_node(node->ifexpr.expr_true);
98 printf("%zu:t:e->%zu:top:w;\n", node->id, node->ifexpr.expr_true->id);
99 if (node->ifexpr.expr_false != NULL) {
100 viz_node(node->ifexpr.expr_false);
101 printf("%zu:f:e->%zu:top:w;\n", node->id, node->ifexpr.expr_false->id);
102 }
103 } break;
104 case NODE_FUN: {
105 printf(" | Name: ");
106 sv_write(&node->fun.name->string);
107 printf(" | Type: ");
108 printf("(");
109 size_t n_params = array_size(node->fun.param_names);
110 for (size_t i = 0; i < n_params; ++i) {
111 printf(":");
112 sv_write(&node->fun.param_types[i]->string);
113 if (i < n_params - 1) {
114 printf(" ");
115 }
116 }
117 printf("):");
118 sv_write(&node->fun.return_type->string);
119 if (n_params > 0) {
120 printf(" | Parameters: (");
121 for (size_t i = 0; i < n_params; ++i) {
122 sv_write(&node->fun.param_names[i]->string);
123 if (i < n_params - 1) {
124 printf(" ");
125 }
126 }
127 printf(")");
128 }
129 printf(" | <bod> Body: ");
130 printf("\"];\n");
131 viz_node(node->fun.body);
132 printf("%zu:bod:e->%zu:top:w;\n", node->id, node->fun.body->id);
133 } break;
134 }
135}
136
137void
138viz_ast(ParseTree *parse_tree) {
139 printf("digraph ast {\n");
140 printf("rankdir=LR;\n");
141 printf("ranksep=\"0.95 equally\";\n");
142 printf("nodesep=\"0.5 equally\";\n");
143 printf("overlap=scale;\n");
144 for (size_t i = 0; i < array_size(parse_tree->roots); ++i) {
145 printf("subgraph %zu {\n", i);
146 Node *root = parse_tree->roots[array_size(parse_tree->roots) - 1 - i];
147 viz_node(root);
148 printf("}\n");
149 }
150 printf("}\n");
151}
152