]> git.saurik.com Git - bison.git/commitdiff
Extract the parsing of user actions from the grammar scanner.
authorAkim Demaille <akim@epita.fr>
Tue, 6 Jun 2006 16:40:06 +0000 (16:40 +0000)
committerAkim Demaille <akim@epita.fr>
Tue, 6 Jun 2006 16:40:06 +0000 (16:40 +0000)
As a consequence, the relation between the grammar scanner and
parser is much simpler.  We can also split "composite tokens" back
into simple tokens.
* src/gram.h (ITEM_NUMBER_MAX, RULE_NUMBER_MAX): New.
* src/scan-gram.l (add_column_width, adjust_location): Move to and
rename as...
* src/location.h, src/location.c (add_column_width)
(location_compute): these.
Fix the column count: the initial column is 0.
(location_print): Be robust to ending column being 0.
* src/location.h (boundary_set): New.
* src/main.c: Adjust to scanner_free being renamed as
gram_scanner_free.
* src/output.c: Include scan-code.h.
* src/parse-gram.y: Include scan-gram.h and scan-code.h.
Use boundary_set.
(PERCENT_DESTRUCTOR, PERCENT_PRINTER, PERCENT_INITIAL_ACTION)
(PERCENT_LEX_PARAM, PERCENT_PARSE_PARAM): Remove the {...} part,
which is now, again, a separate token.
Adjust all dependencies.
Whereever actions with $ and @ are used, use translate_code.
(action): Remove this nonterminal which is now useless.
* src/reader.c: Include assert.h, scan-gram.h and scan-code.h.
(grammar_current_rule_action_append): Use translate_code.
(packgram): Bound check ruleno, itemno, and rule_length.
* src/reader.h (gram_in, gram__flex_debug, scanner_cursor)
(last_string, last_braced_code_loc, max_left_semantic_context)
(scanner_initialize, scanner_free, scanner_last_string_free)
(gram_out, gram_lineno, YY_DECL_): Move to...
* src/scan-gram.h: this new file.
(YY_DECL): Rename as...
(GRAM_DECL): this.
* src/scan-code.h, src/scan-code.l, src/scan-code-c.c: New.
* src/scan-gram.l (gram_get_lineno, gram_get_in, gram_get_out):
(gram_get_leng, gram_get_text, gram_set_lineno, gram_set_in):
(gram_set_out, gram_get_debug, gram_set_debug, gram_lex_destroy):
Move these declarations, and...
(obstack_for_string, STRING_GROW, STRING_FINISH, STRING_FREE):
these to...
* src/flex-scanner.h: this new file.
* src/scan-gram.l (rule_length, rule_length_overflow)
(increment_rule_length): Remove.
(last_braced_code_loc): Rename as...
(gram_last_braced_code_loc): this.
Adjust to the changes of the parser.
Move all the handling of $ and @ into...
* src/scan-code.l: here.
* src/scan-gram.l (handle_dollar, handle_at): Remove.
(handle_action_dollar, handle_action_at): Move to...
* src/scan-code.l: here.
* src/Makefile.am (bison_SOURCES): Add flex-scanner.h,
scan-code.h, scan-code-c.c, scan-gram.h.
(EXTRA_bison_SOURCES): Add scan-code.l.
(BUILT_SOURCES): Add scan-code.c.
(yacc): Be robust to white spaces.
* tests/conflicts.at, tests/input.at, tests/reduce.at,
* tests/regression.at: Adjust the column numbers.
* tests/regression.at: Adjust the error message.

21 files changed:
ChangeLog
src/Makefile.am
src/gram.h
src/location.c
src/location.h
src/main.c
src/output.c
src/parse-gram.c
src/parse-gram.h
src/parse-gram.y
src/reader.c
src/reader.h
src/scan-action.l [new file with mode: 0644]
src/scan-code-c.c [new file with mode: 0644]
src/scan-code.h [new file with mode: 0644]
src/scan-code.l [new file with mode: 0644]
src/scan-gram.h [new file with mode: 0644]
src/scan-gram.l
src/system.h
tests/input.at
tests/regression.at

index 511d1799e421184d24b6ca3828e94a417e7deda6..143fd8be8ca0e8511db4f9e17f8a3750ee2e861f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,65 @@
-$Id$
+2006-06-06  Akim Demaille  <akim@epita.fr>
+
+       Extract the parsing of user actions from the grammar scanner.
+       As a consequence, the relation between the grammar scanner and
+       parser is much simpler.  We can also split "composite tokens" back
+       into simple tokens.
+       * src/gram.h (ITEM_NUMBER_MAX, RULE_NUMBER_MAX): New.
+       * src/scan-gram.l (add_column_width, adjust_location): Move to and
+       rename as...
+       * src/location.h, src/location.c (add_column_width)
+       (location_compute): these.
+       Fix the column count: the initial column is 0.
+       (location_print): Be robust to ending column being 0.
+       * src/location.h (boundary_set): New.
+       * src/main.c: Adjust to scanner_free being renamed as
+       gram_scanner_free.
+       * src/output.c: Include scan-code.h.
+       * src/parse-gram.y: Include scan-gram.h and scan-code.h.
+       Use boundary_set.
+       (PERCENT_DESTRUCTOR, PERCENT_PRINTER, PERCENT_INITIAL_ACTION)
+       (PERCENT_LEX_PARAM, PERCENT_PARSE_PARAM): Remove the {...} part,
+       which is now, again, a separate token.
+       Adjust all dependencies.
+       Whereever actions with $ and @ are used, use translate_code.
+       (action): Remove this nonterminal which is now useless.
+       * src/reader.c: Include assert.h, scan-gram.h and scan-code.h.
+       (grammar_current_rule_action_append): Use translate_code.
+       (packgram): Bound check ruleno, itemno, and rule_length.
+       * src/reader.h (gram_in, gram__flex_debug, scanner_cursor)
+       (last_string, last_braced_code_loc, max_left_semantic_context)
+       (scanner_initialize, scanner_free, scanner_last_string_free)
+       (gram_out, gram_lineno, YY_DECL_): Move to...
+       * src/scan-gram.h: this new file.
+       (YY_DECL): Rename as...
+       (GRAM_DECL): this.
+       * src/scan-code.h, src/scan-code.l, src/scan-code-c.c: New.
+       * src/scan-gram.l (gram_get_lineno, gram_get_in, gram_get_out):
+       (gram_get_leng, gram_get_text, gram_set_lineno, gram_set_in):
+       (gram_set_out, gram_get_debug, gram_set_debug, gram_lex_destroy):
+       Move these declarations, and...
+       (obstack_for_string, STRING_GROW, STRING_FINISH, STRING_FREE):
+       these to...
+       * src/flex-scanner.h: this new file.
+       * src/scan-gram.l (rule_length, rule_length_overflow)
+       (increment_rule_length): Remove.
+       (last_braced_code_loc): Rename as...
+       (gram_last_braced_code_loc): this.
+       Adjust to the changes of the parser.
+       Move all the handling of $ and @ into...
+       * src/scan-code.l: here.
+       * src/scan-gram.l (handle_dollar, handle_at): Remove.
+       (handle_action_dollar, handle_action_at): Move to...
+       * src/scan-code.l: here.
+       * src/Makefile.am (bison_SOURCES): Add flex-scanner.h,
+       scan-code.h, scan-code-c.c, scan-gram.h.
+       (EXTRA_bison_SOURCES): Add scan-code.l.
+       (BUILT_SOURCES): Add scan-code.c.
+       (yacc): Be robust to white spaces.
+
+       * tests/conflicts.at, tests/input.at, tests/reduce.at,
+       * tests/regression.at: Adjust the column numbers.
+       * tests/regression.at: Adjust the error message.
 
 2006-06-06  Joel E. Denny  <jdenny@ces.clemson.edu>
 
 
 2006-06-06  Joel E. Denny  <jdenny@ces.clemson.edu>
 
@@ -16057,3 +16118,5 @@ $Id$
        Copying and distribution of this file, with or without
        modification, are permitted provided the copyright notice and this
        notice are preserved.
        Copying and distribution of this file, with or without
        modification, are permitted provided the copyright notice and this
        notice are preserved.
+
+$Id$
index fd148f1034d5b3316d66366d3251840473c89821..7f3369227bc9ebd4ef8f95853949e1a074987ef4 100644 (file)
@@ -1,4 +1,4 @@
-## Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+## Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 ## This program is free software; you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
 
 ## This program is free software; you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -39,6 +39,7 @@ bison_SOURCES =                                         \
        conflicts.c conflicts.h                   \
        derives.c derives.h                       \
        files.c files.h                           \
        conflicts.c conflicts.h                   \
        derives.c derives.h                       \
        files.c files.h                           \
+       flex-scanner.h                            \
        getargs.c getargs.h                       \
        gram.c gram.h                             \
        lalr.h lalr.c                             \
        getargs.c getargs.h                       \
        gram.c gram.h                             \
        lalr.h lalr.c                             \
@@ -54,8 +55,9 @@ bison_SOURCES =                                         \
        reduce.c reduce.h                         \
        revision.c revision.h                     \
        relation.c relation.h                     \
        reduce.c reduce.h                         \
        revision.c revision.h                     \
        relation.c relation.h                     \
-       scan-gram-c.c                             \
-       scan-skel-c.c scan-skel.h                 \
+       scan-code.h scan-code-c.c                 \
+       scan-gram.h scan-gram-c.c                 \
+       scan-skel.h scan-skel-c.c                 \
        state.c state.h                           \
        symlist.c symlist.h                       \
        symtab.c symtab.h                         \
        state.c state.h                           \
        symlist.c symlist.h                       \
        symtab.c symtab.h                         \
@@ -65,15 +67,20 @@ bison_SOURCES =                                       \
        vcg.c vcg.h                               \
        vcg_defaults.h
 
        vcg.c vcg.h                               \
        vcg_defaults.h
 
-EXTRA_bison_SOURCES = scan-skel.l scan-gram.l
+EXTRA_bison_SOURCES = scan-code.l scan-skel.l scan-gram.l
 
 
-BUILT_SOURCES = revision.c scan-skel.c scan-gram.c parse-gram.c parse-gram.h
+BUILT_SOURCES =                                        \
+parse-gram.c parse-gram.h                      \
+revision.c                                     \
+scan-code.c                                    \
+scan-skel.c                                    \
+scan-gram.c                                    \
 
 MOSTLYCLEANFILES = yacc
 
 yacc:
        echo '#! /bin/sh' >$@
 
 MOSTLYCLEANFILES = yacc
 
 yacc:
        echo '#! /bin/sh' >$@
-       echo 'exec $(bindir)/bison -y "$$@"' >>$@
+       echo "exec '$(bindir)/bison' -y \"$$@\"" >>$@
        chmod a+x $@
 
 echo:
        chmod a+x $@
 
 echo:
index b8f316a03945546fa2c6c63267bef98c7e08517d..3b742d565e8be947365dccc14b6561b140bd5c3b 100644 (file)
@@ -1,6 +1,6 @@
 /* Data definitions for internal representation of Bison's input.
 
 /* Data definitions for internal representation of Bison's input.
 
-   Copyright (C) 1984, 1986, 1989, 1992, 2001, 2002, 2003, 2004, 2005
+   Copyright (C) 1984, 1986, 1989, 1992, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
    Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
@@ -115,6 +115,7 @@ extern int ntokens;
 extern int nvars;
 
 typedef int item_number;
 extern int nvars;
 
 typedef int item_number;
+#define ITEM_NUMBER_MAX INT_MAX
 extern item_number *ritem;
 extern unsigned int nritems;
 
 extern item_number *ritem;
 extern unsigned int nritems;
 
@@ -146,6 +147,7 @@ item_number_is_symbol_number (item_number i)
 
 /* Rule numbers.  */
 typedef int rule_number;
 
 /* Rule numbers.  */
 typedef int rule_number;
+#define RULE_NUMBER_MAX INT_MAX
 extern rule_number nrules;
 
 static inline item_number
 extern rule_number nrules;
 
 static inline item_number
index ecd3658b14cb42de74548343c004b878388fa1ac..2213f8104875c3504d0052a85920db53957f9f1c 100644 (file)
@@ -1,6 +1,5 @@
 /* Locations for Bison
 /* Locations for Bison
-
-   Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
 location const empty_location;
 
 
 location const empty_location;
 
+/* If BUF is null, add BUFSIZE (which in this case must be less than
+   INT_MAX) to COLUMN; otherwise, add mbsnwidth (BUF, BUFSIZE, 0) to
+   COLUMN.  If an overflow occurs, or might occur but is undetectable,
+   return INT_MAX.  Assume COLUMN is nonnegative.  */
+
+static inline int
+add_column_width (int column, char const *buf, size_t bufsize)
+{
+  size_t width;
+  unsigned int remaining_columns = INT_MAX - column;
+
+  if (buf)
+    {
+      if (INT_MAX / 2 <= bufsize)
+       return INT_MAX;
+      width = mbsnwidth (buf, bufsize, 0);
+    }
+  else
+    width = bufsize;
+
+  return width <= remaining_columns ? column + width : INT_MAX;
+}
+
+/* Set *LOC and adjust scanner cursor to account for token TOKEN of
+   size SIZE.  */
+
+void
+location_compute (location *loc, boundary *cur, char const *token, size_t size)
+{
+  int line = cur->line;
+  int column = cur->column;
+  char const *p0 = token;
+  char const *p = token;
+  char const *lim = token + size;
+
+  loc->start = *cur;
+
+  for (p = token; p < lim; p++)
+    switch (*p)
+      {
+      case '\n':
+       line += line < INT_MAX;
+       column = 1;
+       p0 = p + 1;
+       break;
+
+      case '\t':
+       column = add_column_width (column, p0, p - p0);
+       column = add_column_width (column, NULL, 8 - ((column - 1) & 7));
+       p0 = p + 1;
+       break;
+
+      default:
+       break;
+      }
+
+  cur->line = line;
+  cur->column = column = add_column_width (column, p0, p - p0);
+
+  loc->end = *cur;
+
+  if (line == INT_MAX && loc->start.line != INT_MAX)
+    warn_at (*loc, _("line number overflow"));
+  if (column == INT_MAX && loc->start.column != INT_MAX)
+    warn_at (*loc, _("column number overflow"));
+}
+
+
 /* Output to OUT the location LOC.
    Warning: it uses quotearg's slot 3.  */
 void
 location_print (FILE *out, location loc)
 {
 /* Output to OUT the location LOC.
    Warning: it uses quotearg's slot 3.  */
 void
 location_print (FILE *out, location loc)
 {
+  int end_col = 0 < loc.end.column ? loc.end.column - 1 : 0;
   fprintf (out, "%s:%d.%d",
           quotearg_n_style (3, escape_quoting_style, loc.start.file),
           loc.start.line, loc.start.column);
   fprintf (out, "%s:%d.%d",
           quotearg_n_style (3, escape_quoting_style, loc.start.file),
           loc.start.line, loc.start.column);
@@ -40,9 +108,9 @@ location_print (FILE *out, location loc)
   if (loc.start.file != loc.end.file)
     fprintf (out, "-%s:%d.%d",
             quotearg_n_style (3, escape_quoting_style, loc.end.file),
   if (loc.start.file != loc.end.file)
     fprintf (out, "-%s:%d.%d",
             quotearg_n_style (3, escape_quoting_style, loc.end.file),
-            loc.end.line, loc.end.column - 1);
+            loc.end.line, end_col);
   else if (loc.start.line < loc.end.line)
   else if (loc.start.line < loc.end.line)
-    fprintf (out, "-%d.%d", loc.end.line, loc.end.column - 1);
-  else if (loc.start.column < loc.end.column - 1)
-    fprintf (out, "-%d", loc.end.column - 1);
+    fprintf (out, "-%d.%d", loc.end.line, end_col);
+  else if (loc.start.column < end_col)
+    fprintf (out, "-%d", end_col);
 }
 }
index 49d2a2edfae801305872808c5fd72257b09ab68e..542c632057276b29dd646fc40db7efd85ca47247 100644 (file)
@@ -40,6 +40,15 @@ typedef struct
 
 } boundary;
 
 
 } boundary;
 
+/* Set the position of \a a. */
+static inline void
+boundary_set (boundary *b, const char *f, int l, int c)
+{
+  b->file = f; 
+  b->line = l;         
+  b->column = c;               
+}
+
 /* Return nonzero if A and B are equal boundaries.  */
 static inline bool
 equal_boundaries (boundary a, boundary b)
 /* Return nonzero if A and B are equal boundaries.  */
 static inline bool
 equal_boundaries (boundary a, boundary b)
@@ -64,6 +73,11 @@ typedef struct
 
 extern location const empty_location;
 
 
 extern location const empty_location;
 
+/* Set *LOC and adjust scanner cursor to account for token TOKEN of
+   size SIZE.  */
+void location_compute (location *loc,
+                      boundary *cur, char const *token, size_t size);
+
 void location_print (FILE *out, location loc);
 
 #endif /* ! defined LOCATION_H_ */
 void location_print (FILE *out, location loc);
 
 #endif /* ! defined LOCATION_H_ */
index 8769fef8aa0ae2ab95b300a2da2d9aac8fffaca4..4d7fd3319085bdf3c1d1f477393482c3d6511f22 100644 (file)
@@ -1,6 +1,7 @@
 /* Top level entry point of Bison.
 
 /* Top level entry point of Bison.
 
-   Copyright (C) 1984, 1986, 1989, 1992, 1995, 2000, 2001, 2002, 2004, 2005
+   Copyright (C) 1984, 1986, 1989, 1992, 1995, 2000, 2001, 2002, 2004, 2005,
+   2006
    Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
    Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
@@ -169,7 +170,7 @@ main (int argc, char *argv[])
 
   /* The scanner memory cannot be released right after parsing, as it
      contains things such as user actions, prologue, epilogue etc.  */
 
   /* The scanner memory cannot be released right after parsing, as it
      contains things such as user actions, prologue, epilogue etc.  */
-  scanner_free ();
+  gram_scanner_free ();
   muscle_free ();
   uniqstrs_free ();
   timevar_pop (TV_FREE);
   muscle_free ();
   uniqstrs_free ();
   timevar_pop (TV_FREE);
index 6a02bb3306ef42b69b16f3fdba0defa3a69df323..1391959a4367e81a86907a9bb22f2fab3e067b86 100644 (file)
@@ -36,6 +36,7 @@
 #include "muscle_tab.h"
 #include "output.h"
 #include "reader.h"
 #include "muscle_tab.h"
 #include "output.h"
 #include "reader.h"
+#include "scan-code.h"    /* max_left_semantic_context */
 #include "scan-skel.h"
 #include "symtab.h"
 #include "tables.h"
 #include "scan-skel.h"
 #include "symtab.h"
 #include "tables.h"
index 2b77f3eafa7d0d427b4811d28be3b4357fec9942..00c39a5f7e522cda2ab7b4eeb67170b910579eca 100644 (file)
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 2.2a.  */
+/* A Bison parser, made by GNU Bison 2.1b.  */
 
 /* Skeleton implementation for Bison's Yacc-like parsers in C
 
 
 /* Skeleton implementation for Bison's Yacc-like parsers in C
 
@@ -47,7 +47,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.2a"
+#define YYBISON_VERSION "2.1b"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
 
 
 /* Copy the first part of user declarations.  */
 
 
 /* Copy the first part of user declarations.  */
