bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFA] GLR parsing


From: Paul Hilfinger
Subject: [RFA] GLR parsing
Date: Wed, 26 Jun 2002 16:09:17 -0700

I finally received the necessary release from the University of
California, and have started checking in changes for an experimental
GLR parsing feature in Bison.  So far, I have added data/bison.glr and
tests/cxx-type.at, which (being additions) have no effect on existing
stuff.  I have appended a mongo patch for connecting things in, on
which (by some access of caution) I would appreciate review before checkin.

Paul Hilfinger

ChangeLog:

2002-05-14  Paul Hilfinger  <address@hidden>

        * src/reader.h: Add declaration for free_merger_functions.

        * src/reader.c: Add dprec and merger fields to symbol_list.
        (merge_functions): New variable.
        (symbol_list_new): Initialized new dprec and merger fields.
        (get_merge_function): New function.
        (free_merger_functions): New function.
        (readgram): Check for %prec that is not followed by a symbol.
        Handle %dprec and %merge declarations.
        (packgram): Initialize dprec and merger fields in rules array.

        * src/output.c (conflict_tos, conflrow, conflict_table, conflict_list,
        conflict_list_cnt, conflict_list_free): New variables.
        (table_grow): Also grow conflict_table.
        (prepare_rules): Output dprec and merger tables.  
        (conflict_row): New function.
        (action_row): Output conflict lists for GLR parser.  Don't use 
        default reduction in conflicted states for GLR parser so that there
        are spaces for the conflict lists.
        (save_row): Also save conflict information.
        (token_actions): Allocate conflict list.
        (merger_output): New function.
        (pack_vector): Pack conflict table, too.
        (output_conflicts): New function to output yyconflp and yyconfl.
        (output_check): Allocate conflict_tos.
        (output_actions): Output conflict tables, also.
        (output_skeleton): Output b4_mergers definition.
        (prepare): Output b4_max_rhs_length definition.
        Use 'bison.glr' as default skeleton for GLR parsers.

        * src/gram.c (glr_parser): New flag.
        (grammar_free): Call free_merger_functions.

        * src/conflicts.c (count_rr_conflicts): Augment to optionally count
        all pairs of conflicting reductions, rather than just all tokens
        causing conflicts.  Needed to size conflict tables.
        (conflicts_output): Modify call to count_rr_conflicts for new 
        interface.
        (conflicts_print): Ditto.
        (count_total_conflicts): New function.

        * src/reader.h (merger_list): New type.
        (merge_functions): New variable.

        * src/lex.h (tok_dprec, tok_merge): New token types.

        * src/gram.h (rule_s): Add dprec and merger fields.
        (glr_parser): New flag.

        * src/conflicts.h (count_total_conflicts): New function.

        * src/options.c (option_table): Add %dprec, %merge, and %glr-parser.

        * doc/bison.texinfo (Generalized LR Parsing): New section.
        (GLR Parsers): New section.
        (Language and Grammar): Mention GLR parsing.
        (Table of Symbols): Add %dprec, %glr-parser, %merge, GLR
        Correct typo ("tge" -> "the").

        * data/bison.glr: New skeleton for GLR parsing.

        * tests/cxx-gram.at: New tests for GLR parsing.

        * tests/testsuite.at: Include cxx-gram.at.

        * tests/Makefile.am: Add cxx-gram.at.

Index: bison-1_5.26/doc/bison.texinfo
--- bison-1_5.26/doc/bison.texinfo Wed, 19 Jun 2002 13:38:57 -0700 hilfingr 
(glrbison/26_bison.texi 1.1.1.2.1.1 644)
+++ 2.64(w)/doc/bison.texinfo Wed, 19 Jun 2002 14:06:17 -0700 hilfingr 
(glrbison/26_bison.texi 1.1.1.2.1.2 644)
@@ -282,6 +282,7 @@ The Bison Parser Algorithm
 * Parser States::     The parser is a finite-state-machine with stack.
 * Reduce/Reduce::     When two rules are applicable in the same situation.
 * Mystery Conflicts::  Reduce/reduce conflicts that look unjustified.
+* Generalized LR Parsing::  Parsing arbitrary context-free grammars.
 * Stack Overflow::    What happens when stack gets full.  How to avoid it.
 
 Operator Precedence
@@ -388,6 +389,7 @@ use Bison or Yacc, we suggest you start 
                         a semantic value (the value of an integer,
                         the name of an identifier, etc.).
 * Semantic Actions::  Each rule can have an action containing C code.
+* GLR Parsers::       Writing parsers for general context-free languages
 * Locations Overview::    Tracking Locations.
 * Bison Parser::      What are Bison's input and output,
                         how is the output used?
@@ -418,8 +420,12 @@ specify the language Algol 60.  Any gram
 context-free grammar.  The input to Bison is essentially machine-readable
 BNF.
 
-Not all context-free languages can be handled by Bison, only those
-that are LALR(1).  In brief, this means that it must be possible to
address@hidden LALR(1) grammars
address@hidden LR(1) grammars
+There are various important subclasses of context-free grammar.  Although it
+can handle almost all context-free grammars, Bison is optimized for what
+are called LALR(1) grammars.
+In brief, in these grammars, it must be possible to
 tell how to parse any portion of an input string with just a single
 token of look-ahead.  Strictly speaking, that is a description of an
 LR(1) grammar, and LALR(1) involves additional restrictions that are
@@ -427,6 +433,24 @@ hard to explain simply; but it is rare i
 LR(1) grammar that fails to be LALR(1).  @xref{Mystery Conflicts, ,
 Mysterious Reduce/Reduce Conflicts}, for more information on this.
 
address@hidden GLR parsing
address@hidden generalized LR (GLR) parsing
address@hidden ambiguous grammars
address@hidden non-deterministic parsing
+Parsers for LALR(1) grammars are @dfn{deterministic}, meaning roughly that
+the next grammar rule to apply at any point in the input is uniquely 
+determined by the preceding input and a fixed, finite portion (called
+a @dfn{look-ahead}) of the remaining input.
+A context-free grammar can be @dfn{ambiguous}, meaning that 
+there are multiple ways to apply the grammar rules to get the some inputs.
+Even unambiguous grammars can be @dfn{non-deterministic}, meaning that no
+fixed look-ahead always suffices to determine the next grammar rule to apply.
+With the proper declarations, Bison is also able to parse these more general 
+context-free grammars, using a technique known as GLR parsing (for 
+Generalized LR).  Bison's GLR parsers are able to handle any context-free 
+grammar for which the number of possible parses of any given string 
+is finite.  
+
 @cindex symbols (abstract)
 @cindex token
 @cindex syntactic grouping
