/* $Id: u.y,v 1.10 2003/11/13 20:16:37 hal Exp $ */ /* semantic tag gives 4 shift/reduce conflicts (but bison reports 3) */ /* also rtbrace, rtbracket, ... */ /* then we have { # obj ... */ /* bison -d -v u.y -> y.output, u.tab.h, u.tab.c */ %expect 6 %pure_parser %{ /* C declarations - defines and includes */ /* XXX fixme - memory leak on parse errors */ /* XXX fixme - malloc failure on new_ubf_* */ #define YYERROR_VERBOSE 1 #define YYPARSE_PARAM param #include #include #include #include "ubf_a.h" void yyerror (const char *s); #define YYSTYPE ubfa_term_t static ubfa_list_node_t * ul_new; %} /* bison declarations */ %token INTEGER %token CONSTANT %token STRING %token BIN_DATA %token SEM_TAG %token DONE %% /* grammar rules and actions */ object : term '$' { (*(ubfa_term_t **)param) = new_ubfa_term($1.t); *(*(ubfa_term_t **)param) = $1; return 0; } | '$' { (*(ubfa_term_t **)param) = new_ubfa_empty(); return 0; } | DONE { return -1; } prim : INTEGER | CONSTANT | STRING | binary term : prim sem_tag { $$ = $1; if($2.t == ubfa_tag) { $$.g = $2.d.buf; }} | tuple | list { ubfprintf(("parsed list\n")); } sem_tag : /* empty */ { $$.t = ubfa_empty; } | SEM_TAG { $$ = $1; ubfprintf(("bison SEM_TAG\n")); } binary : INTEGER BIN_DATA { $$.t = ubfa_binary; $$.d.buf = $2.d.buf; $$.len = $1.d.i; $$.g = NULL; /* XXX check that $1.d.i == $2.len */ } terms : /* empty */ { $$.t = ubfa_struct; $$.len = 0; $$.d.list.first = NULL; $$.d.list.last = NULL; } | terms term { /* first nonterminal is a possibly empty list */ /* append second nonterminal to first */ $$ = $1; $$.len = $1.len + 1; /* get a new list node (contains a term) from heap */ ul_new = new_ubfa_list_node(); ul_new->term = $2; if ($1.len == 0) { /* special case - first term added to struct */ $$.d.list.first = ul_new; ul_new->prev = NULL; } else { /* append a term after there is at least one */ ul_new->prev = $$.d.list.last; $$.d.list.last->next = ul_new; } ul_new->next = NULL; $$.d.list.last = ul_new; } tuple : '{' terms '}' { $$ = $2; } terml : /* empty */ { $$.t = ubfa_list; $$.len = 0; $$.d.list.first = NULL; $$.d.list.last = NULL; } | terml term '&' { /* first nonterminal is a possibly empty list */ /* prepend second nonterminal to first */ $$ = $1; $$.len = $1.len + 1; /* get a new list node (contains a term) from heap */ ul_new = new_ubfa_list_node(); ul_new->term = $2; if ($1.len == 0) { /* special case - first term added to list */ $$.d.list.last = ul_new; ul_new->next = NULL; } else { /* prepend a term after there is at least one */ ul_new->next = $$.d.list.first; $$.d.list.first->prev = ul_new; } ul_new->prev = NULL; $$.d.list.first = ul_new; } list : '[' terms ']' { $$ = $2; $$.t = ubfa_list; } | '#' terml { $$ = $2; } %% /* additional C code */ void yyerror (const char *s) /* Called by yyparse on error */ { ubfprintf (("%s\n", s)); }