parser-bottom-up.c

     
   1  //! @file parser-bottom-up.c
   2  //! @author J. Marcel van der Veer
   3  
   4  //! @section Copyright
   5  //!
   6  //! This file is part of Algol68G - an Algol 68 compiler-interpreter.
   7  //! Copyright 2001-2026 J. Marcel van der Veer [algol68g@xs4all.nl].
   8  
   9  //! @section License
  10  //!
  11  //! This program is free software; you can redistribute it and/or modify it 
  12  //! under the terms of the GNU General Public License as published by the 
  13  //! Free Software Foundation; either version 3 of the License, or 
  14  //! (at your option) any later version.
  15  //!
  16  //! This program is distributed in the hope that it will be useful, but 
  17  //! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  18  //! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
  19  //! more details. You should have received a copy of the GNU General Public 
  20  //! License along with this program. If not, see [http://www.gnu.org/licenses/].
  21  
  22  //! @section Synopsis 
  23  //!
  24  //! Hand-coded bottom-up parser for Algol 68.
  25  
  26  // This code constitutes an effective "Algol 68 VW parser"; a pragmatic
  27  // approach was chosen since in the early days of Algol 68, many "ab initio" 
  28  // implementations failed.
  29  // 
  30  // This is a Mailloux-type parser, in the sense that it scans a "phrase" for
  31  // definitions needed for parsing, and therefore allows for tags to be used
  32  // before they are defined, which gives some freedom in top-down programming.
  33  // 
  34  //    B. J. Mailloux. On the implementation of Algol 68.
  35  //    Thesis, Universiteit van Amsterdam (Mathematisch Centrum) [1968].
  36  // 
  37  // Technically, Mailloux's approach renders the two-level grammar LALR.
  38  // 
  39  // This is the bottom-up parser that resolves the structure of the program.
  40  
  41  #include "a68g.h"
  42  #include "a68g-parser.h"
  43  #include "a68g-prelude.h"
  44  
  45  // Bottom-up parser, reduces all constructs.
  46  
  47  //! @brief Whether a series is serial or collateral.
  48  
  49  int serial_or_collateral (NODE_T * p)
  50  {
  51    int semis = 0, commas = 0, exits = 0;
  52    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
  53      if (IS (q, COMMA_SYMBOL)) {
  54        commas++;
  55      } else if (IS (q, SEMI_SYMBOL)) {
  56        semis++;
  57      } else if (IS (q, EXIT_SYMBOL)) {
  58        exits++;
  59      }
  60    }
  61    if (semis == 0 && exits == 0 && commas > 0) {
  62      return COLLATERAL_CLAUSE;
  63    } else if ((semis > 0 || exits > 0) && commas == 0) {
  64      return SERIAL_CLAUSE;
  65    } else if (semis == 0 && exits == 0 && commas == 0) {
  66      return SERIAL_CLAUSE;
  67    } else {
  68  // Heuristic guess to give intelligible error message.
  69      if (semis + exits >= commas) {
  70        return SERIAL_CLAUSE;
  71      } else {
  72        return COLLATERAL_CLAUSE;
  73      }
  74    }
  75  }
  76  
  77  //! @brief Insert a node with attribute "a" after "p".
  78  
  79  void pad_node (NODE_T * p, int a)
  80  {
  81  // This is used to fill information that Algol 68 does not require to be present.
  82  // Filling in gives one format for such construct; this helps later passes.
  83    NODE_T *z = new_node ();
  84    *z = *p;
  85    if (GINFO (p) != NO_GINFO) {
  86      GINFO (z) = new_genie_info ();
  87    }
  88    PREVIOUS (z) = p;
  89    SUB (z) = NO_NODE;
  90    ATTRIBUTE (z) = a;
  91    MOID (z) = NO_MOID;
  92    if (NEXT (z) != NO_NODE) {
  93      PREVIOUS (NEXT (z)) = z;
  94    }
  95    NEXT (p) = z;
  96  }
  97  
  98  //! @brief Diagnose extensions.
  99  
 100  void a68g_extension (NODE_T * p)
 101  {
 102    if (OPTION_PORTCHECK (&A68G_JOB)) {
 103      diagnostic (A68G_WARNING, p, WARNING_EXTENSION);
 104    } else {
 105      diagnostic (A68G_NOTICE, p, WARNING_EXTENSION);
 106    }
 107  }
 108  
 109  //! @brief Diagnose for clauses not yielding a value.
 110  
 111  void empty_clause (NODE_T * p)
 112  {
 113    diagnostic (A68G_SYNTAX_ERROR, p, ERROR_CLAUSE_WITHOUT_VALUE);
 114  }
 115  
 116  #if !defined (BUILD_PARALLEL_CLAUSE)
 117  
 118  //! @brief Diagnose for parallel clause.
 119  
 120  void par_clause (NODE_T * p)
 121  {
 122    diagnostic (A68G_SYNTAX_ERROR, p, ERROR_NO_PARALLEL_CLAUSE);
 123  }
 124  
 125  #endif
 126  
 127  //! @brief Diagnose for missing symbol.
 128  
 129  void strange_tokens (NODE_T * p)
 130  {
 131    NODE_T *q = ((p != NO_NODE && NEXT (p) != NO_NODE) ? NEXT (p) : p);
 132    diagnostic (A68G_SYNTAX_ERROR, q, ERROR_SYNTAX_STRANGE_TOKENS);
 133  }
 134  
 135  //! @brief Diagnose for strange separator.
 136  
 137  void strange_separator (NODE_T * p)
 138  {
 139    NODE_T *q = ((p != NO_NODE && NEXT (p) != NO_NODE) ? NEXT (p) : p);
 140    diagnostic (A68G_SYNTAX_ERROR, q, ERROR_SYNTAX_STRANGE_TOKENS);
 141  }
 142  
 143  //! @brief If match then reduce a sentence, the core BU parser routine.
 144  
 145  void reduce (NODE_T * p, void (*a) (NODE_T *), BOOL_T * z, ...)
 146  {
 147    va_list list;
 148    va_start (list, z);
 149    int result = va_arg (list, int), expect;
 150    NODE_T *head = p, *tail = NO_NODE;
 151    while ((expect = va_arg (list, int)) != STOP)
 152    {
 153      BOOL_T keep_matching;
 154      if (p == NO_NODE) {
 155        keep_matching = A68G_FALSE;
 156      } else if (expect == WILDCARD) {
 157  // WILDCARD matches any Algol68G non terminal, but no keyword.
 158        keep_matching = (BOOL_T) (non_terminal_string (A68G (edit_line), ATTRIBUTE (p)) != NO_TEXT);
 159      } else {
 160        if (expect == SKIP) {
 161  // Stray "~" matches expected SKIP.
 162          if (IS (p, OPERATOR) && IS_LITERALLY (p, "~")) {
 163            ATTRIBUTE (p) = SKIP;
 164          }
 165        }
 166        if (expect >= 0) {
 167          keep_matching = (BOOL_T) (expect == ATTRIBUTE (p));
 168        } else {
 169          keep_matching = (BOOL_T) (expect != ATTRIBUTE (p));
 170        }
 171      }
 172      if (keep_matching) {
 173        tail = p;
 174        FORWARD (p);
 175      } else {
 176        va_end (list);
 177        return;
 178      }
 179    }
 180  // Print parser reductions.
 181    if (head != NO_NODE && OPTION_REDUCTIONS (&A68G_JOB) && LINE_NUMBER (head) > 0) {
 182      A68G_PARSER (reductions)++;
 183      WIS (head);
 184      ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "\nReduction %d: %s<-", A68G_PARSER (reductions), non_terminal_string (A68G (edit_line), result)) >= 0);
 185      WRITE (A68G_STDOUT, A68G (output_line));
 186      int count = 0;
 187      for (NODE_T *q = head; q != NO_NODE && tail != NO_NODE && q != NEXT (tail); FORWARD (q), count++) {
 188        int gatt = ATTRIBUTE (q);
 189        char *str = non_terminal_string (A68G (input_line), gatt);
 190        if (count > 0) {
 191          WRITE (A68G_STDOUT, ", ");
 192        }
 193        if (str != NO_TEXT) {
 194          WRITE (A68G_STDOUT, str);
 195          if (gatt == IDENTIFIER || gatt == OPERATOR || gatt == DENOTATION || gatt == INDICANT) {
 196            ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, " \"%s\"", NSYMBOL (q)) >= 0);
 197            WRITE (A68G_STDOUT, A68G (output_line));
 198          }
 199        } else {
 200          WRITE (A68G_STDOUT, NSYMBOL (q));
 201        }
 202      }
 203    }
 204  // Make reduction.
 205    if (a != NO_NOTE) {
 206      a (head);
 207    }
 208    make_sub (head, tail, result);
 209    va_end (list);
 210    if (z != NO_TICK) {
 211      *z = A68G_TRUE;
 212    }
 213  }
 214  
 215  //! @brief Graciously ignore extra semicolons.
 216  
 217  void ignore_superfluous_semicolons (NODE_T * p)
 218  {
 219  // This routine relaxes the parser a bit with respect to superfluous semicolons,
 220  // for instance "FI; OD". These provoke only a warning.
 221    for (; p != NO_NODE; FORWARD (p)) {
 222      ignore_superfluous_semicolons (SUB (p));
 223      if (NEXT (p) != NO_NODE && IS (NEXT (p), SEMI_SYMBOL) && NEXT_NEXT (p) == NO_NODE) {
 224        diagnostic (A68G_WARNING, NEXT (p), WARNING_SKIPPED_SUPERFLUOUS, ATTRIBUTE (NEXT (p)));
 225        NEXT (p) = NO_NODE;
 226      } else if (IS (p, SEMI_SYMBOL) && is_semicolon_less (NEXT (p))) {
 227        diagnostic (A68G_WARNING, p, WARNING_SKIPPED_SUPERFLUOUS, ATTRIBUTE (p));
 228        if (PREVIOUS (p) != NO_NODE) {
 229          NEXT (PREVIOUS (p)) = NEXT (p);
 230        }
 231        PREVIOUS (NEXT (p)) = PREVIOUS (p);
 232      }
 233    }
 234  }
 235  
 236  //! @brief Driver for the bottom-up parser.
 237  
 238  void bottom_up_parser (NODE_T * p)
 239  {
 240    if (p != NO_NODE) {
 241      if (!setjmp (A68G_PARSER (bottom_up_crash_exit))) {
 242        NODE_T *q;
 243        int error_count_0 = ERROR_COUNT (&A68G_JOB);
 244        ignore_superfluous_semicolons (p);
 245  // A program is "label sequence; particular program".
 246        extract_labels (p, SERIAL_CLAUSE);
 247  // Parse the program itself.
 248        for (q = p; q != NO_NODE; FORWARD (q)) {
 249          BOOL_T siga = A68G_TRUE;
 250          if (SUB (q) != NO_NODE) {
 251            reduce_branch (q, SOME_CLAUSE);
 252          }
 253          while (siga) {
 254            siga = A68G_FALSE;
 255            reduce (q, NO_NOTE, &siga, LABEL, DEFINING_IDENTIFIER, COLON_SYMBOL, STOP);
 256            reduce (q, NO_NOTE, &siga, LABEL, LABEL, DEFINING_IDENTIFIER, COLON_SYMBOL, STOP);
 257          }
 258        }
 259  // Determine the encompassing enclosed clause.
 260        for (q = p; q != NO_NODE; FORWARD (q)) {
 261          #if defined (BUILD_PARALLEL_CLAUSE)
 262            reduce (q, NO_NOTE, NO_TICK, PARALLEL_CLAUSE, PAR_SYMBOL, COLLATERAL_CLAUSE, STOP);
 263          #else
 264            reduce (q, par_clause, NO_TICK, PARALLEL_CLAUSE, PAR_SYMBOL, COLLATERAL_CLAUSE, STOP);
 265          #endif
 266          reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, PARALLEL_CLAUSE, STOP);
 267          reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CLOSED_CLAUSE, STOP);
 268          reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, COLLATERAL_CLAUSE, STOP);
 269          reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CONDITIONAL_CLAUSE, STOP);
 270          reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CASE_CLAUSE, STOP);
 271          reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CONFORMITY_CLAUSE, STOP);
 272          reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, LOOP_CLAUSE, STOP);
 273        }
 274  // Try reducing the particular program.
 275        q = p;
 276        reduce (q, NO_NOTE, NO_TICK, PARTICULAR_PROGRAM, LABEL, ENCLOSED_CLAUSE, STOP);
 277        reduce (q, NO_NOTE, NO_TICK, PARTICULAR_PROGRAM, ENCLOSED_CLAUSE, STOP);
 278        if (SUB (p) == NO_NODE || NEXT (p) != NO_NODE) {
 279          recover_from_error (p, PARTICULAR_PROGRAM, (BOOL_T) ((ERROR_COUNT (&A68G_JOB) - error_count_0) > MAX_ERRORS));
 280        }
 281      }
 282    }
 283  }
 284  
 285  //! @brief Reduce code clause.
 286  
 287  void reduce_code_clause (NODE_T * p)
 288  {
 289    BOOL_T siga = A68G_TRUE;
 290    while (siga) {
 291      siga = A68G_FALSE;
 292      for (NODE_T *u = p; u != NO_NODE; FORWARD (u)) {
 293        reduce (u, NO_NOTE, &siga, CODE_LIST, CODE_SYMBOL, ROW_CHAR_DENOTATION, STOP);
 294        reduce (u, NO_NOTE, &siga, CODE_LIST, CODE_LIST, ROW_CHAR_DENOTATION, STOP);
 295        reduce (u, NO_NOTE, &siga, CODE_LIST, CODE_LIST, COMMA_SYMBOL, ROW_CHAR_DENOTATION, STOP);
 296        reduce (u, NO_NOTE, &siga, CODE_CLAUSE, CODE_LIST, EDOC_SYMBOL, STOP);
 297      }
 298    }
 299  }
 300  
 301  //! @brief Reduce the sub-phrase that starts one level down.
 302  
 303  void reduce_branch (NODE_T * q, int expect)
 304  {
 305  // If unsuccessful then the routine will at least copy the resulting attribute
 306  // as the parser can repair some faults. This gives less spurious diagnostics.
 307    if (q != NO_NODE && SUB (q) != NO_NODE) {
 308      NODE_T *p = SUB (q), *u = NO_NODE;
 309      int error_count_0 = ERROR_COUNT (&A68G_JOB), error_count_02;
 310      BOOL_T declarer_pack = A68G_FALSE, no_error;
 311      switch (expect) {
 312      case STRUCTURE_PACK:
 313      case PARAMETER_PACK:
 314      case FORMAL_DECLARERS:
 315      case UNION_PACK:
 316      case SPECIFIER: {
 317          declarer_pack = A68G_TRUE;
 318          break;
 319        }
 320      default: {
 321          declarer_pack = A68G_FALSE;
 322          break;
 323        }
 324      }
 325  // Sample all info needed to decide whether a bold tag is operator or indicant.
 326  // Find the meaning of bold tags and quit in case of extra errors.
 327      extract_indicants (p);
 328      if (!declarer_pack) {
 329        extract_priorities (p);
 330        extract_operators (p);
 331      }
 332      error_count_02 = ERROR_COUNT (&A68G_JOB);
 333      elaborate_bold_tags (p);
 334      if ((ERROR_COUNT (&A68G_JOB) - error_count_02) > 0) {
 335        longjmp (A68G_PARSER (bottom_up_crash_exit), 1);
 336      }
 337  // Now we can reduce declarers, knowing which bold tags are indicants.
 338      reduce_declarers (p, expect);
 339  // Parse the phrase, as appropriate.
 340      if (expect == CODE_CLAUSE) {
 341        reduce_code_clause (p);
 342      } else if (declarer_pack == A68G_FALSE) {
 343        error_count_02 = ERROR_COUNT (&A68G_JOB);
 344        extract_declarations (p);
 345        if ((ERROR_COUNT (&A68G_JOB) - error_count_02) > 0) {
 346          longjmp (A68G_PARSER (bottom_up_crash_exit), 1);
 347        }
 348        extract_labels (p, expect);
 349        for (u = p; u != NO_NODE; FORWARD (u)) {
 350          if (SUB (u) != NO_NODE) {
 351            if (IS (u, FORMAT_DELIMITER_SYMBOL)) {
 352              reduce_branch (u, FORMAT_TEXT);
 353            } else if (IS (u, FORMAT_OPEN_SYMBOL)) {
 354              reduce_branch (u, FORMAT_TEXT);
 355            } else if (IS (u, OPEN_SYMBOL)) {
 356              if (NEXT (u) != NO_NODE && IS (NEXT (u), THEN_BAR_SYMBOL)) {
 357                reduce_branch (u, ENQUIRY_CLAUSE);
 358              } else if (PREVIOUS (u) != NO_NODE && IS (PREVIOUS (u), PAR_SYMBOL)) {
 359                reduce_branch (u, COLLATERAL_CLAUSE);
 360              }
 361            } else if (is_one_of (u, IF_SYMBOL, ELIF_SYMBOL, CASE_SYMBOL, OUSE_SYMBOL, WHILE_SYMBOL, UNTIL_SYMBOL, ELSE_BAR_SYMBOL, ACCO_SYMBOL, STOP)) {
 362              reduce_branch (u, ENQUIRY_CLAUSE);
 363            } else if (IS (u, BEGIN_SYMBOL)) {
 364              reduce_branch (u, SOME_CLAUSE);
 365            } else if (is_one_of (u, THEN_SYMBOL, ELSE_SYMBOL, OUT_SYMBOL, DO_SYMBOL, ALT_DO_SYMBOL, STOP)) {
 366              reduce_branch (u, SERIAL_CLAUSE);
 367            } else if (IS (u, IN_SYMBOL)) {
 368              reduce_branch (u, COLLATERAL_CLAUSE);
 369            } else if (IS (u, THEN_BAR_SYMBOL)) {
 370              reduce_branch (u, SOME_CLAUSE);
 371            } else if (IS (u, LOOP_CLAUSE)) {
 372              reduce_branch (u, ENCLOSED_CLAUSE);
 373            } else if (is_one_of (u, FOR_SYMBOL, FROM_SYMBOL, BY_SYMBOL, TO_SYMBOL, DOWNTO_SYMBOL, STOP)) {
 374              reduce_branch (u, UNIT);
 375            }
 376          }
 377        }
 378        reduce_primary_parts (p, expect);
 379        if (expect != ENCLOSED_CLAUSE) {
 380          reduce_primaries (p, expect);
 381          if (expect == FORMAT_TEXT) {
 382            reduce_format_texts (p);
 383          } else {
 384            reduce_secondaries (p);
 385            reduce_formulae (p);
 386            reduce_tertiaries (p);
 387          }
 388        }
 389        for (u = p; u != NO_NODE; FORWARD (u)) {
 390          if (SUB (u) != NO_NODE) {
 391            if (IS (u, CODE_SYMBOL)) {
 392              reduce_branch (u, CODE_CLAUSE);
 393            }
 394          }
 395        }
 396        reduce_right_to_left_constructs (p);
 397  // Reduce units and declarations.
 398        reduce_basic_declarations (p);
 399        reduce_units (p);
 400        reduce_erroneous_units (p);
 401        if (expect != UNIT) {
 402          if (expect == GENERIC_ARGUMENT) {
 403            reduce_generic_arguments (p);
 404          } else if (expect == BOUNDS) {
 405            reduce_bounds (p);
 406          } else {
 407            reduce_declaration_lists (p);
 408            if (expect != DECLARATION_LIST) {
 409              for (u = p; u != NO_NODE; FORWARD (u)) {
 410                reduce (u, NO_NOTE, NO_TICK, LABELED_UNIT, LABEL, UNIT, STOP);
 411                reduce (u, NO_NOTE, NO_TICK, SPECIFIED_UNIT, SPECIFIER, COLON_SYMBOL, UNIT, STOP);
 412              }
 413              if (expect == SOME_CLAUSE) {
 414                expect = serial_or_collateral (p);
 415              }
 416              if (expect == SERIAL_CLAUSE) {
 417                reduce_serial_clauses (p);
 418              } else if (expect == ENQUIRY_CLAUSE) {
 419                reduce_enquiry_clauses (p);
 420              } else if (expect == COLLATERAL_CLAUSE) {
 421                reduce_collateral_clauses (p);
 422              } else if (expect == ARGUMENT) {
 423                reduce_arguments (p);
 424              }
 425            }
 426          }
 427        }
 428        reduce_enclosed_clauses (p, expect);
 429      }
 430  // Do something if parsing failed.
 431      if (SUB (p) == NO_NODE || NEXT (p) != NO_NODE) {
 432        recover_from_error (p, expect, (BOOL_T) ((ERROR_COUNT (&A68G_JOB) - error_count_0) > MAX_ERRORS));
 433        no_error = A68G_FALSE;
 434      } else {
 435        no_error = A68G_TRUE;
 436      }
 437      ATTRIBUTE (q) = ATTRIBUTE (p);
 438      if (no_error) {
 439        SUB (q) = SUB (p);
 440      }
 441    }
 442  }
 443  
 444  //! @brief Driver for reducing declarers.
 445  
 446  void reduce_declarers (NODE_T * p, int expect)
 447  {
 448    NODE_T *q; BOOL_T siga; // Must be in this scope.
 449  // Reduce lengtheties.
 450    for (q = p; q != NO_NODE; FORWARD (q)) {
 451      siga = A68G_TRUE;
 452      reduce (q, NO_NOTE, NO_TICK, LONGETY, LONG_SYMBOL, STOP);
 453      reduce (q, NO_NOTE, NO_TICK, SHORTETY, SHORT_SYMBOL, STOP);
 454      while (siga) {
 455        siga = A68G_FALSE;
 456        reduce (q, NO_NOTE, &siga, LONGETY, LONGETY, LONG_SYMBOL, STOP);
 457        reduce (q, NO_NOTE, &siga, SHORTETY, SHORTETY, SHORT_SYMBOL, STOP);
 458      }
 459    }
 460  // Reduce indicants.
 461    for (q = p; q != NO_NODE; FORWARD (q)) {
 462      reduce (q, NO_NOTE, NO_TICK, INDICANT, INT_SYMBOL, STOP);
 463      reduce (q, NO_NOTE, NO_TICK, INDICANT, REAL_SYMBOL, STOP);
 464      reduce (q, NO_NOTE, NO_TICK, INDICANT, BITS_SYMBOL, STOP);
 465      reduce (q, NO_NOTE, NO_TICK, INDICANT, BYTES_SYMBOL, STOP);
 466      reduce (q, NO_NOTE, NO_TICK, INDICANT, COMPLEX_SYMBOL, STOP);
 467      reduce (q, NO_NOTE, NO_TICK, INDICANT, COMPL_SYMBOL, STOP);
 468      reduce (q, NO_NOTE, NO_TICK, INDICANT, BOOL_SYMBOL, STOP);
 469      reduce (q, NO_NOTE, NO_TICK, INDICANT, CHAR_SYMBOL, STOP);
 470      reduce (q, NO_NOTE, NO_TICK, INDICANT, FORMAT_SYMBOL, STOP);
 471      reduce (q, NO_NOTE, NO_TICK, INDICANT, STRING_SYMBOL, STOP);
 472      reduce (q, NO_NOTE, NO_TICK, INDICANT, FILE_SYMBOL, STOP);
 473      reduce (q, NO_NOTE, NO_TICK, INDICANT, CHANNEL_SYMBOL, STOP);
 474      reduce (q, NO_NOTE, NO_TICK, INDICANT, SEMA_SYMBOL, STOP);
 475      reduce (q, NO_NOTE, NO_TICK, INDICANT, PIPE_SYMBOL, STOP);
 476      reduce (q, NO_NOTE, NO_TICK, INDICANT, SOUND_SYMBOL, STOP);
 477    }
 478  // Reduce standard stuff.
 479    for (q = p; q != NO_NODE; FORWARD (q)) {
 480      if (whether (q, LONGETY, INDICANT, STOP)) {
 481        if (SUB_NEXT (q) == NO_NODE) {
 482          diagnostic (A68G_SYNTAX_ERROR, NEXT (q), ERROR_EXPECTED, INFO_APPROPRIATE_DECLARER);
 483          reduce (q, NO_NOTE, NO_TICK, DECLARER, LONGETY, INDICANT, STOP);
 484        } else {
 485          int a = ATTRIBUTE (SUB_NEXT (q));
 486          if (a == INT_SYMBOL || a == REAL_SYMBOL || a == BITS_SYMBOL || a == BYTES_SYMBOL || a == COMPLEX_SYMBOL || a == COMPL_SYMBOL) {
 487            reduce (q, NO_NOTE, NO_TICK, DECLARER, LONGETY, INDICANT, STOP);
 488          } else {
 489            diagnostic (A68G_SYNTAX_ERROR, NEXT (q), ERROR_EXPECTED, INFO_APPROPRIATE_DECLARER);
 490            reduce (q, NO_NOTE, NO_TICK, DECLARER, LONGETY, INDICANT, STOP);
 491          }
 492        }
 493      } else if (whether (q, SHORTETY, INDICANT, STOP)) {
 494        if (SUB_NEXT (q) == NO_NODE) {
 495          diagnostic (A68G_SYNTAX_ERROR, NEXT (q), ERROR_EXPECTED, INFO_APPROPRIATE_DECLARER);
 496          reduce (q, NO_NOTE, NO_TICK, DECLARER, SHORTETY, INDICANT, STOP);
 497        } else {
 498          int a = ATTRIBUTE (SUB_NEXT (q));
 499          if (a == INT_SYMBOL || a == REAL_SYMBOL || a == BITS_SYMBOL || a == BYTES_SYMBOL || a == COMPLEX_SYMBOL || a == COMPL_SYMBOL) {
 500            reduce (q, NO_NOTE, NO_TICK, DECLARER, SHORTETY, INDICANT, STOP);
 501          } else {
 502            diagnostic (A68G_SYNTAX_ERROR, NEXT (q), ERROR_EXPECTED, INFO_APPROPRIATE_DECLARER);
 503            reduce (q, NO_NOTE, NO_TICK, DECLARER, LONGETY, INDICANT, STOP);
 504          }
 505        }
 506      }
 507    }
 508    for (q = p; q != NO_NODE; FORWARD (q)) {
 509      reduce (q, NO_NOTE, NO_TICK, DECLARER, INDICANT, STOP);
 510    }
 511  // Reduce declarer lists.
 512    for (q = p; q != NO_NODE; FORWARD (q)) {
 513      if (NEXT (q) != NO_NODE && SUB_NEXT (q) != NO_NODE) {
 514        if (IS (q, STRUCT_SYMBOL)) {
 515          reduce_branch (NEXT (q), STRUCTURE_PACK);
 516          reduce (q, NO_NOTE, NO_TICK, DECLARER, STRUCT_SYMBOL, STRUCTURE_PACK, STOP);
 517        } else if (IS (q, UNION_SYMBOL)) {
 518          reduce_branch (NEXT (q), UNION_PACK);
 519          reduce (q, NO_NOTE, NO_TICK, DECLARER, UNION_SYMBOL, UNION_PACK, STOP);
 520        } else if (IS (q, PROC_SYMBOL)) {
 521          if (whether (q, PROC_SYMBOL, OPEN_SYMBOL, STOP)) {
 522            if (!is_formal_bounds (SUB_NEXT (q))) {
 523              reduce_branch (NEXT (q), FORMAL_DECLARERS);
 524            }
 525          }
 526        } else if (IS (q, OP_SYMBOL)) {
 527          if (whether (q, OP_SYMBOL, OPEN_SYMBOL, STOP)) {
 528            if (!is_formal_bounds (SUB_NEXT (q))) {
 529              reduce_branch (NEXT (q), FORMAL_DECLARERS);
 530            }
 531          }
 532        }
 533      }
 534    }
 535  // Reduce row, proc or op declarers.
 536    siga = A68G_TRUE;
 537    while (siga) {
 538      siga = A68G_FALSE;
 539      for (q = p; q != NO_NODE; FORWARD (q)) {
 540  // FLEX DECL.
 541        if (whether (q, FLEX_SYMBOL, DECLARER, STOP)) {
 542          reduce (q, NO_NOTE, &siga, DECLARER, FLEX_SYMBOL, DECLARER, STOP);
 543        }
 544  // FLEX [] DECL.
 545        if (whether (q, FLEX_SYMBOL, SUB_SYMBOL, DECLARER, STOP) && SUB_NEXT (q) != NO_NODE) {
 546          reduce_branch (NEXT (q), BOUNDS);
 547          reduce (q, NO_NOTE, &siga, DECLARER, FLEX_SYMBOL, BOUNDS, DECLARER, STOP);
 548          reduce (q, NO_NOTE, &siga, DECLARER, FLEX_SYMBOL, FORMAL_BOUNDS, DECLARER, STOP);
 549        }
 550  // FLEX () DECL.
 551        if (whether (q, FLEX_SYMBOL, OPEN_SYMBOL, DECLARER, STOP) && SUB_NEXT (q) != NO_NODE) {
 552          if (!whether (q, FLEX_SYMBOL, OPEN_SYMBOL, DECLARER, COLON_SYMBOL, STOP)) {
 553            reduce_branch (NEXT (q), BOUNDS);
 554            reduce (q, NO_NOTE, &siga, DECLARER, FLEX_SYMBOL, BOUNDS, DECLARER, STOP);
 555            reduce (q, NO_NOTE, &siga, DECLARER, FLEX_SYMBOL, FORMAL_BOUNDS, DECLARER, STOP);
 556          }
 557        }
 558  // [] DECL.
 559        if (whether (q, SUB_SYMBOL, DECLARER, STOP) && SUB (q) != NO_NODE) {
 560          reduce_branch (q, BOUNDS);
 561          reduce (q, NO_NOTE, &siga, DECLARER, BOUNDS, DECLARER, STOP);
 562          reduce (q, NO_NOTE, &siga, DECLARER, FORMAL_BOUNDS, DECLARER, STOP);
 563        }
 564  // () DECL.
 565        if (whether (q, OPEN_SYMBOL, DECLARER, STOP) && SUB (q) != NO_NODE) {
 566          if (whether (q, OPEN_SYMBOL, DECLARER, COLON_SYMBOL, STOP)) {
 567  // Catch e.g. (INT i) () INT:.
 568            if (is_formal_bounds (SUB (q))) {
 569              reduce_branch (q, BOUNDS);
 570              reduce (q, NO_NOTE, &siga, DECLARER, BOUNDS, DECLARER, STOP);
 571              reduce (q, NO_NOTE, &siga, DECLARER, FORMAL_BOUNDS, DECLARER, STOP);
 572            }
 573          } else {
 574            reduce_branch (q, BOUNDS);
 575            reduce (q, NO_NOTE, &siga, DECLARER, BOUNDS, DECLARER, STOP);
 576            reduce (q, NO_NOTE, &siga, DECLARER, FORMAL_BOUNDS, DECLARER, STOP);
 577          }
 578        }
 579      }
 580  // PROC DECL, PROC () DECL, OP () DECL.
 581      for (q = p; q != NO_NODE; FORWARD (q)) {
 582        int a = ATTRIBUTE (q);
 583        if (a == REF_SYMBOL) {
 584          reduce (q, NO_NOTE, &siga, DECLARER, REF_SYMBOL, DECLARER, STOP);
 585        } else if (a == PROC_SYMBOL) {
 586          reduce (q, NO_NOTE, &siga, DECLARER, PROC_SYMBOL, DECLARER, STOP);
 587          reduce (q, NO_NOTE, &siga, DECLARER, PROC_SYMBOL, FORMAL_DECLARERS, DECLARER, STOP);
 588          reduce (q, NO_NOTE, &siga, DECLARER, PROC_SYMBOL, VOID_SYMBOL, STOP);
 589          reduce (q, NO_NOTE, &siga, DECLARER, PROC_SYMBOL, FORMAL_DECLARERS, VOID_SYMBOL, STOP);
 590        } else if (a == OP_SYMBOL) {
 591          reduce (q, NO_NOTE, &siga, OPERATOR_PLAN, OP_SYMBOL, FORMAL_DECLARERS, DECLARER, STOP);
 592          reduce (q, NO_NOTE, &siga, OPERATOR_PLAN, OP_SYMBOL, FORMAL_DECLARERS, VOID_SYMBOL, STOP);
 593        }
 594      }
 595    }
 596  // Reduce packs etcetera.
 597    if (expect == STRUCTURE_PACK) {
 598      for (q = p; q != NO_NODE; FORWARD (q)) {
 599        siga = A68G_TRUE;
 600        while (siga) {
 601          siga = A68G_FALSE;
 602          reduce (q, NO_NOTE, &siga, STRUCTURED_FIELD, DECLARER, IDENTIFIER, STOP);
 603          reduce (q, NO_NOTE, &siga, STRUCTURED_FIELD, STRUCTURED_FIELD, COMMA_SYMBOL, IDENTIFIER, STOP);
 604        }
 605      }
 606      for (q = p; q != NO_NODE; FORWARD (q)) {
 607        siga = A68G_TRUE;
 608        while (siga) {
 609          siga = A68G_FALSE;
 610          reduce (q, NO_NOTE, &siga, STRUCTURED_FIELD_LIST, STRUCTURED_FIELD, STOP);
 611          reduce (q, NO_NOTE, &siga, STRUCTURED_FIELD_LIST, STRUCTURED_FIELD_LIST, COMMA_SYMBOL, STRUCTURED_FIELD, STOP);
 612          reduce (q, strange_separator, &siga, STRUCTURED_FIELD_LIST, STRUCTURED_FIELD_LIST, STRUCTURED_FIELD, STOP);
 613          reduce (q, strange_separator, &siga, STRUCTURED_FIELD_LIST, STRUCTURED_FIELD_LIST, SEMI_SYMBOL, STRUCTURED_FIELD, STOP);
 614        }
 615      }
 616      q = p;
 617      reduce (q, NO_NOTE, NO_TICK, STRUCTURE_PACK, OPEN_SYMBOL, STRUCTURED_FIELD_LIST, CLOSE_SYMBOL, STOP);
 618    } else if (expect == PARAMETER_PACK) {
 619      for (q = p; q != NO_NODE; FORWARD (q)) {
 620        siga = A68G_TRUE;
 621        while (siga) {
 622          siga = A68G_FALSE;
 623          reduce (q, NO_NOTE, &siga, PARAMETER, DECLARER, IDENTIFIER, STOP);
 624          reduce (q, NO_NOTE, &siga, PARAMETER, PARAMETER, COMMA_SYMBOL, IDENTIFIER, STOP);
 625        }
 626      }
 627      for (q = p; q != NO_NODE; FORWARD (q)) {
 628        siga = A68G_TRUE;
 629        while (siga) {
 630          siga = A68G_FALSE;
 631          reduce (q, NO_NOTE, &siga, PARAMETER_LIST, PARAMETER, STOP);
 632          reduce (q, NO_NOTE, &siga, PARAMETER_LIST, PARAMETER_LIST, COMMA_SYMBOL, PARAMETER, STOP);
 633        }
 634      }
 635      q = p;
 636      reduce (q, NO_NOTE, NO_TICK, PARAMETER_PACK, OPEN_SYMBOL, PARAMETER_LIST, CLOSE_SYMBOL, STOP);
 637    } else if (expect == FORMAL_DECLARERS) {
 638      for (q = p; q != NO_NODE; FORWARD (q)) {
 639        siga = A68G_TRUE;
 640        while (siga) {
 641          siga = A68G_FALSE;
 642          reduce (q, NO_NOTE, &siga, FORMAL_DECLARERS_LIST, DECLARER, STOP);
 643          reduce (q, NO_NOTE, &siga, FORMAL_DECLARERS_LIST, FORMAL_DECLARERS_LIST, COMMA_SYMBOL, DECLARER, STOP);
 644          reduce (q, strange_separator, &siga, FORMAL_DECLARERS_LIST, FORMAL_DECLARERS_LIST, SEMI_SYMBOL, DECLARER, STOP);
 645          reduce (q, strange_separator, &siga, FORMAL_DECLARERS_LIST, FORMAL_DECLARERS_LIST, DECLARER, STOP);
 646        }
 647      }
 648      q = p;
 649      reduce (q, NO_NOTE, NO_TICK, FORMAL_DECLARERS, OPEN_SYMBOL, FORMAL_DECLARERS_LIST, CLOSE_SYMBOL, STOP);
 650    } else if (expect == UNION_PACK) {
 651      for (q = p; q != NO_NODE; FORWARD (q)) {
 652        siga = A68G_TRUE;
 653        while (siga) {
 654          siga = A68G_FALSE;
 655          reduce (q, NO_NOTE, &siga, UNION_DECLARER_LIST, DECLARER, STOP);
 656          reduce (q, NO_NOTE, &siga, UNION_DECLARER_LIST, VOID_SYMBOL, STOP);
 657          reduce (q, NO_NOTE, &siga, UNION_DECLARER_LIST, UNION_DECLARER_LIST, COMMA_SYMBOL, DECLARER, STOP);
 658          reduce (q, NO_NOTE, &siga, UNION_DECLARER_LIST, UNION_DECLARER_LIST, COMMA_SYMBOL, VOID_SYMBOL, STOP);
 659          reduce (q, strange_separator, &siga, UNION_DECLARER_LIST, UNION_DECLARER_LIST, SEMI_SYMBOL, DECLARER, STOP);
 660          reduce (q, strange_separator, &siga, UNION_DECLARER_LIST, UNION_DECLARER_LIST, SEMI_SYMBOL, VOID_SYMBOL, STOP);
 661          reduce (q, strange_separator, &siga, UNION_DECLARER_LIST, UNION_DECLARER_LIST, DECLARER, STOP);
 662          reduce (q, strange_separator, &siga, UNION_DECLARER_LIST, UNION_DECLARER_LIST, VOID_SYMBOL, STOP);
 663        }
 664      }
 665      q = p;
 666      reduce (q, NO_NOTE, NO_TICK, UNION_PACK, OPEN_SYMBOL, UNION_DECLARER_LIST, CLOSE_SYMBOL, STOP);
 667    } else if (expect == SPECIFIER) {
 668      reduce (p, NO_NOTE, NO_TICK, SPECIFIER, OPEN_SYMBOL, DECLARER, IDENTIFIER, CLOSE_SYMBOL, STOP);
 669      reduce (p, NO_NOTE, NO_TICK, SPECIFIER, OPEN_SYMBOL, DECLARER, CLOSE_SYMBOL, STOP);
 670      reduce (p, NO_NOTE, NO_TICK, SPECIFIER, OPEN_SYMBOL, VOID_SYMBOL, CLOSE_SYMBOL, STOP);
 671    } else {
 672      for (q = p; q != NO_NODE; FORWARD (q)) {
 673        if (whether (q, OPEN_SYMBOL, COLON_SYMBOL, STOP) && !(expect == GENERIC_ARGUMENT || expect == BOUNDS)) {
 674          if (is_one_of (p, IN_SYMBOL, THEN_BAR_SYMBOL, STOP)) {
 675            reduce_branch (q, SPECIFIER);
 676          }
 677        }
 678        if (whether (q, OPEN_SYMBOL, DECLARER, COLON_SYMBOL, STOP)) {
 679          reduce_branch (q, PARAMETER_PACK);
 680        }
 681        if (whether (q, OPEN_SYMBOL, VOID_SYMBOL, COLON_SYMBOL, STOP)) {
 682          reduce_branch (q, PARAMETER_PACK);
 683        }
 684      }
 685    }
 686  }
 687  
 688  //! @brief Handle cases that need reducing from right-to-left.
 689  
 690  void reduce_right_to_left_constructs (NODE_T * p)
 691  {
 692  // Here are cases that need reducing from right-to-left whereas many things
 693  // can be reduced left-to-right. Assignations are a notable example; one could
 694  // discuss whether it would not be more natural to write 1 =: k in stead of
 695  // k := 1. The latter is said to be more natural, or it could be just computing
 696  // history. Meanwhile we use this routine.
 697    if (p != NO_NODE) {
 698      reduce_right_to_left_constructs (NEXT (p));
 699  // Assignations.
 700      if (IS (p, TERTIARY)) {
 701        reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, TERTIARY, STOP);
 702        reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, IDENTITY_RELATION, STOP);
 703        reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, AND_FUNCTION, STOP);
 704        reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, OR_FUNCTION, STOP);
 705        reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, ROUTINE_TEXT, STOP);
 706        reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, JUMP, STOP);
 707        reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, SKIP, STOP);
 708        reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, ASSIGNATION, STOP);
 709        reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, CODE_CLAUSE, STOP);
 710      }
 711  // Routine texts with parameter pack.
 712      else if (IS (p, PARAMETER_PACK)) {
 713        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, ASSIGNATION, STOP);
 714        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, IDENTITY_RELATION, STOP);
 715        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, AND_FUNCTION, STOP);
 716        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, OR_FUNCTION, STOP);
 717        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, JUMP, STOP);
 718        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, SKIP, STOP);
 719        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, TERTIARY, STOP);
 720        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, ROUTINE_TEXT, STOP);
 721        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, CODE_CLAUSE, STOP);
 722        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, ASSIGNATION, STOP);
 723        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, IDENTITY_RELATION, STOP);
 724        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, AND_FUNCTION, STOP);
 725        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, OR_FUNCTION, STOP);
 726        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, JUMP, STOP);
 727        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, SKIP, STOP);
 728        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, TERTIARY, STOP);
 729        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, ROUTINE_TEXT, STOP);
 730        reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, CODE_CLAUSE, STOP);
 731      }
 732  // Routine texts without parameter pack.
 733      else if (IS (p, DECLARER)) {
 734        if (!(PREVIOUS (p) != NO_NODE && IS (PREVIOUS (p), PARAMETER_PACK))) {
 735          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, ASSIGNATION, STOP);
 736          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, IDENTITY_RELATION, STOP);
 737          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, AND_FUNCTION, STOP);
 738          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, OR_FUNCTION, STOP);
 739          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, JUMP, STOP);
 740          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, SKIP, STOP);
 741          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, TERTIARY, STOP);
 742          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, ROUTINE_TEXT, STOP);
 743          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, CODE_CLAUSE, STOP);
 744        }
 745      } else if (IS (p, VOID_SYMBOL)) {
 746        if (!(PREVIOUS (p) != NO_NODE && IS (PREVIOUS (p), PARAMETER_PACK))) {
 747          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, ASSIGNATION, STOP);
 748          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, IDENTITY_RELATION, STOP);
 749          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, AND_FUNCTION, STOP);
 750          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, OR_FUNCTION, STOP);
 751          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, JUMP, STOP);
 752          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, SKIP, STOP);
 753          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, TERTIARY, STOP);
 754          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, ROUTINE_TEXT, STOP);
 755          reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, CODE_CLAUSE, STOP);
 756        }
 757      }
 758    }
 759  }
 760  
 761  //! @brief Reduce primary elements.
 762  
 763  void reduce_primary_parts (NODE_T * p, int expect)
 764  {
 765    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
 766      if (whether (q, IDENTIFIER, OF_SYMBOL, STOP)) {
 767        ATTRIBUTE (q) = FIELD_IDENTIFIER;
 768      }
 769      reduce (q, NO_NOTE, NO_TICK, ENVIRON_NAME, ENVIRON_SYMBOL, ROW_CHAR_DENOTATION, STOP);
 770      reduce (q, NO_NOTE, NO_TICK, NIHIL, NIL_SYMBOL, STOP);
 771      reduce (q, NO_NOTE, NO_TICK, SKIP, SKIP_SYMBOL, STOP);
 772      reduce (q, NO_NOTE, NO_TICK, SELECTOR, FIELD_IDENTIFIER, OF_SYMBOL, STOP);
 773  // JUMPs without GOTO are resolved later.
 774      reduce (q, NO_NOTE, NO_TICK, JUMP, GOTO_SYMBOL, IDENTIFIER, STOP);
 775      reduce (q, NO_NOTE, NO_TICK, DENOTATION, LONGETY, INT_DENOTATION, STOP);
 776      reduce (q, NO_NOTE, NO_TICK, DENOTATION, LONGETY, REAL_DENOTATION, STOP);
 777      reduce (q, NO_NOTE, NO_TICK, DENOTATION, LONGETY, BITS_DENOTATION, STOP);
 778      reduce (q, NO_NOTE, NO_TICK, DENOTATION, SHORTETY, INT_DENOTATION, STOP);
 779      reduce (q, NO_NOTE, NO_TICK, DENOTATION, SHORTETY, REAL_DENOTATION, STOP);
 780      reduce (q, NO_NOTE, NO_TICK, DENOTATION, SHORTETY, BITS_DENOTATION, STOP);
 781      reduce (q, NO_NOTE, NO_TICK, DENOTATION, INT_DENOTATION, STOP);
 782      reduce (q, NO_NOTE, NO_TICK, DENOTATION, REAL_DENOTATION, STOP);
 783      reduce (q, NO_NOTE, NO_TICK, DENOTATION, BITS_DENOTATION, STOP);
 784      reduce (q, NO_NOTE, NO_TICK, DENOTATION, ROW_CHAR_DENOTATION, STOP);
 785      reduce (q, NO_NOTE, NO_TICK, DENOTATION, TRUE_SYMBOL, STOP);
 786      reduce (q, NO_NOTE, NO_TICK, DENOTATION, FALSE_SYMBOL, STOP);
 787      reduce (q, NO_NOTE, NO_TICK, DENOTATION, EMPTY_SYMBOL, STOP);
 788      if (expect == SERIAL_CLAUSE || expect == ENQUIRY_CLAUSE || expect == SOME_CLAUSE) {
 789        BOOL_T siga = A68G_TRUE;
 790        while (siga) {
 791          siga = A68G_FALSE;
 792          reduce (q, NO_NOTE, &siga, LABEL, DEFINING_IDENTIFIER, COLON_SYMBOL, STOP);
 793          reduce (q, NO_NOTE, &siga, LABEL, LABEL, DEFINING_IDENTIFIER, COLON_SYMBOL, STOP);
 794        }
 795      }
 796    }
 797    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
 798      #if defined (BUILD_PARALLEL_CLAUSE)
 799        reduce (q, NO_NOTE, NO_TICK, PARALLEL_CLAUSE, PAR_SYMBOL, COLLATERAL_CLAUSE, STOP);
 800      #else
 801        reduce (q, par_clause, NO_TICK, PARALLEL_CLAUSE, PAR_SYMBOL, COLLATERAL_CLAUSE, STOP);
 802      #endif
 803      reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, PARALLEL_CLAUSE, STOP);
 804      reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CLOSED_CLAUSE, STOP);
 805      reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, COLLATERAL_CLAUSE, STOP);
 806      reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CONDITIONAL_CLAUSE, STOP);
 807      reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CASE_CLAUSE, STOP);
 808      reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CONFORMITY_CLAUSE, STOP);
 809      reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, LOOP_CLAUSE, STOP);
 810    }
 811  }
 812  
 813  //! @brief Reduce primaries completely.
 814  
 815  void reduce_primaries (NODE_T * p, int expect)
 816  {
 817    NODE_T *q = p;
 818    while (q != NO_NODE) {
 819      BOOL_T fwd = A68G_TRUE, siga;
 820  // Primaries excepts call and slice.
 821      reduce (q, NO_NOTE, NO_TICK, PRIMARY, IDENTIFIER, STOP);
 822      reduce (q, NO_NOTE, NO_TICK, PRIMARY, DENOTATION, STOP);
 823      reduce (q, NO_NOTE, NO_TICK, CAST, DECLARER, ENCLOSED_CLAUSE, STOP);
 824      reduce (q, NO_NOTE, NO_TICK, CAST, VOID_SYMBOL, ENCLOSED_CLAUSE, STOP);
 825      reduce (q, NO_NOTE, NO_TICK, ASSERTION, ASSERT_SYMBOL, ENCLOSED_CLAUSE, STOP);
 826      reduce (q, NO_NOTE, NO_TICK, PRIMARY, CAST, STOP);
 827      reduce (q, NO_NOTE, NO_TICK, PRIMARY, ENCLOSED_CLAUSE, STOP);
 828      reduce (q, NO_NOTE, NO_TICK, PRIMARY, FORMAT_TEXT, STOP);
 829  // Call and slice.
 830      siga = A68G_TRUE;
 831      while (siga) {
 832        NODE_T *x = NEXT (q);
 833        siga = A68G_FALSE;
 834        if (IS (q, PRIMARY) && x != NO_NODE) {
 835          if (IS (x, OPEN_SYMBOL)) {
 836            reduce_branch (NEXT (q), GENERIC_ARGUMENT);
 837            reduce (q, NO_NOTE, &siga, SPECIFICATION, PRIMARY, GENERIC_ARGUMENT, STOP);
 838            reduce (q, NO_NOTE, &siga, PRIMARY, SPECIFICATION, STOP);
 839          } else if (IS (x, SUB_SYMBOL)) {
 840            reduce_branch (NEXT (q), GENERIC_ARGUMENT);
 841            reduce (q, NO_NOTE, &siga, SPECIFICATION, PRIMARY, GENERIC_ARGUMENT, STOP);
 842            reduce (q, NO_NOTE, &siga, PRIMARY, SPECIFICATION, STOP);
 843          }
 844        }
 845      }
 846  // Now that call and slice are known, reduce remaining ( .. ).
 847      if (IS (q, OPEN_SYMBOL) && SUB (q) != NO_NODE) {
 848        reduce_branch (q, SOME_CLAUSE);
 849        reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CLOSED_CLAUSE, STOP);
 850        reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, COLLATERAL_CLAUSE, STOP);
 851        reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CONDITIONAL_CLAUSE, STOP);
 852        reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CASE_CLAUSE, STOP);
 853        reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CONFORMITY_CLAUSE, STOP);
 854        if (PREVIOUS (q) != NO_NODE) {
 855          BACKWARD (q);
 856          fwd = A68G_FALSE;
 857        }
 858      }
 859  // Format text items.
 860      if (expect == FORMAT_TEXT) {
 861        NODE_T *r;
 862        for (r = p; r != NO_NODE; FORWARD (r)) {
 863          reduce (r, NO_NOTE, NO_TICK, DYNAMIC_REPLICATOR, FORMAT_ITEM_N, ENCLOSED_CLAUSE, STOP);
 864          reduce (r, NO_NOTE, NO_TICK, GENERAL_PATTERN, FORMAT_ITEM_G, ENCLOSED_CLAUSE, STOP);
 865          reduce (r, NO_NOTE, NO_TICK, GENERAL_PATTERN, FORMAT_ITEM_H, ENCLOSED_CLAUSE, STOP);
 866          reduce (r, NO_NOTE, NO_TICK, FORMAT_PATTERN, FORMAT_ITEM_F, ENCLOSED_CLAUSE, STOP);
 867        }
 868      }
 869      if (fwd) {
 870        FORWARD (q);
 871      }
 872    }
 873  }
 874  
 875  //! @brief Enforce that ambiguous patterns are separated by commas.
 876  
 877  void ambiguous_patterns (NODE_T * p)
 878  {
 879  // Example: printf (($+d.2d +d.2d$, 1, 2)) can produce either "+1.00 +2.00" or
 880  // "+1+002.00". A comma must be supplied to resolve the ambiguity.
 881  // 
 882  // The obvious thing would be to weave this into the syntax, letting the BU parser
 883  // sort it out. But the C-style patterns do not suffer from Algol 68 pattern
 884  // ambiguity, so by solving it this way we maximise freedom in writing the patterns
 885  // as we want without introducing two "kinds" of patterns, and so we have shorter
 886  // routines for implementing formatted transput. This is a pragmatic system.
 887    NODE_T *q, *last_pat = NO_NODE;
 888    for (q = p; q != NO_NODE; FORWARD (q)) {
 889      switch (ATTRIBUTE (q)) {
 890      case INTEGRAL_PATTERN:     // These are the potentially ambiguous patterns
 891      case REAL_PATTERN:
 892      case COMPLEX_PATTERN:
 893      case BITS_PATTERN: {
 894          if (last_pat != NO_NODE) {
 895            diagnostic (A68G_SYNTAX_ERROR, q, ERROR_COMMA_MUST_SEPARATE, ATTRIBUTE (last_pat), ATTRIBUTE (q));
 896          }
 897          last_pat = q;
 898          break;
 899        }
 900      case COMMA_SYMBOL: {
 901          last_pat = NO_NODE;
 902          break;
 903        }
 904      }
 905    }
 906  }
 907  
 908  //! @brief Reduce format texts completely.
 909  
 910  void reduce_c_pattern (NODE_T * p, int pr, int let)
 911  {
 912    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
 913      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, let, STOP);
 914      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
 915      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, REPLICATOR, let, STOP);
 916      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, REPLICATOR, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
 917      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_PLUS, let, STOP);
 918      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_PLUS, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
 919      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_PLUS, REPLICATOR, let, STOP);
 920      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_PLUS, REPLICATOR, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
 921      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, let, STOP);
 922      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
 923      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, REPLICATOR, let, STOP);
 924      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, REPLICATOR, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
 925      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, FORMAT_ITEM_PLUS, let, STOP);
 926      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, FORMAT_ITEM_PLUS, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
 927      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, FORMAT_ITEM_PLUS, REPLICATOR, let, STOP);
 928      reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, FORMAT_ITEM_PLUS, REPLICATOR, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
 929    }
 930  }
 931  
 932  //! @brief Reduce format texts completely.
 933  
 934  void reduce_format_texts (NODE_T * p)
 935  {
 936  // Replicators.
 937    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
 938      reduce (q, NO_NOTE, NO_TICK, REPLICATOR, STATIC_REPLICATOR, STOP);
 939      reduce (q, NO_NOTE, NO_TICK, REPLICATOR, DYNAMIC_REPLICATOR, STOP);
 940    }
 941  // "OTHER" patterns.
 942    reduce_c_pattern (p, BITS_C_PATTERN, FORMAT_ITEM_B);
 943    reduce_c_pattern (p, BITS_C_PATTERN, FORMAT_ITEM_O);
 944    reduce_c_pattern (p, BITS_C_PATTERN, FORMAT_ITEM_X);
 945    reduce_c_pattern (p, CHAR_C_PATTERN, FORMAT_ITEM_C);
 946    reduce_c_pattern (p, FIXED_C_PATTERN, FORMAT_ITEM_F);
 947    reduce_c_pattern (p, FLOAT_C_PATTERN, FORMAT_ITEM_E);
 948    reduce_c_pattern (p, GENERAL_C_PATTERN, FORMAT_ITEM_G);
 949    reduce_c_pattern (p, INTEGRAL_C_PATTERN, FORMAT_ITEM_D);
 950    reduce_c_pattern (p, INTEGRAL_C_PATTERN, FORMAT_ITEM_I);
 951    reduce_c_pattern (p, STRING_C_PATTERN, FORMAT_ITEM_S);
 952  // Radix frames.
 953    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
 954      reduce (q, NO_NOTE, NO_TICK, RADIX_FRAME, REPLICATOR, FORMAT_ITEM_R, STOP);
 955    }
 956  // Insertions.
 957    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
 958      reduce (q, NO_NOTE, NO_TICK, INSERTION, FORMAT_ITEM_X, STOP);
 959      reduce (q, NO_NOTE, NO_TICK, INSERTION, FORMAT_ITEM_Y, STOP);
 960      reduce (q, NO_NOTE, NO_TICK, INSERTION, FORMAT_ITEM_L, STOP);
 961      reduce (q, NO_NOTE, NO_TICK, INSERTION, FORMAT_ITEM_P, STOP);
 962      reduce (q, NO_NOTE, NO_TICK, INSERTION, FORMAT_ITEM_Q, STOP);
 963      reduce (q, NO_NOTE, NO_TICK, INSERTION, FORMAT_ITEM_K, STOP);
 964      reduce (q, NO_NOTE, NO_TICK, INSERTION, LITERAL, STOP);
 965    }
 966    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
 967      reduce (q, NO_NOTE, NO_TICK, INSERTION, REPLICATOR, INSERTION, STOP);
 968    }
 969    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
 970      BOOL_T siga = A68G_TRUE;
 971      while (siga) {
 972        siga = A68G_FALSE;
 973        reduce (q, NO_NOTE, &siga, INSERTION, INSERTION, INSERTION, STOP);
 974      }
 975    }
 976  // Replicated suppressible frames.
 977    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
 978      reduce (q, NO_NOTE, NO_TICK, FORMAT_A_FRAME, REPLICATOR, FORMAT_ITEM_S, FORMAT_ITEM_A, STOP);
 979      reduce (q, NO_NOTE, NO_TICK, FORMAT_Z_FRAME, REPLICATOR, FORMAT_ITEM_S, FORMAT_ITEM_Z, STOP);
 980      reduce (q, NO_NOTE, NO_TICK, FORMAT_D_FRAME, REPLICATOR, FORMAT_ITEM_S, FORMAT_ITEM_D, STOP);
 981    }
 982  // Suppressible frames.
 983    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
 984      reduce (q, NO_NOTE, NO_TICK, FORMAT_A_FRAME, FORMAT_ITEM_S, FORMAT_ITEM_A, STOP);
 985      reduce (q, NO_NOTE, NO_TICK, FORMAT_Z_FRAME, FORMAT_ITEM_S, FORMAT_ITEM_Z, STOP);
 986      reduce (q, NO_NOTE, NO_TICK, FORMAT_D_FRAME, FORMAT_ITEM_S, FORMAT_ITEM_D, STOP);
 987      reduce (q, NO_NOTE, NO_TICK, FORMAT_E_FRAME, FORMAT_ITEM_S, FORMAT_ITEM_E, STOP);
 988      reduce (q, NO_NOTE, NO_TICK, FORMAT_POINT_FRAME, FORMAT_ITEM_S, FORMAT_ITEM_POINT, STOP);
 989      reduce (q, NO_NOTE, NO_TICK, FORMAT_I_FRAME, FORMAT_ITEM_S, FORMAT_ITEM_I, STOP);
 990    }
 991  // Replicated frames.
 992    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
 993      reduce (q, NO_NOTE, NO_TICK, FORMAT_A_FRAME, REPLICATOR, FORMAT_ITEM_A, STOP);
 994      reduce (q, NO_NOTE, NO_TICK, FORMAT_Z_FRAME, REPLICATOR, FORMAT_ITEM_Z, STOP);
 995      reduce (q, NO_NOTE, NO_TICK, FORMAT_D_FRAME, REPLICATOR, FORMAT_ITEM_D, STOP);
 996    }
 997  // Frames.
 998    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
 999      reduce (q, NO_NOTE, NO_TICK, FORMAT_A_FRAME, FORMAT_ITEM_A, STOP);
