X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/1c7b7e1d87f698efb2e3daad0f6484829563d96f..a7706735d143e3d7ab255e162499584e5337ba72:/src/parse-gram.y?ds=sidebyside

diff --git a/src/parse-gram.y b/src/parse-gram.y
index a8a1335b..683a05ff 100644
--- a/src/parse-gram.y
+++ b/src/parse-gram.y
@@ -1,13 +1,13 @@
 %{/* Bison Grammar Parser                             -*- C -*-
 
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation,
-   Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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
+   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
+   the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -16,22 +16,18 @@
    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
-*/
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include "system.h"
 
-#include <strverscmp.h>
-
 #include "complain.h"
 #include "conflicts.h"
 #include "files.h"
 #include "getargs.h"
 #include "gram.h"
-#include "muscle_tab.h"
+#include "muscle-tab.h"
+#include "named-ref.h"
 #include "quotearg.h"
 #include "reader.h"
 #include "symlist.h"
@@ -54,35 +50,29 @@ static void version_check (location const *loc, char const *version);
 static void gram_error (location const *, char const *);
 
 static char const *char_name (char);
-
-/** Add a lex-param or a parse-param.
- *
- * \param type  \a lex_param or \a parse_param
- * \param decl  the formal argument
- * \param loc   the location in the source.
- */
-static void add_param (char const *type, char *decl, location loc);
-
-
-static symbol_class current_class = unknown_sym;
-static uniqstr current_type = NULL;
-static symbol *current_lhs;
-static location current_lhs_location;
-static int current_prec = 0;
-
-#define YYTYPE_INT16 int_fast16_t
-#define YYTYPE_INT8 int_fast8_t
-#define YYTYPE_UINT16 uint_fast16_t
-#define YYTYPE_UINT8 uint_fast8_t
 %}
 
+%code
+{
+  static symbol_class current_class = unknown_sym;
+  static uniqstr current_type = NULL;
+  static symbol *current_lhs;
+  static location current_lhs_location;
+  static named_ref *current_lhs_named_ref;
+  static int current_prec = 0;
+
+  #define YYTYPE_INT16 int_fast16_t
+  #define YYTYPE_INT8 int_fast8_t
+  #define YYTYPE_UINT16 uint_fast16_t
+  #define YYTYPE_UINT8 uint_fast8_t
+}
+
 %debug
 %verbose
 %defines
 %locations
 %pure-parser
-%error-verbose
-%defines
+%define parse.error "verbose"
 %name-prefix="gram_"
 %expect 0
 
@@ -96,12 +86,13 @@ static int current_prec = 0;
 
 %union
 {
+  assoc assoc;
+  char *code;
+  char const *chars;
+  int integer;
+  named_ref *named_ref;
   symbol *symbol;
   symbol_list *list;
-  int integer;
-  char const *chars;
-  char *code;
-  assoc assoc;
   uniqstr uniqstr;
   unsigned char character;
 };
@@ -121,6 +112,7 @@ static int current_prec = 0;
 %token PERCENT_LEFT        "%left"
 %token PERCENT_RIGHT       "%right"
 %token PERCENT_NONASSOC    "%nonassoc"
+%token PERCENT_PRECEDENCE  "%precedence"
 
 %token PERCENT_PREC          "%prec"
 %token PERCENT_DPREC         "%dprec"
@@ -133,31 +125,24 @@ static int current_prec = 0;
 
 %token
   PERCENT_CODE            "%code"
-  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_EXPECT_RR       "%expect-rr"
+  PERCENT_FLAG            "%<flag>"
   PERCENT_FILE_PREFIX     "%file-prefix"
   PERCENT_GLR_PARSER      "%glr-parser"
   PERCENT_INITIAL_ACTION  "%initial-action"
   PERCENT_LANGUAGE        "%language"
-  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"
+                          "%nondeterministic-parser"
   PERCENT_OUTPUT          "%output"
-  PERCENT_PARSE_PARAM     "%parse-param"
-  PERCENT_PURE_PARSER     "%pure-parser"
-  PERCENT_PUSH_PARSER     "%push-parser"
-  PERCENT_PUSH_PULL_PARSER
-                          "%push-pull-parser"
-  PERCENT_REQUIRE	  "%require"
+  PERCENT_REQUIRE         "%require"
   PERCENT_SKELETON        "%skeleton"
   PERCENT_START           "%start"
   PERCENT_TOKEN_TABLE     "%token-table"
