]> git.saurik.com Git - bison.git/blobdiff - src/parse-gram.y
* src/scan-gram.l (gram_get_lineno, gram_get_in, gram_get_out):
[bison.git] / src / parse-gram.y
index 3a6de2ff57ac6b8a0e50ce9c8a75d7f37cb279c2..735a3fd730dad60424699b16a94281b487881683 100644 (file)
@@ -1,5 +1,6 @@
-/* Bison Grammar Parser                             -*- C -*-
-   Copyright (C) 2002 Free Software Foundation, Inc.
+%{/* Bison Grammar Parser                             -*- C -*-
+
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
 
    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., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307  USA
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301  USA
 */
 
 */
 
-
-%debug
-%defines
-%locations
-%pure-parser
-// %error-verbose
-%defines
-%name-prefix="gram_"
-
-%{
 #include "system.h"
 
 #include "complain.h"
 #include "system.h"
 
 #include "complain.h"
 #include "gram.h"
 #include "muscle_tab.h"
 #include "output.h"
 #include "gram.h"
 #include "muscle_tab.h"
 #include "output.h"
+#include "quotearg.h"
 #include "reader.h"
 #include "symlist.h"
 
 #include "reader.h"
 #include "symlist.h"
 
-/* Produce verbose syntax errors.  */
-#define YYERROR_VERBOSE 1
-
 #define YYLLOC_DEFAULT(Current, Rhs, N)  (Current) = lloc_default (Rhs, N)
 static YYLTYPE lloc_default (YYLTYPE const *, int);
 
 #define YYLLOC_DEFAULT(Current, Rhs, N)  (Current) = lloc_default (Rhs, N)
 static YYLTYPE lloc_default (YYLTYPE const *, int);
 
+#define YY_LOCATION_PRINT(File, Loc) \
+          location_print (File, Loc)
+
 /* Request detailed syntax error messages, and pass them to GRAM_ERROR.
    FIXME: depends on the undocumented availability of YYLLOC.  */
 #undef  yyerror
 /* Request detailed syntax error messages, and pass them to GRAM_ERROR.
    FIXME: depends on the undocumented availability of YYLLOC.  */
 #undef  yyerror
@@ -54,11 +46,7 @@ static YYLTYPE lloc_default (YYLTYPE const *, int);
         gram_error (&yylloc, Msg)
 static void gram_error (location const *, char const *);
 
         gram_error (&yylloc, Msg)
 static void gram_error (location const *, char const *);
 
-#define YYPRINT(File, Type, Value) \
-       print_token_value (File, Type, &Value)
-static void print_token_value (FILE *, int, YYSTYPE const *);
-
-static void add_param (char const *, char const *, location);
+static void add_param (char const *, char *, location);
 
 symbol_class current_class = unknown_sym;
 uniqstr current_type = 0;
 
 symbol_class current_class = unknown_sym;
 uniqstr current_type = 0;
@@ -66,9 +54,25 @@ symbol *current_lhs;
 location current_lhs_location;
 assoc current_assoc;
 int current_prec = 0;
 location current_lhs_location;
 assoc current_assoc;
 int current_prec = 0;
-braced_code current_braced_code = action_braced_code;
 %}
 
 %}
 