-#line 1 "parse-gram.y"
+#line 1 "../../src/parse-gram.y"
 /* Bison Grammar Parser                             -*- C -*-
 
    Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 /* Bison Grammar Parser                             -*- C -*-
 
    Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 #include "quotearg.h"
 #include "reader.h"
 #include "symlist.h"
 #include "quotearg.h"
 #include "reader.h"
 #include "symlist.h"
+#include "scan-gram.h"
+#include "scan-code.h"
 #include "strverscmp.h"
 
 #define YYLLOC_DEFAULT(Current, Rhs, N)  (Current) = lloc_default (Rhs, N)
 #include "strverscmp.h"
 
 #define YYLLOC_DEFAULT(Current, Rhs, N)  (Current) = lloc_default (Rhs, N)
@@ -276,7 +278,7 @@ static int current_prec = 0;
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-#line 94 "parse-gram.y"
+#line 95 "../../src/parse-gram.y"
 {
   symbol *symbol;
   symbol_list *list;
 {
   symbol *symbol;
   symbol_list *list;
@@ -286,7 +288,7 @@ typedef union YYSTYPE
   uniqstr uniqstr;
 }
 /* Line 193 of yacc.c.  */
   uniqstr uniqstr;
 }
 /* Line 193 of yacc.c.  */
-#line 290 "parse-gram.c"
+#line 292 "../../src/parse-gram.c"
        YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
        YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
@@ -311,7 +313,7 @@ typedef struct YYLTYPE
 
 
 /* Line 216 of yacc.c.  */
 
 
 /* Line 216 of yacc.c.  */
-#line 315 "parse-gram.c"
+#line 317 "../../src/parse-gram.c"
 
 #ifdef short
 # undef short
 
 #ifdef short
 # undef short
@@ -528,16 +530,16 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  3
 /* YYLAST -- Last index in YYTABLE.  */
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  3
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   161
+#define YYLAST   164
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  52
 /* YYNNTS -- Number of nonterminals.  */
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  52
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  26
+#define YYNNTS  24
 /* YYNRULES -- Number of rules.  */
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  82
+#define YYNRULES  80
 /* YYNRULES -- Number of states.  */
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  111
+#define YYNSTATES  114
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
@@ -588,54 +590,54 @@ static const yytype_uint8 yytranslate[] =
 static const yytype_uint8 yyprhs[] =
 {
        0,     0,     3,     8,     9,    12,    14,    16,    18,    21,
 static const yytype_uint8 yyprhs[] =
 {
        0,     0,     3,     8,     9,    12,    14,    16,    18,    21,
-      25,    27,    29,    32,    35,    39,    41,    43,    45,    47,
-      51,    53,    55,    59,    61,    63,    66,    69,    71,    73,
-      75,    77,    79,    81,    84,    86,    89,    92,    94,    96,
-      97,   101,   102,   106,   110,   114,   116,   118,   120,   121,
-     123,   125,   128,   130,   132,   135,   138,   142,   144,   147,
-     149,   152,   154,   157,   160,   161,   165,   167,   171,   174,
-     175,   178,   181,   185,   189,   193,   195,   197,   198,   201,
-     203,   205,   206
+      25,    27,    29,    32,    35,    39,    41,    44,    47,    49,
+      53,    55,    57,    61,    64,    66,    69,    72,    74,    76,
+      78,    80,    82,    84,    87,    89,    93,    97,    99,   101,
+     102,   106,   107,   111,   115,   119,   121,   123,   125,   126,
+     128,   130,   133,   135,   137,   140,   143,   147,   149,   152,
+     154,   157,   159,   162,   165,   166,   170,   172,   176,   179,
+     180,   183,   186,   190,   194,   198,   200,   202,   204,   206,
+     207
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      53,     0,    -1,    54,    48,    66,    77,    -1,    -1,    54,
-      55,    -1,    56,    -1,    49,    -1,    17,    -1,    19,    76,
-      -1,    19,    76,    76,    -1,    20,    -1,    21,    -1,    22,
-       4,    -1,    23,     4,    -1,    24,    43,    76,    -1,    25,
-      -1,    26,    -1,    27,    -1,    28,    -1,    29,    43,    76,
-      -1,    31,    -1,    32,    -1,    33,    43,    76,    -1,    34,
-      -1,    35,    -1,    36,    76,    -1,    37,    76,    -1,    39,
-      -1,    40,    -1,    41,    -1,    44,    -1,    60,    -1,    57,
-      -1,    38,    72,    -1,    10,    -1,     8,    63,    -1,     9,
-      63,    -1,    18,    -1,    30,    -1,    -1,     6,    58,    65,
-      -1,    -1,     5,    59,    65,    -1,     7,    42,    63,    -1,
-      61,    62,    63,    -1,    11,    -1,    12,    -1,    13,    -1,
-      -1,    42,    -1,    72,    -1,    63,    72,    -1,    42,    -1,
-      46,    -1,    46,     4,    -1,    46,    75,    -1,    46,     4,
-      75,    -1,    64,    -1,    65,    64,    -1,    67,    -1,    66,
-      67,    -1,    68,    -1,    56,    44,    -1,     1,    44,    -1,
-      -1,    47,    69,    70,    -1,    71,    -1,    70,    45,    71,
-      -1,    70,    44,    -1,    -1,    71,    72,    -1,    71,    73,
-      -1,    71,    14,    72,    -1,    71,    15,     4,    -1,    71,
-      16,    42,    -1,    46,    -1,    75,    -1,    -1,    74,    51,
-      -1,     3,    -1,     3,    -1,    -1,    48,    50,    -1
+      53,     0,    -1,    54,    48,    66,    75,    -1,    -1,    54,
+      55,    -1,    56,    -1,    49,    -1,    17,    -1,    19,    74,
+      -1,    19,    74,    74,    -1,    20,    -1,    21,    -1,    22,
+       4,    -1,    23,     4,    -1,    24,    43,    74,    -1,    25,
+      -1,    26,    51,    -1,    27,    51,    -1,    28,    -1,    29,
+      43,    74,    -1,    31,    -1,    32,    -1,    33,    43,    74,
+      -1,    34,    51,    -1,    35,    -1,    36,    74,    -1,    37,
+      74,    -1,    39,    -1,    40,    -1,    41,    -1,    44,    -1,
+      60,    -1,    57,    -1,    38,    72,    -1,    10,    -1,     8,
+      51,    63,    -1,     9,    51,    63,    -1,    18,    -1,    30,
+      -1,    -1,     6,    58,    65,    -1,    -1,     5,    59,    65,
+      -1,     7,    42,    63,    -1,    61,    62,    63,    -1,    11,
+      -1,    12,    -1,    13,    -1,    -1,    42,    -1,    72,    -1,
+      63,    72,    -1,    42,    -1,    46,    -1,    46,     4,    -1,
+      46,    73,    -1,    46,     4,    73,    -1,    64,    -1,    65,
+      64,    -1,    67,    -1,    66,    67,    -1,    68,    -1,    56,
+      44,    -1,     1,    44,    -1,    -1,    47,    69,    70,    -1,
+      71,    -1,    70,    45,    71,    -1,    70,    44,    -1,    -1,
+      71,    72,    -1,    71,    51,    -1,    71,    14,    72,    -1,
+      71,    15,     4,    -1,    71,    16,    42,    -1,    46,    -1,
+      73,    -1,     3,    -1,     3,    -1,    -1,    48,    50,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   202,   202,   210,   212,   216,   217,   218,   219,   224,
-     225,   226,   227,   228,   229,   230,   235,   239,   240,   241,
-     242,   243,   244,   245,   246,   247,   248,   249,   250,   251,
-     252,   256,   257,   258,   262,   278,   285,   292,   296,   303,
-     303,   308,   308,   313,   323,   338,   339,   340,   344,   345,
-     351,   352,   357,   361,   366,   372,   378,   389,   390,   399,
-     400,   406,   407,   408,   415,   415,   419,   420,   421,   426,
-     427,   429,   430,   432,   434,   439,   440,   456,   456,   462,
-     471,   476,   478
+       0,   194,   194,   202,   204,   208,   209,   211,   212,   217,
+     218,   219,   220,   221,   222,   223,   228,   232,   233,   234,
+     235,   236,   237,   238,   239,   240,   241,   242,   243,   244,
+     245,   249,   250,   251,   255,   271,   279,   287,   291,   298,
+     298,   303,   303,   308,   318,   333,   334,   335,   339,   340,
+     345,   346,   351,   355,   360,   366,   372,   383,   384,   393,
+     394,   400,   401,   402,   409,   409,   413,   414,   415,   420,
+     421,   423,   426,   428,   430,   435,   436,   441,   450,   455,
+     457
 };
 #endif
 
 };
 #endif
 
@@ -645,14 +647,14 @@ static const yytype_uint16 yyrline[] =
 static const char *const yytname[] =
 {
   "\"end of file\"", "error", "$undefined", "\"string\"", "\"integer\"",
 static const char *const yytname[] =
 {
   "\"end of file\"", "error", "$undefined", "\"string\"", "\"integer\"",
-  "\"%token\"", "\"%nterm\"", "\"%type\"", "\"%destructor {...}\"",
-  "\"%printer {...}\"", "\"%union {...}\"", "\"%left\"", "\"%right\"",
+  "\"%token\"", "\"%nterm\"", "\"%type\"", "\"%destructor\"",
+  "\"%printer\"", "\"%union {...}\"", "\"%left\"", "\"%right\"",
   "\"%nonassoc\"", "\"%prec\"", "\"%dprec\"", "\"%merge\"", "\"%debug\"",
   "\"%default-prec\"", "\"%define\"", "\"%defines\"", "\"%error-verbose\"",
   "\"%expect\"", "\"%expect-rr\"", "\"%file-prefix\"", "\"%glr-parser\"",
   "\"%nonassoc\"", "\"%prec\"", "\"%dprec\"", "\"%merge\"", "\"%debug\"",
   "\"%default-prec\"", "\"%define\"", "\"%defines\"", "\"%error-verbose\"",
   "\"%expect\"", "\"%expect-rr\"", "\"%file-prefix\"", "\"%glr-parser\"",
-  "\"%initial-action {...}\"", "\"%lex-param {...}\"", "\"%locations\"",
+  "\"%initial-action\"", "\"%lex-param\"", "\"%locations\"",
   "\"%name-prefix\"", "\"%no-default-prec\"", "\"%no-lines\"",
   "\"%name-prefix\"", "\"%no-default-prec\"", "\"%no-lines\"",
-  "\"%nondeterministic-parser\"", "\"%output\"", "\"%parse-param {...}\"",
+  "\"%nondeterministic-parser\"", "\"%output\"", "\"%parse-param\"",
   "\"%pure-parser\"", "\"%require\"", "\"%skeleton\"", "\"%start\"",
   "\"%token-table\"", "\"%verbose\"", "\"%yacc\"", "\"type\"", "\"=\"",
   "\";\"", "\"|\"", "\"identifier\"", "\"identifier:\"", "\"%%\"",
   "\"%pure-parser\"", "\"%require\"", "\"%skeleton\"", "\"%start\"",
   "\"%token-table\"", "\"%verbose\"", "\"%yacc\"", "\"type\"", "\"=\"",
   "\";\"", "\"|\"", "\"identifier\"", "\"identifier:\"", "\"%%\"",
@@ -661,8 +663,8 @@ static const char *const yytname[] =
   "symbol_declaration", "@1", "@2", "precedence_declaration",
   "precedence_declarator", "type.opt", "symbols.1", "symbol_def",
   "symbol_defs.1", "grammar", "rules_or_grammar_declaration", "rules",
   "symbol_declaration", "@1", "@2", "precedence_declaration",
   "precedence_declarator", "type.opt", "symbols.1", "symbol_def",
   "symbol_defs.1", "grammar", "rules_or_grammar_declaration", "rules",
-  "@3", "rhses.1", "rhs", "symbol", "action", "@4", "string_as_id",
-  "string_content", "epilogue.opt", 0
+  "@3", "rhses.1", "rhs", "symbol", "string_as_id", "string_content",
+  "epilogue.opt", 0
 };
 #endif
 
 };
 #endif
 
@@ -690,22 +692,22 @@ static const yytype_uint8 yyr1[] =
       57,    59,    57,    57,    60,    61,    61,    61,    62,    62,
       63,    63,    64,    64,    64,    64,    64,    65,    65,    66,
       66,    67,    67,    67,    69,    68,    70,    70,    70,    71,
       57,    59,    57,    57,    60,    61,    61,    61,    62,    62,
       63,    63,    64,    64,    64,    64,    64,    65,    65,    66,
       66,    67,    67,    67,    69,    68,    70,    70,    70,    71,
-      71,    71,    71,    71,    71,    72,    72,    74,    73,    75,
-      76,    77,    77
+      71,    71,    71,    71,    71,    72,    72,    73,    74,    75,
+      75
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
        0,     2,     4,     0,     2,     1,     1,     1,     2,     3,
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
        0,     2,     4,     0,     2,     1,     1,     1,     2,     3,
-       1,     1,     2,     2,     3,     1,     1,     1,     1,     3,
-       1,     1,     3,     1,     1,     2,     2,     1,     1,     1,
-       1,     1,     1,     2,     1,     2,     2,     1,     1,     0,
+       1,     1,     2,     2,     3,     1,     2,     2,     1,     3,
+       1,     1,     3,     2,     1,     2,     2,     1,     1,     1,
+       1,     1,     1,     2,     1,     3,     3,     1,     1,     0,
        3,     0,     3,     3,     3,     1,     1,     1,     0,     1,
        1,     2,     1,     1,     2,     2,     3,     1,     2,     1,
        2,     1,     2,     2,     0,     3,     1,     3,     2,     0,
        3,     0,     3,     3,     3,     1,     1,     1,     0,     1,
        1,     2,     1,     1,     2,     2,     3,     1,     2,     1,
        2,     1,     2,     2,     0,     3,     1,     3,     2,     0,