@@ -632,6 +656,160 @@ expr: expr '+' expr   @{ $$ = $1 + $3; @
 The action says how to produce the semantic value of the sum expression
 from the values of the two subexpressions.
 
address@hidden GLR Parsers
address@hidden Writing GLR Parsers
address@hidden GLR parsing
address@hidden generalized LR (GLR) parsing
address@hidden %glr-parser
address@hidden conflicts
address@hidden shift/reduce conflicts
+
+In some grammars, there will be cases where Bison's standard LALR(1) parsing
+algorithm cannot decide whether to apply a certain grammar rule at a given
+point.  That is, it may not be able to decide (on the basis of the input read
+so far) which of two possible reductions (applications of a grammar rule)
+applies, or whether to apply a reduction or read more of the input and
+apply a reduction later in the input.  These are known respectively as
address@hidden/reduce} conflicts (@pxref{Reduce/Reduce}), and 
address@hidden/reduce} conflicts (@pxref{Shift/Reduce}).
+
+To use a grammar that is not easily modified to be LALR(1), a more general
+parsing algorithm is sometimes necessary.  If you include 
address@hidden among the Bison declarations in your file 
+(@pxref{Grammar Outline}), the result will be a Generalized LR (GLR) parser.
+These parsers handle Bison grammars that contain no unresolved 
+conflicts (i.e., after
+applying precedence declarations) identically to LALR(1) parsers.
+However, when faced with unresolved shift/reduce and reduce/reduce conflicts,
+GLR parsers use the simple
+expedient of doing both, effectively cloning the parser to 
+follow both possibilities.  Each of the resulting parsers can again split, 
+so that at any given time, there can be any number of possible parses being
+explored.  The parsers proceed in lockstep; that is, all of them 
+consume (shift) a given input symbol before any of them proceed to the next.
+Each of the cloned parsers eventually meets one of two possible fates: 
+either it runs into a parsing error, in which case it simply vanishes, or it 
+merges with another parser, because the two of them have reduced the input to
+an identical set of symbols.  
+
+During the time that there are multiple parsers,
+semantic actions are recorded, but not performed.  When a parser disappears,
+its recorded semantic actions disappear as well, and are never performed.
+When a reduction makes two parsers identical, causing them to merge,
+Bison records both sets of semantic actions.  Whenever the last two parsers 
+merge, reverting to the single-parser case, Bison resolves all the outstanding
+actions either by precedences given to the grammar rules involved, or by
+performing both actions, and then calling a designated user-defined 
+function on the resulting values to produce an arbitrary merged result.
+
+Let's consider an example, vastly simplified from C++.  
+
address@hidden
address@hidden
+  #define YYSTYPE const char*
address@hidden
+
+%token TYPENAME ID
+
+%right '='
+%left '+'
+
+%glr-parser
+
+%%
+
+prog : 
+     | prog stmt   @{ printf ("\n"); @}
+     ;
+
+stmt : expr ';'  %dprec 1
+     | decl      %dprec 2
+     ;
+
+expr : ID              @{ printf ("%s ", $$); @}
+     | TYPENAME '(' expr ')'  
+                       @{ printf ("%s <cast> ", $1); @}
+     | expr '+' expr   @{ printf ("+ "); @}
+     | expr '=' expr   @{ printf ("= "); @}
+     ;
+
+decl : TYPENAME declarator ';' 
+                       @{ printf ("%s <declare> ", $1); @}
+     | TYPENAME declarator '=' expr ';'
+                       @{ printf ("%s <init-declare> ", $1); @}
+     ;
+
+declarator : ID                @{ printf ("\"%s\" ", $1); @}
+     | '(' declarator ')'
+     ;
address@hidden example
+
address@hidden
+This models a problematic part of the C++ grammar---the ambiguity between
+certain declarations and statements.  For example,
address@hidden
+T (x) = y+z;
address@hidden example
+parses as either an @code{expr} or a @code{stmt}
+(assuming that @samp{T} is recognized as a TYPENAME and @samp{x} as an ID).
+Bison detects this as a reduce/reduce conflict between the rules
address@hidden : ID} and @code{declarator : ID}, which it cannot resolve at the 
+time it encounters @code{x} in the example above.  The two @code{%dprec} 
+declarations, however, give precedence to interpreting the example as a 
address@hidden, which implies that @code{x} is a declarator.  The parser 
therefore
+prints
address@hidden
+"x" y z + T <init-declare> 
address@hidden example
+
+Consider a different input string for this parser:
address@hidden
+T (x) + y;
address@hidden example
+Here, there is no ambiguity (this cannot be parsed as a declaration).
+However, at the time the Bison parser encounters @code{x}, it does not
+have enough information to resolve the reduce/reduce conflict (again,
+between @code{x} as an @code{expr} or a @code{declarator}).  In this
+case, no precedence declaration is used.  Instead, the parser splits
+into two, one assuming that @code{x} is an @code{expr}, and the other
+assuming @code{x} is a @code{declarator}.  The second of these parsers
+then vanishes when it sees @code{+}, and the parser prints
address@hidden
+x T <cast> y + 
address@hidden example
+
+Suppose that instead of resolving the ambiguity, you wanted to see all
+the possibilities.  For this purpose, we must @dfn{merge} the semantic 
+actions of the two possible parsers, rather than choosing one over the other.
+To do so, you could change the declaration of @code{stmt} as follows:
address@hidden
+stmt : expr ';'  %merge <stmtMerge>
+     | decl      %merge <stmtMerge>
+     ;
address@hidden example
+and define the @code{stmtMerge} function as:
address@hidden
+static YYSTYPE stmtMerge (YYSTYPE x0, YYSTYPE x1)
address@hidden
+  printf ("<OR> ");
+  return "";
address@hidden
address@hidden example
+with an accompanying forward declaration
+in the C declarations at the beginning of the file:
address@hidden
address@hidden
+  #define YYSTYPE const char*
+  static YYSTYPE stmtMerge (YYSTYPE x0, YYSTYPE x1);
address@hidden
address@hidden example
+With these declarations, the resulting parser will parse the first example
+as both an @code{expr} and a @code{decl}, and print
address@hidden
+"x" y z + T <init-declare> x T <cast> y z + = <OR> 
address@hidden example
+
+
 @node Locations Overview
 @section Locations
 @cindex location