@@ -175,36 +160,84 @@ static int current_prec = 0;
 %token PIPE            "|"
 %token PROLOGUE        "%{...%}"
 %token SEMICOLON       ";"
-%token TYPE            "type"
-%token TYPE_TAG_ANY    "<*>"
-%token TYPE_TAG_NONE   "<>"
+%token TAG             "<tag>"
+%token TAG_ANY         "<*>"
+%token TAG_NONE        "<>"
+%token BRACKETED_ID    "[identifier]"
 
 %type <character> CHAR
 %printer { fputs (char_name ($$), stderr); } CHAR
 
 /* braceless is not to be used for rule or symbol actions, as it
    calls code_props_plain_init.  */
-%type <chars> STRING "%{...%}" EPILOGUE braceless content content.opt
+%type <chars> STRING "%{...%}" EPILOGUE braceless content.opt
 %type <code> "{...}"
 %printer { fputs (quotearg_style (c_quoting_style, $$), stderr); }
 	 STRING
 %printer { fprintf (stderr, "{\n%s\n}", $$); }
-	 braceless content content.opt "{...}" "%{...%}" EPILOGUE
+	 braceless content.opt "{...}" "%{...%}" EPILOGUE
 
-%type <uniqstr> TYPE ID ID_COLON
-%printer { fprintf (stderr, "<%s>", $$); } TYPE
-%printer { fputs ($$, stderr); } ID
+%type <uniqstr> TAG ID ID_COLON BRACKETED_ID PERCENT_FLAG variable
+%type <named_ref> named_ref.opt
+%printer { fputs ($$, stderr); } ID variable
 %printer { fprintf (stderr, "%s:", $$); } ID_COLON
+%printer { fprintf (stderr, "%%%s", $$); } PERCENT_FLAG
+%printer { fprintf (stderr, "<%s>", $$); } TAG
 
 %type <integer> INT
 %printer { fprintf (stderr, "%d", $$); } INT
 
-%type <symbol> id id_colon symbol string_as_id
+%type <symbol> id id_colon symbol symbol.prec string_as_id
 %printer { fprintf (stderr, "%s", $$->tag); } id symbol string_as_id
 %printer { fprintf (stderr, "%s:", $$->tag); } id_colon
 
 %type <assoc> precedence_declarator
-%type <list>  symbols.1 generic_symlist generic_symlist_item
+%type <list>  symbols.1 symbols.prec generic_symlist generic_symlist_item
+
+/*---------.
+| %param.  |
+`---------*/
+%code requires
+{
+# ifndef PARAM_TYPE
+#  define PARAM_TYPE
+  typedef enum
+  {
+    param_lex    = 1 << 0,
+    param_parse  = 1 << 1,
+    param_both   = param_lex | param_parse
+  } param_type;
+# endif
+};
+%code
+{
+  /** Add a lex-param and/or a parse-param.
+   *
+   * \param type  where to push this formal argument.
+   * \param decl  the formal argument.  Destroyed.
+   * \param loc   the location in the source.
+   */
+  static void add_param (param_type type, char *decl, location loc);
+};
+%union
+{
+  param_type param;
+}
+%token <param> PERCENT_PARAM "%param";
+%printer
+{
+  switch ($$)
+    {
+#define CASE(In, Out)                                           \
+      case param_ ## In:   fputs ("%" #Out, stderr); break
+
+      CASE(lex,   lex-param);
+      CASE(parse, parse-param);
+      CASE(both,  param);
+    }
+#undef CASE
+} <param>;
+
 %%
 
 input:
@@ -229,18 +262,30 @@ prologue_declaration:
       code_props_plain_init (&plain_code, $1, @1);
       code_props_translate_code (&plain_code);
       gram_scanner_last_string_free ();
-      prologue_augment (plain_code.code, @1, union_seen);
+      muscle_code_grow (union_seen ? "post_prologue" : "pre_prologue",
+                        plain_code.code, @1);
       code_scanner_last_string_free ();
     }