-       2,     2,     3,     3,     3,     1,     1,     0,     2,     1,
-       1,     0,     2
+       2,     2,     3,     3,     3,     1,     1,     1,     1,     0,
+       2
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -715,98 +717,98 @@ static const yytype_uint8 yydefact[] =
 {
        3,     0,     0,     1,    41,    39,     0,     0,     0,    34,
       45,    46,    47,     7,    37,     0,    10,    11,     0,     0,
 {
        3,     0,     0,     1,    41,    39,     0,     0,     0,    34,
       45,    46,    47,     7,    37,     0,    10,    11,     0,     0,
-       0,    15,    16,    17,    18,     0,    38,    20,    21,     0,
-      23,    24,     0,     0,     0,    27,    28,    29,    30,     0,
-       6,     4,     5,    32,    31,    48,     0,     0,     0,    79,
-      75,    35,    50,    76,    36,    80,     8,    12,    13,     0,
-       0,     0,    25,    26,    33,     0,    64,     0,     0,    59,
-      61,    49,     0,    52,    53,    57,    42,    40,    43,    51,
-       9,    14,    19,    22,    63,    69,    62,     0,    60,     2,
-      44,    54,    55,    58,    65,    66,    82,    56,    68,    69,
-       0,     0,     0,    70,    71,     0,    67,    72,    73,    74,
-      78
+       0,    15,     0,     0,    18,     0,    38,    20,    21,     0,
+       0,    24,     0,     0,     0,    27,    28,    29,    30,     0,
+       6,     4,     5,    32,    31,    48,     0,     0,     0,     0,
+       0,    78,     8,    12,    13,     0,    16,    17,     0,     0,
+      23,    25,    26,    77,    75,    33,    76,     0,    64,     0,
+       0,    59,    61,    49,     0,    52,    53,    57,    42,    40,
+      43,    50,    35,    36,     9,    14,    19,    22,    63,    69,
+      62,     0,    60,     2,    44,    54,    55,    58,    51,    65,
+      66,    80,    56,    68,    69,     0,     0,     0,    71,    70,
+      67,    72,    73,    74
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,     1,     2,    41,    67,    43,    47,    46,    44,    45,
-      72,    51,    75,    76,    68,    69,    70,    85,    94,    95,
-      52,   104,   105,    53,    56,    89
+      -1,     1,     2,    41,    69,    43,    47,    46,    44,    45,
+      74,    80,    77,    78,    70,    71,    72,    89,    99,   100,
+      81,    66,    52,    93
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -69
+#define YYPACT_NINF -72
 static const yytype_int8 yypact[] =
 {
 static const yytype_int8 yypact[] =
 {
-     -69,     5,   112,   -69,   -69,   -69,   -35,     0,     0,   -69,
-     -69,   -69,   -69,   -69,   -69,    13,   -69,   -69,    20,    31,
-     -18,   -69,   -69,   -69,   -69,    -6,   -69,   -69,   -69,    -5,
-     -69,   -69,    13,    13,     0,   -69,   -69,   -69,   -69,    69,
-     -69,   -69,   -69,   -69,   -69,    -2,   -38,   -38,     0,   -69,
-     -69,     0,   -69,   -69,     0,   -69,    13,   -69,   -69,    13,
-      13,    13,   -69,   -69,   -69,    -8,   -69,     3,    21,   -69,
-     -69,   -69,     0,   -69,     6,   -69,   -38,   -38,     0,   -69,
-     -69,   -69,   -69,   -69,   -69,   -69,   -69,     2,   -69,   -69,
-       0,    39,   -69,   -69,   -33,    -1,   -69,   -69,   -69,   -69,
-       0,    44,     1,   -69,   -69,     4,    -1,   -69,   -69,   -69,
-     -69
+     -72,     7,   115,   -72,   -72,   -72,   -22,   -17,   -16,   -72,
+     -72,   -72,   -72,   -72,   -72,    26,   -72,   -72,    32,    33,
+      -3,   -72,    -8,    -6,   -72,     4,   -72,   -72,   -72,     9,
+       2,   -72,    26,    26,    -2,   -72,   -72,   -72,   -72,    72,
+     -72,   -72,   -72,   -72,   -72,    12,   -40,   -40,    -2,    -2,
+      -2,   -72,    26,   -72,   -72,    26,   -72,   -72,    26,    26,
+     -72,   -72,   -72,   -72,   -72,   -72,   -72,    11,   -72,    13,
+       3,   -72,   -72,   -72,    -2,   -72,    19,   -72,   -40,   -40,
+      -2,   -72,    -2,    -2,   -72,   -72,   -72,   -72,   -72,   -72,
+     -72,    18,   -72,   -72,    -2,    53,   -72,   -72,   -72,   -19,
+      16,   -72,   -72,   -72,   -72,    -2,    55,    21,   -72,   -72,
+      16,   -72,   -72,   -72
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -69,   -69,   -69,   -69,    47,   -69,   -69,   -69,   -69,   -69,
-     -69,    -7,   -58,     7,   -69,   -15,   -69,   -69,   -69,   -42,
-     -34,   -69,   -69,   -68,    30,   -69
+     -72,   -72,   -72,   -72,    67,   -72,   -72,   -72,   -72,   -72,
+     -72,   -32,   -51,    23,   -72,     5,   -72,   -72,   -72,   -30,
+     -34,   -71,     6,   -72
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If zero, do what YYDEFACT says.
    If YYTABLE_NINF, syntax error.  */
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If zero, do what YYDEFACT says.
    If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -82
+#define YYTABLE_NINF -80
 static const yytype_int8 yytable[] =
 {
 static const yytype_int8 yytable[] =
 {
-      64,    54,    49,    49,    73,     3,    92,    48,    74,    49,
-      91,    98,    99,   100,   101,   102,    55,    79,    93,    93,
-      79,   -81,    65,    97,    57,    59,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    58,    84,    60,    61,    14,
-      71,    78,    49,   109,    79,    50,    50,    86,   108,    42,
-     -77,    26,    96,    88,    77,   110,    79,   106,     0,    34,
-       0,   103,    62,    63,     0,    90,   107,     0,    66,    87,
-      65,     0,   103,     0,     4,     5,     6,     7,     8,     9,
-      10,    11,    12,     0,     0,     0,    80,    14,     0,    81,
-      82,    83,     0,     0,     0,     0,     0,     0,     0,    26,
-       0,     0,     0,     0,     0,     0,     0,    34,     0,     0,
-       0,     0,     0,     0,     0,     0,    66,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,     0,     0,     0,    13,
-      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
-      34,    35,    36,    37,     0,     0,    38,     0,     0,     0,
-      39,    40
+      65,    63,    75,   -79,    67,    96,    76,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,    82,    83,    63,
+      48,    14,    63,    95,   102,   103,   104,    97,    97,    51,
+     105,   106,   107,    26,    49,    50,    53,    54,    61,    62,
+      55,    34,    94,    56,    64,    57,    98,    58,    98,    98,
+      68,    91,    59,    60,    73,    88,    63,    90,    84,   112,
+      98,    85,    64,   113,    86,    87,   109,   108,   101,    42,
+      79,   111,     0,    67,   110,    92,   109,     4,     5,     6,
+       7,     8,     9,    10,    11,    12,     0,     0,     0,     0,
+      14,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    26,     0,     0,     0,     0,     0,     0,     0,
+      34,     0,     0,     0,     0,     0,     0,     0,     0,    68,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,     0,
+       0,     0,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,    32,    33,    34,    35,    36,    37,     0,     0,    38,
+       0,     0,     0,    39,    40
 };
 
 static const yytype_int8 yycheck[] =
 {
 };
 
 static const yytype_int8 yycheck[] =
 {
-      34,     8,     3,     3,    42,     0,    74,    42,    46,     3,
-       4,    44,    45,    14,    15,    16,     3,    51,    76,    77,
-      54,     0,     1,    91,     4,    43,     5,     6,     7,     8,
-       9,    10,    11,    12,    13,     4,    44,    43,    43,    18,
-      42,    48,     3,    42,    78,    46,    46,    44,     4,     2,
-      51,    30,    50,    68,    47,    51,    90,    99,    -1,    38,
-      -1,    95,    32,    33,    -1,    72,   100,    -1,    47,    48,
-       1,    -1,   106,    -1,     5,     6,     7,     8,     9,    10,
-      11,    12,    13,    -1,    -1,    -1,    56,    18,    -1,    59,
-      60,    61,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    30,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    38,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    47,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    -1,    -1,    -1,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
-      38,    39,    40,    41,    -1,    -1,    44,    -1,    -1,    -1,
-      48,    49
+      34,     3,    42,     0,     1,    76,    46,     0,     5,     6,
+       7,     8,     9,    10,    11,    12,    13,    49,    50,     3,
+      42,    18,     3,     4,    95,    44,    45,    78,    79,     3,
+      14,    15,    16,    30,    51,    51,     4,     4,    32,    33,
+      43,    38,    74,    51,    46,    51,    80,    43,    82,    83,
+      47,    48,    43,    51,    42,    44,     3,    44,    52,     4,
+      94,    55,    46,    42,    58,    59,   100,    51,    50,     2,
+      47,   105,    -1,     1,   104,    70,   110,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    -1,    -1,    -1,    -1,
+      18,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    30,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      38,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    47,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    -1,
+      -1,    -1,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    -1,    -1,    44,
+      -1,    -1,    -1,    48,    49
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -817,14 +819,14 @@ static const yytype_uint8 yystos[] =
       11,    12,    13,    17,    18,    19,    20,    21,    22,    23,
       24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
       34,    35,    36,    37,    38,    39,    40,    41,    44,    48,
       11,    12,    13,    17,    18,    19,    20,    21,    22,    23,
       24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
       34,    35,    36,    37,    38,    39,    40,    41,    44,    48,
-      49,    55,    56,    57,    60,    61,    59,    58,    42,     3,
-      46,    63,    72,    75,    63,     3,    76,     4,     4,    43,
-      43,    43,    76,    76,    72,     1,    47,    56,    66,    67,
-      68,    42,    62,    42,    46,    64,    65,    65,    63,    72,
-      76,    76,    76,    76,    44,    69,    44,    48,    67,    77,
-      63,     4,    75,    64,    70,    71,    50,    75,    44,    45,
-      14,    15,    16,    72,    73,    74,    71,    72,     4,    42,
-      51
+      49,    55,    56,    57,    60,    61,    59,    58,    42,    51,
+      51,     3,    74,     4,     4,    43,    51,    51,    43,    43,
+      51,    74,    74,     3,    46,    72,    73,     1,    47,    56,
+      66,    67,    68,    42,    62,    42,    46,    64,    65,    65,
+      63,    72,    63,    63,    74,    74,    74,    74,    44,    69,
+      44,    48,    67,    75,    63,     4,    73,    64,    72,    70,
+      71,    50,    73,    44,    45,    14,    15,    16,    51,    72,
+      71,    72,     4,    42
 };
 
 #define yyerrok                (yyerrstatus = 0)
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -973,84 +975,64 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
   switch (yytype)
     {
       case 3: /* "\"string\"" */
   switch (yytype)
     {
       case 3: /* "\"string\"" */
-#line 179 "parse-gram.y"
+#line 175 "../../src/parse-gram.y"
        { fprintf (stderr, "\"%s\"", (yyvaluep->chars)); };
        { fprintf (stderr, "\"%s\"", (yyvaluep->chars)); };
-#line 979 "parse-gram.c"
+#line 981 "../../src/parse-gram.c"
        break;
       case 4: /* "\"integer\"" */
        break;
       case 4: /* "\"integer\"" */
-#line 192 "parse-gram.y"
+#line 184 "../../src/parse-gram.y"
        { fprintf (stderr, "%d", (yyvaluep->integer)); };
        { fprintf (stderr, "%d", (yyvaluep->integer)); };
-#line 984 "parse-gram.c"
-       break;
-      case 8: /* "\"%destructor {...}\"" */
-#line 181 "parse-gram.y"
-       { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
-#line 989 "parse-gram.c"
-       break;
-      case 9: /* "\"%printer {...}\"" */
-#line 181 "parse-gram.y"
-       { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
-#line 994 "parse-gram.c"
+#line 986 "../../src/parse-gram.c"
        break;
       case 10: /* "\"%union {...}\"" */
        break;
       case 10: /* "\"%union {...}\"" */
-#line 181 "parse-gram.y"
-       { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
-#line 999 "parse-gram.c"
-       break;
-      case 26: /* "\"%initial-action {...}\"" */
-#line 181 "parse-gram.y"
-       { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
-#line 1004 "parse-gram.c"
-       break;
-      case 27: /* "\"%lex-param {...}\"" */
-#line 181 "parse-gram.y"
-       { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
-#line 1009 "parse-gram.c"
-       break;
-      case 34: /* "\"%parse-param {...}\"" */
-#line 181 "parse-gram.y"
+#line 177 "../../src/parse-gram.y"
        { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
        { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
-#line 1014 "parse-gram.c"
+#line 991 "../../src/parse-gram.c"
        break;
       case 42: /* "\"type\"" */
        break;
       case 42: /* "\"type\"" */
-#line 190 "parse-gram.y"
+#line 182 "../../src/parse-gram.y"
        { fprintf (stderr, "<%s>", (yyvaluep->uniqstr)); };
        { fprintf (stderr, "<%s>", (yyvaluep->uniqstr)); };
-#line 1019 "parse-gram.c"
+#line 996 "../../src/parse-gram.c"
        break;
       case 46: /* "\"identifier\"" */
        break;
       case 46: /* "\"identifier\"" */
-#line 194 "parse-gram.y"
+#line 186 "../../src/parse-gram.y"
        { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); };
        { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); };
-#line 1024 "parse-gram.c"
+#line 1001 "../../src/parse-gram.c"
        break;
       case 47: /* "\"identifier:\"" */
        break;
       case 47: /* "\"identifier:\"" */
-#line 196 "parse-gram.y"
+#line 188 "../../src/parse-gram.y"
        { fprintf (stderr, "%s:", (yyvaluep->symbol)->tag); };
        { fprintf (stderr, "%s:", (yyvaluep->symbol)->tag); };
-#line 1029 "parse-gram.c"
+#line 1006 "../../src/parse-gram.c"
        break;
       case 49: /* "\"%{...%}\"" */
        break;
       case 49: /* "\"%{...%}\"" */
-#line 181 "parse-gram.y"
+#line 177 "../../src/parse-gram.y"
        { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
        { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
-#line 1034 "parse-gram.c"
+#line 1011 "../../src/parse-gram.c"
        break;
       case 50: /* "\"epilogue\"" */
        break;
       case 50: /* "\"epilogue\"" */
-#line 181 "parse-gram.y"
+#line 177 "../../src/parse-gram.y"
        { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
        { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
-#line 1039 "parse-gram.c"
+#line 1016 "../../src/parse-gram.c"
+       break;
+      case 51: /* "\"{...}\"" */
+#line 177 "../../src/parse-gram.y"
+       { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
+#line 1021 "../../src/parse-gram.c"
        break;
       case 72: /* "symbol" */
        break;
       case 72: /* "symbol" */
-#line 194 "parse-gram.y"
+#line 186 "../../src/parse-gram.y"
        { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); };
        { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); };
-#line 1044 "parse-gram.c"
+#line 1026 "../../src/parse-gram.c"
        break;
        break;
-      case 75: /* "string_as_id" */
-#line 194 "parse-gram.y"
+      case 73: /* "string_as_id" */
+#line 186 "../../src/parse-gram.y"
        { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); };
        { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); };
-#line 1049 "parse-gram.c"
+#line 1031 "../../src/parse-gram.c"
        break;
        break;
-      case 76: /* "string_content" */
-#line 179 "parse-gram.y"
+      case 74: /* "string_content" */
+#line 175 "../../src/parse-gram.y"
        { fprintf (stderr, "\"%s\"", (yyvaluep->chars)); };
        { fprintf (stderr, "\"%s\"", (yyvaluep->chars)); };
-#line 1054 "parse-gram.c"
+#line 1036 "../../src/parse-gram.c"
        break;
       default:
        break;
        break;
       default:
        break;
@@ -1560,16 +1542,15 @@ YYLTYPE yylloc;
 
 
   /* User initialization code.  */
 
 
   /* User initialization code.  */
-#line 84 "parse-gram.y"
+#line 86 "../../src/parse-gram.y"
 {
   /* Bison's grammar can initial empty locations, hence a default
      location is needed. */
 {
   /* Bison's grammar can initial empty locations, hence a default
      location is needed. */
-  yylloc.start.file   = yylloc.end.file   = current_file;
-  yylloc.start.line   = yylloc.end.line   = 1;
-  yylloc.start.column = yylloc.end.column = 0;
+  boundary_set (&yylloc.start, current_file, 1, 0);
+  boundary_set (&yylloc.end, current_file, 1, 0);
 }
 /* Line 1078 of yacc.c.  */
 }
 /* Line 1078 of yacc.c.  */
-#line 1573 "parse-gram.c"
+#line 1554 "../../src/parse-gram.c"
   yylsp[0] = yylloc;
   goto yysetstate;
 
   yylsp[0] = yylloc;
   goto yysetstate;
 
@@ -1754,17 +1735,18 @@ yyreduce:
   switch (yyn)
     {
         case 6:
   switch (yyn)
     {
         case 6:
-#line 217 "parse-gram.y"
-    { prologue_augment ((yyvsp[(1) - (1)].chars), (yylsp[(1) - (1)])); }
+#line 209 "../../src/parse-gram.y"
+    { prologue_augment (translate_code ((yyvsp[(1) - (1)].chars), (yylsp[(1) - (1)])),
+                                                      (yylsp[(1) - (1)])); }
     break;
 
   case 7:
     break;
 
   case 7:
-#line 218 "parse-gram.y"
+#line 211 "../../src/parse-gram.y"
     { debug_flag = true; }
     break;
 
   case 8:
     { debug_flag = true; }
     break;
 
   case 8:
-#line 220 "parse-gram.y"
+#line 213 "../../src/parse-gram.y"
     {
       static char one[] = "1";
       muscle_insert ((yyvsp[(2) - (2)].chars), one);
     {
       static char one[] = "1";
       muscle_insert ((yyvsp[(2) - (2)].chars), one);
@@ -1772,37 +1754,37 @@ yyreduce:
     break;
 
   case 9:
     break;
 
   case 9:
-#line 224 "parse-gram.y"
+#line 217 "../../src/parse-gram.y"
     { muscle_insert ((yyvsp[(2) - (3)].chars), (yyvsp[(3) - (3)].chars)); }
     break;
 
   case 10:
     { muscle_insert ((yyvsp[(2) - (3)].chars), (yyvsp[(3) - (3)].chars)); }
     break;
 
   case 10:
-#line 225 "parse-gram.y"
+#line 218 "../../src/parse-gram.y"
     { defines_flag = true; }
     break;
 
   case 11:
     { defines_flag = true; }
     break;
 
   case 11:
-#line 226 "parse-gram.y"
+#line 219 "../../src/parse-gram.y"
     { error_verbose = true; }
     break;
 
   case 12:
     { error_verbose = true; }
     break;
 
   case 12:
-#line 227 "parse-gram.y"
+#line 220 "../../src/parse-gram.y"
     { expected_sr_conflicts = (yyvsp[(2) - (2)].integer); }
     break;
 
   case 13:
     { expected_sr_conflicts = (yyvsp[(2) - (2)].integer); }
     break;
 
   case 13:
-#line 228 "parse-gram.y"
+#line 221 "../../src/parse-gram.y"
     { expected_rr_conflicts = (yyvsp[(2) - (2)].integer); }
     break;
 
   case 14:
     { expected_rr_conflicts = (yyvsp[(2) - (2)].integer); }
     break;
 
   case 14:
-#line 229 "parse-gram.y"
+#line 222 "../../src/parse-gram.y"
     { spec_file_prefix = (yyvsp[(3) - (3)].chars); }
     break;
 
   case 15:
     { spec_file_prefix = (yyvsp[(3) - (3)].chars); }
     break;
 
   case 15:
-#line 231 "parse-gram.y"
+#line 224 "../../src/parse-gram.y"
     {
       nondeterministic_parser = true;
       glr_parser = true;
     {
       nondeterministic_parser = true;
       glr_parser = true;
@@ -1810,86 +1792,86 @@ yyreduce:
     break;
 
   case 16:
     break;
 
   case 16:
-#line 236 "parse-gram.y"
+#line 229 "../../src/parse-gram.y"
     {
     {
-      muscle_code_grow ("initial_action", (yyvsp[(1) - (1)].chars), (yylsp[(1) - (1)]));
+      muscle_code_grow ("initial_action", translate_symbol_action ((yyvsp[(2) - (2)].chars), (yylsp[(2) - (2)])), (yylsp[(2) - (2)]));
     }
     break;
 
   case 17:
     }
     break;
 
   case 17:
-#line 239 "parse-gram.y"
-    { add_param ("lex_param", (yyvsp[(1) - (1)].chars), (yylsp[(1) - (1)])); }
+#line 232 "../../src/parse-gram.y"
+    { add_param ("lex_param", (yyvsp[(2) - (2)].chars), (yylsp[(2) - (2)])); }
     break;
 
   case 18:
     break;
 
   case 18:
-#line 240 "parse-gram.y"
+#line 233 "../../src/parse-gram.y"
     { locations_flag = true; }
     break;
 
   case 19:
     { locations_flag = true; }
     break;
 
   case 19:
-#line 241 "parse-gram.y"
+#line 234 "../../src/parse-gram.y"
     { spec_name_prefix = (yyvsp[(3) - (3)].chars); }
     break;
 
   case 20:
     { spec_name_prefix = (yyvsp[(3) - (3)].chars); }
     break;
 
   case 20:
-#line 242 "parse-gram.y"
+#line 235 "../../src/parse-gram.y"
     { no_lines_flag = true; }
     break;
 
   case 21:
     { no_lines_flag = true; }
     break;
 
   case 21:
-#line 243 "parse-gram.y"
+#line 236 "../../src/parse-gram.y"
     { nondeterministic_parser = true; }
     break;
 
   case 22:
     { nondeterministic_parser = true; }
     break;
 
   case 22:
-#line 244 "parse-gram.y"
+#line 237 "../../src/parse-gram.y"
     { spec_outfile = (yyvsp[(3) - (3)].chars); }
     break;
 
   case 23:
     { spec_outfile = (yyvsp[(3) - (3)].chars); }
     break;
 
   case 23:
-#line 245 "parse-gram.y"
-    { add_param ("parse_param", (yyvsp[(1) - (1)].chars), (yylsp[(1) - (1)])); }
+#line 238 "../../src/parse-gram.y"
+    { add_param ("parse_param", (yyvsp[(2) - (2)].chars), (yylsp[(2) - (2)])); }
     break;
 
   case 24:
     break;
 
   case 24:
-#line 246 "parse-gram.y"
+#line 239 "../../src/parse-gram.y"
     { pure_parser = true; }
     break;
 
   case 25:
     { pure_parser = true; }
     break;
 
   case 25:
-#line 247 "parse-gram.y"
+#line 240 "../../src/parse-gram.y"
     { version_check (&(yylsp[(2) - (2)]), (yyvsp[(2) - (2)].chars)); }
     break;
 
   case 26:
     { version_check (&(yylsp[(2) - (2)]), (yyvsp[(2) - (2)].chars)); }
     break;
 
   case 26:
-#line 248 "parse-gram.y"
+#line 241 "../../src/parse-gram.y"
     { skeleton = (yyvsp[(2) - (2)].chars); }
     break;
 
   case 27:
     { skeleton = (yyvsp[(2) - (2)].chars); }
     break;
 
   case 27:
-#line 249 "parse-gram.y"
+#line 242 "../../src/parse-gram.y"
     { token_table_flag = true; }
     break;
 
   case 28:
     { token_table_flag = true; }
     break;
 
   case 28:
-#line 250 "parse-gram.y"
+#line 243 "../../src/parse-gram.y"
     { report_flag = report_states; }
     break;
 
   case 29:
     { report_flag = report_states; }
     break;
 
   case 29:
-#line 251 "parse-gram.y"
+#line 244 "../../src/parse-gram.y"
     { yacc_flag = true; }
     break;
 
   case 33:
     { yacc_flag = true; }
     break;
 
   case 33:
-#line 259 "parse-gram.y"
+#line 252 "../../src/parse-gram.y"
     {
       grammar_start_symbol_set ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)]));
     }
     break;
 
   case 34:
     {
       grammar_start_symbol_set ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)]));
     }
     break;
 
   case 34:
-#line 263 "parse-gram.y"
+#line 256 "../../src/parse-gram.y"
     {
       char const *body = (yyvsp[(1) - (1)].chars);
 
     {
       char const *body = (yyvsp[(1) - (1)].chars);
 
@@ -1908,46 +1890,48 @@ yyreduce:
     break;
 
   case 35:
     break;
 
   case 35:
-#line 279 "parse-gram.y"
+#line 272 "../../src/parse-gram.y"
     {
       symbol_list *list;
     {
       symbol_list *list;
-      for (list = (yyvsp[(2) - (2)].list); list; list = list->next)
-       symbol_destructor_set (list->sym, (yyvsp[(1) - (2)].chars), (yylsp[(1) - (2)]));
-      symbol_list_free ((yyvsp[(2) - (2)].list));
+      const char *action = translate_symbol_action ((yyvsp[(2) - (3)].chars), (yylsp[(2) - (3)]));
+      for (list = (yyvsp[(3) - (3)].list); list; list = list->next)
+       symbol_destructor_set (list->sym, action, (yylsp[(2) - (3)]));
+      symbol_list_free ((yyvsp[(3) - (3)].list));
     }
     break;
 
   case 36:
     }
     break;
 
   case 36:
-#line 286 "parse-gram.y"
+#line 280 "../../src/parse-gram.y"
     {
       symbol_list *list;
     {
       symbol_list *list;
-      for (list = (yyvsp[(2) - (2)].list); list; list = list->next)
-       symbol_printer_set (list->sym, (yyvsp[(1) - (2)].chars), (yylsp[(1) - (2)]));
-      symbol_list_free ((yyvsp[(2) - (2)].list));
+      const char *action = translate_symbol_action ((yyvsp[(2) - (3)].chars), (yylsp[(2) - (3)]));
+      for (list = (yyvsp[(3) - (3)].list); list; list = list->next)
+       symbol_printer_set (list->sym, action, (yylsp[(2) - (3)]));
+      symbol_list_free ((yyvsp[(3) - (3)].list));
     }
     break;
 
   case 37:
     }
     break;
 
   case 37:
-#line 293 "parse-gram.y"
+#line 288 "../../src/parse-gram.y"
     {
       default_prec = true;
     }
     break;
 
   case 38:
     {
       default_prec = true;
     }
     break;
 
   case 38:
-#line 297 "parse-gram.y"
+#line 292 "../../src/parse-gram.y"
     {
       default_prec = false;
     }
     break;
 
   case 39:
     {
       default_prec = false;
     }
     break;
 
   case 39:
-#line 303 "parse-gram.y"
+#line 298 "../../src/parse-gram.y"
     { current_class = nterm_sym; }
     break;
 
   case 40:
     { current_class = nterm_sym; }
     break;
 
   case 40:
-#line 304 "parse-gram.y"
+#line 299 "../../src/parse-gram.y"
     {
       current_class = unknown_sym;
       current_type = NULL;
     {
       current_class = unknown_sym;
       current_type = NULL;
@@ -1955,12 +1939,12 @@ yyreduce:
     break;
 
   case 41:
     break;
 
   case 41:
-#line 308 "parse-gram.y"
+#line 303 "../../src/parse-gram.y"
     { current_class = token_sym; }
     break;
 
   case 42:
     { current_class = token_sym; }
     break;
 
   case 42:
-#line 309 "parse-gram.y"
+#line 304 "../../src/parse-gram.y"
     {
       current_class = unknown_sym;
       current_type = NULL;
     {
       current_class = unknown_sym;
       current_type = NULL;
@@ -1968,7 +1952,7 @@ yyreduce:
     break;
 
   case 43:
     break;
 
   case 43:
-#line 314 "parse-gram.y"
+#line 309 "../../src/parse-gram.y"
     {
       symbol_list *list;
       for (list = (yyvsp[(3) - (3)].list); list; list = list->next)
     {
       symbol_list *list;
       for (list = (yyvsp[(3) - (3)].list); list; list = list->next)
@@ -1978,7 +1962,7 @@ yyreduce:
     break;
 
   case 44:
     break;
 
   case 44:
-#line 324 "parse-gram.y"
+#line 319 "../../src/parse-gram.y"
     {
       symbol_list *list;
       ++current_prec;
     {
       symbol_list *list;
       ++current_prec;
@@ -1993,49 +1977,49 @@ yyreduce:
     break;
 
   case 45:
     break;
 
   case 45:
-#line 338 "parse-gram.y"
+#line 333 "../../src/parse-gram.y"
     { (yyval.assoc) = left_assoc; }
     break;
 
   case 46:
     { (yyval.assoc) = left_assoc; }
     break;
 
   case 46:
-#line 339 "parse-gram.y"
+#line 334 "../../src/parse-gram.y"
     { (yyval.assoc) = right_assoc; }
     break;
 
   case 47:
     { (yyval.assoc) = right_assoc; }
     break;
 
   case 47:
-#line 340 "parse-gram.y"
+#line 335 "../../src/parse-gram.y"
     { (yyval.assoc) = non_assoc; }
     break;
 
   case 48:
     { (yyval.assoc) = non_assoc; }
     break;
 
   case 48:
-#line 344 "parse-gram.y"
+#line 339 "../../src/parse-gram.y"
     { current_type = NULL; }
     break;
 
   case 49:
     { current_type = NULL; }
     break;
 
   case 49:
-#line 345 "parse-gram.y"
+#line 340 "../../src/parse-gram.y"
     { current_type = (yyvsp[(1) - (1)].uniqstr); }
     break;
 
   case 50:
     { current_type = (yyvsp[(1) - (1)].uniqstr); }
     break;
 
   case 50:
-#line 351 "parse-gram.y"
+#line 345 "../../src/parse-gram.y"
     { (yyval.list) = symbol_list_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); }
     break;
 
   case 51:
     { (yyval.list) = symbol_list_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); }
     break;
 
   case 51:
-#line 352 "parse-gram.y"
+#line 346 "../../src/parse-gram.y"
     { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)])); }
     break;
 
   case 52:
     { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)])); }
     break;
 
   case 52:
-#line 358 "parse-gram.y"
+#line 352 "../../src/parse-gram.y"
     {
        current_type = (yyvsp[(1) - (1)].uniqstr);
      }
     break;
 
   case 53:
     {
        current_type = (yyvsp[(1) - (1)].uniqstr);
      }
     break;
 
   case 53:
-#line 362 "parse-gram.y"
+#line 356 "../../src/parse-gram.y"
     {
        symbol_class_set ((yyvsp[(1) - (1)].symbol), current_class, (yylsp[(1) - (1)]), true);
        symbol_type_set ((yyvsp[(1) - (1)].symbol), current_type, (yylsp[(1) - (1)]));
     {
        symbol_class_set ((yyvsp[(1) - (1)].symbol), current_class, (yylsp[(1) - (1)]), true);
        symbol_type_set ((yyvsp[(1) - (1)].symbol), current_type, (yylsp[(1) - (1)]));
@@ -2043,7 +2027,7 @@ yyreduce:
     break;
 
   case 54:
     break;
 
   case 54:
-#line 367 "parse-gram.y"
+#line 361 "../../src/parse-gram.y"
     {
       symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true);
       symbol_type_set ((yyvsp[(1) - (2)].symbol), current_type, (yylsp[(1) - (2)]));
     {
       symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true);
       symbol_type_set ((yyvsp[(1) - (2)].symbol), current_type, (yylsp[(1) - (2)]));
@@ -2052,7 +2036,7 @@ yyreduce:
     break;
 
   case 55:
     break;
 
   case 55:
-#line 373 "parse-gram.y"
+#line 367 "../../src/parse-gram.y"
     {
       symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true);
       symbol_type_set ((yyvsp[(1) - (2)].symbol), current_type, (yylsp[(1) - (2)]));
     {
       symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true);
       symbol_type_set ((yyvsp[(1) - (2)].symbol), current_type, (yylsp[(1) - (2)]));
@@ -2061,7 +2045,7 @@ yyreduce:
     break;
 
   case 56:
     break;
 
   case 56:
-#line 379 "parse-gram.y"
+#line 373 "../../src/parse-gram.y"
     {
       symbol_class_set ((yyvsp[(1) - (3)].symbol), current_class, (yylsp[(1) - (3)]), true);
       symbol_type_set ((yyvsp[(1) - (3)].symbol), current_type, (yylsp[(1) - (3)]));
     {
       symbol_class_set ((yyvsp[(1) - (3)].symbol), current_class, (yylsp[(1) - (3)]), true);
       symbol_type_set ((yyvsp[(1) - (3)].symbol), current_type, (yylsp[(1) - (3)]));
@@ -2071,91 +2055,92 @@ yyreduce:
     break;
 
   case 63:
     break;
 
   case 63:
-#line 409 "parse-gram.y"
+#line 403 "../../src/parse-gram.y"
     {
       yyerrok;
     }
     break;
 
   case 64:
     {
       yyerrok;
     }
     break;
 
   case 64:
-#line 415 "parse-gram.y"
+#line 409 "../../src/parse-gram.y"
     { current_lhs = (yyvsp[(1) - (1)].symbol); current_lhs_location = (yylsp[(1) - (1)]); }
     break;
 
   case 66:
     { current_lhs = (yyvsp[(1) - (1)].symbol); current_lhs_location = (yylsp[(1) - (1)]); }
     break;
 
   case 66:
-#line 419 "parse-gram.y"
+#line 413 "../../src/parse-gram.y"
     { grammar_current_rule_end ((yylsp[(1) - (1)])); }
     break;
 
   case 67:
     { grammar_current_rule_end ((yylsp[(1) - (1)])); }
     break;
 
   case 67:
-#line 420 "parse-gram.y"
+#line 414 "../../src/parse-gram.y"
     { grammar_current_rule_end ((yylsp[(3) - (3)])); }
     break;
 
   case 69:
     { grammar_current_rule_end ((yylsp[(3) - (3)])); }
     break;
 
   case 69:
-#line 426 "parse-gram.y"
+#line 420 "../../src/parse-gram.y"
     { grammar_current_rule_begin (current_lhs, current_lhs_location); }
     break;
 
   case 70:
     { grammar_current_rule_begin (current_lhs, current_lhs_location); }
     break;
 
   case 70:
-#line 428 "parse-gram.y"
+#line 422 "../../src/parse-gram.y"
     { grammar_current_rule_symbol_append ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)])); }
     break;
 
     { grammar_current_rule_symbol_append ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)])); }
     break;
 
+  case 71:
+#line 424 "../../src/parse-gram.y"
+    { grammar_current_rule_action_append (gram_last_string,
+                                         gram_last_braced_code_loc); }
+    break;
+
   case 72:
   case 72:
-#line 431 "parse-gram.y"
+#line 427 "../../src/parse-gram.y"
     { grammar_current_rule_prec_set ((yyvsp[(3) - (3)].symbol), (yylsp[(3) - (3)])); }
     break;
 
   case 73:
     { grammar_current_rule_prec_set ((yyvsp[(3) - (3)].symbol), (yylsp[(3) - (3)])); }
     break;
 
   case 73:
-#line 433 "parse-gram.y"
+#line 429 "../../src/parse-gram.y"
     { grammar_current_rule_dprec_set ((yyvsp[(3) - (3)].integer), (yylsp[(3) - (3)])); }
     break;
 
   case 74:
     { grammar_current_rule_dprec_set ((yyvsp[(3) - (3)].integer), (yylsp[(3) - (3)])); }
     break;
 
   case 74:
-#line 435 "parse-gram.y"
+#line 431 "../../src/parse-gram.y"
     { grammar_current_rule_merge_set ((yyvsp[(3) - (3)].uniqstr), (yylsp[(3) - (3)])); }
     break;
 
   case 75:
     { grammar_current_rule_merge_set ((yyvsp[(3) - (3)].uniqstr), (yylsp[(3) - (3)])); }
     break;
 
   case 75:
-#line 439 "parse-gram.y"
+#line 435 "../../src/parse-gram.y"
     { (yyval.symbol) = (yyvsp[(1) - (1)].symbol); }
     break;
 
   case 76:
     { (yyval.symbol) = (yyvsp[(1) - (1)].symbol); }
     break;
 
   case 76:
-#line 440 "parse-gram.y"
+#line 436 "../../src/parse-gram.y"
     { (yyval.symbol) = (yyvsp[(1) - (1)].symbol); }
     break;
 
   case 77:
     { (yyval.symbol) = (yyvsp[(1) - (1)].symbol); }
     break;
 
   case 77:
-#line 456 "parse-gram.y"
-    { grammar_current_rule_action_append (last_string, last_braced_code_loc); }
-    break;
-
-  case 79:
-#line 463 "parse-gram.y"
+#line 442 "../../src/parse-gram.y"
     {
       (yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[(1) - (1)].chars)), (yylsp[(1) - (1)]));
       symbol_class_set ((yyval.symbol), token_sym, (yylsp[(1) - (1)]), false);
     }
     break;
 
     {
       (yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[(1) - (1)].chars)), (yylsp[(1) - (1)]));
       symbol_class_set ((yyval.symbol), token_sym, (yylsp[(1) - (1)]), false);
     }
     break;
 
-  case 80:
-#line 472 "parse-gram.y"
+  case 78:
+#line 451 "../../src/parse-gram.y"
     { (yyval.chars) = (yyvsp[(1) - (1)].chars); }
     break;
 
     { (yyval.chars) = (yyvsp[(1) - (1)].chars); }
     break;
 
-  case 82:
-#line 479 "parse-gram.y"
+  case 80:
+#line 458 "../../src/parse-gram.y"
     {
     {
-      muscle_code_grow ("epilogue", (yyvsp[(2) - (2)].chars), (yylsp[(2) - (2)]));
-      scanner_last_string_free ();
+      muscle_code_grow ("epilogue", translate_code ((yyvsp[(2) - (2)].chars), (yylsp[(2) - (2)])), (yylsp[(2) - (2)]));
+      gram_scanner_last_string_free ();
     }
     break;
 
 
 /* Line 1267 of yacc.c.  */
     }
     break;
 
 
 /* Line 1267 of yacc.c.  */
-#line 2159 "parse-gram.c"
+#line 2144 "../../src/parse-gram.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2375,7 +2360,7 @@ yyreturn:
 }
 
 
 }
 
 
-#line 485 "parse-gram.y"
+#line 464 "../../src/parse-gram.y"
 
 
 
 
 
 
@@ -2457,7 +2442,7 @@ add_param (char const *type, char *decl, location loc)
       free (name);
     }
 
       free (name);
     }
 