@@ -2913,7 +3091,7 @@ the location of the grouping (the result
 is an array holding locations of all right hand side elements of the rule
 being matched. The last one is the size of the right hand side rule.
 
-By default, it is defined this way:
+By default, it is defined this way for simple LALR(1) parsers:
 
 @example
 @group
@@ -2925,6 +3103,19 @@ By default, it is defined this way:
 @end group
 @end example
 
address@hidden
+and like this for GLR parsers:
+
address@hidden
address@hidden
+#define YYLLOC_DEFAULT(Current, Rhs, N)          \
+  Current.first_line   = YYRHSLOC(Rhs,1).first_line;      \
+  Current.first_column = YYRHSLOC(Rhs,1).first_column;    \
+  Current.last_line    = YYRHSLOC(Rhs,N).last_line;       \
+  Current.last_column  = YYRHSLOC(Rhs,N).last_column;
address@hidden group
address@hidden example
+
 When defining @code{YYLLOC_DEFAULT}, you should consider that:
 
 @itemize @bullet
@@ -3890,6 +4081,7 @@ Return immediately from @code{yyparse}, 
 @findex YYBACKUP
 Unshift a token.  This macro is allowed only for rules that reduce
 a single value, and only when there is no look-ahead token.
+It is also disallowed in GLR parsers.
 It installs a look-ahead token with token type @var{token} and
 semantic value @var{value}; then it discards the value that was
 going to be reduced by this rule.
@@ -4030,6 +4222,7 @@ This kind of parser is known in the lite
 * Parser States::     The parser is a finite-state-machine with stack.
 * Reduce/Reduce::     When two rules are applicable in the same situation.
 * Mystery Conflicts::  Reduce/reduce conflicts that look unjustified.
+* Generalized LR Parsing::  Parsing arbitrary context-free grammars.
 * Stack Overflow::    What happens when stack gets full.  How to avoid it.
 @end menu
 
@@ -4624,6 +4817,82 @@ return_spec:
         ;
 @end example
 
address@hidden Generalized LR Parsing 
address@hidden Generalized LR (GLR) Parsing
address@hidden GLR parsing
address@hidden generalized LR (GLR) parsing
address@hidden ambiguous grammars
address@hidden non-deterministic parsing
+
+Bison produces @emph{deterministic} parsers that choose uniquely 
+when to reduce and which reduction to apply 
+based on a summary of the preceding input and on one extra token of lookahead.
+As a result, normal Bison handles a proper subset of the family of
+context-free languages.
+Ambiguous grammars, since they have strings with more than one possible 
+sequence of reductions cannot have deterministic parsers in this sense.
+The same is true of languages that require more than one symbol of
+lookahead, since the parser lacks the information necessary to make a
+decision at the point it must be made in a shift-reduce parser.
+Finally, as previously mentioned (@pxref{Mystery Conflicts}), 
+there are languages where Bison's particular choice of how to
+summarize the input seen so far loses necessary information.
+
+When you use the @samp{%glr-parser} declaration in your grammar file,
+Bison generates a parser that uses a different algorithm, called
+Generalized LR (or GLR).  A Bison GLR parser uses the same basic
+algorithm for parsing as an ordinary Bison parser, but behaves
+differently in cases where there is a shift-reduce conflict that has not
+been resolved by precedence rules (@pxref{Precedence}) or a 
+reduce-reduce conflict.  When a GLR parser encounters such a situation, it
+effectively @emph{splits} into a several parsers, one for each possible 
+shift or reduction.  These parsers then proceed as usual, consuming
+tokens in lock-step.  Some of the stacks may encounter other conflicts
+and split further, with the result that instead of a sequence of states, 
+a Bison GLR parsing stack is what is in effect a tree of states.  
+
+In effect, each stack represents a guess as to what the proper parse
+is.  Additional input may indicate that a guess was wrong, in which case
+the appropriate stack silently disappears.  Otherwise, the semantics
+actions generated in each stack are saved, rather than being executed 
+immediately.  When a stack disappears, its saved semantic actions never
+get executed.  When a reduction causes two stacks to become equivalent, 
+their sets of semantic actions are both saved with the state that
+results from the reduction.  We say that two stacks are equivalent
+when they both represent the same sequence of states, 
+and each pair of corresponding states represents a
+grammar symbol that produces the same segment of the input token
+stream.
+
+Whenever the parser makes a transition from having multiple
+states to having one, it reverts to the normal LALR(1) parsing
+algorithm, after resolving and executing the saved-up actions.
+At this transition, some of the states on the stack will have semantic
+values that are sets (actually multisets) of possible actions.  The
+parser tries to pick one of the actions by first finding one whose rule
+has the highest dynamic precedence, as set by the @samp{%dprec}
+declaration.  Otherwise, if the alternative actions are not ordered by 
+precedence, but there the same merging function is declared for both
+rules by the @samp{%merge} declaration, 
+Bison resolves and evaluates both and then calls the merge function on
+the result.  Otherwise, it reports an ambiguity.
+
+It is possible to use a data structure for the GLR parsing tree that
+permits the processing of any LALR(1) grammar in linear time (in the
+size of the input), any unambiguous (not necessarily LALR(1)) grammar in
+quadratic worst-case time, and any general (possibly ambiguous) 
+context-free grammar in cubic worst-case time.  However, Bison currently
+uses a simpler data structure that requires time proportional to the
+length of the input times the maximum number of stacks required for any
+prefix of the input.  Thus, really ambiguous or non-deterministic
+grammars can require exponential time and space to process.  Such badly
+behaving examples, however, are not generally of practical interest.
+Usually, non-determinism in a grammar is local---the parser is ``in
+doubt'' only for a few tokens at a time.  Therefore, the current data
+structure should generally be adequate.  On LALR(1) portions of a
+grammar, in particular, it is only slightly slower than with the default
+Bison parser.
+
 @node Stack Overflow
 @section Stack Overflow, and How to Avoid It
 @cindex stack overflow
@@ -5930,10 +6199,17 @@ Equip the parser for debugging.  @xref{D
 Bison declaration to create a header file meant for the scanner.
 @xref{Decl Summary}.
 
address@hidden %dprec 
+Bison declaration to assign a precedence to a rule that is used at parse
+time to resolve reduce/reduce conflicts.  @xref{GLR Parsers}.
+
 @item %file-prefix="@var{prefix}"
-Bison declaration to set tge prefix of the output files. @xref{Decl
+Bison declaration to set the prefix of the output files. @xref{Decl
 Summary}.
 
address@hidden %glr-parser
+Bison declaration to produce a GLR parser.  @xref{GLR Parsers}.
+
 @c @item %source-extension
 @c Bison declaration to specify the generated parser output file extension.
 @c @xref{Decl Summary}.
@@ -5946,6 +6222,12 @@ Summary}.
 Bison declaration to assign left associativity to token(s).
 @xref{Precedence Decl, ,Operator Precedence}.
 
address@hidden %merge
+Bison declaration to assign a merging function to a rule.  If there is a
+reduce/reduce conflict with a rule having the same merging function, the 
+function is applied to the two semantic values to get a single result.
address@hidden Parsers}.
+
 @item %name-prefix="@var{prefix}"
 Bison declaration to rename the external symbols. @xref{Decl Summary}.
 
@@ -6057,6 +6339,13 @@ machine moves from state to state as spe
 machine.  In the case of the parser, the input is the language being
 parsed, and the states correspond to various stages in the grammar
 rules.  @xref{Algorithm, ,The Bison Parser Algorithm }.
+
address@hidden Generalized LR (GLR)
+A parsing algorithm that can handle all context-free grammars, including those
+that are not LALR(1).  It resolves situations that Bison's usual LALR(1) 
+algorithm cannot by effectively splitting off multiple parsers, trying all
+possible parsers, and discarding those that fail in the light of additional
+right context.  @xref{Generalized LR Parsing, ,Generalized LR Parsing}.
 
 @item Grouping
 A language construct that is (in general) grammatically divisible;
Index: bison-1_5.26/doc/version.texi
--- bison-1_5.26/doc/version.texi Sun, 12 May 2002 19:40:04 -0700 hilfingr 
(glrbison/27_version.te 1.1.1.2 644)
+++ 2.64(w)/doc/version.texi Wed, 19 Jun 2002 14:07:09 -0700 hilfingr 
(glrbison/27_version.te 1.13 644)
@@ -1,4 +1,4 @@
address@hidden UPDATED 7 May 2002
address@hidden UPDATED-MONTH May 2002
address@hidden UPDATED 19 June 2002
address@hidden UPDATED-MONTH June 2002
 @set EDITION 1.49b
 @set VERSION 1.49b
Index: bison-1_5.26/doc/stamp-vti
--- bison-1_5.26/doc/stamp-vti Sun, 12 May 2002 19:40:04 -0700 hilfingr 
(glrbison/28_stamp-vti 1.1.1.2 644)
+++ 2.64(w)/doc/stamp-vti Wed, 19 Jun 2002 14:07:09 -0700 hilfingr 
(glrbison/28_stamp-vti 1.13 644)
@@ -1,4 +1,4 @@
address@hidden UPDATED 7 May 2002
address@hidden UPDATED-MONTH May 2002
address@hidden UPDATED 19 June 2002
address@hidden UPDATED-MONTH June 2002
 @set EDITION 1.49b
 @set VERSION 1.49b
Index: bison-1_5.26/src/reader.c
--- bison-1_5.26/src/reader.c Thu, 20 Jun 2002 12:56:37 -0700 hilfingr 
(glrbison/44_reader.c 1.1.1.3.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.1 644)
+++ 2.64(w)/src/reader.c Thu, 20 Jun 2002 13:01:15 -0700 hilfingr 
(glrbison/44_reader.c 1.1.1.3.1.1.1.1.1.1.1.1.1.1.1.2.1.1.1.2 644)
@@ -38,6 +38,7 @@
 int lineno;
 static symbol_list_t *grammar = NULL;
 static int start_flag = 0;
+merger_list *merge_functions;
 
 /* Nonzero if %union has been seen.  */
 int typed = 0;
@@ -106,6 +107,60 @@ epilogue_set (const char *epilogue, loca
 
 
 
+ /*-------------------------------------------------------------------.
+| Return the merger index for a merging function named NAME, whose   |
+| arguments have type TYPE.  Records the function, if new, in        |
+| merger_list.                                                      |
+`-------------------------------------------------------------------*/
+
+static int
+get_merge_function (const char* name, const char* type)
+{
+  merger_list *syms;
+  merger_list head;
+  int n;
+
+  if (! glr_parser)
+    return 0;
+
+  if (type == NULL)
+    type = "";
+
+  head.next = merge_functions;
+  for (syms = &head, n = 1; syms->next != NULL; syms = syms->next, n += 1) 
+    if (strcmp (name, syms->next->name) == 0)
+      break;
+  if (syms->next == NULL) {
+    syms->next = XMALLOC (merger_list, 1);
+    syms->next->name = strdup (name);
+    syms->next->type = strdup (type);
+    syms->next->next = NULL;
+    merge_functions = head.next;
+  } else if (strcmp (type, syms->next->type) != 0)
+    warn (_("result type clash on merge function %s: `%s' vs. `%s'"), 
+         name, type, syms->next->type);
+  return n;
+}
+
+/*--------------------------------------.
+| Free all merge-function definitions. |
+`--------------------------------------*/
+
+void
+free_merger_functions (void)
+{
+  merger_list *L0;
+  if (! glr_parser)
+    return;
+  L0 = merge_functions;
+  while (L0 != NULL)
+    {
+      merger_list *L1 = L0->next;
+      XFREE (L0);
+      L0 = L1;
+    }
+}
+
 /*-------------------------------------------------------------------.
 | Generate a dummy symbol, a nonterminal, whose name cannot conflict |
 | with the user's names.                                             |
@@ -308,6 +363,34 @@ grammar_current_rule_prec_set (symbol_t 
   current_rule->ruleprec = precsym;
 }
 
+/* Attach dynamic precedence DPREC to the current rule. */
+
+void
+grammar_current_rule_dprec_set (int dprec, location_t location)
+{
+  if (! glr_parser)
+    warn_at (location, _("%%dprec affects only GLR parsers"));
+  if (dprec <= 0)
+    complain_at (location, _("%%dprec must be followed by positive number"));
+  else if (current_rule->dprec != 0) 
+    complain_at (location, _("only one %%dprec allowed per rule"));
+  current_rule->dprec = dprec;
+}
+
+/* Attach a merge function NAME with argument type TYPE to current
+   rule. */
+
+void
+grammar_current_rule_merge_set (const char* name, location_t location)
+{
+  if (! glr_parser)
+    warn_at (location, _("%%merge affects only GLR parsers"));
+  if (current_rule->merger != 0) 
+    complain_at (location, _("only one %%merge allowed per rule"));
+  current_rule->merger = 
+    get_merge_function (name, current_rule->sym->type_name);
+}
+
 /* Attach a SYMBOL to the current rule.  If needed, move the previous
    action as a mid-rule action.  */
 
@@ -320,7 +403,6 @@ grammar_current_rule_symbol_append (symb
   grammar_symbol_append (symbol, location);
 }
 
-
 /* Attach an ACTION to the current rule.  If needed, move the previous
    action as a mid-rule action.  */
 
@@ -364,6 +446,8 @@ packgram (void)
       rules[ruleno].useful = TRUE;
       rules[ruleno].action = p->action;
       rules[ruleno].action_location = p->action_location;
+      rules[ruleno].dprec = p->dprec;
+      rules[ruleno].merger = p->merger;
 
       p = p->next;
       while (p && p->sym)
Index: bison-1_5.26/src/output.c
--- bison-1_5.26/src/output.c Thu, 20 Jun 2002 12:56:37 -0700 hilfingr 
(glrbison/48_output.c 1.1.1.3.1.1.1.2.1.1.1.2.1.1.1.1.1.1 644)
+++ 2.64(w)/src/output.c Thu, 20 Jun 2002 12:57:20 -0700 hilfingr 
(glrbison/48_output.c 1.1.1.3.1.1.1.2.1.1.1.2.1.1.1.1.1.2 644)
@@ -115,14 +115,21 @@ static int nvectors;
 static int nentries;
 static short **froms = NULL;
 static short **tos = NULL;
+static unsigned int **conflict_tos = NULL;
 static short *tally = NULL;
 static short *width = NULL;
 static short *actrow = NULL;
+static short *conflrow = NULL;
 static short *state_count = NULL;
 static short *order = NULL;
 static short *base = NULL;
 static short *pos = NULL;
 
+static unsigned int *conflict_table = NULL;
+static unsigned int *conflict_list = NULL;
+static int conflict_list_cnt;
+static int conflict_list_free;
+
 /* TABLE_SIZE is the allocated size of both TABLE and CHECK.
    We start with the original hard-coded value: SHRT_MAX
    (yes, not USHRT_MAX). */
@@ -157,6 +164,8 @@ table_grow (size_t desired)
 
   table = XREALLOC (table, short, table_size);
   check = XREALLOC (check, short, table_size);
+  if (glr_parser)
+    conflict_table = XREALLOC (conflict_table, unsigned int, table_size);
 
   for (/* Nothing. */; old_size < table_size; ++old_size)
     {
@@ -278,7 +287,7 @@ prepare_tokens (void)
 
 /*-------------------------------------------------------------.
 | Prepare the muscles related to the rules: rhs, prhs, r1, r2, |
-| rline.                                                       |
+| rline, dprec, merger                                         |
 `-------------------------------------------------------------*/
 
 static void
@@ -291,6 +300,8 @@ prepare_rules (void)
   unsigned int *rline = XMALLOC (unsigned int, nrules + 1);
   symbol_number_t *r1 = XMALLOC (symbol_number_t, nrules + 1);
   unsigned int *r2 = XMALLOC (unsigned int, nrules + 1);
+  short *dprec = XMALLOC (short, nrules + 1);
+  short *merger = XMALLOC (short, nrules + 1);
 
   for (r = 1; r < nrules + 1; ++r)
     {
@@ -308,6 +319,10 @@ prepare_rules (void)
       rhs[i++] = -1;
       /* Line where rule was defined. */
       rline[r] = rules[r].location.first_line;
+      /* Dynamic precedence (GLR) */
+      dprec[r] = rules[r].dprec;
+      /* Merger-function index (GLR) */
+      merger[r] = rules[r].merger;
     }
   assert (i == nritems);
 
@@ -316,12 +331,16 @@ prepare_rules (void)
   muscle_insert_unsigned_int_table ("rline", rline, 0, 1, nrules + 1);
   muscle_insert_symbol_number_table ("r1", r1, 0, 1, nrules + 1);
   muscle_insert_unsigned_int_table ("r2", r2, 0, 1, nrules + 1);
+  muscle_insert_short_table ("dprec", dprec, 0, 1, nrules + 1);
+  muscle_insert_short_table ("merger", merger, 0, 1, nrules + 1);
 
   free (rhs);
   free (prhs);
   free (rline);
   free (r1);
   free (r2);
+  free (dprec);
+  free (merger);
 }
 
 /*--------------------------------------------.
@@ -341,6 +360,50 @@ prepare_states (void)
 }
 
 
+/*-------------------------------------------------------------------.
+| For GLR parsers, for each conflicted token in STATE, as indicated  |
+| by non-zero entries in conflrow, create a list of possible        |
+| reductions that are alternatives to the shift or reduction        |
+| currently recorded for that token in STATE.  Store the alternative |
+| reductions followed by a 0 in conflict_list, updating                     |
+| conflict_list_cnt, and storing an index to the start of the list   |
+| back into conflrow.                                               |
+`-------------------------------------------------------------------*/
+
+static void
+conflict_row (state_t *state)
+{
+  int i, j;
+
+  if (! glr_parser)
+    return;
+
+  for (j = 0; j < ntokens; j += 1) 
+    if (conflrow[j]) 
+      {
+       conflrow[j] = conflict_list_cnt;
+
+       /* find all reductions for token j, and record all that do
+        * not match actrow[j] */
+       for (i = 0; i < state->nlookaheads; i += 1)
+         if (bitset_test (state->lookaheads[i], j)
+             && actrow[j] != -state->lookaheads_rule[i]->number)
+           {       
+             assert (conflict_list_free > 0);
+             conflict_list[conflict_list_cnt] 
+               = state->lookaheads_rule[i]->number;
+             conflict_list_cnt += 1;
+             conflict_list_free -= 1;
+           }
+       
+       /* Leave a 0 at the end */
+       assert (conflict_list_free > 0);
+       conflict_list_cnt += 1;
+       conflict_list_free -= 1;
+      }
+}
+
+
 /*------------------------------------------------------------------.
 | Decide what to do for each type of token if seen as the lookahead |
 | token in specified state.  The value returned is used as the      |
@@ -353,6 +416,11 @@ prepare_states (void)
 | This is where conflicts are resolved.  The loop over lookahead    |
 | rules considered lower-numbered rules last, and the last rule     |
 | considered that likes a token gets to handle it.                  |
+|                                                                  |
+| For GLR parsers, also sets conflrow[SYM] to an index into         |
+| conflict_list iff there is an unresolved conflict (s/r or r/r)    |
+| with symbol SYM. The default reduction is not used for a symbol   |
+| that has any such conflicts.                                     |
 `------------------------------------------------------------------*/
 
 static int
@@ -365,9 +433,10 @@ action_row (state_t *state)
   errs *errp = state->errs;
   /* set nonzero to inhibit having any default reduction */
   int nodefault = 0;
+  int conflicted = 0;
 
   for (i = 0; i < ntokens; i++)
-    actrow[i] = 0;
+    actrow[i] = conflrow[i] = 0;
 
   if (redp->nreds >= 1)
     {
@@ -381,7 +450,11 @@ action_row (state_t *state)
          /* and record this rule as the rule to use if that
             token follows.  */
          if (bitset_test (state->lookaheads[i], j))
-           actrow[j] = -state->lookaheads_rule[i]->number;
+           {
+             if (actrow[j] != 0)
+               conflicted = conflrow[j] = 1;
+             actrow[j] = -state->lookaheads_rule[i]->number;
+           }
     }
 
   /* Now see which tokens are allowed for shifts in this state.  For
@@ -399,6 +472,8 @@ action_row (state_t *state)
       if (ISVAR (symbol))
        break;
 
+      if (actrow[symbol] != 0)
+       conflicted = conflrow[symbol] = 1;
       actrow[symbol] = shift_state;
 
       /* Do not use any default reduction if there is a shift for
@@ -442,18 +517,20 @@ action_row (state_t *state)
                }
            }
 
-         /* actions which match the default are replaced with zero,
-            which means "use the default" */
+         /* GLR parsers need space for conflict lists, so we can't
+            default conflicted entries.  For non-conflicted entries
+            or as long as we are not building a GLR parser, 
+            actions that match the default are replaced with zero,
+            which means "use the default". */
 
          if (max > 0)
            {
              int j;
              for (j = 0; j < ntokens; j++)
-               if (actrow[j] == default_rule)
+               if (actrow[j] == default_rule && ! (glr_parser && conflrow[j]))
                  actrow[j] = 0;
-
-             default_rule = -default_rule;
            }
+         default_rule = -default_rule;
        }
     }
 
