parser.c

     
   1  //! @file parser.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-2023 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  //! Mailloux-type Algol 68 parser driver.
  25  
  26  // The Algol 68 grammar is a two level (Van Wijngaarden, "VW") grammar 
  27  // that incorporates, as syntactical rules, the semantical rules in 
  28  // other languages. Examples are correct use of symbols, modes and scope.
  29  // 
  30  // This code constitutes an effective "VW Algol 68 parser". A pragmatic
  31  // approach was chosen since in the early days of Algol 68, many "ab initio" 
  32  // implementations failed, probably because techniques to parse a language
  33  // like Algol 68 had yet to be invented.
  34  // 
  35  // This is a Mailloux-type parser, in the sense that it scans a "phrase" for
  36  // definitions needed for parsing. Algol 68 allows for tags to be used
  37  // before they are defined, which gives freedom in top-down programming.
  38  // 
  39  //    B. J. Mailloux. On the implementation of Algol 68.
  40  //    Thesis, Universiteit van Amsterdam (Mathematisch Centrum) [1968].
  41  // 
  42  // Technically, Mailloux's approach renders the two-level grammar LALR.
  43  // 
  44  // First part of the parser is the scanner. The source file is read,
  45  // is tokenised, and if needed a refinement preprocessor elaborates a stepwise
  46  // refined program. The result is a linear list of tokens that is input for the
  47  // parser, that will transform the linear list into a syntax tree.
  48  // 
  49  // Algol68G tokenises all symbols before the bottom-up parser is invoked. 
  50  // This means that scanning does not use information from the parser.
  51  // The scanner does of course some rudimentary parsing. Format texts can have
  52  // enclosed clauses in them, so we record information in a stack as to know
  53  // what is being scanned. Also, the refinement preprocessor implements a
  54  // (trivial) grammar.
  55  // 
  56  // The scanner supports two stropping regimes: "bold" (or "upper") and "quote". 
  57  // Examples of both:
  58  // 
  59  //    bold stropping: BEGIN INT i = 1, j = 1; print (i + j) END
  60  // 
  61  //    quote stropping: 'BEGIN' 'INT' I = 1, J = 1; PRINT (I + J) 'END'
  62  // 
  63  // Quote stropping was used frequently in the (excusez-le-mot) punch-card age.
  64  // Hence, bold stropping is the default. There also existed point stropping, 
  65  // but that has not been implemented here.
  66  // 
  67  // Next part of the parser is a recursive-descent type to check parenthesis.
  68  // Also a first set-up is made of symbol tables, needed by the bottom-up parser.
  69  // Next part is the bottom-up parser, that parses without knowing modes while
  70  // parsing and reducing. It can therefore not exchange "[]" with "()" as was
  71  // blessed by the Revised Report. This is solved by treating CALL and SLICE as
  72  // equivalent for the moment and letting the mode checker sort it out later.
  73  // 
  74  // Parsing progresses in various phases to avoid spurious diagnostics from a
  75  // recovering parser. Every phase "tightens" the grammar more.
  76  // An error in any phase makes the parser quit when that phase ends.
  77  // The parser is forgiving in case of superfluous semicolons.
  78  // 
  79  // These are the parser phases:
  80  // 
  81  //  (1) Parenthesis are checked to see whether they match. Then, a top-down 
  82  //      parser determines the basic-block structure of the program
  83  //      so symbol tables can be set up that the bottom-up parser will consult
  84  //      as you can define things before they are applied.
  85  // 
  86  //  (2) A bottom-up parser resolves the structure of the program.
  87  // 
  88  //  (3) After the symbol tables have been finalised, a small rearrangement of the
  89  //      tree may be required where JUMPs have no GOTO. This leads to the
  90  //      non-standard situation that JUMPs without GOTO can have the syntactic
  91  //      position of a PRIMARY, SECONDARY or TERTIARY. The bottom-up parser also
  92  //      does not check VICTAL correctness of declarers. This is done separately. 
  93  //      Also structure of format texts is checked separately.
  94  // 
  95  // The parser sets up symbol tables and populates them as far as needed to parse
  96  // the source. After the bottom-up parser terminates succesfully, the symbol tables
  97  // are completed.
  98  // 
  99  //  (4) Next, modes are collected and rules for well-formedness and structural 
 100  //      equivalence are applied. Then the symbol-table is completed now moids are 
 101  //      all known.
 102  // 
 103  //  (5) Next phases are the mode checker and coercion inserter. The syntax tree is 
 104  //      traversed to determine and check all modes, and to select operators. Then 
 105  //      the tree is traversed again to insert coercions.
 106  // 
 107  //  (6) A static scope checker detects where objects are transported out of scope.
 108  //      At run time, a dynamic scope checker will check that what the static scope 
 109  //      checker cannot see.
 110  
 111  #include "a68g.h"
 112  #include "a68g-parser.h"
 113  #include "a68g-mp.h"
 114  #include "a68g-postulates.h"
 115  #include "a68g-prelude.h"
 116  
 117  //! @brief First initialisations.
 118  
 119  void init_before_tokeniser (void)
 120  {
 121  // Heap management set-up.
 122    errno = 0;
 123    init_heap ();
 124    A68 (top_keyword) = NO_KEYWORD;
 125    A68 (top_token) = NO_TOKEN;
 126    TOP_NODE (&A68_JOB) = NO_NODE;
 127    TOP_MOID (&A68_JOB) = NO_MOID;
 128    TOP_LINE (&A68_JOB) = NO_LINE;
 129    STANDENV_MOID (&A68_JOB) = NO_MOID;
 130    set_up_tables ();
 131  // Various initialisations.
 132    ERROR_COUNT (&A68_JOB) = WARNING_COUNT (&A68_JOB) = 0;
 133    ABEND (errno != 0, ERROR_ALLOCATION, __func__);
 134    errno = 0;
 135  }
 136  
 137  void init_parser (void)
 138  {
 139    A68_PARSER (stop_scanner) = A68_FALSE;
 140    A68_PARSER (read_error) = A68_FALSE;
 141    A68_PARSER (no_preprocessing) = A68_FALSE;
 142  }
 143  
 144  //! @brief Is_ref_refety_flex.
 145  
 146  BOOL_T is_ref_refety_flex (MOID_T * m)
 147  {
 148    if (IS_REF_FLEX (m)) {
 149      return A68_TRUE;
 150    } else if (IS_REF (m)) {
 151      return is_ref_refety_flex (SUB (m));
 152    } else {
 153      return A68_FALSE;
 154    }
 155  }
 156  
 157  //! @brief Count number of operands in operator parameter list.
 158  
 159  int count_operands (NODE_T * p)
 160  {
 161    if (p != NO_NODE) {
 162      if (IS (p, DECLARER)) {
 163        return count_operands (NEXT (p));
 164      } else if (IS (p, COMMA_SYMBOL)) {
 165        return 1 + count_operands (NEXT (p));
 166      } else {
 167        return count_operands (NEXT (p)) + count_operands (SUB (p));
 168      }
 169    } else {
 170      return 0;
 171    }
 172  }
 173  
 174  //! @brief Count formal bounds in declarer in tree.
 175  
 176  int count_formal_bounds (NODE_T * p)
 177  {
 178    if (p == NO_NODE) {
 179      return 0;
 180    } else {
 181      if (IS (p, COMMA_SYMBOL)) {
 182        return 1;
 183      } else {
 184        return count_formal_bounds (NEXT (p)) + count_formal_bounds (SUB (p));
 185      }
 186    }
 187  }
 188  
 189  //! @brief Count pictures.
 190  
 191  void count_pictures (NODE_T * p, int *k)
 192  {
 193    for (; p != NO_NODE; FORWARD (p)) {
 194      if (IS (p, PICTURE)) {
 195        (*k)++;
 196      }
 197      count_pictures (SUB (p), k);
 198    }
 199  }
 200  
 201  //! @brief Whether token cannot follow semicolon or EXIT.
 202  
 203  BOOL_T is_semicolon_less (NODE_T * p)
 204  {
 205    switch (ATTRIBUTE (p)) {
 206    case BUS_SYMBOL:
 207    case CLOSE_SYMBOL:
 208    case END_SYMBOL:
 209    case SEMI_SYMBOL:
 210    case EXIT_SYMBOL:
 211    case THEN_BAR_SYMBOL:
 212    case ELSE_BAR_SYMBOL:
 213    case THEN_SYMBOL:
 214    case ELIF_SYMBOL:
 215    case ELSE_SYMBOL:
 216    case FI_SYMBOL:
 217    case IN_SYMBOL:
 218    case OUT_SYMBOL:
 219    case OUSE_SYMBOL:
 220    case ESAC_SYMBOL:
 221    case EDOC_SYMBOL:
 222    case OCCA_SYMBOL:
 223    case OD_SYMBOL:
 224    case UNTIL_SYMBOL:
 225      {
 226        return A68_TRUE;
 227      }
 228    default:
 229      {
 230        return A68_FALSE;
 231      }
 232    }
 233  }
 234  
 235  //! @brief Whether formal bounds.
 236  
 237  BOOL_T is_formal_bounds (NODE_T * p)
 238  {
 239    if (p == NO_NODE) {
 240      return A68_TRUE;
 241    } else {
 242      switch (ATTRIBUTE (p)) {
 243      case OPEN_SYMBOL:
 244      case CLOSE_SYMBOL:
 245      case SUB_SYMBOL:
 246      case BUS_SYMBOL:
 247      case COMMA_SYMBOL:
 248      case COLON_SYMBOL:
 249      case DOTDOT_SYMBOL:
 250      case INT_DENOTATION:
 251      case IDENTIFIER:
 252      case OPERATOR:
 253        {
 254          return (BOOL_T) (is_formal_bounds (SUB (p)) && is_formal_bounds (NEXT (p)));
 255        }
 256      default:
 257        {
 258          return A68_FALSE;
 259        }
 260      }
 261    }
 262  }
 263  
 264  //! @brief Whether token terminates a unit.
 265  
 266  BOOL_T is_unit_terminator (NODE_T * p)
 267  {
 268    switch (ATTRIBUTE (p)) {
 269    case BUS_SYMBOL:
 270    case CLOSE_SYMBOL:
 271    case END_SYMBOL:
 272    case SEMI_SYMBOL:
 273    case EXIT_SYMBOL:
 274    case COMMA_SYMBOL:
 275    case THEN_BAR_SYMBOL:
 276    case ELSE_BAR_SYMBOL:
 277    case THEN_SYMBOL:
 278    case ELIF_SYMBOL:
 279    case ELSE_SYMBOL:
 280    case FI_SYMBOL:
 281    case IN_SYMBOL:
 282    case OUT_SYMBOL:
 283    case OUSE_SYMBOL:
 284    case ESAC_SYMBOL:
 285    case EDOC_SYMBOL:
 286    case OCCA_SYMBOL:
 287      {
 288        return A68_TRUE;
 289      }
 290    }
 291    return A68_FALSE;
 292  }
 293  
 294  //! @brief Whether token is a unit-terminator in a loop clause.
 295  
 296  BOOL_T is_loop_keyword (NODE_T * p)
 297  {
 298    switch (ATTRIBUTE (p)) {
 299    case FOR_SYMBOL:
 300    case FROM_SYMBOL:
 301    case BY_SYMBOL:
 302    case TO_SYMBOL:
 303    case DOWNTO_SYMBOL:
 304    case WHILE_SYMBOL:
 305    case DO_SYMBOL:
 306      {
 307        return A68_TRUE;
 308      }
 309    }
 310    return A68_FALSE;
 311  }
 312  
 313  //! @brief Get good attribute.
 314  
 315  int get_good_attribute (NODE_T * p)
 316  {
 317    switch (ATTRIBUTE (p)) {
 318    case UNIT:
 319    case TERTIARY:
 320    case SECONDARY:
 321    case PRIMARY:
 322      {
 323        return get_good_attribute (SUB (p));
 324      }
 325    default:
 326      {
 327        return ATTRIBUTE (p);
 328      }
 329    }
 330  }
 331  
 332  //! @brief Preferably don't put intelligible diagnostic here.
 333  
 334  BOOL_T dont_mark_here (NODE_T * p)
 335  {
 336    switch (ATTRIBUTE (p)) {
 337    case ACCO_SYMBOL:
 338    case ALT_DO_SYMBOL:
 339    case ALT_EQUALS_SYMBOL:
 340    case ANDF_SYMBOL:
 341    case ASSERT_SYMBOL:
 342    case ASSIGN_SYMBOL:
 343    case ASSIGN_TO_SYMBOL:
 344    case AT_SYMBOL:
 345    case BEGIN_SYMBOL:
 346    case BITS_SYMBOL:
 347    case BOLD_COMMENT_SYMBOL:
 348    case BOLD_PRAGMAT_SYMBOL:
 349    case BOOL_SYMBOL:
 350    case BUS_SYMBOL:
 351    case BY_SYMBOL:
 352    case BYTES_SYMBOL:
 353    case CASE_SYMBOL:
 354    case CHANNEL_SYMBOL:
 355    case CHAR_SYMBOL:
 356    case CLOSE_SYMBOL:
 357    case CODE_SYMBOL:
 358    case COLON_SYMBOL:
 359    case COLUMN_SYMBOL:
 360    case COMMA_SYMBOL:
 361    case COMPLEX_SYMBOL:
 362    case COMPL_SYMBOL:
 363    case DIAGONAL_SYMBOL:
 364    case DO_SYMBOL:
 365    case DOTDOT_SYMBOL:
 366    case DOWNTO_SYMBOL:
 367    case EDOC_SYMBOL:
 368    case ELIF_SYMBOL:
 369    case ELSE_BAR_SYMBOL:
 370    case ELSE_SYMBOL:
 371    case EMPTY_SYMBOL:
 372    case END_SYMBOL:
 373    case ENVIRON_SYMBOL:
 374    case EQUALS_SYMBOL:
 375    case ESAC_SYMBOL:
 376    case EXIT_SYMBOL:
 377    case FALSE_SYMBOL:
 378    case FILE_SYMBOL:
 379    case FI_SYMBOL:
 380    case FLEX_SYMBOL:
 381    case FORMAT_DELIMITER_SYMBOL:
 382    case FORMAT_SYMBOL:
 383    case FOR_SYMBOL:
 384    case FROM_SYMBOL:
 385    case GO_SYMBOL:
 386    case GOTO_SYMBOL:
 387    case HEAP_SYMBOL:
 388    case IF_SYMBOL:
 389    case IN_SYMBOL:
 390    case INT_SYMBOL:
 391    case ISNT_SYMBOL:
 392    case IS_SYMBOL:
 393    case LOC_SYMBOL:
 394    case LONG_SYMBOL:
 395    case MAIN_SYMBOL:
 396    case MODE_SYMBOL:
 397    case NIL_SYMBOL:
 398    case OCCA_SYMBOL:
 399    case OD_SYMBOL:
 400    case OF_SYMBOL:
 401    case OPEN_SYMBOL:
 402    case OP_SYMBOL:
 403    case ORF_SYMBOL:
 404    case OUSE_SYMBOL:
 405    case OUT_SYMBOL:
 406    case PAR_SYMBOL:
 407    case PIPE_SYMBOL:
 408    case POINT_SYMBOL:
 409    case PRIO_SYMBOL:
 410    case PROC_SYMBOL:
 411    case REAL_SYMBOL:
 412    case REF_SYMBOL:
 413    case ROWS_SYMBOL:
 414    case ROW_SYMBOL:
 415    case SEMA_SYMBOL:
 416    case SEMI_SYMBOL:
 417    case SHORT_SYMBOL:
 418    case SKIP_SYMBOL:
 419    case SOUND_SYMBOL:
 420    case STRING_SYMBOL:
 421    case STRUCT_SYMBOL:
 422    case STYLE_I_COMMENT_SYMBOL:
 423    case STYLE_II_COMMENT_SYMBOL:
 424    case STYLE_I_PRAGMAT_SYMBOL:
 425    case SUB_SYMBOL:
 426    case THEN_BAR_SYMBOL:
 427    case THEN_SYMBOL:
 428    case TO_SYMBOL:
 429    case TRANSPOSE_SYMBOL:
 430    case TRUE_SYMBOL:
 431    case UNION_SYMBOL:
 432    case UNTIL_SYMBOL:
 433    case VOID_SYMBOL:
 434    case WHILE_SYMBOL:
 435    case SERIAL_CLAUSE:
 436    case ENQUIRY_CLAUSE:
 437    case INITIALISER_SERIES:
 438    case DECLARATION_LIST:
 439      {
 440        return A68_TRUE;
 441      }
 442    }
 443    return A68_FALSE;
 444  }
 445  
 446  void a68_parser (void)
 447  {
 448  // Tokeniser.
 449    int renum;
 450    FILE_SOURCE_OPENED (&A68_JOB) = A68_TRUE;
 451    announce_phase ("initialiser");
 452    A68_PARSER (error_tag) = (TAG_T *) new_tag ();
 453    init_parser ();
 454    if (ERROR_COUNT (&A68_JOB) == 0) {
 455      int frame_stack_size_2 = A68 (frame_stack_size);
 456      int expr_stack_size_2 = A68 (expr_stack_size);
 457      int heap_size_2 = A68 (heap_size);
 458      int handle_pool_size_2 = A68 (handle_pool_size);
 459      BOOL_T ok;
 460      announce_phase ("tokeniser");
 461      ok = lexical_analyser ();
 462      if (!ok || errno != 0) {
 463        diagnostics_to_terminal (TOP_LINE (&A68_JOB), A68_ALL_DIAGNOSTICS);
 464        return;
 465      }
 466  // Maybe the program asks for more memory through a PRAGMAT. We restart.
 467      if (frame_stack_size_2 != A68 (frame_stack_size) || expr_stack_size_2 != A68 (expr_stack_size) || heap_size_2 != A68 (heap_size) || handle_pool_size_2 != A68 (handle_pool_size)) {
 468        announce_phase ("tokeniser");
 469        free_syntax_tree (TOP_NODE (&A68_JOB));
 470        discard_heap ();
 471        init_before_tokeniser ();
 472        SOURCE_SCAN (&A68_JOB)++;
 473        ok = lexical_analyser ();
 474        verbosity ();
 475      }
 476      if (!ok || errno != 0) {
 477        diagnostics_to_terminal (TOP_LINE (&A68_JOB), A68_ALL_DIAGNOSTICS);
 478        return;
 479      }
 480      ASSERT (close (FILE_SOURCE_FD (&A68_JOB)) == 0);
 481      FILE_SOURCE_OPENED (&A68_JOB) = A68_FALSE;
 482      prune_echoes (OPTION_LIST (&A68_JOB));
 483      TREE_LISTING_SAFE (&A68_JOB) = A68_TRUE;
 484      renum = 0;
 485      renumber_nodes (TOP_NODE (&A68_JOB), &renum);
 486    }
 487  // Now the default precision of LONG LONG modes is fixed.
 488    if (long_mp_digits () == 0) {
 489      set_long_mp_digits (LONG_LONG_MP_DIGITS);
 490    }
 491  // Final initialisations.
 492    if (ERROR_COUNT (&A68_JOB) == 0) {
 493      if (OPTION_REGRESSION_TEST (&A68_JOB)) {
 494        bufcpy (A68 (a68_cmd_name), "a68g", BUFFER_SIZE);
 495        io_close_tty_line ();
 496        WRITE (STDERR_FILENO, "[");
 497        WRITE (STDERR_FILENO, FILE_INITIAL_NAME (&A68_JOB));
 498        WRITE (STDERR_FILENO, "]\n");
 499      }
 500      A68_STANDENV = NO_TABLE;
 501      init_postulates ();
 502      A68 (mode_count) = 0;
 503      make_special_mode (&M_HIP, A68 (mode_count)++);
 504      make_special_mode (&M_UNDEFINED, A68 (mode_count)++);
 505      make_special_mode (&M_ERROR, A68 (mode_count)++);
 506      make_special_mode (&M_VACUUM, A68 (mode_count)++);
 507      make_special_mode (&M_C_STRING, A68 (mode_count)++);
 508      make_special_mode (&M_COLLITEM, A68 (mode_count)++);
 509      make_special_mode (&M_SOUND_DATA, A68 (mode_count)++);
 510    }
 511  // Refinement preprocessor.
 512    if (ERROR_COUNT (&A68_JOB) == 0) {
 513      announce_phase ("preprocessor");
 514      get_refinements ();
 515      if (ERROR_COUNT (&A68_JOB) == 0) {
 516        put_refinements ();
 517      }
 518      renum = 0;
 519      renumber_nodes (TOP_NODE (&A68_JOB), &renum);
 520      verbosity ();
 521    }
 522  // Top-down parser.
 523    if (ERROR_COUNT (&A68_JOB) == 0) {
 524      announce_phase ("parser phase 1");
 525      check_parenthesis (TOP_NODE (&A68_JOB));
 526      if (ERROR_COUNT (&A68_JOB) == 0) {
 527        if (OPTION_BRACKETS (&A68_JOB)) {
 528          substitute_brackets (TOP_NODE (&A68_JOB));
 529        }
 530        A68 (symbol_table_count) = 0;
 531        A68_STANDENV = new_symbol_table (NO_TABLE);
 532        LEVEL (A68_STANDENV) = 0;
 533        top_down_parser (TOP_NODE (&A68_JOB));
 534      }
 535      renum = 0;
 536      renumber_nodes (TOP_NODE (&A68_JOB), &renum);
 537      verbosity ();
 538    }
 539  // Standard environment builder.
 540    if (ERROR_COUNT (&A68_JOB) == 0) {
 541      announce_phase ("standard environ builder");
 542      TABLE (TOP_NODE (&A68_JOB)) = new_symbol_table (A68_STANDENV);
 543      make_standard_environ ();
 544      STANDENV_MOID (&A68_JOB) = TOP_MOID (&A68_JOB);
 545      verbosity ();
 546    }
 547  // Bottom-up parser.
 548    if (ERROR_COUNT (&A68_JOB) == 0) {
 549      announce_phase ("parser phase 2");
 550      preliminary_symbol_table_setup (TOP_NODE (&A68_JOB));
 551      bottom_up_parser (TOP_NODE (&A68_JOB));
 552      renum = 0;
 553      renumber_nodes (TOP_NODE (&A68_JOB), &renum);
 554      verbosity ();
 555    }
 556    if (ERROR_COUNT (&A68_JOB) == 0) {
 557      announce_phase ("parser phase 3");
 558      bottom_up_error_check (TOP_NODE (&A68_JOB));
 559      victal_checker (TOP_NODE (&A68_JOB));
 560      if (ERROR_COUNT (&A68_JOB) == 0) {
 561        finalise_symbol_table_setup (TOP_NODE (&A68_JOB), 2);
 562        NEST (TABLE (TOP_NODE (&A68_JOB))) = A68 (symbol_table_count) = 3;
 563        reset_symbol_table_nest_count (TOP_NODE (&A68_JOB));
 564        fill_symbol_table_outer (TOP_NODE (&A68_JOB), TABLE (TOP_NODE (&A68_JOB)));
 565        set_nest (TOP_NODE (&A68_JOB), NO_NODE);
 566        set_proc_level (TOP_NODE (&A68_JOB), 1);
 567      }
 568      renum = 0;
 569      renumber_nodes (TOP_NODE (&A68_JOB), &renum);
 570      verbosity ();
 571    }
 572  // Mode table builder.
 573    if (ERROR_COUNT (&A68_JOB) == 0) {
 574      announce_phase ("mode table builder");
 575      make_moid_list (&A68_JOB);
 576      verbosity ();
 577    }
 578    CROSS_REFERENCE_SAFE (&A68_JOB) = A68_TRUE;
 579  // Symbol table builder.
 580    if (ERROR_COUNT (&A68_JOB) == 0) {
 581      announce_phase ("symbol table builder");
 582      collect_taxes (TOP_NODE (&A68_JOB));
 583      verbosity ();
 584    }
 585  // Post parser.
 586    if (ERROR_COUNT (&A68_JOB) == 0) {
 587      announce_phase ("parser phase 4");
 588      rearrange_goto_less_jumps (TOP_NODE (&A68_JOB));
 589      verbosity ();
 590    }
 591  // Mode checker.
 592    if (ERROR_COUNT (&A68_JOB) == 0) {
 593      announce_phase ("mode checker");
 594      mode_checker (TOP_NODE (&A68_JOB));
 595      verbosity ();
 596    }
 597  // Coercion inserter.
 598    if (ERROR_COUNT (&A68_JOB) == 0) {
 599      announce_phase ("coercion enforcer");
 600      coercion_inserter (TOP_NODE (&A68_JOB));
 601      widen_denotation (TOP_NODE (&A68_JOB));
 602      get_max_simplout_size (TOP_NODE (&A68_JOB));
 603      set_moid_sizes (TOP_MOID (&A68_JOB));
 604      assign_offsets_table (A68_STANDENV);
 605      assign_offsets (TOP_NODE (&A68_JOB));
 606      assign_offsets_packs (TOP_MOID (&A68_JOB));
 607      renum = 0;
 608      renumber_nodes (TOP_NODE (&A68_JOB), &renum);
 609      verbosity ();
 610    }
 611  // Application checker.
 612    if (ERROR_COUNT (&A68_JOB) == 0) {
 613      announce_phase ("application checker");
 614      mark_moids (TOP_NODE (&A68_JOB));
 615      mark_auxilliary (TOP_NODE (&A68_JOB));
 616      jumps_from_procs (TOP_NODE (&A68_JOB));
 617      warn_for_unused_tags (TOP_NODE (&A68_JOB));
 618      verbosity ();
 619    }
 620  // Scope checker.
 621    if (ERROR_COUNT (&A68_JOB) == 0) {
 622      announce_phase ("static scope checker");
 623      tie_label_to_serial (TOP_NODE (&A68_JOB));
 624      tie_label_to_unit (TOP_NODE (&A68_JOB));
 625      bind_routine_tags_to_tree (TOP_NODE (&A68_JOB));
 626      bind_format_tags_to_tree (TOP_NODE (&A68_JOB));
 627      scope_checker (TOP_NODE (&A68_JOB));
 628      verbosity ();
 629    }
 630  }
 631  
 632  //! @brief Renumber nodes.
 633  
 634  void renumber_nodes (NODE_T * p, int *n)
 635  {
 636    for (; p != NO_NODE; FORWARD (p)) {
 637      NUMBER (p) = (*n)++;
 638      renumber_nodes (SUB (p), n);
 639    }
 640  }
 641  
 642  //! @brief Register nodes.
 643  
 644  void register_nodes (NODE_T * p)
 645  {
 646    for (; p != NO_NODE; FORWARD (p)) {
 647      A68 (node_register)[NUMBER (p)] = p;
 648      register_nodes (SUB (p));
 649    }
 650  }
 651  
 652  //! @brief New_node_info.
 653  
 654  NODE_INFO_T *new_node_info (void)
 655  {
 656    NODE_INFO_T *z = (NODE_INFO_T *) get_fixed_heap_space ((size_t) SIZE_ALIGNED (NODE_INFO_T));
 657    A68 (new_node_infos)++;
 658    PROCEDURE_LEVEL (z) = 0;
 659    CHAR_IN_LINE (z) = NO_TEXT;
 660    SYMBOL (z) = NO_TEXT;
 661    PRAGMENT (z) = NO_TEXT;
 662    PRAGMENT_TYPE (z) = 0;
 663    LINE (z) = NO_LINE;
 664    return z;
 665  }
 666  
 667  //! @brief New_genie_info.
 668  
 669  GINFO_T *new_genie_info (void)
 670  {
 671    GINFO_T *z = (GINFO_T *) get_fixed_heap_space ((size_t) SIZE_ALIGNED (GINFO_T));
 672    A68 (new_genie_infos)++;
 673    UNIT (&PROP (z)) = NO_PPROC;
 674    SOURCE (&PROP (z)) = NO_NODE;
 675    PARTIAL_PROC (z) = NO_MOID;
 676    PARTIAL_LOCALE (z) = NO_MOID;
 677    IS_COERCION (z) = A68_FALSE;
 678    IS_NEW_LEXICAL_LEVEL (z) = A68_FALSE;
 679    NEED_DNS (z) = A68_FALSE;
 680    PARENT (z) = NO_NODE;
 681    OFFSET (z) = NO_BYTE;
 682    CONSTANT (z) = NO_CONSTANT;
 683    LEVEL (z) = 0;
 684    ARGSIZE (z) = 0;
 685    SIZE (z) = 0;
 686    COMPILE_NAME (z) = NO_TEXT;
 687    COMPILE_NODE (z) = 0;
 688    return z;
 689  }
 690  
 691  //! @brief New_node.
 692  
 693  NODE_T *new_node (void)
 694  {
 695    NODE_T *z = (NODE_T *) get_fixed_heap_space ((size_t) SIZE_ALIGNED (NODE_T));
 696    A68 (new_nodes)++;
 697    STATUS (z) = NULL_MASK;
 698    CODEX (z) = NULL_MASK;
 699    TABLE (z) = NO_TABLE;
 700    INFO (z) = NO_NINFO;
 701    GINFO (z) = NO_GINFO;
 702    ATTRIBUTE (z) = 0;
 703    ANNOTATION (z) = 0;
 704    MOID (z) = NO_MOID;
 705    NEXT (z) = NO_NODE;
 706    PREVIOUS (z) = NO_NODE;
 707    SUB (z) = NO_NODE;
 708    NEST (z) = NO_NODE;
 709    NON_LOCAL (z) = NO_TABLE;
 710    TAX (z) = NO_TAG;
 711    SEQUENCE (z) = NO_NODE;
 712    PACK (z) = NO_PACK;
 713    return z;
 714  }
 715  
 716  //! @brief New_symbol_table.
 717  
 718  TABLE_T *new_symbol_table (TABLE_T * p)
 719  {
 720    TABLE_T *z = (TABLE_T *) get_fixed_heap_space ((size_t) SIZE_ALIGNED (TABLE_T));
 721    NUM (z) = A68 (symbol_table_count);
 722    LEVEL (z) = A68 (symbol_table_count)++;
 723    NEST (z) = A68 (symbol_table_count);
 724    ATTRIBUTE (z) = 0;
 725    AP_INCREMENT (z) = 0;
 726    INITIALISE_FRAME (z) = A68_TRUE;
 727    PROC_OPS (z) = A68_TRUE;
 728    INITIALISE_ANON (z) = A68_TRUE;
 729    PREVIOUS (z) = p;
 730    OUTER (z) = NO_TABLE;
 731    IDENTIFIERS (z) = NO_TAG;
 732    OPERATORS (z) = NO_TAG;
 733    PRIO (z) = NO_TAG;
 734    INDICANTS (z) = NO_TAG;
 735    LABELS (z) = NO_TAG;
 736    ANONYMOUS (z) = NO_TAG;
 737    JUMP_TO (z) = NO_NODE;
 738    SEQUENCE (z) = NO_NODE;
 739    return z;
 740  }
 741  
 742  //! @brief New_moid.
 743  
 744  MOID_T *new_moid (void)
 745  {
 746    MOID_T *z = (MOID_T *) get_fixed_heap_space ((size_t) SIZE_ALIGNED (MOID_T));
 747    A68 (new_modes)++;
 748    ATTRIBUTE (z) = 0;
 749    NUMBER (z) = 0;
 750    DIM (z) = 0;
 751    USE (z) = A68_FALSE;
 752    HAS_ROWS (z) = A68_FALSE;
 753    SIZE (z) = 0;
 754    DIGITS (z) = 0;
 755    SIZEC (z) = 0;
 756    DIGITSC (z) = 0;
 757    PORTABLE (z) = A68_TRUE;
 758    DERIVATE (z) = A68_FALSE;
 759    NODE (z) = NO_NODE;
 760    PACK (z) = NO_PACK;
 761    SUB (z) = NO_MOID;
 762    EQUIVALENT_MODE (z) = NO_MOID;
 763    SLICE (z) = NO_MOID;
 764    TRIM (z) = NO_MOID;
 765    DEFLEXED (z) = NO_MOID;
 766    NAME (z) = NO_MOID;
 767    MULTIPLE_MODE (z) = NO_MOID;
 768    NEXT (z) = NO_MOID;
 769    return z;
 770  }
 771  
 772  //! @brief New_pack.
 773  
 774  PACK_T *new_pack (void)
 775  {
 776    PACK_T *z = (PACK_T *) get_fixed_heap_space ((size_t) SIZE_ALIGNED (PACK_T));
 777    MOID (z) = NO_MOID;
 778    TEXT (z) = NO_TEXT;
 779    NODE (z) = NO_NODE;
 780    NEXT (z) = NO_PACK;
 781    PREVIOUS (z) = NO_PACK;
 782    SIZE (z) = 0;
 783    OFFSET (z) = 0;
 784    return z;
 785  }
 786  
 787  //! @brief New_tag.
 788  
 789  TAG_T *new_tag (void)
 790  {
 791    TAG_T *z = (TAG_T *) get_fixed_heap_space ((size_t) SIZE_ALIGNED (TAG_T));
 792    STATUS (z) = NULL_MASK;
 793    CODEX (z) = NULL_MASK;
 794    TAG_TABLE (z) = NO_TABLE;
 795    MOID (z) = NO_MOID;
 796    NODE (z) = NO_NODE;
 797    UNIT (z) = NO_NODE;
 798    VALUE (z) = NO_TEXT;
 799    A68_STANDENV_PROC (z) = 0;
 800    PROCEDURE (z) = NO_GPROC;
 801    SCOPE (z) = PRIMAL_SCOPE;
 802    SCOPE_ASSIGNED (z) = A68_FALSE;
 803    PRIO (z) = 0;
 804    USE (z) = A68_FALSE;
 805    IN_PROC (z) = A68_FALSE;
 806    HEAP (z) = A68_FALSE;
 807    SIZE (z) = 0;
 808    OFFSET (z) = 0;
 809    YOUNGEST_ENVIRON (z) = PRIMAL_SCOPE;
 810    LOC_ASSIGNED (z) = A68_FALSE;
 811    NEXT (z) = NO_TAG;
 812    BODY (z) = NO_TAG;
 813    PORTABLE (z) = A68_TRUE;
 814    NUMBER (z) = ++A68_PARSER (tag_number);
 815    return z;
 816  }
 817  
 818  //! @brief Make special, internal mode.
 819  
 820  void make_special_mode (MOID_T ** n, int m)
 821  {
 822    (*n) = new_moid ();
 823    ATTRIBUTE (*n) = 0;
 824    NUMBER (*n) = m;
 825    PACK (*n) = NO_PACK;
 826    SUB (*n) = NO_MOID;
 827    EQUIVALENT (*n) = NO_MOID;
 828    DEFLEXED (*n) = NO_MOID;
 829    NAME (*n) = NO_MOID;
 830    SLICE (*n) = NO_MOID;
 831    TRIM (*n) = NO_MOID;
 832    ROWED (*n) = NO_MOID;
 833  }
 834  
 835  //! @brief Whether x matches c; case insensitive.
 836  
 837  BOOL_T match_string (char *x, char *c, char alt)
 838  {
 839    BOOL_T match = A68_TRUE;
 840    while ((IS_UPPER (c[0]) || IS_DIGIT (c[0]) || c[0] == '-') && match) {
 841      match = (BOOL_T) (match & (TO_LOWER (x[0]) == TO_LOWER ((c++)[0])));
 842      if (!(x[0] == NULL_CHAR || x[0] == alt)) {
 843        x++;
 844      }
 845    }
 846    while (x[0] != NULL_CHAR && x[0] != alt && c[0] != NULL_CHAR && match) {
 847      match = (BOOL_T) (match & (TO_LOWER ((x++)[0]) == TO_LOWER ((c++)[0])));
 848    }
 849    return (BOOL_T) (match ? (x[0] == NULL_CHAR || x[0] == alt) : A68_FALSE);
 850  }
 851  
 852  //! @brief Whether attributes match in subsequent nodes.
 853  
 854  BOOL_T whether (NODE_T * p, ...)
 855  {
 856    va_list vl;
 857    int a;
 858    va_start (vl, p);
 859    while ((a = va_arg (vl, int)) != STOP)
 860    {
 861      if (p != NO_NODE && a == WILDCARD) {
 862        FORWARD (p);
 863      } else if (p != NO_NODE && (a == KEYWORD)) {
 864        if (find_keyword_from_attribute (A68 (top_keyword), ATTRIBUTE (p)) != NO_KEYWORD) {
 865          FORWARD (p);
 866        } else {
 867          va_end (vl);
 868          return A68_FALSE;
 869        }
 870      } else if (p != NO_NODE && (a >= 0 ? a == ATTRIBUTE (p) : (-a) != ATTRIBUTE (p))) {
 871        FORWARD (p);
 872      } else {
 873        va_end (vl);
 874        return A68_FALSE;
 875      }
 876    }
 877    va_end (vl);
 878    return A68_TRUE;
 879  }
 880  
 881  //! @brief Whether one of a series of attributes matches a node.
 882  
 883  BOOL_T is_one_of (NODE_T * p, ...)
 884  {
 885    if (p != NO_NODE) {
 886      va_list vl;
 887      int a;
 888      BOOL_T match = A68_FALSE;
 889      va_start (vl, p);
 890      while ((a = va_arg (vl, int)) != STOP)
 891      {
 892        match = (BOOL_T) (match | (BOOL_T) (IS (p, a)));
 893      }
 894      va_end (vl);
 895      return match;
 896    } else {
 897      return A68_FALSE;
 898    }
 899  }
 900  
 901  //! @brief Isolate nodes p-q making p a branch to p-q.
 902  
 903  void make_sub (NODE_T * p, NODE_T * q, int t)
 904  {
 905    NODE_T *z = new_node ();
 906    ABEND (p == NO_NODE || q == NO_NODE, ERROR_INTERNAL_CONSISTENCY, __func__);
 907    *z = *p;
 908    if (GINFO (p) != NO_GINFO) {
 909      GINFO (z) = new_genie_info ();
 910    }
 911    PREVIOUS (z) = NO_NODE;
 912    if (p == q) {
 913      NEXT (z) = NO_NODE;
 914    } else {
 915      if (NEXT (p) != NO_NODE) {
 916        PREVIOUS (NEXT (p)) = z;
 917      }
 918      NEXT (p) = NEXT (q);
 919      if (NEXT (p) != NO_NODE) {
 920        PREVIOUS (NEXT (p)) = p;
 921      }
 922      NEXT (q) = NO_NODE;
 923    }
 924    SUB (p) = z;
 925    ATTRIBUTE (p) = t;
 926  }
 927  
 928  //! @brief Find symbol table at level 'i'.
 929  
 930  TABLE_T *find_level (NODE_T * n, int i)
 931  {
 932    if (n == NO_NODE) {
 933      return NO_TABLE;
 934    } else {
 935      TABLE_T *s = TABLE (n);
 936      if (s != NO_TABLE && LEVEL (s) == i) {
 937        return s;
 938      } else if ((s = find_level (SUB (n), i)) != NO_TABLE) {
 939        return s;
 940      } else if ((s = find_level (NEXT (n), i)) != NO_TABLE) {
 941        return s;
 942      } else {
 943        return NO_TABLE;
 944      }
 945    }
 946  }
 947  
 948  //! @brief Whether 'p' is top of lexical level.
 949  
 950  BOOL_T is_new_lexical_level (NODE_T * p)
 951  {
 952    switch (ATTRIBUTE (p)) {
 953    case ALT_DO_PART:
 954    case BRIEF_ELIF_PART:
 955    case BRIEF_OUSE_PART:
 956    case BRIEF_CONFORMITY_OUSE_PART:
 957    case CHOICE:
 958    case CLOSED_CLAUSE:
 959    case CONDITIONAL_CLAUSE:
 960    case DO_PART:
 961    case ELIF_PART:
 962    case ELSE_PART:
 963    case FORMAT_TEXT:
 964    case CASE_CLAUSE:
 965    case CASE_CHOICE_CLAUSE:
 966    case CASE_IN_PART:
 967    case CASE_OUSE_PART:
 968    case OUT_PART:
 969    case ROUTINE_TEXT:
 970    case SPECIFIED_UNIT:
 971    case THEN_PART:
 972    case UNTIL_PART:
 973    case CONFORMITY_CLAUSE:
 974    case CONFORMITY_CHOICE:
 975    case CONFORMITY_IN_PART:
 976    case CONFORMITY_OUSE_PART:
 977    case WHILE_PART:
 978      {
 979        return A68_TRUE;
 980      }
 981    default:
 982      {
 983        return A68_FALSE;
 984      }
 985    }
 986  }
 987  
 988  //! @brief Some_node.
 989  
 990  NODE_T *some_node (char *t)
 991  {
 992    NODE_T *z = new_node ();
 993    INFO (z) = new_node_info ();
 994    GINFO (z) = new_genie_info ();
 995    NSYMBOL (z) = t;
 996    return z;
 997  }