-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathast.c
145 lines (115 loc) · 3.66 KB
/
ast.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <stdlib.h>
#include <stdio.h>
#include "ast.h"
/* Visitor */
struct seg_ast_visitor {
seg_integer_handler visit_integer;
seg_string_handler visit_string;
seg_symbol_handler visit_symbol;
seg_var_handler visit_var;
seg_methodcall_handler visit_methodcall_pre;
seg_methodcall_handler visit_methodcall_post;
seg_block_handler visit_block_pre;
seg_block_handler visit_block_post;
};
static void visit_null(void *node, void *state) { }
seg_ast_visitor seg_new_ast_visitor()
{
seg_ast_visitor visitor = malloc(sizeof(struct seg_ast_visitor));
visitor->visit_integer = (seg_integer_handler) &visit_null;
visitor->visit_string = (seg_string_handler) &visit_null;
visitor->visit_symbol = (seg_symbol_handler) &visit_null;
visitor->visit_var = (seg_var_handler) &visit_null;
visitor->visit_methodcall_pre = (seg_methodcall_handler) &visit_null;
visitor->visit_methodcall_post = (seg_methodcall_handler) &visit_null;
visitor->visit_block_pre = (seg_block_handler) &visit_null;
visitor->visit_block_post = (seg_block_handler) &visit_null;
return visitor;
}
void seg_ast_visit_integer(seg_ast_visitor visitor, seg_integer_handler visit)
{
visitor->visit_integer = visit;
}
void seg_ast_visit_string(seg_ast_visitor visitor, seg_string_handler visit)
{
visitor->visit_string = visit;
}
void seg_ast_visit_symbol(seg_ast_visitor visitor, seg_symbol_handler visit)
{
visitor->visit_symbol = visit;
}
void seg_ast_visit_methodcall(
seg_ast_visitor visitor,
seg_visit_when when,
seg_methodcall_handler visit
) {
if (when == SEG_VISIT_PRE) {
visitor->visit_methodcall_pre = visit;
} else {
visitor->visit_methodcall_post = visit;
}
}
void seg_ast_visit_var(seg_ast_visitor visitor, seg_var_handler visit)
{
visitor->visit_var = visit;
}
void seg_ast_visit_block(seg_ast_visitor visitor, seg_visit_when when, seg_block_handler visit)
{
if (when == SEG_VISIT_PRE) {
visitor->visit_block_pre = visit;
} else {
visitor->visit_block_post = visit;
}
}
static void visit_expr(seg_expr_node *root, seg_ast_visitor visitor, void *state);
static void visit_block(seg_block_node *node, seg_ast_visitor visitor, void *state)
{
(*(visitor->visit_block_pre))(node, state);
seg_expr_node *current = node->first;
while (current != NULL) {
visit_expr(current, visitor, state);
current = current->next;
}
(*(visitor->visit_block_post))(node, state);
}
/* Visitor walking function. */
static void visit_expr(seg_expr_node *root, seg_ast_visitor visitor, void *state)
{
switch(root->child_kind) {
case SEG_INTEGER:
(*(visitor->visit_integer))(&(root->child.integer), state);
break;
case SEG_STRING:
(*(visitor->visit_string))(&(root->child.string), state);
break;
case SEG_SYMBOL:
(*(visitor->visit_symbol))(&(root->child.symbol), state);
break;
case SEG_VAR:
(*(visitor->visit_var))(&(root->child.var), state);
break;
case SEG_METHODCALL:
(*(visitor->visit_methodcall_pre))(&(root->child.methodcall), state);
visit_expr(root->child.methodcall.receiver, visitor, state);
seg_arg_list *current = root->child.methodcall.args;
while (current != NULL) {
visit_expr(current->value, visitor, state);
current = current->next;
}
(*(visitor->visit_methodcall_post))(&(root->child.methodcall), state);
break;
case SEG_BLOCK:
visit_block(&(root->child.block), visitor, state);
break;
default:
fprintf(stderr, "Unexpected child_kind in expr: %d\n", root->child_kind);
}
}
void seg_ast_visit(seg_ast_visitor visitor, seg_block_node *root, void *state)
{
visit_block(root, visitor, state);
}
void seg_delete_ast_visitor(seg_ast_visitor visitor)
{
free(visitor);
}