@@ -465,6 +542,9 @@ action_row (state_t *state)
       if (actrow[i] == SHRT_MIN)
        actrow[i] = 0;
 
+  if (conflicted)
+    conflict_row (state);
+
   return default_rule;
 }
 
@@ -477,6 +557,7 @@ save_row (int state)
   short *sp;
   short *sp1;
   short *sp2;
+  unsigned int *sp3;
 
   count = 0;
   for (i = 0; i < ntokens; i++)
@@ -488,12 +569,18 @@ save_row (int state)
 
   froms[state] = sp1 = sp = XCALLOC (short, count);
   tos[state] = sp2 = XCALLOC (short, count);
+  if (glr_parser)
+    conflict_tos[state] = sp3 = XCALLOC (unsigned int, count);  
+  else 
+    conflict_tos[state] = NULL;
 
   for (i = 0; i < ntokens; i++)
     if (actrow[i] != 0)
       {
        *sp1++ = i;
        *sp2++ = actrow[i];
+       if (glr_parser)
+         *sp3++ = conflrow[i];
       }
 
   tally[state] = count;
@@ -513,9 +600,22 @@ static void
 token_actions (void)
 {
   size_t i;
+  int nconflict = count_total_conflicts ();
+
   short *yydefact = XCALLOC (short, nstates);
 
   actrow = XCALLOC (short, ntokens);
+
+  conflrow = XCALLOC (short, ntokens);
+  if (glr_parser)
+    {
+      conflict_list = XCALLOC (unsigned int, 1 + 2 * nconflict);
+      conflict_list_free = 2 * nconflict;
+      conflict_list_cnt = 1;
+    } 
+  else 
+    conflict_list_free = conflict_list_cnt = 0;
+
   for (i = 0; i < nstates; ++i)
     {
       yydefact[i] = action_row (states[i]);
@@ -525,6 +625,7 @@ token_actions (void)
   muscle_insert_short_table ("defact", yydefact,
                             yydefact[0], 1, nstates);
   XFREE (actrow);
+  XFREE (conflrow);
   XFREE (yydefact);
 }
 
@@ -555,6 +656,28 @@ actions_output (FILE *out)
   fputs ("]])\n\n", out);
 }
 