+%debug
+%verbose
+%defines
+%locations
+%pure-parser
+%error-verbose
+%defines
+%name-prefix="gram_"
+
+%initial-action
+{
+  /* 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;
+}
 
 /* Only NUMBERS have a value.  */
 %union
 
 /* Only NUMBERS have a value.  */
 %union
@@ -90,10 +94,10 @@ braced_code current_braced_code = action_braced_code;
 %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 {...}"
 
 %token PERCENT_LEFT        "%left"
 %token PERCENT_RIGHT       "%right"
 
 %token PERCENT_LEFT        "%left"
 %token PERCENT_RIGHT       "%right"
@@ -109,25 +113,31 @@ braced_code current_braced_code = action_braced_code;
 `----------------------*/
 
 %token
 `----------------------*/
 
 %token
-  PERCENT_DEBUG         "%debug"
-  PERCENT_DEFINE        "%define"
-  PERCENT_DEFINES       "%defines"
-  PERCENT_ERROR_VERBOSE "%error-verbose"
-  PERCENT_EXPECT        "%expect"
-  PERCENT_FILE_PREFIX   "%file-prefix"
-  PERCENT_GLR_PARSER    "%glr-parser"
-  PERCENT_LEX_PARAM     "%lex-param"
-  PERCENT_LOCATIONS     "%locations"
-  PERCENT_NAME_PREFIX   "%name-prefix"
-  PERCENT_NO_LINES      "%no-lines"
-  PERCENT_OUTPUT        "%output"
-  PERCENT_PARSE_PARAM   "%parse-param"
-  PERCENT_PURE_PARSER   "%pure-parser"
-  PERCENT_SKELETON      "%skeleton"
-  PERCENT_START         "%start"
-  PERCENT_TOKEN_TABLE   "%token-table"
-  PERCENT_VERBOSE       "%verbose"
-  PERCENT_YACC          "%yacc"
+  PERCENT_DEBUG           "%debug"
+  PERCENT_DEFAULT_PREC    "%default-prec"
+  PERCENT_DEFINE          "%define"
+  PERCENT_DEFINES         "%defines"
+  PERCENT_ERROR_VERBOSE   "%error-verbose"
+  PERCENT_EXPECT          "%expect"
+  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_LOCATIONS       "%locations"
+  PERCENT_NAME_PREFIX     "%name-prefix"
+  PERCENT_NO_DEFAULT_PREC "%no-default-prec"
+  PERCENT_NO_LINES        "%no-lines"
+  PERCENT_NONDETERMINISTIC_PARSER
+                          "%nondeterministic-parser"
+  PERCENT_OUTPUT          "%output"
+  PERCENT_PARSE_PARAM     "%parse-param {...}"
+  PERCENT_PURE_PARSER     "%pure-parser"
+  PERCENT_SKELETON        "%skeleton"
+  PERCENT_START           "%start"
+  PERCENT_TOKEN_TABLE     "%token-table"
+  PERCENT_VERBOSE         "%verbose"
+  PERCENT_YACC            "%yacc"
 ;
 
 %token TYPE            "type"
 ;
 
 %token TYPE            "type"
@@ -143,11 +153,33 @@ braced_code current_braced_code = action_braced_code;
 
 
 %type <chars> STRING string_content
 
 
 %type <chars> STRING string_content
-             BRACED_CODE code_content action
+             "%destructor {...}"
+             "%initial-action {...}"
+             "%lex-param {...}"
+             "%parse-param {...}"
+             "%printer {...}"
+             "%union {...}"
+             BRACED_CODE action
+             PROLOGUE EPILOGUE
+%printer { fprintf (stderr, "\"%s\"", $$); }
+              STRING string_content
+%printer { fprintf (stderr, "{\n%s\n}", $$); }
+             "%destructor {...}"
+             "%initial-action {...}"
+             "%lex-param {...}"
+             "%parse-param {...}"
+             "%printer {...}"
+             "%union {...}"
+             BRACED_CODE action
              PROLOGUE EPILOGUE
 %type <uniqstr> TYPE
              PROLOGUE EPILOGUE
 %type <uniqstr> TYPE
+%printer { fprintf (stderr, "<%s>", $$); } TYPE
 %type <integer> INT
 %type <integer> INT
-%type <symbol> ID ID_COLON symbol string_as_id
+%printer { fprintf (stderr, "%d", $$); } INT
+%type <symbol> ID symbol string_as_id
+%printer { fprintf (stderr, "%s", $$->tag); } ID symbol string_as_id
+%type <symbol> ID_COLON
+%printer { fprintf (stderr, "%s:", $$->tag); } ID_COLON
 %type <assoc> precedence_declarator
 %type <list>  symbols.1
 %%
 %type <assoc> precedence_declarator
 %type <list>  symbols.1
 %%
@@ -169,25 +201,35 @@ declarations:
 declaration:
   grammar_declaration
 | PROLOGUE                                 { prologue_augment ($1, @1); }
 declaration:
   grammar_declaration
 | PROLOGUE                                 { prologue_augment ($1, @1); }
-| "%debug"                                 { debug_flag = 1; }
+| "%debug"                                 { debug_flag = true; }
 | "%define" string_content string_content  { muscle_insert ($2, $3); }
 | "%define" string_content string_content  { muscle_insert ($2, $3); }
-| "%defines"                               { defines_flag = 1; }
-| "%error-verbose"                         { error_verbose = 1; }
-| "%expect" INT                            { expected_conflicts = $2; }
+| "%defines"                               { defines_flag = true; }
+| "%error-verbose"                         { error_verbose = true; }
+| "%expect" INT                            { expected_sr_conflicts = $2; }
+| "%expect-rr" INT                        { expected_rr_conflicts = $2; }
 | "%file-prefix" "=" string_content        { spec_file_prefix = $3; }
 | "%file-prefix" "=" string_content        { spec_file_prefix = $3; }
-| "%glr-parser"                           { glr_parser = 1; }
-| "%lex-param" code_content               { add_param ("lex_param", $2, @2); }
-| "%locations"                             { locations_flag = 1; }
+| "%glr-parser"
+  {
+    nondeterministic_parser = true;
+    glr_parser = true;
+  }
+| "%initial-action {...}"
+  {
+    muscle_code_grow ("initial_action", $1, @1);
+  }
+| "%lex-param {...}"                      { add_param ("lex_param", $1, @1); }
+| "%locations"                             { locations_flag = true; }
 | "%name-prefix" "=" string_content        { spec_name_prefix = $3; }
 | "%name-prefix" "=" string_content        { spec_name_prefix = $3; }
-| "%no-lines"                              { no_lines_flag = 1; }
+| "%no-lines"                              { no_lines_flag = true; }
+| "%nondeterministic-parser"              { nondeterministic_parser = true; }
 | "%output" "=" string_content             { spec_outfile = $3; }
 | "%output" "=" string_content             { spec_outfile = $3; }
-| "%parse-param" code_content          { add_param ("parse_param", $2, @2); }
-| "%pure-parser"                           { pure_parser = 1; }
+| "%parse-param {...}"                    { add_param ("parse_param", $1, @1); }
+| "%pure-parser"                           { pure_parser = true; }
 | "%skeleton" string_content               { skeleton = $2; }
 | "%skeleton" string_content               { skeleton = $2; }
-| "%token-table"                           { token_table_flag = 1; }
-| "%verbose"                               { report_flag = 1; }
-| "%yacc"                                  { yacc_flag = 1; }
-| ";"
+| "%token-table"                           { token_table_flag = true; }
+| "%verbose"                               { report_flag = report_states; }
+| "%yacc"                                  { yacc_flag = true; }
+| /*FIXME: Err?  What is this horror doing here? */ ";"
 ;
 
 grammar_declaration:
 ;
 
 grammar_declaration:
@@ -197,31 +239,33 @@ grammar_declaration:
     {
       grammar_start_symbol_set ($2, @2);
     }
     {
       grammar_start_symbol_set ($2, @2);
     }
-| "%union" BRACED_CODE
+| "%union {...}"
     {
     {
-      typed = 1;
-      MUSCLE_INSERT_INT ("stype_line", @2.start.line);
-      muscle_insert ("stype", $2);
+      typed = true;
+      MUSCLE_INSERT_INT ("stype_line", @1.start.line);
+      muscle_insert ("stype", $1);
     }
     }
-| "%destructor"
-    { current_braced_code = destructor_braced_code; }
-  BRACED_CODE symbols.1
+| "%destructor {...}" symbols.1
     {
       symbol_list *list;
     {
       symbol_list *list;
-      for (list = $4; list; list = list->next)
-       symbol_destructor_set (list->sym, $3, @3);
-      symbol_list_free ($4);
-      current_braced_code = action_braced_code;
+      for (list = $2; list; list = list->next)
+       symbol_destructor_set (list->sym, $1, @1);
+      symbol_list_free ($2);
     }
     }
-| "%printer"
-    { current_braced_code = printer_braced_code; }
-  BRACED_CODE symbols.1
+| "%printer {...}" symbols.1
     {
       symbol_list *list;
     {
       symbol_list *list;
-      for (list = $4; list; list = list->next)
-       symbol_printer_set (list->sym, $3, list->location);
-      symbol_list_free ($4);
-      current_braced_code = action_braced_code;
+      for (list = $2; list; list = list->next)
+       symbol_printer_set (list->sym, $1, list->location);
+      symbol_list_free ($2);
+    }
+| "%default-prec"
+    {
+      default_prec = true;
+    }
+| "%no-default-prec"
+    {
+      default_prec = false;
     }
 ;
 
     }
 ;
 
@@ -330,7 +374,7 @@ grammar:
    body of the grammar.  */
 rules_or_grammar_declaration:
   rules
    body of the grammar.  */
 rules_or_grammar_declaration:
   rules
-| grammar_declaration
+| grammar_declaration ";"
     {
       if (yacc_flag)
        complain_at (@$, _("POSIX forbids declarations in the grammar"));
     {
       if (yacc_flag)
        complain_at (@$, _("POSIX forbids declarations in the grammar"));
@@ -339,7 +383,6 @@ rules_or_grammar_declaration:
     {
       yyerrok;
     }
     {
       yyerrok;
     }
-| ";"
 ;
 
 rules:
 ;
 
 rules:
@@ -349,6 +392,7 @@ rules:
 rhses.1:
   rhs                { grammar_rule_end (@1); }
 | rhses.1 "|" rhs    { grammar_rule_end (@3); }
 rhses.1:
   rhs                { grammar_rule_end (@1); }
 | rhses.1 "|" rhs    { grammar_rule_end (@3); }
+| rhses.1 ";"
 ;
 
 rhs:
 ;
 
 rhs:
@@ -373,41 +417,30 @@ symbol:
 
 action:
   BRACED_CODE
 
 action:
   BRACED_CODE
-   { $$ = $1; }
+    { $$ = $1; }
 ;
 
 ;
 
-/* A string used as an ID: we have to keep the quotes. */
+/* A string used as an ID: quote it.  */
 string_as_id:
   STRING
     {
 string_as_id:
   STRING
     {
-      $$ = symbol_get ($1, @1);
+      $$ = symbol_get (quotearg_style (c_quoting_style, $1), @1);
       symbol_class_set ($$, token_sym, @1);
     }
 ;
 
       symbol_class_set ($$, token_sym, @1);
     }
 ;
 
-/* A string used for its contents.  Strip the quotes. */
+/* A string used for its contents.  Don't quote it.  */
 string_content:
   STRING
 string_content:
   STRING
-    {
-      $$ = $1 + 1;
-      $$[strlen ($$) - 1] = '\0';
-    };
-
-
-/* A BRACED_CODE used for its contents.  Strip the braces. */
-code_content:
-  BRACED_CODE
-    {
-      $$ = $1 + 1;
-      $$[strlen ($$) - 1] = '\0';
-    };
+    { $$ = $1; }
+;
 
 
 epilogue.opt:
   /* Nothing.  */
 | "%%" EPILOGUE
     {
 
 
 epilogue.opt:
   /* Nothing.  */
 | "%%" EPILOGUE
     {
-      epilogue_augment ($2, @2);
+      muscle_code_grow ("epilogue", $2, @2);
       scanner_last_string_free ();
     }
 ;
       scanner_last_string_free ();
     }
 ;
@@ -424,24 +457,24 @@ static YYLTYPE
 lloc_default (YYLTYPE const *rhs, int n)
 {
   int i;
 lloc_default (YYLTYPE const *rhs, int n)
 {
   int i;
-  int j;
-  YYLTYPE r;
-  r.start = r.end = rhs[n].end;
+  YYLTYPE loc;
+
+  /* SGI MIPSpro 7.4.1m miscompiles "loc.start = loc.end = rhs[n].end;".
+     The bug is fixed in 7.4.2m, but play it safe for now.  */
+  loc.start = rhs[n].end;
+  loc.end = rhs[n].end;
 
 
+  /* Ignore empty nonterminals the start of the the right-hand side.
+     Do not bother to ignore them at the end of the right-hand side,
+     since empty nonterminals have the same end as their predecessors.  */
   for (i = 1; i <= n; i++)
     if (! equal_boundaries (rhs[i].start, rhs[i].end))
       {
   for (i = 1; i <= n; i++)
     if (! equal_boundaries (rhs[i].start, rhs[i].end))
       {
-       r.start = rhs[i].start;
-
-       for (j = n; i < j; j--)
-         if (! equal_boundaries (rhs[j].start, rhs[j].end))
-           break;
-       r.end = rhs[j].end;
-
+       loc.start = rhs[i].start;
        break;
       }
 
        break;
       }
 
-  return r;
+  return loc;
 }
 
 
 }
 
 
@@ -449,21 +482,31 @@ lloc_default (YYLTYPE const *rhs, int n)
    declaration DECL and location LOC.  */
 
 static void
    declaration DECL and location LOC.  */
 
 static void
-add_param (char const *type, char const *decl, location loc)
+add_param (char const *type, char *decl, location loc)
 {
 {
-  static char const alphanum[] =
-    "0123456789"
+  static char const alphanum[26 + 26 + 1 + 10] =
     "abcdefghijklmnopqrstuvwxyz"
     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     "abcdefghijklmnopqrstuvwxyz"
     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-    "_";
-  char const *alpha = alphanum + 10;
+    "_"
+    "0123456789";
   char const *name_start = NULL;
   char const *name_start = NULL;
-  char const *p;
+  char *p;
 
 
-  for (p = decl; *p; p++)
-    if ((p == decl || ! strchr (alphanum, p[-1])) && strchr (alpha, p[0]))
+  /* Stop on last actual character.  */
+  for (p = decl; p[1]; p++)
+    if ((p == decl
+        || ! memchr (alphanum, p[-1], sizeof alphanum))
+       && memchr (alphanum, p[0], sizeof alphanum - 10))
       name_start = p;
 
       name_start = p;
 
+  /* Strip the surrounding '{' and '}', and any blanks just inside
+     the braces.  */
+  while (*--p == ' ' || *p == '\t')
+    continue;
+  p[1] = '\0';
+  while (*++decl == ' ' || *decl == '\t')
+    continue;
+
   if (! name_start)
     complain_at (loc, _("missing identifier in parameter declaration"));
   else
   if (! name_start)
     complain_at (loc, _("missing identifier in parameter declaration"));
   else
@@ -472,7 +515,7 @@ add_param (char const *type, char const *decl, location loc)
       size_t name_len;
 
       for (name_len = 1;
       size_t name_len;
 
       for (name_len = 1;
-          name_start[name_len] && strchr (alphanum, name_start[name_len]);
+          memchr (alphanum, name_start[name_len], sizeof alphanum);
           name_len++)
        continue;
 
           name_len++)
        continue;
 
@@ -486,46 +529,14 @@ add_param (char const *type, char const *decl, location loc)
   scanner_last_string_free ();
 }
 
   scanner_last_string_free ();
 }
 
-/*------------------------------------------------------------------.
-| When debugging the parser, display tokens' locations and values.  |
-`------------------------------------------------------------------*/
-
 static void
 static void
-print_token_value (FILE *file, int type, YYSTYPE const *value)
+gram_error (location const *loc, char const *msg)
 {
 {
-  fputc (' ', file);
-  switch (type)
-    {
-    case ID:
-      fprintf (file, " = %s", value->symbol->tag);
-      break;
-
-    case INT:
-      fprintf (file, " = %d", value->integer);
-      break;
-
-    case STRING:
-      fprintf (file, " = \"%s\"", value->chars);
-      break;
-
-    case TYPE:
-      fprintf (file, " = <%s>", value->uniqstr);
-      break;
-
-    case BRACED_CODE:
-    case PROLOGUE:
-    case EPILOGUE:
-      fprintf (file, " = {{ %s }}", value->chars);
-      break;
-
-    default:
-      fprintf (file, "unknown token type");
-      break;
-    }
+  complain_at (*loc, "%s", msg);
 }
 
 }
 
-static void
-gram_error (location const *loc, char const *msg)
+char const *
+token_name (int type)
 {
 {
-  complain_at (*loc, "%s", msg);
+  return yytname[type];
 }
 }