-  scanner_last_string_free ();
+  gram_scanner_last_string_free ();
 }
 
 static void
 }
 
 static void
index 2d37fc10f0f4b0ede588e35a0fe0e6e6651e324a..2c5a09db2b790fcd50a74e068672c40885d58f5a 100644 (file)
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 2.2a.  */
+/* A Bison parser, made by GNU Bison 2.1b.  */
 
 /* Skeleton interface for Bison's Yacc-like parsers in C
 
 
 /* Skeleton interface for Bison's Yacc-like parsers in C
 
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-#line 94 "parse-gram.y"
+#line 95 "../../src/parse-gram.y"
 {
   symbol *symbol;
   symbol_list *list;
 {
   symbol *symbol;
   symbol_list *list;
@@ -158,7 +158,7 @@ typedef union YYSTYPE
   uniqstr uniqstr;
 }
 /* Line 1529 of yacc.c.  */
   uniqstr uniqstr;
 }
 /* Line 1529 of yacc.c.  */
-#line 162 "parse-gram.h"
+#line 162 "../../src/parse-gram.h"
        YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
        YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
index e189e1434611b97b87d868a3d8b7477ae8b88a93..a0c708b3e416edfebb9c85a6e5009d37a3e1c7bf 100644 (file)
@@ -32,6 +32,8 @@
 #include "quotearg.h"
 #include "reader.h"
 #include "symlist.h"
 #include "quotearg.h"
 #include "reader.h"
 #include "symlist.h"
+#include "scan-gram.h"
+#include "scan-code.h"
 #include "strverscmp.h"
 
 #define YYLLOC_DEFAULT(Current, Rhs, N)  (Current) = lloc_default (Rhs, N)
 #include "strverscmp.h"
 
 #define YYLLOC_DEFAULT(Current, Rhs, N)  (Current) = lloc_default (Rhs, N)
@@ -84,9 +86,8 @@ static int current_prec = 0;
 {
   /* Bison's grammar can initial empty locations, hence a default
      location is needed. */
 {
   /* Bison's grammar can initial empty locations, hence a default
      location is needed. */
-  @$.start.file   = @$.end.file   = current_file;
-  @$.start.line   = @$.end.line   = 1;
-  @$.start.column = @$.end.column = 0;
+  boundary_set (&@$.start, current_file, 1, 0);
+  boundary_set (&@$.end, current_file, 1, 0);
 }
 
 /* Only NUMBERS have a value.  */
 }
 
 /* Only NUMBERS have a value.  */
@@ -109,8 +110,8 @@ static int current_prec = 0;
 %token PERCENT_NTERM       "%nterm"
 
 %token PERCENT_TYPE        "%type"
 %token PERCENT_NTERM       "%nterm"
 
 %token PERCENT_TYPE        "%type"
-%token PERCENT_DESTRUCTOR  "%destructor {...}"
-%token PERCENT_PRINTER     "%printer {...}"
+%token PERCENT_DESTRUCTOR  "%destructor"
+%token PERCENT_PRINTER     "%printer"
 
 %token PERCENT_UNION       "%union {...}"
 
 
 %token PERCENT_UNION       "%union {...}"
 
@@ -137,8 +138,8 @@ static int current_prec = 0;
   PERCENT_EXPECT_RR      "%expect-rr"
   PERCENT_FILE_PREFIX     "%file-prefix"
   PERCENT_GLR_PARSER      "%glr-parser"
   PERCENT_EXPECT_RR      "%expect-rr"
   PERCENT_FILE_PREFIX     "%file-prefix"
   PERCENT_GLR_PARSER      "%glr-parser"
-  PERCENT_INITIAL_ACTION  "%initial-action {...}"
-  PERCENT_LEX_PARAM       "%lex-param {...}"
+  PERCENT_INITIAL_ACTION  "%initial-action"
+  PERCENT_LEX_PARAM       "%lex-param"
   PERCENT_LOCATIONS       "%locations"
   PERCENT_NAME_PREFIX     "%name-prefix"
   PERCENT_NO_DEFAULT_PREC "%no-default-prec"
   PERCENT_LOCATIONS       "%locations"
   PERCENT_NAME_PREFIX     "%name-prefix"
   PERCENT_NO_DEFAULT_PREC "%no-default-prec"
@@ -146,7 +147,7 @@ static int current_prec = 0;
   PERCENT_NONDETERMINISTIC_PARSER
                          "%nondeterministic-parser"
   PERCENT_OUTPUT          "%output"
   PERCENT_NONDETERMINISTIC_PARSER
                          "%nondeterministic-parser"
   PERCENT_OUTPUT          "%output"
-  PERCENT_PARSE_PARAM     "%parse-param {...}"
+  PERCENT_PARSE_PARAM     "%parse-param"
   PERCENT_PURE_PARSER     "%pure-parser"
   PERCENT_REQUIRE        "%require"
   PERCENT_SKELETON        "%skeleton"
   PERCENT_PURE_PARSER     "%pure-parser"
   PERCENT_REQUIRE        "%require"
   PERCENT_SKELETON        "%skeleton"
@@ -167,23 +168,14 @@ static int current_prec = 0;
 %token EPILOGUE        "epilogue"
 %token BRACED_CODE     "{...}"
 
 %token EPILOGUE        "epilogue"
 %token BRACED_CODE     "{...}"
 
-
 %type <chars> STRING string_content
 %type <chars> STRING string_content
-             "%destructor {...}"
-             "%initial-action {...}"
-             "%lex-param {...}"
-             "%parse-param {...}"
-             "%printer {...}"
+             "{...}"
              "%union {...}"
              PROLOGUE EPILOGUE
 %printer { fprintf (stderr, "\"%s\"", $$); }
              STRING string_content
 %printer { fprintf (stderr, "{\n%s\n}", $$); }
              "%union {...}"
              PROLOGUE EPILOGUE
 %printer { fprintf (stderr, "\"%s\"", $$); }
              STRING string_content
 %printer { fprintf (stderr, "{\n%s\n}", $$); }
-             "%destructor {...}"
-             "%initial-action {...}"
-             "%lex-param {...}"
-             "%parse-param {...}"
-             "%printer {...}"
+             "{...}"
              "%union {...}"
              PROLOGUE EPILOGUE
 %type <uniqstr> TYPE
              "%union {...}"
              PROLOGUE EPILOGUE
 %type <uniqstr> TYPE
@@ -214,7 +206,8 @@ declarations:
 
 declaration:
   grammar_declaration
 
 declaration:
   grammar_declaration
-| PROLOGUE                                 { prologue_augment ($1, @1); }
+| PROLOGUE                         { prologue_augment (translate_code ($1, @1),
+                                                      @1); }
 | "%debug"                                 { debug_flag = true; }
 | "%define" string_content
     {
 | "%debug"                                 { debug_flag = true; }
 | "%define" string_content
     {
@@ -232,17 +225,17 @@ declaration:
       nondeterministic_parser = true;
       glr_parser = true;
     }
       nondeterministic_parser = true;
       glr_parser = true;
     }
-| "%initial-action {...}"
+| "%initial-action" "{...}"
     {
     {
-      muscle_code_grow ("initial_action", $1, @1);
+      muscle_code_grow ("initial_action", translate_symbol_action ($2, @2), @2);
     }
     }
