summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/parse-gram.y184
-rw-r--r--src/symlist.c9
-rw-r--r--src/symlist.h5
-rw-r--r--tests/regression.at4
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"
%%