tre-ast.c revision 1.1 1 1.1 agc /*
2 1.1 agc tre-ast.c - Abstract syntax tree (AST) routines
3 1.1 agc
4 1.1 agc This software is released under a BSD-style license.
5 1.1 agc See the file LICENSE for details and copyright.
6 1.1 agc
7 1.1 agc */
8 1.1 agc
9 1.1 agc #ifdef HAVE_CONFIG_H
10 1.1 agc #include <config.h>
11 1.1 agc #endif /* HAVE_CONFIG_H */
12 1.1 agc #include <assert.h>
13 1.1 agc
14 1.1 agc #include "tre-ast.h"
15 1.1 agc #include "tre-mem.h"
16 1.1 agc
17 1.1 agc tre_ast_node_t *
18 1.1 agc tre_ast_new_node(tre_mem_t mem, tre_ast_type_t type, size_t size)
19 1.1 agc {
20 1.1 agc tre_ast_node_t *node;
21 1.1 agc
22 1.1 agc node = tre_mem_calloc(mem, sizeof(*node));
23 1.1 agc if (!node)
24 1.1 agc return NULL;
25 1.1 agc node->obj = tre_mem_calloc(mem, size);
26 1.1 agc if (!node->obj)
27 1.1 agc return NULL;
28 1.1 agc node->type = type;
29 1.1 agc node->nullable = -1;
30 1.1 agc node->submatch_id = -1;
31 1.1 agc
32 1.1 agc return node;
33 1.1 agc }
34 1.1 agc
35 1.1 agc tre_ast_node_t *
36 1.1 agc tre_ast_new_literal(tre_mem_t mem, int code_min, int code_max, int position)
37 1.1 agc {
38 1.1 agc tre_ast_node_t *node;
39 1.1 agc tre_literal_t *lit;
40 1.1 agc
41 1.1 agc node = tre_ast_new_node(mem, LITERAL, sizeof(tre_literal_t));
42 1.1 agc if (!node)
43 1.1 agc return NULL;
44 1.1 agc lit = node->obj;
45 1.1 agc lit->code_min = code_min;
46 1.1 agc lit->code_max = code_max;
47 1.1 agc lit->position = position;
48 1.1 agc
49 1.1 agc return node;
50 1.1 agc }
51 1.1 agc
52 1.1 agc tre_ast_node_t *
53 1.1 agc tre_ast_new_iter(tre_mem_t mem, tre_ast_node_t *arg, int min, int max,
54 1.1 agc int minimal)
55 1.1 agc {
56 1.1 agc tre_ast_node_t *node;
57 1.1 agc tre_iteration_t *iter;
58 1.1 agc
59 1.1 agc node = tre_ast_new_node(mem, ITERATION, sizeof(tre_iteration_t));
60 1.1 agc if (!node)
61 1.1 agc return NULL;
62 1.1 agc iter = node->obj;
63 1.1 agc iter->arg = arg;
64 1.1 agc iter->min = min;
65 1.1 agc iter->max = max;
66 1.1 agc iter->minimal = minimal;
67 1.1 agc node->num_submatches = arg->num_submatches;
68 1.1 agc
69 1.1 agc return node;
70 1.1 agc }
71 1.1 agc
72 1.1 agc tre_ast_node_t *
73 1.1 agc tre_ast_new_union(tre_mem_t mem, tre_ast_node_t *left, tre_ast_node_t *right)
74 1.1 agc {
75 1.1 agc tre_ast_node_t *node;
76 1.1 agc
77 1.1 agc node = tre_ast_new_node(mem, UNION, sizeof(tre_union_t));
78 1.1 agc if (node == NULL)
79 1.1 agc return NULL;
80 1.1 agc ((tre_union_t *)node->obj)->left = left;
81 1.1 agc ((tre_union_t *)node->obj)->right = right;
82 1.1 agc node->num_submatches = left->num_submatches + right->num_submatches;
83 1.1 agc
84 1.1 agc return node;
85 1.1 agc }
86 1.1 agc
87 1.1 agc tre_ast_node_t *
88 1.1 agc tre_ast_new_catenation(tre_mem_t mem, tre_ast_node_t *left,
89 1.1 agc tre_ast_node_t *right)
90 1.1 agc {
91 1.1 agc tre_ast_node_t *node;
92 1.1 agc
93 1.1 agc node = tre_ast_new_node(mem, CATENATION, sizeof(tre_catenation_t));
94 1.1 agc if (node == NULL)
95 1.1 agc return NULL;
96 1.1 agc ((tre_catenation_t *)node->obj)->left = left;
97 1.1 agc ((tre_catenation_t *)node->obj)->right = right;
98 1.1 agc node->num_submatches = left->num_submatches + right->num_submatches;
99 1.1 agc
100 1.1 agc return node;
101 1.1 agc }
102 1.1 agc
103 1.1 agc #ifdef TRE_DEBUG
104 1.1 agc
105 1.1 agc static void
106 1.1 agc tre_findent(FILE *stream, int i)
107 1.1 agc {
108 1.1 agc while (i-- > 0)
109 1.1 agc fputc(' ', stream);
110 1.1 agc }
111 1.1 agc
112 1.1 agc void
113 1.1 agc tre_print_params(int *params)
114 1.1 agc {
115 1.1 agc int i;
116 1.1 agc if (params)
117 1.1 agc {
118 1.1 agc DPRINT(("params ["));
119 1.1 agc for (i = 0; i < TRE_PARAM_LAST; i++)
120 1.1 agc {
121 1.1 agc if (params[i] == TRE_PARAM_UNSET)
122 1.1 agc DPRINT(("unset"));
123 1.1 agc else if (params[i] == TRE_PARAM_DEFAULT)
124 1.1 agc DPRINT(("default"));
125 1.1 agc else
126 1.1 agc DPRINT(("%d", params[i]));
127 1.1 agc if (i < TRE_PARAM_LAST - 1)
128 1.1 agc DPRINT((", "));
129 1.1 agc }
130 1.1 agc DPRINT(("]"));
131 1.1 agc }
132 1.1 agc }
133 1.1 agc
134 1.1 agc static void
135 1.1 agc tre_do_print(FILE *stream, tre_ast_node_t *ast, int indent)
136 1.1 agc {
137 1.1 agc int code_min, code_max, pos;
138 1.1 agc int num_tags = ast->num_tags;
139 1.1 agc tre_literal_t *lit;
140 1.1 agc tre_iteration_t *iter;
141 1.1 agc
142 1.1 agc tre_findent(stream, indent);
143 1.1 agc switch (ast->type)
144 1.1 agc {
145 1.1 agc case LITERAL:
146 1.1 agc lit = ast->obj;
147 1.1 agc code_min = lit->code_min;
148 1.1 agc code_max = lit->code_max;
149 1.1 agc pos = lit->position;
150 1.1 agc if (IS_EMPTY(lit))
151 1.1 agc {
152 1.1 agc fprintf(stream, "literal empty\n");
153 1.1 agc }
154 1.1 agc else if (IS_ASSERTION(lit))
155 1.1 agc {
156 1.1 agc int i;
157 1.1 agc char *assertions[] = { "bol", "eol", "ctype", "!ctype",
158 1.1 agc "bow", "eow", "wb", "!wb" };
159 1.1 agc if (code_max >= ASSERT_LAST << 1)
160 1.1 agc assert(0);
161 1.1 agc fprintf(stream, "assertions: ");
162 1.1 agc for (i = 0; (1 << i) <= ASSERT_LAST; i++)
163 1.1 agc if (code_max & (1 << i))
164 1.1 agc fprintf(stream, "%s ", assertions[i]);
165 1.1 agc fprintf(stream, "\n");
166 1.1 agc }
167 1.1 agc else if (IS_TAG(lit))
168 1.1 agc {
169 1.1 agc fprintf(stream, "tag %d\n", code_max);
170 1.1 agc }
171 1.1 agc else if (IS_BACKREF(lit))
172 1.1 agc {
173 1.1 agc fprintf(stream, "backref %d, pos %d\n", code_max, pos);
174 1.1 agc }
175 1.1 agc else if (IS_PARAMETER(lit))
176 1.1 agc {
177 1.1 agc tre_print_params(lit->u.params);
178 1.1 agc fprintf(stream, "\n");
179 1.1 agc }
180 1.1 agc else
181 1.1 agc {
182 1.1 agc fprintf(stream, "literal (%c, %c) (%d, %d), pos %d, sub %d, "
183 1.1 agc "%d tags\n", code_min, code_max, code_min, code_max, pos,
184 1.1 agc ast->submatch_id, num_tags);
185 1.1 agc }
186 1.1 agc break;
187 1.1 agc case ITERATION:
188 1.1 agc iter = ast->obj;
189 1.1 agc fprintf(stream, "iteration {%d, %d}, sub %d, %d tags, %s\n",
190 1.1 agc iter->min, iter->max, ast->submatch_id, num_tags,
191 1.1 agc iter->minimal ? "minimal" : "greedy");
192 1.1 agc tre_do_print(stream, iter->arg, indent + 2);
193 1.1 agc break;
194 1.1 agc case UNION:
195 1.1 agc fprintf(stream, "union, sub %d, %d tags\n", ast->submatch_id, num_tags);
196 1.1 agc tre_do_print(stream, ((tre_union_t *)ast->obj)->left, indent + 2);
197 1.1 agc tre_do_print(stream, ((tre_union_t *)ast->obj)->right, indent + 2);
198 1.1 agc break;
199 1.1 agc case CATENATION:
200 1.1 agc fprintf(stream, "catenation, sub %d, %d tags\n", ast->submatch_id,
201 1.1 agc num_tags);
202 1.1 agc tre_do_print(stream, ((tre_catenation_t *)ast->obj)->left, indent + 2);
203 1.1 agc tre_do_print(stream, ((tre_catenation_t *)ast->obj)->right, indent + 2);
204 1.1 agc break;
205 1.1 agc default:
206 1.1 agc assert(0);
207 1.1 agc break;
208 1.1 agc }
209 1.1 agc }
210 1.1 agc
211 1.1 agc static void
212 1.1 agc tre_ast_fprint(FILE *stream, tre_ast_node_t *ast)
213 1.1 agc {
214 1.1 agc tre_do_print(stream, ast, 0);
215 1.1 agc }
216 1.1 agc
217 1.1 agc void
218 1.1 agc tre_ast_print(tre_ast_node_t *tree)
219 1.1 agc {
220 1.1 agc printf("AST:\n");
221 1.1 agc tre_ast_fprint(stdout, tree);
222 1.1 agc }
223 1.1 agc
224 1.1 agc #endif /* TRE_DEBUG */
225 1.1 agc
226 1.1 agc /* EOF */
227