-| "%debug"                         { debug_flag = true; }
-| "%define" STRING content.opt     { muscle_insert ($2, $3); }
+| "%<flag>"
+    {
+      muscle_percent_define_ensure ($1, @1, true);
+    }
+| "%define" variable content.opt
+    {
+      muscle_percent_define_insert ($2, @2, $3,
+                                    MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
+    }
 | "%defines"                       { defines_flag = true; }
 | "%defines" STRING
     {
       defines_flag = true;
       spec_defines_file = xstrdup ($2);
     }
-| "%error-verbose"                 { error_verbose = true; }
+| "%error-verbose"
+    {
+      muscle_percent_define_insert ("parse.error", @1, "verbose",
+                                    MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
+    }
 | "%expect" INT                    { expected_sr_conflicts = $2; }
 | "%expect-rr" INT		   { expected_rr_conflicts = $2; }
 | "%file-prefix" STRING            { spec_file_prefix = $2; }
@@ -259,27 +304,50 @@ prologue_declaration:
       muscle_code_grow ("initial_action", action.code, @2);
       code_scanner_last_string_free ();
     }
-| "%language" STRING		{ language_argmatch ($2, 1, &@1); }
-| "%lex-param" "{...}"		{ add_param ("lex_param", $2, @2); }
-| "%locations"                  { locations_flag = true; }
+| "%language" STRING		{ language_argmatch ($2, grammar_prio, @1); }
 | "%name-prefix" STRING         { spec_name_prefix = $2; }
 | "%name-prefix" "=" STRING     { spec_name_prefix = $3; } /* deprecated */
 | "%no-lines"                   { no_lines_flag = true; }
 | "%nondeterministic-parser"	{ nondeterministic_parser = true; }
 | "%output" STRING              { spec_outfile = $2; }
 | "%output" "=" STRING          { spec_outfile = $3; }  /* deprecated */
-| "%parse-param" "{...}"	{ add_param ("parse_param", $2, @2); }
-| "%pure-parser"                { pure_parser = true; }
-| "%push-parser"                { push_parser = true; pull_parser = false; }
-| "%push-pull-parser"           { push_parser = true; pull_parser = true; }
+| "%param" "{...}"	        { add_param ($1, $2, @2); }
 | "%require" STRING             { version_check (&@2, $2); }
-| "%skeleton" STRING            { skeleton_arg ($2, 1, &@1); }
+| "%skeleton" STRING
+    {
+      char const *skeleton_user = $2;
+      if (strchr (skeleton_user, '/'))
+        {
+          size_t dir_length = strlen (current_file);
+          char *skeleton_build;
+          while (dir_length && current_file[dir_length - 1] != '/')
+            --dir_length;
+          while (dir_length && current_file[dir_length - 1] == '/')
+            --dir_length;
+          skeleton_build =
+            xmalloc (dir_length + 1 + strlen (skeleton_user) + 1);
+          if (dir_length > 0)
+            {
+              strncpy (skeleton_build, current_file, dir_length);
+              skeleton_build[dir_length++] = '/';
+            }
+          strcpy (skeleton_build + dir_length, skeleton_user);
+          skeleton_user = uniqstr_new (skeleton_build);
+          free (skeleton_build);
+        }
+      skeleton_arg (skeleton_user, grammar_prio, @1);
+    }
 | "%token-table"                { token_table_flag = true; }
-| "%verbose"                    { report_flag = report_states; }
+| "%verbose"                    { report_flag |= report_states; }
 | "%yacc"                       { yacc_flag = true; }
 | /*FIXME: Err?  What is this horror doing here? */ ";"
 ;
 
+
+/*----------------------.
+| grammar_declaration.  |
+`----------------------*/
+
 grammar_declaration:
   precedence_declaration
 | symbol_declaration
@@ -311,28 +379,22 @@ grammar_declaration:
     }
 | "%code" braceless
     {
-      muscle_code_grow ("percent_code", $2, @2);
+      /* Do not invoke muscle_percent_code_grow here since it invokes
+         muscle_user_name_list_grow.  */
+      muscle_code_grow ("percent_code()", $2, @2);
       code_scanner_last_string_free ();
     }