+/*--------------------------------------.
+| Output the merge functions to OOUT.   |
+`--------------------------------------*/
+
+void
+merger_output (FILE *out)
+{
+  int n;
+  merger_list* p;
+
+  fputs ("m4_define([b4_mergers], \n[[", out);
+  for (n = 1, p = merge_functions; p != NULL; n += 1, p = p->next) 
+    {
+      if (p->type[0] == '\0') 
+       fprintf (out, "  case %d: yyval = %s (*yy0, *yy1); break;\n",
+                n, p->name);
+      else
+       fprintf (out, "  case %d: yyval.%s = %s (*yy0, *yy1); break;\n",
+                n, p->type, p->name);
+    }
+  fputs ("]])\n\n", out);
+}
 
 /*---------------------------------------.
 | Output the tokens definition to OOUT.  |
@@ -844,6 +967,7 @@ pack_vector (int vector)
   int loc = 0;
   short *from = froms[i];
   short *to = tos[i];
+  unsigned int *conflict_to = conflict_tos[i];
 
   assert (t);
 
@@ -872,6 +996,8 @@ pack_vector (int vector)
            {
              loc = j + from[k];
              table[loc] = to[k];
+             if (glr_parser && conflict_to != NULL)
+               conflict_table[loc] = conflict_to[k];
              check[loc] = from[k];
            }
 
@@ -900,6 +1026,8 @@ pack_table (void)
   base = XCALLOC (short, nvectors);
   pos = XCALLOC (short, nentries);
   table = XCALLOC (short, table_size);
+  if (glr_parser)
+    conflict_table = XCALLOC (unsigned int, table_size);
   check = XCALLOC (short, table_size);
 
   lowzero = 0;
@@ -928,14 +1056,16 @@ pack_table (void)
     {
       XFREE (froms[i]);
       XFREE (tos[i]);
+      XFREE (conflict_tos[i]);
     }
 
   XFREE (froms);
   XFREE (tos);
+  XFREE (conflict_tos);
   XFREE (pos);
 }
 
-/* the following functions output yytable, yycheck
+/* the following functions output yytable, yycheck, yyconflp, yyconfl,
    and the vectors whose elements index the portion starts */
 
 static void