-| "%lex-param {...}"                      { add_param ("lex_param", $1, @1); }
+| "%lex-param" "{...}"                    { add_param ("lex_param", $2, @2); }
 | "%locations"                             { locations_flag = true; }
 | "%name-prefix" "=" string_content        { spec_name_prefix = $3; }
 | "%no-lines"                              { no_lines_flag = true; }
 | "%nondeterministic-parser"              { nondeterministic_parser = true; }
 | "%output" "=" string_content             { spec_outfile = $3; }
 | "%locations"                             { locations_flag = true; }
 | "%name-prefix" "=" string_content        { spec_name_prefix = $3; }
 | "%no-lines"                              { no_lines_flag = true; }
 | "%nondeterministic-parser"              { nondeterministic_parser = true; }
 | "%output" "=" string_content             { spec_outfile = $3; }
-| "%parse-param {...}"                    { add_param ("parse_param", $1, @1); }
+| "%parse-param" "{...}"                  { add_param ("parse_param", $2, @2); }
 | "%pure-parser"                           { pure_parser = true; }
 | "%require" string_content                { version_check (&@2, $2); }
 | "%skeleton" string_content               { skeleton = $2; }
 | "%pure-parser"                           { pure_parser = true; }
 | "%require" string_content                { version_check (&@2, $2); }
 | "%skeleton" string_content               { skeleton = $2; }
@@ -275,19 +268,21 @@ grammar_declaration:
       typed = true;
       muscle_code_grow ("stype", body, @1);
     }
       typed = true;
       muscle_code_grow ("stype", body, @1);
     }
-| "%destructor {...}" symbols.1
+| "%destructor" "{...}" symbols.1
     {
       symbol_list *list;
     {
       symbol_list *list;
-      for (list = $2; list; list = list->next)
-       symbol_destructor_set (list->sym, $1, @1);
-      symbol_list_free ($2);
+      const char *action = translate_symbol_action ($2, @2);
+      for (list = $3; list; list = list->next)
+       symbol_destructor_set (list->sym, action, @2);
+      symbol_list_free ($3);
     }
     }
-| "%printer {...}" symbols.1
+| "%printer" "{...}" symbols.1
     {
       symbol_list *list;
     {
       symbol_list *list;
-      for (list = $2; list; list = list->next)
-       symbol_printer_set (list->sym, $1, @1);
-      symbol_list_free ($2);
+      const char *action = translate_symbol_action ($2, @2);
+      for (list = $3; list; list = list->next)
+       symbol_printer_set (list->sym, action, @2);
+      symbol_list_free ($3);
     }
 | "%default-prec"
     {
     }
 | "%default-prec"
     {
@@ -346,7 +341,6 @@ type.opt:
 ;
 
 /* One or more nonterminals to be %typed. */
 ;
 
 /* One or more nonterminals to be %typed. */
-
 symbols.1:
   symbol            { $$ = symbol_list_new ($1, @1); }
 | symbols.1 symbol  { $$ = symbol_list_prepend ($1, $2, @2); }
 symbols.1:
   symbol            { $$ = symbol_list_new ($1, @1); }
 | symbols.1 symbol  { $$ = symbol_list_prepend ($1, $2, @2); }
@@ -426,7 +420,9 @@ rhs:
     { grammar_current_rule_begin (current_lhs, current_lhs_location); }
 | rhs symbol
     { grammar_current_rule_symbol_append ($2, @2); }
     { grammar_current_rule_begin (current_lhs, current_lhs_location); }
 | rhs symbol
     { grammar_current_rule_symbol_append ($2, @2); }
-| rhs action
+| rhs "{...}"
+    { grammar_current_rule_action_append (gram_last_string,
+                                         gram_last_braced_code_loc); }
 | rhs "%prec" symbol
     { grammar_current_rule_prec_set ($3, @3); }
 | rhs "%dprec" INT
 | rhs "%prec" symbol
     { grammar_current_rule_prec_set ($3, @3); }
 | rhs "%dprec" INT
@@ -440,23 +436,6 @@ symbol:
 | string_as_id    { $$ = $1; }
 ;
 
 | string_as_id    { $$ = $1; }
 ;
 
-/* Handle the semantics of an action specially, with a mid-rule
-   action, so that grammar_current_rule_action_append is invoked
-   immediately after the braced code is read by the scanner.
-
-   This implementation relies on the LALR(1) parsing algorithm.
-   If grammar_current_rule_action_append were executed in a normal
-   action for this rule, then when the input grammar contains two
-   successive actions, the scanner would have to read both actions
-   before reducing this rule.  That wouldn't work, since the scanner
-   relies on all preceding input actions being processed by
-   grammar_current_rule_action_append before it scans the next
-   action.  */
-action:
-    { grammar_current_rule_action_append (last_string, last_braced_code_loc); }
-  BRACED_CODE
-;
-
 /* A string used as an ID: quote it.  */
 string_as_id:
   STRING
 /* A string used as an ID: quote it.  */
 string_as_id:
   STRING
@@ -477,8 +456,8 @@ epilogue.opt:
   /* Nothing.  */
 | "%%" EPILOGUE
     {
   /* Nothing.  */
 | "%%" EPILOGUE
     {
-      muscle_code_grow ("epilogue", $2, @2);
-      scanner_last_string_free ();
+      muscle_code_grow ("epilogue", translate_code ($2, @2), @2);
+      gram_scanner_last_string_free ();
     }
 ;
 
     }
 ;
 
@@ -563,7 +542,7 @@ add_param (char const *type, char *decl, location loc)
       free (name);
     }
 
       free (name);
     }
 
-  scanner_last_string_free ();
+  gram_scanner_last_string_free ();
 }
 
 static void
 }
 
 static void
index d07ce5caa9e9c18b96bc989cfaf70cbbc07ae156..33b62c2cfaff5afda1d106d25171df323f0acc4b 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <config.h>
 #include "system.h"
 
 #include <config.h>
 #include "system.h"
+#include <assert.h>
 
 #include <quotearg.h>
 
 
 #include <quotearg.h>
 
@@ -34,6 +35,8 @@
 #include "reader.h"
 #include "symlist.h"
 #include "symtab.h"
 #include "reader.h"
 #include "symlist.h"
 #include "symtab.h"
+#include "scan-gram.h"
+#include "scan-code.h"
 
 static void check_and_convert_grammar (void);
 
 
 static void check_and_convert_grammar (void);
 
@@ -77,6 +80,8 @@ prologue_augment (const char *prologue, location loc)
     !typed ? &pre_prologue_obstack : &post_prologue_obstack;
 
   obstack_fgrow1 (oout, "]b4_syncline(%d, [[", loc.start.line);
     !typed ? &pre_prologue_obstack : &post_prologue_obstack;
 
   obstack_fgrow1 (oout, "]b4_syncline(%d, [[", loc.start.line);
+  /* FIXME: Protection of M4 characters missing here.  See
+     output.c:escaped_output.  */
   MUSCLE_OBSTACK_SGROW (oout,
                        quotearg_style (c_quoting_style, loc.start.file));
   obstack_sgrow (oout, "]])[\n");
   MUSCLE_OBSTACK_SGROW (oout,
                        quotearg_style (c_quoting_style, loc.start.file));
   obstack_sgrow (oout, "]])[\n");
@@ -398,9 +403,7 @@ grammar_current_rule_symbol_append (symbol *sym, location loc)
 void
 grammar_current_rule_action_append (const char *action, location loc)
 {
 void
 grammar_current_rule_action_append (const char *action, location loc)
 {
-  /* There's no need to invoke grammar_midrule_action here, since the
-     scanner already did it if necessary.  */
-  current_rule->action = action;
+  current_rule->action = translate_rule_action (current_rule, action, loc);
   current_rule->action_location = loc;
 }
 
   current_rule->action_location = loc;
 }
 
