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