-| "%code" STRING braceless
+| "%code" ID braceless
     {
-      char const name_prefix[] = "percent_code_";
-      char *name = xmalloc (sizeof name_prefix + strlen ($2));
-      strcpy (name, name_prefix);
-      strcpy (name + sizeof name_prefix - 1, $2);
-      muscle_code_grow (uniqstr_new (name), $3, @3);
-      free (name);
+      muscle_percent_code_grow ($2, @2, $3, @3);
       code_scanner_last_string_free ();
-      muscle_grow ("used_percent_code_qualifiers", "[[", ",");
-      muscle_grow ("used_percent_code_qualifiers", $2, "");
-      muscle_grow ("used_percent_code_qualifiers", "]]", "");
     }
 ;
 
 
-/*----------*
- | %union.  |
- *----------*/
+/*---------.
+| %union.  |
+`---------*/
 
 %token PERCENT_UNION "%union";
 
@@ -342,28 +404,11 @@ union_name:
 ;
 
 grammar_declaration:
-  "%union" union_name "{...}"
+  "%union" union_name braceless
     {
-      char const *body = $3;
-
-      /* Concatenate the %union bodies.  If this is the first %union, make sure
-	 the synchronization line appears after the opening '{' so as not to
-	 confuse Doxygen.  Otherwise, turn the previous %union's trailing '}'
-	 into '\n', and omit the new %union's leading '{'.  */
-      if (!union_seen)
-	{
-	  muscle_grow ("stype", "{", "");
-	}
-      else
-	{
-	  char *code = muscle_find ("stype");
-	  code[strlen (code) - 1] = '\n';
-	}
-      body++;
-
       union_seen = true;
-      muscle_code_grow ("stype", body, @3);
-      gram_scanner_last_string_free ();
+      muscle_code_grow ("stype", $3, @3);
+      code_scanner_last_string_free ();
     }
 ;
 
@@ -381,7 +426,7 @@ symbol_declaration:
       current_class = unknown_sym;
       current_type = NULL;
     }