@@ -426,6 +429,7 @@ packgram (void)
 
   while (p)
     {
 
   while (p)
     {
+      int rule_length = 0;
       symbol *ruleprec = p->ruleprec;
       rules[ruleno].user_number = ruleno;
       rules[ruleno].number = ruleno;
       symbol *ruleprec = p->ruleprec;
       rules[ruleno].user_number = ruleno;
       rules[ruleno].number = ruleno;
@@ -440,18 +444,22 @@ packgram (void)
       rules[ruleno].action = p->action;
       rules[ruleno].action_location = p->action_location;
 
       rules[ruleno].action = p->action;
       rules[ruleno].action_location = p->action_location;
 
-      p = p->next;
-      while (p && p->sym)
+      for (p = p->next; p && p->sym; p = p->next)
        {
        {
+         ++rule_length;
+
+         /* Don't allow rule_length == INT_MAX, since that might
+            cause confusion with strtol if INT_MAX == LONG_MAX.  */
+         if (rule_length == INT_MAX)
+             fatal_at (rules[ruleno].location, _("rule is too long"));
+
          /* item_number = symbol_number.
             But the former needs to contain more: negative rule numbers. */
          ritem[itemno++] = symbol_number_as_item_number (p->sym->number);
          /* A rule gets by default the precedence and associativity
          /* item_number = symbol_number.
             But the former needs to contain more: negative rule numbers. */
          ritem[itemno++] = symbol_number_as_item_number (p->sym->number);
          /* A rule gets by default the precedence and associativity
-            of the last token in it.  */
+            of its last token.  */
          if (p->sym->class == token_sym && default_prec)
            rules[ruleno].prec = p->sym;
          if (p->sym->class == token_sym && default_prec)
            rules[ruleno].prec = p->sym;
-         if (p)
-           p = p->next;
        }
 
       /* If this rule has a %prec,
        }
 
       /* If this rule has a %prec,
@@ -461,8 +469,11 @@ packgram (void)
          rules[ruleno].precsym = ruleprec;
          rules[ruleno].prec = ruleprec;
        }
          rules[ruleno].precsym = ruleprec;
          rules[ruleno].prec = ruleprec;
        }
+      /* An item ends by the rule number (negated).  */
       ritem[itemno++] = rule_number_as_item_number (ruleno);
       ritem[itemno++] = rule_number_as_item_number (ruleno);
+      assert (itemno < ITEM_NUMBER_MAX);
       ++ruleno;
       ++ruleno;
+      assert (ruleno < RULE_NUMBER_MAX);
 
       if (p)
        p = p->next;
 
       if (p)
        p = p->next;
@@ -511,7 +522,7 @@ reader (void)
 
   gram__flex_debug = trace_flag & trace_scan;
   gram_debug = trace_flag & trace_parse;
 
   gram__flex_debug = trace_flag & trace_scan;
   gram_debug = trace_flag & trace_parse;
-  scanner_initialize ();
+  gram_scanner_initialize ();
   gram_parse ();
 
   if (! complaint_issued)
   gram_parse ();
 
   if (! complaint_issued)
index f110f70e7042e7513c18d88b96e4de657385f902..ec289f2d6911a44f8124f897595a482c9c0cc184 100644 (file)
@@ -35,26 +35,6 @@ typedef struct merger_list
   uniqstr type;
 } merger_list;
 
   uniqstr type;
 } merger_list;
 
-/* From the scanner.  */
-extern FILE *gram_in;
-extern int gram__flex_debug;
-extern boundary scanner_cursor;
-extern char *last_string;
-extern location last_braced_code_loc;
-extern int max_left_semantic_context;
-void scanner_initialize (void);
-void scanner_free (void);
-void scanner_last_string_free (void);
-
-/* These are declared by the scanner, but not used.  We put them here
-   to pacify "make syntax-check".  */
-extern FILE *gram_out;
-extern int gram_lineno;
-
-# define YY_DECL int gram_lex (YYSTYPE *val, location *loc)
-YY_DECL;
-
-
 /* From the parser.  */
 extern int gram_debug;
 int gram_parse (void);
 /* From the parser.  */
 extern int gram_debug;
 int gram_parse (void);
diff --git a/src/scan-action.l b/src/scan-action.l
new file mode 100644 (file)
index 0000000..f8dbf67
--- /dev/null
@@ -0,0 +1,866 @@
+/* Bison Grammar Scanner                             -*- C -*-
+
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+   This file is part of Bison, the GNU Compiler Compiler.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301  USA
+*/
+
+%option debug nodefault nounput noyywrap never-interactive
+%option prefix="gram_" outfile="lex.yy.c"
+
+%{
+#include "system.h"
+
+#include <mbswidth.h>
+#include <get-errno.h>
+#include <quote.h>
+
+#include "complain.h"
+#include "files.h"
+#include "getargs.h"
+#include "gram.h"
+#include "quotearg.h"
+#include "reader.h"
+#include "uniqstr.h"
+
+#define YY_USER_INIT                                   \
+  do                                                   \
+    {                                                  \
+      scanner_cursor.file = current_file;              \
+      scanner_cursor.line = 1;                         \
+      scanner_cursor.column = 1;                       \
+      code_start = scanner_cursor;                     \
+    }                                                  \
+  while (0)
+
+/* Location of scanner cursor.  */
+boundary scanner_cursor;
+
+static void adjust_location (location *, char const *, size_t);
+#define YY_USER_ACTION  adjust_location (loc, yytext, yyleng);
+
+static size_t no_cr_read (FILE *, char *, size_t);
+#define YY_INPUT(buf, result, size) ((result) = no_cr_read (yyin, buf, size))
+
+/* Within well-formed rules, RULE_LENGTH is the number of values in
+   the current rule so far, which says where to find `$0' with respect
+   to the top of the stack.  It is not the same as the rule->length in
+   the case of mid rule actions.
+
+   Outside of well-formed rules, RULE_LENGTH has an undefined value.  */
+int rule_length;
+
+static void handle_dollar (int token_type, char *cp, location loc);
+static void handle_at (int token_type, char *cp, location loc);
+static void handle_syncline (char *args);
+static unsigned long int scan_integer (char const *p, int base, location loc);
+static int convert_ucn_to_byte (char const *hex_text);
+static void unexpected_eof (boundary, char const *);
+static void unexpected_newline (boundary, char const *);
+
+%}
+%x SC_COMMENT SC_LINE_COMMENT SC_YACC_COMMENT
+%x SC_STRING SC_CHARACTER
+%x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
+%x SC_PRE_CODE SC_BRACED_CODE SC_PROLOGUE SC_EPILOGUE
+
+letter   [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
+id       {letter}({letter}|[0-9])*
+directive %{letter}({letter}|[0-9]|-)*
+int      [0-9]+
+
+/* POSIX says that a tag must be both an id and a C union member, but
+   historically almost any character is allowed in a tag.  We disallow
+   NUL and newline, as this simplifies our implementation.  */
+tag     [^\0\n>]+
+
+/* Zero or more instances of backslash-newline.  Following GCC, allow
+   white space between the backslash and the newline.  */
+splice  (\\[ \f\t\v]*\n)*
+
+%%
+%{
+  /* Nesting level of the current code in braces.  */
+  int braces_level IF_LINT (= 0);
+
+  /* Parent context state, when applicable.  */
+  int context_state IF_LINT (= 0);
+
+  /* Token type to return, when applicable.  */
+  int token_type IF_LINT (= 0);
+
+  /* Where containing code started, when applicable.  Its initial
+     value is relevant only when yylex is invoked in the SC_EPILOGUE
+     start condition.  */
+  boundary code_start = scanner_cursor;
+
+  /* Where containing comment or string or character literal started,
+     when applicable.  */
+  boundary token_start IF_LINT (= scanner_cursor);
+%}
+
+
+  /*-----------------------.
+  | Scanning white space.  |
+  `-----------------------*/
+
+<INITIAL>
+{
+  /* Comments and white space.  */
+  ","         warn_at (*loc, _("stray `,' treated as white space"));
+  [ \f\n\t\v]  |
+  "//".*       ;
+  "/*" {
+    token_start = loc->start;
+    context_state = YY_START;
+    BEGIN SC_YACC_COMMENT;
+  }
+
+  /* #line directives are not documented, and may be withdrawn or
+     modified in future versions of Bison.  */
+  ^"#line "{int}" \"".*"\"\n" {
+    handle_syncline (yytext + sizeof "#line " - 1);
+  }
+}
+
+
+  /*----------------------------.
+  | Scanning Bison directives.  |
+  `----------------------------*/
+<INITIAL>
+{
+
+  /* Code in between braces.  */
+  "{" {
+    STRING_GROW;
+    token_type = BRACED_CODE;
+    braces_level = 0;
+    code_start = loc->start;
+    BEGIN SC_BRACED_CODE;
+  }
+
+}
+
+
+  /*------------------------------------------------------------.
+  | Scanning a C comment.  The initial `/ *' is already eaten.  |
+  `------------------------------------------------------------*/
+
+<SC_COMMENT>
+{
+  "*"{splice}"/"  STRING_GROW; BEGIN context_state;
+  <<EOF>>        unexpected_eof (token_start, "*/"); BEGIN context_state;
+}
+
+
+  /*--------------------------------------------------------------.
+  | Scanning a line comment.  The initial `//' is already eaten.  |
+  `--------------------------------------------------------------*/
+
+<SC_LINE_COMMENT>
+{
+  "\n"          STRING_GROW; BEGIN context_state;
+  {splice}      STRING_GROW;
+  <<EOF>>       BEGIN context_state;
+}
+
+
+  /*------------------------------------------------.
+  | Scanning a Bison string, including its escapes. |
+  | The initial quote is already eaten.             |
+  `------------------------------------------------*/
+
+<SC_ESCAPED_STRING>
+{
+  "\"" {
+    STRING_FINISH;
+    loc->start = token_start;
+    val->chars = last_string;
+    rule_length++;
+    BEGIN INITIAL;
+    return STRING;
+  }
+  \n           unexpected_newline (token_start, "\""); BEGIN INITIAL;
+  <<EOF>>      unexpected_eof (token_start, "\"");     BEGIN INITIAL;
+}
+
+  /*----------------------------------------------------------.
+  | Scanning a Bison character literal, decoding its escapes. |
+  | The initial quote is already eaten.                              |
+  `----------------------------------------------------------*/
+
+<SC_ESCAPED_CHARACTER>
+{
+  "'" {
+    unsigned char last_string_1;
+    STRING_GROW;
+    STRING_FINISH;
+    loc->start = token_start;
+    val->symbol = symbol_get (quotearg_style (escape_quoting_style,
+                                             last_string),
+                             *loc);
+    symbol_class_set (val->symbol, token_sym, *loc);
+    last_string_1 = last_string[1];
+    symbol_user_token_number_set (val->symbol, last_string_1, *loc);
+    STRING_FREE;
+    rule_length++;
+    BEGIN INITIAL;
+    return ID;
+  }
+  \n           unexpected_newline (token_start, "'");  BEGIN INITIAL;
+  <<EOF>>      unexpected_eof (token_start, "'");      BEGIN INITIAL;
+}
+
+<SC_ESCAPED_CHARACTER,SC_ESCAPED_STRING>
+{
+  \0       complain_at (*loc, _("invalid null character"));
+}
+
+
+  /*----------------------------.
+  | Decode escaped characters.  |
+  `----------------------------*/
+
+<SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>
+{
+  \\[0-7]{1,3} {
+    unsigned long int c = strtoul (yytext + 1, 0, 8);
+    if (UCHAR_MAX < c)
+      complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext));
+    else if (! c)
+      complain_at (*loc, _("invalid null character: %s"), quote (yytext));
+    else
+      obstack_1grow (&obstack_for_string, c);
+  }
+
+  \\x[0-9abcdefABCDEF]+ {
+    unsigned long int c;
+    set_errno (0);
+    c = strtoul (yytext + 2, 0, 16);
+    if (UCHAR_MAX < c || get_errno ())
+      complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext));
+    else if (! c)
+      complain_at (*loc, _("invalid null character: %s"), quote (yytext));
+    else
+      obstack_1grow (&obstack_for_string, c);
+  }
+
+  \\a  obstack_1grow (&obstack_for_string, '\a');
+  \\b  obstack_1grow (&obstack_for_string, '\b');
+  \\f  obstack_1grow (&obstack_for_string, '\f');
+  \\n  obstack_1grow (&obstack_for_string, '\n');
+  \\r  obstack_1grow (&obstack_for_string, '\r');
+  \\t  obstack_1grow (&obstack_for_string, '\t');
+  \\v  obstack_1grow (&obstack_for_string, '\v');
+
+  /* \\[\"\'?\\] would be shorter, but it confuses xgettext.  */
+  \\("\""|"'"|"?"|"\\")  obstack_1grow (&obstack_for_string, yytext[1]);
+
+  \\(u|U[0-9abcdefABCDEF]{4})[0-9abcdefABCDEF]{4} {
+    int c = convert_ucn_to_byte (yytext);
+    if (c < 0)
+      complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext));
+    else if (! c)
+      complain_at (*loc, _("invalid null character: %s"), quote (yytext));
+    else
+      obstack_1grow (&obstack_for_string, c);
+  }
+  \\(.|\n)     {
+    complain_at (*loc, _("unrecognized escape sequence: %s"), quote (yytext));
+    STRING_GROW;
+  }
+}
+
+  /*--------------------------------------------.
+  | Scanning user-code characters and strings.  |
+  `--------------------------------------------*/
+
+<SC_CHARACTER,SC_STRING>
+{
+  {splice}|\\{splice}[^\n$@\[\]]       STRING_GROW;
+}
+
+<SC_CHARACTER>
+{
+  "'"          STRING_GROW; BEGIN context_state;
+  \n           unexpected_newline (token_start, "'"); BEGIN context_state;
+  <<EOF>>      unexpected_eof (token_start, "'"); BEGIN context_state;
+}
+
+<SC_STRING>
+{
+  "\""         STRING_GROW; BEGIN context_state;
+  \n           unexpected_newline (token_start, "\""); BEGIN context_state;
+  <<EOF>>      unexpected_eof (token_start, "\""); BEGIN context_state;
+}
+
+
+  /*---------------------------------------------------.
+  | Strings, comments etc. can be found in user code.  |
+  `---------------------------------------------------*/
+
+<INITIAL>
+{
+  "'" {
+    STRING_GROW;
+    context_state = YY_START;
+    token_start = loc->start;
+    BEGIN SC_CHARACTER;
+  }
+  "\"" {
+    STRING_GROW;
+    context_state = YY_START;
+    token_start = loc->start;
+    BEGIN SC_STRING;
+  }
+  "/"{splice}"*" {
+    STRING_GROW;
+    context_state = YY_START;
+    token_start = loc->start;
+    BEGIN SC_COMMENT;
+  }
+  "/"{splice}"/" {
+    STRING_GROW;
+    context_state = YY_START;
+    BEGIN SC_LINE_COMMENT;
+  }
+}
+
+
+  /*---------------------------------------------------------------.
+  | Scanning some code in braces (%union and actions). The initial |
+  | "{" is already eaten.                                          |
+  `---------------------------------------------------------------*/
+
+<INITIAL>
+{
+  "{"|"<"{splice}"%"  STRING_GROW; braces_level++;
+  "%"{splice}">"      STRING_GROW; braces_level--;
+  "}" {
+    bool outer_brace = --braces_level < 0;
+
+    /* As an undocumented Bison extension, append `;' before the last
+       brace in braced code, so that the user code can omit trailing
+       `;'.  But do not append `;' if emulating Yacc, since Yacc does
+       not append one.
+
+       FIXME: Bison should warn if a semicolon seems to be necessary
+       here, and should omit the semicolon if it seems unnecessary
+       (e.g., after ';', '{', or '}', each followed by comments or
+       white space).  Such a warning shouldn't depend on --yacc; it
+       should depend on a new --pedantic option, which would cause
+       Bison to warn if it detects an extension to POSIX.  --pedantic
+       should also diagnose other Bison extensions like %yacc.
+       Perhaps there should also be a GCC-style --pedantic-errors
+       option, so that such warnings are diagnosed as errors.  */
+    if (outer_brace && token_type == BRACED_CODE && ! yacc_flag)
+      obstack_1grow (&obstack_for_string, ';');
+
+    obstack_1grow (&obstack_for_string, '}');
+
+    if (outer_brace)
+      {
+       STRING_FINISH;
+       rule_length++;
+       loc->start = code_start;
+       val->chars = last_string;
+       BEGIN INITIAL;
+       return token_type;
+      }
+  }
+
+  /* Tokenize `<<%' correctly (as `<<' `%') rather than incorrrectly
+     (as `<' `<%').  */
+  "<"{splice}"<"  STRING_GROW;
+
+  "$"("<"{tag}">")?(-?[0-9]+|"$")  handle_dollar (token_type, yytext, *loc);
+  "@"(-?[0-9]+|"$")               handle_at (token_type, yytext, *loc);
+
+  <<EOF>>  unexpected_eof (code_start, "}"); BEGIN INITIAL;
+}
+
+
+  /*--------------------------------------------------------------.
+  | Scanning some prologue: from "%{" (already scanned) to "%}".  |
+  `--------------------------------------------------------------*/
+
+<SC_PROLOGUE>
+{
+  "%}" {
+    STRING_FINISH;
+    loc->start = code_start;
+    val->chars = last_string;
+    BEGIN INITIAL;
+    return PROLOGUE;
+  }
+
+  <<EOF>>  unexpected_eof (code_start, "%}"); BEGIN INITIAL;
+}
+
+
+  /*---------------------------------------------------------------.
+  | Scanning the epilogue (everything after the second "%%", which |
+  | has already been eaten).                                       |
+  `---------------------------------------------------------------*/
+
+<SC_EPILOGUE>
+{
+  <<EOF>> {
+    STRING_FINISH;
+    loc->start = code_start;
+    val->chars = last_string;
+    BEGIN INITIAL;
+    return EPILOGUE;
+  }
+}
+
+
+  /*-----------------------------------------.
+  | Escape M4 quoting characters in C code.  |
+  `-----------------------------------------*/
+
+<SC_COMMENT,SC_LINE_COMMENT,SC_STRING,SC_CHARACTER,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
+{
+  \$   obstack_sgrow (&obstack_for_string, "$][");
+  \@   obstack_sgrow (&obstack_for_string, "@@");
+  \[   obstack_sgrow (&obstack_for_string, "@{");
+  \]   obstack_sgrow (&obstack_for_string, "@}");
+}
+
+
+  /*-----------------------------------------------------.
+  | By default, grow the string obstack with the input.  |
+  `-----------------------------------------------------*/
+
+<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE,SC_STRING,SC_CHARACTER,SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>.     |
+<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>\n  STRING_GROW;
+
+%%
+
+/* Keeps track of the maximum number of semantic values to the left of
+   a handle (those referenced by $0, $-1, etc.) are required by the
+   semantic actions of this grammar. */
+int max_left_semantic_context = 0;
+
+/* Set *LOC and adjust scanner cursor to account for token TOKEN of
+   size SIZE.  */
+
+static void
+adjust_location (location *loc, char const *token, size_t size)
+{
+  int line = scanner_cursor.line;
+  int column = scanner_cursor.column;
+  char const *p0 = token;
+  char const *p = token;
+  char const *lim = token + size;
+
+  loc->start = scanner_cursor;
+
+  for (p = token; p < lim; p++)
+    switch (*p)
+      {
+      case '\n':
+       line++;
+       column = 1;
+       p0 = p + 1;
+       break;
+
+      case '\t':
+       column += mbsnwidth (p0, p - p0, 0);
+       column += 8 - ((column - 1) & 7);
+       p0 = p + 1;
+       break;
+      }
+
+  scanner_cursor.line = line;
+  scanner_cursor.column = column + mbsnwidth (p0, p - p0, 0);
+
+  loc->end = scanner_cursor;
+}
+
+
+/* Read bytes from FP into buffer BUF of size SIZE.  Return the
+   number of bytes read.  Remove '\r' from input, treating \r\n
+   and isolated \r as \n.  */
+
+static size_t
+no_cr_read (FILE *fp, char *buf, size_t size)
+{
+  size_t bytes_read = fread (buf, 1, size, fp);
+  if (bytes_read)
+    {
+      char *w = memchr (buf, '\r', bytes_read);
+      if (w)
+       {
+         char const *r = ++w;
+         char const *lim = buf + bytes_read;
+
+         for (;;)
+           {
+             /* Found an '\r'.  Treat it like '\n', but ignore any
+                '\n' that immediately follows.  */
+             w[-1] = '\n';
+             if (r == lim)
+               {
+                 int ch = getc (fp);
+                 if (ch != '\n' && ungetc (ch, fp) != ch)
+                   break;
+               }
+             else if (*r == '\n')
+               r++;
+
+             /* Copy until the next '\r'.  */
+             do
+               {
+                 if (r == lim)
+                   return w - buf;
+               }
+             while ((*w++ = *r++) != '\r');
+           }
+
+         return w - buf;
+       }
+    }
+
+  return bytes_read;
+}
+
+
+/*------------------------------------------------------------------.
+| TEXT is pointing to a wannabee semantic value (i.e., a `$').      |
+|                                                                   |
+| Possible inputs: $[<TYPENAME>]($|integer)                         |
+|                                                                   |
+| Output to OBSTACK_FOR_STRING a reference to this semantic value.  |
+`------------------------------------------------------------------*/
+
+static inline bool
+handle_action_dollar (char *text, location loc)
+{
+  const char *type_name = NULL;
+  char *cp = text + 1;
+
+  if (! current_rule)
+    return false;
+
+  /* Get the type name if explicit. */
+  if (*cp == '<')
+    {
+      type_name = ++cp;
+      while (*cp != '>')
+       ++cp;
+      *cp = '\0';
+      ++cp;
+    }
+
+  if (*cp == '$')
+    {
+      if (!type_name)
+       type_name = symbol_list_n_type_name_get (current_rule, loc, 0);
+      if (!type_name && typed)
+       complain_at (loc, _("$$ of `%s' has no declared type"),
+                    current_rule->sym->tag);
+      if (!type_name)
+       type_name = "";
+      obstack_fgrow1 (&obstack_for_string,
+                     "]b4_lhs_value([%s])[", type_name);
+    }
+  else
+    {
+      long int num;
+      set_errno (0);
+      num = strtol (cp, 0, 10);
+
+      if (INT_MIN <= num && num <= rule_length && ! get_errno ())
+       {
+         int n = num;
+         if (1-n > max_left_semantic_context)
+           max_left_semantic_context = 1-n;
+         if (!type_name && n > 0)
+           type_name = symbol_list_n_type_name_get (current_rule, loc, n);
+         if (!type_name && typed)
+           complain_at (loc, _("$%d of `%s' has no declared type"),
+                        n, current_rule->sym->tag);
+         if (!type_name)
+           type_name = "";
+         obstack_fgrow3 (&obstack_for_string,
+                         "]b4_rhs_value(%d, %d, [%s])[",
+                         rule_length, n, type_name);
+       }
+      else
+       complain_at (loc, _("integer out of range: %s"), quote (text));
+    }
+
+  return true;
+}
+
+
+/*----------------------------------------------------------------.
+| Map `$?' onto the proper M4 symbol, depending on its TOKEN_TYPE |
+| (are we in an action?).                                         |
+`----------------------------------------------------------------*/
+
+static void
+handle_dollar (int token_type, char *text, location loc)
+{
+  switch (token_type)
+    {
+    case BRACED_CODE:
+      if (handle_action_dollar (text, loc))
+       return;
+      break;
+
+    case PERCENT_DESTRUCTOR:
+    case PERCENT_INITIAL_ACTION:
+    case PERCENT_PRINTER:
+      if (text[1] == '$')
+       {
+         obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar[");
+         return;
+       }
+      break;
+
+    default:
+      break;
+    }
+
+  complain_at (loc, _("invalid value: %s"), quote (text));
+}
+
+
+/*------------------------------------------------------.
+| TEXT is a location token (i.e., a `@...').  Output to |
+| OBSTACK_FOR_STRING a reference to this location.      |
+`------------------------------------------------------*/
+
+static inline bool
+handle_action_at (char *text, location loc)
+{
+  char *cp = text + 1;
+  locations_flag = true;
+
+  if (! current_rule)
+    return false;
+
+  if (*cp == '$')
+    obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
+  else
+    {
+      long int num;
+      set_errno (0);
+      num = strtol (cp, 0, 10);
+
+      if (INT_MIN <= num && num <= rule_length && ! get_errno ())
+       {
+         int n = num;
+         obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
+                         rule_length, n);
+       }
+      else
+       complain_at (loc, _("integer out of range: %s"), quote (text));
+    }
+
+  return true;
+}
+
+
+/*----------------------------------------------------------------.
+| Map `@?' onto the proper M4 symbol, depending on its TOKEN_TYPE |
+| (are we in an action?).                                         |
+`----------------------------------------------------------------*/
+
+static void
+handle_at (int token_type, char *text, location loc)
+{
+  switch (token_type)
+    {
+    case BRACED_CODE:
+      handle_action_at (text, loc);
+      return;
+
+    case PERCENT_INITIAL_ACTION:
+    case PERCENT_DESTRUCTOR:
+    case PERCENT_PRINTER:
+      if (text[1] == '$')
+       {
+         obstack_sgrow (&obstack_for_string, "]b4_at_dollar[");
+         return;
+       }
+      break;
+
+    default:
+      break;
+    }
+
+  complain_at (loc, _("invalid value: %s"), quote (text));
+}
+
+
+/*------------------------------------------------------.
+| Scan NUMBER for a base-BASE integer at location LOC.  |
+`------------------------------------------------------*/
+
+static unsigned long int
+scan_integer (char const *number, int base, location loc)
+{
+  unsigned long int num;
+  set_errno (0);
+  num = strtoul (number, 0, base);
+  if (INT_MAX < num || get_errno ())
+    {
+      complain_at (loc, _("integer out of range: %s"), quote (number));
+      num = INT_MAX;
+    }
+  return num;
+}
+
+
+/*------------------------------------------------------------------.
+| Convert universal character name UCN to a single-byte character,  |
+| and return that character.  Return -1 if UCN does not correspond  |
+| to a single-byte character.                                      |
+`------------------------------------------------------------------*/
+
+static int
+convert_ucn_to_byte (char const *ucn)
+{
+  unsigned long int code = strtoul (ucn + 2, 0, 16);
+
+  /* FIXME: Currently we assume Unicode-compatible unibyte characters
+     on ASCII hosts (i.e., Latin-1 on hosts with 8-bit bytes).  On
+     non-ASCII hosts we support only the portable C character set.
+     These limitations should be removed once we add support for
+     multibyte characters.  */
+
+  if (UCHAR_MAX < code)
+    return -1;
+
+#if ! ('$' == 0x24 && '@' == 0x40 && '`' == 0x60 && '~' == 0x7e)
+  {
+    /* A non-ASCII host.  Use CODE to index into a table of the C
+       basic execution character set, which is guaranteed to exist on
+       all Standard C platforms.  This table also includes '$', '@',
+       and '`', which are not in the basic execution character set but
+       which are unibyte characters on all the platforms that we know
+       about.  */
+    static signed char const table[] =
+      {
+       '\0',   -1,   -1,   -1,   -1,   -1,   -1, '\a',
+       '\b', '\t', '\n', '\v', '\f', '\r',   -1,   -1,
+         -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+         -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+        ' ',  '!',  '"',  '#',  '$',  '%',  '&', '\'',
+        '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
+        '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
+        '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
+        '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',
+        'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
+        'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
+        'X',  'Y',  'Z',  '[', '\\',  ']',  '^',  '_',
+        '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',
+        'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
+        'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
+        'x',  'y',  'z',  '{',  '|',  '}',  '~'
+      };
+
+    code = code < sizeof table ? table[code] : -1;
+  }
+#endif
+
+  return code;
+}
+
+
+/*----------------------------------------------------------------.
+| Handle `#line INT "FILE"'.  ARGS has already skipped `#line '.  |
+`----------------------------------------------------------------*/
+
+static void
+handle_syncline (char *args)
+{
+  int lineno = strtol (args, &args, 10);
+  const char *file = NULL;
+  file = strchr (args, '"') + 1;
+  *strchr (file, '"') = 0;
+  scanner_cursor.file = current_file = uniqstr_new (file);
+  scanner_cursor.line = lineno;
+  scanner_cursor.column = 1;
+}
+
+
+/*----------------------------------------------------------------.
+| For a token or comment starting at START, report message MSGID, |
+| which should say that an end marker was found before           |
+| the expected TOKEN_END.                                        |
+`----------------------------------------------------------------*/
+
+static void
+unexpected_end (boundary start, char const *msgid, char const *token_end)
+{
+  location loc;
+  loc.start = start;
+  loc.end = scanner_cursor;
+  complain_at (loc, _(msgid), token_end);
+}
+
+
+/*------------------------------------------------------------------------.
+| Report an unexpected EOF in a token or comment starting at START.       |
+| An end of file was encountered and the expected TOKEN_END was missing.  |
+`------------------------------------------------------------------------*/
+
+static void
+unexpected_eof (boundary start, char const *token_end)
+{
+  unexpected_end (start, N_("missing `%s' at end of file"), token_end);
+}
+
+
+/*----------------------------------------.
+| Likewise, but for unexpected newlines.  |
+`----------------------------------------*/
+
+static void
+unexpected_newline (boundary start, char const *token_end)
+{
+  unexpected_end (start, N_("missing `%s' at end of line"), token_end);
+}
+
+
+/*-------------------------.
+| Initialize the scanner.  |
+`-------------------------*/
+
+void
+scanner_initialize (void)
+{
+  obstack_init (&obstack_for_string);
+}
+
+
+/*-----------------------------------------------.
+| Free all the memory allocated to the scanner.  |
+`-----------------------------------------------*/
+
+void
+scanner_free (void)
+{
+  obstack_free (&obstack_for_string, 0);
+  /* Reclaim Flex's buffers.  */
+  yy_delete_buffer (YY_CURRENT_BUFFER);
+}
diff --git a/src/scan-code-c.c b/src/scan-code-c.c
new file mode 100644 (file)
index 0000000..fd60856
--- /dev/null
@@ -0,0 +1,2 @@
+#include <config.h>
+#include "scan-code.c"
diff --git a/src/scan-code.h b/src/scan-code.h
new file mode 100644 (file)
index 0000000..8d97935
--- /dev/null
@@ -0,0 +1,47 @@
+/* Bison Action Scanner
+
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+   This file is part of Bison, the GNU Compiler Compiler.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301  USA
+*/
+
+#ifndef SCAN_CODE_H_
+# define SCAN_CODE_H_
+
+# include "location.h"
+# include "symlist.h"
+
+/* Keeps track of the maximum number of semantic values to the left of
+   a handle (those referenced by $0, $-1, etc.) are required by the
+   semantic actions of this grammar. */
+extern int max_left_semantic_context;
+
+void code_scanner_free (void);
+
+/* The action A contains $$, $1 etc. referring to the values
+   of the rule R. */
+const char *translate_rule_action (symbol_list *r, const char *a, location l);
+
+/* The action A refers to $$ and @$ only, referring to a symbol. */
+const char *translate_symbol_action (const char *a, location l);
+
+/* The action contains no special escapes, just protect M4 special
+   symbols.  */
+const char *translate_code (const char *a, location l);
+
+#endif /* !SCAN_CODE_H_ */
diff --git a/src/scan-code.l b/src/scan-code.l
new file mode 100644 (file)
index 0000000..70b250b
--- /dev/null
@@ -0,0 +1,358 @@
+/* Bison Action Scanner                             -*- C -*-
+
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+   This file is part of Bison, the GNU Compiler Compiler.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301  USA
+*/
+
+%option debug nodefault nounput noyywrap never-interactive
+%option prefix="code_" outfile="lex.yy.c"
+
+%{
+/* Work around a bug in flex 2.5.31.  See Debian bug 333231
+   <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>.  */
+#undef code_wrap
+#define code_wrap() 1
+
+#define FLEX_PREFIX(Id) code_ ## Id
+#include "flex-scanner.h"
+#include "reader.h"
+#include "getargs.h"
+#include <assert.h>
+#include <get-errno.h>
+#include <quote.h>
+
+#include "scan-code.h"
+
+/* The current calling start condition: SC_RULE_ACTION or
+   SC_SYMBOL_ACTION. */
+# define YY_DECL const char *code_lex (int sc_context)
+YY_DECL;
+
+#define YY_USER_ACTION  location_compute (loc, &loc->end, yytext, yyleng);
+
+static void handle_action_dollar (char *cp, location loc);
+static void handle_action_at (char *cp, location loc);
+static location the_location;
+static location *loc = &the_location;
+
+/* The rule being processed. */
+symbol_list *current_rule;
+%}
+ /* C and C++ comments in code. */
+%x SC_COMMENT SC_LINE_COMMENT
+ /* Strings and characters in code. */
+%x SC_STRING SC_CHARACTER
+ /* Whether in a rule or symbol action.  Specifies the translation
+    of $ and @.  */
+%x SC_RULE_ACTION SC_SYMBOL_ACTION
+
+
+/* POSIX says that a tag must be both an id and a C union member, but
+   historically almost any character is allowed in a tag.  We disallow
+   NUL and newline, as this simplifies our implementation.  */
+tag     [^\0\n>]+
+
+/* Zero or more instances of backslash-newline.  Following GCC, allow
+   white space between the backslash and the newline.  */
+splice  (\\[ \f\t\v]*\n)*
+
+%%
+
+%{
+  /* This scanner is special: it is invoked only once, henceforth
+     is expected to return only once.  This initialization is
+     therefore done once per action to translate. */
+  assert (sc_context == SC_SYMBOL_ACTION
+         || sc_context == SC_RULE_ACTION
+         || sc_context == INITIAL);
+  BEGIN sc_context;
+%}
+
+  /*------------------------------------------------------------.
+  | Scanning a C comment.  The initial `/ *' is already eaten.  |
+  `------------------------------------------------------------*/
+
+<SC_COMMENT>
+{
+  "*"{splice}"/"  STRING_GROW; BEGIN sc_context;
+}
+
+
+  /*--------------------------------------------------------------.
+  | Scanning a line comment.  The initial `//' is already eaten.  |
+  `--------------------------------------------------------------*/
+
+<SC_LINE_COMMENT>
+{
+  "\n"          STRING_GROW; BEGIN sc_context;
+  {splice}      STRING_GROW;
+}
+
+
+  /*--------------------------------------------.
+  | Scanning user-code characters and strings.  |
+  `--------------------------------------------*/
+
+<SC_CHARACTER,SC_STRING>
+{
+  {splice}|\\{splice}. STRING_GROW;
+}
+
+<SC_CHARACTER>
+{
+  "'"          STRING_GROW; BEGIN sc_context;
+}
+
+<SC_STRING>
+{
+  "\""         STRING_GROW; BEGIN sc_context;
+}
+
+
+<SC_RULE_ACTION,SC_SYMBOL_ACTION>{
+  "'" {
+    STRING_GROW;
+    BEGIN SC_CHARACTER;
+  }
+  "\"" {
+    STRING_GROW;
+    BEGIN SC_STRING;
+  }
+  "/"{splice}"*" {
+    STRING_GROW;
+    BEGIN SC_COMMENT;
+  }
+  "/"{splice}"/" {
+    STRING_GROW;
+    BEGIN SC_LINE_COMMENT;
+  }
+}
+
+<SC_RULE_ACTION>
+{
+  "$"("<"{tag}">")?(-?[0-9]+|"$")   handle_action_dollar (yytext, *loc);
+  "@"(-?[0-9]+|"$")                handle_action_at (yytext, *loc);
+
+  "$"  {
+    warn_at (*loc, _("stray `$'"));
+    obstack_sgrow (&obstack_for_string, "$][");
+  }
+  "@"  {
+    warn_at (*loc, _("stray `@'"));
+    obstack_sgrow (&obstack_for_string, "@@");
+  }
+}
+
+<SC_SYMBOL_ACTION>
+{
+  "$$"   obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar[");
+  "@$"   obstack_sgrow (&obstack_for_string, "]b4_at_dollar[");
+}
+
+
+  /*-----------------------------------------.
+  | Escape M4 quoting characters in C code.  |
+  `-----------------------------------------*/
+
+<*>
+{
+  \$   obstack_sgrow (&obstack_for_string, "$][");
+  \@   obstack_sgrow (&obstack_for_string, "@@");
+  \[   obstack_sgrow (&obstack_for_string, "@{");
+  \]   obstack_sgrow (&obstack_for_string, "@}");
+}
+
+  /*-----------------------------------------------------.
+  | By default, grow the string obstack with the input.  |
+  `-----------------------------------------------------*/
+
+<*>.|\n        STRING_GROW;
+
+ /* End of processing. */
+<*><<EOF>>      {
+                   obstack_1grow (&obstack_for_string, '\0');
+                  return obstack_finish (&obstack_for_string);
+                 }
+
+%%
+
+/* Keeps track of the maximum number of semantic values to the left of
+   a handle (those referenced by $0, $-1, etc.) are required by the
+   semantic actions of this grammar. */
+int max_left_semantic_context = 0;
+
+
+/*------------------------------------------------------------------.
+| TEXT is pointing to a wannabee semantic value (i.e., a `$').      |
+|                                                                   |
+| Possible inputs: $[<TYPENAME>]($|integer)                         |
+|                                                                   |
+| Output to OBSTACK_FOR_STRING a reference to this semantic value.  |
+`------------------------------------------------------------------*/
+
+static void
+handle_action_dollar (char *text, location loc)
+{
+  const char *type_name = NULL;
+  char *cp = text + 1;
+  int rule_length = symbol_list_length (current_rule->next);
+
+  /* Get the type name if explicit. */
+  if (*cp == '<')
+    {
+      type_name = ++cp;
+      while (*cp != '>')
+       ++cp;
+      *cp = '\0';
+      ++cp;
+    }
+
+  if (*cp == '$')
+    {
+      if (!type_name)
+       type_name = symbol_list_n_type_name_get (current_rule, loc, 0);
+      if (!type_name && typed)
+       complain_at (loc, _("$$ of `%s' has no declared type"),
+                    current_rule->sym->tag);
+      if (!type_name)
+       type_name = "";
+      obstack_fgrow1 (&obstack_for_string,
+                     "]b4_lhs_value([%s])[", type_name);
+      current_rule->used = true;
+    }
+  else
+    {
+      long int num;
+      set_errno (0);
+      num = strtol (cp, 0, 10);
+      if (INT_MIN <= num && num <= rule_length && ! get_errno ())
+       {
+         int n = num;
+         if (1-n > max_left_semantic_context)
+           max_left_semantic_context = 1-n;
+         if (!type_name && n > 0)
+           type_name = symbol_list_n_type_name_get (current_rule, loc, n);
+         if (!type_name && typed)
+           complain_at (loc, _("$%d of `%s' has no declared type"),
+                        n, current_rule->sym->tag);
+         if (!type_name)
+           type_name = "";
+         obstack_fgrow3 (&obstack_for_string,
+                         "]b4_rhs_value(%d, %d, [%s])[",
+                         rule_length, n, type_name);
+         symbol_list_n_used_set (current_rule, n, true);
+       }
+      else
+       complain_at (loc, _("integer out of range: %s"), quote (text));
+    }
+}
+
+
+/*------------------------------------------------------.
+| TEXT is a location token (i.e., a `@...').  Output to |
+| OBSTACK_FOR_STRING a reference to this location.      |
+`------------------------------------------------------*/
+
+static void
+handle_action_at (char *text, location loc)
+{
+  char *cp = text + 1;
+  int rule_length = symbol_list_length (current_rule->next);
+  locations_flag = true;
+
+  if (*cp == '$')
+    obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
+  else
+    {
+      long int num;
+      set_errno (0);
+      num = strtol (cp, 0, 10);
+
+      if (INT_MIN <= num && num <= rule_length && ! get_errno ())
+       {
+         int n = num;
+         obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
+                         rule_length, n);
+       }
+      else
+       complain_at (loc, _("integer out of range: %s"), quote (text));
+    }
+}
+
+
+/*-------------------------.
+| Initialize the scanner.  |
+`-------------------------*/
+
+/* Translate the dollars and ats in \a a, whose location is l.
+   Depending on the \a sc_context (SC_RULE_ACTION, SC_SYMBOL_ACTION,
+   INITIAL), the processing is different.  */
+
+static const char *
+translate_action (int sc_context, const char *a, location l)
+{
+  const char *res;
+  static bool initialized = false;
+  if (!initialized)
+    {
+      obstack_init (&obstack_for_string);
+      /* The initial buffer, never used. */
+      yy_delete_buffer (YY_CURRENT_BUFFER);
+      yy_flex_debug = 0;
+      initialized = true;
+    }
+
+  loc->start = loc->end = l.start;
+  yy_switch_to_buffer (yy_scan_string (a));
+  res = code_lex (sc_context);
+  yy_delete_buffer (YY_CURRENT_BUFFER);
+
+  return res;
+}
+
+const char *
+translate_rule_action (symbol_list *r, const char *a, location l)
+{
+  current_rule = r;
+  return translate_action (SC_RULE_ACTION, a, l);
+}
+
+const char *
+translate_symbol_action (const char *a, location l)
+{
+  return translate_action (SC_SYMBOL_ACTION, a, l);
+}
+
+const char *
+translate_code (const char *a, location l)
+{
+  return translate_action (INITIAL, a, l);
+}
+
+/*-----------------------------------------------.
+| Free all the memory allocated to the scanner.  |
+`-----------------------------------------------*/
+
+void
+code_scanner_free (void)
+{
+  obstack_free (&obstack_for_string, 0);
+  /* Reclaim Flex's buffers.  */
+  yy_delete_buffer (YY_CURRENT_BUFFER);
+}
diff --git a/src/scan-gram.h b/src/scan-gram.h
new file mode 100644 (file)
index 0000000..4e00dfa
--- /dev/null
@@ -0,0 +1,44 @@
+/* Bison Grammar Scanner
+
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+   This file is part of Bison, the GNU Compiler Compiler.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301  USA
+*/
+
+#ifndef SCAN_GRAM_H_
+# define SCAN_GRAM_H_
+
+/* From the scanner.  */
+extern FILE *gram_in;
+extern int gram__flex_debug;
+extern boundary gram_scanner_cursor;
+extern char *gram_last_string;
+extern location gram_last_braced_code_loc;
+void gram_scanner_initialize (void);
+void gram_scanner_free (void);
+void gram_scanner_last_string_free (void);
+
+/* These are declared by the scanner, but not used.  We put them here
+   to pacify "make syntax-check".  */
+extern FILE *gram_out;
+extern int gram_lineno;
+
+# define GRAM_LEX_DECL int gram_lex (YYSTYPE *val, location *loc)
+GRAM_LEX_DECL;
+
+#endif /* !SCAN_GRAM_H_ */
index cf704c7724e65c624392025547c9550116d7b805..329e5087956e3f7d405f4ebe498a797fc51e4bd4 100644 (file)
 #undef gram_wrap
 #define gram_wrap() 1
 
 #undef gram_wrap
 #define gram_wrap() 1
 