@@ -962,6 +1092,28 @@ output_table (void)
 
 
 static void
+output_conflicts (void)
+{
+  /* GLR parsing slightly modifies yytable and yycheck
+     (and thus yypact) so that in states with unresolved conflicts,
+     the default reduction is not used in the conflicted entries, so
+     that there is a place to put a conflict pointer.  This means that
+     yyconflp and yyconfl are nonsense for a non-GLR parser, so we
+     avoid accidents by not writing them out in that case. */
+  if (! glr_parser)
+    return;
+
+  muscle_insert_unsigned_int_table ("conflp", conflict_table, 
+                                   conflict_table[0], 1, high+1);
+  muscle_insert_unsigned_int_table ("confl", conflict_list, 
+                            conflict_list[0], 1, conflict_list_cnt);
+
+  XFREE (conflict_table);
+  XFREE (conflict_list);
+}
+
+
+static void
 output_check (void)
 {
   muscle_insert_short_table ("check", check,
@@ -982,6 +1134,7 @@ output_actions (void)
 
   froms = XCALLOC (short *, nvectors);
   tos = XCALLOC (short *, nvectors);
+  conflict_tos = XCALLOC (unsigned int *, nvectors);
   tally = XCALLOC (short, nvectors);
   width = XCALLOC (short, nvectors);
 
@@ -999,6 +1152,7 @@ output_actions (void)
 
   output_base ();
   output_table ();
+  output_conflicts ();
 
   output_check ();
 
@@ -1084,6 +1238,7 @@ output_skeleton (void)
   fputs ("m4_init()\n", out);
 
   actions_output (out);
+  merger_output (out);
   token_definitions_output (out);
   symbol_destructors_output (out);
   symbol_printers_output (out);
@@ -1140,7 +1295,12 @@ prepare (void)
 
   /* Find the right skeleton file.  */
   if (!skeleton)
-    skeleton = "bison.simple";
+    {
+      if (glr_parser)
+       skeleton = "bison.glr";
+      else
+       skeleton = "bison.simple";
+    }
 
   /* Parse the skeleton file and output the needed parsers.  */
   muscle_insert ("skeleton", skeleton);
Index: bison-1_5.26/src/gram.c
--- bison-1_5.26/src/gram.c Sun, 16 Jun 2002 13:39:03 -0700 hilfingr 
(glrbison/b/2_gram.c 1.1.1.3.1.1.1.1.1.1 644)
+++ 2.64(w)/src/gram.c Sun, 16 Jun 2002 13:47:14 -0700 hilfingr 
(glrbison/b/2_gram.c 1.1.1.3.1.1.1.1.1.2 644)
@@ -43,6 +43,7 @@ symbol_number_t *token_translations = NU
 
 int max_user_token_number = 256;
 
+int glr_parser = 0;
 int pure_parser = 0;
 
 
@@ -249,4 +250,5 @@ grammar_free (void)
   XFREE (token_translations);
   /* Free the symbol table data structure.  */
   symbols_free ();
+  free_merger_functions ();
 }
Index: bison-1_5.26/src/getargs.c
--- bison-1_5.26/src/getargs.c Wed, 26 Jun 2002 14:01:25 -0700 hilfingr 
(glrbison/b/3_getargs.c 1.1.1.2.1.1.1.1 644)
+++ 2.64(w)/src/getargs.c Wed, 26 Jun 2002 14:14:28 -0700 hilfingr 
(glrbison/b/3_getargs.c 1.1.1.2.1.1.1.3 644)
@@ -25,6 +25,7 @@
 #include "complain.h"
 #include "getargs.h"
 #include "options.h"
+#include "gram.h"     /* For glr_parser */
 #include "files.h"
 
 int debug_flag = 0;
Index: bison-1_5.26/src/conflicts.c
--- bison-1_5.26/src/conflicts.c Sun, 16 Jun 2002 13:39:03 -0700 hilfingr 
(glrbison/b/5_conflicts. 1.1.1.2.1.1.1.1.1.1.1.1 644)
+++ 2.64(w)/src/conflicts.c Sun, 16 Jun 2002 13:47:14 -0700 hilfingr 
(glrbison/b/5_conflicts. 1.1.1.2.1.1.1.1.1.1.1.2 644)
@@ -331,12 +331,15 @@ count_sr_conflicts (state_t *state)
 }
 
 
