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