-#include "system.h"
-
-#include <mbswidth.h>
-#include <quote.h>
+#define FLEX_PREFIX(Id) gram_ ## Id
+#include "flex-scanner.h"
 
 #include "complain.h"
 #include "files.h"
 
 #include "complain.h"
 #include "files.h"
-#include "getargs.h"
+#include "getargs.h"    /* yacc_flag */
 #include "gram.h"
 #include "quotearg.h"
 #include "reader.h"
 #include "uniqstr.h"
 
 #include "gram.h"
 #include "quotearg.h"
 #include "reader.h"
 #include "uniqstr.h"
 
+#include <mbswidth.h>
+#include <quote.h>
+
+#include "scan-gram.h"
+
+#define YY_DECL GRAM_LEX_DECL
+   
 #define YY_USER_INIT                                   \
 #define YY_USER_INIT                                   \
-  do                                                   \
-    {                                                  \
-      scanner_cursor.file = current_file;              \
-      scanner_cursor.line = 1;                         \
-      scanner_cursor.column = 1;                       \
-      code_start = scanner_cursor;                     \
-    }                                                  \
-  while (0)
-
-/* Pacify "gcc -Wmissing-prototypes" when flex 2.5.31 is used.  */
-int gram_get_lineno (void);
-FILE *gram_get_in (void);
-FILE *gram_get_out (void);
-int gram_get_leng (void);
-char *gram_get_text (void);
-void gram_set_lineno (int);
-void gram_set_in (FILE *);
-void gram_set_out (FILE *);
-int gram_get_debug (void);
-void gram_set_debug (int);
-int gram_lex_destroy (void);
+   code_start = scanner_cursor = loc->start;           \
 
 /* Location of scanner cursor.  */
 boundary scanner_cursor;
 
 
 /* Location of scanner cursor.  */
 boundary scanner_cursor;
 
-static void adjust_location (location *, char const *, size_t);
-#define YY_USER_ACTION  adjust_location (loc, yytext, yyleng);
+#define YY_USER_ACTION  location_compute (loc, &scanner_cursor, yytext, yyleng);
 
 static size_t no_cr_read (FILE *, char *, size_t);
 #define YY_INPUT(buf, result, size) ((result) = no_cr_read (yyin, buf, size))
 
 
 static size_t no_cr_read (FILE *, char *, size_t);
 #define YY_INPUT(buf, result, size) ((result) = no_cr_read (yyin, buf, size))
 
-
-/* OBSTACK_FOR_STRING -- Used to store all the characters that we need to
-   keep (to construct ID, STRINGS etc.).  Use the following macros to
-   use it.
-
-   Use STRING_GROW to append what has just been matched, and
-   STRING_FINISH to end the string (it puts the ending 0).
-   STRING_FINISH also stores this string in LAST_STRING, which can be
-   used, and which is used by STRING_FREE to free the last string.  */
-
-static struct obstack obstack_for_string;
-
 /* A string representing the most recently saved token.  */
 char *last_string;
 
 /* A string representing the most recently saved token.  */
 char *last_string;
 
-/* The location of the most recently saved token, if it was a
-   BRACED_CODE token; otherwise, this has an unspecified value.  */
-location last_braced_code_loc;
-
-#define STRING_GROW   \
-  obstack_grow (&obstack_for_string, yytext, yyleng)
-
-#define STRING_FINISH                                  \
-  do {                                                 \
-    obstack_1grow (&obstack_for_string, '\0');         \
-    last_string = obstack_finish (&obstack_for_string);        \
-  } while (0)
-
-#define STRING_FREE \
-  obstack_free (&obstack_for_string, last_string)
-
 void
 void
-scanner_last_string_free (void)
+gram_scanner_last_string_free (void)
 {
   STRING_FREE;
 }
 
 {
   STRING_FREE;
 }
 
-/* Within well-formed rules, RULE_LENGTH is the number of values in
-   the current rule so far, which says where to find `$0' with respect
-   to the top of the stack.  It is not the same as the rule->length in
-   the case of mid rule actions.
-
-   Outside of well-formed rules, RULE_LENGTH has an undefined value.  */
-static int rule_length;
-
-static void rule_length_overflow (location) __attribute__ ((__noreturn__));
-
-/* Increment the rule length by one, checking for overflow.  */
-static inline void
-increment_rule_length (location loc)
-{
-  rule_length++;
-
-  /* Don't allow rule_length == INT_MAX, since that might cause
-     confusion with strtol if INT_MAX == LONG_MAX.  */
-  if (rule_length == INT_MAX)
-    rule_length_overflow (loc);
-}
+/* The location of the most recently saved token, if it was a
+   BRACED_CODE token; otherwise, this has an unspecified value.  */
+location gram_last_braced_code_loc;
 
 
-static void handle_dollar (int token_type, char *cp, location loc);
-static void handle_at (int token_type, char *cp, location loc);
 static void handle_syncline (char *, location);
 static unsigned long int scan_integer (char const *p, int base, location loc);
 static int convert_ucn_to_byte (char const *hex_text);
 static void handle_syncline (char *, location);
 static unsigned long int scan_integer (char const *p, int base, location loc);
 static int convert_ucn_to_byte (char const *hex_text);
@@ -142,11 +78,26 @@ static void unexpected_eof (boundary, char const *);
 static void unexpected_newline (boundary, char const *);
 
 %}
 static void unexpected_newline (boundary, char const *);
 
 %}
-%x SC_COMMENT SC_LINE_COMMENT SC_YACC_COMMENT
-%x SC_STRING SC_CHARACTER
-%x SC_AFTER_IDENTIFIER
+ /* A C-like comment in directives/rules. */
+%x SC_YACC_COMMENT
+ /* Strings and characters in directives/rules. */
 %x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
 %x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