-/*----------------------------------------------.
-| Count the number of reduce/reduce conflicts.  |
-`----------------------------------------------*/
+/*----------------------------------------------------------------.
+| Count the number of reduce/reduce conflicts.  If ONE_PER_TOKEN, |
+| count one conflict for each token that has any reduce/reduce    |
+| conflicts.  Otherwise, count one conflict for each pair of      |
+| conflicting reductions.                                         |
++`----------------------------------------------------------------*/
 
 static int
-count_rr_conflicts (state_t *state)
+count_rr_conflicts (state_t *state, int one_per_token)
 {
   int i;
   int rrc_count = 0;
@@ -353,7 +356,7 @@ count_rr_conflicts (state_t *state)
          count++;
 
       if (count >= 2)
-       rrc_count++;
+       rrc_count += one_per_token ? 1 : count-1;
     }
 
   return rrc_count;
@@ -412,13 +415,37 @@ conflicts_output (FILE *out)
       {
        fprintf (out, _("State %d contains "), i);
        fputs (conflict_report (count_sr_conflicts (states[i]),
-                               count_rr_conflicts (states[i])), out);
+                               count_rr_conflicts (states[i], TRUE)), out);
        printed_sth = TRUE;
       }
   if (printed_sth)
     fputs ("\n\n", out);
 }
 
+/*--------------------------------------------------------.
+| Total the number of S/R and R/R conflicts.  Unlike the  |
+| code in conflicts_output, however, count EACH pair of   |
+| reductions for the same state and lookahead as one      |
+| conflict.                                              |
+`--------------------------------------------------------*/
+
+int
+count_total_conflicts (void)
+{
+  int i;
+  int count;
+
+  /* Conflicts by state.  */
+  count = 0;
+  for (i = 0; i < nstates; i++)
+    if (conflicts[i])
+      {
+       count += count_sr_conflicts (states[i]);
+       count += count_rr_conflicts (states[i], FALSE);
+      }
+  return count;
+}
+ 
 
 /*------------------------------------------.
 | Reporting the total number of conflicts.  |
@@ -442,7 +469,7 @@ conflicts_print (void)
     if (conflicts[i])
       {
        src_total += count_sr_conflicts (states[i]);
-       rrc_total += count_rr_conflicts (states[i]);
+       rrc_total += count_rr_conflicts (states[i], TRUE);
       }
 
   src_ok = src_total == (expected_conflicts == -1 ? 0 : expected_conflicts);
Index: bison-1_5.26/src/reader.h
--- bison-1_5.26/src/reader.h Thu, 20 Jun 2002 12:56:37 -0700 hilfingr 
(glrbison/b/20_reader.h 1.1.1.3.1.1.1.2.1.1.1.1 644)
+++ 2.64(w)/src/reader.h Thu, 20 Jun 2002 13:01:44 -0700 hilfingr 
(glrbison/b/20_reader.h 1.1.1.3.1.1.1.2.1.1.1.2 644)
@@ -24,6 +24,14 @@
 # include "symlist.h"
 # include "parse-gram.h"
 
+typedef struct merger_list
+{
+  struct merger_list* next;
+  const char* name;
+  const char* type;
+} 
+merger_list;
+
 typedef struct gram_control_s
 {
   int errcode;
@@ -70,12 +78,21 @@ void grammar_rule_end PARAMS ((location_
 void grammar_midrule_action PARAMS ((void));
 void grammar_current_rule_prec_set PARAMS ((symbol_t *precsym,
                                            location_t l));
+void grammar_current_rule_dprec_set PARAMS ((int dprec,
+                                           location_t l));
+void grammer_current_rule_merge_set PARAMS ((const char* name,
+                                           location_t l));
+
 void grammar_current_rule_symbol_append PARAMS ((symbol_t *symbol,
                                                 location_t l));
 void grammar_current_rule_action_append PARAMS ((const char *action,
                                                 location_t l));
 extern symbol_list_t *current_rule;
 void reader PARAMS ((void));
+void free_merger_functions PARAMS ((void));
+
+extern merger_list *merge_functions;
+
 extern int typed;
 
 #endif /* !READER_H_ */
Index: bison-1_5.26/src/gram.h
--- bison-1_5.26/src/gram.h Sun, 16 Jun 2002 13:39:03 -0700 hilfingr 
(glrbison/b/25_gram.h 1.1.1.3.1.1.1.1.1.1 644)
+++ 2.64(w)/src/gram.h Sun, 16 Jun 2002 13:47:16 -0700 hilfingr 
(glrbison/b/25_gram.h 1.1.1.3.1.1.1.1.1.2 644)
@@ -68,6 +68,10 @@
 
    RULES[R].assoc -- the associativity of R.
 