1000      reduce (q, NO_NOTE, NO_TICK, FORMAT_Z_FRAME, FORMAT_ITEM_Z, STOP);
1001      reduce (q, NO_NOTE, NO_TICK, FORMAT_D_FRAME, FORMAT_ITEM_D, STOP);
1002      reduce (q, NO_NOTE, NO_TICK, FORMAT_E_FRAME, FORMAT_ITEM_E, STOP);
1003      reduce (q, NO_NOTE, NO_TICK, FORMAT_POINT_FRAME, FORMAT_ITEM_POINT, STOP);
1004      reduce (q, NO_NOTE, NO_TICK, FORMAT_I_FRAME, FORMAT_ITEM_I, STOP);
1005    }
1006  // Frames with an insertion.
1007    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1008      reduce (q, NO_NOTE, NO_TICK, FORMAT_A_FRAME, INSERTION, FORMAT_A_FRAME, STOP);
1009      reduce (q, NO_NOTE, NO_TICK, FORMAT_Z_FRAME, INSERTION, FORMAT_Z_FRAME, STOP);
1010      reduce (q, NO_NOTE, NO_TICK, FORMAT_D_FRAME, INSERTION, FORMAT_D_FRAME, STOP);
1011      reduce (q, NO_NOTE, NO_TICK, FORMAT_E_FRAME, INSERTION, FORMAT_E_FRAME, STOP);
1012      reduce (q, NO_NOTE, NO_TICK, FORMAT_POINT_FRAME, INSERTION, FORMAT_POINT_FRAME, STOP);
1013      reduce (q, NO_NOTE, NO_TICK, FORMAT_I_FRAME, INSERTION, FORMAT_I_FRAME, STOP);
1014    }
1015  // String patterns.
1016    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1017      reduce (q, NO_NOTE, NO_TICK, STRING_PATTERN, REPLICATOR, FORMAT_A_FRAME, STOP);
1018    }
1019    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1020      reduce (q, NO_NOTE, NO_TICK, STRING_PATTERN, FORMAT_A_FRAME, STOP);
1021    }
1022    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1023      BOOL_T siga = A68G_TRUE;
1024      while (siga) {
1025        siga = A68G_FALSE;
1026        reduce (q, NO_NOTE, &siga, STRING_PATTERN, STRING_PATTERN, STRING_PATTERN, STOP);
1027        reduce (q, NO_NOTE, &siga, STRING_PATTERN, STRING_PATTERN, INSERTION, STRING_PATTERN, STOP);
1028      }
1029    }
1030  // Integral moulds.
1031    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1032      reduce (q, NO_NOTE, NO_TICK, INTEGRAL_MOULD, FORMAT_Z_FRAME, STOP);
1033      reduce (q, NO_NOTE, NO_TICK, INTEGRAL_MOULD, FORMAT_D_FRAME, STOP);
1034    }
1035    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1036      BOOL_T siga = A68G_TRUE;
1037      while (siga) {
1038        siga = A68G_FALSE;
1039        reduce (q, NO_NOTE, &siga, INTEGRAL_MOULD, INTEGRAL_MOULD, INTEGRAL_MOULD, STOP);
1040        reduce (q, NO_NOTE, &siga, INTEGRAL_MOULD, INTEGRAL_MOULD, INSERTION, STOP);
1041      }
1042    }
1043  // Sign moulds.
1044    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1045      reduce (q, NO_NOTE, NO_TICK, SIGN_MOULD, INTEGRAL_MOULD, FORMAT_ITEM_PLUS, STOP);
1046      reduce (q, NO_NOTE, NO_TICK, SIGN_MOULD, INTEGRAL_MOULD, FORMAT_ITEM_MINUS, STOP);
1047    }
1048    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1049      reduce (q, NO_NOTE, NO_TICK, SIGN_MOULD, FORMAT_ITEM_PLUS, STOP);
1050      reduce (q, NO_NOTE, NO_TICK, SIGN_MOULD, FORMAT_ITEM_MINUS, STOP);
1051    }
1052  // Exponent frames.
1053    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1054      reduce (q, NO_NOTE, NO_TICK, EXPONENT_FRAME, FORMAT_E_FRAME, SIGN_MOULD, INTEGRAL_MOULD, STOP);
1055      reduce (q, NO_NOTE, NO_TICK, EXPONENT_FRAME, FORMAT_E_FRAME, INTEGRAL_MOULD, STOP);
1056    }
1057  // Real patterns.
1058    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1059      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, INTEGRAL_MOULD, FORMAT_POINT_FRAME, INTEGRAL_MOULD, EXPONENT_FRAME, STOP);
1060      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, INTEGRAL_MOULD, FORMAT_POINT_FRAME, INTEGRAL_MOULD, STOP);
1061      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, INTEGRAL_MOULD, FORMAT_POINT_FRAME, EXPONENT_FRAME, STOP);
1062      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, INTEGRAL_MOULD, FORMAT_POINT_FRAME, STOP);
1063    }
1064    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1065      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, FORMAT_POINT_FRAME, INTEGRAL_MOULD, EXPONENT_FRAME, STOP);
1066      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, FORMAT_POINT_FRAME, INTEGRAL_MOULD, STOP);
1067      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, FORMAT_POINT_FRAME, EXPONENT_FRAME, STOP);
1068      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, FORMAT_POINT_FRAME, STOP);
1069    }
1070    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1071      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, INTEGRAL_MOULD, FORMAT_POINT_FRAME, INTEGRAL_MOULD, EXPONENT_FRAME, STOP);
1072      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, INTEGRAL_MOULD, FORMAT_POINT_FRAME, INTEGRAL_MOULD, STOP);
1073      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, INTEGRAL_MOULD, FORMAT_POINT_FRAME, EXPONENT_FRAME, STOP);
1074      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, INTEGRAL_MOULD, FORMAT_POINT_FRAME, STOP);
1075      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, FORMAT_POINT_FRAME, INTEGRAL_MOULD, EXPONENT_FRAME, STOP);
1076      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, FORMAT_POINT_FRAME, INTEGRAL_MOULD, STOP);
1077    }
1078    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1079      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, INTEGRAL_MOULD, EXPONENT_FRAME, STOP);
1080      reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, INTEGRAL_MOULD, EXPONENT_FRAME, STOP);
1081    }
1082  // Complex patterns.
1083    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1084      reduce (q, NO_NOTE, NO_TICK, COMPLEX_PATTERN, REAL_PATTERN, FORMAT_I_FRAME, REAL_PATTERN, STOP);
1085    }
1086  // Bits patterns.
1087    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1088      reduce (q, NO_NOTE, NO_TICK, BITS_PATTERN, RADIX_FRAME, INTEGRAL_MOULD, STOP);
1089    }
1090  // Integral patterns.
1091    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1092      reduce (q, NO_NOTE, NO_TICK, INTEGRAL_PATTERN, SIGN_MOULD, INTEGRAL_MOULD, STOP);
1093      reduce (q, NO_NOTE, NO_TICK, INTEGRAL_PATTERN, INTEGRAL_MOULD, STOP);
1094    }
1095  // Patterns.
1096    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1097      reduce (q, NO_NOTE, NO_TICK, BOOLEAN_PATTERN, FORMAT_ITEM_B, COLLECTION, STOP);
1098      reduce (q, NO_NOTE, NO_TICK, CHOICE_PATTERN, FORMAT_ITEM_C, COLLECTION, STOP);
1099    }
1100    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1101      reduce (q, NO_NOTE, NO_TICK, BOOLEAN_PATTERN, FORMAT_ITEM_B, STOP);
1102      reduce (q, NO_NOTE, NO_TICK, GENERAL_PATTERN, FORMAT_ITEM_G, STOP);
1103      reduce (q, NO_NOTE, NO_TICK, GENERAL_PATTERN, FORMAT_ITEM_H, STOP);
1104    }
1105    ambiguous_patterns (p);
1106    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1107      reduce (q, a68g_extension, NO_TICK, A68G_PATTERN, BITS_C_PATTERN, STOP);
1108      reduce (q, a68g_extension, NO_TICK, A68G_PATTERN, CHAR_C_PATTERN, STOP);
1109      reduce (q, a68g_extension, NO_TICK, A68G_PATTERN, FIXED_C_PATTERN, STOP);
1110      reduce (q, a68g_extension, NO_TICK, A68G_PATTERN, FLOAT_C_PATTERN, STOP);
1111      reduce (q, a68g_extension, NO_TICK, A68G_PATTERN, GENERAL_C_PATTERN, STOP);
1112      reduce (q, a68g_extension, NO_TICK, A68G_PATTERN, INTEGRAL_C_PATTERN, STOP);
1113      reduce (q, a68g_extension, NO_TICK, A68G_PATTERN, STRING_C_PATTERN, STOP);
1114      reduce (q, NO_NOTE, NO_TICK, A68G_PATTERN, BITS_PATTERN, STOP);
1115      reduce (q, NO_NOTE, NO_TICK, A68G_PATTERN, BOOLEAN_PATTERN, STOP);
1116      reduce (q, NO_NOTE, NO_TICK, A68G_PATTERN, CHOICE_PATTERN, STOP);
1117      reduce (q, NO_NOTE, NO_TICK, A68G_PATTERN, COMPLEX_PATTERN, STOP);
1118      reduce (q, NO_NOTE, NO_TICK, A68G_PATTERN, FORMAT_PATTERN, STOP);
1119      reduce (q, NO_NOTE, NO_TICK, A68G_PATTERN, GENERAL_PATTERN, STOP);
1120      reduce (q, NO_NOTE, NO_TICK, A68G_PATTERN, INTEGRAL_PATTERN, STOP);
1121      reduce (q, NO_NOTE, NO_TICK, A68G_PATTERN, REAL_PATTERN, STOP);
1122      reduce (q, NO_NOTE, NO_TICK, A68G_PATTERN, STRING_PATTERN, STOP);
1123    }
1124  // Pictures.
1125    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1126      reduce (q, NO_NOTE, NO_TICK, PICTURE, INSERTION, STOP);
1127      reduce (q, NO_NOTE, NO_TICK, PICTURE, A68G_PATTERN, STOP);
1128      reduce (q, NO_NOTE, NO_TICK, PICTURE, COLLECTION, STOP);
1129      reduce (q, NO_NOTE, NO_TICK, PICTURE, REPLICATOR, COLLECTION, STOP);
1130    }
1131  // Picture lists.
1132    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1133      if (IS (q, PICTURE)) {
1134        BOOL_T siga = A68G_TRUE;
1135        reduce (q, NO_NOTE, NO_TICK, PICTURE_LIST, PICTURE, STOP);
1136        while (siga) {
1137          siga = A68G_FALSE;
1138          reduce (q, NO_NOTE, &siga, PICTURE_LIST, PICTURE_LIST, COMMA_SYMBOL, PICTURE, STOP);
1139  // We filtered ambiguous patterns, so commas may be omitted 
1140          reduce (q, NO_NOTE, &siga, PICTURE_LIST, PICTURE_LIST, PICTURE, STOP);
1141        }
1142      }
1143    }
1144  }
1145  
1146  //! @brief Reduce secondaries completely.
1147  
1148  void reduce_secondaries (NODE_T * p)
1149  {
1150    NODE_T *q; BOOL_T siga;
1151    for (q = p; q != NO_NODE; FORWARD (q)) {
1152      reduce (q, NO_NOTE, NO_TICK, SECONDARY, PRIMARY, STOP);
1153      reduce (q, NO_NOTE, NO_TICK, GENERATOR, LOC_SYMBOL, DECLARER, STOP);
1154      reduce (q, NO_NOTE, NO_TICK, GENERATOR, HEAP_SYMBOL, DECLARER, STOP);
1155      reduce (q, NO_NOTE, NO_TICK, GENERATOR, NEW_SYMBOL, DECLARER, STOP);
1156      reduce (q, NO_NOTE, NO_TICK, SECONDARY, GENERATOR, STOP);
1157    }
1158    siga = A68G_TRUE;
1159    while (siga) {
1160      siga = A68G_FALSE;
1161      for (q = p; NEXT (q) != NO_NODE; FORWARD (q)) {
1162        ;
1163      }
1164      for (; q != NO_NODE; BACKWARD (q)) {
1165        reduce (q, NO_NOTE, &siga, SELECTION, SELECTOR, SECONDARY, STOP);
1166        reduce (q, NO_NOTE, &siga, SECONDARY, SELECTION, STOP);
1167      }
1168    }
1169  }
1170  
1171  //! @brief Whether "q" is an operator with priority "k".
1172  
1173  int operator_with_priority (NODE_T * q, int k)
1174  {
1175    return NEXT (q) != NO_NODE && ATTRIBUTE (NEXT (q)) == OPERATOR && PRIO (INFO (NEXT (q))) == k;
1176  }
1177  
1178  //! @brief Reduce formulae.
1179  
1180  void reduce_formulae (NODE_T * p)
1181  {
1182    NODE_T *q = p;
1183    while (q != NO_NODE) {
1184      if (is_one_of (q, OPERATOR, SECONDARY, STOP)) {
1185        q = reduce_dyadic (q, STOP);
1186      } else {
1187        FORWARD (q);
1188      }
1189    }
1190  // Reduce the expression.
1191    for (int prio = MAX_PRIORITY; prio >= 0; prio--) {
1192      for (q = p; q != NO_NODE; FORWARD (q)) {
1193        if (operator_with_priority (q, prio)) {
1194          BOOL_T siga = A68G_FALSE;
1195          NODE_T *op = NEXT (q);
1196          if (IS (q, SECONDARY)) {
1197            reduce (q, NO_NOTE, &siga, FORMULA, SECONDARY, OPERATOR, SECONDARY, STOP);
1198            reduce (q, NO_NOTE, &siga, FORMULA, SECONDARY, OPERATOR, MONADIC_FORMULA, STOP);
1199            reduce (q, NO_NOTE, &siga, FORMULA, SECONDARY, OPERATOR, FORMULA, STOP);
1200          } else if (IS (q, MONADIC_FORMULA)) {
1201            reduce (q, NO_NOTE, &siga, FORMULA, MONADIC_FORMULA, OPERATOR, SECONDARY, STOP);
1202            reduce (q, NO_NOTE, &siga, FORMULA, MONADIC_FORMULA, OPERATOR, MONADIC_FORMULA, STOP);
1203            reduce (q, NO_NOTE, &siga, FORMULA, MONADIC_FORMULA, OPERATOR, FORMULA, STOP);
1204          }
1205          if (prio == 0 && siga) {
1206            diagnostic (A68G_SYNTAX_ERROR, op, ERROR_NO_PRIORITY);
1207          }
1208          siga = A68G_TRUE;
1209          while (siga) {
1210            NODE_T *op2 = NEXT (q);
1211            siga = A68G_FALSE;
1212            if (operator_with_priority (q, prio)) {
1213              reduce (q, NO_NOTE, &siga, FORMULA, FORMULA, OPERATOR, SECONDARY, STOP);
1214            }
1215            if (operator_with_priority (q, prio)) {
1216              reduce (q, NO_NOTE, &siga, FORMULA, FORMULA, OPERATOR, MONADIC_FORMULA, STOP);
1217            }
1218            if (operator_with_priority (q, prio)) {
1219              reduce (q, NO_NOTE, &siga, FORMULA, FORMULA, OPERATOR, FORMULA, STOP);
1220            }
1221            if (prio == 0 && siga) {
1222              diagnostic (A68G_SYNTAX_ERROR, op2, ERROR_NO_PRIORITY);
1223            }
1224          }
1225        }
1226      }
1227    }
1228  }
1229  
1230  //! @brief Reduce dyadic expressions.
1231  
1232  NODE_T *reduce_dyadic (NODE_T * p, int u)
1233  {
1234  // We work inside out - higher priority expressions get reduced first.
1235    if (u > MAX_PRIORITY) {
1236      if (p == NO_NODE) {
1237        return NO_NODE;
1238      } else if (IS (p, OPERATOR)) {
1239  // Reduce monadic formulas.
1240        NODE_T *q = p;
1241        BOOL_T siga;
1242        do {
1243          PRIO (INFO (q)) = 10;
1244          siga = (BOOL_T) ((NEXT (q) != NO_NODE) && (IS (NEXT (q), OPERATOR)));
1245          if (siga) {
1246            FORWARD (q);
1247          }
1248        } while (siga);
1249        reduce (q, NO_NOTE, NO_TICK, MONADIC_FORMULA, OPERATOR, SECONDARY, STOP);
1250        while (q != p) {
1251          BACKWARD (q);
1252          reduce (q, NO_NOTE, NO_TICK, MONADIC_FORMULA, OPERATOR, MONADIC_FORMULA, STOP);
1253        }
1254      }
1255      FORWARD (p);
1256    } else {
1257      p = reduce_dyadic (p, u + 1);
1258      while (p != NO_NODE && IS (p, OPERATOR) && PRIO (INFO (p)) == u) {
1259        FORWARD (p);
1260        p = reduce_dyadic (p, u + 1);
1261      }
1262    }
1263    return p;
1264  }
1265  
1266  //! @brief Reduce tertiaries completely.
1267  
1268  void reduce_tertiaries (NODE_T * p)
1269  {
1270    BOOL_T siga;
1271    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1272      reduce (q, NO_NOTE, NO_TICK, TERTIARY, NIHIL, STOP);
1273      reduce (q, NO_NOTE, NO_TICK, FORMULA, MONADIC_FORMULA, STOP);
1274      reduce (q, NO_NOTE, NO_TICK, TERTIARY, FORMULA, STOP);
1275      reduce (q, NO_NOTE, NO_TICK, TERTIARY, SECONDARY, STOP);
1276    }
1277    siga = A68G_TRUE;
1278    while (siga) {
1279      siga = A68G_FALSE;
1280      for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1281        reduce (q, NO_NOTE, &siga, TRANSPOSE_FUNCTION, TRANSPOSE_SYMBOL, TERTIARY, STOP);
1282        reduce (q, NO_NOTE, &siga, DIAGONAL_FUNCTION, TERTIARY, DIAGONAL_SYMBOL, TERTIARY, STOP);
1283        reduce (q, NO_NOTE, &siga, DIAGONAL_FUNCTION, DIAGONAL_SYMBOL, TERTIARY, STOP);
1284        reduce (q, NO_NOTE, &siga, COLUMN_FUNCTION, TERTIARY, COLUMN_SYMBOL, TERTIARY, STOP);
1285        reduce (q, NO_NOTE, &siga, COLUMN_FUNCTION, COLUMN_SYMBOL, TERTIARY, STOP);
1286        reduce (q, NO_NOTE, &siga, ROW_FUNCTION, TERTIARY, ROW_SYMBOL, TERTIARY, STOP);
1287        reduce (q, NO_NOTE, &siga, ROW_FUNCTION, ROW_SYMBOL, TERTIARY, STOP);
1288      }
1289      for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1290        reduce (q, a68g_extension, &siga, TERTIARY, TRANSPOSE_FUNCTION, STOP);
1291        reduce (q, a68g_extension, &siga, TERTIARY, DIAGONAL_FUNCTION, STOP);
1292        reduce (q, a68g_extension, &siga, TERTIARY, COLUMN_FUNCTION, STOP);
1293        reduce (q, a68g_extension, &siga, TERTIARY, ROW_FUNCTION, STOP);
1294      }
1295    }
1296    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1297      reduce (q, NO_NOTE, NO_TICK, IDENTITY_RELATION, TERTIARY, IS_SYMBOL, TERTIARY, STOP);
1298      reduce (q, NO_NOTE, NO_TICK, IDENTITY_RELATION, TERTIARY, ISNT_SYMBOL, TERTIARY, STOP);
1299    }
1300    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1301      reduce (q, NO_NOTE, NO_TICK, AND_FUNCTION, TERTIARY, ANDF_SYMBOL, TERTIARY, STOP);
1302      reduce (q, NO_NOTE, NO_TICK, OR_FUNCTION, TERTIARY, ORF_SYMBOL, TERTIARY, STOP);
1303    }
1304  }
1305  
1306  //! @brief Reduce units.
1307  
1308  void reduce_units (NODE_T * p)
1309  {
1310  // Stray ~ is a SKIP.
1311    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1312      if (IS (q, OPERATOR) && IS_LITERALLY (q, "~")) {
1313        ATTRIBUTE (q) = SKIP;
1314      }
1315    }
1316  // Reduce units.
1317    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1318      reduce (q, NO_NOTE, NO_TICK, UNIT, ASSIGNATION, STOP);
1319      reduce (q, NO_NOTE, NO_TICK, UNIT, IDENTITY_RELATION, STOP);
1320      reduce (q, a68g_extension, NO_TICK, UNIT, AND_FUNCTION, STOP);
1321      reduce (q, a68g_extension, NO_TICK, UNIT, OR_FUNCTION, STOP);
1322      reduce (q, NO_NOTE, NO_TICK, UNIT, ROUTINE_TEXT, STOP);
1323      reduce (q, NO_NOTE, NO_TICK, UNIT, JUMP, STOP);
1324      reduce (q, NO_NOTE, NO_TICK, UNIT, SKIP, STOP);
1325      reduce (q, NO_NOTE, NO_TICK, UNIT, TERTIARY, STOP);
1326      reduce (q, NO_NOTE, NO_TICK, UNIT, ASSERTION, STOP);
1327      reduce (q, NO_NOTE, NO_TICK, UNIT, CODE_CLAUSE, STOP);
1328    }
1329  }
1330  
1331  //! @brief Reduce_generic arguments.
1332  
1333  void reduce_generic_arguments (NODE_T * p)
1334  {
1335    NODE_T *q; BOOL_T siga; // In this scope.
1336    for (q = p; q != NO_NODE; FORWARD (q)) {
1337      if (IS (q, UNIT)) {
1338        reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, COLON_SYMBOL, UNIT, AT_SYMBOL, UNIT, STOP);
1339        reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, COLON_SYMBOL, UNIT, STOP);
1340        reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, COLON_SYMBOL, AT_SYMBOL, UNIT, STOP);
1341        reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, COLON_SYMBOL, STOP);
1342        reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, DOTDOT_SYMBOL, UNIT, AT_SYMBOL, UNIT, STOP);
1343        reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, DOTDOT_SYMBOL, UNIT, STOP);
1344        reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, DOTDOT_SYMBOL, AT_SYMBOL, UNIT, STOP);
1345        reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, DOTDOT_SYMBOL, STOP);
1346      } else if (IS (q, COLON_SYMBOL)) {
1347        reduce (q, NO_NOTE, NO_TICK, TRIMMER, COLON_SYMBOL, UNIT, AT_SYMBOL, UNIT, STOP);
1348        reduce (q, NO_NOTE, NO_TICK, TRIMMER, COLON_SYMBOL, UNIT, STOP);
1349        reduce (q, NO_NOTE, NO_TICK, TRIMMER, COLON_SYMBOL, AT_SYMBOL, UNIT, STOP);
1350        reduce (q, NO_NOTE, NO_TICK, TRIMMER, COLON_SYMBOL, STOP);
1351      } else if (IS (q, DOTDOT_SYMBOL)) {
1352        reduce (q, NO_NOTE, NO_TICK, TRIMMER, DOTDOT_SYMBOL, UNIT, AT_SYMBOL, UNIT, STOP);
1353        reduce (q, NO_NOTE, NO_TICK, TRIMMER, DOTDOT_SYMBOL, UNIT, STOP);
1354        reduce (q, NO_NOTE, NO_TICK, TRIMMER, DOTDOT_SYMBOL, AT_SYMBOL, UNIT, STOP);
1355        reduce (q, NO_NOTE, NO_TICK, TRIMMER, DOTDOT_SYMBOL, STOP);
1356      }
1357    }
1358    for (q = p; q != NO_NODE; FORWARD (q)) {
1359      reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, AT_SYMBOL, UNIT, STOP);
1360    }
1361    for (q = p; q != NO_NODE; FORWARD (q)) {
1362      reduce (q, NO_NOTE, NO_TICK, TRIMMER, AT_SYMBOL, UNIT, STOP);
1363    }
1364    for (q = p; q && NEXT (q); FORWARD (q)) {
1365      if (IS (q, COMMA_SYMBOL)) {
1366        if (!(ATTRIBUTE (NEXT (q)) == UNIT || ATTRIBUTE (NEXT (q)) == TRIMMER)) {
1367          pad_node (q, TRIMMER);
1368        }
1369      } else {
1370        if (IS (NEXT (q), COMMA_SYMBOL)) {
1371          if (!IS (q, UNIT) && !IS (q, TRIMMER)) {
1372            pad_node (q, TRIMMER);
1373          }
1374        }
1375      }
1376    }
1377    q = NEXT (p);
1378    ABEND (q == NO_NODE, ERROR_INTERNAL_CONSISTENCY, NO_TEXT);
1379    reduce (q, NO_NOTE, NO_TICK, GENERIC_ARGUMENT_LIST, UNIT, STOP);
1380    reduce (q, NO_NOTE, NO_TICK, GENERIC_ARGUMENT_LIST, TRIMMER, STOP);
1381    do {
1382      siga = A68G_FALSE;
1383      reduce (q, NO_NOTE, &siga, GENERIC_ARGUMENT_LIST, GENERIC_ARGUMENT_LIST, COMMA_SYMBOL, UNIT, STOP);
1384      reduce (q, NO_NOTE, &siga, GENERIC_ARGUMENT_LIST, GENERIC_ARGUMENT_LIST, COMMA_SYMBOL, TRIMMER, STOP);
1385      reduce (q, strange_separator, &siga, GENERIC_ARGUMENT_LIST, GENERIC_ARGUMENT_LIST, UNIT, STOP);
1386      reduce (q, strange_separator, &siga, GENERIC_ARGUMENT_LIST, GENERIC_ARGUMENT_LIST, TRIMMER, STOP);
1387    } while (siga);
1388  }
1389  
1390  //! @brief Reduce bounds.
1391  
1392  void reduce_bounds (NODE_T * p)
1393  {
1394    NODE_T *q; BOOL_T siga;
1395    for (q = p; q != NO_NODE; FORWARD (q)) {
1396      reduce (q, NO_NOTE, NO_TICK, BOUND, UNIT, COLON_SYMBOL, UNIT, STOP);
1397      reduce (q, NO_NOTE, NO_TICK, BOUND, UNIT, DOTDOT_SYMBOL, UNIT, STOP);
1398      reduce (q, NO_NOTE, NO_TICK, BOUND, UNIT, STOP);
1399    }
1400    q = NEXT (p);
1401    reduce (q, NO_NOTE, NO_TICK, BOUNDS_LIST, BOUND, STOP);
1402    reduce (q, NO_NOTE, NO_TICK, FORMAL_BOUNDS_LIST, COMMA_SYMBOL, STOP);
1403    reduce (q, NO_NOTE, NO_TICK, ALT_FORMAL_BOUNDS_LIST, COLON_SYMBOL, STOP);
1404    reduce (q, NO_NOTE, NO_TICK, ALT_FORMAL_BOUNDS_LIST, DOTDOT_SYMBOL, STOP);
1405    do {
1406      siga = A68G_FALSE;
1407      reduce (q, NO_NOTE, &siga, BOUNDS_LIST, BOUNDS_LIST, COMMA_SYMBOL, BOUND, STOP);
1408      reduce (q, NO_NOTE, &siga, FORMAL_BOUNDS_LIST, FORMAL_BOUNDS_LIST, COMMA_SYMBOL, STOP);
1409      reduce (q, NO_NOTE, &siga, ALT_FORMAL_BOUNDS_LIST, FORMAL_BOUNDS_LIST, COLON_SYMBOL, STOP);
1410      reduce (q, NO_NOTE, &siga, ALT_FORMAL_BOUNDS_LIST, FORMAL_BOUNDS_LIST, DOTDOT_SYMBOL, STOP);
1411      reduce (q, NO_NOTE, &siga, FORMAL_BOUNDS_LIST, ALT_FORMAL_BOUNDS_LIST, COMMA_SYMBOL, STOP);
1412      reduce (q, strange_separator, &siga, BOUNDS_LIST, BOUNDS_LIST, BOUND, STOP);
1413    } while (siga);
1414  }
1415  
1416  //! @brief Reduce argument packs.
1417  
1418  void reduce_arguments (NODE_T * p)
1419  {
1420    if (NEXT (p) != NO_NODE) {
1421      NODE_T *q = NEXT (p);
1422      BOOL_T siga;
1423      reduce (q, NO_NOTE, NO_TICK, ARGUMENT_LIST, UNIT, STOP);
1424      do {
1425        siga = A68G_FALSE;
1426        reduce (q, NO_NOTE, &siga, ARGUMENT_LIST, ARGUMENT_LIST, COMMA_SYMBOL, UNIT, STOP);
1427        reduce (q, strange_separator, &siga, ARGUMENT_LIST, ARGUMENT_LIST, UNIT, STOP);
1428      } while (siga);
1429    }
1430  }
1431  
1432  //! @brief Reduce declarations.
1433  
1434  void reduce_basic_declarations (NODE_T * p)
1435  {
1436    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1437      reduce (q, NO_NOTE, NO_TICK, ENVIRON_NAME, ENVIRON_SYMBOL, ROW_CHAR_DENOTATION, STOP);
1438      reduce (q, NO_NOTE, NO_TICK, PRIORITY_DECLARATION, PRIO_SYMBOL, DEFINING_OPERATOR, EQUALS_SYMBOL, PRIORITY, STOP);
1439      reduce (q, NO_NOTE, NO_TICK, MODE_DECLARATION, MODE_SYMBOL, DEFINING_INDICANT, EQUALS_SYMBOL, DECLARER, STOP);
1440      reduce (q, NO_NOTE, NO_TICK, MODE_DECLARATION, MODE_SYMBOL, DEFINING_INDICANT, EQUALS_SYMBOL, VOID_SYMBOL, STOP);
1441      reduce (q, NO_NOTE, NO_TICK, PROCEDURE_DECLARATION, PROC_SYMBOL, DEFINING_IDENTIFIER, EQUALS_SYMBOL, ROUTINE_TEXT, STOP);
1442      reduce (q, NO_NOTE, NO_TICK, PROCEDURE_VARIABLE_DECLARATION, PROC_SYMBOL, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, ROUTINE_TEXT, STOP);
1443      reduce (q, NO_NOTE, NO_TICK, PROCEDURE_VARIABLE_DECLARATION, QUALIFIER, PROC_SYMBOL, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, ROUTINE_TEXT, STOP);
1444      reduce (q, NO_NOTE, NO_TICK, BRIEF_OPERATOR_DECLARATION, OP_SYMBOL, DEFINING_OPERATOR, EQUALS_SYMBOL, ROUTINE_TEXT, STOP);
1445  // Errors.
1446      reduce (q, strange_tokens, NO_TICK, PRIORITY_DECLARATION, PRIO_SYMBOL, -DEFINING_OPERATOR, -EQUALS_SYMBOL, -PRIORITY, STOP);
1447      reduce (q, strange_tokens, NO_TICK, MODE_DECLARATION, MODE_SYMBOL, DEFINING_INDICANT, EQUALS_SYMBOL, -DECLARER, STOP);
1448      reduce (q, strange_tokens, NO_TICK, PROCEDURE_DECLARATION, PROC_SYMBOL, DEFINING_IDENTIFIER, EQUALS_SYMBOL, -ROUTINE_TEXT, STOP);
1449      reduce (q, strange_tokens, NO_TICK, PROCEDURE_VARIABLE_DECLARATION, PROC_SYMBOL, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, -ROUTINE_TEXT, STOP);
1450      reduce (q, strange_tokens, NO_TICK, PROCEDURE_VARIABLE_DECLARATION, QUALIFIER, PROC_SYMBOL, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, -ROUTINE_TEXT, STOP);
1451      reduce (q, strange_tokens, NO_TICK, BRIEF_OPERATOR_DECLARATION, OP_SYMBOL, DEFINING_OPERATOR, EQUALS_SYMBOL, -ROUTINE_TEXT, STOP);
1452  // Errors. WILDCARD catches TERTIARY which catches IDENTIFIER.
1453      reduce (q, strange_tokens, NO_TICK, PROCEDURE_DECLARATION, PROC_SYMBOL, WILDCARD, ROUTINE_TEXT, STOP);
1454    }
1455    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1456      BOOL_T siga;
1457      do {
1458        siga = A68G_FALSE;
1459        reduce (q, NO_NOTE, &siga, ENVIRON_NAME, ENVIRON_NAME, COMMA_SYMBOL, ROW_CHAR_DENOTATION, STOP);
1460        reduce (q, NO_NOTE, &siga, PRIORITY_DECLARATION, PRIORITY_DECLARATION, COMMA_SYMBOL, DEFINING_OPERATOR, EQUALS_SYMBOL, PRIORITY, STOP);
1461        reduce (q, NO_NOTE, &siga, MODE_DECLARATION, MODE_DECLARATION, COMMA_SYMBOL, DEFINING_INDICANT, EQUALS_SYMBOL, DECLARER, STOP);
1462        reduce (q, NO_NOTE, &siga, MODE_DECLARATION, MODE_DECLARATION, COMMA_SYMBOL, DEFINING_INDICANT, EQUALS_SYMBOL, VOID_SYMBOL, STOP);
1463        reduce (q, NO_NOTE, &siga, PROCEDURE_DECLARATION, PROCEDURE_DECLARATION, COMMA_SYMBOL, DEFINING_IDENTIFIER, EQUALS_SYMBOL, ROUTINE_TEXT, STOP);
1464        reduce (q, NO_NOTE, &siga, PROCEDURE_VARIABLE_DECLARATION, PROCEDURE_VARIABLE_DECLARATION, COMMA_SYMBOL, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, ROUTINE_TEXT, STOP);
1465        reduce (q, NO_NOTE, &siga, BRIEF_OPERATOR_DECLARATION, BRIEF_OPERATOR_DECLARATION, COMMA_SYMBOL, DEFINING_OPERATOR, EQUALS_SYMBOL, ROUTINE_TEXT, STOP);
1466  // Errors. WILDCARD catches TERTIARY which catches IDENTIFIER.
1467        reduce (q, strange_tokens, &siga, PROCEDURE_DECLARATION, PROCEDURE_DECLARATION, COMMA_SYMBOL, WILDCARD, ROUTINE_TEXT, STOP);
1468      } while (siga);
1469    }
1470  }
1471  
1472  //! @brief Reduce declaration lists.
1473  
1474  void reduce_declaration_lists (NODE_T * p)
1475  {
1476    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1477      reduce (q, NO_NOTE, NO_TICK, IDENTITY_DECLARATION, DECLARER, DEFINING_IDENTIFIER, EQUALS_SYMBOL, UNIT, STOP);
1478      reduce (q, NO_NOTE, NO_TICK, VARIABLE_DECLARATION, QUALIFIER, DECLARER, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, UNIT, STOP);
1479      reduce (q, NO_NOTE, NO_TICK, VARIABLE_DECLARATION, QUALIFIER, DECLARER, DEFINING_IDENTIFIER, STOP);
1480      reduce (q, NO_NOTE, NO_TICK, VARIABLE_DECLARATION, DECLARER, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, UNIT, STOP);
1481      reduce (q, NO_NOTE, NO_TICK, VARIABLE_DECLARATION, DECLARER, DEFINING_IDENTIFIER, STOP);
1482    }
1483    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1484      BOOL_T siga;
1485      do {
1486        siga = A68G_FALSE;
1487        reduce (q, NO_NOTE, &siga, IDENTITY_DECLARATION, IDENTITY_DECLARATION, COMMA_SYMBOL, DEFINING_IDENTIFIER, EQUALS_SYMBOL, UNIT, STOP);
1488        reduce (q, NO_NOTE, &siga, VARIABLE_DECLARATION, VARIABLE_DECLARATION, COMMA_SYMBOL, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, UNIT, STOP);
1489        if (!whether (q, VARIABLE_DECLARATION, COMMA_SYMBOL, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, UNIT, STOP)) {
1490          reduce (q, NO_NOTE, &siga, VARIABLE_DECLARATION, VARIABLE_DECLARATION, COMMA_SYMBOL, DEFINING_IDENTIFIER, STOP);
1491        }
1492      } while (siga);
1493    }
1494    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1495      reduce (q, NO_NOTE, NO_TICK, OPERATOR_DECLARATION, OPERATOR_PLAN, DEFINING_OPERATOR, EQUALS_SYMBOL, UNIT, STOP);
1496    }
1497    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1498      BOOL_T siga;
1499      do {
1500        siga = A68G_FALSE;
1501        reduce (q, NO_NOTE, &siga, OPERATOR_DECLARATION, OPERATOR_DECLARATION, COMMA_SYMBOL, DEFINING_OPERATOR, EQUALS_SYMBOL, UNIT, STOP);
1502      } while (siga);
1503    }
1504    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1505      reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, MODE_DECLARATION, STOP);
1506      reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, PRIORITY_DECLARATION, STOP);
1507      reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, BRIEF_OPERATOR_DECLARATION, STOP);
1508      reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, OPERATOR_DECLARATION, STOP);
1509      reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, IDENTITY_DECLARATION, STOP);
1510      reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, PROCEDURE_DECLARATION, STOP);
1511      reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, PROCEDURE_VARIABLE_DECLARATION, STOP);
1512      reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, VARIABLE_DECLARATION, STOP);
1513      reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, ENVIRON_NAME, STOP);
1514    }
1515    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1516      BOOL_T siga;
1517      do {
1518        siga = A68G_FALSE;
1519        reduce (q, NO_NOTE, &siga, DECLARATION_LIST, DECLARATION_LIST, COMMA_SYMBOL, DECLARATION_LIST, STOP);
1520      } while (siga);
1521    }
1522  }
1523  
1524  //! @brief Reduce serial clauses.
1525  
1526  void reduce_serial_clauses (NODE_T * p)
1527  {
1528    if (NEXT (p) != NO_NODE) {
1529      NODE_T *q = NEXT (p), *u;
1530      BOOL_T siga, label_seen;
1531  // Check wrong exits.
1532      for (u = q; u != NO_NODE; FORWARD (u)) {
1533        if (IS (u, EXIT_SYMBOL)) {
1534          if (NEXT (u) == NO_NODE || !IS (NEXT (u), LABELED_UNIT)) {
1535            diagnostic (A68G_SYNTAX_ERROR, u, ERROR_LABELED_UNIT_MUST_FOLLOW);
1536          }
1537        }
1538      }
1539  // Check wrong jumps and declarations.
1540      for (u = q, label_seen = A68G_FALSE; u != NO_NODE; FORWARD (u)) {
1541        if (IS (u, LABELED_UNIT)) {
1542          label_seen = A68G_TRUE;
1543        } else if (IS (u, DECLARATION_LIST)) {
1544          if (label_seen) {
1545            diagnostic (A68G_SYNTAX_ERROR, u, ERROR_LABEL_BEFORE_DECLARATION);
1546          }
1547        }
1548      }
1549  // Reduce serial clauses.
1550      reduce (q, NO_NOTE, NO_TICK, SERIAL_CLAUSE, LABELED_UNIT, STOP);
1551      reduce (q, NO_NOTE, NO_TICK, SERIAL_CLAUSE, UNIT, STOP);
1552      reduce (q, NO_NOTE, NO_TICK, INITIALISER_SERIES, DECLARATION_LIST, STOP);
1553      do {
1554        siga = A68G_FALSE;
1555        if (IS (q, SERIAL_CLAUSE)) {
1556          reduce (q, NO_NOTE, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, SEMI_SYMBOL, UNIT, STOP);
1557          reduce (q, NO_NOTE, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, EXIT_SYMBOL, LABELED_UNIT, STOP);
1558          reduce (q, NO_NOTE, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, SEMI_SYMBOL, LABELED_UNIT, STOP);
1559          reduce (q, NO_NOTE, &siga, INITIALISER_SERIES, SERIAL_CLAUSE, SEMI_SYMBOL, DECLARATION_LIST, STOP);
1560  // Errors 
1561          reduce (q, strange_separator, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, COMMA_SYMBOL, UNIT, STOP);
1562          reduce (q, strange_separator, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, COMMA_SYMBOL, LABELED_UNIT, STOP);
1563          reduce (q, strange_separator, &siga, INITIALISER_SERIES, SERIAL_CLAUSE, COMMA_SYMBOL, DECLARATION_LIST, STOP);
1564          reduce (q, strange_separator, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, COLON_SYMBOL, UNIT, STOP);
1565          reduce (q, strange_separator, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, COLON_SYMBOL, LABELED_UNIT, STOP);
1566          reduce (q, strange_separator, &siga, INITIALISER_SERIES, SERIAL_CLAUSE, COLON_SYMBOL, DECLARATION_LIST, STOP);
1567          reduce (q, strange_separator, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, UNIT, STOP);
1568          reduce (q, strange_separator, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, LABELED_UNIT, STOP);
1569          reduce (q, strange_separator, &siga, INITIALISER_SERIES, SERIAL_CLAUSE, DECLARATION_LIST, STOP);
1570        } else if (IS (q, INITIALISER_SERIES)) {
1571          reduce (q, NO_NOTE, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, SEMI_SYMBOL, UNIT, STOP);
1572          reduce (q, NO_NOTE, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, SEMI_SYMBOL, LABELED_UNIT, STOP);
1573          reduce (q, NO_NOTE, &siga, INITIALISER_SERIES, INITIALISER_SERIES, SEMI_SYMBOL, DECLARATION_LIST, STOP);
1574  // Errors 
1575          reduce (q, strange_separator, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, COMMA_SYMBOL, UNIT, STOP);
1576          reduce (q, strange_separator, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, COMMA_SYMBOL, LABELED_UNIT, STOP);
1577          reduce (q, strange_separator, &siga, INITIALISER_SERIES, INITIALISER_SERIES, COMMA_SYMBOL, DECLARATION_LIST, STOP);
1578          reduce (q, strange_separator, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, COLON_SYMBOL, UNIT, STOP);
1579          reduce (q, strange_separator, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, COLON_SYMBOL, LABELED_UNIT, STOP);
1580          reduce (q, strange_separator, &siga, INITIALISER_SERIES, INITIALISER_SERIES, COLON_SYMBOL, DECLARATION_LIST, STOP);
1581          reduce (q, strange_separator, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, UNIT, STOP);
1582          reduce (q, strange_separator, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, LABELED_UNIT, STOP);
1583          reduce (q, strange_separator, &siga, INITIALISER_SERIES, INITIALISER_SERIES, DECLARATION_LIST, STOP);
1584        }
1585      }
1586      while (siga);
1587    }
1588  }
1589  
1590  //! @brief Reduce enquiry clauses.
1591  
1592  void reduce_enquiry_clauses (NODE_T * p)
1593  {
1594    if (NEXT (p) != NO_NODE) {
1595      NODE_T *q = NEXT (p);
1596      BOOL_T siga;
1597      reduce (q, NO_NOTE, NO_TICK, ENQUIRY_CLAUSE, UNIT, STOP);
1598      reduce (q, NO_NOTE, NO_TICK, INITIALISER_SERIES, DECLARATION_LIST, STOP);
1599      do {
1600        siga = A68G_FALSE;
1601        if (IS (q, ENQUIRY_CLAUSE)) {
1602          reduce (q, NO_NOTE, &siga, ENQUIRY_CLAUSE, ENQUIRY_CLAUSE, SEMI_SYMBOL, UNIT, STOP);
1603          reduce (q, NO_NOTE, &siga, INITIALISER_SERIES, ENQUIRY_CLAUSE, SEMI_SYMBOL, DECLARATION_LIST, STOP);
1604          reduce (q, strange_separator, &siga, ENQUIRY_CLAUSE, ENQUIRY_CLAUSE, COMMA_SYMBOL, UNIT, STOP);
1605          reduce (q, strange_separator, &siga, INITIALISER_SERIES, ENQUIRY_CLAUSE, COMMA_SYMBOL, DECLARATION_LIST, STOP);
1606          reduce (q, strange_separator, &siga, ENQUIRY_CLAUSE, ENQUIRY_CLAUSE, COLON_SYMBOL, UNIT, STOP);
1607          reduce (q, strange_separator, &siga, INITIALISER_SERIES, ENQUIRY_CLAUSE, COLON_SYMBOL, DECLARATION_LIST, STOP);
1608          reduce (q, strange_separator, &siga, ENQUIRY_CLAUSE, ENQUIRY_CLAUSE, UNIT, STOP);
1609          reduce (q, strange_separator, &siga, INITIALISER_SERIES, ENQUIRY_CLAUSE, DECLARATION_LIST, STOP);
1610        } else if (IS (q, INITIALISER_SERIES)) {
1611          reduce (q, NO_NOTE, &siga, ENQUIRY_CLAUSE, INITIALISER_SERIES, SEMI_SYMBOL, UNIT, STOP);
1612          reduce (q, NO_NOTE, &siga, INITIALISER_SERIES, INITIALISER_SERIES, SEMI_SYMBOL, DECLARATION_LIST, STOP);
1613          reduce (q, strange_separator, &siga, ENQUIRY_CLAUSE, INITIALISER_SERIES, COMMA_SYMBOL, UNIT, STOP);
1614          reduce (q, strange_separator, &siga, INITIALISER_SERIES, INITIALISER_SERIES, COMMA_SYMBOL, DECLARATION_LIST, STOP);
1615          reduce (q, strange_separator, &siga, ENQUIRY_CLAUSE, INITIALISER_SERIES, COLON_SYMBOL, UNIT, STOP);
1616          reduce (q, strange_separator, &siga, INITIALISER_SERIES, INITIALISER_SERIES, COLON_SYMBOL, DECLARATION_LIST, STOP);
1617          reduce (q, strange_separator, &siga, ENQUIRY_CLAUSE, INITIALISER_SERIES, UNIT, STOP);
1618          reduce (q, strange_separator, &siga, INITIALISER_SERIES, INITIALISER_SERIES, DECLARATION_LIST, STOP);
1619        }
1620      }
1621      while (siga);
1622    }
1623  }
1624  
1625  //! @brief Reduce collateral clauses.
1626  
1627  void reduce_collateral_clauses (NODE_T * p)
1628  {
1629    if (NEXT (p) != NO_NODE) {
1630      NODE_T *q = NEXT (p);
1631      if (IS (q, UNIT)) {
1632        BOOL_T siga;
1633        reduce (q, NO_NOTE, NO_TICK, UNIT_LIST, UNIT, STOP);
1634        do {
1635          siga = A68G_FALSE;
1636          reduce (q, NO_NOTE, &siga, UNIT_LIST, UNIT_LIST, COMMA_SYMBOL, UNIT, STOP);
1637          reduce (q, strange_separator, &siga, UNIT_LIST, UNIT_LIST, UNIT, STOP);
1638        } while (siga);
1639      } else if (IS (q, SPECIFIED_UNIT)) {
1640        BOOL_T siga;
1641        reduce (q, NO_NOTE, NO_TICK, SPECIFIED_UNIT_LIST, SPECIFIED_UNIT, STOP);
1642        do {
1643          siga = A68G_FALSE;
1644          reduce (q, NO_NOTE, &siga, SPECIFIED_UNIT_LIST, SPECIFIED_UNIT_LIST, COMMA_SYMBOL, SPECIFIED_UNIT, STOP);
1645          reduce (q, strange_separator, &siga, SPECIFIED_UNIT_LIST, SPECIFIED_UNIT_LIST, SPECIFIED_UNIT, STOP);
1646        } while (siga);
1647      }
1648    }
1649  }
1650  
1651  //! @brief Reduces enclosed clauses.
1652  
1653  void reduce_enclosed_clauses (NODE_T * q, int expect)
1654  {
1655    NODE_T *p = q;
1656    if (SUB (p) == NO_NODE) {
1657      if (IS (p, FOR_SYMBOL)) {
1658        reduce (p, NO_NOTE, NO_TICK, FOR_PART, FOR_SYMBOL, DEFINING_IDENTIFIER, STOP);
1659      } else if (IS (p, OPEN_SYMBOL)) {
1660        if (expect == ENQUIRY_CLAUSE) {
1661          reduce (p, NO_NOTE, NO_TICK, OPEN_PART, OPEN_SYMBOL, ENQUIRY_CLAUSE, STOP);
1662        } else if (expect == ARGUMENT) {
1663          reduce (p, NO_NOTE, NO_TICK, ARGUMENT, OPEN_SYMBOL, CLOSE_SYMBOL, STOP);
1664          reduce (p, NO_NOTE, NO_TICK, ARGUMENT, OPEN_SYMBOL, ARGUMENT_LIST, CLOSE_SYMBOL, STOP);
1665          reduce (p, empty_clause, NO_TICK, ARGUMENT, OPEN_SYMBOL, INITIALISER_SERIES, CLOSE_SYMBOL, STOP);
1666        } else if (expect == GENERIC_ARGUMENT) {
1667          if (whether (p, OPEN_SYMBOL, CLOSE_SYMBOL, STOP)) {
1668            pad_node (p, TRIMMER);
1669            reduce (p, NO_NOTE, NO_TICK, GENERIC_ARGUMENT, OPEN_SYMBOL, TRIMMER, CLOSE_SYMBOL, STOP);
1670          }
1671          reduce (p, NO_NOTE, NO_TICK, GENERIC_ARGUMENT, OPEN_SYMBOL, GENERIC_ARGUMENT_LIST, CLOSE_SYMBOL, STOP);
1672        } else if (expect == BOUNDS) {
1673          reduce (p, NO_NOTE, NO_TICK, FORMAL_BOUNDS, OPEN_SYMBOL, CLOSE_SYMBOL, STOP);
1674          reduce (p, NO_NOTE, NO_TICK, BOUNDS, OPEN_SYMBOL, BOUNDS_LIST, CLOSE_SYMBOL, STOP);
1675          reduce (p, NO_NOTE, NO_TICK, FORMAL_BOUNDS, OPEN_SYMBOL, FORMAL_BOUNDS_LIST, CLOSE_SYMBOL, STOP);
1676          reduce (p, NO_NOTE, NO_TICK, FORMAL_BOUNDS, OPEN_SYMBOL, ALT_FORMAL_BOUNDS_LIST, CLOSE_SYMBOL, STOP);
1677        } else {
1678          reduce (p, NO_NOTE, NO_TICK, CLOSED_CLAUSE, OPEN_SYMBOL, SERIAL_CLAUSE, CLOSE_SYMBOL, STOP);
1679          reduce (p, NO_NOTE, NO_TICK, COLLATERAL_CLAUSE, OPEN_SYMBOL, UNIT_LIST, CLOSE_SYMBOL, STOP);
1680          reduce (p, NO_NOTE, NO_TICK, COLLATERAL_CLAUSE, OPEN_SYMBOL, CLOSE_SYMBOL, STOP);
1681          reduce (p, empty_clause, NO_TICK, CLOSED_CLAUSE, OPEN_SYMBOL, INITIALISER_SERIES, CLOSE_SYMBOL, STOP);
1682        }
1683      } else if (IS (p, SUB_SYMBOL)) {
1684        if (expect == GENERIC_ARGUMENT) {
1685          if (whether (p, SUB_SYMBOL, BUS_SYMBOL, STOP)) {
1686            pad_node (p, TRIMMER);
1687            reduce (p, NO_NOTE, NO_TICK, GENERIC_ARGUMENT, SUB_SYMBOL, TRIMMER, BUS_SYMBOL, STOP);
1688          }
1689          reduce (p, NO_NOTE, NO_TICK, GENERIC_ARGUMENT, SUB_SYMBOL, GENERIC_ARGUMENT_LIST, BUS_SYMBOL, STOP);
1690        } else if (expect == BOUNDS) {
1691          reduce (p, NO_NOTE, NO_TICK, FORMAL_BOUNDS, SUB_SYMBOL, BUS_SYMBOL, STOP);
1692          reduce (p, NO_NOTE, NO_TICK, BOUNDS, SUB_SYMBOL, BOUNDS_LIST, BUS_SYMBOL, STOP);
1693          reduce (p, NO_NOTE, NO_TICK, FORMAL_BOUNDS, SUB_SYMBOL, FORMAL_BOUNDS_LIST, BUS_SYMBOL, STOP);
1694          reduce (p, NO_NOTE, NO_TICK, FORMAL_BOUNDS, SUB_SYMBOL, ALT_FORMAL_BOUNDS_LIST, BUS_SYMBOL, STOP);
1695        }
1696      } else if (IS (p, BEGIN_SYMBOL)) {
1697        reduce (p, NO_NOTE, NO_TICK, COLLATERAL_CLAUSE, BEGIN_SYMBOL, UNIT_LIST, END_SYMBOL, STOP);
1698        reduce (p, NO_NOTE, NO_TICK, COLLATERAL_CLAUSE, BEGIN_SYMBOL, END_SYMBOL, STOP);
1699        reduce (p, NO_NOTE, NO_TICK, CLOSED_CLAUSE, BEGIN_SYMBOL, SERIAL_CLAUSE, END_SYMBOL, STOP);
1700        reduce (p, empty_clause, NO_TICK, CLOSED_CLAUSE, BEGIN_SYMBOL, INITIALISER_SERIES, END_SYMBOL, STOP);
1701      } else if (IS (p, FORMAT_DELIMITER_SYMBOL)) {
1702        reduce (p, NO_NOTE, NO_TICK, FORMAT_TEXT, FORMAT_DELIMITER_SYMBOL, PICTURE_LIST, FORMAT_DELIMITER_SYMBOL, STOP);
1703        reduce (p, NO_NOTE, NO_TICK, FORMAT_TEXT, FORMAT_DELIMITER_SYMBOL, FORMAT_DELIMITER_SYMBOL, STOP);
1704      } else if (IS (p, FORMAT_OPEN_SYMBOL)) {
1705        reduce (p, NO_NOTE, NO_TICK, COLLECTION, FORMAT_OPEN_SYMBOL, PICTURE_LIST, FORMAT_CLOSE_SYMBOL, STOP);
1706      } else if (IS (p, IF_SYMBOL)) {
1707        reduce (p, NO_NOTE, NO_TICK, IF_PART, IF_SYMBOL, ENQUIRY_CLAUSE, STOP);
1708        reduce (p, empty_clause, NO_TICK, IF_PART, IF_SYMBOL, INITIALISER_SERIES, STOP);
1709      } else if (IS (p, THEN_SYMBOL)) {
1710        reduce (p, NO_NOTE, NO_TICK, THEN_PART, THEN_SYMBOL, SERIAL_CLAUSE, STOP);
1711        reduce (p, empty_clause, NO_TICK, THEN_PART, THEN_SYMBOL, INITIALISER_SERIES, STOP);
1712      } else if (IS (p, ELSE_SYMBOL)) {
1713        reduce (p, NO_NOTE, NO_TICK, ELSE_PART, ELSE_SYMBOL, SERIAL_CLAUSE, STOP);
1714        reduce (p, empty_clause, NO_TICK, ELSE_PART, ELSE_SYMBOL, INITIALISER_SERIES, STOP);
1715      } else if (IS (p, ELIF_SYMBOL)) {
1716        reduce (p, NO_NOTE, NO_TICK, ELIF_IF_PART, ELIF_SYMBOL, ENQUIRY_CLAUSE, STOP);
1717      } else if (IS (p, CASE_SYMBOL)) {
1718        reduce (p, NO_NOTE, NO_TICK, CASE_PART, CASE_SYMBOL, ENQUIRY_CLAUSE, STOP);
1719        reduce (p, empty_clause, NO_TICK, CASE_PART, CASE_SYMBOL, INITIALISER_SERIES, STOP);
1720      } else if (IS (p, IN_SYMBOL)) {
1721        reduce (p, NO_NOTE, NO_TICK, CASE_IN_PART, IN_SYMBOL, UNIT_LIST, STOP);
1722        reduce (p, NO_NOTE, NO_TICK, CONFORMITY_IN_PART, IN_SYMBOL, SPECIFIED_UNIT_LIST, STOP);
1723      } else if (IS (p, OUT_SYMBOL)) {
1724        reduce (p, NO_NOTE, NO_TICK, OUT_PART, OUT_SYMBOL, SERIAL_CLAUSE, STOP);
1725        reduce (p, empty_clause, NO_TICK, OUT_PART, OUT_SYMBOL, INITIALISER_SERIES, STOP);
1726      } else if (IS (p, OUSE_SYMBOL)) {
1727        reduce (p, NO_NOTE, NO_TICK, OUSE_PART, OUSE_SYMBOL, ENQUIRY_CLAUSE, STOP);
1728      } else if (IS (p, THEN_BAR_SYMBOL)) {
1729        reduce (p, NO_NOTE, NO_TICK, CHOICE, THEN_BAR_SYMBOL, SERIAL_CLAUSE, STOP);
1730        reduce (p, NO_NOTE, NO_TICK, CASE_CHOICE_CLAUSE, THEN_BAR_SYMBOL, UNIT_LIST, STOP);
1731        reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CHOICE, THEN_BAR_SYMBOL, SPECIFIED_UNIT_LIST, STOP);
1732        reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CHOICE, THEN_BAR_SYMBOL, SPECIFIED_UNIT, STOP);
1733        reduce (p, empty_clause, NO_TICK, CHOICE, THEN_BAR_SYMBOL, INITIALISER_SERIES, STOP);
1734      } else if (IS (p, ELSE_BAR_SYMBOL)) {
1735        reduce (p, NO_NOTE, NO_TICK, ELSE_OPEN_PART, ELSE_BAR_SYMBOL, ENQUIRY_CLAUSE, STOP);
1736        reduce (p, empty_clause, NO_TICK, ELSE_OPEN_PART, ELSE_BAR_SYMBOL, INITIALISER_SERIES, STOP);
1737      } else if (IS (p, FROM_SYMBOL)) {
1738        reduce (p, NO_NOTE, NO_TICK, FROM_PART, FROM_SYMBOL, UNIT, STOP);
1739      } else if (IS (p, BY_SYMBOL)) {
1740        reduce (p, NO_NOTE, NO_TICK, BY_PART, BY_SYMBOL, UNIT, STOP);
1741      } else if (IS (p, TO_SYMBOL)) {
1742        reduce (p, NO_NOTE, NO_TICK, TO_PART, TO_SYMBOL, UNIT, STOP);
1743      } else if (IS (p, DOWNTO_SYMBOL)) {
1744        reduce (p, NO_NOTE, NO_TICK, TO_PART, DOWNTO_SYMBOL, UNIT, STOP);
1745      } else if (IS (p, WHILE_SYMBOL)) {
1746        reduce (p, NO_NOTE, NO_TICK, WHILE_PART, WHILE_SYMBOL, ENQUIRY_CLAUSE, STOP);
1747        reduce (p, empty_clause, NO_TICK, WHILE_PART, WHILE_SYMBOL, INITIALISER_SERIES, STOP);
1748      } else if (IS (p, UNTIL_SYMBOL)) {
1749        reduce (p, NO_NOTE, NO_TICK, UNTIL_PART, UNTIL_SYMBOL, ENQUIRY_CLAUSE, STOP);
1750        reduce (p, empty_clause, NO_TICK, UNTIL_PART, UNTIL_SYMBOL, INITIALISER_SERIES, STOP);
1751      } else if (IS (p, DO_SYMBOL)) {
1752        reduce (p, NO_NOTE, NO_TICK, DO_PART, DO_SYMBOL, SERIAL_CLAUSE, UNTIL_PART, OD_SYMBOL, STOP);
1753        reduce (p, NO_NOTE, NO_TICK, DO_PART, DO_SYMBOL, SERIAL_CLAUSE, OD_SYMBOL, STOP);
1754        reduce (p, NO_NOTE, NO_TICK, DO_PART, DO_SYMBOL, UNTIL_PART, OD_SYMBOL, STOP);
1755      } else if (IS (p, ALT_DO_SYMBOL)) {
1756        reduce (p, NO_NOTE, NO_TICK, ALT_DO_PART, ALT_DO_SYMBOL, SERIAL_CLAUSE, UNTIL_PART, OD_SYMBOL, STOP);
1757        reduce (p, NO_NOTE, NO_TICK, ALT_DO_PART, ALT_DO_SYMBOL, SERIAL_CLAUSE, OD_SYMBOL, STOP);
1758        reduce (p, NO_NOTE, NO_TICK, ALT_DO_PART, ALT_DO_SYMBOL, UNTIL_PART, OD_SYMBOL, STOP);
1759      }
1760    }
1761    p = q;
1762    if (SUB (p) != NO_NODE) {
1763      if (IS (p, OPEN_PART)) {
1764        reduce (p, NO_NOTE, NO_TICK, CONDITIONAL_CLAUSE, OPEN_PART, CHOICE, CHOICE, CLOSE_SYMBOL, STOP);
1765        reduce (p, NO_NOTE, NO_TICK, CONDITIONAL_CLAUSE, OPEN_PART, CHOICE, CLOSE_SYMBOL, STOP);
1766        reduce (p, NO_NOTE, NO_TICK, CONDITIONAL_CLAUSE, OPEN_PART, CHOICE, BRIEF_ELIF_PART, STOP);
1767        reduce (p, NO_NOTE, NO_TICK, CASE_CLAUSE, OPEN_PART, CASE_CHOICE_CLAUSE, CHOICE, CLOSE_SYMBOL, STOP);
1768        reduce (p, NO_NOTE, NO_TICK, CASE_CLAUSE, OPEN_PART, CASE_CHOICE_CLAUSE, CLOSE_SYMBOL, STOP);
1769        reduce (p, NO_NOTE, NO_TICK, CASE_CLAUSE, OPEN_PART, CASE_CHOICE_CLAUSE, BRIEF_OUSE_PART, STOP);
1770        reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CLAUSE, OPEN_PART, CONFORMITY_CHOICE, CHOICE, CLOSE_SYMBOL, STOP);
1771        reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CLAUSE, OPEN_PART, CONFORMITY_CHOICE, CLOSE_SYMBOL, STOP);
1772        reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CLAUSE, OPEN_PART, CONFORMITY_CHOICE, BRIEF_CONFORMITY_OUSE_PART, STOP);
1773      } else if (IS (p, ELSE_OPEN_PART)) {
1774        reduce (p, NO_NOTE, NO_TICK, BRIEF_ELIF_PART, ELSE_OPEN_PART, CHOICE, CHOICE, CLOSE_SYMBOL, STOP);
1775        reduce (p, NO_NOTE, NO_TICK, BRIEF_ELIF_PART, ELSE_OPEN_PART, CHOICE, CLOSE_SYMBOL, STOP);
1776        reduce (p, NO_NOTE, NO_TICK, BRIEF_ELIF_PART, ELSE_OPEN_PART, CHOICE, BRIEF_ELIF_PART, STOP);
1777        reduce (p, NO_NOTE, NO_TICK, BRIEF_OUSE_PART, ELSE_OPEN_PART, CASE_CHOICE_CLAUSE, CHOICE, CLOSE_SYMBOL, STOP);
1778        reduce (p, NO_NOTE, NO_TICK, BRIEF_OUSE_PART, ELSE_OPEN_PART, CASE_CHOICE_CLAUSE, CLOSE_SYMBOL, STOP);
1779        reduce (p, NO_NOTE, NO_TICK, BRIEF_OUSE_PART, ELSE_OPEN_PART, CASE_CHOICE_CLAUSE, BRIEF_OUSE_PART, STOP);
1780        reduce (p, NO_NOTE, NO_TICK, BRIEF_CONFORMITY_OUSE_PART, ELSE_OPEN_PART, CONFORMITY_CHOICE, CHOICE, CLOSE_SYMBOL, STOP);
1781        reduce (p, NO_NOTE, NO_TICK, BRIEF_CONFORMITY_OUSE_PART, ELSE_OPEN_PART, CONFORMITY_CHOICE, CLOSE_SYMBOL, STOP);
1782        reduce (p, NO_NOTE, NO_TICK, BRIEF_CONFORMITY_OUSE_PART, ELSE_OPEN_PART, CONFORMITY_CHOICE, BRIEF_CONFORMITY_OUSE_PART, STOP);
1783      } else if (IS (p, IF_PART)) {
1784        reduce (p, NO_NOTE, NO_TICK, CONDITIONAL_CLAUSE, IF_PART, THEN_PART, ELSE_PART, FI_SYMBOL, STOP);
1785        reduce (p, NO_NOTE, NO_TICK, CONDITIONAL_CLAUSE, IF_PART, THEN_PART, ELIF_PART, STOP);
1786        reduce (p, NO_NOTE, NO_TICK, CONDITIONAL_CLAUSE, IF_PART, THEN_PART, FI_SYMBOL, STOP);
1787      } else if (IS (p, ELIF_IF_PART)) {
1788        reduce (p, NO_NOTE, NO_TICK, ELIF_PART, ELIF_IF_PART, THEN_PART, ELSE_PART, FI_SYMBOL, STOP);
1789        reduce (p, NO_NOTE, NO_TICK, ELIF_PART, ELIF_IF_PART, THEN_PART, FI_SYMBOL, STOP);
1790        reduce (p, NO_NOTE, NO_TICK, ELIF_PART, ELIF_IF_PART, THEN_PART, ELIF_PART, STOP);
1791      } else if (IS (p, CASE_PART)) {
1792        reduce (p, NO_NOTE, NO_TICK, CASE_CLAUSE, CASE_PART, CASE_IN_PART, OUT_PART, ESAC_SYMBOL, STOP);
1793        reduce (p, NO_NOTE, NO_TICK, CASE_CLAUSE, CASE_PART, CASE_IN_PART, ESAC_SYMBOL, STOP);
1794        reduce (p, NO_NOTE, NO_TICK, CASE_CLAUSE, CASE_PART, CASE_IN_PART, CASE_OUSE_PART, STOP);
1795        reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CLAUSE, CASE_PART, CONFORMITY_IN_PART, OUT_PART, ESAC_SYMBOL, STOP);
1796        reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CLAUSE, CASE_PART, CONFORMITY_IN_PART, ESAC_SYMBOL, STOP);
1797        reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CLAUSE, CASE_PART, CONFORMITY_IN_PART, CONFORMITY_OUSE_PART, STOP);
1798      } else if (IS (p, OUSE_PART)) {
1799        reduce (p, NO_NOTE, NO_TICK, CASE_OUSE_PART, OUSE_PART, CASE_IN_PART, OUT_PART, ESAC_SYMBOL, STOP);
1800        reduce (p, NO_NOTE, NO_TICK, CASE_OUSE_PART, OUSE_PART, CASE_IN_PART, ESAC_SYMBOL, STOP);
1801        reduce (p, NO_NOTE, NO_TICK, CASE_OUSE_PART, OUSE_PART, CASE_IN_PART, CASE_OUSE_PART, STOP);
1802        reduce (p, NO_NOTE, NO_TICK, CONFORMITY_OUSE_PART, OUSE_PART, CONFORMITY_IN_PART, OUT_PART, ESAC_SYMBOL, STOP);
1803        reduce (p, NO_NOTE, NO_TICK, CONFORMITY_OUSE_PART, OUSE_PART, CONFORMITY_IN_PART, ESAC_SYMBOL, STOP);
1804        reduce (p, NO_NOTE, NO_TICK, CONFORMITY_OUSE_PART, OUSE_PART, CONFORMITY_IN_PART, CONFORMITY_OUSE_PART, STOP);
1805      } else if (IS (p, FOR_PART)) {
1806        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, BY_PART, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
1807        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, BY_PART, WHILE_PART, ALT_DO_PART, STOP);
1808        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
1809        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, WHILE_PART, ALT_DO_PART, STOP);
1810        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, BY_PART, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
1811        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, BY_PART, WHILE_PART, ALT_DO_PART, STOP);
1812        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
1813        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, WHILE_PART, ALT_DO_PART, STOP);
1814        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, BY_PART, TO_PART, ALT_DO_PART, STOP);
1815        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, BY_PART, ALT_DO_PART, STOP);
1816        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, TO_PART, ALT_DO_PART, STOP);
1817        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, ALT_DO_PART, STOP);
1818        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, BY_PART, TO_PART, ALT_DO_PART, STOP);
1819        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, BY_PART, ALT_DO_PART, STOP);
1820        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, TO_PART, ALT_DO_PART, STOP);
1821        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, ALT_DO_PART, STOP);
1822      } else if (IS (p, FROM_PART)) {
1823        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, BY_PART, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
1824        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, BY_PART, WHILE_PART, ALT_DO_PART, STOP);
1825        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
1826        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, WHILE_PART, ALT_DO_PART, STOP);
1827        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, BY_PART, TO_PART, ALT_DO_PART, STOP);
1828        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, BY_PART, ALT_DO_PART, STOP);
1829        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, TO_PART, ALT_DO_PART, STOP);
1830        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, ALT_DO_PART, STOP);
1831      } else if (IS (p, BY_PART)) {
1832        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, BY_PART, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
1833        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, BY_PART, WHILE_PART, ALT_DO_PART, STOP);
1834        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, BY_PART, TO_PART, ALT_DO_PART, STOP);
1835        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, BY_PART, ALT_DO_PART, STOP);
1836      } else if (IS (p, TO_PART)) {
1837        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
1838        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, TO_PART, ALT_DO_PART, STOP);
1839      } else if (IS (p, WHILE_PART)) {
1840        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, WHILE_PART, ALT_DO_PART, STOP);
1841      } else if (IS (p, DO_PART)) {
1842        reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, DO_PART, STOP);
1843      }
1844    }
1845  }
1846  
1847  //! @brief Substitute reduction when a phrase could not be parsed.
1848  
1849  void recover_from_error (NODE_T * p, int expect, BOOL_T suppress)
1850  {
1851  // This routine does not do fancy things as that might introduce more errors.
1852    NODE_T *q = p;
1853    if (p == NO_NODE) {
1854      return;
1855    }
1856    if (expect == 0) {
1857      expect = serial_or_collateral (p);
1858    }
1859    if (!suppress) {
1860  // Give an error message.
1861      NODE_T *w = p;
1862      char *seq = phrase_to_text (p, &w);
1863      if (strlen (seq) == 0) {
1864        if (ERROR_COUNT (&A68G_JOB) == 0) {
1865          diagnostic (A68G_SYNTAX_ERROR, w, ERROR_SYNTAX_EXPECTED, expect);
1866        }
1867      } else {
1868        diagnostic (A68G_SYNTAX_ERROR, w, ERROR_SYNTAX_SENTENCE, seq);
1869      }
1870      if (ERROR_COUNT (&A68G_JOB) >= MAX_ERRORS) {
1871        longjmp (A68G_PARSER (bottom_up_crash_exit), 1);
1872      }
1873    }
1874  // Try to prevent spurious diagnostics by guessing what was expected.
1875    while (NEXT (q) != NO_NODE) {
1876      FORWARD (q);
1877    }
1878    if (is_one_of (p, BEGIN_SYMBOL, OPEN_SYMBOL, STOP)) {
1879      if (expect == ARGUMENT || expect == COLLATERAL_CLAUSE || expect == PARAMETER_PACK || expect == STRUCTURE_PACK || expect == UNION_PACK) {
1880        make_sub (p, q, expect);
1881      } else if (expect == ENQUIRY_CLAUSE) {
1882        make_sub (p, q, OPEN_PART);
1883      } else if (expect == FORMAL_DECLARERS) {
1884        make_sub (p, q, FORMAL_DECLARERS);
1885      } else {
1886        make_sub (p, q, CLOSED_CLAUSE);
1887      }
1888    } else if (IS (p, FORMAT_DELIMITER_SYMBOL) && expect == FORMAT_TEXT) {
1889      make_sub (p, q, FORMAT_TEXT);
1890    } else if (IS (p, CODE_SYMBOL)) {
1891      make_sub (p, q, CODE_CLAUSE);
1892    } else if (is_one_of (p, THEN_BAR_SYMBOL, CHOICE, STOP)) {
1893      make_sub (p, q, CHOICE);
1894    } else if (is_one_of (p, IF_SYMBOL, IF_PART, STOP)) {
1895      make_sub (p, q, IF_PART);
1896    } else if (is_one_of (p, THEN_SYMBOL, THEN_PART, STOP)) {
1897      make_sub (p, q, THEN_PART);
1898    } else if (is_one_of (p, ELSE_SYMBOL, ELSE_PART, STOP)) {
1899      make_sub (p, q, ELSE_PART);
1900    } else if (is_one_of (p, ELIF_SYMBOL, ELIF_IF_PART, STOP)) {
1901      make_sub (p, q, ELIF_IF_PART);
1902    } else if (is_one_of (p, CASE_SYMBOL, CASE_PART, STOP)) {
1903      make_sub (p, q, CASE_PART);
1904    } else if (is_one_of (p, OUT_SYMBOL, OUT_PART, STOP)) {
1905      make_sub (p, q, OUT_PART);
1906    } else if (is_one_of (p, OUSE_SYMBOL, OUSE_PART, STOP)) {
1907      make_sub (p, q, OUSE_PART);
1908    } else if (is_one_of (p, FOR_SYMBOL, FOR_PART, STOP)) {
1909      make_sub (p, q, FOR_PART);
1910    } else if (is_one_of (p, FROM_SYMBOL, FROM_PART, STOP)) {
1911      make_sub (p, q, FROM_PART);
1912    } else if (is_one_of (p, BY_SYMBOL, BY_PART, STOP)) {
1913      make_sub (p, q, BY_PART);
1914    } else if (is_one_of (p, TO_SYMBOL, DOWNTO_SYMBOL, TO_PART, STOP)) {
1915      make_sub (p, q, TO_PART);
1916    } else if (is_one_of (p, WHILE_SYMBOL, WHILE_PART, STOP)) {
1917      make_sub (p, q, WHILE_PART);
1918    } else if (is_one_of (p, UNTIL_SYMBOL, UNTIL_PART, STOP)) {
1919      make_sub (p, q, UNTIL_PART);
1920    } else if (is_one_of (p, DO_SYMBOL, DO_PART, STOP)) {
1921      make_sub (p, q, DO_PART);
1922    } else if (is_one_of (p, ALT_DO_SYMBOL, ALT_DO_PART, STOP)) {
1923      make_sub (p, q, ALT_DO_PART);
1924    } else if (non_terminal_string (A68G (edit_line), expect) != NO_TEXT) {
1925      make_sub (p, q, expect);
1926    }
1927  }
1928  
1929  //! @brief Heuristic aid in pinpointing errors.
1930  
1931  void reduce_erroneous_units (NODE_T * p)
1932  {
1933  // Constructs are reduced to units in an attempt to limit spurious diagnostics.
1934    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1935  // Some implementations allow selection from a tertiary, when there is no risk
1936  // of ambiguity. Algol68G follows RR, so some extra attention here to guide an
1937  // unsuspecting user.
1938      if (whether (q, SELECTOR, -SECONDARY, STOP)) {
1939        diagnostic (A68G_SYNTAX_ERROR, NEXT (q), ERROR_SYNTAX_EXPECTED, SECONDARY);
1940        reduce (q, NO_NOTE, NO_TICK, UNIT, SELECTOR, WILDCARD, STOP);
1941      }
1942  // Attention for identity relations that require tertiaries.
1943      if (whether (q, -TERTIARY, IS_SYMBOL, TERTIARY, STOP) || whether (q, TERTIARY, IS_SYMBOL, -TERTIARY, STOP) || whether (q, -TERTIARY, IS_SYMBOL, -TERTIARY, STOP)) {
1944        diagnostic (A68G_SYNTAX_ERROR, NEXT (q), ERROR_SYNTAX_EXPECTED, TERTIARY);
1945        reduce (q, NO_NOTE, NO_TICK, UNIT, WILDCARD, IS_SYMBOL, WILDCARD, STOP);
1946      } else if (whether (q, -TERTIARY, ISNT_SYMBOL, TERTIARY, STOP) || whether (q, TERTIARY, ISNT_SYMBOL, -TERTIARY, STOP) || whether (q, -TERTIARY, ISNT_SYMBOL, -TERTIARY, STOP)) {
1947        diagnostic (A68G_SYNTAX_ERROR, NEXT (q), ERROR_SYNTAX_EXPECTED, TERTIARY);
1948        reduce (q, NO_NOTE, NO_TICK, UNIT, WILDCARD, ISNT_SYMBOL, WILDCARD, STOP);
1949      }
1950    }
1951  }
1952  
1953  // A posteriori checks of the syntax tree built by the BU parser.
1954  
1955  //! @brief Driver for a posteriori error checking.
1956  
1957  void bottom_up_error_check (NODE_T * p)
1958  {
1959    for (; p != NO_NODE; FORWARD (p)) {
1960      if (IS (p, BOOLEAN_PATTERN)) {
1961        int k = 0;
1962        count_pictures (SUB (p), &k);
1963        if (!(k == 0 || k == 2)) {
1964          diagnostic (A68G_SYNTAX_ERROR, p, ERROR_FORMAT_PICTURE_NUMBER, ATTRIBUTE (p));
1965        }
1966      } else {
1967        bottom_up_error_check (SUB (p));
1968      }
1969    }
1970  }
1971  
1972  // Next part rearranges and checks the tree after the symbol tables are finished.
1973  
1974  //! @brief Transfer IDENTIFIER to JUMP where appropriate.
1975  
1976  void rearrange_goto_less_jumps (NODE_T * p)
1977  {
1978    for (; p != NO_NODE; FORWARD (p)) {
1979      if (IS (p, UNIT)) {
1980        NODE_T *q = SUB (p);
1981        if (IS (q, TERTIARY)) {
1982          NODE_T *tertiary = q;
1983          q = SUB (q);
1984          if (q != NO_NODE && IS (q, SECONDARY)) {
1985            q = SUB (q);
1986            if (q != NO_NODE && IS (q, PRIMARY)) {
1987              q = SUB (q);
1988              if (q != NO_NODE && IS (q, IDENTIFIER)) {
1989                if (is_identifier_or_label_global (TABLE (q), NSYMBOL (q)) == LABEL) {
1990                  ATTRIBUTE (tertiary) = JUMP;
1991                  SUB (tertiary) = q;
1992                }
1993              }
1994            }
1995          }
1996        }
1997      } else if (IS (p, TERTIARY)) {
1998        NODE_T *q = SUB (p);
1999        if (q != NO_NODE && IS (q, SECONDARY)) {
2000          NODE_T *secondary = q;
2001          q = SUB (q);
2002          if (q != NO_NODE && IS (q, PRIMARY)) {
2003            q = SUB (q);
2004            if (q != NO_NODE && IS (q, IDENTIFIER)) {
2005              if (is_identifier_or_label_global (TABLE (q), NSYMBOL (q)) == LABEL) {
2006                ATTRIBUTE (secondary) = JUMP;
2007                SUB (secondary) = q;
2008              }
2009            }
2010          }
2011        }
2012      } else if (IS (p, SECONDARY)) {
2013        NODE_T *q = SUB (p);
2014        if (q != NO_NODE && IS (q, PRIMARY)) {
2015          NODE_T *primary = q;
2016          q = SUB (q);
2017          if (q != NO_NODE && IS (q, IDENTIFIER)) {
2018            if (is_identifier_or_label_global (TABLE (q), NSYMBOL (q)) == LABEL) {
2019              ATTRIBUTE (primary) = JUMP;
2020              SUB (primary) = q;
2021            }
2022          }
2023        }
2024      } else if (IS (p, PRIMARY)) {
2025        NODE_T *q = SUB (p);
2026        if (q != NO_NODE && IS (q, IDENTIFIER)) {
2027          if (is_identifier_or_label_global (TABLE (q), NSYMBOL (q)) == LABEL) {
2028            make_sub (q, q, JUMP);
2029          }
2030        }
2031      }
2032      rearrange_goto_less_jumps (SUB (p));
2033    }
2034  }
     


© 2002-2026 J.M. van der Veer (jmvdveer@xs4all.nl)