Home | History | Annotate | Line # | Download | only in lib
      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