[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