[COMMITTED] a68: bit of documentation for a68-parser-bottom-up.cc:reduce

Jose E. Marchesi jemarch@gnu.org
Thu Nov 6 20:45:02 GMT 2025


---
 gcc/algol68/a68-parser-bottom-up.cc | 82 +++++++++++++++++++++++++++--
 1 file changed, 79 insertions(+), 3 deletions(-)

diff --git a/gcc/algol68/a68-parser-bottom-up.cc b/gcc/algol68/a68-parser-bottom-up.cc
index bcad6167ef9..8d383e02da7 100644
--- a/gcc/algol68/a68-parser-bottom-up.cc
+++ b/gcc/algol68/a68-parser-bottom-up.cc
@@ -155,10 +155,86 @@ strange_separator (NODE_T *p)
   a68_error (q, "possibly a missing or erroneous separator nearby");
 }
 
-/* If match then reduce a sentence, the core bottom-up parser routine.  */
+/* If match then reduce a sentence, the core bottom-up parser routine.  The
+   reduction of a sequence of nodes stating at P:
+
+      P - A - B - C - D - E - F
+
+   where the attributes passed to this function are Z P A B C, the result of
+   the reduction is:
+
+      Z - D - E - F
+      |
+      P - A - B - C
+
+   Note how the node pointed by P gets changed after a reduction gets
+   performed.
+
+   P is the AST node from where start matching.
+
+   ATTRS is a sequence of node attributes.  The first of these attributes is
+   the kind of node resulting from the reduction.  The rest of attributes are
+   the matched in order starting at P, then a reduction is performed.  Two node
+   attributes exist that convey special meaning when passing to "reduce":
+
+     STOP marks the end of the variable-length sequence of attributes to match.
+
+     WILDCARD will match any non terminal, with the exception of a keyword.  It
+     is used to recover from errors.
+
+   A is a "noting" function that is invoked and passed P right before doing the
+   reduction.  If A is NO_NOTE then it is not used.
+
+   The boolean Z is set to "true" if the reduction has been performed, and is
+   left untouched otherwise.  If Z is NO_TICK then it is not used.
+
+   It is common to invoke "reduce" in a row in order to try the reduction of
+   several alternatives, which are mutually exclusive.  For example:
+
+     reduce (p, NO_NOTE, NO_TICK, PARTICULAR_PROGRAM, LABEL, ENCLOSED_CLAUSE, STOP);
+     reduce (p, NO_NOTE, NO_TICK, PARTICULAR_PROGRAM, ENCLOSED_CLAUSE, STOP);
+
+   We know that at much only one of these reductions will succeed, becuase if
+   the first reduction succeeds, then P gets changed to LABEL which cannot
+   match ENCLOSED_CLAUSE.
+
+   Sometimes, however, "reduce" is invoked in a row in a way the second
+   reduction is intended to succeed if the first one succeeds.  For example:
+
+     reduce (p, NO_NOTE, NO_TICK, PARALLEL_CLAUSE, PAR_SYMBOL, COLLATERAL_CLAUSE, STOP);
+     reduce (p, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, PARALLEL_CLAUSE, STOP);
+
+   In this case if the first reduction succeeds, then the resulting
+   PARALLEL_CLAUSE will be itself reduced to an ENCLOSED_CLAUSE.
+
+   Another typical usage of "reduce" is to put it in a loop in order to reduce
+   matches of a left-recursive rule.  This is where Z comes to play.  For
+   example, consider the rules:
+
+     label : defining identifier, colon symbol ;
+             label, defining identifier, colon symbol.
+
+   The second alternative is left-recursive, and along with the first rule
+   defines a sequence of one or more labels, each label consisting on a
+   defining identifier followed by a colon symbol.  We could match these rules
+   using the following loop:
+
+     while (siga)
+       {
+         siga = false;
+	 reduce (q, NO_NOTE, &siga, LABEL, DEFINING_IDENTIFIER, COLON_SYMBOL, STOP);
+	 reduce (q, NO_NOTE, &siga, LABEL, LABEL, DEFINING_IDENTIFIER, COLON_SYMBOL, STOP);
+       }
+
+   Note how, when presented with a sequence of labels like `l1: l2: l3: ...',
+   the first call to "reduce" will succeed, turning Q into a LABEL.  Then the
+   second call to "reduce" will also succed, reducing to another LABEL and
+   setting SIGA to "true".  In subsequent iterations of the loop the first call
+   will always fail, and the second call will keep succeeding as more sequences
+   of DEFINING_IDENTIFIER, COLON_SYMBOL get matched.  */
 
 static void
-reduce (NODE_T *p, void (*a) (NODE_T *), bool *z, ...)
+reduce (NODE_T *p, void (*a) (NODE_T *), bool *z, /* attrs */...)
 {
   va_list list;
   va_start (list, z);
@@ -173,7 +249,7 @@ reduce (NODE_T *p, void (*a) (NODE_T *), bool *z, ...)
     if (p == NO_NODE)
       keep_matching = false;
     else if (expect == WILDCARD)
-      /* WILDCARD matches any Algol68G non terminal, but no keyword.  */
+      /* WILDCARD matches any non terminal, but no keyword.  */
       keep_matching = (a68_attribute_name (ATTRIBUTE (p)) != NO_TEXT);
     else
       {
-- 
2.30.2



More information about the Algol68 mailing list