-| "%type" TYPE symbols.1
+| "%type" TAG symbols.1
     {
       symbol_list *list;
       tag_seen = true;
@@ -392,7 +437,7 @@ symbol_declaration:
 ;
 
 precedence_declaration:
-  precedence_declarator type.opt symbols.1
+  precedence_declarator tag.opt symbols.prec
     {
       symbol_list *list;
       ++current_prec;
@@ -407,16 +452,30 @@ precedence_declaration:
 ;
 
 precedence_declarator:
-  "%left"     { $$ = left_assoc; }
-| "%right"    { $$ = right_assoc; }
-| "%nonassoc" { $$ = non_assoc; }
+  "%left"       { $$ = left_assoc; }
+| "%right"      { $$ = right_assoc; }
+| "%nonassoc"   { $$ = non_assoc; }
+| "%precedence" { $$ = precedence_assoc; }
 ;
 
-type.opt:
+tag.opt:
   /* Nothing. */ { current_type = NULL; }
-| TYPE           { current_type = $1; tag_seen = true; }
+| TAG            { current_type = $1; tag_seen = true; }
+;
+
+/* Just like symbols.1 but accept INT for the sake of POSIX.  */
+symbols.prec:
+  symbol.prec
+    { $$ = symbol_list_sym_new ($1, @1); }
+| symbols.prec symbol.prec
+    { $$ = symbol_list_prepend ($1, symbol_list_sym_new ($2, @2)); }
 ;
 
+symbol.prec:
+    symbol { $$ = $1; }
+  | symbol INT { $$ = $1; symbol_user_token_number_set ($1, $2, @2); }
+  ;
+
 /* One or more symbols to be %typed. */
 symbols.1:
   symbol
@@ -431,15 +490,15 @@ generic_symlist:
 ;
 
 generic_symlist_item:
-  symbol            { $$ = symbol_list_sym_new ($1, @1); }
-| TYPE              { $$ = symbol_list_type_new ($1, @1); }
-| "<*>"             { $$ = symbol_list_default_tagged_new (@1); }
-| "<>"             { $$ = symbol_list_default_tagless_new (@1); }
+  symbol    { $$ = symbol_list_sym_new ($1, @1); }
+| TAG       { $$ = symbol_list_type_new ($1, @1); }
+| "<*>"     { $$ = symbol_list_default_tagged_new (@1); }
+| "<>"      { $$ = symbol_list_default_tagless_new (@1); }
 ;
 
 /* One token definition.  */
 symbol_def:
-  TYPE
+  TAG
      {
        current_type = $1;
        tag_seen = true;
@@ -498,7 +557,8 @@ rules_or_grammar_declaration:
 ;
 
 rules:
-  id_colon { current_lhs = $1; current_lhs_location = @1; } rhses.1
+  id_colon named_ref.opt { current_lhs = $1; current_lhs_location = @1;
+    current_lhs_named_ref = $2; } rhses.1
 ;
 
 rhses.1:
@@ -509,40 +569,50 @@ rhses.1:
 
 rhs:
   /* Nothing.  */
-    { grammar_current_rule_begin (current_lhs, current_lhs_location); }
-| rhs symbol
-    { grammar_current_rule_symbol_append ($2, @2); }
-| rhs "{...}"
-    { grammar_current_rule_action_append ($2, @2); }
+    { grammar_current_rule_begin (current_lhs, current_lhs_location,
+				  current_lhs_named_ref); }
+| rhs symbol named_ref.opt
+    { grammar_current_rule_symbol_append ($2, @2, $3); }
+| rhs "{...}" named_ref.opt
+    { grammar_current_rule_action_append ($2, @2, $3); }
 | rhs "%prec" symbol
     { grammar_current_rule_prec_set ($3, @3); }
 | rhs "%dprec" INT
     { grammar_current_rule_dprec_set ($3, @3); }
-| rhs "%merge" TYPE
+| rhs "%merge" TAG
     { grammar_current_rule_merge_set ($3, @3); }
 ;
 
+named_ref.opt:
+  /* Nothing. */ { $$ = 0; }
+|
+  BRACKETED_ID   { $$ = named_ref_new($1, @1); }
+;
 
-/*-----------*
- | content.  |
- *-----------*/
 
-content:
-  STRING
-| braceless
+/*---------------------------.
+| variable and content.opt.  |
+`---------------------------*/
+
+/* The STRING form of variable is deprecated and is not M4-friendly.
+   For example, M4 fails for `%define "[" "value"'.  */
+variable:
+  ID
+| STRING { $$ = uniqstr_new ($1); }
 ;
 
-/* Some content or "1" by default. */
+/* Some content or empty by default. */
 content.opt:
-  /* Nothing. */
-    {
-      static char one[] = "1";
-      $$ = one;
-    }
-| content
+  /* Nothing. */   { $$ = ""; }
+| ID { $$ = $1; }
+| STRING
 ;
 
 
+/*------------.
+| braceless.  |
+`------------*/
+
 braceless:
   "{...}"
     {
@@ -556,9 +626,9 @@ braceless:
 ;
 
 
-/*---------------*
- | Identifiers.  |
- *---------------*/
+/*--------------.
+| Identifiers.  |
+`--------------*/
 
 /* Identifiers are returned as uniqstr values by the scanner.
    Depending on their use, we may need to make them genuine symbols.  */
@@ -639,11 +709,8 @@ lloc_default (YYLTYPE const *rhs, int n)
 }
 
 
-/* Add a lex-param or a parse-param (depending on TYPE) with
-   declaration DECL and location LOC.  */
-
 static void
-add_param (char const *type, char *decl, location loc)
+add_param (param_type type, char *decl, location loc)
 {
   static char const alphanum[26 + 26 + 1 + 10] =
     "abcdefghijklmnopqrstuvwxyz"
@@ -683,7 +750,10 @@ add_param (char const *type, char *decl, location loc)
       name = xmalloc (name_len + 1);
       memcpy (name, name_start, name_len);
       name[name_len] = '\0';
-      muscle_pair_list_grow (type, decl, name);
+      if (type & param_lex)
+        muscle_pair_list_grow ("lex_param", decl, name);
+      if (type & param_parse)
+        muscle_pair_list_grow ("parse_param", decl, name);
       free (name);
     }