-%x SC_PRE_CODE SC_BRACED_CODE SC_PROLOGUE SC_EPILOGUE
+ /* A identifier was just read in directives/rules.  Special state
+    to capture the sequence `identifier :'. */
+%x SC_AFTER_IDENTIFIER
+ /* A keyword that should be followed by some code was read (e.g.
+    %printer). */
+%x SC_PRE_CODE
+
+ /* Three types of user code:
+    - prologue (code between `%{' `%}' in the first section, before %%);
+    - actions, printers, union, etc, (between braced in the middle section);
+    - epilogue (everything after the second %%). */
+%x SC_PROLOGUE SC_BRACED_CODE SC_EPILOGUE
+ /* C and C++ comments in code. */
+%x SC_COMMENT SC_LINE_COMMENT
+ /* Strings and characters in code. */
+%x SC_STRING SC_CHARACTER
 
 letter   [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
 id       {letter}({letter}|[0-9])*
 
 letter   [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
 id       {letter}({letter}|[0-9])*
@@ -221,17 +172,17 @@ splice     (\\[ \f\t\v]*\n)*
   "%default"[-_]"prec"    return PERCENT_DEFAULT_PREC;
   "%define"               return PERCENT_DEFINE;
   "%defines"              return PERCENT_DEFINES;
   "%default"[-_]"prec"    return PERCENT_DEFAULT_PREC;
   "%define"               return PERCENT_DEFINE;
   "%defines"              return PERCENT_DEFINES;
-  "%destructor"                  token_type = PERCENT_DESTRUCTOR; BEGIN SC_PRE_CODE;
+  "%destructor"                  /* FIXME: Remove once %union handled differently.  */ token_type = BRACED_CODE; return PERCENT_DESTRUCTOR;
   "%dprec"               return PERCENT_DPREC;
   "%error"[-_]"verbose"   return PERCENT_ERROR_VERBOSE;
   "%expect"               return PERCENT_EXPECT;
   "%expect"[-_]"rr"      return PERCENT_EXPECT_RR;
   "%file-prefix"          return PERCENT_FILE_PREFIX;
   "%fixed"[-_]"output"[-_]"files"   return PERCENT_YACC;
   "%dprec"               return PERCENT_DPREC;
   "%error"[-_]"verbose"   return PERCENT_ERROR_VERBOSE;
   "%expect"               return PERCENT_EXPECT;
   "%expect"[-_]"rr"      return PERCENT_EXPECT_RR;
   "%file-prefix"          return PERCENT_FILE_PREFIX;
   "%fixed"[-_]"output"[-_]"files"   return PERCENT_YACC;
-  "%initial-action"       token_type = PERCENT_INITIAL_ACTION; BEGIN SC_PRE_CODE;
+  "%initial-action"       /* FIXME: Remove once %union handled differently.  */ token_type = BRACED_CODE; return PERCENT_INITIAL_ACTION;
   "%glr-parser"           return PERCENT_GLR_PARSER;
   "%left"                 return PERCENT_LEFT;
   "%glr-parser"           return PERCENT_GLR_PARSER;
   "%left"                 return PERCENT_LEFT;
-  "%lex-param"           token_type = PERCENT_LEX_PARAM; BEGIN SC_PRE_CODE;
+  "%lex-param"           /* FIXME: Remove once %union handled differently.  */ token_type = BRACED_CODE; return PERCENT_LEX_PARAM;
   "%locations"            return PERCENT_LOCATIONS;
   "%merge"               return PERCENT_MERGE;
   "%name"[-_]"prefix"     return PERCENT_NAME_PREFIX;
   "%locations"            return PERCENT_LOCATIONS;
   "%merge"               return PERCENT_MERGE;
   "%name"[-_]"prefix"     return PERCENT_NAME_PREFIX;
@@ -241,9 +192,9 @@ splice       (\\[ \f\t\v]*\n)*
   "%nondeterministic-parser"   return PERCENT_NONDETERMINISTIC_PARSER;
   "%nterm"                return PERCENT_NTERM;
   "%output"               return PERCENT_OUTPUT;
   "%nondeterministic-parser"   return PERCENT_NONDETERMINISTIC_PARSER;
   "%nterm"                return PERCENT_NTERM;
   "%output"               return PERCENT_OUTPUT;
-  "%parse-param"         token_type = PERCENT_PARSE_PARAM; BEGIN SC_PRE_CODE;
-  "%prec"                 rule_length--; return PERCENT_PREC;
-  "%printer"              token_type = PERCENT_PRINTER; BEGIN SC_PRE_CODE;
+  "%parse-param"         /* FIXME: Remove once %union handled differently.  */ token_type = BRACED_CODE; return PERCENT_PARSE_PARAM;
+  "%prec"                 return PERCENT_PREC;
+  "%printer"              /* FIXME: Remove once %union handled differently.  */ token_type = BRACED_CODE; return PERCENT_PRINTER;
   "%pure"[-_]"parser"     return PERCENT_PURE_PARSER;
   "%require"              return PERCENT_REQUIRE;
   "%right"                return PERCENT_RIGHT;
   "%pure"[-_]"parser"     return PERCENT_PURE_PARSER;
   "%require"              return PERCENT_REQUIRE;
   "%right"                return PERCENT_RIGHT;
@@ -262,13 +213,12 @@ splice     (\\[ \f\t\v]*\n)*
   }
 
   "="                     return EQUAL;
   }
 
   "="                     return EQUAL;
-  "|"                     rule_length = 0; return PIPE;
+  "|"                     return PIPE;
   ";"                     return SEMICOLON;
 
   {id} {
     val->symbol = symbol_get (yytext, *loc);
     id_loc = *loc;
   ";"                     return SEMICOLON;
 
   {id} {
     val->symbol = symbol_get (yytext, *loc);
     id_loc = *loc;
-    increment_rule_length (*loc);
     BEGIN SC_AFTER_IDENTIFIER;
   }
 
     BEGIN SC_AFTER_IDENTIFIER;
   }
 
@@ -335,7 +285,6 @@ splice       (\\[ \f\t\v]*\n)*
 <SC_AFTER_IDENTIFIER>
 {
   ":" {
 <SC_AFTER_IDENTIFIER>
 {
   ":" {
-    rule_length = 0;
     *loc = id_loc;
     BEGIN INITIAL;
     return ID_COLON;
     *loc = id_loc;
     BEGIN INITIAL;
     return ID_COLON;
@@ -401,7 +350,6 @@ splice       (\\[ \f\t\v]*\n)*
     STRING_FINISH;
     loc->start = token_start;
     val->chars = last_string;
     STRING_FINISH;
     loc->start = token_start;
     val->chars = last_string;
-    increment_rule_length (*loc);
     BEGIN INITIAL;
     return STRING;
   }
     BEGIN INITIAL;
     return STRING;
   }
@@ -428,7 +376,6 @@ splice       (\\[ \f\t\v]*\n)*
     last_string_1 = last_string[1];
     symbol_user_token_number_set (val->symbol, last_string_1, *loc);
     STRING_FREE;
     last_string_1 = last_string[1];
     symbol_user_token_number_set (val->symbol, last_string_1, *loc);
     STRING_FREE;
-    increment_rule_length (*loc);
     BEGIN INITIAL;
     return ID;
   }
     BEGIN INITIAL;
     return ID;
   }
@@ -501,7 +448,7 @@ splice       (\\[ \f\t\v]*\n)*
 
 <SC_CHARACTER,SC_STRING>
 {
 
 <SC_CHARACTER,SC_STRING>
 {
-  {splice}|\\{splice}[^\n$@\[\]]       STRING_GROW;
+  {splice}|\\{splice}[^\n\[\]] STRING_GROW;
 }
 
 <SC_CHARACTER>
 }
 
 <SC_CHARACTER>
@@ -622,8 +569,7 @@ splice       (\\[ \f\t\v]*\n)*
        STRING_FINISH;
        loc->start = code_start;
        val->chars = last_string;
        STRING_FINISH;
        loc->start = code_start;
        val->chars = last_string;
-       increment_rule_length (*loc);
-       last_braced_code_loc = *loc;
+       gram_last_braced_code_loc = *loc;
        BEGIN INITIAL;
        return token_type;
       }
        BEGIN INITIAL;
        return token_type;
       }
@@ -633,18 +579,6 @@ splice      (\\[ \f\t\v]*\n)*
      (as `<' `<%').  */
   "<"{splice}"<"  STRING_GROW;
 
      (as `<' `<%').  */
   "<"{splice}"<"  STRING_GROW;
 
-  "$"("<"{tag}">")?(-?[0-9]+|"$")  handle_dollar (token_type, yytext, *loc);
-  "@"(-?[0-9]+|"$")               handle_at (token_type, yytext, *loc);
-
-  "$"  {
-    warn_at (*loc, _("stray `$'"));
-    obstack_sgrow (&obstack_for_string, "$][");
-  }
-  "@"  {
-    warn_at (*loc, _("stray `@'"));
-    obstack_sgrow (&obstack_for_string, "@@");
-  }
-
   <<EOF>>  unexpected_eof (code_start, "}"); BEGIN INITIAL;
 }
 
   <<EOF>>  unexpected_eof (code_start, "}"); BEGIN INITIAL;
 }
 
@@ -684,19 +618,6 @@ splice      (\\[ \f\t\v]*\n)*
 }
 
 
 }
 
 
-  /*-----------------------------------------.
-  | Escape M4 quoting characters in C code.  |
-  `-----------------------------------------*/
-
-<SC_COMMENT,SC_LINE_COMMENT,SC_STRING,SC_CHARACTER,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
-{
-  \$   obstack_sgrow (&obstack_for_string, "$][");
-  \@   obstack_sgrow (&obstack_for_string, "@@");
-  \[   obstack_sgrow (&obstack_for_string, "@{");
-  \]   obstack_sgrow (&obstack_for_string, "@}");
-}
-
-
   /*-----------------------------------------------------.
   | By default, grow the string obstack with the input.  |
   `-----------------------------------------------------*/
   /*-----------------------------------------------------.
   | By default, grow the string obstack with the input.  |
   `-----------------------------------------------------*/
@@ -706,79 +627,6 @@ splice      (\\[ \f\t\v]*\n)*
 
 %%
 
 
 %%
 
-/* Keeps track of the maximum number of semantic values to the left of
-   a handle (those referenced by $0, $-1, etc.) are required by the
-   semantic actions of this grammar. */
-int max_left_semantic_context = 0;
-
-/* If BUF is null, add BUFSIZE (which in this case must be less than
-   INT_MAX) to COLUMN; otherwise, add mbsnwidth (BUF, BUFSIZE, 0) to
-   COLUMN.  If an overflow occurs, or might occur but is undetectable,
-   return INT_MAX.  Assume COLUMN is nonnegative.  */
-
-static inline int
-add_column_width (int column, char const *buf, size_t bufsize)
-{
-  size_t width;
-  unsigned int remaining_columns = INT_MAX - column;
-
-  if (buf)
-    {
-      if (INT_MAX / 2 <= bufsize)
-       return INT_MAX;
-      width = mbsnwidth (buf, bufsize, 0);
-    }
-  else
-    width = bufsize;
-
-  return width <= remaining_columns ? column + width : INT_MAX;
-}
-
-/* Set *LOC and adjust scanner cursor to account for token TOKEN of
-   size SIZE.  */
-
-static void
-adjust_location (location *loc, char const *token, size_t size)
-{
-  int line = scanner_cursor.line;
-  int column = scanner_cursor.column;
-  char const *p0 = token;
-  char const *p = token;
-  char const *lim = token + size;
-
-  loc->start = scanner_cursor;
-
-  for (p = token; p < lim; p++)
-    switch (*p)
-      {
-      case '\n':
-       line += line < INT_MAX;
-       column = 1;
-       p0 = p + 1;
-       break;
-
-      case '\t':
-       column = add_column_width (column, p0, p - p0);
-       column = add_column_width (column, NULL, 8 - ((column - 1) & 7));
-       p0 = p + 1;
-       break;
-
-      default:
-       break;
-      }
-
-  scanner_cursor.line = line;
-  scanner_cursor.column = column = add_column_width (column, p0, p - p0);
-
-  loc->end = scanner_cursor;
-
-  if (line == INT_MAX && loc->start.line != INT_MAX)
-    warn_at (*loc, _("line number overflow"));
-  if (column == INT_MAX && loc->start.column != INT_MAX)
-    warn_at (*loc, _("column number overflow"));
-}
-
-
 /* Read bytes from FP into buffer BUF of size SIZE.  Return the
    number of bytes read.  Remove '\r' from input, treating \r\n
    and isolated \r as \n.  */
 /* Read bytes from FP into buffer BUF of size SIZE.  Return the
    number of bytes read.  Remove '\r' from input, treating \r\n
    and isolated \r as \n.  */
@@ -826,173 +674,6 @@ no_cr_read (FILE *fp, char *buf, size_t size)
 }
 
 
 }
 
 
-/*------------------------------------------------------------------.
-| TEXT is pointing to a wannabee semantic value (i.e., a `$').      |
-|                                                                   |
-| Possible inputs: $[<TYPENAME>]($|integer)                         |
-|                                                                   |
-| Output to OBSTACK_FOR_STRING a reference to this semantic value.  |
-`------------------------------------------------------------------*/
-
-static inline bool
-handle_action_dollar (char *text, location loc)
-{
-  const char *type_name = NULL;
-  char *cp = text + 1;
-
-  if (! current_rule)
-    return false;
-
-  /* Get the type name if explicit. */
-  if (*cp == '<')
-    {
-      type_name = ++cp;
-      while (*cp != '>')
-       ++cp;
-      *cp = '\0';
-      ++cp;
-    }
-
-  if (*cp == '$')
-    {
-      if (!type_name)
-       type_name = symbol_list_n_type_name_get (current_rule, loc, 0);
-      if (!type_name && typed)
-       complain_at (loc, _("$$ of `%s' has no declared type"),
-                    current_rule->sym->tag);
-      if (!type_name)
-       type_name = "";
-      obstack_fgrow1 (&obstack_for_string,
-                     "]b4_lhs_value([%s])[", type_name);
-      current_rule->used = true;
-    }
-  else
-    {
-      long int num = strtol (cp, NULL, 10);
-
-      if (1 - INT_MAX + rule_length <= num && num <= rule_length)
-       {
-         int n = num;
-         if (max_left_semantic_context < 1 - n)
-           max_left_semantic_context = 1 - n;
-         if (!type_name && 0 < n)
-           type_name = symbol_list_n_type_name_get (current_rule, loc, n);
-         if (!type_name && typed)
-           complain_at (loc, _("$%d of `%s' has no declared type"),
-                        n, current_rule->sym->tag);
-         if (!type_name)
-           type_name = "";
-         obstack_fgrow3 (&obstack_for_string,
-                         "]b4_rhs_value(%d, %d, [%s])[",
-                         rule_length, n, type_name);
-         symbol_list_n_used_set (current_rule, n, true);
-       }
-      else
-       complain_at (loc, _("integer out of range: %s"), quote (text));
-    }
-
-  return true;
-}
-
-
-/*----------------------------------------------------------------.
-| Map `$?' onto the proper M4 symbol, depending on its TOKEN_TYPE |
-| (are we in an action?).                                         |
-`----------------------------------------------------------------*/
-
-static void
-handle_dollar (int token_type, char *text, location loc)
-{
-  switch (token_type)
-    {
-    case BRACED_CODE:
-      if (handle_action_dollar (text, loc))
-       return;
-      break;
-
-    case PERCENT_DESTRUCTOR:
-    case PERCENT_INITIAL_ACTION:
-    case PERCENT_PRINTER:
-      if (text[1] == '$')
-       {
-         obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar[");
-         return;
-       }
-      break;
-
-    default:
-      break;
-    }
-
-  complain_at (loc, _("invalid value: %s"), quote (text));
-}
-
-
-/*------------------------------------------------------.
-| TEXT is a location token (i.e., a `@...').  Output to |
-| OBSTACK_FOR_STRING a reference to this location.      |
-`------------------------------------------------------*/
-
-static inline bool
-handle_action_at (char *text, location loc)
-{
-  char *cp = text + 1;
-  locations_flag = true;
-
-  if (! current_rule)
-    return false;
-
-  if (*cp == '$')
-    obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
-  else
-    {
-      long int num = strtol (cp, NULL, 10);
-
-      if (1 - INT_MAX + rule_length <= num && num <= rule_length)
-       {
-         int n = num;
-         obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
-                         rule_length, n);
-       }
-      else
-       complain_at (loc, _("integer out of range: %s"), quote (text));
-    }
-
-  return true;
-}
-
-
-/*----------------------------------------------------------------.
-| Map `@?' onto the proper M4 symbol, depending on its TOKEN_TYPE |
-| (are we in an action?).                                         |
-`----------------------------------------------------------------*/
-
-static void
-handle_at (int token_type, char *text, location loc)
-{
-  switch (token_type)
-    {
-    case BRACED_CODE:
-      handle_action_at (text, loc);
-      return;
-
-    case PERCENT_INITIAL_ACTION:
-    case PERCENT_DESTRUCTOR:
-    case PERCENT_PRINTER:
-      if (text[1] == '$')
-       {
-         obstack_sgrow (&obstack_for_string, "]b4_at_dollar[");
-         return;
-       }
-      break;
-
-    default:
-      break;
-    }
-
-  complain_at (loc, _("invalid value: %s"), quote (text));
-}
-
 
 /*------------------------------------------------------.
 | Scan NUMBER for a base-BASE integer at location LOC.  |
 
 /*------------------------------------------------------.
 | Scan NUMBER for a base-BASE integer at location LOC.  |
@@ -1087,20 +768,8 @@ handle_syncline (char *args, location loc)
       warn_at (loc, _("line number overflow"));
       lineno = INT_MAX;
     }
       warn_at (loc, _("line number overflow"));
       lineno = INT_MAX;
     }
-  scanner_cursor.file = current_file = uniqstr_new (file);
-  scanner_cursor.line = lineno;
-  scanner_cursor.column = 1;
-}
-
-
-/*---------------------------------.
-| Report a rule that is too long.  |
-`---------------------------------*/
-
-static void
-rule_length_overflow (location loc)
-{
-  fatal_at (loc, _("rule is too long"));
+  current_file = uniqstr_new (file);
+  boundary_set, (&scanner_cursor, current_file, lineno, 1);
 }
 
 
 }
 
 
@@ -1148,7 +817,7 @@ unexpected_newline (boundary start, char const *token_end)
 `-------------------------*/
 
 void
 `-------------------------*/
 
 void
-scanner_initialize (void)
+gram_scanner_initialize (void)
 {
   obstack_init (&obstack_for_string);
 }
 {
   obstack_init (&obstack_for_string);
 }
@@ -1159,7 +828,7 @@ scanner_initialize (void)
 `-----------------------------------------------*/
 
 void
 `-----------------------------------------------*/
 
 void
-scanner_free (void)
+gram_scanner_free (void)
 {
   obstack_free (&obstack_for_string, 0);
   /* Reclaim Flex's buffers.  */
 {
   obstack_free (&obstack_for_string, 0);
   /* Reclaim Flex's buffers.  */
index 63157904fb69f6f4aedea4f3094f3e8f41c0c161..2468deed4d58ad4112433ecbdd84622fce23da14 100644 (file)
@@ -113,6 +113,8 @@ char *base_name (char const *name);
 # define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
 #endif
 
 # define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
 #endif
 
+#define FUNCTION_PRINT() fprintf (stderr, "%s: ", __func__)
+
 /*------.
 | NLS.  |
 `------*/
 /*------.
 | NLS.  |
 `------*/
index 82fbe06346c99c84d71deac1e2da506ff2f9f4f0..afacd20156c9e86e5aa7067b7c1581f74058ae9e 100644 (file)
@@ -25,33 +25,17 @@ AT_BANNER([[Input Processing.]])
 ## Invalid $n.  ##
 ## ------------ ##
 
 ## Invalid $n.  ##
 ## ------------ ##
 
-AT_SETUP([Invalid dollar-n])
+AT_SETUP([Invalid \$n and @n])
 
 AT_DATA([input.y],
 [[%%
 exp: { $$ = $1 ; };
 
 AT_DATA([input.y],
 [[%%
 exp: { $$ = $1 ; };
-]])
-
-AT_CHECK([bison input.y], [1], [],
-[[input.y:2.13-14: integer out of range: `$1'
-]])
-
-AT_CLEANUP
-
-
-## ------------ ##
-## Invalid @n.  ##
-## ------------ ##
-
-AT_SETUP([Invalid @n])
-
-AT_DATA([input.y],
-[[%%
 exp: { @$ = @1 ; };
 ]])
 
 AT_CHECK([bison input.y], [1], [],
 exp: { @$ = @1 ; };
 ]])
 
 AT_CHECK([bison input.y], [1], [],
-[[input.y:2.13-14: integer out of range: `@1'
+[[input.y:2.13-14: integer out of range: `$1'
+input.y:3.13-14: integer out of range: `@1'
 ]])
 
 AT_CLEANUP
 ]])
 
 AT_CLEANUP
@@ -200,11 +184,11 @@ AT_SETUP([Torturing the Scanner])
 
 AT_DATA([input.y], [])
 AT_CHECK([bison input.y], [1], [],
 
 AT_DATA([input.y], [])
 AT_CHECK([bison input.y], [1], [],
-[[input.y:1.1: syntax error, unexpected end of file
+[[input.y:1.0: syntax error, unexpected end of file
 ]])
 
 
 ]])
 
 
-AT_DATA([input.y], 
+AT_DATA([input.y],
 [{}
 ])
 AT_CHECK([bison input.y], [1], [],
 [{}
 ])
 AT_CHECK([bison input.y], [1], [],
index 6a37f759a8e80a330e4ad5cabe88f79125251c34..04beccc3298245ebe25ae300441958877d65bf23 100644 (file)
@@ -346,9 +346,7 @@ AT_DATA([input.y],
 ]])
 
 AT_CHECK([bison input.y], [1], [],
 ]])
 
 AT_CHECK([bison input.y], [1], [],
-[[input.y:3.1: missing `{' in "%destructor {...}"
-input.y:4.1: missing `{' in "%initial-action {...}"
-input.y:4.1: syntax error, unexpected %initial-action {...}, expecting string or identifier
+[[input.y:3.1-15: syntax error, unexpected %initial-action, expecting {...}
 ]])
 
 AT_CLEANUP
 ]])
 
 AT_CLEANUP