X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/50a339934c5e471f02a1d28171b14e2875a05cf0..eb1b07409f0ccad9970c8a60ded9f2a56d205b9c:/src/parse-gram.y?ds=sidebyside

diff --git a/src/parse-gram.y b/src/parse-gram.y
index bc012637..df92d642 100644
--- a/src/parse-gram.y
+++ b/src/parse-gram.y
@@ -1,6 +1,7 @@
 %{/* Bison Grammar Parser                             -*- C -*-
 
-   Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation,
+   Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
@@ -81,8 +82,8 @@ static int current_prec = 0;
 %locations
 %pure-parser
 %error-verbose
-%defines
 %name-prefix="gram_"
+%expect 0
 
 %initial-action
 {
@@ -92,13 +93,13 @@ static int current_prec = 0;
   boundary_set (&@$.end, current_file, 1, 1);
 }
 
-/* Only NUMBERS have a value.  */
 %union
 {
   symbol *symbol;
   symbol_list *list;
   int integer;
-  char *chars;
+  char const *chars;
+  char *code;
   assoc assoc;
   uniqstr uniqstr;
   unsigned char character;
@@ -130,19 +131,18 @@ static int current_prec = 0;
 `----------------------*/
 
 %token
-  PERCENT_AFTER_HEADER    "%after-header"
-  PERCENT_BEFORE_HEADER   "%before-header"
+  PERCENT_CODE            "%code"
   PERCENT_DEBUG           "%debug"
   PERCENT_DEFAULT_PREC    "%default-prec"
   PERCENT_DEFINE          "%define"
   PERCENT_DEFINES         "%defines"
-  PERCENT_END_HEADER      "%end-header"
   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_LANGUAGE        "%language"
   PERCENT_LEX_PARAM       "%lex-param"
   PERCENT_LOCATIONS       "%locations"
   PERCENT_NAME_PREFIX     "%name-prefix"
@@ -153,10 +153,12 @@ static int current_prec = 0;
   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_SKELETON        "%skeleton"
   PERCENT_START           "%start"
-  PERCENT_START_HEADER    "%start-header"
   PERCENT_TOKEN_TABLE     "%token-table"
   PERCENT_VERBOSE         "%verbose"
   PERCENT_YACC            "%yacc"
@@ -173,21 +175,24 @@ static int current_prec = 0;
 %token PROLOGUE        "%{...%}"
 %token SEMICOLON       ";"
 %token TYPE            "type"
+%token TYPE_TAG_ANY    "<*>"
+%token TYPE_TAG_NONE   "<>"
 
 %type <character> CHAR
 %printer { fputs (char_name ($$), stderr); } CHAR
 
 /* braceless is not to be used for rule or symbol actions, as it
-   calls translate_code. */
-%type <chars> STRING "{...}" "%{...%}" EPILOGUE braceless content content.opt
+   calls code_props_plain_init.  */
+%type <chars> STRING "%{...%}" EPILOGUE braceless content.opt
+%type <code> "{...}"
 %printer { fputs (quotearg_style (c_quoting_style, $$), stderr); }
-         STRING
+	 STRING
 %printer { fprintf (stderr, "{\n%s\n}", $$); }
-         braceless content content.opt "{...}" "%{...%}" EPILOGUE
+	 braceless content.opt "{...}" "%{...%}" EPILOGUE
 
-%type <uniqstr> TYPE ID ID_COLON
+%type <uniqstr> TYPE ID ID_COLON variable
 %printer { fprintf (stderr, "<%s>", $$); } TYPE
-%printer { fputs ($$, stderr); } ID
+%printer { fputs ($$, stderr); } ID variable
 %printer { fprintf (stderr, "%s:", $$); } ID_COLON
 
 %type <integer> INT
@@ -198,7 +203,7 @@ static int current_prec = 0;
 %printer { fprintf (stderr, "%s:", $$->tag); } id_colon
 
 %type <assoc> precedence_declarator
-%type <list>  symbols.1
+%type <list>  symbols.1 generic_symlist generic_symlist_item
 %%
 
 input:
@@ -217,17 +222,32 @@ prologue_declarations:
 
 prologue_declaration:
   grammar_declaration
-| "%{...%}"     { prologue_augment (translate_code ($1, @1), @1, union_seen); }
-| "%after-header" braceless        { prologue_augment ($2, @2, true); }
-| "%before-header" braceless       { prologue_augment ($2, @2, false); }
+| "%{...%}"
+    {
+      code_props plain_code;
+      code_props_plain_init (&plain_code, $1, @1);
+      code_props_translate_code (&plain_code);
+      gram_scanner_last_string_free ();
+      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); }
+| "%define" variable content.opt
+    {
+      muscle_percent_define_insert ($2, @2, $3);
+    }
 | "%defines"                       { defines_flag = true; }
-| "%end-header" braceless          { muscle_code_grow ("end_header", $2, @2); }
+| "%defines" STRING
+    {
+      defines_flag = true;
+      spec_defines_file = xstrdup ($2);
+    }
 | "%error-verbose"                 { error_verbose = true; }
 | "%expect" INT                    { expected_sr_conflicts = $2; }
 | "%expect-rr" INT		   { expected_rr_conflicts = $2; }
-| "%file-prefix" "=" STRING        { spec_file_prefix = $3; }
+| "%file-prefix" STRING            { spec_file_prefix = $2; }
+| "%file-prefix" "=" STRING        { spec_file_prefix = $3; } /* deprecated */
 | "%glr-parser"
     {
       nondeterministic_parser = true;
@@ -235,19 +255,51 @@ prologue_declaration:
     }
 | "%initial-action" "{...}"
     {
-      muscle_code_grow ("initial_action", translate_symbol_action ($2, @2), @2);
+      code_props action;
+      code_props_symbol_action_init (&action, $2, @2);
+      code_props_translate_code (&action);
+      gram_scanner_last_string_free ();
+      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; }
-| "%name-prefix" "=" STRING     { spec_name_prefix = $3; }
+| "%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 = $3; }
+| "%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; }
 | "%require" STRING             { version_check (&@2, $2); }
-| "%skeleton" STRING            { skeleton = $2; }
-| "%start-header" braceless     { muscle_code_grow ("start_header", $2, @2); }
+| "%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, 1, &@1);
+    }
 | "%token-table"                { token_table_flag = true; }
 | "%verbose"                    { report_flag = report_states; }
 | "%yacc"                       { yacc_flag = true; }
@@ -261,20 +313,18 @@ grammar_declaration:
     {
       grammar_start_symbol_set ($2, @2);
     }
-| "%destructor" "{...}" symbols.1
+| "%destructor" "{...}" generic_symlist
     {
       symbol_list *list;
-      const char *action = translate_symbol_action ($2, @2);
       for (list = $3; list; list = list->next)
- 	symbol_destructor_set (list->sym, action, @2);
+	symbol_list_destructor_set (list, $2, @2);
       symbol_list_free ($3);
     }
-| "%printer" "{...}" symbols.1
+| "%printer" "{...}" generic_symlist
     {
       symbol_list *list;
-      const char *action = translate_symbol_action ($2, @2);
       for (list = $3; list; list = list->next)
-	symbol_printer_set (list->sym, action, @2);
+	symbol_list_printer_set (list, $2, @2);
       symbol_list_free ($3);
     }
 | "%default-prec"
@@ -285,6 +335,18 @@ grammar_declaration:
     {
       default_prec = false;
     }
+| "%code" braceless
+    {
+      /* 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" ID braceless
+    {
+      muscle_percent_code_grow ($2, @2, $3, @3);
+      code_scanner_last_string_free ();
+    }
 ;
 
 
@@ -300,27 +362,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);
+      muscle_code_grow ("stype", $3, @3);
+      code_scanner_last_string_free ();
     }
 ;
 
@@ -340,10 +386,10 @@ symbol_declaration:
     }
 | "%type" TYPE symbols.1
     {
-      tag_seen = true;
       symbol_list *list;
+      tag_seen = true;
       for (list = $3; list; list = list->next)
-	symbol_type_set (list->sym, $2, @2);
+	symbol_type_set (list->content.sym, $2, @2);
       symbol_list_free ($3);
     }
 ;
@@ -355,8 +401,8 @@ precedence_declaration:
       ++current_prec;
       for (list = $3; list; list = list->next)
 	{
-	  symbol_type_set (list->sym, current_type, @2);
-	  symbol_precedence_set (list->sym, current_prec, $1, @1);
+	  symbol_type_set (list->content.sym, current_type, @2);
+	  symbol_precedence_set (list->content.sym, current_prec, $1, @1);
 	}
       symbol_list_free ($3);
       current_type = NULL;
@@ -374,10 +420,24 @@ type.opt:
 | TYPE           { current_type = $1; tag_seen = true; }
 ;
 
-/* One or more nonterminals to be %typed. */
+/* One or more symbols to be %typed. */
 symbols.1:
-  symbol            { $$ = symbol_list_new ($1, @1); }
-| symbols.1 symbol  { $$ = symbol_list_prepend ($1, $2, @2); }
+  symbol
+    { $$ = symbol_list_sym_new ($1, @1); }
+| symbols.1 symbol
+    { $$ = symbol_list_prepend ($1, symbol_list_sym_new ($2, @2)); }
+;
+
+generic_symlist:
+  generic_symlist_item { $$ = $1; }
+| generic_symlist generic_symlist_item { $$ = symbol_list_prepend ($1, $2); }
+;
+
+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); }
 ;
 
 /* One token definition.  */
@@ -466,31 +526,38 @@ rhs:
 ;
 
 
-/*-----------*
- | content.  |
- *-----------*/
+/*----------------------------*
+ | variable and content.opt.  |
+ *---------------------------*/
 
-content:
-  STRING
-| braceless
-;
+variable:
+  ID
+  | STRING { $$ = uniqstr_new ($1); } /* deprecated and not M4-friendly */
+  ;
 
-/* Some content or "1" by default. */
+/* Some content or empty by default. */
 content.opt:
   /* Nothing. */
     {
-      static char one[] = "1";
-      $$ = one;
+      $$ = "";
     }
-| content
+| STRING
 ;
 
 
+/*-------------*
+ | braceless.  |
+ *-------------*/
+
 braceless:
   "{...}"
     {
+      code_props plain_code;
       $1[strlen ($1) - 1] = '\n';
-      $$ = translate_code ($1 + 1, @1);
+      code_props_plain_init (&plain_code, $1+1, @1);
+      code_props_translate_code (&plain_code);
+      gram_scanner_last_string_free ();
+      $$ = plain_code.code;
     }
 ;
 
@@ -536,8 +603,12 @@ epilogue.opt:
   /* Nothing.  */
 | "%%" EPILOGUE
     {
-      muscle_code_grow ("epilogue", translate_code ($2, @2), @2);
+      code_props plain_code;
+      code_props_plain_init (&plain_code, $2, @2);
+      code_props_translate_code (&plain_code);
       gram_scanner_last_string_free ();
+      muscle_code_grow ("epilogue", plain_code.code, @2);
+      code_scanner_last_string_free ();
     }
 ;