-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathast-calc.peg
122 lines (104 loc) · 4.47 KB
/
ast-calc.peg
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
# This code is hereby placed in the public domain.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
%prefix "calc"
%value "pcc_ast_node_t *" # <-- must be set
%auxil "pcc_ast_manager_t *" # <-- must be set
%header {
#define PCC_AST_NODE_CUSTOM_DATA_DEFINED /* <-- enables node custom data */
typedef struct text_data_tag { /* <-- node custom data type */
char *text;
} pcc_ast_node_custom_data_t;
}
%source {
#include <stdio.h>
#include <string.h>
}
statement <- _ e:expression _ EOL { $$ = e; }
/ ( !EOL . )* EOL { $$ = NULL; }
expression <- e:term { $$ = e; }
term <- l:term _ '+' _ r:factor { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("+"); }
/ l:term _ '-' _ r:factor { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("-"); }
/ e:factor { $$ = e; }
factor <- l:factor _ '*' _ r:unary { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("*"); }
/ l:factor _ '/' _ r:unary { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("/"); }
/ e:unary { $$ = e; }
unary <- '+' _ e:unary { $$ = pcc_ast_node__create_1(e); $$->custom.text = strdup("+"); }
/ '-' _ e:unary { $$ = pcc_ast_node__create_1(e); $$->custom.text = strdup("-"); }
/ e:primary { $$ = e; }
primary <- < [0-9]+ > { $$ = pcc_ast_node__create_0(); $$->custom.text = strdup($1); }
/ '(' _ e:expression _ ')' { $$ = e; }
_ <- [ \t]*
EOL <- '\n' / '\r\n' / '\r' / ';'
%import "code/pcc_ast.peg" # <-- provides AST build functions
%%
void pcc_ast_node_custom_data__initialize(pcc_ast_node_custom_data_t *obj) { /* <-- must be implemented when enabling node custom data */
obj->text = NULL;
}
void pcc_ast_node_custom_data__finalize(pcc_ast_node_custom_data_t *obj) { /* <-- must be implemented when enabling node custom data */
free(obj->text);
}
static void dump_ast(const pcc_ast_node_t *obj, int depth) {
if (obj) {
switch (obj->type) {
case PCC_AST_NODE_TYPE_NULLARY:
printf("%*s%s: \"%s\"\n", 2 * depth, "", "nullary", obj->custom.text);
break;
case PCC_AST_NODE_TYPE_UNARY:
printf("%*s%s: \"%s\"\n", 2 * depth, "", "unary", obj->custom.text);
dump_ast(obj->data.unary.node, depth + 1);
break;
case PCC_AST_NODE_TYPE_BINARY:
printf("%*s%s: \"%s\"\n", 2 * depth, "", "binary", obj->custom.text);
dump_ast(obj->data.binary.node[0], depth + 1);
dump_ast(obj->data.binary.node[1], depth + 1);
break;
case PCC_AST_NODE_TYPE_TERNARY:
printf("%*s%s: \"%s\"\n", 2 * depth, "", "ternary", obj->custom.text);
dump_ast(obj->data.ternary.node[0], depth + 1);
dump_ast(obj->data.ternary.node[1], depth + 1);
dump_ast(obj->data.ternary.node[2], depth + 1);
break;
case PCC_AST_NODE_TYPE_VARIADIC:
printf("%*s%s: \"%s\"\n", 2 * depth, "", "variadic", obj->custom.text);
{
size_t i;
for (i = 0; i < obj->data.variadic.len; i++) {
dump_ast(obj->data.variadic.node[i], depth + 1);
}
}
break;
default:
printf("%*s%s: \"%s\"\n", 2 * depth, "", "(unknown)", obj->custom.text);
break;
}
}
else {
printf("%*s(null)\n", 2 * depth, "");
}
}
int main(int argc, char **argv) {
pcc_ast_manager_t mgr;
pcc_ast_manager__initialize(&mgr);
{
calc_context_t *ctx = calc_create(&mgr);
pcc_ast_node_t *ast = NULL;
while (calc_parse(ctx, &ast)) {
dump_ast(ast, 0);
pcc_ast_node__destroy(ast);
}
calc_destroy(ctx);
}
pcc_ast_manager__finalize(&mgr);
return 0;
}