diff options
-rw-r--r-- | src/parse-gram.y | 184 | ||||
-rw-r--r-- | src/symlist.c | 9 | ||||
-rw-r--r-- | src/symlist.h | 5 | ||||
-rw-r--r-- | tests/regression.at | 4 |
4 files changed, 138 insertions, 64 deletions
diff --git a/src/parse-gram.y b/src/parse-gram.y index 71ef183d..9970f927 100644 --- a/src/parse-gram.y +++ b/src/parse-gram.y @@ -52,7 +52,6 @@ static named_ref *current_lhs_named_ref; static symbol *current_lhs_symbol; static symbol_class current_class = unknown_sym; - static uniqstr current_type = NULL; /** Set the new current left-hand side symbol, possibly common * to several right-hand side parts of rule. @@ -201,13 +200,14 @@ %token <int> INT "integer" %printer { fprintf (yyo, "%d", $$); } <int> -%type <symbol*> id id_colon string_as_id symbol symbol.prec +%type <symbol*> id id_colon string_as_id symbol token_decl token_decl_for_prec %printer { fprintf (yyo, "%s", $$ ? $$->tag : "<NULL>"); } <symbol*> %printer { fprintf (yyo, "%s:", $$->tag); } id_colon %type <assoc> precedence_declarator -%type <symbol_list*> symbols.1 symbols.prec generic_symlist generic_symlist_item +%destructor { symbol_list_free ($$); } <symbol_list*> +%printer { symbol_list_syms_print ($$, yyo); } <symbol_list*> %type <named_ref*> named_ref.opt @@ -332,8 +332,7 @@ params: `----------------------*/ grammar_declaration: - precedence_declaration -| symbol_declaration + symbol_declaration | "%start" symbol { grammar_start_symbol_set ($2, @2); @@ -402,36 +401,29 @@ grammar_declaration: ; - - +%type <symbol_list*> nterm_decls symbol_decls symbol_decl.1 + token_decls token_decls_for_prec + token_decl.1 token_decl_for_prec.1; symbol_declaration: - "%nterm" { current_class = nterm_sym; } symbol_defs.1 + "%nterm" { current_class = nterm_sym; } nterm_decls[syms] { current_class = unknown_sym; - current_type = NULL; + symbol_list_free ($syms); } -| "%token" { current_class = token_sym; } symbol_defs.1 +| "%token" { current_class = token_sym; } token_decls[syms] { current_class = unknown_sym; - current_type = NULL; + symbol_list_free ($syms); } -| "%type" TAG symbols.1 +| "%type" symbol_decls[syms] { - for (symbol_list *list = $3; list; list = list->next) - symbol_type_set (list->content.sym, $2, @2); - symbol_list_free ($3); + symbol_list_free ($syms); } -; - -precedence_declaration: - precedence_declarator tag.opt symbols.prec[syms] +| precedence_declarator token_decls_for_prec[syms] { ++current_prec; for (symbol_list *list = $syms; list; list = list->next) - { - symbol_type_set (list->content.sym, $[tag.opt], @[tag.opt]); - symbol_precedence_set (list->content.sym, current_prec, $1, @1); - } + symbol_precedence_set (list->content.sym, current_prec, $1, @1); symbol_list_free ($syms); } ; @@ -448,32 +440,7 @@ tag.opt: | TAG { $$ = $1; } ; -/* Just like symbols.1 but accept INT for the sake of POSIX. */ -symbols.prec: - symbol.prec - { $$ = symbol_list_sym_new ($1, @1); } -| symbols.prec symbol.prec - { $$ = symbol_list_append ($1, symbol_list_sym_new ($2, @2)); } -; - -symbol.prec: - symbol[id] int.opt[num] - { - $$ = $id; - symbol_class_set ($id, token_sym, @id, false); - if (0 <= $num) - symbol_user_token_number_set ($id, $num, @num); - } -; - -/* One or more symbols to be %typed. */ -symbols.1: - symbol - { $$ = symbol_list_sym_new ($1, @1); } -| symbols.1 symbol - { $$ = symbol_list_append ($1, symbol_list_sym_new ($2, @2)); } -; - +%type <symbol_list*> generic_symlist generic_symlist_item; generic_symlist: generic_symlist_item | generic_symlist generic_symlist_item { $$ = symbol_list_append ($1, $2); } @@ -490,16 +457,50 @@ tag: | "<>" { $$ = uniqstr_new (""); } ; -/* One symbol (token or nterm depending on current_class) definition. */ -symbol_def: - TAG +/*-----------------------. +| nterm_decls (%nterm). | +`-----------------------*/ + +// A non empty list of possibly tagged symbols for %nterm. +// +// Can easily be defined like symbol_decls but restricted to ID, but +// using token_decls allows to reudce the number of rules, and also to +// make nicer error messages on "%nterm 'a'" or '%nterm FOO "foo"'. +nterm_decls: + token_decls +; + +/*-----------------------------------. +| token_decls (%token, and %nterm). | +`-----------------------------------*/ + +// A non empty list of possibly tagged symbols for %token or %nterm. +token_decls: + token_decl.1[syms] + { + $$ = $syms; + } +| TAG token_decl.1[syms] + { + $$ = symbol_list_type_set ($syms, $TAG, @TAG); + } +| token_decls TAG token_decl.1[syms] { - current_type = $1; + $$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG)); } -| id int.opt[num] string_as_id.opt[alias] +; + +// One or more symbol declarations for %token or %nterm. +token_decl.1: + token_decl { $$ = symbol_list_sym_new ($1, @1); } +| token_decl.1 token_decl { $$ = symbol_list_append ($1, symbol_list_sym_new ($2, @2)); } + +// One symbol declaration for %token or %nterm. +token_decl: + id int.opt[num] string_as_id.opt[alias] { + $$ = $id; symbol_class_set ($id, current_class, @id, true); - symbol_type_set ($id, current_type, @id); if (0 <= $num) symbol_user_token_number_set ($id, $num, @num); if ($alias) @@ -513,15 +514,74 @@ int.opt: | INT ; -/* One or more symbol definitions. */ -symbol_defs.1: - symbol_def -| symbol_defs.1 symbol_def - /* FIXME: cannot do that, results in infinite loop in LAC. -| error { yyerrok; } - */ +/*-------------------------------------. +| token_decls_for_prec (%left, etc.). | +`-------------------------------------*/ + +// A non empty list of possibly tagged tokens for precedence declaration. +// +// Similar to %token (token_decls), but in '%left FOO 1 "foo"', it treats +// FOO and "foo" as two different symbols instead of aliasing them. +token_decls_for_prec: + token_decl_for_prec.1[syms] + { + $$ = $syms; + } +| TAG token_decl_for_prec.1[syms] + { + $$ = symbol_list_type_set ($syms, $TAG, @TAG); + } +| token_decls_for_prec TAG token_decl_for_prec.1[syms] + { + $$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG)); + } +; + +// One or more token declarations for precedence declaration. +token_decl_for_prec.1: + token_decl_for_prec + { $$ = symbol_list_sym_new ($1, @1); } +| token_decl_for_prec.1 token_decl_for_prec + { $$ = symbol_list_append ($1, symbol_list_sym_new ($2, @2)); } + +// One token declaration for precedence declaration. +token_decl_for_prec: + id int.opt[num] + { + $$ = $id; + symbol_class_set ($id, token_sym, @id, false); + if (0 <= $num) + symbol_user_token_number_set ($id, $num, @num); + } +| string_as_id +; + + +/*-----------------------. +| symbol_decls (%type). | +`-----------------------*/ + +// A non empty list of typed symbols. +symbol_decls: + symbol_decl.1[syms] + { + $$ = $syms; + } +| TAG symbol_decl.1[syms] + { + $$ = symbol_list_type_set ($syms, $TAG, @TAG); + } +| symbol_decls TAG symbol_decl.1[syms] + { + $$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG)); + } ; +// One or more token declarations. +symbol_decl.1: + symbol { $$ = symbol_list_sym_new ($1, @1); } +| symbol_decl.1 symbol { $$ = symbol_list_append ($1, symbol_list_sym_new ($2, @2)); } +; /*------------------------------------------. | The grammar section: between the two %%. | diff --git a/src/symlist.c b/src/symlist.c index d7b61e24..7d9fe83f 100644 --- a/src/symlist.c +++ b/src/symlist.c @@ -81,6 +81,15 @@ symbol_list_type_new (uniqstr type_name, location loc) } +symbol_list * +symbol_list_type_set (symbol_list *syms, uniqstr type_name, location loc) +{ + for (symbol_list *l = syms; l; l = l->next) + symbol_type_set (l->content.sym, type_name, loc); + return syms; +} + + /*-----------------------------------------------------------------------. | Print this list, for which every content_type must be SYMLIST_SYMBOL. | `-----------------------------------------------------------------------*/ diff --git a/src/symlist.h b/src/symlist.h index 0bd6bd75..3fdf1710 100644 --- a/src/symlist.h +++ b/src/symlist.h @@ -103,6 +103,11 @@ symbol_list *symbol_list_sym_new (symbol *sym, location loc); /** Create a list containing \c type_name at \c loc. */ symbol_list *symbol_list_type_new (uniqstr type_name, location loc); +/** Assign the type \c type_name to all the members of \c syms. + ** \returns \c syms */ +symbol_list *symbol_list_type_set (symbol_list *syms, + uniqstr type_name, location loc); + /** Print this list. \pre For every node \c n in the list, <tt>n->content_type = diff --git a/tests/regression.at b/tests/regression.at index 1a7d777c..a49b7c13 100644 --- a/tests/regression.at +++ b/tests/regression.at @@ -1096,10 +1096,10 @@ AT_DATA_GRAMMAR([input.y], ]AT_YYERROR_DECLARE[ ]AT_YYLEX_DECLARE[ } - %define parse.error verbose +%token TK_ALIAS 3 "tok alias" %right END 0 -%left TK1 1 TK2 2 "tok alias" 3 +%left TK1 1 TK2 2 "tok alias" %% |