parser.c

You can download the current version of Algol 68 Genie and its documentation here.

   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 .
   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 .
  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 }