+   RULES[R].dprec -- the dynamic precedence level of R (for GLR parsing).
+
+   RULES[R].merger -- index of merging function for R (for GLR parsing).
+
    RULES[R].line -- the line where R was defined.
 
    RULES[R].useful -- TRUE iff the rule is used (i.e., FALSE if thrown
@@ -141,6 +145,9 @@ typedef struct rule_s
   /* This symbol provides both the associativity, and the precedence. */
   symbol_t *prec;
 
+  short dprec;
+  short merger;
+
   /* This symbol was attached to the rule via %prec. */
   symbol_t *precsym;
 
@@ -162,6 +169,12 @@ extern symbol_t **symbols;
 extern symbol_number_t *token_translations;
 extern int max_user_token_number;
 
+
+/* GLR_PARSER is nonzero if the input file says to use the GLR
+   (Generalized LR) parser, and to output some additional
+   information used by the GLR algorithm. */
+
+extern int glr_parser;
 
 /* PURE_PARSER is nonzero if should generate a parser that is all pure
    and reentrant.  */
Index: bison-1_5.26/src/conflicts.h
--- bison-1_5.26/src/conflicts.h Sun, 26 May 2002 14:18:11 -0700 hilfingr 
(glrbison/b/29_conflicts. 1.1.1.2 644)
+++ 2.64(w)/src/conflicts.h Sun, 26 May 2002 15:13:10 -0700 hilfingr 
(glrbison/b/29_conflicts. 1.1.1.3 644)
@@ -24,6 +24,7 @@
 
 void conflicts_solve PARAMS ((void));
 void conflicts_print PARAMS ((void));
+int count_total_conflicts PARAMS ((void));
 void conflicts_output PARAMS ((FILE *out));
 void conflicts_free PARAMS ((void));
 
Index: bison-1_5.26/NEWS
--- bison-1_5.26/NEWS Tue, 18 Jun 2002 17:04:55 -0700 hilfingr 
(glrbison/c/23_NEWS 1.1.1.3.1.1.1.1.1.1.1.1 644)
+++ 2.64(w)/NEWS Tue, 18 Jun 2002 17:05:53 -0700 hilfingr (glrbison/c/23_NEWS 
1.1.1.3.1.1.1.1.1.1.1.2 644)
@@ -3,6 +3,14 @@ Bison News
 
 Changes in version 1.49b:
 
+* GLR parsing
+  The declaration
+     %glr-parser
+  causes Bison to produce a Generalized LR (GLR) parser, capable of handling
+  almost any context-free grammar, ambiguous or not.  The new declarations
+  %dprec and %merge on grammar rules allow parse-time resolution of 
+  ambiguities.
+
 * Output Directory
   When not in Yacc compatibility mode, when the output file was not
   specified, runnning `bison foo/bar.y' created `foo/bar.c'.  It
Index: bison-1_5.26/Makefile.in
--- bison-1_5.26/Makefile.in Sun, 26 May 2002 15:11:14 -0700 hilfingr 
(glrbison/g/4_Makefile.i 1.1 644)
Index: bison-1_5.26/tests/testsuite.at
--- bison-1_5.26/tests/testsuite.at Thu, 02 May 2002 15:41:15 -0700 hilfingr 
(glrbison/c/41_testsuite. 1.1.1.1 644)
+++ 2.64(w)/tests/testsuite.at Fri, 03 May 2002 19:13:57 -0700 hilfingr 
(glrbison/c/41_testsuite. 1.4 644)
@@ -61,3 +61,6 @@ m4_include([existing.at])
 
 # Some old bugs.
 m4_include([regression.at])
+
+# GLR tests: C++ types, simplified
+m4_include([cxx-type.at])
Index: bison-1_5.26/tests/Makefile.am
--- bison-1_5.26/tests/Makefile.am Thu, 02 May 2002 15:41:15 -0700 hilfingr 
(glrbison/c/45_Makefile.a 1.1.1.1 644)
+++ 2.64(w)/tests/Makefile.am Fri, 03 May 2002 19:01:14 -0700 hilfingr 
(glrbison/c/45_Makefile.a 1.4 644)
@@ -49,7 +49,8 @@ TESTSUITE_AT = \
        output.at sets.at reduce.at \
        synclines.at headers.at actions.at conflicts.at \
        calc.at \
-        torture.at existing.at regression.at
+        torture.at existing.at regression.at \
+       cxx-type.at
 
 TESTSUITE = $(srcdir)/testsuite
 
+++ 2.64(w)/data/Makefile.am Thu, 02 May 2002 20:44:05 -0700 hilfingr 
(glrbison/f/42_Makefile.a 1.1 644)
@@ -15,7 +15,7 @@
 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 ## 02111-1307  USA
 
-dist_pkgdata_DATA = bison.simple bison.c++
+dist_pkgdata_DATA = bison.simple bison.c++ bison.glr
 
 m4sugardir = $(pkgdatadir)/m4sugar
 dist_m4sugar_DATA = m4sugar/m4sugar.m4 m4sugar/version.m4
Index: bison-1_5.26/src/scan-gram.l
--- bison-1_5.26/src/scan-gram.l Thu, 20 Jun 2002 12:56:37 -0700 hilfingr 
(glrbison/g/8_scan-gram. 1.1.1.1.1.1.1.1.1.1.1.1 644)
+++ 2.64(w)/src/scan-gram.l Thu, 20 Jun 2002 12:57:25 -0700 hilfingr 
(glrbison/g/8_scan-gram. 1.1.1.1.1.1.1.1.1.1.1.2 644)
@@ -124,12 +124,15 @@ blanks   [ \t\f]+
   "%define"               return PERCENT_DEFINE;
   "%defines"              return PERCENT_DEFINES;
   "%destructor"           return PERCENT_DESTRUCTOR;
+  "%dprec"               return PERCENT_DPREC;
   "%error"[-_]"verbose"   return PERCENT_ERROR_VERBOSE;
   "%expect"               return PERCENT_EXPECT;
   "%file-prefix"          return PERCENT_FILE_PREFIX;
   "%fixed"[-_]"output"[-_]"files"   return PERCENT_YACC;
+  "%glr"[-_]"parser"     return PERCENT_GLR_PARSER;
   "%left"                 return PERCENT_LEFT;
   "%locations"            return PERCENT_LOCATIONS;
+  "%merge"               return PERCENT_MERGE;
   "%name"[-_]"prefix"     return PERCENT_NAME_PREFIX;
   "%no"[-_]"lines"        return PERCENT_NO_LINES;
   "%nonassoc"             return PERCENT_NONASSOC;
Index: bison-1_5.26/src/parse-gram.y
--- bison-1_5.26/src/parse-gram.y Thu, 20 Jun 2002 12:56:37 -0700 hilfingr 
(glrbison/g/11_parse-gram 1.1.1.2.1.1.1.1 644)
+++ 2.64(w)/src/parse-gram.y Thu, 20 Jun 2002 13:02:11 -0700 hilfingr 
(glrbison/g/11_parse-gram 1.1.1.2.1.1.1.2 644)
@@ -114,6 +114,8 @@ braced_code_t current_braced_code = acti
 %token PERCENT_EXPECT "%expect"
 %token PERCENT_START "%start"
 %token PERCENT_PREC     "%prec"
+%token PERCENT_DPREC    "%dprec"
+%token PERCENT_MERGE    "%merge"
 %token PERCENT_VERBOSE  "%verbose"
 %token PERCENT_ERROR_VERBOSE "%error-verbose"
 
@@ -123,6 +125,7 @@ braced_code_t current_braced_code = acti
 
 %token PERCENT_DEFINE "%define"
 %token PERCENT_PURE_PARSER "%pure-parser"
+%token PERCENT_GLR_PARSER "%glr-parser"
 
 %token PERCENT_DEFINES "%defines"
 
@@ -184,6 +187,7 @@ declaration:
 | "%no-lines"                              { no_lines_flag = 1; }
 | "%output" "=" string_content             { spec_outfile = $3; }
 | "%pure-parser"                           { pure_parser = 1; }
+| "%glr-parser"                           { glr_parser = 1; }
 | "%skeleton" string_content               { skeleton = $2; }
 | "%token-table"                           { token_table_flag = 1; }
 | "%verbose"                               { report_flag = 1; }
@@ -355,6 +359,10 @@ rhs:
     { grammar_current_rule_action_append ($2, @2); }
 | rhs "%prec" symbol
     { grammar_current_rule_prec_set ($3, @3); }
+| rhs "%dprec" INT
+    { grammar_current_rule_dprec_set ($3, @3); }
+| rhs "%merge" TYPE
+    { grammar_current_rule_merge_set ($3, @3); }
 ;
 
 symbol:
Index: bison-1_5.26/src/symlist.h
--- bison-1_5.26/src/symlist.h Mon, 17 Jun 2002 14:10:36 -0700 hilfingr 
(glrbison/g/18_symlist.h 1.1 644)
+++ 2.64(w)/src/symlist.h Mon, 17 Jun 2002 14:25:49 -0700 hilfingr 
(glrbison/g/18_symlist.h 1.2 644)
@@ -35,6 +35,8 @@ typedef struct symbol_list_s
   location_t action_location;
 
   symbol_t *ruleprec;
+  int dprec;
+  int merger;
 } symbol_list_t;
 
 
Index: bison-1_5.26/src/symlist.c
--- bison-1_5.26/src/symlist.c Mon, 17 Jun 2002 14:10:36 -0700 hilfingr 
(glrbison/g/19_symlist.c 1.1 644)
+++ 2.64(w)/src/symlist.c Mon, 17 Jun 2002 14:22:25 -0700 hilfingr 
(glrbison/g/19_symlist.c 1.2 644)
@@ -36,6 +36,8 @@ symbol_list_new (symbol_t *sym, location
   res->location = location;
   res->action = NULL;
   res->ruleprec = NULL;
+  res->dprec = 0;
+  res->merger = 0;
   return res;
 }
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]