1 /**
2 @file syntax.c
3 @author J. Marcel van der Veer
4 @brief Hand-coded Algol 68 scanner and parser.
5
6 @section Copyright
7
8 This file is part of Algol 68 Genie - an Algol 68 compiler-interpreter.
9 Copyright 2001-2016 J. Marcel van der Veer <algol68g@xs4all.nl>.
10
11 @section License
12
13 This program is free software; you can redistribute it and/or modify it under
14 the terms of the GNU General Public License as published by the Free Software
15 Foundation; either version 3 of the License, or (at your option) any later
16 version.
17
18 This program is distributed in the hope that it will be useful, but WITHOUT ANY
19 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
20 PARTICULAR PURPOSE. See the GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License along with
23 this program. If not, see <http://www.gnu.org/licenses/>.
24
25 @section Description
26
27 Algol 68 grammar is defined as a two level (Van Wijngaarden) grammar that
28 incorporates, as syntactical rules, the "semantical" rules in
29 other languages. Examples are correct use of symbols, modes and scope.
30 That is why so much functionality is in the "syntax.c" file. In fact, all
31 this material constitutes an effective "Algol 68 VW parser". This pragmatic
32 approach was chosen since in the early days of Algol 68, many "ab initio"
33 implementations failed.
34
35 This is a Mailloux-type parser, in the sense that it scans a "phrase" for
36 definitions before it starts parsing, and therefore allows for tags to be used
37 before they are defined, which gives some freedom in top-down programming.
38 In 2011, FLACC documentation became available again. This documentation
39 suggests that the set-up of this parser resembles that of FLACC, which
40 supports the view that this is a Mailloux-type parser.
41
42 First part in this file is the scanner. The source file is read,
43 is tokenised, and if needed a refinement preprocessor elaborates a stepwise
44 refined program. The result is a linear list of tokens that is input for the
45 parser, that will transform the linear list into a syntax tree.
46
47 Algol68G tokenises all symbols before the bottom-up parser is invoked.
48 This means that scanning does not use information from the parser.
49 The scanner does of course do some rudimentary parsing. Format texts can have
50 enclosed clauses in them, so we record information in a stack as to know
51 what is being scanned. Also, the refinement preprocessor implements a
52 (trivial) grammar.
53
54 The scanner supports two stropping regimes: bold and quote. Examples of both:
55
56 bold stropping: BEGIN INT i = 1, j = 1; print (i + j) END
57
58 quote stropping: 'BEGIN' 'INT' I = 1, J = 1; PRINT (I + J) 'END'
59
60 Quote stropping was used frequently in the (excusez-le-mot) punch-card age.
61 Hence, bold stropping is the default. There also existed point stropping, but
62 that has not been implemented here.
63
64 Next part of the parser is a recursive-descent type to check parenthesis.
65 Also a first set-up is made of symbol tables, needed by the bottom-up parser.
66 Next part is the bottom-up parser, that parses without knowing about modes while
67 parsing and reducing. It can therefore not exchange "[]" with "()" as was
68 blessed by the Revised Report. This is solved by treating CALL and SLICE as
69 equivalent for the moment and letting the mode checker sort it out later.
70
71 Parsing progresses in various phases to avoid spurious diagnostics from a
72 recovering parser. Every phase "tightens" the grammar more.
73 An error in any phase makes the parser quit when that phase ends.
74 The parser is forgiving in case of superfluous semicolons.
75
76 So those are the parser phases:
77
78 (1) Parenthesis are checked to see whether they match. Then, a top-down
79 parser determines the basic-block structure of the program
80 so symbol tables can be set up that the bottom-up parser will consult
81 as you can define things before they are applied.
82
83 (2) A bottom-up parser resolves the structure of the program.
84
85 (3) After the symbol tables have been finalised, a small rearrangement of the
86 tree may be required where JUMPs have no GOTO. This leads to the
87 non-standard situation that JUMPs without GOTO can have the syntactic
88 position of a PRIMARY, SECONDARY or TERTIARY. The bottom-up parser also
89 does not check VICTAL correctness of declarers. This is done separately.
90 Also structure of format texts is checked separately.
91
92 The parser sets up symbol tables and populates them as far as needed to parse
93 the source. After the bottom-up parser terminates succesfully, the symbol tables
94 are completed.
95
96 (4) Next, modes are collected and rules for well-formedness and structural
97 equivalence are applied. Then the symbol-table is completed now moids are
98 all known.
99
100 (5) Next phases are the mode checker and coercion inserter. The syntax tree is
101 traversed to determine and check all modes, and to select operators. Then
102 the tree is traversed again to insert coercions.
103
104 (6) A static scope checker detects where objects are transported out of scope.
105 At run time, a dynamic scope checker will check that what the static scope
106 checker cannot see.
107
108 With respect to the mode checker: Algol 68 contexts are SOFT, WEAK, MEEK, FIRM
109 and STRONG. These contexts are increasing in strength:
110
111 SOFT: Deproceduring
112
113 WEAK: Dereferencing to REF [] or REF STRUCT
114
115 MEEK: Deproceduring and dereferencing
116
117 FIRM: MEEK followed by uniting
118
119 STRONG: FIRM followed by rowing, widening or voiding
120
121 Furthermore you will see in this file next switches:
122
123 (1) FORCE_DEFLEXING allows assignment compatibility between FLEX and non FLEX
124 rows. This can only be the case when there is no danger of altering bounds of a
125 non FLEX row.
126
127 (2) ALIAS_DEFLEXING prohibits aliasing a FLEX row to a non FLEX row (vice versa
128 is no problem) so that one cannot alter the bounds of a non FLEX row by
129 aliasing it to a FLEX row. This is particularly the case when passing names as
130 parameters to procedures:
131
132 PROC x = (REF STRING s) VOID: ..., PROC y = (REF [] CHAR c) VOID: ...;
133
134 x (LOC STRING); # OK #
135
136 x (LOC [10] CHAR); # Not OK, suppose x changes bounds of s! #
137
138 y (LOC STRING); # OK #
139
140 y (LOC [10] CHAR); # OK #
141
142 (3) SAFE_DEFLEXING sets FLEX row apart from non FLEX row. This holds for names,
143 not for values, so common things are not rejected, for instance
144
145 STRING x = read string;
146
147 [] CHAR y = read string
148
149 (4) NO_DEFLEXING sets FLEX row apart from non FLEX row.
150
151 Finally, a static scope checker inspects the source. Note that Algol 68 also
152 needs dynamic scope checking. This phase concludes the parser.
153 **/
154
155 #if defined HAVE_CONFIG_H
156 #include "a68g-config.h"
157 #endif
158
159 #include "a68g.h"
160
161 static MOID_T *get_mode_from_declarer (NODE_T *);
162
163 typedef struct TUPLE_T TUPLE_T;
164 typedef struct SCOPE_T SCOPE_T;
165
166 struct TUPLE_T
167 {
168 int level;
169 BOOL_T transient;
170 };
171
172 struct SCOPE_T
173 {
174 NODE_T *where;
175 TUPLE_T tuple;
176 SCOPE_T *next;
177 };
178
179 enum
180 { NOT_TRANSIENT = 0, TRANSIENT };
181
182 static void gather_scopes_for_youngest (NODE_T *, SCOPE_T **);
183 static void scope_statement (NODE_T *, SCOPE_T **);
184 static void scope_enclosed_clause (NODE_T *, SCOPE_T **);
185 static void scope_formula (NODE_T *, SCOPE_T **);
186 static void scope_routine_text (NODE_T *, SCOPE_T **);
187 TAG_T *error_tag;
188
189 static SOID_T *top_soid_list = NO_SOID;
190
191 static BOOL_T basic_coercions (MOID_T *, MOID_T *, int, int);
192 static BOOL_T is_coercible (MOID_T *, MOID_T *, int, int);
193 static BOOL_T is_nonproc (MOID_T *);
194 static void mode_check_enclosed (NODE_T *, SOID_T *, SOID_T *);
195 static void mode_check_unit (NODE_T *, SOID_T *, SOID_T *);
196 static void mode_check_formula (NODE_T *, SOID_T *, SOID_T *);
197 static void coerce_enclosed (NODE_T *, SOID_T *);
198 static void coerce_operand (NODE_T *, SOID_T *);
199 static void coerce_formula (NODE_T *, SOID_T *);
200 static void coerce_unit (NODE_T *, SOID_T *);
201
202 #define DEPREF A68_TRUE
203 #define NO_DEPREF A68_FALSE
204
205 #define IF_MODE_IS_WELL(n) (! ((n) == MODE (ERROR) || (n) == MODE (UNDEFINED)))
206 #define INSERT_COERCIONS(n, p, q) make_strong ((n), (p), MOID (q))
207
208 #define STOP_CHAR 127
209
210 #define IN_PRELUDE(p) (LINE_NUMBER (p) <= 0)
211 #define EOL(c) ((c) == NEWLINE_CHAR || (c) == NULL_CHAR)
212
213 static BOOL_T stop_scanner = A68_FALSE, read_error = A68_FALSE, no_preprocessing = A68_FALSE;
214 static char *scan_buf;
215 static int max_scan_buf_length, source_file_size;
216 static int reductions = 0;
217 static jmp_buf bottom_up_crash_exit, top_down_crash_exit;
218
219 static BOOL_T victal_check_declarer (NODE_T *, int);
220 static NODE_T *reduce_dyadic (NODE_T *, int u);
221 static NODE_T *top_down_loop (NODE_T *);
222 static NODE_T *top_down_skip_unit (NODE_T *);
223 static void append_source_line (char *, LINE_T **, int *, char *);
224 static void elaborate_bold_tags (NODE_T *);
225 static void extract_declarations (NODE_T *);
226 static void extract_identities (NODE_T *);
227 static void extract_indicants (NODE_T *);
228 static void extract_labels (NODE_T *, int);
229 static void extract_operators (NODE_T *);
230 static void extract_priorities (NODE_T *);
231 static void extract_proc_identities (NODE_T *);
232 static void extract_proc_variables (NODE_T *);
233 static void extract_variables (NODE_T *);
234 static void ignore_superfluous_semicolons (NODE_T *);
235 static void recover_from_error (NODE_T *, int, BOOL_T);
236 static void reduce_arguments (NODE_T *);
237 static void reduce_basic_declarations (NODE_T *);
238 static void reduce_bounds (NODE_T *);
239 static void reduce_collateral_clauses (NODE_T *);
240 static void reduce_declaration_lists (NODE_T *);
241 static void reduce_declarers (NODE_T *, int);
242 static void reduce_enclosed_clauses (NODE_T *, int);
243 static void reduce_enquiry_clauses (NODE_T *);
244 static void reduce_erroneous_units (NODE_T *);
245 static void reduce_format_texts (NODE_T *);
246 static void reduce_formulae (NODE_T *);
247 static void reduce_generic_arguments (NODE_T *);
248 static void reduce_primaries (NODE_T *, int);
249 static void reduce_primary_parts (NODE_T *, int);
250 static void reduce_right_to_left_constructs (NODE_T * q);
251 static void reduce_secondaries (NODE_T *);
252 static void reduce_serial_clauses (NODE_T *);
253 static void reduce_branch (NODE_T *, int);
254 static void reduce_tertiaries (NODE_T *);
255 static void reduce_units (NODE_T *);
256 static void reduce (NODE_T *, void (*)(NODE_T *), BOOL_T *, ...);
257
258 /* Standard environ */
259
260 static char *bold_prelude_start[] = {
261 "BEGIN MODE DOUBLE = LONG REAL, QUAD = LONG LONG REAL;",
262 " start: commence:",
263 " BEGIN",
264 NO_TEXT
265 };
266
267 static char *bold_postlude[] = {
268 " END;",
269 " stop: abort: halt: SKIP",
270 "END",
271 NO_TEXT
272 };
273
274 static char *quote_prelude_start[] = {
275 "'BEGIN' 'MODE' 'DOUBLE' = 'LONG' 'REAL'," " 'QUAD' = 'LONG' 'LONG' 'REAL'," " 'DEVICE' = 'FILE'," " 'TEXT' = 'STRING';" " START: COMMENCE:" " 'BEGIN'",
276 NO_TEXT
277 };
278
279 static char *quote_postlude[] = {
280 " 'END';",
281 " STOP: ABORT: HALT: 'SKIP'",
282 "'END'",
283 NO_TEXT
284 };
285
286 /**
287 @brief Is_ref_refety_flex.
288 @param m Mode under test.
289 @return See brief description.
290 **/
291
292 static BOOL_T
is_ref_refety_flex(MOID_T * m)293 is_ref_refety_flex (MOID_T * m)
294 {
295 if (IS_REF_FLEX (m)) {
296 return (A68_TRUE);
297 } else if (IS (m, REF_SYMBOL)) {
298 return (is_ref_refety_flex (SUB (m)));
299 } else {
300 return (A68_FALSE);
301 }
302 }
303
304 /**
305 @brief Count pictures.
306 @param p Node in syntax tree.
307 @param k Counter.
308 **/
309
310 static void
count_pictures(NODE_T * p,int * k)311 count_pictures (NODE_T * p, int *k)
312 {
313 for (; p != NO_NODE; FORWARD (p)) {
314 if (IS (p, PICTURE)) {
315 (*k)++;
316 }
317 count_pictures (SUB (p), k);
318 }
319 }
320
321 /**
322 @brief Count number of operands in operator parameter list.
323 @param p Node in syntax tree.
324 @return See brief description.
325 **/
326
327 static int
count_operands(NODE_T * p)328 count_operands (NODE_T * p)
329 {
330 if (p != NO_NODE) {
331 if (IS (p, DECLARER)) {
332 return (count_operands (NEXT (p)));
333 } else if (IS (p, COMMA_SYMBOL)) {
334 return (1 + count_operands (NEXT (p)));
335 } else {
336 return (count_operands (NEXT (p)) + count_operands (SUB (p)));
337 }
338 } else {
339 return (0);
340 }
341 }
342
343 /**
344 @brief Count formal bounds in declarer in tree.
345 @param p Node in syntax tree.
346 @return See brief description.
347 **/
348
349 static int
count_formal_bounds(NODE_T * p)350 count_formal_bounds (NODE_T * p)
351 {
352 if (p == NO_NODE) {
353 return (0);
354 } else {
355 if (IS (p, COMMA_SYMBOL)) {
356 return (1);
357 } else {
358 return (count_formal_bounds (NEXT (p)) + count_formal_bounds (SUB (p)));
359 }
360 }
361 }
362
363 /**
364 @brief Count bounds in declarer in tree.
365 @param p Node in syntax tree.
366 @return See brief description.
367 **/
368
369 static int
count_bounds(NODE_T * p)370 count_bounds (NODE_T * p)
371 {
372 if (p == NO_NODE) {
373 return (0);
374 } else {
375 if (IS (p, BOUND)) {
376 return (1 + count_bounds (NEXT (p)));
377 } else {
378 return (count_bounds (NEXT (p)) + count_bounds (SUB (p)));
379 }
380 }
381 }
382
383 /**
384 @brief Count number of SHORTs or LONGs.
385 @param p Node in syntax tree.
386 @return See brief description.
387 **/
388
389 static int
count_sizety(NODE_T * p)390 count_sizety (NODE_T * p)
391 {
392 if (p == NO_NODE) {
393 return (0);
394 } else if (IS (p, LONGETY)) {
395 return (count_sizety (SUB (p)) + count_sizety (NEXT (p)));
396 } else if (IS (p, SHORTETY)) {
397 return (count_sizety (SUB (p)) + count_sizety (NEXT (p)));
398 } else if (IS (p, LONG_SYMBOL)) {
399 return (1);
400 } else if (IS (p, SHORT_SYMBOL)) {
401 return (-1);
402 } else {
403 return (0);
404 }
405 }
406
407 /**
408 @brief Count moids in a pack.
409 @param u Pack.
410 @return See brief description.
411 **/
412
413 int
count_pack_members(PACK_T * u)414 count_pack_members (PACK_T * u)
415 {
416 int k = 0;
417 for (; u != NO_PACK; FORWARD (u)) {
418 k++;
419 }
420 return (k);
421 }
422
423 /**
424 @brief Replace a mode by its equivalent mode.
425 @param m Mode to replace.
426 **/
427
428 static void
resolve_equivalent(MOID_T ** m)429 resolve_equivalent (MOID_T ** m)
430 {
431 while ((*m) != NO_MOID && EQUIVALENT ((*m)) != NO_MOID && (*m) != EQUIVALENT (*m)) {
432 (*m) = EQUIVALENT (*m);
433 }
434 }
435
436 /**
437 @brief Save scanner state, for character look-ahead.
438 @param ref_l Source line.
439 @param ref_s Position in source line text.
440 @param ch Last scanned character.
441 **/
442
443 static void
save_state(LINE_T * ref_l,char * ref_s,char ch)444 save_state (LINE_T * ref_l, char *ref_s, char ch)
445 {
446 SCAN_STATE_L (&program) = ref_l;
447 SCAN_STATE_S (&program) = ref_s;
448 SCAN_STATE_C (&program) = ch;
449 }
450
451 /**
452 @brief Restore scanner state, for character look-ahead.
453 @param ref_l Source line.
454 @param ref_s Position in source line text.
455 @param ch Last scanned character.
456 **/
457
458 static void
restore_state(LINE_T ** ref_l,char ** ref_s,char * ch)459 restore_state (LINE_T ** ref_l, char **ref_s, char *ch)
460 {
461 *ref_l = SCAN_STATE_L (&program);
462 *ref_s = SCAN_STATE_S (&program);
463 *ch = SCAN_STATE_C (&program);
464 }
465
466 /**************************************/
467 /* Scanner, tokenises the source code */
468 /**************************************/
469
470 /**
471 @brief Whether ch is unworthy.
472 @param u Source line with error.
473 @param v Character in line.
474 @param ch
475 **/
476
477 static void
unworthy(LINE_T * u,char * v,char ch)478 unworthy (LINE_T * u, char *v, char ch)
479 {
480 if (IS_PRINT (ch)) {
481 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, "*%s", ERROR_UNWORTHY_CHARACTER) >= 0);
482 } else {
483 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, "*%s %s", ERROR_UNWORTHY_CHARACTER, ctrl_char (ch)) >= 0);
484 }
485 scan_error (u, v, edit_line);
486 }
487
488 /**
489 @brief Concatenate lines that terminate in '\' with next line.
490 @param top Top source line.
491 **/
492
493 static void
concatenate_lines(LINE_T * top)494 concatenate_lines (LINE_T * top)
495 {
496 LINE_T *q;
497 /* Work from bottom backwards */
498 for (q = top; q != NO_LINE && NEXT (q) != NO_LINE; q = NEXT (q)) {
499 ;
500 }
501 for (; q != NO_LINE; BACKWARD (q)) {
502 char *z = STRING (q);
503 int len = (int) strlen (z);
504 if (len >= 2 && z[len - 2] == BACKSLASH_CHAR && z[len - 1] == NEWLINE_CHAR && NEXT (q) != NO_LINE && STRING (NEXT (q)) != NO_TEXT) {
505 z[len - 2] = NULL_CHAR;
506 len += (int) strlen (STRING (NEXT (q)));
507 z = (char *) get_fixed_heap_space ((size_t) (len + 1));
508 bufcpy (z, STRING (q), len + 1);
509 bufcat (z, STRING (NEXT (q)), len + 1);
510 STRING (NEXT (q))[0] = NULL_CHAR;
511 STRING (q) = z;
512 }
513 }
514 }
515
516 /**
517 @brief Whether u is bold tag v, independent of stropping regime.
518 @param u Symbol under test.
519 @param v Bold symbol .
520 @return Whether u is v.
521 **/
522
523 static BOOL_T
is_bold(char * u,char * v)524 is_bold (char *u, char *v)
525 {
526 unsigned len = (unsigned) strlen (v);
527 if (OPTION_STROPPING (&program) == QUOTE_STROPPING) {
528 if (u[0] == '\'') {
529 return ((BOOL_T) (strncmp (++u, v, len) == 0 && u[len] == '\''));
530 } else {
531 return (A68_FALSE);
532 }
533 } else {
534 return ((BOOL_T) (strncmp (u, v, len) == 0 && !IS_UPPER (u[len])));
535 }
536 }
537
538 /**
539 @brief Skip string.
540 @param top Current source line.
541 @param ch Current character in source line.
542 @return Whether string is properly terminated.
543 **/
544
545 static BOOL_T
skip_string(LINE_T ** top,char ** ch)546 skip_string (LINE_T ** top, char **ch)
547 {
548 LINE_T *u = *top;
549 char *v = *ch;
550 v++;
551 while (u != NO_LINE) {
552 while (v[0] != NULL_CHAR) {
553 if (v[0] == QUOTE_CHAR && v[1] != QUOTE_CHAR) {
554 *top = u;
555 *ch = &v[1];
556 return (A68_TRUE);
557 } else if (v[0] == QUOTE_CHAR && v[1] == QUOTE_CHAR) {
558 v += 2;
559 } else {
560 v++;
561 }
562 }
563 FORWARD (u);
564 if (u != NO_LINE) {
565 v = &(STRING (u)[0]);
566 } else {
567 v = NO_TEXT;
568 }
569 }
570 return (A68_FALSE);
571 }
572
573 /**
574 @brief Skip comment.
575 @param top Current source line.
576 @param ch Current character in source line.
577 @param delim Expected terminating delimiter.
578 @return Whether comment is properly terminated.
579 **/
580
581 static BOOL_T
skip_comment(LINE_T ** top,char ** ch,int delim)582 skip_comment (LINE_T ** top, char **ch, int delim)
583 {
584 LINE_T *u = *top;
585 char *v = *ch;
586 v++;
587 while (u != NO_LINE) {
588 while (v[0] != NULL_CHAR) {
589 if (is_bold (v, "COMMENT") && delim == BOLD_COMMENT_SYMBOL) {
590 *top = u;
591 *ch = &v[1];
592 return (A68_TRUE);
593 } else if (is_bold (v, "CO") && delim == STYLE_I_COMMENT_SYMBOL) {
594 *top = u;
595 *ch = &v[1];
596 return (A68_TRUE);
597 } else if (v[0] == '#' && delim == STYLE_II_COMMENT_SYMBOL) {
598 *top = u;
599 *ch = &v[1];
600 return (A68_TRUE);
601 } else {
602 v++;
603 }
604 }
605 FORWARD (u);
606 if (u != NO_LINE) {
607 v = &(STRING (u)[0]);
608 } else {
609 v = NO_TEXT;
610 }
611 }
612 return (A68_FALSE);
613 }
614
615 /**
616 @brief Skip rest of pragmat.
617 @param top Current source line.
618 @param ch Current character in source line.
619 @param delim Expected terminating delimiter.
620 @param whitespace Whether other pragmat items are allowed.
621 @return Whether pragmat is properly terminated.
622 **/
623
624 static BOOL_T
skip_pragmat(LINE_T ** top,char ** ch,int delim,BOOL_T whitespace)625 skip_pragmat (LINE_T ** top, char **ch, int delim, BOOL_T whitespace)
626 {
627 LINE_T *u = *top;
628 char *v = *ch;
629 while (u != NO_LINE) {
630 while (v[0] != NULL_CHAR) {
631 if (is_bold (v, "PRAGMAT") && delim == BOLD_PRAGMAT_SYMBOL) {
632 *top = u;
633 *ch = &v[1];
634 return (A68_TRUE);
635 } else if (is_bold (v, "PR")
636 && delim == STYLE_I_PRAGMAT_SYMBOL) {
637 *top = u;
638 *ch = &v[1];
639 return (A68_TRUE);
640 } else {
641 if (whitespace && !IS_SPACE (v[0]) && v[0] != NEWLINE_CHAR) {
642 scan_error (u, v, ERROR_PRAGMENT);
643 } else if (IS_UPPER (v[0])) {
644 /* Skip a bold word as you may trigger on REPR, for instance .. */
645 while (IS_UPPER (v[0])) {
646 v++;
647 }
648 } else {
649 v++;
650 }
651 }
652 }
653 FORWARD (u);
654 if (u != NO_LINE) {
655 v = &(STRING (u)[0]);
656 } else {
657 v = NO_TEXT;
658 }
659 }
660 return (A68_FALSE);
661 }
662
663 /**
664 @brief Return pointer to next token within pragmat.
665 @param top Current source line.
666 @param ch Current character in source line.
667 @return Pointer to next item, NO_TEXT if none remains.
668 **/
669
670 static char *
get_pragmat_item(LINE_T ** top,char ** ch)671 get_pragmat_item (LINE_T ** top, char **ch)
672 {
673 LINE_T *u = *top;
674 char *v = *ch;
675 while (u != NO_LINE) {
676 while (v[0] != NULL_CHAR) {
677 if (!IS_SPACE (v[0]) && v[0] != NEWLINE_CHAR) {
678 *top = u;
679 *ch = v;
680 return (v);
681 } else {
682 v++;
683 }
684 }
685 FORWARD (u);
686 if (u != NO_LINE) {
687 v = &(STRING (u)[0]);
688 } else {
689 v = NO_TEXT;
690 }
691 }
692 return (NO_TEXT);
693 }
694
695 /**
696 @brief Case insensitive strncmp for at most the number of chars in 'v'.
697 @param u String 1, must not be NO_TEXT.
698 @param v String 2, must not be NO_TEXT.
699 @return Alphabetic difference between 1 and 2.
700 **/
701
702 static int
streq(char * u,char * v)703 streq (char *u, char *v)
704 {
705 int diff;
706 for (diff = 0; diff == 0 && u[0] != NULL_CHAR && v[0] != NULL_CHAR; u++, v++) {
707 diff = ((int) TO_LOWER (u[0])) - ((int) TO_LOWER (v[0]));
708 }
709 return (diff);
710 }
711
712 /**
713 @brief Scan for next pragmat and yield first pragmat item.
714 @param top Current source line.
715 @param ch Current character in source line.
716 @param delim Expected terminating delimiter.
717 @return Pointer to next item or NO_TEXT if none remain.
718 **/
719
720 static char *
next_preprocessor_item(LINE_T ** top,char ** ch,int * delim)721 next_preprocessor_item (LINE_T ** top, char **ch, int *delim)
722 {
723 LINE_T *u = *top;
724 char *v = *ch;
725 *delim = 0;
726 while (u != NO_LINE) {
727 while (v[0] != NULL_CHAR) {
728 LINE_T *start_l = u;
729 char *start_c = v;
730 /* STRINGs must be skipped */
731 if (v[0] == QUOTE_CHAR) {
732 SCAN_ERROR (!skip_string (&u, &v), start_l, start_c, ERROR_UNTERMINATED_STRING);
733 }
734 /* COMMENTS must be skipped */
735 else if (is_bold (v, "COMMENT")) {
736 SCAN_ERROR (!skip_comment (&u, &v, BOLD_COMMENT_SYMBOL), start_l, start_c, ERROR_UNTERMINATED_COMMENT);
737 } else if (is_bold (v, "CO")) {
738 SCAN_ERROR (!skip_comment (&u, &v, STYLE_I_COMMENT_SYMBOL), start_l, start_c, ERROR_UNTERMINATED_COMMENT);
739 } else if (v[0] == '#') {
740 SCAN_ERROR (!skip_comment (&u, &v, STYLE_II_COMMENT_SYMBOL), start_l, start_c, ERROR_UNTERMINATED_COMMENT);
741 } else if (is_bold (v, "PRAGMAT") || is_bold (v, "PR")) {
742 /* We caught a PRAGMAT */
743 char *item;
744 if (is_bold (v, "PRAGMAT")) {
745 *delim = BOLD_PRAGMAT_SYMBOL;
746 v = &v[strlen ("PRAGMAT")];
747 } else if (is_bold (v, "PR")) {
748 *delim = STYLE_I_PRAGMAT_SYMBOL;
749 v = &v[strlen ("PR")];
750 }
751 item = get_pragmat_item (&u, &v);
752 SCAN_ERROR (item == NO_TEXT, start_l, start_c, ERROR_UNTERMINATED_PRAGMAT);
753 /* Item "preprocessor" restarts preprocessing if it is off */
754 if (no_preprocessing && streq (item, "PREPROCESSOR") == 0) {
755 no_preprocessing = A68_FALSE;
756 SCAN_ERROR (!skip_pragmat (&u, &v, *delim, A68_TRUE), start_l, start_c, ERROR_UNTERMINATED_PRAGMAT);
757 }
758 /* If preprocessing is switched off, we idle to closing bracket */
759 else if (no_preprocessing) {
760 SCAN_ERROR (!skip_pragmat (&u, &v, *delim, A68_FALSE), start_l, start_c, ERROR_UNTERMINATED_PRAGMAT);
761 }
762 /* Item "nopreprocessor" stops preprocessing if it is on */
763 if (streq (item, "NOPREPROCESSOR") == 0) {
764 no_preprocessing = A68_TRUE;
765 SCAN_ERROR (!skip_pragmat (&u, &v, *delim, A68_TRUE), start_l, start_c, ERROR_UNTERMINATED_PRAGMAT);
766 }
767 /* Item "INCLUDE" includes a file */
768 else if (streq (item, "INCLUDE") == 0) {
769 *top = u;
770 *ch = v;
771 return (item);
772 }
773 /* Item "READ" includes a file */
774 else if (streq (item, "READ") == 0) {
775 *top = u;
776 *ch = v;
777 return (item);
778 }
779 /* Unrecognised item - probably options handled later by the tokeniser */
780 else {
781 SCAN_ERROR (!skip_pragmat (&u, &v, *delim, A68_FALSE), start_l, start_c, ERROR_UNTERMINATED_PRAGMAT);
782 }
783 } else if (IS_UPPER (v[0])) {
784 /* Skip a bold word as you may trigger on REPR, for instance .. */
785 while (IS_UPPER (v[0])) {
786 v++;
787 }
788 } else {
789 v++;
790 }
791 }
792 FORWARD (u);
793 if (u != NO_LINE) {
794 v = &(STRING (u)[0]);
795 } else {
796 v = NO_TEXT;
797 }
798 }
799 *top = u;
800 *ch = v;
801 return (NO_TEXT);
802 }
803
804 /**
805 @brief Include files.
806 @param top Top source line.
807 **/
808
809 static void
include_files(LINE_T * top)810 include_files (LINE_T * top)
811 {
812 /*
813 include_files
814
815 syntax: PR read "filename" PR
816 PR include "filename" PR
817
818 The file gets inserted before the line containing the pragmat. In this way
819 correct line numbers are preserved which helps diagnostics. A file that has
820 been included will not be included a second time - it will be ignored.
821 */
822 BOOL_T make_pass = A68_TRUE;
823 while (make_pass) {
824 LINE_T *s, *t, *u = top;
825 char *v = &(STRING (u)[0]);
826 make_pass = A68_FALSE;
827 RESET_ERRNO;
828 while (u != NO_LINE) {
829 int pr_lim;
830 char *item = next_preprocessor_item (&u, &v, &pr_lim);
831 LINE_T *start_l = u;
832 char *start_c = v;
833 /* Search for PR include "filename" PR */
834 if (item != NO_TEXT && (streq (item, "INCLUDE") == 0 || streq (item, "READ") == 0)) {
835 FILE_T fd;
836 int n, linum, fsize, k, bytes_read, fnwid;
837 char *fbuf, delim;
838 char fnb[BUFFER_SIZE], *fn;
839 /* Skip to filename */
840 if (streq (item, "INCLUDE") == 0) {
841 v = &v[strlen ("INCLUDE")];
842 } else {
843 v = &v[strlen ("READ")];
844 }
845 while (IS_SPACE (v[0])) {
846 v++;
847 }
848 /* Scan quoted filename */
849 SCAN_ERROR ((v[0] != QUOTE_CHAR && v[0] != '\''), start_l, start_c, ERROR_INCORRECT_FILENAME);
850 delim = (v++)[0];
851 n = 0;
852 fnb[0] = NULL_CHAR;
853 /* Scan Algol 68 string (note: "" denotes a ", while in C it concatenates).*/
854 do {
855 SCAN_ERROR (EOL (v[0]), start_l, start_c, ERROR_INCORRECT_FILENAME);
856 SCAN_ERROR (n == BUFFER_SIZE - 1, start_l, start_c, ERROR_INCORRECT_FILENAME);
857 if (v[0] == delim) {
858 while (v[0] == delim && v[1] == delim) {
859 SCAN_ERROR (n == BUFFER_SIZE - 1, start_l, start_c, ERROR_INCORRECT_FILENAME);
860 fnb[n++] = delim;
861 fnb[n] = NULL_CHAR;
862 v += 2;
863 }
864 } else if (IS_PRINT (v[0])) {
865 fnb[n++] = *(v++);
866 fnb[n] = NULL_CHAR;
867 } else {
868 SCAN_ERROR (A68_TRUE, start_l, start_c, ERROR_INCORRECT_FILENAME);
869 }
870 } while (v[0] != delim);
871 /* Insist that the pragmat is closed properly */
872 v = &v[1];
873 SCAN_ERROR (!skip_pragmat (&u, &v, pr_lim, A68_TRUE), start_l, start_c, ERROR_UNTERMINATED_PRAGMAT);
874 /* Filename valid? */
875 SCAN_ERROR (n == 0, start_l, start_c, ERROR_INCORRECT_FILENAME);
876 fnwid = (int) strlen (fnb) + 1;
877 fn = (char *) get_fixed_heap_space ((size_t) fnwid);
878 bufcpy (fn, fnb, fnwid);
879 /* Recursive include? Then *ignore* the file */
880 for (t = top; t != NO_LINE; t = NEXT (t)) {
881 if (strcmp (FILENAME (t), fn) == 0) {
882 goto search_next_pragmat; /* Eeek! */
883 }
884 }
885 /* Access the file */
886 RESET_ERRNO;
887 fd = open (fn, O_RDONLY | O_BINARY);
888 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, "*%s \"%s\"", ERROR_SOURCE_FILE_OPEN, fn) >= 0);
889 SCAN_ERROR (fd == -1, start_l, start_c, edit_line);
890 /* Access the file */
891 RESET_ERRNO;
892 fsize = (int) lseek (fd, 0, SEEK_END);
893 ASSERT (fsize >= 0);
894 SCAN_ERROR (errno != 0, start_l, start_c, ERROR_FILE_READ);
895 fbuf = (char *) get_temp_heap_space ((unsigned) (8 + fsize));
896 RESET_ERRNO;
897 ASSERT (lseek (fd, 0, SEEK_SET) >= 0);
898 SCAN_ERROR (errno != 0, start_l, start_c, ERROR_FILE_READ);
899 RESET_ERRNO;
900 bytes_read = (int) io_read (fd, fbuf, (size_t) fsize);
901 SCAN_ERROR (errno != 0 || bytes_read != fsize, start_l, start_c, ERROR_FILE_READ);
902 /* Buffer still usable? */
903 if (fsize > max_scan_buf_length) {
904 max_scan_buf_length = fsize;
905 scan_buf = (char *) get_temp_heap_space ((unsigned) (8 + max_scan_buf_length));
906 }
907 /* Link all lines into the list */
908 linum = 1;
909 s = u;
910 t = PREVIOUS (u);
911 k = 0;
912 if (fsize == 0) {
913 /* If file is empty, insert single empty line */
914 scan_buf[0] = NEWLINE_CHAR;
915 scan_buf[1] = NULL_CHAR;
916 append_source_line (scan_buf, &t, &linum, fn);
917 } else
918 while (k < fsize) {
919 n = 0;
920 scan_buf[0] = NULL_CHAR;
921 while (k < fsize && fbuf[k] != NEWLINE_CHAR) {
922 SCAN_ERROR ((IS_CNTRL (fbuf[k]) && !IS_SPACE (fbuf[k])) || fbuf[k] == STOP_CHAR, start_l, start_c, ERROR_FILE_INCLUDE_CTRL);
923 scan_buf[n++] = fbuf[k++];
924 scan_buf[n] = NULL_CHAR;
925 }
926 scan_buf[n++] = NEWLINE_CHAR;
927 scan_buf[n] = NULL_CHAR;
928 if (k < fsize) {
929 k++;
930 }
931 append_source_line (scan_buf, &t, &linum, fn);
932 }
933 /* Conclude and go find another include directive, if any */
934 NEXT (t) = s;
935 PREVIOUS (s) = t;
936 concatenate_lines (top);
937 ASSERT (close (fd) == 0);
938 make_pass = A68_TRUE;
939 }
940 search_next_pragmat: /* skip */ ;
941 }
942 }
943 }
944
945 /**
946 @brief Append a source line to the internal source file.
947 @param str Text line to be appended.
948 @param ref_l Previous source line.
949 @param line_num Previous source line number.
950 @param filename Name of file being read.
951 **/
952
953 static void
append_source_line(char * str,LINE_T ** ref_l,int * line_num,char * filename)954 append_source_line (char *str, LINE_T ** ref_l, int *line_num, char *filename)
955 {
956 LINE_T *z = new_source_line ();
957 /* Allow shell command in first line, f.i. "#!/usr/share/bin/a68g" */
958 if (*line_num == 1) {
959 if (strlen (str) >= 2 && strncmp (str, "#!", 2) == 0) {
960 ABEND (strstr (str, "run-script") != NO_TEXT, ERROR_SHELL_SCRIPT, NO_TEXT);
961 (*line_num)++;
962 return;
963 }
964 }
965 /* Link line into the chain */
966 STRING (z) = new_fixed_string (str);
967 FILENAME (z) = filename;
968 NUMBER (z) = (*line_num)++;
969 PRINT_STATUS (z) = NOT_PRINTED;
970 LIST (z) = A68_TRUE;
971 DIAGNOSTICS (z) = NO_DIAGNOSTIC;
972 NEXT (z) = NO_LINE;
973 PREVIOUS (z) = *ref_l;
974 if (TOP_LINE (&program) == NO_LINE) {
975 TOP_LINE (&program) = z;
976 }
977 if (*ref_l != NO_LINE) {
978 NEXT (*ref_l) = z;
979 }
980 *ref_l = z;
981 }
982
983 /**
984 @brief Size of source file.
985 @return Size of file.
986 **/
987
988 static int
get_source_size(void)989 get_source_size (void)
990 {
991 FILE_T f = FILE_SOURCE_FD (&program);
992 /* This is why WIN32 must open as "read binary" */
993 return ((int) lseek (f, 0, SEEK_END));
994 }
995
996 /**
997 @brief Append environment source lines.
998 @param str Line to append.
999 @param ref_l Source line after which to append.
1000 @param line_num Number of source line 'ref_l'.
1001 @param name Either "prelude" or "postlude".
1002 **/
1003
1004 static void
append_environ(char * str[],LINE_T ** ref_l,int * line_num,char * name)1005 append_environ (char *str[], LINE_T ** ref_l, int *line_num, char *name)
1006 {
1007 int k;
1008 for (k = 0; str[k] != NO_TEXT; k++) {
1009 int zero_line_num = 0;
1010 (*line_num)++;
1011 append_source_line (str[k], ref_l, &zero_line_num, name);
1012 }
1013 /*
1014 char *text = new_string (str, NO_TEXT);
1015 while (text != NO_TEXT && text[0] != NULL_CHAR) {
1016 char *car = text;
1017 char *cdr = a68g_strchr (text, '!');
1018 int zero_line_num = 0;
1019 cdr[0] = NULL_CHAR;
1020 text = &cdr[1];
1021 (*line_num)++;
1022 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, "%s\n", car) >= 0);
1023 append_source_line (edit_line, ref_l, &zero_line_num, name);
1024 }
1025 */
1026 }
1027
1028 /**
1029 @brief Read script file and make internal copy.
1030 @return Whether reading is satisfactory .
1031 **/
1032
1033 static BOOL_T
read_script_file(void)1034 read_script_file (void)
1035 {
1036 LINE_T *ref_l = NO_LINE;
1037 int k, n, num;
1038 unsigned len;
1039 BOOL_T file_end = A68_FALSE;
1040 char filename[BUFFER_SIZE], linenum[BUFFER_SIZE];
1041 char ch, *fn, *line;
1042 char *buffer = (char *) get_temp_heap_space ((unsigned) (8 + source_file_size));
1043 FILE_T source = FILE_SOURCE_FD (&program);
1044 ABEND (source == -1, "source file not open", NO_TEXT);
1045 buffer[0] = NULL_CHAR;
1046 n = 0;
1047 len = (unsigned) (8 + source_file_size);
1048 buffer = (char *) get_temp_heap_space (len);
1049 ASSERT (lseek (source, 0, SEEK_SET) >= 0);
1050 while (!file_end) {
1051 /* Read the original file name */
1052 filename[0] = NULL_CHAR;
1053 k = 0;
1054 if (io_read (source, &ch, 1) == 0) {
1055 file_end = A68_TRUE;
1056 continue;
1057 }
1058 while (ch != NEWLINE_CHAR) {
1059 filename[k++] = ch;
1060 ASSERT (io_read (source, &ch, 1) == 1);
1061 }
1062 filename[k] = NULL_CHAR;
1063 fn = TEXT (add_token (&top_token, filename));
1064 /* Read the original file number */
1065 linenum[0] = NULL_CHAR;
1066 k = 0;
1067 ASSERT (io_read (source, &ch, 1) == 1);
1068 while (ch != NEWLINE_CHAR) {
1069 linenum[k++] = ch;
1070 ASSERT (io_read (source, &ch, 1) == 1);
1071 }
1072 linenum[k] = NULL_CHAR;
1073 num = (int) strtol (linenum, NO_VAR, 10);
1074 ABEND (errno == ERANGE, "strange line number", NO_TEXT);
1075 /* COPY original line into buffer */
1076 ASSERT (io_read (source, &ch, 1) == 1);
1077 line = &buffer[n];
1078 while (ch != NEWLINE_CHAR) {
1079 buffer[n++] = ch;
1080 ASSERT (io_read (source, &ch, 1) == 1);
1081 ABEND ((unsigned) n >= len, "buffer overflow", NO_TEXT);
1082 }
1083 buffer[n++] = NEWLINE_CHAR;
1084 buffer[n] = NULL_CHAR;
1085 append_source_line (line, &ref_l, &num, fn);
1086 }
1087 return (A68_TRUE);
1088 }
1089
1090 /**
1091 @brief Read source file and make internal copy.
1092 @return Whether reading is satisfactory .
1093 **/
1094
1095 static BOOL_T
read_source_file(void)1096 read_source_file (void)
1097 {
1098 LINE_T *ref_l = NO_LINE;
1099 int line_num = 0, k, bytes_read;
1100 ssize_t l;
1101 FILE_T f = FILE_SOURCE_FD (&program);
1102 char **prelude_start, **postlude, *buffer;
1103 /* Prelude */
1104 if (OPTION_STROPPING (&program) == UPPER_STROPPING) {
1105 prelude_start = bold_prelude_start;
1106 postlude = bold_postlude;
1107 } else if (OPTION_STROPPING (&program) == QUOTE_STROPPING) {
1108 prelude_start = quote_prelude_start;
1109 postlude = quote_postlude;
1110 } else {
1111 prelude_start = postlude = NO_VAR;
1112 }
1113 append_environ (prelude_start, &ref_l, &line_num, "prelude");
1114 /* Read the file into a single buffer, so we save on system calls */
1115 line_num = 1;
1116 buffer = (char *) get_temp_heap_space ((unsigned) (8 + source_file_size));
1117 RESET_ERRNO;
1118 ASSERT (lseek (f, 0, SEEK_SET) >= 0);
1119 ABEND (errno != 0, "error while reading source file", NO_TEXT);
1120 RESET_ERRNO;
1121 bytes_read = (int) io_read (f, buffer, (size_t) source_file_size);
1122 ABEND (errno != 0 || bytes_read != source_file_size, "error while reading source file", NO_TEXT);
1123 /* Link all lines into the list */
1124 k = 0;
1125 while (k < source_file_size) {
1126 l = 0;
1127 scan_buf[0] = NULL_CHAR;
1128 while (k < source_file_size && buffer[k] != NEWLINE_CHAR) {
1129 if (k < source_file_size - 1 && buffer[k] == CR_CHAR && buffer[k + 1] == NEWLINE_CHAR) {
1130 k++;
1131 } else {
1132 scan_buf[l++] = buffer[k++];
1133 scan_buf[l] = NULL_CHAR;
1134 }
1135 }
1136 scan_buf[l++] = NEWLINE_CHAR;
1137 scan_buf[l] = NULL_CHAR;
1138 if (k < source_file_size) {
1139 k++;
1140 }
1141 append_source_line (scan_buf, &ref_l, &line_num, FILE_SOURCE_NAME (&program));
1142 SCAN_ERROR (l != (ssize_t) strlen (scan_buf), NO_LINE, NO_TEXT, ERROR_FILE_SOURCE_CTRL);
1143 }
1144 /* Postlude */
1145 append_environ (postlude, &ref_l, &line_num, "postlude");
1146 /* Concatenate lines */
1147 concatenate_lines (TOP_LINE (&program));
1148 /* Include files */
1149 include_files (TOP_LINE (&program));
1150 return (A68_TRUE);
1151 }
1152
1153 /**
1154 @brief Next_char get next character from internal copy of source file.
1155 @param ref_l Source line we're scanning.
1156 @param ref_s Character (in source line) we're scanning.
1157 @param allow_typo Whether typographical display features are allowed.
1158 @return Next char on input.
1159 **/
1160
1161 static char
next_char(LINE_T ** ref_l,char ** ref_s,BOOL_T allow_typo)1162 next_char (LINE_T ** ref_l, char **ref_s, BOOL_T allow_typo)
1163 {
1164 char ch;
1165 #if defined NO_TYPO
1166 allow_typo = A68_FALSE;
1167 #endif
1168 LOW_STACK_ALERT (NO_NODE);
1169 /* Source empty? */
1170 if (*ref_l == NO_LINE) {
1171 return (STOP_CHAR);
1172 } else {
1173 LIST (*ref_l) = (BOOL_T) (OPTION_NODEMASK (&program) & SOURCE_MASK ? A68_TRUE : A68_FALSE);
1174 /* Take new line? */
1175 if ((*ref_s)[0] == NEWLINE_CHAR || (*ref_s)[0] == NULL_CHAR) {
1176 *ref_l = NEXT (*ref_l);
1177 if (*ref_l == NO_LINE) {
1178 return (STOP_CHAR);
1179 }
1180 *ref_s = STRING (*ref_l);
1181 } else {
1182 (*ref_s)++;
1183 }
1184 /* Deliver next char */
1185 ch = (*ref_s)[0];
1186 if (allow_typo && (IS_SPACE (ch) || ch == FORMFEED_CHAR)) {
1187 ch = next_char (ref_l, ref_s, allow_typo);
1188 }
1189 return (ch);
1190 }
1191 }
1192
1193 /**
1194 @brief Find first character that can start a valid symbol.
1195 @param ref_c Pointer to character.
1196 @param ref_l Source line we're scanning.
1197 @param ref_s Character (in source line) we're scanning.
1198 **/
1199
1200 static void
get_good_char(char * ref_c,LINE_T ** ref_l,char ** ref_s)1201 get_good_char (char *ref_c, LINE_T ** ref_l, char **ref_s)
1202 {
1203 while (*ref_c != STOP_CHAR && (IS_SPACE (*ref_c) || (*ref_c == NULL_CHAR))) {
1204 if (*ref_l != NO_LINE) {
1205 LIST (*ref_l) = (BOOL_T) (OPTION_NODEMASK (&program) & SOURCE_MASK ? A68_TRUE : A68_FALSE);
1206 }
1207 *ref_c = next_char (ref_l, ref_s, A68_FALSE);
1208 }
1209 }
1210
1211 /**
1212 @brief Handle a pragment (pragmat or comment).
1213 @param type Type of pragment (#, CO, COMMENT, PR, PRAGMAT).
1214 @param ref_l Source line we're scanning.
1215 @param ref_c Character (in source line) we're scanning.
1216 @return Pragment text as a string for binding in the tree.
1217 **/
1218
1219 static char *
pragment(int type,LINE_T ** ref_l,char ** ref_c)1220 pragment (int type, LINE_T ** ref_l, char **ref_c)
1221 {
1222 #define INIT_BUFFER {chars_in_buf = 0; scan_buf[chars_in_buf] = NULL_CHAR;}
1223 #define ADD_ONE_CHAR(ch) {scan_buf[chars_in_buf ++] = ch; scan_buf[chars_in_buf] = NULL_CHAR;}
1224 char c = **ref_c, *term_s = NO_TEXT, *start_c = *ref_c;
1225 char *z;
1226 LINE_T *start_l = *ref_l;
1227 int term_s_length, chars_in_buf;
1228 BOOL_T stop, pragmat = A68_FALSE;
1229 /* Set terminator */
1230 if (OPTION_STROPPING (&program) == UPPER_STROPPING) {
1231 if (type == STYLE_I_COMMENT_SYMBOL) {
1232 term_s = "CO";
1233 } else if (type == STYLE_II_COMMENT_SYMBOL) {
1234 term_s = "#";
1235 } else if (type == BOLD_COMMENT_SYMBOL) {
1236 term_s = "COMMENT";
1237 } else if (type == STYLE_I_PRAGMAT_SYMBOL) {
1238 term_s = "PR";
1239 pragmat = A68_TRUE;
1240 } else if (type == BOLD_PRAGMAT_SYMBOL) {
1241 term_s = "PRAGMAT";
1242 pragmat = A68_TRUE;
1243 }
1244 } else if (OPTION_STROPPING (&program) == QUOTE_STROPPING) {
1245 if (type == STYLE_I_COMMENT_SYMBOL) {
1246 term_s = "'CO'";
1247 } else if (type == STYLE_II_COMMENT_SYMBOL) {
1248 term_s = "#";
1249 } else if (type == BOLD_COMMENT_SYMBOL) {
1250 term_s = "'COMMENT'";
1251 } else if (type == STYLE_I_PRAGMAT_SYMBOL) {
1252 term_s = "'PR'";
1253 pragmat = A68_TRUE;
1254 } else if (type == BOLD_PRAGMAT_SYMBOL) {
1255 term_s = "'PRAGMAT'";
1256 pragmat = A68_TRUE;
1257 }
1258 }
1259 term_s_length = (int) strlen (term_s);
1260 /* Scan for terminator */
1261 INIT_BUFFER;
1262 stop = A68_FALSE;
1263 while (stop == A68_FALSE) {
1264 SCAN_ERROR (c == STOP_CHAR, start_l, start_c, ERROR_UNTERMINATED_PRAGMENT);
1265 /* A ".." or '..' delimited string in a PRAGMAT */
1266 if (pragmat && (c == QUOTE_CHAR || (c == '\'' && OPTION_STROPPING (&program) == UPPER_STROPPING))) {
1267 char delim = c;
1268 BOOL_T eos = A68_FALSE;
1269 ADD_ONE_CHAR (c);
1270 c = next_char (ref_l, ref_c, A68_FALSE);
1271 while (!eos) {
1272 SCAN_ERROR (EOL (c), start_l, start_c, ERROR_LONG_STRING);
1273 if (c == delim) {
1274 ADD_ONE_CHAR (delim);
1275 save_state (*ref_l, *ref_c, c);
1276 c = next_char (ref_l, ref_c, A68_FALSE);
1277 if (c == delim) {
1278 c = next_char (ref_l, ref_c, A68_FALSE);
1279 } else {
1280 restore_state (ref_l, ref_c, &c);
1281 eos = A68_TRUE;
1282 }
1283 } else if (IS_PRINT (c)) {
1284 ADD_ONE_CHAR (c);
1285 c = next_char (ref_l, ref_c, A68_FALSE);
1286 } else {
1287 unworthy (start_l, start_c, c);
1288 }
1289 }
1290 } else if (EOL (c)) {
1291 ADD_ONE_CHAR (NEWLINE_CHAR);
1292 } else if (IS_PRINT (c) || IS_SPACE (c)) {
1293 ADD_ONE_CHAR (c);
1294 }
1295 if (chars_in_buf >= term_s_length) {
1296 /* Check whether we encountered the terminator */
1297 stop = (BOOL_T) (strcmp (term_s, &(scan_buf[chars_in_buf - term_s_length])) == 0);
1298 }
1299 c = next_char (ref_l, ref_c, A68_FALSE);
1300 }
1301 scan_buf[chars_in_buf - term_s_length] = NULL_CHAR;
1302 z = new_string (term_s, scan_buf, term_s, NO_TEXT);
1303 if (type == STYLE_I_PRAGMAT_SYMBOL || type == BOLD_PRAGMAT_SYMBOL) {
1304 isolate_options (scan_buf, start_l);
1305 }
1306 return (z);
1307 #undef ADD_ONE_CHAR
1308 #undef INIT_BUFFER
1309 }
1310
1311 /**
1312 @brief Attribute for format item.
1313 @param ch Format item in character form.
1314 @return See brief description.
1315 **/
1316
1317 static int
get_format_item(char ch)1318 get_format_item (char ch)
1319 {
1320 switch (TO_LOWER (ch)) {
1321 case 'a':{
1322 return (FORMAT_ITEM_A);
1323 }
1324 case 'b':{
1325 return (FORMAT_ITEM_B);
1326 }
1327 case 'c':{
1328 return (FORMAT_ITEM_C);
1329 }
1330 case 'd':{
1331 return (FORMAT_ITEM_D);
1332 }
1333 case 'e':{
1334 return (FORMAT_ITEM_E);
1335 }
1336 case 'f':{
1337 return (FORMAT_ITEM_F);
1338 }
1339 case 'g':{
1340 return (FORMAT_ITEM_G);
1341 }
1342 case 'h':{
1343 return (FORMAT_ITEM_H);
1344 }
1345 case 'i':{
1346 return (FORMAT_ITEM_I);
1347 }
1348 case 'j':{
1349 return (FORMAT_ITEM_J);
1350 }
1351 case 'k':{
1352 return (FORMAT_ITEM_K);
1353 }
1354 case 'l':
1355 case '/':{
1356 return (FORMAT_ITEM_L);
1357 }
1358 case 'm':{
1359 return (FORMAT_ITEM_M);
1360 }
1361 case 'n':{
1362 return (FORMAT_ITEM_N);
1363 }
1364 case 'o':{
1365 return (FORMAT_ITEM_O);
1366 }
1367 case 'p':{
1368 return (FORMAT_ITEM_P);
1369 }
1370 case 'q':{
1371 return (FORMAT_ITEM_Q);
1372 }
1373 case 'r':{
1374 return (FORMAT_ITEM_R);
1375 }
1376 case 's':{
1377 return (FORMAT_ITEM_S);
1378 }
1379 case 't':{
1380 return (FORMAT_ITEM_T);
1381 }
1382 case 'u':{
1383 return (FORMAT_ITEM_U);
1384 }
1385 case 'v':{
1386 return (FORMAT_ITEM_V);
1387 }
1388 case 'w':{
1389 return (FORMAT_ITEM_W);
1390 }
1391 case 'x':{
1392 return (FORMAT_ITEM_X);
1393 }
1394 case 'y':{
1395 return (FORMAT_ITEM_Y);
1396 }
1397 case 'z':{
1398 return (FORMAT_ITEM_Z);
1399 }
1400 case '+':{
1401 return (FORMAT_ITEM_PLUS);
1402 }
1403 case '-':{
1404 return (FORMAT_ITEM_MINUS);
1405 }
1406 case POINT_CHAR:{
1407 return (FORMAT_ITEM_POINT);
1408 }
1409 case '%':{
1410 return (FORMAT_ITEM_ESCAPE);
1411 }
1412 default:{
1413 return (0);
1414 }
1415 }
1416 }
1417
1418 /* Macros */
1419
1420 #define SCAN_DIGITS(c)\
1421 while (IS_DIGIT (c)) {\
1422 (sym++)[0] = (c);\
1423 (c) = next_char (ref_l, ref_s, A68_TRUE);\
1424 }
1425
1426 #define SCAN_EXPONENT_PART(c)\
1427 (sym++)[0] = EXPONENT_CHAR;\
1428 (c) = next_char (ref_l, ref_s, A68_TRUE);\
1429 if ((c) == '+' || (c) == '-') {\
1430 (sym++)[0] = (c);\
1431 (c) = next_char (ref_l, ref_s, A68_TRUE);\
1432 }\
1433 SCAN_ERROR (!IS_DIGIT (c), *start_l, *start_c, ERROR_EXPONENT_DIGIT);\
1434 SCAN_DIGITS (c)
1435
1436 /**
1437 @brief Whether input shows exponent character.
1438 @param ref_l Source line we're scanning.
1439 @param ref_s Character (in source line) we're scanning.
1440 @param ch Last scanned char.
1441 @return See brief description.
1442 **/
1443
1444 static BOOL_T
is_exp_char(LINE_T ** ref_l,char ** ref_s,char * ch)1445 is_exp_char (LINE_T ** ref_l, char **ref_s, char *ch)
1446 {
1447 BOOL_T ret = A68_FALSE;
1448 char exp_syms[3];
1449 if (OPTION_STROPPING (&program) == UPPER_STROPPING) {
1450 exp_syms[0] = EXPONENT_CHAR;
1451 exp_syms[1] = (char) TO_UPPER (EXPONENT_CHAR);
1452 exp_syms[2] = NULL_CHAR;
1453 } else {
1454 exp_syms[0] = (char) TO_UPPER (EXPONENT_CHAR);
1455 exp_syms[1] = BACKSLASH_CHAR;
1456 exp_syms[2] = NULL_CHAR;
1457 }
1458 save_state (*ref_l, *ref_s, *ch);
1459 if (strchr (exp_syms, *ch) != NO_TEXT) {
1460 *ch = next_char (ref_l, ref_s, A68_TRUE);
1461 ret = (BOOL_T) (strchr ("+-0123456789", *ch) != NO_TEXT);
1462 }
1463 restore_state (ref_l, ref_s, ch);
1464 return (ret);
1465 }
1466
1467 /**
1468 @brief Whether input shows radix character.
1469 @param ref_l Source line we're scanning.
1470 @param ref_s Character (in source line) we're scanning.
1471 @param ch Character to test.
1472 @return See brief description.
1473 **/
1474
1475 static BOOL_T
is_radix_char(LINE_T ** ref_l,char ** ref_s,char * ch)1476 is_radix_char (LINE_T ** ref_l, char **ref_s, char *ch)
1477 {
1478 BOOL_T ret = A68_FALSE;
1479 save_state (*ref_l, *ref_s, *ch);
1480 if (OPTION_STROPPING (&program) == QUOTE_STROPPING) {
1481 if (*ch == TO_UPPER (RADIX_CHAR)) {
1482 *ch = next_char (ref_l, ref_s, A68_TRUE);
1483 ret = (BOOL_T) (strchr ("0123456789ABCDEF", *ch) != NO_TEXT);
1484 }
1485 } else {
1486 if (*ch == RADIX_CHAR) {
1487 *ch = next_char (ref_l, ref_s, A68_TRUE);
1488 ret = (BOOL_T) (strchr ("0123456789abcdef", *ch) != NO_TEXT);
1489 }
1490 }
1491 restore_state (ref_l, ref_s, ch);
1492 return (ret);
1493 }
1494
1495 /**
1496 @brief Whether input shows decimal point.
1497 @param ref_l Source line we're scanning.
1498 @param ref_s Character (in source line) we're scanning.
1499 @param ch Character to test.
1500 @return See brief description.
1501 **/
1502
1503 static BOOL_T
is_decimal_point(LINE_T ** ref_l,char ** ref_s,char * ch)1504 is_decimal_point (LINE_T ** ref_l, char **ref_s, char *ch)
1505 {
1506 BOOL_T ret = A68_FALSE;
1507 save_state (*ref_l, *ref_s, *ch);
1508 if (*ch == POINT_CHAR) {
1509 char exp_syms[3];
1510 if (OPTION_STROPPING (&program) == UPPER_STROPPING) {
1511 exp_syms[0] = EXPONENT_CHAR;
1512 exp_syms[1] = (char) TO_UPPER (EXPONENT_CHAR);
1513 exp_syms[2] = NULL_CHAR;
1514 } else {
1515 exp_syms[0] = (char) TO_UPPER (EXPONENT_CHAR);
1516 exp_syms[1] = BACKSLASH_CHAR;
1517 exp_syms[2] = NULL_CHAR;
1518 }
1519 *ch = next_char (ref_l, ref_s, A68_TRUE);
1520 if (strchr (exp_syms, *ch) != NO_TEXT) {
1521 *ch = next_char (ref_l, ref_s, A68_TRUE);
1522 ret = (BOOL_T) (strchr ("+-0123456789", *ch) != NO_TEXT);
1523 } else {
1524 ret = (BOOL_T) (strchr ("0123456789", *ch) != NO_TEXT);
1525 }
1526 }
1527 restore_state (ref_l, ref_s, ch);
1528 return (ret);
1529 }
1530
1531 /**
1532 @brief Get next token from internal copy of source file..
1533 @param in_format Are we scanning a format text.
1534 @param ref_l Source line we're scanning.
1535 @param ref_s Character (in source line) we're scanning.
1536 @param start_l Line where token starts.
1537 @param start_c Character where token starts.
1538 @param att Attribute designated to token.
1539 **/
1540
1541 static void
get_next_token(BOOL_T in_format,LINE_T ** ref_l,char ** ref_s,LINE_T ** start_l,char ** start_c,int * att)1542 get_next_token (BOOL_T in_format, LINE_T ** ref_l, char **ref_s, LINE_T ** start_l, char **start_c, int *att)
1543 {
1544 char c = **ref_s, *sym = scan_buf;
1545 sym[0] = NULL_CHAR;
1546 get_good_char (&c, ref_l, ref_s);
1547 *start_l = *ref_l;
1548 *start_c = *ref_s;
1549 if (c == STOP_CHAR) {
1550 /* We are at EOF */
1551 (sym++)[0] = STOP_CHAR;
1552 sym[0] = NULL_CHAR;
1553 return;
1554 }
1555 /***************/
1556 /* In a format */
1557 /***************/
1558 if (in_format) {
1559 char *format_items;
1560 if (OPTION_STROPPING (&program) == UPPER_STROPPING) {
1561 format_items = "/%\\+-.abcdefghijklmnopqrstuvwxyz";
1562 } else { /* if (OPTION_STROPPING (&program) == QUOTE_STROPPING) */
1563 format_items = "/%\\+-.ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1564 }
1565 if (a68g_strchr (format_items, c) != NO_TEXT) {
1566 /* General format items */
1567 (sym++)[0] = c;
1568 sym[0] = NULL_CHAR;
1569 *att = get_format_item (c);
1570 (void) next_char (ref_l, ref_s, A68_FALSE);
1571 return;
1572 }
1573 if (IS_DIGIT (c)) {
1574 /* INT denotation for static replicator */
1575 SCAN_DIGITS (c);
1576 sym[0] = NULL_CHAR;
1577 *att = STATIC_REPLICATOR;
1578 return;
1579 }
1580 }
1581 /*******************/
1582 /* Not in a format */
1583 /*******************/
1584 if (IS_UPPER (c)) {
1585 if (OPTION_STROPPING (&program) == UPPER_STROPPING) {
1586 /* Upper case word - bold tag */
1587 while (IS_UPPER (c) || c == '_') {
1588 (sym++)[0] = c;
1589 c = next_char (ref_l, ref_s, A68_FALSE);
1590 }
1591 sym[0] = NULL_CHAR;
1592 *att = BOLD_TAG;
1593 } else if (OPTION_STROPPING (&program) == QUOTE_STROPPING) {
1594 while (IS_UPPER (c) || IS_DIGIT (c) || c == '_') {
1595 (sym++)[0] = c;
1596 c = next_char (ref_l, ref_s, A68_TRUE);
1597 }
1598 sym[0] = NULL_CHAR;
1599 *att = IDENTIFIER;
1600 }
1601 } else if (c == '\'') {
1602 /* Quote, uppercase word, quote - bold tag */
1603 int k = 0;
1604 c = next_char (ref_l, ref_s, A68_FALSE);
1605 while (IS_UPPER (c) || IS_DIGIT (c) || c == '_') {
1606 (sym++)[0] = c;
1607 k++;
1608 c = next_char (ref_l, ref_s, A68_TRUE);
1609 }
1610 SCAN_ERROR (k == 0, *start_l, *start_c, ERROR_QUOTED_BOLD_TAG);
1611 sym[0] = NULL_CHAR;
1612 *att = BOLD_TAG;
1613 /* Skip terminating quote, or complain if it is not there */
1614 SCAN_ERROR (c != '\'', *start_l, *start_c, ERROR_QUOTED_BOLD_TAG);
1615 c = next_char (ref_l, ref_s, A68_FALSE);
1616 } else if (IS_LOWER (c)) {
1617 /* Lower case word - identifier */
1618 while (IS_LOWER (c) || IS_DIGIT (c) || c == '_') {
1619 (sym++)[0] = c;
1620 c = next_char (ref_l, ref_s, A68_TRUE);
1621 }
1622 sym[0] = NULL_CHAR;
1623 *att = IDENTIFIER;
1624 } else if (c == POINT_CHAR) {
1625 /* Begins with a point symbol - point, dotdot, L REAL denotation */
1626 if (is_decimal_point (ref_l, ref_s, &c)) {
1627 (sym++)[0] = '0';
1628 (sym++)[0] = POINT_CHAR;
1629 c = next_char (ref_l, ref_s, A68_TRUE);
1630 SCAN_DIGITS (c);
1631 if (is_exp_char (ref_l, ref_s, &c)) {
1632 SCAN_EXPONENT_PART (c);
1633 }
1634 sym[0] = NULL_CHAR;
1635 *att = REAL_DENOTATION;
1636 } else {
1637 c = next_char (ref_l, ref_s, A68_TRUE);
1638 if (c == POINT_CHAR) {
1639 (sym++)[0] = POINT_CHAR;
1640 (sym++)[0] = POINT_CHAR;
1641 sym[0] = NULL_CHAR;
1642 *att = DOTDOT_SYMBOL;
1643 c = next_char (ref_l, ref_s, A68_FALSE);
1644 } else {
1645 (sym++)[0] = POINT_CHAR;
1646 sym[0] = NULL_CHAR;
1647 *att = POINT_SYMBOL;
1648 }
1649 }
1650 } else if (IS_DIGIT (c)) {
1651 /* Something that begins with a digit - L INT denotation, L REAL denotation */
1652 SCAN_DIGITS (c);
1653 if (is_decimal_point (ref_l, ref_s, &c)) {
1654 c = next_char (ref_l, ref_s, A68_TRUE);
1655 if (is_exp_char (ref_l, ref_s, &c)) {
1656 (sym++)[0] = POINT_CHAR;
1657 (sym++)[0] = '0';
1658 SCAN_EXPONENT_PART (c);
1659 *att = REAL_DENOTATION;
1660 } else {
1661 (sym++)[0] = POINT_CHAR;
1662 SCAN_DIGITS (c);
1663 if (is_exp_char (ref_l, ref_s, &c)) {
1664 SCAN_EXPONENT_PART (c);
1665 }
1666 *att = REAL_DENOTATION;
1667 }
1668 } else if (is_exp_char (ref_l, ref_s, &c)) {
1669 SCAN_EXPONENT_PART (c);
1670 *att = REAL_DENOTATION;
1671 } else if (is_radix_char (ref_l, ref_s, &c)) {
1672 (sym++)[0] = c;
1673 c = next_char (ref_l, ref_s, A68_TRUE);
1674 if (OPTION_STROPPING (&program) == UPPER_STROPPING) {
1675 while (IS_DIGIT (c) || strchr ("abcdef", c) != NO_TEXT) {
1676 (sym++)[0] = c;
1677 c = next_char (ref_l, ref_s, A68_TRUE);
1678 }
1679 } else {
1680 while (IS_DIGIT (c) || strchr ("ABCDEF", c) != NO_TEXT) {
1681 (sym++)[0] = c;
1682 c = next_char (ref_l, ref_s, A68_TRUE);
1683 }
1684 }
1685 *att = BITS_DENOTATION;
1686 } else {
1687 *att = INT_DENOTATION;
1688 }
1689 sym[0] = NULL_CHAR;
1690 } else if (c == QUOTE_CHAR) {
1691 /* STRING denotation */
1692 BOOL_T stop = A68_FALSE;
1693 while (!stop) {
1694 c = next_char (ref_l, ref_s, A68_FALSE);
1695 while (c != QUOTE_CHAR && c != STOP_CHAR) {
1696 SCAN_ERROR (EOL (c), *start_l, *start_c, ERROR_LONG_STRING);
1697 (sym++)[0] = c;
1698 c = next_char (ref_l, ref_s, A68_FALSE);
1699 }
1700 SCAN_ERROR (*ref_l == NO_LINE, *start_l, *start_c, ERROR_UNTERMINATED_STRING);
1701 c = next_char (ref_l, ref_s, A68_FALSE);
1702 if (c == QUOTE_CHAR) {
1703 (sym++)[0] = QUOTE_CHAR;
1704 } else {
1705 stop = A68_TRUE;
1706 }
1707 }
1708 sym[0] = NULL_CHAR;
1709 *att = (in_format ? LITERAL : ROW_CHAR_DENOTATION);
1710 } else if (a68g_strchr ("#$()[]{},;@", c) != NO_TEXT) {
1711 /* Single character symbols */
1712 (sym++)[0] = c;
1713 (void) next_char (ref_l, ref_s, A68_FALSE);
1714 sym[0] = NULL_CHAR;
1715 *att = 0;
1716 } else if (c == '|') {
1717 /* Bar */
1718 (sym++)[0] = c;
1719 c = next_char (ref_l, ref_s, A68_FALSE);
1720 if (c == ':') {
1721 (sym++)[0] = c;
1722 (void) next_char (ref_l, ref_s, A68_FALSE);
1723 }
1724 sym[0] = NULL_CHAR;
1725 *att = 0;
1726 } else if (c == '!' && OPTION_STROPPING (&program) == QUOTE_STROPPING) {
1727 /* Bar, will be replaced with modern variant.
1728 For this reason ! is not a MONAD with quote-stropping */
1729 (sym++)[0] = '|';
1730 c = next_char (ref_l, ref_s, A68_FALSE);
1731 if (c == ':') {
1732 (sym++)[0] = c;
1733 (void) next_char (ref_l, ref_s, A68_FALSE);
1734 }
1735 sym[0] = NULL_CHAR;
1736 *att = 0;
1737 } else if (c == ':') {
1738 /* Colon, semicolon, IS, ISNT */
1739 (sym++)[0] = c;
1740 c = next_char (ref_l, ref_s, A68_FALSE);
1741 if (c == '=') {
1742 (sym++)[0] = c;
1743 if ((c = next_char (ref_l, ref_s, A68_FALSE)) == ':') {
1744 (sym++)[0] = c;
1745 c = next_char (ref_l, ref_s, A68_FALSE);
1746 }
1747 } else if (c == '/') {
1748 (sym++)[0] = c;
1749 if ((c = next_char (ref_l, ref_s, A68_FALSE)) == '=') {
1750 (sym++)[0] = c;
1751 if ((c = next_char (ref_l, ref_s, A68_FALSE)) == ':') {
1752 (sym++)[0] = c;
1753 c = next_char (ref_l, ref_s, A68_FALSE);
1754 }
1755 }
1756 } else if (c == ':') {
1757 (sym++)[0] = c;
1758 if ((c = next_char (ref_l, ref_s, A68_FALSE)) == '=') {
1759 (sym++)[0] = c;
1760 }
1761 }
1762 sym[0] = NULL_CHAR;
1763 *att = 0;
1764 } else if (c == '=') {
1765 /* Operator starting with "=" */
1766 char *scanned = sym;
1767 (sym++)[0] = c;
1768 c = next_char (ref_l, ref_s, A68_FALSE);
1769 if (a68g_strchr (NOMADS, c) != NO_TEXT) {
1770 (sym++)[0] = c;
1771 c = next_char (ref_l, ref_s, A68_FALSE);
1772 }
1773 if (c == '=') {
1774 (sym++)[0] = c;
1775 if (next_char (ref_l, ref_s, A68_FALSE) == ':') {
1776 (sym++)[0] = ':';
1777 c = next_char (ref_l, ref_s, A68_FALSE);
1778 if (strlen (sym) < 4 && c == '=') {
1779 (sym++)[0] = '=';
1780 (void) next_char (ref_l, ref_s, A68_FALSE);
1781 }
1782 }
1783 } else if (c == ':') {
1784 (sym++)[0] = c;
1785 sym[0] = NULL_CHAR;
1786 if (next_char (ref_l, ref_s, A68_FALSE) == '=') {
1787 (sym++)[0] = '=';
1788 (void) next_char (ref_l, ref_s, A68_FALSE);
1789 } else {
1790 SCAN_ERROR (!(strcmp (scanned, "=:") == 0 || strcmp (scanned, "==:") == 0), *start_l, *start_c, ERROR_INVALID_OPERATOR_TAG);
1791 }
1792 }
1793 sym[0] = NULL_CHAR;
1794 if (strcmp (scanned, "=") == 0) {
1795 *att = EQUALS_SYMBOL;
1796 } else {
1797 *att = OPERATOR;
1798 }
1799 } else if (a68g_strchr (MONADS, c) != NO_TEXT || a68g_strchr (NOMADS, c) != NO_TEXT) {
1800 /* Operator */
1801 char *scanned = sym;
1802 (sym++)[0] = c;
1803 c = next_char (ref_l, ref_s, A68_FALSE);
1804 if (a68g_strchr (NOMADS, c) != NO_TEXT) {
1805 (sym++)[0] = c;
1806 c = next_char (ref_l, ref_s, A68_FALSE);
1807 }
1808 if (c == '=') {
1809 (sym++)[0] = c;
1810 if (next_char (ref_l, ref_s, A68_FALSE) == ':') {
1811 (sym++)[0] = ':';
1812 c = next_char (ref_l, ref_s, A68_FALSE);
1813 if (strlen (scanned) < 4 && c == '=') {
1814 (sym++)[0] = '=';
1815 (void) next_char (ref_l, ref_s, A68_FALSE);
1816 }
1817 }
1818 } else if (c == ':') {
1819 (sym++)[0] = c;
1820 sym[0] = NULL_CHAR;
1821 if (next_char (ref_l, ref_s, A68_FALSE) == '=') {
1822 (sym++)[0] = '=';
1823 sym[0] = NULL_CHAR;
1824 (void) next_char (ref_l, ref_s, A68_FALSE);
1825 } else {
1826 SCAN_ERROR (strcmp (&(scanned[1]), "=:") != 0, *start_l, *start_c, ERROR_INVALID_OPERATOR_TAG);
1827 }
1828 }
1829 sym[0] = NULL_CHAR;
1830 *att = OPERATOR;
1831 } else {
1832 /* Afuuus ... strange characters! */
1833 unworthy (*start_l, *start_c, (int) c);
1834 }
1835 }
1836
1837 /**
1838 @brief Whether att opens an embedded clause.
1839 @param att Attribute under test.
1840 @return Whether att opens an embedded clause.
1841 **/
1842
1843 static BOOL_T
open_nested_clause(int att)1844 open_nested_clause (int att)
1845 {
1846 switch (att) {
1847 case OPEN_SYMBOL:
1848 case BEGIN_SYMBOL:
1849 case PAR_SYMBOL:
1850 case IF_SYMBOL:
1851 case CASE_SYMBOL:
1852 case FOR_SYMBOL:
1853 case FROM_SYMBOL:
1854 case BY_SYMBOL:
1855 case TO_SYMBOL:
1856 case DOWNTO_SYMBOL:
1857 case WHILE_SYMBOL:
1858 case DO_SYMBOL:
1859 case SUB_SYMBOL:
1860 case ACCO_SYMBOL:
1861 {
1862 return (A68_TRUE);
1863 }
1864 }
1865 return (A68_FALSE);
1866 }
1867
1868 /**
1869 @brief Whether att closes an embedded clause.
1870 @param att Attribute under test.
1871 @return Whether att closes an embedded clause.
1872 **/
1873
1874 static BOOL_T
close_nested_clause(int att)1875 close_nested_clause (int att)
1876 {
1877 switch (att) {
1878 case CLOSE_SYMBOL:
1879 case END_SYMBOL:
1880 case FI_SYMBOL:
1881 case ESAC_SYMBOL:
1882 case OD_SYMBOL:
1883 case BUS_SYMBOL:
1884 case OCCA_SYMBOL:
1885 {
1886 return (A68_TRUE);
1887 }
1888 }
1889 return (A68_FALSE);
1890 }
1891
1892 /**
1893 @brief Cast a string to lower case.
1894 @param p String to cast.
1895 **/
1896
1897 static void
make_lower_case(char * p)1898 make_lower_case (char *p)
1899 {
1900 for (; p != NO_TEXT && p[0] != NULL_CHAR; p++) {
1901 p[0] = (char) TO_LOWER (p[0]);
1902 }
1903 }
1904
1905 /**
1906 @brief Construct a linear list of tokens.
1907 @param root Node where to insert new symbol.
1908 @param level Current recursive descent depth.
1909 @param in_format Whether we scan a format.
1910 @param l Current source line.
1911 @param s Current character in source line.
1912 @param start_l Source line where symbol starts.
1913 @param start_c Character where symbol starts.
1914 **/
1915
1916 static void
tokenise_source(NODE_T ** root,int level,BOOL_T in_format,LINE_T ** l,char ** s,LINE_T ** start_l,char ** start_c)1917 tokenise_source (NODE_T ** root, int level, BOOL_T in_format, LINE_T ** l, char **s, LINE_T ** start_l, char **start_c)
1918 {
1919 char *lpr = NO_TEXT;
1920 int lprt = 0;
1921 while (l != NO_VAR && !stop_scanner) {
1922 int att = 0;
1923 get_next_token (in_format, l, s, start_l, start_c, &att);
1924 if (scan_buf[0] == STOP_CHAR) {
1925 stop_scanner = A68_TRUE;
1926 } else if (strlen (scan_buf) > 0 || att == ROW_CHAR_DENOTATION || att == LITERAL) {
1927 KEYWORD_T *kw;
1928 char *c = NO_TEXT;
1929 BOOL_T make_node = A68_TRUE;
1930 char *trailing = NO_TEXT;
1931 if (att != IDENTIFIER) {
1932 kw = find_keyword (top_keyword, scan_buf);
1933 } else {
1934 kw = NO_KEYWORD;
1935 }
1936 if (!(kw != NO_KEYWORD && att != ROW_CHAR_DENOTATION)) {
1937 if (att == IDENTIFIER) {
1938 make_lower_case (scan_buf);
1939 }
1940 if (att != ROW_CHAR_DENOTATION && att != LITERAL) {
1941 int len = (int) strlen (scan_buf);
1942 while (len >= 1 && scan_buf[len - 1] == '_') {
1943 trailing = "_";
1944 scan_buf[len - 1] = NULL_CHAR;
1945 len--;
1946 }
1947 }
1948 c = TEXT (add_token (&top_token, scan_buf));
1949 } else {
1950 if (IS (kw, TO_SYMBOL)) {
1951 /* Merge GO and TO to GOTO */
1952 if (*root != NO_NODE && IS (*root, GO_SYMBOL)) {
1953 ATTRIBUTE (*root) = GOTO_SYMBOL;
1954 NSYMBOL (*root) = TEXT (find_keyword (top_keyword, "GOTO"));
1955 make_node = A68_FALSE;
1956 } else {
1957 att = ATTRIBUTE (kw);
1958 c = TEXT (kw);
1959 }
1960 } else {
1961 if (att == 0 || att == BOLD_TAG) {
1962 att = ATTRIBUTE (kw);
1963 }
1964 c = TEXT (kw);
1965 /* Handle pragments */
1966 if (att == STYLE_II_COMMENT_SYMBOL || att == STYLE_I_COMMENT_SYMBOL || att == BOLD_COMMENT_SYMBOL) {
1967 char *nlpr = pragment (ATTRIBUTE (kw), l, s);
1968 if (lpr == NO_TEXT || (int) strlen (lpr) == 0) {
1969 lpr = nlpr;
1970 } else {
1971 lpr = new_string (lpr, "\n\n", nlpr, NO_TEXT);
1972 }
1973 lprt = att;
1974 make_node = A68_FALSE;
1975 } else if (att == STYLE_I_PRAGMAT_SYMBOL || att == BOLD_PRAGMAT_SYMBOL) {
1976 char *nlpr = pragment (ATTRIBUTE (kw), l, s);
1977 if (lpr == NO_TEXT || (int) strlen (lpr) == 0) {
1978 lpr = nlpr;
1979 } else {
1980 lpr = new_string (lpr, "\n\n", nlpr, NO_TEXT);
1981 }
1982 lprt = att;
1983 if (!stop_scanner) {
1984 (void) set_options (OPTION_LIST (&program), A68_FALSE);
1985 make_node = A68_FALSE;
1986 }
1987 }
1988 }
1989 }
1990 /* Add token to the tree */
1991 if (make_node) {
1992 NODE_T *q = new_node ();
1993 INFO (q) = new_node_info ();
1994 switch (att) {
1995 case ASSIGN_SYMBOL:
1996 case END_SYMBOL:
1997 case ESAC_SYMBOL:
1998 case OD_SYMBOL:
1999 case OF_SYMBOL:
2000 case FI_SYMBOL:
2001 case CLOSE_SYMBOL:
2002 case BUS_SYMBOL:
2003 case COLON_SYMBOL:
2004 case COMMA_SYMBOL:
2005 case DOTDOT_SYMBOL:
2006 case SEMI_SYMBOL:
2007 {
2008 GINFO (q) = NO_GINFO;
2009 break;
2010 }
2011 default:{
2012 GINFO (q) = new_genie_info ();
2013 break;
2014 }
2015 }
2016 STATUS (q) = OPTION_NODEMASK (&program);
2017 LINE (INFO (q)) = *start_l;
2018 CHAR_IN_LINE (INFO (q)) = *start_c;
2019 PRIO (INFO (q)) = 0;
2020 PROCEDURE_LEVEL (INFO (q)) = 0;
2021 ATTRIBUTE (q) = att;
2022 NSYMBOL (q) = c;
2023 PREVIOUS (q) = *root;
2024 SUB (q) = NEXT (q) = NO_NODE;
2025 TABLE (q) = NO_TABLE;
2026 MOID (q) = NO_MOID;
2027 TAX (q) = NO_TAG;
2028 if (lpr != NO_TEXT) {
2029 NPRAGMENT (q) = lpr;
2030 NPRAGMENT_TYPE (q) = lprt;
2031 lpr = NO_TEXT;
2032 lprt = 0;
2033 }
2034 if (*root != NO_NODE) {
2035 NEXT (*root) = q;
2036 }
2037 if (TOP_NODE (&program) == NO_NODE) {
2038 TOP_NODE (&program) = q;
2039 }
2040 *root = q;
2041 if (trailing != NO_TEXT) {
2042 diagnostic_node (A68_WARNING | A68_FORCE_DIAGNOSTICS, q, WARNING_TRAILING, trailing, att);
2043 }
2044 }
2045 /*
2046 Redirection in tokenising formats. The scanner is a recursive-descent type as
2047 to know when it scans a format text and when not.
2048 */
2049 if (in_format && att == FORMAT_DELIMITER_SYMBOL) {
2050 return;
2051 } else if (!in_format && att == FORMAT_DELIMITER_SYMBOL) {
2052 tokenise_source (root, level + 1, A68_TRUE, l, s, start_l, start_c);
2053 } else if (in_format && open_nested_clause (att)) {
2054 NODE_T *z = PREVIOUS (*root);
2055 if (z != NO_NODE && is_one_of (z, FORMAT_ITEM_N, FORMAT_ITEM_G, FORMAT_ITEM_H, FORMAT_ITEM_F)) {
2056 tokenise_source (root, level, A68_FALSE, l, s, start_l, start_c);
2057 } else if (att == OPEN_SYMBOL) {
2058 ATTRIBUTE (*root) = FORMAT_OPEN_SYMBOL;
2059 } else if (OPTION_BRACKETS (&program) && att == SUB_SYMBOL) {
2060 ATTRIBUTE (*root) = FORMAT_OPEN_SYMBOL;
2061 } else if (OPTION_BRACKETS (&program) && att == ACCO_SYMBOL) {
2062 ATTRIBUTE (*root) = FORMAT_OPEN_SYMBOL;
2063 }
2064 } else if (!in_format && level > 0 && open_nested_clause (att)) {
2065 tokenise_source (root, level + 1, A68_FALSE, l, s, start_l, start_c);
2066 } else if (!in_format && level > 0 && close_nested_clause (att)) {
2067 return;
2068 } else if (in_format && att == CLOSE_SYMBOL) {
2069 ATTRIBUTE (*root) = FORMAT_CLOSE_SYMBOL;
2070 } else if (OPTION_BRACKETS (&program) && in_format && att == BUS_SYMBOL) {
2071 ATTRIBUTE (*root) = FORMAT_CLOSE_SYMBOL;
2072 } else if (OPTION_BRACKETS (&program) && in_format && att == OCCA_SYMBOL) {
2073 ATTRIBUTE (*root) = FORMAT_CLOSE_SYMBOL;
2074 }
2075 }
2076 }
2077 }
2078
2079 /**
2080 @brief Tokenise source file, build initial syntax tree.
2081 @return Whether tokenising ended satisfactorily.
2082 **/
2083
2084 BOOL_T
lexical_analyser(void)2085 lexical_analyser (void)
2086 {
2087 LINE_T *l, *start_l = NO_LINE;
2088 char *s = NO_TEXT, *start_c = NO_TEXT;
2089 NODE_T *root = NO_NODE;
2090 scan_buf = NO_TEXT;
2091 max_scan_buf_length = source_file_size = get_source_size ();
2092 /* Errors in file? */
2093 if (max_scan_buf_length == 0) {
2094 return (A68_FALSE);
2095 }
2096 if (OPTION_RUN_SCRIPT (&program)) {
2097 scan_buf = (char *) get_temp_heap_space ((unsigned) (8 + max_scan_buf_length));
2098 if (!read_script_file ()) {
2099 return (A68_FALSE);
2100 }
2101 } else {
2102 max_scan_buf_length += KILOBYTE; /* for the environ, more than enough */
2103 scan_buf = (char *) get_temp_heap_space ((unsigned) max_scan_buf_length);
2104 /* Errors in file? */
2105 if (!read_source_file ()) {
2106 return (A68_FALSE);
2107 }
2108 }
2109 /* Start tokenising */
2110 read_error = A68_FALSE;
2111 stop_scanner = A68_FALSE;
2112 if ((l = TOP_LINE (&program)) != NO_LINE) {
2113 s = STRING (l);
2114 }
2115 tokenise_source (&root, 0, A68_FALSE, &l, &s, &start_l, &start_c);
2116 return (A68_TRUE);
2117 }
2118
2119 /************************************************/
2120 /* A small refinement preprocessor for Algol68G */
2121 /************************************************/
2122
2123 /**
2124 @brief Whether refinement terminator.
2125 @param p Position in syntax tree.
2126 @return See brief description.
2127 **/
2128
2129 static BOOL_T
is_refinement_terminator(NODE_T * p)2130 is_refinement_terminator (NODE_T * p)
2131 {
2132 if (IS (p, POINT_SYMBOL)) {
2133 if (IN_PRELUDE (NEXT (p))) {
2134 return (A68_TRUE);
2135 } else {
2136 return (whether (p, POINT_SYMBOL, IDENTIFIER, COLON_SYMBOL, STOP));
2137 }
2138 } else {
2139 return (A68_FALSE);
2140 }
2141 }
2142
2143 /**
2144 @brief Get refinement definitions in the internal source.
2145 **/
2146
2147 void
get_refinements(void)2148 get_refinements (void)
2149 {
2150 NODE_T *p = TOP_NODE (&program);
2151 TOP_REFINEMENT (&program) = NO_REFINEMENT;
2152 /* First look where the prelude ends */
2153 while (p != NO_NODE && IN_PRELUDE (p)) {
2154 FORWARD (p);
2155 }
2156 /* Determine whether the program contains refinements at all */
2157 while (p != NO_NODE && !IN_PRELUDE (p) && !is_refinement_terminator (p)) {
2158 FORWARD (p);
2159 }
2160 if (p == NO_NODE || IN_PRELUDE (p)) {
2161 return;
2162 }
2163 /* Apparently this is code with refinements */
2164 FORWARD (p);
2165 if (p == NO_NODE || IN_PRELUDE (p)) {
2166 /* Ok, we accept a program with no refinements as well */
2167 return;
2168 }
2169 while (p != NO_NODE && !IN_PRELUDE (p) && whether (p, IDENTIFIER, COLON_SYMBOL, STOP)) {
2170 REFINEMENT_T *new_one = (REFINEMENT_T *) get_fixed_heap_space ((size_t) SIZE_AL (REFINEMENT_T)), *x;
2171 BOOL_T exists;
2172 NEXT (new_one) = NO_REFINEMENT;
2173 NAME (new_one) = NSYMBOL (p);
2174 APPLICATIONS (new_one) = 0;
2175 LINE_DEFINED (new_one) = LINE (INFO (p));
2176 LINE_APPLIED (new_one) = NO_LINE;
2177 NODE_DEFINED (new_one) = p;
2178 BEGIN (new_one) = END (new_one) = NO_NODE;
2179 p = NEXT_NEXT (p);
2180 if (p == NO_NODE) {
2181 diagnostic_node (A68_SYNTAX_ERROR, NO_NODE, ERROR_REFINEMENT_EMPTY);
2182 return;
2183 } else {
2184 BEGIN (new_one) = p;
2185 }
2186 while (p != NO_NODE && ATTRIBUTE (p) != POINT_SYMBOL) {
2187 END (new_one) = p;
2188 FORWARD (p);
2189 }
2190 if (p == NO_NODE) {
2191 diagnostic_node (A68_SYNTAX_ERROR, NO_NODE, ERROR_SYNTAX_EXPECTED, POINT_SYMBOL);
2192 return;
2193 } else {
2194 FORWARD (p);
2195 }
2196 /* Do we already have one by this name */
2197 x = TOP_REFINEMENT (&program);
2198 exists = A68_FALSE;
2199 while (x != NO_REFINEMENT && !exists) {
2200 if (NAME (x) == NAME (new_one)) {
2201 diagnostic_node (A68_SYNTAX_ERROR, NODE_DEFINED (new_one), ERROR_REFINEMENT_DEFINED);
2202 exists = A68_TRUE;
2203 }
2204 FORWARD (x);
2205 }
2206 /* Straight insertion in chain */
2207 if (!exists) {
2208 NEXT (new_one) = TOP_REFINEMENT (&program);
2209 TOP_REFINEMENT (&program) = new_one;
2210 }
2211 }
2212 if (p != NO_NODE && !IN_PRELUDE (p)) {
2213 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_REFINEMENT_INVALID);
2214 }
2215 }
2216
2217 /**
2218 @brief Put refinement applications in the internal source.
2219 **/
2220
2221 void
put_refinements(void)2222 put_refinements (void)
2223 {
2224 REFINEMENT_T *x;
2225 NODE_T *p, *point;
2226 /* If there are no refinements, there's little to do */
2227 if (TOP_REFINEMENT (&program) == NO_REFINEMENT) {
2228 return;
2229 }
2230 /* Initialisation */
2231 x = TOP_REFINEMENT (&program);
2232 while (x != NO_REFINEMENT) {
2233 APPLICATIONS (x) = 0;
2234 FORWARD (x);
2235 }
2236 /* Before we introduce infinite loops, find where closing-prelude starts */
2237 p = TOP_NODE (&program);
2238 while (p != NO_NODE && IN_PRELUDE (p)) {
2239 FORWARD (p);
2240 }
2241 while (p != NO_NODE && !IN_PRELUDE (p)) {
2242 FORWARD (p);
2243 }
2244 ABEND (p == NO_NODE, ERROR_INTERNAL_CONSISTENCY, NO_TEXT);
2245 point = p;
2246 /* We need to substitute until the first point */
2247 p = TOP_NODE (&program);
2248 while (p != NO_NODE && ATTRIBUTE (p) != POINT_SYMBOL) {
2249 if (IS (p, IDENTIFIER)) {
2250 /* See if we can find its definition */
2251 REFINEMENT_T *y = NO_REFINEMENT;
2252 x = TOP_REFINEMENT (&program);
2253 while (x != NO_REFINEMENT && y == NO_REFINEMENT) {
2254 if (NAME (x) == NSYMBOL (p)) {
2255 y = x;
2256 } else {
2257 FORWARD (x);
2258 }
2259 }
2260 if (y != NO_REFINEMENT) {
2261 /* We found its definition */
2262 APPLICATIONS (y)++;
2263 if (APPLICATIONS (y) > 1) {
2264 diagnostic_node (A68_SYNTAX_ERROR, NODE_DEFINED (y), ERROR_REFINEMENT_APPLIED);
2265 FORWARD (p);
2266 } else {
2267 /* Tie the definition in the tree */
2268 LINE_APPLIED (y) = LINE (INFO (p));
2269 if (PREVIOUS (p) != NO_NODE) {
2270 NEXT (PREVIOUS (p)) = BEGIN (y);
2271 }
2272 if (BEGIN (y) != NO_NODE) {
2273 PREVIOUS (BEGIN (y)) = PREVIOUS (p);
2274 }
2275 if (NEXT (p) != NO_NODE) {
2276 PREVIOUS (NEXT (p)) = END (y);
2277 }
2278 if (END (y) != NO_NODE) {
2279 NEXT (END (y)) = NEXT (p);
2280 }
2281 p = BEGIN (y); /* So we can substitute the refinements within */
2282 }
2283 } else {
2284 FORWARD (p);
2285 }
2286 } else {
2287 FORWARD (p);
2288 }
2289 }
2290 /* After the point we ignore it all until the prelude */
2291 if (p != NO_NODE && IS (p, POINT_SYMBOL)) {
2292 if (PREVIOUS (p) != NO_NODE) {
2293 NEXT (PREVIOUS (p)) = point;
2294 }
2295 if (PREVIOUS (point) != NO_NODE) {
2296 PREVIOUS (point) = PREVIOUS (p);
2297 }
2298 } else {
2299 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_SYNTAX_EXPECTED, POINT_SYMBOL);
2300 }
2301 /* Has the programmer done it well? */
2302 if (ERROR_COUNT (&program) == 0) {
2303 x = TOP_REFINEMENT (&program);
2304 while (x != NO_REFINEMENT) {
2305 if (APPLICATIONS (x) == 0) {
2306 diagnostic_node (A68_SYNTAX_ERROR, NODE_DEFINED (x), ERROR_REFINEMENT_NOT_APPLIED);
2307 }
2308 FORWARD (x);
2309 }
2310 }
2311 }
2312
2313 /*****************************************************/
2314 /* Top-down parser, elaborates the control structure */
2315 /*****************************************************/
2316
2317 /**
2318 @brief Insert alt equals symbol.
2319 @param p Node after which to insert.
2320 **/
2321
2322 static void
insert_alt_equals(NODE_T * p)2323 insert_alt_equals (NODE_T * p)
2324 {
2325 NODE_T *q = new_node ();
2326 *q = *p;
2327 INFO (q) = new_node_info ();
2328 *INFO (q) = *INFO (p);
2329 GINFO (q) = new_genie_info ();
2330 *GINFO (q) = *GINFO (p);
2331 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
2332 NSYMBOL (q) = TEXT (add_token (&top_token, "="));
2333 NEXT (p) = q;
2334 PREVIOUS (q) = p;
2335 if (NEXT (q) != NO_NODE) {
2336 PREVIOUS (NEXT (q)) = q;
2337 }
2338 }
2339
2340 /**
2341 @brief Substitute brackets.
2342 @param p Node in syntax tree.
2343 **/
2344
2345 void
substitute_brackets(NODE_T * p)2346 substitute_brackets (NODE_T * p)
2347 {
2348 for (; p != NO_NODE; FORWARD (p)) {
2349 substitute_brackets (SUB (p));
2350 switch (ATTRIBUTE (p)) {
2351 case ACCO_SYMBOL:
2352 {
2353 ATTRIBUTE (p) = OPEN_SYMBOL;
2354 break;
2355 }
2356 case OCCA_SYMBOL:
2357 {
2358 ATTRIBUTE (p) = CLOSE_SYMBOL;
2359 break;
2360 }
2361 case SUB_SYMBOL:
2362 {
2363 ATTRIBUTE (p) = OPEN_SYMBOL;
2364 break;
2365 }
2366 case BUS_SYMBOL:
2367 {
2368 ATTRIBUTE (p) = CLOSE_SYMBOL;
2369 break;
2370 }
2371 }
2372 }
2373 }
2374
2375 /**
2376 @brief Whether token terminates a unit.
2377 @param p Node in syntax tree.
2378 \return TRUE or FALSE whether token terminates a unit
2379 **/
2380
2381 static BOOL_T
is_unit_terminator(NODE_T * p)2382 is_unit_terminator (NODE_T * p)
2383 {
2384 switch (ATTRIBUTE (p)) {
2385 case BUS_SYMBOL:
2386 case CLOSE_SYMBOL:
2387 case END_SYMBOL:
2388 case SEMI_SYMBOL:
2389 case EXIT_SYMBOL:
2390 case COMMA_SYMBOL:
2391 case THEN_BAR_SYMBOL:
2392 case ELSE_BAR_SYMBOL:
2393 case THEN_SYMBOL:
2394 case ELIF_SYMBOL:
2395 case ELSE_SYMBOL:
2396 case FI_SYMBOL:
2397 case IN_SYMBOL:
2398 case OUT_SYMBOL:
2399 case OUSE_SYMBOL:
2400 case ESAC_SYMBOL:
2401 case EDOC_SYMBOL:
2402 case OCCA_SYMBOL:
2403 {
2404 return (A68_TRUE);
2405 }
2406 }
2407 return (A68_FALSE);
2408 }
2409
2410 /**
2411 @brief Whether token is a unit-terminator in a loop clause.
2412 @param p Node in syntax tree.
2413 @return Whether token is a unit-terminator in a loop clause.
2414 **/
2415
2416 static BOOL_T
is_loop_keyword(NODE_T * p)2417 is_loop_keyword (NODE_T * p)
2418 {
2419 switch (ATTRIBUTE (p)) {
2420 case FOR_SYMBOL:
2421 case FROM_SYMBOL:
2422 case BY_SYMBOL:
2423 case TO_SYMBOL:
2424 case DOWNTO_SYMBOL:
2425 case WHILE_SYMBOL:
2426 case DO_SYMBOL:
2427 {
2428 return (A68_TRUE);
2429 }
2430 }
2431 return (A68_FALSE);
2432 }
2433
2434 /**
2435 @brief Whether token cannot follow semicolon or EXIT.
2436 @param p Node in syntax tree.
2437 @return Whether token cannot follow semicolon or EXIT.
2438 **/
2439
2440 static BOOL_T
is_semicolon_less(NODE_T * p)2441 is_semicolon_less (NODE_T * p)
2442 {
2443 switch (ATTRIBUTE (p)) {
2444 case BUS_SYMBOL:
2445 case CLOSE_SYMBOL:
2446 case END_SYMBOL:
2447 case SEMI_SYMBOL:
2448 case EXIT_SYMBOL:
2449 case THEN_BAR_SYMBOL:
2450 case ELSE_BAR_SYMBOL:
2451 case THEN_SYMBOL:
2452 case ELIF_SYMBOL:
2453 case ELSE_SYMBOL:
2454 case FI_SYMBOL:
2455 case IN_SYMBOL:
2456 case OUT_SYMBOL:
2457 case OUSE_SYMBOL:
2458 case ESAC_SYMBOL:
2459 case EDOC_SYMBOL:
2460 case OCCA_SYMBOL:
2461 case OD_SYMBOL:
2462 case UNTIL_SYMBOL:
2463 {
2464 return (A68_TRUE);
2465 }
2466 default:
2467 {
2468 return (A68_FALSE);
2469 }
2470 }
2471 }
2472
2473 /**
2474 @brief Get good attribute.
2475 @param p Node in syntax tree.
2476 @return See brief description.
2477 **/
2478
2479 static int
get_good_attribute(NODE_T * p)2480 get_good_attribute (NODE_T * p)
2481 {
2482 switch (ATTRIBUTE (p)) {
2483 case UNIT:
2484 case TERTIARY:
2485 case SECONDARY:
2486 case PRIMARY:
2487 {
2488 return (get_good_attribute (SUB (p)));
2489 }
2490 default:
2491 {
2492 return (ATTRIBUTE (p));
2493 }
2494 }
2495 }
2496
2497 /**
2498 @brief Preferably don't put intelligible diagnostic here.
2499 @param p Node in syntax tree.
2500 @return See brief description.
2501 **/
2502
2503 static BOOL_T
dont_mark_here(NODE_T * p)2504 dont_mark_here (NODE_T * p)
2505 {
2506 switch (ATTRIBUTE (p)) {
2507 case ACCO_SYMBOL:
2508 case ALT_DO_SYMBOL:
2509 case ALT_EQUALS_SYMBOL:
2510 case ANDF_SYMBOL:
2511 case ASSERT_SYMBOL:
2512 case ASSIGN_SYMBOL:
2513 case ASSIGN_TO_SYMBOL:
2514 case AT_SYMBOL:
2515 case BEGIN_SYMBOL:
2516 case BITS_SYMBOL:
2517 case BOLD_COMMENT_SYMBOL:
2518 case BOLD_PRAGMAT_SYMBOL:
2519 case BOOL_SYMBOL:
2520 case BUS_SYMBOL:
2521 case BY_SYMBOL:
2522 case BYTES_SYMBOL:
2523 case CASE_SYMBOL:
2524 case CHANNEL_SYMBOL:
2525 case CHAR_SYMBOL:
2526 case CLOSE_SYMBOL:
2527 case CODE_SYMBOL:
2528 case COLON_SYMBOL:
2529 case COLUMN_SYMBOL:
2530 case COMMA_SYMBOL:
2531 case COMPLEX_SYMBOL:
2532 case COMPL_SYMBOL:
2533 case DIAGONAL_SYMBOL:
2534 case DO_SYMBOL:
2535 case DOTDOT_SYMBOL:
2536 case DOWNTO_SYMBOL:
2537 case EDOC_SYMBOL:
2538 case ELIF_SYMBOL:
2539 case ELSE_BAR_SYMBOL:
2540 case ELSE_SYMBOL:
2541 case EMPTY_SYMBOL:
2542 case END_SYMBOL:
2543 case ENVIRON_SYMBOL:
2544 case EQUALS_SYMBOL:
2545 case ESAC_SYMBOL:
2546 case EXIT_SYMBOL:
2547 case FALSE_SYMBOL:
2548 case FILE_SYMBOL:
2549 case FI_SYMBOL:
2550 case FLEX_SYMBOL:
2551 case FORMAT_DELIMITER_SYMBOL:
2552 case FORMAT_SYMBOL:
2553 case FOR_SYMBOL:
2554 case FROM_SYMBOL:
2555 case GO_SYMBOL:
2556 case GOTO_SYMBOL:
2557 case HEAP_SYMBOL:
2558 case IF_SYMBOL:
2559 case IN_SYMBOL:
2560 case INT_SYMBOL:
2561 case ISNT_SYMBOL:
2562 case IS_SYMBOL:
2563 case LOC_SYMBOL:
2564 case LONG_SYMBOL:
2565 case MAIN_SYMBOL:
2566 case MODE_SYMBOL:
2567 case NIL_SYMBOL:
2568 case OCCA_SYMBOL:
2569 case OD_SYMBOL:
2570 case OF_SYMBOL:
2571 case OPEN_SYMBOL:
2572 case OP_SYMBOL:
2573 case ORF_SYMBOL:
2574 case OUSE_SYMBOL:
2575 case OUT_SYMBOL:
2576 case PAR_SYMBOL:
2577 case PIPE_SYMBOL:
2578 case POINT_SYMBOL:
2579 case PRIO_SYMBOL:
2580 case PROC_SYMBOL:
2581 case REAL_SYMBOL:
2582 case REF_SYMBOL:
2583 case ROWS_SYMBOL:
2584 case ROW_SYMBOL:
2585 case SEMA_SYMBOL:
2586 case SEMI_SYMBOL:
2587 case SHORT_SYMBOL:
2588 case SKIP_SYMBOL:
2589 case SOUND_SYMBOL:
2590 case STRING_SYMBOL:
2591 case STRUCT_SYMBOL:
2592 case STYLE_I_COMMENT_SYMBOL:
2593 case STYLE_II_COMMENT_SYMBOL:
2594 case STYLE_I_PRAGMAT_SYMBOL:
2595 case SUB_SYMBOL:
2596 case THEN_BAR_SYMBOL:
2597 case THEN_SYMBOL:
2598 case TO_SYMBOL:
2599 case TRANSPOSE_SYMBOL:
2600 case TRUE_SYMBOL:
2601 case UNION_SYMBOL:
2602 case UNTIL_SYMBOL:
2603 case VOID_SYMBOL:
2604 case WHILE_SYMBOL:
2605 /* and than */
2606 case SERIAL_CLAUSE:
2607 case ENQUIRY_CLAUSE:
2608 case INITIALISER_SERIES:
2609 case DECLARATION_LIST:
2610 {
2611 return (A68_TRUE);
2612 }
2613 }
2614 return (A68_FALSE);
2615 }
2616
2617 /**
2618 @brief Intelligible diagnostic from syntax tree branch.
2619 @param p Node in syntax tree.
2620 @param w Where to put error message.
2621 @return See brief description.
2622 **/
2623
2624 char *
phrase_to_text(NODE_T * p,NODE_T ** w)2625 phrase_to_text (NODE_T * p, NODE_T ** w)
2626 {
2627 #define MAX_TERMINALS 8
2628 int count = 0, line = -1;
2629 static char buffer[BUFFER_SIZE];
2630 for (buffer[0] = NULL_CHAR; p != NO_NODE && count < MAX_TERMINALS; FORWARD (p)) {
2631 if (LINE_NUMBER (p) > 0) {
2632 int gatt = get_good_attribute (p);
2633 char *z = non_terminal_string (input_line, gatt);
2634 /*
2635 Where to put the error message? Bob Uzgalis noted that actual content of a
2636 diagnostic is not as important as accurately indicating *were* the problem is!
2637 */
2638 if (w != NO_VAR) {
2639 if (count == 0 || (*w) == NO_NODE) {
2640 *w = p;
2641 } else if (dont_mark_here (*w)) {
2642 *w = p;
2643 }
2644 }
2645 /* Add initiation */
2646 if (count == 0) {
2647 if (w != NO_VAR) {
2648 bufcat (buffer, "construct beginning with", BUFFER_SIZE);
2649 }
2650 } else if (count == 1) {
2651 bufcat (buffer, " followed by", BUFFER_SIZE);
2652 } else if (count == 2) {
2653 bufcat (buffer, " and then", BUFFER_SIZE);
2654 } else if (count >= 3) {
2655 bufcat (buffer, ",", BUFFER_SIZE);
2656 }
2657 /* Attribute or symbol */
2658 if (z != NO_TEXT && SUB (p) != NO_NODE) {
2659 if (gatt == IDENTIFIER || gatt == OPERATOR || gatt == DENOTATION) {
2660 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, " \"%s\"", NSYMBOL (p)) >= 0);
2661 bufcat (buffer, edit_line, BUFFER_SIZE);
2662 } else {
2663 if (strchr ("aeio", z[0]) != NO_TEXT) {
2664 bufcat (buffer, " an", BUFFER_SIZE);
2665 } else {
2666 bufcat (buffer, " a", BUFFER_SIZE);
2667 }
2668 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, " %s", z) >= 0);
2669 bufcat (buffer, edit_line, BUFFER_SIZE);
2670 }
2671 } else if (z != NO_TEXT && SUB (p) == NO_NODE) {
2672 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, " \"%s\"", NSYMBOL (p)) >= 0);
2673 bufcat (buffer, edit_line, BUFFER_SIZE);
2674 } else if (NSYMBOL (p) != NO_TEXT) {
2675 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, " \"%s\"", NSYMBOL (p)) >= 0);
2676 bufcat (buffer, edit_line, BUFFER_SIZE);
2677 }
2678 /* Add "starting in line nn" */
2679 if (z != NO_TEXT && line != LINE_NUMBER (p)) {
2680 line = LINE_NUMBER (p);
2681 if (gatt == SERIAL_CLAUSE || gatt == ENQUIRY_CLAUSE || gatt == INITIALISER_SERIES) {
2682 bufcat (buffer, " starting", BUFFER_SIZE);
2683 }
2684 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, " in line %d", line) >= 0);
2685 bufcat (buffer, edit_line, BUFFER_SIZE);
2686 }
2687 count++;
2688 }
2689 }
2690 if (p != NO_NODE && count == MAX_TERMINALS) {
2691 bufcat (buffer, " etcetera", BUFFER_SIZE);
2692 }
2693 return (buffer);
2694 }
2695
2696 /**
2697 @brief Intelligible diagnostic from syntax tree branch.
2698 @param p Node in syntax tree.
2699 @param w Where to put error message.
2700 @return See brief description.
2701 **/
2702
2703 char *
phrase_to_text_2(NODE_T * p,NODE_T ** w)2704 phrase_to_text_2 (NODE_T * p, NODE_T ** w)
2705 {
2706 #define MAX_TERMINALS 8
2707 int count = 0;
2708 static char buffer[BUFFER_SIZE];
2709 for (buffer[0] = NULL_CHAR; p != NO_NODE && count < MAX_TERMINALS; FORWARD (p)) {
2710 if (LINE_NUMBER (p) > 0) {
2711 char *z = non_terminal_string (input_line, ATTRIBUTE (p));
2712 /*
2713 Where to put the error message? Bob Uzgalis noted that actual content of a
2714 diagnostic is not as important as accurately indicating *were* the problem is!
2715 */
2716 if (w != NO_VAR) {
2717 if (count == 0 || (*w) == NO_NODE) {
2718 *w = p;
2719 } else if (dont_mark_here (*w)) {
2720 *w = p;
2721 }
2722 }
2723 /* Add initiation */
2724 if (count >= 1) {
2725 bufcat (buffer, ",", BUFFER_SIZE);
2726 }
2727 /* Attribute or symbol */
2728 if (z != NO_TEXT) {
2729 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, " %s", z) >= 0);
2730 bufcat (buffer, edit_line, BUFFER_SIZE);
2731 } else if (NSYMBOL (p) != NO_TEXT) {
2732 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, " \"%s\"", NSYMBOL (p)) >= 0);
2733 bufcat (buffer, edit_line, BUFFER_SIZE);
2734 }
2735 count++;
2736 }
2737 }
2738 if (p != NO_NODE && count == MAX_TERMINALS) {
2739 bufcat (buffer, " etcetera", BUFFER_SIZE);
2740 }
2741 return (buffer);
2742 }
2743
2744 /*
2745 This is a parenthesis checker. After this checker, we know that at least
2746 brackets are matched. This stabilises later parser phases.
2747 Top-down parsing is done to place error diagnostics near offending lines.
2748 */
2749
2750 static char bracket_check_error_text[BUFFER_SIZE];
2751
2752 /**
2753 @brief Intelligible diagnostics for the bracket checker.
2754 @param txt Buffer to which to append text.
2755 @param n Count mismatch (~= 0).
2756 @param bra Opening bracket.
2757 @param ket Expected closing bracket.
2758 @return See brief description.
2759 **/
2760
2761 static void
bracket_check_error(char * txt,int n,char * bra,char * ket)2762 bracket_check_error (char *txt, int n, char *bra, char *ket)
2763 {
2764 if (n != 0) {
2765 char b[BUFFER_SIZE];
2766 ASSERT (snprintf (b, SNPRINTF_SIZE, "\"%s\" without matching \"%s\"", (n > 0 ? bra : ket), (n > 0 ? ket : bra)) >= 0);
2767 if (strlen (txt) > 0) {
2768 bufcat (txt, " and ", BUFFER_SIZE);
2769 }
2770 bufcat (txt, b, BUFFER_SIZE);
2771 }
2772 }
2773
2774 /**
2775 @brief Diagnose brackets in local branch of the tree.
2776 @param p Node in syntax tree.
2777 @return Error message.
2778 **/
2779
2780 static char *
bracket_check_diagnose(NODE_T * p)2781 bracket_check_diagnose (NODE_T * p)
2782 {
2783 int begins = 0, opens = 0, format_delims = 0, format_opens = 0, subs = 0, ifs = 0, cases = 0, dos = 0, accos = 0;
2784 for (; p != NO_NODE; FORWARD (p)) {
2785 switch (ATTRIBUTE (p)) {
2786 case BEGIN_SYMBOL:
2787 {
2788 begins++;
2789 break;
2790 }
2791 case END_SYMBOL:
2792 {
2793 begins--;
2794 break;
2795 }
2796 case OPEN_SYMBOL:
2797 {
2798 opens++;
2799 break;
2800 }
2801 case CLOSE_SYMBOL:
2802 {
2803 opens--;
2804 break;
2805 }
2806 case ACCO_SYMBOL:
2807 {
2808 accos++;
2809 break;
2810 }
2811 case OCCA_SYMBOL:
2812 {
2813 accos--;
2814 break;
2815 }
2816 case FORMAT_DELIMITER_SYMBOL:
2817 {
2818 if (format_delims == 0) {
2819 format_delims = 1;
2820 } else {
2821 format_delims = 0;
2822 }
2823 break;
2824 }
2825 case FORMAT_OPEN_SYMBOL:
2826 {
2827 format_opens++;
2828 break;
2829 }
2830 case FORMAT_CLOSE_SYMBOL:
2831 {
2832 format_opens--;
2833 break;
2834 }
2835 case SUB_SYMBOL:
2836 {
2837 subs++;
2838 break;
2839 }
2840 case BUS_SYMBOL:
2841 {
2842 subs--;
2843 break;
2844 }
2845 case IF_SYMBOL:
2846 {
2847 ifs++;
2848 break;
2849 }
2850 case FI_SYMBOL:
2851 {
2852 ifs--;
2853 break;
2854 }
2855 case CASE_SYMBOL:
2856 {
2857 cases++;
2858 break;
2859 }
2860 case ESAC_SYMBOL:
2861 {
2862 cases--;
2863 break;
2864 }
2865 case DO_SYMBOL:
2866 {
2867 dos++;
2868 break;
2869 }
2870 case OD_SYMBOL:
2871 {
2872 dos--;
2873 break;
2874 }
2875 }
2876 }
2877 bracket_check_error_text[0] = NULL_CHAR;
2878 bracket_check_error (bracket_check_error_text, begins, "BEGIN", "END");
2879 bracket_check_error (bracket_check_error_text, opens, "(", ")");
2880 bracket_check_error (bracket_check_error_text, format_opens, "(", ")");
2881 bracket_check_error (bracket_check_error_text, format_delims, "$", "$");
2882 bracket_check_error (bracket_check_error_text, accos, "{", "}");
2883 bracket_check_error (bracket_check_error_text, subs, "[", "]");
2884 bracket_check_error (bracket_check_error_text, ifs, "IF", "FI");
2885 bracket_check_error (bracket_check_error_text, cases, "CASE", "ESAC");
2886 bracket_check_error (bracket_check_error_text, dos, "DO", "OD");
2887 return (bracket_check_error_text);
2888 }
2889
2890 /**
2891 @brief Driver for locally diagnosing non-matching tokens.
2892 @param top
2893 @param p Node in syntax tree.
2894 @return Token from where to continue.
2895 **/
2896
2897 static NODE_T *
bracket_check_parse(NODE_T * top,NODE_T * p)2898 bracket_check_parse (NODE_T * top, NODE_T * p)
2899 {
2900 BOOL_T ignore_token;
2901 for (; p != NO_NODE; FORWARD (p)) {
2902 int ket = STOP;
2903 NODE_T *q = NO_NODE;
2904 ignore_token = A68_FALSE;
2905 switch (ATTRIBUTE (p)) {
2906 case BEGIN_SYMBOL:
2907 {
2908 ket = END_SYMBOL;
2909 q = bracket_check_parse (top, NEXT (p));
2910 break;
2911 }
2912 case OPEN_SYMBOL:
2913 {
2914 ket = CLOSE_SYMBOL;
2915 q = bracket_check_parse (top, NEXT (p));
2916 break;
2917 }
2918 case ACCO_SYMBOL:
2919 {
2920 ket = OCCA_SYMBOL;
2921 q = bracket_check_parse (top, NEXT (p));
2922 break;
2923 }
2924 case FORMAT_OPEN_SYMBOL:
2925 {
2926 ket = FORMAT_CLOSE_SYMBOL;
2927 q = bracket_check_parse (top, NEXT (p));
2928 break;
2929 }
2930 case SUB_SYMBOL:
2931 {
2932 ket = BUS_SYMBOL;
2933 q = bracket_check_parse (top, NEXT (p));
2934 break;
2935 }
2936 case IF_SYMBOL:
2937 {
2938 ket = FI_SYMBOL;
2939 q = bracket_check_parse (top, NEXT (p));
2940 break;
2941 }
2942 case CASE_SYMBOL:
2943 {
2944 ket = ESAC_SYMBOL;
2945 q = bracket_check_parse (top, NEXT (p));
2946 break;
2947 }
2948 case DO_SYMBOL:
2949 {
2950 ket = OD_SYMBOL;
2951 q = bracket_check_parse (top, NEXT (p));
2952 break;
2953 }
2954 case END_SYMBOL:
2955 case OCCA_SYMBOL:
2956 case CLOSE_SYMBOL:
2957 case FORMAT_CLOSE_SYMBOL:
2958 case BUS_SYMBOL:
2959 case FI_SYMBOL:
2960 case ESAC_SYMBOL:
2961 case OD_SYMBOL:
2962 {
2963 return (p);
2964 }
2965 default:
2966 {
2967 ignore_token = A68_TRUE;
2968 }
2969 }
2970 if (ignore_token) {
2971 ;
2972 } else if (q != NO_NODE && IS (q, ket)) {
2973 p = q;
2974 } else if (q == NO_NODE) {
2975 char *diag = bracket_check_diagnose (top);
2976 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_PARENTHESIS, (strlen (diag) > 0 ? diag : INFO_MISSING_KEYWORDS));
2977 longjmp (top_down_crash_exit, 1);
2978 } else {
2979 char *diag = bracket_check_diagnose (top);
2980 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_PARENTHESIS_2, ATTRIBUTE (q), LINE (INFO (q)), ket, (strlen (diag) > 0 ? diag : INFO_MISSING_KEYWORDS));
2981 longjmp (top_down_crash_exit, 1);
2982 }
2983 }
2984 return (NO_NODE);
2985 }
2986
2987 /**
2988 @brief Driver for globally diagnosing non-matching tokens.
2989 @param top Top node in syntax tree.
2990 **/
2991
2992 void
check_parenthesis(NODE_T * top)2993 check_parenthesis (NODE_T * top)
2994 {
2995 if (!setjmp (top_down_crash_exit)) {
2996 if (bracket_check_parse (top, top) != NO_NODE) {
2997 diagnostic_node (A68_SYNTAX_ERROR, top, ERROR_PARENTHESIS, INFO_MISSING_KEYWORDS);
2998 }
2999 }
3000 }
3001
3002 /*
3003 Next is a top-down parser that branches out the basic blocks.
3004 After this we can assign symbol tables to basic blocks.
3005 */
3006
3007 /**
3008 @brief Give diagnose from top-down parser.
3009 @param start Embedding clause starts here.
3010 @param posit Error issued at this point.
3011 @param clause Type of clause being processed.
3012 @param expected Token expected.
3013 **/
3014
3015 static void
top_down_diagnose(NODE_T * start,NODE_T * posit,int clause,int expected)3016 top_down_diagnose (NODE_T * start, NODE_T * posit, int clause, int expected)
3017 {
3018 NODE_T *issue = (posit != NO_NODE ? posit : start);
3019 if (expected != 0) {
3020 diagnostic_node (A68_SYNTAX_ERROR, issue, ERROR_EXPECTED_NEAR, expected, clause, NSYMBOL (start), LINE (INFO (start)));
3021 } else {
3022 diagnostic_node (A68_SYNTAX_ERROR, issue, ERROR_UNBALANCED_KEYWORD, clause, NSYMBOL (start), LINE (INFO (start)));
3023 }
3024 }
3025
3026 /**
3027 @brief Check for premature exhaustion of tokens.
3028 @param p Node in syntax tree.
3029 @param q
3030 **/
3031
3032 static void
tokens_exhausted(NODE_T * p,NODE_T * q)3033 tokens_exhausted (NODE_T * p, NODE_T * q)
3034 {
3035 if (p == NO_NODE) {
3036 diagnostic_node (A68_SYNTAX_ERROR, q, ERROR_KEYWORD);
3037 longjmp (top_down_crash_exit, 1);
3038 }
3039 }
3040
3041 /* This part specifically branches out loop clauses */
3042
3043 /**
3044 @brief Whether in cast or formula with loop clause.
3045 @param p Node in syntax tree.
3046 @return Number of symbols to skip.
3047 **/
3048
3049 static int
is_loop_cast_formula(NODE_T * p)3050 is_loop_cast_formula (NODE_T * p)
3051 {
3052 /* Accept declarers that can appear in such casts but not much more */
3053 if (IS (p, VOID_SYMBOL)) {
3054 return (1);
3055 } else if (IS (p, INT_SYMBOL)) {
3056 return (1);
3057 } else if (IS (p, REF_SYMBOL)) {
3058 return (1);
3059 } else if (is_one_of (p, OPERATOR, BOLD_TAG, STOP)) {
3060 return (1);
3061 } else if (whether (p, UNION_SYMBOL, OPEN_SYMBOL, STOP)) {
3062 return (2);
3063 } else if (is_one_of (p, OPEN_SYMBOL, SUB_SYMBOL, STOP)) {
3064 int k;
3065 for (k = 0; p != NO_NODE && (is_one_of (p, OPEN_SYMBOL, SUB_SYMBOL, STOP)); FORWARD (p), k++) {
3066 ;
3067 }
3068 return (p != NO_NODE && (whether (p, UNION_SYMBOL, OPEN_SYMBOL, STOP) ? k : 0));
3069 }
3070 return (0);
3071 }
3072
3073 /**
3074 @brief Skip a unit in a loop clause (FROM u BY u TO u).
3075 @param p Node in syntax tree.
3076 @return Token from where to proceed or NO_NODE.
3077 **/
3078
3079 static NODE_T *
top_down_skip_loop_unit(NODE_T * p)3080 top_down_skip_loop_unit (NODE_T * p)
3081 {
3082 /* Unit may start with, or consist of, a loop */
3083 if (is_loop_keyword (p)) {
3084 p = top_down_loop (p);
3085 }
3086 /* Skip rest of unit */
3087 while (p != NO_NODE) {
3088 int k = is_loop_cast_formula (p);
3089 if (k != 0) {
3090 /* operator-cast series .. */
3091 while (p != NO_NODE && k != 0) {
3092 while (k != 0) {
3093 FORWARD (p);
3094 k--;
3095 }
3096 k = is_loop_cast_formula (p);
3097 }
3098 /* ... may be followed by a loop clause */
3099 if (is_loop_keyword (p)) {
3100 p = top_down_loop (p);
3101 }
3102 } else if (is_loop_keyword (p) || IS (p, OD_SYMBOL)) {
3103 /* new loop or end-of-loop */
3104 return (p);
3105 } else if (IS (p, COLON_SYMBOL)) {
3106 FORWARD (p);
3107 /* skip routine header: loop clause */
3108 if (p != NO_NODE && is_loop_keyword (p)) {
3109 p = top_down_loop (p);
3110 }
3111 } else if (is_one_of (p, SEMI_SYMBOL, COMMA_SYMBOL, STOP) || IS (p, EXIT_SYMBOL)) {
3112 /* Statement separators */
3113 return (p);
3114 } else {
3115 FORWARD (p);
3116 }
3117 }
3118 return (NO_NODE);
3119 }
3120
3121 /**
3122 @brief Skip a loop clause.
3123 @param p Node in syntax tree.
3124 @return Token from where to proceed or NO_NODE.
3125 **/
3126
3127 static NODE_T *
top_down_skip_loop_series(NODE_T * p)3128 top_down_skip_loop_series (NODE_T * p)
3129 {
3130 BOOL_T siga;
3131 do {
3132 p = top_down_skip_loop_unit (p);
3133 siga = (BOOL_T) (p != NO_NODE && (is_one_of (p, SEMI_SYMBOL, EXIT_SYMBOL, COMMA_SYMBOL, COLON_SYMBOL, STOP)));
3134 if (siga) {
3135 FORWARD (p);
3136 }
3137 } while (!(p == NO_NODE || !siga));
3138 return (p);
3139 }
3140
3141 /**
3142 @brief Make branch of loop parts.
3143 @param p Node in syntax tree.
3144 @return Token from where to proceed or NO_NODE.
3145 **/
3146
3147 NODE_T *
top_down_loop(NODE_T * p)3148 top_down_loop (NODE_T * p)
3149 {
3150 NODE_T *start = p, *q = p, *save;
3151 if (IS (q, FOR_SYMBOL)) {
3152 tokens_exhausted (FORWARD (q), start);
3153 if (IS (q, IDENTIFIER)) {
3154 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
3155 } else {
3156 top_down_diagnose (start, q, LOOP_CLAUSE, IDENTIFIER);
3157 longjmp (top_down_crash_exit, 1);
3158 }
3159 tokens_exhausted (FORWARD (q), start);
3160 if (is_one_of (q, FROM_SYMBOL, BY_SYMBOL, TO_SYMBOL, DOWNTO_SYMBOL, WHILE_SYMBOL, STOP)) {
3161 ;
3162 } else if (IS (q, DO_SYMBOL)) {
3163 ATTRIBUTE (q) = ALT_DO_SYMBOL;
3164 } else {
3165 top_down_diagnose (start, q, LOOP_CLAUSE, STOP);
3166 longjmp (top_down_crash_exit, 1);
3167 }
3168 }
3169 if (IS (q, FROM_SYMBOL)) {
3170 start = q;
3171 q = top_down_skip_loop_unit (NEXT (q));
3172 tokens_exhausted (q, start);
3173 if (is_one_of (q, BY_SYMBOL, TO_SYMBOL, DOWNTO_SYMBOL, WHILE_SYMBOL, STOP)) {
3174 ;
3175 } else if (IS (q, DO_SYMBOL)) {
3176 ATTRIBUTE (q) = ALT_DO_SYMBOL;
3177 } else {
3178 top_down_diagnose (start, q, LOOP_CLAUSE, STOP);
3179 longjmp (top_down_crash_exit, 1);
3180 }
3181 make_sub (start, PREVIOUS (q), FROM_SYMBOL);
3182 }
3183 if (IS (q, BY_SYMBOL)) {
3184 start = q;
3185 q = top_down_skip_loop_series (NEXT (q));
3186 tokens_exhausted (q, start);
3187 if (is_one_of (q, TO_SYMBOL, DOWNTO_SYMBOL, WHILE_SYMBOL, STOP)) {
3188 ;
3189 } else if (IS (q, DO_SYMBOL)) {
3190 ATTRIBUTE (q) = ALT_DO_SYMBOL;
3191 } else {
3192 top_down_diagnose (start, q, LOOP_CLAUSE, STOP);
3193 longjmp (top_down_crash_exit, 1);
3194 }
3195 make_sub (start, PREVIOUS (q), BY_SYMBOL);
3196 }
3197 if (is_one_of (q, TO_SYMBOL, DOWNTO_SYMBOL, STOP)) {
3198 start = q;
3199 q = top_down_skip_loop_series (NEXT (q));
3200 tokens_exhausted (q, start);
3201 if (IS (q, WHILE_SYMBOL)) {
3202 ;
3203 } else if (IS (q, DO_SYMBOL)) {
3204 ATTRIBUTE (q) = ALT_DO_SYMBOL;
3205 } else {
3206 top_down_diagnose (start, q, LOOP_CLAUSE, STOP);
3207 longjmp (top_down_crash_exit, 1);
3208 }
3209 make_sub (start, PREVIOUS (q), TO_SYMBOL);
3210 }
3211 if (IS (q, WHILE_SYMBOL)) {
3212 start = q;
3213 q = top_down_skip_loop_series (NEXT (q));
3214 tokens_exhausted (q, start);
3215 if (IS (q, DO_SYMBOL)) {
3216 ATTRIBUTE (q) = ALT_DO_SYMBOL;
3217 } else {
3218 top_down_diagnose (start, q, LOOP_CLAUSE, DO_SYMBOL);
3219 longjmp (top_down_crash_exit, 1);
3220 }
3221 make_sub (start, PREVIOUS (q), WHILE_SYMBOL);
3222 }
3223 if (is_one_of (q, DO_SYMBOL, ALT_DO_SYMBOL, STOP)) {
3224 int k = ATTRIBUTE (q);
3225 start = q;
3226 q = top_down_skip_loop_series (NEXT (q));
3227 tokens_exhausted (q, start);
3228 if (ISNT (q, OD_SYMBOL)) {
3229 top_down_diagnose (start, q, LOOP_CLAUSE, OD_SYMBOL);
3230 longjmp (top_down_crash_exit, 1);
3231 }
3232 make_sub (start, q, k);
3233 }
3234 save = NEXT (start);
3235 make_sub (p, start, LOOP_CLAUSE);
3236 return (save);
3237 }
3238
3239 /**
3240 @brief Driver for making branches of loop parts.
3241 @param p Node in syntax tree.
3242 **/
3243
3244 static void
top_down_loops(NODE_T * p)3245 top_down_loops (NODE_T * p)
3246 {
3247 NODE_T *q = p;
3248 for (; q != NO_NODE; FORWARD (q)) {
3249 if (SUB (q) != NO_NODE) {
3250 top_down_loops (SUB (q));
3251 }
3252 }
3253 q = p;
3254 while (q != NO_NODE) {
3255 if (is_loop_keyword (q) != STOP) {
3256 q = top_down_loop (q);
3257 } else {
3258 FORWARD (q);
3259 }
3260 }
3261 }
3262
3263 /**
3264 @brief Driver for making branches of until parts.
3265 @param p Node in syntax tree.
3266 **/
3267
3268 static void
top_down_untils(NODE_T * p)3269 top_down_untils (NODE_T * p)
3270 {
3271 NODE_T *q = p;
3272 for (; q != NO_NODE; FORWARD (q)) {
3273 if (SUB (q) != NO_NODE) {
3274 top_down_untils (SUB (q));
3275 }
3276 }
3277 q = p;
3278 while (q != NO_NODE) {
3279 if (IS (q, UNTIL_SYMBOL)) {
3280 NODE_T *u = q;
3281 while (NEXT (u) != NO_NODE) {
3282 FORWARD (u);
3283 }
3284 make_sub (q, PREVIOUS (u), UNTIL_SYMBOL);
3285 return;
3286 } else {
3287 FORWARD (q);
3288 }
3289 }
3290 }
3291
3292 /* Branch anything except parts of a loop */
3293
3294 /**
3295 @brief Skip serial/enquiry clause (unit series).
3296 @param p Node in syntax tree.
3297 @return Token from where to proceed or NO_NODE.
3298 **/
3299
3300 static NODE_T *
top_down_series(NODE_T * p)3301 top_down_series (NODE_T * p)
3302 {
3303 BOOL_T siga = A68_TRUE;
3304 while (siga) {
3305 siga = A68_FALSE;
3306 p = top_down_skip_unit (p);
3307 if (p != NO_NODE) {
3308 if (is_one_of (p, SEMI_SYMBOL, EXIT_SYMBOL, COMMA_SYMBOL, STOP)) {
3309 siga = A68_TRUE;
3310 FORWARD (p);
3311 }
3312 }
3313 }
3314 return (p);
3315 }
3316
3317 /**
3318 @brief Make branch of BEGIN .. END.
3319 @param begin_p
3320 @return Token from where to proceed or NO_NODE.
3321 **/
3322
3323 static NODE_T *
top_down_begin(NODE_T * begin_p)3324 top_down_begin (NODE_T * begin_p)
3325 {
3326 NODE_T *end_p = top_down_series (NEXT (begin_p));
3327 if (end_p == NO_NODE || ISNT (end_p, END_SYMBOL)) {
3328 top_down_diagnose (begin_p, end_p, ENCLOSED_CLAUSE, END_SYMBOL);
3329 longjmp (top_down_crash_exit, 1);
3330 return (NO_NODE);
3331 } else {
3332 make_sub (begin_p, end_p, BEGIN_SYMBOL);
3333 return (NEXT (begin_p));
3334 }
3335 }
3336
3337 /**
3338 @brief Make branch of CODE .. EDOC.
3339 @param code_p
3340 @return Token from where to proceed or NO_NODE.
3341 **/
3342
3343 static NODE_T *
top_down_code(NODE_T * code_p)3344 top_down_code (NODE_T * code_p)
3345 {
3346 NODE_T *edoc_p = top_down_series (NEXT (code_p));
3347 if (edoc_p == NO_NODE || ISNT (edoc_p, EDOC_SYMBOL)) {
3348 diagnostic_node (A68_SYNTAX_ERROR, code_p, ERROR_KEYWORD);
3349 longjmp (top_down_crash_exit, 1);
3350 return (NO_NODE);
3351 } else {
3352 make_sub (code_p, edoc_p, CODE_SYMBOL);
3353 return (NEXT (code_p));
3354 }
3355 }
3356
3357 /**
3358 @brief Make branch of ( .. ).
3359 @param open_p
3360 @return Token from where to proceed or NO_NODE.
3361 **/
3362
3363 static NODE_T *
top_down_open(NODE_T * open_p)3364 top_down_open (NODE_T * open_p)
3365 {
3366 NODE_T *then_bar_p = top_down_series (NEXT (open_p)), *elif_bar_p;
3367 if (then_bar_p != NO_NODE && IS (then_bar_p, CLOSE_SYMBOL)) {
3368 make_sub (open_p, then_bar_p, OPEN_SYMBOL);
3369 return (NEXT (open_p));
3370 }
3371 if (then_bar_p == NO_NODE || ISNT (then_bar_p, THEN_BAR_SYMBOL)) {
3372 top_down_diagnose (open_p, then_bar_p, ENCLOSED_CLAUSE, STOP);
3373 longjmp (top_down_crash_exit, 1);
3374 }
3375 make_sub (open_p, PREVIOUS (then_bar_p), OPEN_SYMBOL);
3376 elif_bar_p = top_down_series (NEXT (then_bar_p));
3377 if (elif_bar_p != NO_NODE && IS (elif_bar_p, CLOSE_SYMBOL)) {
3378 make_sub (then_bar_p, PREVIOUS (elif_bar_p), THEN_BAR_SYMBOL);
3379 make_sub (open_p, elif_bar_p, OPEN_SYMBOL);
3380 return (NEXT (open_p));
3381 }
3382 if (elif_bar_p != NO_NODE && IS (elif_bar_p, THEN_BAR_SYMBOL)) {
3383 NODE_T *close_p = top_down_series (NEXT (elif_bar_p));
3384 if (close_p == NO_NODE || ISNT (close_p, CLOSE_SYMBOL)) {
3385 top_down_diagnose (open_p, elif_bar_p, ENCLOSED_CLAUSE, CLOSE_SYMBOL);
3386 longjmp (top_down_crash_exit, 1);
3387 }
3388 make_sub (then_bar_p, PREVIOUS (elif_bar_p), THEN_BAR_SYMBOL);
3389 make_sub (elif_bar_p, PREVIOUS (close_p), THEN_BAR_SYMBOL);
3390 make_sub (open_p, close_p, OPEN_SYMBOL);
3391 return (NEXT (open_p));
3392 }
3393 if (elif_bar_p != NO_NODE && IS (elif_bar_p, ELSE_BAR_SYMBOL)) {
3394 NODE_T *close_p = top_down_open (elif_bar_p);
3395 make_sub (then_bar_p, PREVIOUS (elif_bar_p), THEN_BAR_SYMBOL);
3396 make_sub (open_p, elif_bar_p, OPEN_SYMBOL);
3397 return (close_p);
3398 } else {
3399 top_down_diagnose (open_p, elif_bar_p, ENCLOSED_CLAUSE, CLOSE_SYMBOL);
3400 longjmp (top_down_crash_exit, 1);
3401 return (NO_NODE);
3402 }
3403 }
3404
3405 /**
3406 @brief Make branch of [ .. ].
3407 @param sub_p
3408 @return Token from where to proceed or NO_NODE.
3409 **/
3410
3411 static NODE_T *
top_down_sub(NODE_T * sub_p)3412 top_down_sub (NODE_T * sub_p)
3413 {
3414 NODE_T *bus_p = top_down_series (NEXT (sub_p));
3415 if (bus_p != NO_NODE && IS (bus_p, BUS_SYMBOL)) {
3416 make_sub (sub_p, bus_p, SUB_SYMBOL);
3417 return (NEXT (sub_p));
3418 } else {
3419 top_down_diagnose (sub_p, bus_p, 0, BUS_SYMBOL);
3420 longjmp (top_down_crash_exit, 1);
3421 return (NO_NODE);
3422 }
3423 }
3424
3425 /**
3426 @brief Make branch of { .. }.
3427 @param acco_p
3428 @return Token from where to proceed or NO_NODE.
3429 **/
3430
3431 static NODE_T *
top_down_acco(NODE_T * acco_p)3432 top_down_acco (NODE_T * acco_p)
3433 {
3434 NODE_T *occa_p = top_down_series (NEXT (acco_p));
3435 if (occa_p != NO_NODE && IS (occa_p, OCCA_SYMBOL)) {
3436 make_sub (acco_p, occa_p, ACCO_SYMBOL);
3437 return (NEXT (acco_p));
3438 } else {
3439 top_down_diagnose (acco_p, occa_p, ENCLOSED_CLAUSE, OCCA_SYMBOL);
3440 longjmp (top_down_crash_exit, 1);
3441 return (NO_NODE);
3442 }
3443 }
3444
3445 /**
3446 @brief Make branch of IF .. THEN .. ELSE .. FI.
3447 @param if_p
3448 @return Token from where to proceed or NO_NODE.
3449 **/
3450
3451 static NODE_T *
top_down_if(NODE_T * if_p)3452 top_down_if (NODE_T * if_p)
3453 {
3454 NODE_T *then_p = top_down_series (NEXT (if_p)), *elif_p;
3455 if (then_p == NO_NODE || ISNT (then_p, THEN_SYMBOL)) {
3456 top_down_diagnose (if_p, then_p, CONDITIONAL_CLAUSE, THEN_SYMBOL);
3457 longjmp (top_down_crash_exit, 1);
3458 }
3459 make_sub (if_p, PREVIOUS (then_p), IF_SYMBOL);
3460 elif_p = top_down_series (NEXT (then_p));
3461 if (elif_p != NO_NODE && IS (elif_p, FI_SYMBOL)) {
3462 make_sub (then_p, PREVIOUS (elif_p), THEN_SYMBOL);
3463 make_sub (if_p, elif_p, IF_SYMBOL);
3464 return (NEXT (if_p));
3465 }
3466 if (elif_p != NO_NODE && IS (elif_p, ELSE_SYMBOL)) {
3467 NODE_T *fi_p = top_down_series (NEXT (elif_p));
3468 if (fi_p == NO_NODE || ISNT (fi_p, FI_SYMBOL)) {
3469 top_down_diagnose (if_p, fi_p, CONDITIONAL_CLAUSE, FI_SYMBOL);
3470 longjmp (top_down_crash_exit, 1);
3471 } else {
3472 make_sub (then_p, PREVIOUS (elif_p), THEN_SYMBOL);
3473 make_sub (elif_p, PREVIOUS (fi_p), ELSE_SYMBOL);
3474 make_sub (if_p, fi_p, IF_SYMBOL);
3475 return (NEXT (if_p));
3476 }
3477 }
3478 if (elif_p != NO_NODE && IS (elif_p, ELIF_SYMBOL)) {
3479 NODE_T *fi_p = top_down_if (elif_p);
3480 make_sub (then_p, PREVIOUS (elif_p), THEN_SYMBOL);
3481 make_sub (if_p, elif_p, IF_SYMBOL);
3482 return (fi_p);
3483 } else {
3484 top_down_diagnose (if_p, elif_p, CONDITIONAL_CLAUSE, FI_SYMBOL);
3485 longjmp (top_down_crash_exit, 1);
3486 return (NO_NODE);
3487 }
3488 }
3489
3490 /**
3491 @brief Make branch of CASE .. IN .. OUT .. ESAC.
3492 @param case_p
3493 @return Token from where to proceed or NO_NODE.
3494 **/
3495
3496 static NODE_T *
top_down_case(NODE_T * case_p)3497 top_down_case (NODE_T * case_p)
3498 {
3499 NODE_T *in_p = top_down_series (NEXT (case_p)), *ouse_p;
3500 if (in_p == NO_NODE || ISNT (in_p, IN_SYMBOL)) {
3501 top_down_diagnose (case_p, in_p, ENCLOSED_CLAUSE, IN_SYMBOL);
3502 longjmp (top_down_crash_exit, 1);
3503 }
3504 make_sub (case_p, PREVIOUS (in_p), CASE_SYMBOL);
3505 ouse_p = top_down_series (NEXT (in_p));
3506 if (ouse_p != NO_NODE && IS (ouse_p, ESAC_SYMBOL)) {
3507 make_sub (in_p, PREVIOUS (ouse_p), IN_SYMBOL);
3508 make_sub (case_p, ouse_p, CASE_SYMBOL);
3509 return (NEXT (case_p));
3510 }
3511 if (ouse_p != NO_NODE && IS (ouse_p, OUT_SYMBOL)) {
3512 NODE_T *esac_p = top_down_series (NEXT (ouse_p));
3513 if (esac_p == NO_NODE || ISNT (esac_p, ESAC_SYMBOL)) {
3514 top_down_diagnose (case_p, esac_p, ENCLOSED_CLAUSE, ESAC_SYMBOL);
3515 longjmp (top_down_crash_exit, 1);
3516 } else {
3517 make_sub (in_p, PREVIOUS (ouse_p), IN_SYMBOL);
3518 make_sub (ouse_p, PREVIOUS (esac_p), OUT_SYMBOL);
3519 make_sub (case_p, esac_p, CASE_SYMBOL);
3520 return (NEXT (case_p));
3521 }
3522 }
3523 if (ouse_p != NO_NODE && IS (ouse_p, OUSE_SYMBOL)) {
3524 NODE_T *esac_p = top_down_case (ouse_p);
3525 make_sub (in_p, PREVIOUS (ouse_p), IN_SYMBOL);
3526 make_sub (case_p, ouse_p, CASE_SYMBOL);
3527 return (esac_p);
3528 } else {
3529 top_down_diagnose (case_p, ouse_p, ENCLOSED_CLAUSE, ESAC_SYMBOL);
3530 longjmp (top_down_crash_exit, 1);
3531 return (NO_NODE);
3532 }
3533 }
3534
3535 /**
3536 @brief Skip a unit.
3537 @param p Node in syntax tree.
3538 @return Token from where to proceed or NO_NODE.
3539 **/
3540
3541 NODE_T *
top_down_skip_unit(NODE_T * p)3542 top_down_skip_unit (NODE_T * p)
3543 {
3544 while (p != NO_NODE && !is_unit_terminator (p)) {
3545 if (IS (p, BEGIN_SYMBOL)) {
3546 p = top_down_begin (p);
3547 } else if (IS (p, SUB_SYMBOL)) {
3548 p = top_down_sub (p);
3549 } else if (IS (p, OPEN_SYMBOL)) {
3550 p = top_down_open (p);
3551 } else if (IS (p, IF_SYMBOL)) {
3552 p = top_down_if (p);
3553 } else if (IS (p, CASE_SYMBOL)) {
3554 p = top_down_case (p);
3555 } else if (IS (p, CODE_SYMBOL)) {
3556 p = top_down_code (p);
3557 } else if (IS (p, ACCO_SYMBOL)) {
3558 p = top_down_acco (p);
3559 } else {
3560 FORWARD (p);
3561 }
3562 }
3563 return (p);
3564 }
3565
3566 static NODE_T *top_down_skip_format (NODE_T *);
3567
3568 /**
3569 @brief Make branch of ( .. ) in a format.
3570 @param open_p
3571 @return Token from where to proceed or NO_NODE.
3572 **/
3573
3574 static NODE_T *
top_down_format_open(NODE_T * open_p)3575 top_down_format_open (NODE_T * open_p)
3576 {
3577 NODE_T *close_p = top_down_skip_format (NEXT (open_p));
3578 if (close_p != NO_NODE && IS (close_p, FORMAT_CLOSE_SYMBOL)) {
3579 make_sub (open_p, close_p, FORMAT_OPEN_SYMBOL);
3580 return (NEXT (open_p));
3581 } else {
3582 top_down_diagnose (open_p, close_p, 0, FORMAT_CLOSE_SYMBOL);
3583 longjmp (top_down_crash_exit, 1);
3584 return (NO_NODE);
3585 }
3586 }
3587
3588 /**
3589 @brief Skip a format text.
3590 @param p Node in syntax tree.
3591 @return Token from where to proceed or NO_NODE.
3592 **/
3593
3594 static NODE_T *
top_down_skip_format(NODE_T * p)3595 top_down_skip_format (NODE_T * p)
3596 {
3597 while (p != NO_NODE) {
3598 if (IS (p, FORMAT_OPEN_SYMBOL)) {
3599 p = top_down_format_open (p);
3600 } else if (is_one_of (p, FORMAT_CLOSE_SYMBOL, FORMAT_DELIMITER_SYMBOL, STOP)) {
3601 return (p);
3602 } else {
3603 FORWARD (p);
3604 }
3605 }
3606 return (NO_NODE);
3607 }
3608
3609 /**
3610 @brief Make branch of $ .. $.
3611 @param p Node in syntax tree.
3612 **/
3613
3614 static void
top_down_formats(NODE_T * p)3615 top_down_formats (NODE_T * p)
3616 {
3617 NODE_T *q;
3618 for (q = p; q != NO_NODE; FORWARD (q)) {
3619 if (SUB (q) != NO_NODE) {
3620 top_down_formats (SUB (q));
3621 }
3622 }
3623 for (q = p; q != NO_NODE; FORWARD (q)) {
3624 if (IS (q, FORMAT_DELIMITER_SYMBOL)) {
3625 NODE_T *f = NEXT (q);
3626 while (f != NO_NODE && ISNT (f, FORMAT_DELIMITER_SYMBOL)) {
3627 if (IS (f, FORMAT_OPEN_SYMBOL)) {
3628 f = top_down_format_open (f);
3629 } else {
3630 f = NEXT (f);
3631 }
3632 }
3633 if (f == NO_NODE) {
3634 top_down_diagnose (p, f, FORMAT_TEXT, FORMAT_DELIMITER_SYMBOL);
3635 longjmp (top_down_crash_exit, 1);
3636 } else {
3637 make_sub (q, f, FORMAT_DELIMITER_SYMBOL);
3638 }
3639 }
3640 }
3641 }
3642
3643 /**
3644 @brief Make branches of phrases for the bottom-up parser.
3645 @param p Node in syntax tree.
3646 **/
3647
3648 void
top_down_parser(NODE_T * p)3649 top_down_parser (NODE_T * p)
3650 {
3651 if (p != NO_NODE) {
3652 if (!setjmp (top_down_crash_exit)) {
3653 (void) top_down_series (p);
3654 top_down_loops (p);
3655 top_down_untils (p);
3656 top_down_formats (p);
3657 }
3658 }
3659 }
3660
3661 /********************************************/
3662 /* Bottom-up parser, reduces all constructs */
3663 /********************************************/
3664
3665 /**
3666 @brief Detect redefined keyword.
3667 @param p Node in syntax tree.
3668 @param construct Where detected.
3669 */
3670
3671 static void
detect_redefined_keyword(NODE_T * p,int construct)3672 detect_redefined_keyword (NODE_T * p, int construct)
3673 {
3674 if (p != NO_NODE && whether (p, KEYWORD, EQUALS_SYMBOL, STOP)) {
3675 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_REDEFINED_KEYWORD, NSYMBOL (p), construct);
3676 }
3677 }
3678
3679 /**
3680 @brief Whether a series is serial or collateral.
3681 @param p Node in syntax tree.
3682 @return Whether a series is serial or collateral.
3683 **/
3684
3685 static int
serial_or_collateral(NODE_T * p)3686 serial_or_collateral (NODE_T * p)
3687 {
3688 NODE_T *q;
3689 int semis = 0, commas = 0, exits = 0;
3690 for (q = p; q != NO_NODE; FORWARD (q)) {
3691 if (IS (q, COMMA_SYMBOL)) {
3692 commas++;
3693 } else if (IS (q, SEMI_SYMBOL)) {
3694 semis++;
3695 } else if (IS (q, EXIT_SYMBOL)) {
3696 exits++;
3697 }
3698 }
3699 if (semis == 0 && exits == 0 && commas > 0) {
3700 return (COLLATERAL_CLAUSE);
3701 } else if ((semis > 0 || exits > 0) && commas == 0) {
3702 return (SERIAL_CLAUSE);
3703 } else if (semis == 0 && exits == 0 && commas == 0) {
3704 return (SERIAL_CLAUSE);
3705 } else {
3706 /* Heuristic guess to give intelligible error message */
3707 return ((semis + exits) >= (commas ? SERIAL_CLAUSE : COLLATERAL_CLAUSE));
3708 }
3709 }
3710
3711 /**
3712 @brief Whether formal bounds.
3713 @param p Node in syntax tree.
3714 @return Whether formal bounds.
3715 **/
3716
3717 static BOOL_T
is_formal_bounds(NODE_T * p)3718 is_formal_bounds (NODE_T * p)
3719 {
3720 if (p == NO_NODE) {
3721 return (A68_TRUE);
3722 } else {
3723 switch (ATTRIBUTE (p)) {
3724 case OPEN_SYMBOL:
3725 case CLOSE_SYMBOL:
3726 case SUB_SYMBOL:
3727 case BUS_SYMBOL:
3728 case COMMA_SYMBOL:
3729 case COLON_SYMBOL:
3730 case DOTDOT_SYMBOL:
3731 case INT_DENOTATION:
3732 case IDENTIFIER:
3733 case OPERATOR:
3734 {
3735 return ((BOOL_T) (is_formal_bounds (SUB (p)) && is_formal_bounds (NEXT (p))));
3736 }
3737 default:
3738 {
3739 return (A68_FALSE);
3740 }
3741 }
3742 }
3743 }
3744
3745 /**
3746 @brief Insert a node with attribute "a" after "p".
3747 @param p Node in syntax tree.
3748 @param a Attribute.
3749 **/
3750
3751 static void
pad_node(NODE_T * p,int a)3752 pad_node (NODE_T * p, int a)
3753 {
3754 /*
3755 This is used to fill information that Algol 68 does not require to be present.
3756 Filling in gives one format for such construct; this helps later passes.
3757 */
3758 NODE_T *z = new_node ();
3759 *z = *p;
3760 if (GINFO (p) != NO_GINFO) {
3761 GINFO (z) = new_genie_info ();
3762 }
3763 PREVIOUS (z) = p;
3764 SUB (z) = NO_NODE;
3765 ATTRIBUTE (z) = a;
3766 MOID (z) = NO_MOID;
3767 if (NEXT (z) != NO_NODE) {
3768 PREVIOUS (NEXT (z)) = z;
3769 }
3770 NEXT (p) = z;
3771 }
3772
3773 /**
3774 @brief Diagnose extensions.
3775 @param p Node in syntax tree.
3776 **/
3777
3778 static void
a68_extension(NODE_T * p)3779 a68_extension (NODE_T * p)
3780 {
3781 if (OPTION_PORTCHECK (&program)) {
3782 diagnostic_node (A68_WARNING | A68_FORCE_DIAGNOSTICS, p, WARNING_EXTENSION);
3783 } else {
3784 diagnostic_node (A68_WARNING, p, WARNING_EXTENSION);
3785 }
3786 }
3787
3788 /**
3789 @brief Diagnose for clauses not yielding a value.
3790 @param p Node in syntax tree.
3791 **/
3792
3793 static void
empty_clause(NODE_T * p)3794 empty_clause (NODE_T * p)
3795 {
3796 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_CLAUSE_WITHOUT_VALUE);
3797 }
3798
3799 #if ! defined HAVE_PARALLEL_CLAUSE
3800
3801 /**
3802 @brief Diagnose for parallel clause.
3803 @param p Node in syntax tree.
3804 **/
3805
3806 static void
par_clause(NODE_T * p)3807 par_clause (NODE_T * p)
3808 {
3809 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_NO_PARALLEL_CLAUSE);
3810 }
3811
3812 #endif
3813
3814 /**
3815 @brief Diagnose for missing symbol.
3816 @param p Node in syntax tree.
3817 **/
3818
3819 static void
strange_tokens(NODE_T * p)3820 strange_tokens (NODE_T * p)
3821 {
3822 NODE_T *q = ((p != NO_NODE && NEXT (p) != NO_NODE) ? NEXT (p) : p);
3823 diagnostic_node (A68_SYNTAX_ERROR, q, ERROR_SYNTAX_STRANGE_TOKENS);
3824 }
3825
3826 /**
3827 @brief Diagnose for strange separator.
3828 @param p Node in syntax tree.
3829 **/
3830
3831 static void
strange_separator(NODE_T * p)3832 strange_separator (NODE_T * p)
3833 {
3834 NODE_T *q = ((p != NO_NODE && NEXT (p) != NO_NODE) ? NEXT (p) : p);
3835 diagnostic_node (A68_SYNTAX_ERROR, q, ERROR_SYNTAX_STRANGE_SEPARATOR);
3836 }
3837
3838 /*
3839 Here is a set of routines that gather definitions from phrases.
3840 This way we can apply tags before defining them.
3841 These routines do not look very elegant as they have to scan through all
3842 kind of symbols to find a pattern that they recognise.
3843 */
3844
3845 /**
3846 @brief Skip anything until a comma, semicolon or EXIT is found.
3847 @param p Node in syntax tree.
3848 @return Node from where to proceed.
3849 **/
3850
3851 static NODE_T *
skip_unit(NODE_T * p)3852 skip_unit (NODE_T * p)
3853 {
3854 for (; p != NO_NODE; FORWARD (p)) {
3855 if (IS (p, COMMA_SYMBOL)) {
3856 return (p);
3857 } else if (IS (p, SEMI_SYMBOL)) {
3858 return (p);
3859 } else if (IS (p, EXIT_SYMBOL)) {
3860 return (p);
3861 }
3862 }
3863 return (NO_NODE);
3864 }
3865
3866 /**
3867 @brief Attribute of entry in symbol table.
3868 @param table Current symbol table.
3869 @param name Token name.
3870 @return Attribute of entry in symbol table, or 0 if not found.
3871 **/
3872
3873 static int
find_tag_definition(TABLE_T * table,char * name)3874 find_tag_definition (TABLE_T * table, char *name)
3875 {
3876 if (table != NO_TABLE) {
3877 int ret = 0;
3878 TAG_T *s;
3879 BOOL_T found;
3880 found = A68_FALSE;
3881 for (s = INDICANTS (table); s != NO_TAG && !found; FORWARD (s)) {
3882 if (NSYMBOL (NODE (s)) == name) {
3883 ret += INDICANT;
3884 found = A68_TRUE;
3885 }
3886 }
3887 found = A68_FALSE;
3888 for (s = OPERATORS (table); s != NO_TAG && !found; FORWARD (s)) {
3889 if (NSYMBOL (NODE (s)) == name) {
3890 ret += OPERATOR;
3891 found = A68_TRUE;
3892 }
3893 }
3894 if (ret == 0) {
3895 return (find_tag_definition (PREVIOUS (table), name));
3896 } else {
3897 return (ret);
3898 }
3899 } else {
3900 return (0);
3901 }
3902 }
3903
3904 /**
3905 @brief Fill in whether bold tag is operator or indicant.
3906 @param p Node in syntax tree.
3907 **/
3908
3909 static void
elaborate_bold_tags(NODE_T * p)3910 elaborate_bold_tags (NODE_T * p)
3911 {
3912 NODE_T *q;
3913 for (q = p; q != NO_NODE; FORWARD (q)) {
3914 if (IS (q, BOLD_TAG)) {
3915 switch (find_tag_definition (TABLE (q), NSYMBOL (q))) {
3916 case 0:
3917 {
3918 diagnostic_node (A68_SYNTAX_ERROR, q, ERROR_UNDECLARED_TAG);
3919 break;
3920 }
3921 case INDICANT:
3922 {
3923 ATTRIBUTE (q) = INDICANT;
3924 break;
3925 }
3926 case OPERATOR:
3927 {
3928 ATTRIBUTE (q) = OPERATOR;
3929 break;
3930 }
3931 }
3932 }
3933 }
3934 }
3935
3936 /**
3937 @brief Skip declarer, or argument pack and declarer.
3938 @param p Node in syntax tree.
3939 @return Node before token that is not part of pack or declarer .
3940 **/
3941
3942 static NODE_T *
skip_pack_declarer(NODE_T * p)3943 skip_pack_declarer (NODE_T * p)
3944 {
3945 /* Skip () REF [] REF FLEX [] [] .. */
3946 while (p != NO_NODE && (is_one_of (p, SUB_SYMBOL, OPEN_SYMBOL, REF_SYMBOL, FLEX_SYMBOL, SHORT_SYMBOL, LONG_SYMBOL, STOP))) {
3947 FORWARD (p);
3948 }
3949 /* Skip STRUCT (), UNION () or PROC [()] */
3950 if (p != NO_NODE && (is_one_of (p, STRUCT_SYMBOL, UNION_SYMBOL, STOP))) {
3951 return (NEXT (p));
3952 } else if (p != NO_NODE && IS (p, PROC_SYMBOL)) {
3953 return (skip_pack_declarer (NEXT (p)));
3954 } else {
3955 return (p);
3956 }
3957 }
3958
3959 /**
3960 @brief Search MODE A = .., B = .. and store indicants.
3961 @param p Node in syntax tree.
3962 **/
3963
3964 static void
extract_indicants(NODE_T * p)3965 extract_indicants (NODE_T * p)
3966 {
3967 NODE_T *q = p;
3968 while (q != NO_NODE) {
3969 if (IS (q, MODE_SYMBOL)) {
3970 BOOL_T siga = A68_TRUE;
3971 do {
3972 FORWARD (q);
3973 detect_redefined_keyword (q, MODE_DECLARATION);
3974 if (whether (q, BOLD_TAG, EQUALS_SYMBOL, STOP)) {
3975 /* Store in the symbol table, but also in the moid list.
3976 Position of definition (q) connects to this lexical level!
3977 */
3978 ASSERT (add_tag (TABLE (p), INDICANT, q, NO_MOID, STOP) != NO_TAG);
3979 ASSERT (add_mode (&TOP_MOID (&program), INDICANT, 0, q, NO_MOID, NO_PACK) != NO_MOID);
3980 ATTRIBUTE (q) = DEFINING_INDICANT;
3981 FORWARD (q);
3982 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
3983 q = skip_pack_declarer (NEXT (q));
3984 FORWARD (q);
3985 } else {
3986 siga = A68_FALSE;
3987 }
3988 } while (siga && q != NO_NODE && IS (q, COMMA_SYMBOL));
3989 } else {
3990 FORWARD (q);
3991 }
3992 }
3993 }
3994
3995 #define GET_PRIORITY(q, k)\
3996 RESET_ERRNO;\
3997 (k) = atoi (NSYMBOL (q));\
3998 if (errno != 0) {\
3999 diagnostic_node (A68_SYNTAX_ERROR, (q), ERROR_INVALID_PRIORITY);\
4000 (k) = MAX_PRIORITY;\
4001 } else if ((k) < 1 || (k) > MAX_PRIORITY) {\
4002 diagnostic_node (A68_SYNTAX_ERROR, (q), ERROR_INVALID_PRIORITY);\
4003 (k) = MAX_PRIORITY;\
4004 }
4005
4006 /**
4007 @brief Search PRIO X = .., Y = .. and store priorities.
4008 @param p Node in syntax tree.
4009 **/
4010
4011 static void
extract_priorities(NODE_T * p)4012 extract_priorities (NODE_T * p)
4013 {
4014 NODE_T *q = p;
4015 while (q != NO_NODE) {
4016 if (IS (q, PRIO_SYMBOL)) {
4017 BOOL_T siga = A68_TRUE;
4018 do {
4019 FORWARD (q);
4020 detect_redefined_keyword (q, PRIORITY_DECLARATION);
4021 /* An operator tag like ++ or && gives strange errors so we catch it here */
4022 if (whether (q, OPERATOR, OPERATOR, STOP)) {
4023 int k;
4024 NODE_T *y = q;
4025 diagnostic_node (A68_SYNTAX_ERROR, q, ERROR_INVALID_OPERATOR_TAG);
4026 ATTRIBUTE (q) = DEFINING_OPERATOR;
4027 /* Remove one superfluous operator, and hope it was only one. */
4028 NEXT (q) = NEXT_NEXT (q);
4029 PREVIOUS (NEXT (q)) = q;
4030 FORWARD (q);
4031 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
4032 FORWARD (q);
4033 GET_PRIORITY (q, k);
4034 ATTRIBUTE (q) = PRIORITY;
4035 ASSERT (add_tag (TABLE (p), PRIO_SYMBOL, y, NO_MOID, k) != NO_TAG);
4036 FORWARD (q);
4037 } else if (whether (q, OPERATOR, EQUALS_SYMBOL, INT_DENOTATION, STOP) || whether (q, EQUALS_SYMBOL, EQUALS_SYMBOL, INT_DENOTATION, STOP)) {
4038 int k;
4039 NODE_T *y = q;
4040 ATTRIBUTE (q) = DEFINING_OPERATOR;
4041 FORWARD (q);
4042 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
4043 FORWARD (q);
4044 GET_PRIORITY (q, k);
4045 ATTRIBUTE (q) = PRIORITY;
4046 ASSERT (add_tag (TABLE (p), PRIO_SYMBOL, y, NO_MOID, k) != NO_TAG);
4047 FORWARD (q);
4048 } else if (whether (q, BOLD_TAG, IDENTIFIER, STOP)) {
4049 siga = A68_FALSE;
4050 } else if (whether (q, BOLD_TAG, EQUALS_SYMBOL, INT_DENOTATION, STOP)) {
4051 int k;
4052 NODE_T *y = q;
4053 ATTRIBUTE (q) = DEFINING_OPERATOR;
4054 FORWARD (q);
4055 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
4056 FORWARD (q);
4057 GET_PRIORITY (q, k);
4058 ATTRIBUTE (q) = PRIORITY;
4059 ASSERT (add_tag (TABLE (p), PRIO_SYMBOL, y, NO_MOID, k) != NO_TAG);
4060 FORWARD (q);
4061 } else if (whether (q, BOLD_TAG, INT_DENOTATION, STOP) || whether (q, OPERATOR, INT_DENOTATION, STOP) || whether (q, EQUALS_SYMBOL, INT_DENOTATION, STOP)) {
4062 /* The scanner cannot separate operator and "=" sign so we do this here */
4063 int len = (int) strlen (NSYMBOL (q));
4064 if (len > 1 && NSYMBOL (q)[len - 1] == '=') {
4065 int k;
4066 NODE_T *y = q;
4067 char *sym = (char *) get_temp_heap_space ((size_t) (len + 1));
4068 bufcpy (sym, NSYMBOL (q), len + 1);
4069 sym[len - 1] = NULL_CHAR;
4070 NSYMBOL (q) = TEXT (add_token (&top_token, sym));
4071 if (len > 2 && NSYMBOL (q)[len - 2] == ':' && NSYMBOL (q)[len - 3] != '=') {
4072 diagnostic_node (A68_SYNTAX_ERROR, q, ERROR_OPERATOR_INVALID_END);
4073 }
4074 ATTRIBUTE (q) = DEFINING_OPERATOR;
4075 insert_alt_equals (q);
4076 q = NEXT_NEXT (q);
4077 GET_PRIORITY (q, k);
4078 ATTRIBUTE (q) = PRIORITY;
4079 ASSERT (add_tag (TABLE (p), PRIO_SYMBOL, y, NO_MOID, k) != NO_TAG);
4080 FORWARD (q);
4081 } else {
4082 siga = A68_FALSE;
4083 }
4084 } else {
4085 siga = A68_FALSE;
4086 }
4087 } while (siga && q != NO_NODE && IS (q, COMMA_SYMBOL));
4088 } else {
4089 FORWARD (q);
4090 }
4091 }
4092 }
4093
4094 /**
4095 @brief Search OP [( .. ) ..] X = .., Y = .. and store operators.
4096 @param p Node in syntax tree.
4097 **/
4098
4099 static void
extract_operators(NODE_T * p)4100 extract_operators (NODE_T * p)
4101 {
4102 NODE_T *q = p;
4103 while (q != NO_NODE) {
4104 if (ISNT (q, OP_SYMBOL)) {
4105 FORWARD (q);
4106 } else {
4107 BOOL_T siga = A68_TRUE;
4108 /* Skip operator plan */
4109 if (NEXT (q) != NO_NODE && IS (NEXT (q), OPEN_SYMBOL)) {
4110 q = skip_pack_declarer (NEXT (q));
4111 }
4112 /* Sample operators */
4113 if (q != NO_NODE) {
4114 do {
4115 FORWARD (q);
4116 detect_redefined_keyword (q, OPERATOR_DECLARATION);
4117 /* Unacceptable operator tags like ++ or && could give strange errors */
4118 if (whether (q, OPERATOR, OPERATOR, STOP)) {
4119 diagnostic_node (A68_SYNTAX_ERROR, q, ERROR_INVALID_OPERATOR_TAG);
4120 ATTRIBUTE (q) = DEFINING_OPERATOR;
4121 ASSERT (add_tag (TABLE (p), OP_SYMBOL, q, NO_MOID, STOP) != NO_TAG);
4122 NEXT (q) = NEXT_NEXT (q); /* Remove one superfluous operator, and hope it was only one */
4123 PREVIOUS (NEXT (q)) = q;
4124 FORWARD (q);
4125 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
4126 q = skip_unit (q);
4127 } else if (whether (q, OPERATOR, EQUALS_SYMBOL, STOP) || whether (q, EQUALS_SYMBOL, EQUALS_SYMBOL, STOP)) {
4128 ATTRIBUTE (q) = DEFINING_OPERATOR;
4129 ASSERT (add_tag (TABLE (p), OP_SYMBOL, q, NO_MOID, STOP) != NO_TAG);
4130 FORWARD (q);
4131 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
4132 q = skip_unit (q);
4133 } else if (whether (q, BOLD_TAG, IDENTIFIER, STOP)) {
4134 siga = A68_FALSE;
4135 } else if (whether (q, BOLD_TAG, EQUALS_SYMBOL, STOP)) {
4136 ATTRIBUTE (q) = DEFINING_OPERATOR;
4137 ASSERT (add_tag (TABLE (p), OP_SYMBOL, q, NO_MOID, STOP) != NO_TAG);
4138 FORWARD (q);
4139 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
4140 q = skip_unit (q);
4141 } else if (q != NO_NODE && (is_one_of (q, OPERATOR, BOLD_TAG, EQUALS_SYMBOL, STOP))) {
4142 /* The scanner cannot separate operator and "=" sign so we do this here */
4143 int len = (int) strlen (NSYMBOL (q));
4144 if (len > 1 && NSYMBOL (q)[len - 1] == '=') {
4145 char *sym = (char *) get_temp_heap_space ((size_t) (len + 1));
4146 bufcpy (sym, NSYMBOL (q), len + 1);
4147 sym[len - 1] = NULL_CHAR;
4148 NSYMBOL (q) = TEXT (add_token (&top_token, sym));
4149 if (len > 2 && NSYMBOL (q)[len - 2] == ':' && NSYMBOL (q)[len - 3] != '=') {
4150 diagnostic_node (A68_SYNTAX_ERROR, q, ERROR_OPERATOR_INVALID_END);
4151 }
4152 ATTRIBUTE (q) = DEFINING_OPERATOR;
4153 insert_alt_equals (q);
4154 ASSERT (add_tag (TABLE (p), OP_SYMBOL, q, NO_MOID, STOP) != NO_TAG);
4155 FORWARD (q);
4156 q = skip_unit (q);
4157 } else {
4158 siga = A68_FALSE;
4159 }
4160 } else {
4161 siga = A68_FALSE;
4162 }
4163 } while (siga && q != NO_NODE && IS (q, COMMA_SYMBOL));
4164 }
4165 }
4166 }
4167 }
4168
4169 /**
4170 @brief Search and store labels.
4171 @param p Node in syntax tree.
4172 @param expect Information the parser may have on what is expected.
4173 **/
4174
4175 static void
extract_labels(NODE_T * p,int expect)4176 extract_labels (NODE_T * p, int expect)
4177 {
4178 NODE_T *q;
4179 /* Only handle candidate phrases as not to search indexers! */
4180 if (expect == SERIAL_CLAUSE || expect == ENQUIRY_CLAUSE || expect == SOME_CLAUSE) {
4181 for (q = p; q != NO_NODE; FORWARD (q)) {
4182 if (whether (q, IDENTIFIER, COLON_SYMBOL, STOP)) {
4183 TAG_T *z = add_tag (TABLE (p), LABEL, q, NO_MOID, LOCAL_LABEL);
4184 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
4185 UNIT (z) = NO_NODE;
4186 }
4187 }
4188 }
4189 }
4190
4191 /**
4192 @brief Search MOID x = .., y = .. and store identifiers.
4193 @param p Node in syntax tree.
4194 **/
4195
4196 static void
extract_identities(NODE_T * p)4197 extract_identities (NODE_T * p)
4198 {
4199 NODE_T *q = p;
4200 while (q != NO_NODE) {
4201 if (whether (q, DECLARER, IDENTIFIER, EQUALS_SYMBOL, STOP)) {
4202 BOOL_T siga = A68_TRUE;
4203 do {
4204 if (whether ((FORWARD (q)), IDENTIFIER, EQUALS_SYMBOL, STOP)) {
4205 ASSERT (add_tag (TABLE (p), IDENTIFIER, q, NO_MOID, NORMAL_IDENTIFIER) != NO_TAG);
4206 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
4207 FORWARD (q);
4208 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
4209 q = skip_unit (q);
4210 } else if (whether (q, IDENTIFIER, ASSIGN_SYMBOL, STOP)) {
4211 /* Handle common error in ALGOL 68 programs */
4212 diagnostic_node (A68_SYNTAX_ERROR, q, ERROR_SYNTAX_MIXED_DECLARATION);
4213 ASSERT (add_tag (TABLE (p), IDENTIFIER, q, NO_MOID, NORMAL_IDENTIFIER) != NO_TAG);
4214 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
4215 ATTRIBUTE (FORWARD (q)) = ALT_EQUALS_SYMBOL;
4216 q = skip_unit (q);
4217 } else {
4218 siga = A68_FALSE;
4219 }
4220 } while (siga && q != NO_NODE && IS (q, COMMA_SYMBOL));
4221 } else {
4222 FORWARD (q);
4223 }
4224 }
4225 }
4226
4227 /**
4228 @brief Search MOID x [:= ..], y [:= ..] and store identifiers.
4229 @param p Node in syntax tree.
4230 **/
4231
4232 static void
extract_variables(NODE_T * p)4233 extract_variables (NODE_T * p)
4234 {
4235 NODE_T *q = p;
4236 while (q != NO_NODE) {
4237 if (whether (q, DECLARER, IDENTIFIER, STOP)) {
4238 BOOL_T siga = A68_TRUE;
4239 do {
4240 FORWARD (q);
4241 if (whether (q, IDENTIFIER, STOP)) {
4242 if (whether (q, IDENTIFIER, EQUALS_SYMBOL, STOP)) {
4243 /* Handle common error in ALGOL 68 programs */
4244 diagnostic_node (A68_SYNTAX_ERROR, q, ERROR_SYNTAX_MIXED_DECLARATION);
4245 ATTRIBUTE (NEXT (q)) = ASSIGN_SYMBOL;
4246 }
4247 ASSERT (add_tag (TABLE (p), IDENTIFIER, q, NO_MOID, NORMAL_IDENTIFIER) != NO_TAG);
4248 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
4249 q = skip_unit (q);
4250 } else {
4251 siga = A68_FALSE;
4252 }
4253 } while (siga && q != NO_NODE && IS (q, COMMA_SYMBOL));
4254 } else {
4255 FORWARD (q);
4256 }
4257 }
4258 }
4259
4260 /**
4261 @brief Search PROC x = .., y = .. and stores identifiers.
4262 @param p Node in syntax tree.
4263 **/
4264
4265 static void
extract_proc_identities(NODE_T * p)4266 extract_proc_identities (NODE_T * p)
4267 {
4268 NODE_T *q = p;
4269 while (q != NO_NODE) {
4270 if (whether (q, PROC_SYMBOL, IDENTIFIER, EQUALS_SYMBOL, STOP)) {
4271 BOOL_T siga = A68_TRUE;
4272 do {
4273 FORWARD (q);
4274 if (whether (q, IDENTIFIER, EQUALS_SYMBOL, STOP)) {
4275 TAG_T *t = add_tag (TABLE (p), IDENTIFIER, q, NO_MOID, NORMAL_IDENTIFIER);
4276 IN_PROC (t) = A68_TRUE;
4277 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
4278 ATTRIBUTE (FORWARD (q)) = ALT_EQUALS_SYMBOL;
4279 q = skip_unit (q);
4280 } else if (whether (q, IDENTIFIER, ASSIGN_SYMBOL, STOP)) {
4281 /* Handle common error in ALGOL 68 programs */
4282 diagnostic_node (A68_SYNTAX_ERROR, q, ERROR_SYNTAX_MIXED_DECLARATION);
4283 ASSERT (add_tag (TABLE (p), IDENTIFIER, q, NO_MOID, NORMAL_IDENTIFIER) != NO_TAG);
4284 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
4285 ATTRIBUTE (FORWARD (q)) = ALT_EQUALS_SYMBOL;
4286 q = skip_unit (q);
4287 } else {
4288 siga = A68_FALSE;
4289 }
4290 } while (siga && q != NO_NODE && IS (q, COMMA_SYMBOL));
4291 } else {
4292 FORWARD (q);
4293 }
4294 }
4295 }
4296
4297 /**
4298 @brief Search PROC x [:= ..], y [:= ..]; store identifiers.
4299 @param p Node in syntax tree.
4300 **/
4301
4302 static void
extract_proc_variables(NODE_T * p)4303 extract_proc_variables (NODE_T * p)
4304 {
4305 NODE_T *q = p;
4306 while (q != NO_NODE) {
4307 if (whether (q, PROC_SYMBOL, IDENTIFIER, STOP)) {
4308 BOOL_T siga = A68_TRUE;
4309 do {
4310 FORWARD (q);
4311 if (whether (q, IDENTIFIER, ASSIGN_SYMBOL, STOP)) {
4312 ASSERT (add_tag (TABLE (p), IDENTIFIER, q, NO_MOID, NORMAL_IDENTIFIER) != NO_TAG);
4313 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
4314 q = skip_unit (FORWARD (q));
4315 } else if (whether (q, IDENTIFIER, EQUALS_SYMBOL, STOP)) {
4316 /* Handle common error in ALGOL 68 programs */
4317 diagnostic_node (A68_SYNTAX_ERROR, q, ERROR_SYNTAX_MIXED_DECLARATION);
4318 ASSERT (add_tag (TABLE (p), IDENTIFIER, q, NO_MOID, NORMAL_IDENTIFIER) != NO_TAG);
4319 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
4320 ATTRIBUTE (FORWARD (q)) = ASSIGN_SYMBOL;
4321 q = skip_unit (q);
4322 } else {
4323 siga = A68_FALSE;
4324 }
4325 } while (siga && q != NO_NODE && IS (q, COMMA_SYMBOL));
4326 } else {
4327 FORWARD (q);
4328 }
4329 }
4330 }
4331
4332
4333 /**
4334 @brief Schedule gathering of definitions in a phrase.
4335 @param p Node in syntax tree.
4336 **/
4337
4338 static void
extract_declarations(NODE_T * p)4339 extract_declarations (NODE_T * p)
4340 {
4341 NODE_T *q;
4342 /* Get definitions so we know what is defined in this range */
4343 extract_identities (p);
4344 extract_variables (p);
4345 extract_proc_identities (p);
4346 extract_proc_variables (p);
4347 /* By now we know whether "=" is an operator or not */
4348 for (q = p; q != NO_NODE; FORWARD (q)) {
4349 if (IS (q, EQUALS_SYMBOL)) {
4350 ATTRIBUTE (q) = OPERATOR;
4351 } else if (IS (q, ALT_EQUALS_SYMBOL)) {
4352 ATTRIBUTE (q) = EQUALS_SYMBOL;
4353 }
4354 }
4355 /* Get qualifiers */
4356 for (q = p; q != NO_NODE; FORWARD (q)) {
4357 if (whether (q, LOC_SYMBOL, DECLARER, DEFINING_IDENTIFIER, STOP)) {
4358 make_sub (q, q, QUALIFIER);
4359 }
4360 if (whether (q, HEAP_SYMBOL, DECLARER, DEFINING_IDENTIFIER, STOP)) {
4361 make_sub (q, q, QUALIFIER);
4362 }
4363 if (whether (q, NEW_SYMBOL, DECLARER, DEFINING_IDENTIFIER, STOP)) {
4364 make_sub (q, q, QUALIFIER);
4365 }
4366 if (whether (q, LOC_SYMBOL, PROC_SYMBOL, DEFINING_IDENTIFIER, STOP)) {
4367 make_sub (q, q, QUALIFIER);
4368 }
4369 if (whether (q, HEAP_SYMBOL, PROC_SYMBOL, DEFINING_IDENTIFIER, STOP)) {
4370 make_sub (q, q, QUALIFIER);
4371 }
4372 if (whether (q, NEW_SYMBOL, PROC_SYMBOL, DEFINING_IDENTIFIER, STOP)) {
4373 make_sub (q, q, QUALIFIER);
4374 }
4375 }
4376 /* Give priorities to operators */
4377 for (q = p; q != NO_NODE; FORWARD (q)) {
4378 if (IS (q, OPERATOR)) {
4379 if (find_tag_global (TABLE (q), OP_SYMBOL, NSYMBOL (q))) {
4380 TAG_T *s = find_tag_global (TABLE (q), PRIO_SYMBOL, NSYMBOL (q));
4381 if (s != NO_TAG) {
4382 PRIO (INFO (q)) = PRIO (s);
4383 } else {
4384 PRIO (INFO (q)) = 0;
4385 }
4386 } else {
4387 diagnostic_node (A68_SYNTAX_ERROR, q, ERROR_UNDECLARED_TAG);
4388 PRIO (INFO (q)) = 1;
4389 }
4390 }
4391 }
4392 }
4393
4394 /**
4395 @brief If match then reduce a sentence, the core BU parser routine.
4396 @param p Token where to start matching.
4397 @param a If not NO_NOTE, procedure to execute upon match.
4398 @param z If not NO_TICK, to be set to TRUE upon match.
4399 **/
4400
4401 static void
reduce(NODE_T * p,void (* a)(NODE_T *),BOOL_T * z,...)4402 reduce (NODE_T * p, void (*a) (NODE_T *), BOOL_T * z, ...)
4403 {
4404 va_list list;
4405 int result, arg;
4406 NODE_T *head = p, *tail = NO_NODE;
4407 va_start (list, z);
4408 result = va_arg (list, int);
4409 while ((arg = va_arg (list, int)) != STOP)
4410 {
4411 BOOL_T keep_matching;
4412 if (p == NO_NODE) {
4413 keep_matching = A68_FALSE;
4414 } else if (arg == WILDCARD) {
4415 /* WILDCARD matches any Algol68G non terminal, but no keyword */
4416 keep_matching = (BOOL_T) (non_terminal_string (edit_line, ATTRIBUTE (p)) != NO_TEXT);
4417 } else {
4418 if (arg >= 0) {
4419 keep_matching = (BOOL_T) (arg == ATTRIBUTE (p));
4420 } else {
4421 keep_matching = (BOOL_T) (arg != ATTRIBUTE (p));
4422 }
4423 }
4424 if (keep_matching) {
4425 tail = p;
4426 FORWARD (p);
4427 } else {
4428 va_end (list);
4429 return;
4430 }
4431 }
4432 /* Print parser reductions */
4433 if (head != NO_NODE && OPTION_REDUCTIONS (&program) && LINE_NUMBER (head) > 0) {
4434 NODE_T *q;
4435 int count = 0;
4436 reductions++;
4437 WIS (head);
4438 ASSERT (snprintf (output_line, SNPRINTF_SIZE, "\nReduction %d: %s<-", reductions, non_terminal_string (edit_line, result)) >= 0);
4439 WRITE (STDOUT_FILENO, output_line);
4440 for (q = head; q != NO_NODE && tail != NO_NODE && q != NEXT (tail); FORWARD (q), count++) {
4441 int gatt = ATTRIBUTE (q);
4442 char *str = non_terminal_string (input_line, gatt);
4443 if (count > 0) {
4444 WRITE (STDOUT_FILENO, ", ");
4445 }
4446 if (str != NO_TEXT) {
4447 WRITE (STDOUT_FILENO, str);
4448 if (gatt == IDENTIFIER || gatt == OPERATOR || gatt == DENOTATION || gatt == INDICANT) {
4449 ASSERT (snprintf (output_line, SNPRINTF_SIZE, " \"%s\"", NSYMBOL (q)) >= 0);
4450 WRITE (STDOUT_FILENO, output_line);
4451 }
4452 } else {
4453 WRITE (STDOUT_FILENO, NSYMBOL (q));
4454 }
4455 }
4456 }
4457 /* Make reduction */
4458 if (a != NO_NOTE) {
4459 a (head);
4460 }
4461 make_sub (head, tail, result);
4462 va_end (list);
4463 if (z != NO_TICK) {
4464 *z = A68_TRUE;
4465 }
4466 }
4467
4468 /**
4469 @brief Graciously ignore extra semicolons.
4470 @param p Node in syntax tree.
4471 **/
4472
4473 static void
ignore_superfluous_semicolons(NODE_T * p)4474 ignore_superfluous_semicolons (NODE_T * p)
4475 {
4476 /*
4477 This routine relaxes the parser a bit with respect to superfluous semicolons,
4478 for instance "FI; OD". These provoke only a warning.
4479 */
4480 for (; p != NO_NODE; FORWARD (p)) {
4481 ignore_superfluous_semicolons (SUB (p));
4482 if (NEXT (p) != NO_NODE && IS (NEXT (p), SEMI_SYMBOL) && NEXT_NEXT (p) == NO_NODE) {
4483 diagnostic_node (A68_WARNING | A68_FORCE_DIAGNOSTICS, NEXT (p), WARNING_SKIPPED_SUPERFLUOUS, ATTRIBUTE (NEXT (p)));
4484 NEXT (p) = NO_NODE;
4485 } else if (IS (p, SEMI_SYMBOL) && is_semicolon_less (NEXT (p))) {
4486 diagnostic_node (A68_WARNING | A68_FORCE_DIAGNOSTICS, p, WARNING_SKIPPED_SUPERFLUOUS, ATTRIBUTE (p));
4487 if (PREVIOUS (p) != NO_NODE) {
4488 NEXT (PREVIOUS (p)) = NEXT (p);
4489 }
4490 PREVIOUS (NEXT (p)) = PREVIOUS (p);
4491 }
4492 }
4493 }
4494
4495 /**
4496 @brief Driver for the bottom-up parser.
4497 @param p Node in syntax tree.
4498 **/
4499
4500 void
bottom_up_parser(NODE_T * p)4501 bottom_up_parser (NODE_T * p)
4502 {
4503 if (p != NO_NODE) {
4504 if (!setjmp (bottom_up_crash_exit)) {
4505 NODE_T *q;
4506 int error_count_0 = ERROR_COUNT (&program);
4507 ignore_superfluous_semicolons (p);
4508 /* A program is "label sequence; particular program" */
4509 extract_labels (p, SERIAL_CLAUSE /* a fake here, but ok */ );
4510 /* Parse the program itself */
4511 for (q = p; q != NO_NODE; FORWARD (q)) {
4512 BOOL_T siga = A68_TRUE;
4513 if (SUB (q) != NO_NODE) {
4514 reduce_branch (q, SOME_CLAUSE);
4515 }
4516 while (siga) {
4517 siga = A68_FALSE;
4518 reduce (q, NO_NOTE, &siga, LABEL, DEFINING_IDENTIFIER, COLON_SYMBOL, STOP);
4519 reduce (q, NO_NOTE, &siga, LABEL, LABEL, DEFINING_IDENTIFIER, COLON_SYMBOL, STOP);
4520 }
4521 }
4522 /* Determine the encompassing enclosed clause */
4523 for (q = p; q != NO_NODE; FORWARD (q)) {
4524 #if defined HAVE_PARALLEL_CLAUSE
4525 reduce (q, NO_NOTE, NO_TICK, PARALLEL_CLAUSE, PAR_SYMBOL, COLLATERAL_CLAUSE, STOP);
4526 #else
4527 reduce (q, par_clause, NO_TICK, PARALLEL_CLAUSE, PAR_SYMBOL, COLLATERAL_CLAUSE, STOP);
4528 #endif
4529 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, PARALLEL_CLAUSE, STOP);
4530 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CLOSED_CLAUSE, STOP);
4531 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, COLLATERAL_CLAUSE, STOP);
4532 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CONDITIONAL_CLAUSE, STOP);
4533 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CASE_CLAUSE, STOP);
4534 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CONFORMITY_CLAUSE, STOP);
4535 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, LOOP_CLAUSE, STOP);
4536 }
4537 /* Try reducing the particular program */
4538 q = p;
4539 reduce (q, NO_NOTE, NO_TICK, PARTICULAR_PROGRAM, LABEL, ENCLOSED_CLAUSE, STOP);
4540 reduce (q, NO_NOTE, NO_TICK, PARTICULAR_PROGRAM, ENCLOSED_CLAUSE, STOP);
4541 if (SUB (p) == NO_NODE || NEXT (p) != NO_NODE) {
4542 recover_from_error (p, PARTICULAR_PROGRAM, (BOOL_T) ((ERROR_COUNT (&program) - error_count_0) > MAX_ERRORS));
4543 }
4544 }
4545 }
4546 }
4547
4548 /**
4549 @brief Reduce code clause.
4550 @param p Node in syntax tree.
4551 **/
4552
4553 static void
reduce_code_clause(NODE_T * p)4554 reduce_code_clause (NODE_T * p)
4555 {
4556 BOOL_T siga = A68_TRUE;
4557 while (siga) {
4558 NODE_T *u;
4559 siga = A68_FALSE;
4560 for (u = p; u != NO_NODE; FORWARD (u)) {
4561 reduce (u, NO_NOTE, &siga, CODE_LIST, CODE_SYMBOL, ROW_CHAR_DENOTATION, STOP);
4562 reduce (u, NO_NOTE, &siga, CODE_LIST, CODE_LIST, ROW_CHAR_DENOTATION, STOP);
4563 reduce (u, NO_NOTE, &siga, CODE_LIST, CODE_LIST, COMMA_SYMBOL, ROW_CHAR_DENOTATION, STOP);
4564 reduce (u, NO_NOTE, &siga, CODE_CLAUSE, CODE_LIST, EDOC_SYMBOL, STOP);
4565 }
4566 }
4567 }
4568
4569 /**
4570 @brief Reduce the sub-phrase that starts one level down.
4571 @param q Node in syntax tree.
4572 @param expect Information the parser may have on what is expected.
4573 **/
4574
4575 static void
reduce_branch(NODE_T * q,int expect)4576 reduce_branch (NODE_T * q, int expect)
4577 {
4578 /*
4579 If this is unsuccessful then it will at least copy the resulting attribute
4580 as the parser can repair some faults. This gives less spurious diagnostics.
4581 */
4582 if (q != NO_NODE && SUB (q) != NO_NODE) {
4583 NODE_T *p = SUB (q), *u = NO_NODE;
4584 int error_count_0 = ERROR_COUNT (&program), error_count_02;
4585 BOOL_T declarer_pack = A68_FALSE, no_error;
4586 switch (expect) {
4587 case STRUCTURE_PACK:
4588 case PARAMETER_PACK:
4589 case FORMAL_DECLARERS:
4590 case UNION_PACK:
4591 case SPECIFIER:{
4592 declarer_pack = A68_TRUE;
4593 }
4594 default:{
4595 declarer_pack = A68_FALSE;
4596 }
4597 }
4598 /* Sample all info needed to decide whether a bold tag is operator or indicant.
4599 Find the meaning of bold tags and quit in case of extra errors. */
4600 extract_indicants (p);
4601 if (!declarer_pack) {
4602 extract_priorities (p);
4603 extract_operators (p);
4604 }
4605 error_count_02 = ERROR_COUNT (&program);
4606 elaborate_bold_tags (p);
4607 if ((ERROR_COUNT (&program) - error_count_02) > 0) {
4608 longjmp (bottom_up_crash_exit, 1);
4609 }
4610 /* Now we can reduce declarers, knowing which bold tags are indicants */
4611 reduce_declarers (p, expect);
4612 /* Parse the phrase, as appropriate */
4613 if (expect == CODE_CLAUSE) {
4614 reduce_code_clause (p);
4615 } else if (declarer_pack == A68_FALSE) {
4616 error_count_02 = ERROR_COUNT (&program);
4617 extract_declarations (p);
4618 if ((ERROR_COUNT (&program) - error_count_02) > 0) {
4619 longjmp (bottom_up_crash_exit, 1);
4620 }
4621 extract_labels (p, expect);
4622 for (u = p; u != NO_NODE; FORWARD (u)) {
4623 if (SUB (u) != NO_NODE) {
4624 if (IS (u, FORMAT_DELIMITER_SYMBOL)) {
4625 reduce_branch (u, FORMAT_TEXT);
4626 } else if (IS (u, FORMAT_OPEN_SYMBOL)) {
4627 reduce_branch (u, FORMAT_TEXT);
4628 } else if (IS (u, OPEN_SYMBOL)) {
4629 if (NEXT (u) != NO_NODE && IS (NEXT (u), THEN_BAR_SYMBOL)) {
4630 reduce_branch (u, ENQUIRY_CLAUSE);
4631 } else if (PREVIOUS (u) != NO_NODE && IS (PREVIOUS (u), PAR_SYMBOL)) {
4632 reduce_branch (u, COLLATERAL_CLAUSE);
4633 }
4634 } else if (is_one_of (u, IF_SYMBOL, ELIF_SYMBOL, CASE_SYMBOL, OUSE_SYMBOL, WHILE_SYMBOL, UNTIL_SYMBOL, ELSE_BAR_SYMBOL, ACCO_SYMBOL, STOP)) {
4635 reduce_branch (u, ENQUIRY_CLAUSE);
4636 } else if (IS (u, BEGIN_SYMBOL)) {
4637 reduce_branch (u, SOME_CLAUSE);
4638 } else if (is_one_of (u, THEN_SYMBOL, ELSE_SYMBOL, OUT_SYMBOL, DO_SYMBOL, ALT_DO_SYMBOL, STOP)) {
4639 reduce_branch (u, SERIAL_CLAUSE);
4640 } else if (IS (u, IN_SYMBOL)) {
4641 reduce_branch (u, COLLATERAL_CLAUSE);
4642 } else if (IS (u, THEN_BAR_SYMBOL)) {
4643 reduce_branch (u, SOME_CLAUSE);
4644 } else if (IS (u, LOOP_CLAUSE)) {
4645 reduce_branch (u, ENCLOSED_CLAUSE);
4646 } else if (is_one_of (u, FOR_SYMBOL, FROM_SYMBOL, BY_SYMBOL, TO_SYMBOL, DOWNTO_SYMBOL, STOP)) {
4647 reduce_branch (u, UNIT);
4648 }
4649 }
4650 }
4651 reduce_primary_parts (p, expect);
4652 if (expect != ENCLOSED_CLAUSE) {
4653 reduce_primaries (p, expect);
4654 if (expect == FORMAT_TEXT) {
4655 reduce_format_texts (p);
4656 } else {
4657 reduce_secondaries (p);
4658 reduce_formulae (p);
4659 reduce_tertiaries (p);
4660 }
4661 }
4662 for (u = p; u != NO_NODE; FORWARD (u)) {
4663 if (SUB (u) != NO_NODE) {
4664 if (IS (u, CODE_SYMBOL)) {
4665 reduce_branch (u, CODE_CLAUSE);
4666 }
4667 }
4668 }
4669 reduce_right_to_left_constructs (p);
4670 /* Reduce units and declarations */
4671 reduce_basic_declarations (p);
4672 reduce_units (p);
4673 reduce_erroneous_units (p);
4674 if (expect != UNIT) {
4675 if (expect == GENERIC_ARGUMENT) {
4676 reduce_generic_arguments (p);
4677 } else if (expect == BOUNDS) {
4678 reduce_bounds (p);
4679 } else {
4680 reduce_declaration_lists (p);
4681 if (expect != DECLARATION_LIST) {
4682 for (u = p; u != NO_NODE; FORWARD (u)) {
4683 reduce (u, NO_NOTE, NO_TICK, LABELED_UNIT, LABEL, UNIT, STOP);
4684 reduce (u, NO_NOTE, NO_TICK, SPECIFIED_UNIT, SPECIFIER, COLON_SYMBOL, UNIT, STOP);
4685 }
4686 if (expect == SOME_CLAUSE) {
4687 expect = serial_or_collateral (p);
4688 }
4689 if (expect == SERIAL_CLAUSE) {
4690 reduce_serial_clauses (p);
4691 } else if (expect == ENQUIRY_CLAUSE) {
4692 reduce_enquiry_clauses (p);
4693 } else if (expect == COLLATERAL_CLAUSE) {
4694 reduce_collateral_clauses (p);
4695 } else if (expect == ARGUMENT) {
4696 reduce_arguments (p);
4697 }
4698 }
4699 }
4700 }
4701 reduce_enclosed_clauses (p, expect);
4702 }
4703 /* Do something if parsing failed */
4704 if (SUB (p) == NO_NODE || NEXT (p) != NO_NODE) {
4705 recover_from_error (p, expect, (BOOL_T) ((ERROR_COUNT (&program) - error_count_0) > MAX_ERRORS));
4706 no_error = A68_FALSE;
4707 } else {
4708 no_error = A68_TRUE;
4709 }
4710 ATTRIBUTE (q) = ATTRIBUTE (p);
4711 if (no_error) {
4712 SUB (q) = SUB (p);
4713 }
4714 }
4715 }
4716
4717 /**
4718 @brief Driver for reducing declarers.
4719 @param p Node in syntax tree.
4720 @param expect Information the parser may have on what is expected.
4721 **/
4722
4723 static void
reduce_declarers(NODE_T * p,int expect)4724 reduce_declarers (NODE_T * p, int expect)
4725 {
4726 NODE_T *q;
4727 BOOL_T siga;
4728 /* Reduce lengtheties */
4729 for (q = p; q != NO_NODE; FORWARD (q)) {
4730 siga = A68_TRUE;
4731 reduce (q, NO_NOTE, NO_TICK, LONGETY, LONG_SYMBOL, STOP);
4732 reduce (q, NO_NOTE, NO_TICK, SHORTETY, SHORT_SYMBOL, STOP);
4733 while (siga) {
4734 siga = A68_FALSE;
4735 reduce (q, NO_NOTE, &siga, LONGETY, LONGETY, LONG_SYMBOL, STOP);
4736 reduce (q, NO_NOTE, &siga, SHORTETY, SHORTETY, SHORT_SYMBOL, STOP);
4737 }
4738 }
4739 /* Reduce indicants */
4740 for (q = p; q != NO_NODE; FORWARD (q)) {
4741 reduce (q, NO_NOTE, NO_TICK, INDICANT, INT_SYMBOL, STOP);
4742 reduce (q, NO_NOTE, NO_TICK, INDICANT, REAL_SYMBOL, STOP);
4743 reduce (q, NO_NOTE, NO_TICK, INDICANT, BITS_SYMBOL, STOP);
4744 reduce (q, NO_NOTE, NO_TICK, INDICANT, BYTES_SYMBOL, STOP);
4745 reduce (q, NO_NOTE, NO_TICK, INDICANT, COMPLEX_SYMBOL, STOP);
4746 reduce (q, NO_NOTE, NO_TICK, INDICANT, COMPL_SYMBOL, STOP);
4747 reduce (q, NO_NOTE, NO_TICK, INDICANT, BOOL_SYMBOL, STOP);
4748 reduce (q, NO_NOTE, NO_TICK, INDICANT, CHAR_SYMBOL, STOP);
4749 reduce (q, NO_NOTE, NO_TICK, INDICANT, FORMAT_SYMBOL, STOP);
4750 reduce (q, NO_NOTE, NO_TICK, INDICANT, STRING_SYMBOL, STOP);
4751 reduce (q, NO_NOTE, NO_TICK, INDICANT, FILE_SYMBOL, STOP);
4752 reduce (q, NO_NOTE, NO_TICK, INDICANT, CHANNEL_SYMBOL, STOP);
4753 reduce (q, NO_NOTE, NO_TICK, INDICANT, SEMA_SYMBOL, STOP);
4754 reduce (q, NO_NOTE, NO_TICK, INDICANT, PIPE_SYMBOL, STOP);
4755 reduce (q, NO_NOTE, NO_TICK, INDICANT, SOUND_SYMBOL, STOP);
4756 }
4757 /* Reduce standard stuff */
4758 for (q = p; q != NO_NODE; FORWARD (q)) {
4759 if (whether (q, LONGETY, INDICANT, STOP)) {
4760 int a;
4761 if (SUB_NEXT (q) == NO_NODE) {
4762 diagnostic_node (A68_SYNTAX_ERROR, NEXT (q), ERROR_EXPECTED, INFO_APPROPRIATE_DECLARER);
4763 reduce (q, NO_NOTE, NO_TICK, DECLARER, LONGETY, INDICANT, STOP);
4764 } else {
4765 a = ATTRIBUTE (SUB_NEXT (q));
4766 if (a == INT_SYMBOL || a == REAL_SYMBOL || a == BITS_SYMBOL || a == BYTES_SYMBOL || a == COMPLEX_SYMBOL || a == COMPL_SYMBOL) {
4767 reduce (q, NO_NOTE, NO_TICK, DECLARER, LONGETY, INDICANT, STOP);
4768 } else {
4769 diagnostic_node (A68_SYNTAX_ERROR, NEXT (q), ERROR_EXPECTED, INFO_APPROPRIATE_DECLARER);
4770 reduce (q, NO_NOTE, NO_TICK, DECLARER, LONGETY, INDICANT, STOP);
4771 }
4772 }
4773 } else if (whether (q, SHORTETY, INDICANT, STOP)) {
4774 int a;
4775 if (SUB_NEXT (q) == NO_NODE) {
4776 diagnostic_node (A68_SYNTAX_ERROR, NEXT (q), ERROR_EXPECTED, INFO_APPROPRIATE_DECLARER);
4777 reduce (q, NO_NOTE, NO_TICK, DECLARER, SHORTETY, INDICANT, STOP);
4778 } else {
4779 a = ATTRIBUTE (SUB_NEXT (q));
4780 if (a == INT_SYMBOL || a == REAL_SYMBOL || a == BITS_SYMBOL || a == BYTES_SYMBOL || a == COMPLEX_SYMBOL || a == COMPL_SYMBOL) {
4781 reduce (q, NO_NOTE, NO_TICK, DECLARER, SHORTETY, INDICANT, STOP);
4782 } else {
4783 diagnostic_node (A68_SYNTAX_ERROR, NEXT (q), ERROR_EXPECTED, INFO_APPROPRIATE_DECLARER);
4784 reduce (q, NO_NOTE, NO_TICK, DECLARER, LONGETY, INDICANT, STOP);
4785 }
4786 }
4787 }
4788 }
4789 for (q = p; q != NO_NODE; FORWARD (q)) {
4790 reduce (q, NO_NOTE, NO_TICK, DECLARER, INDICANT, STOP);
4791 }
4792 /* Reduce declarer lists */
4793 for (q = p; q != NO_NODE; FORWARD (q)) {
4794 if (NEXT (q) != NO_NODE && SUB_NEXT (q) != NO_NODE) {
4795 if (IS (q, STRUCT_SYMBOL)) {
4796 reduce_branch (NEXT (q), STRUCTURE_PACK);
4797 reduce (q, NO_NOTE, NO_TICK, DECLARER, STRUCT_SYMBOL, STRUCTURE_PACK, STOP);
4798 } else if (IS (q, UNION_SYMBOL)) {
4799 reduce_branch (NEXT (q), UNION_PACK);
4800 reduce (q, NO_NOTE, NO_TICK, DECLARER, UNION_SYMBOL, UNION_PACK, STOP);
4801 } else if (IS (q, PROC_SYMBOL)) {
4802 if (whether (q, PROC_SYMBOL, OPEN_SYMBOL, STOP)) {
4803 if (!is_formal_bounds (SUB_NEXT (q))) {
4804 reduce_branch (NEXT (q), FORMAL_DECLARERS);
4805 }
4806 }
4807 } else if (IS (q, OP_SYMBOL)) {
4808 if (whether (q, OP_SYMBOL, OPEN_SYMBOL, STOP)) {
4809 if (!is_formal_bounds (SUB_NEXT (q))) {
4810 reduce_branch (NEXT (q), FORMAL_DECLARERS);
4811 }
4812 }
4813 }
4814 }
4815 }
4816 /* Reduce row, proc or op declarers */
4817 siga = A68_TRUE;
4818 while (siga) {
4819 siga = A68_FALSE;
4820 for (q = p; q != NO_NODE; FORWARD (q)) {
4821 /* FLEX DECL */
4822 if (whether (q, FLEX_SYMBOL, DECLARER, STOP)) {
4823 reduce (q, NO_NOTE, &siga, DECLARER, FLEX_SYMBOL, DECLARER, STOP);
4824 }
4825 /* FLEX [] DECL */
4826 if (whether (q, FLEX_SYMBOL, SUB_SYMBOL, DECLARER, STOP) && SUB_NEXT (q) != NO_NODE) {
4827 reduce_branch (NEXT (q), BOUNDS);
4828 reduce (q, NO_NOTE, &siga, DECLARER, FLEX_SYMBOL, BOUNDS, DECLARER, STOP);
4829 reduce (q, NO_NOTE, &siga, DECLARER, FLEX_SYMBOL, FORMAL_BOUNDS, DECLARER, STOP);
4830 }
4831 /* FLEX () DECL */
4832 if (whether (q, FLEX_SYMBOL, OPEN_SYMBOL, DECLARER, STOP) && SUB_NEXT (q) != NO_NODE) {
4833 if (!whether (q, FLEX_SYMBOL, OPEN_SYMBOL, DECLARER, COLON_SYMBOL, STOP)) {
4834 reduce_branch (NEXT (q), BOUNDS);
4835 reduce (q, NO_NOTE, &siga, DECLARER, FLEX_SYMBOL, BOUNDS, DECLARER, STOP);
4836 reduce (q, NO_NOTE, &siga, DECLARER, FLEX_SYMBOL, FORMAL_BOUNDS, DECLARER, STOP);
4837 }
4838 }
4839 /* [] DECL */
4840 if (whether (q, SUB_SYMBOL, DECLARER, STOP) && SUB (q) != NO_NODE) {
4841 reduce_branch (q, BOUNDS);
4842 reduce (q, NO_NOTE, &siga, DECLARER, BOUNDS, DECLARER, STOP);
4843 reduce (q, NO_NOTE, &siga, DECLARER, FORMAL_BOUNDS, DECLARER, STOP);
4844 }
4845 /* () DECL */
4846 if (whether (q, OPEN_SYMBOL, DECLARER, STOP) && SUB (q) != NO_NODE) {
4847 if (whether (q, OPEN_SYMBOL, DECLARER, COLON_SYMBOL, STOP)) {
4848 /* Catch e.g. (INT i) () INT: */
4849 if (is_formal_bounds (SUB (q))) {
4850 reduce_branch (q, BOUNDS);
4851 reduce (q, NO_NOTE, &siga, DECLARER, BOUNDS, DECLARER, STOP);
4852 reduce (q, NO_NOTE, &siga, DECLARER, FORMAL_BOUNDS, DECLARER, STOP);
4853 }
4854 } else {
4855 reduce_branch (q, BOUNDS);
4856 reduce (q, NO_NOTE, &siga, DECLARER, BOUNDS, DECLARER, STOP);
4857 reduce (q, NO_NOTE, &siga, DECLARER, FORMAL_BOUNDS, DECLARER, STOP);
4858 }
4859 }
4860 }
4861 /* PROC DECL, PROC () DECL, OP () DECL */
4862 for (q = p; q != NO_NODE; FORWARD (q)) {
4863 int a = ATTRIBUTE (q);
4864 if (a == REF_SYMBOL) {
4865 reduce (q, NO_NOTE, &siga, DECLARER, REF_SYMBOL, DECLARER, STOP);
4866 } else if (a == PROC_SYMBOL) {
4867 reduce (q, NO_NOTE, &siga, DECLARER, PROC_SYMBOL, DECLARER, STOP);
4868 reduce (q, NO_NOTE, &siga, DECLARER, PROC_SYMBOL, FORMAL_DECLARERS, DECLARER, STOP);
4869 reduce (q, NO_NOTE, &siga, DECLARER, PROC_SYMBOL, VOID_SYMBOL, STOP);
4870 reduce (q, NO_NOTE, &siga, DECLARER, PROC_SYMBOL, FORMAL_DECLARERS, VOID_SYMBOL, STOP);
4871 } else if (a == OP_SYMBOL) {
4872 reduce (q, NO_NOTE, &siga, OPERATOR_PLAN, OP_SYMBOL, FORMAL_DECLARERS, DECLARER, STOP);
4873 reduce (q, NO_NOTE, &siga, OPERATOR_PLAN, OP_SYMBOL, FORMAL_DECLARERS, VOID_SYMBOL, STOP);
4874 }
4875 }
4876 }
4877 /* Reduce packs etcetera */
4878 if (expect == STRUCTURE_PACK) {
4879 for (q = p; q != NO_NODE; FORWARD (q)) {
4880 siga = A68_TRUE;
4881 while (siga) {
4882 siga = A68_FALSE;
4883 reduce (q, NO_NOTE, &siga, STRUCTURED_FIELD, DECLARER, IDENTIFIER, STOP);
4884 reduce (q, NO_NOTE, &siga, STRUCTURED_FIELD, STRUCTURED_FIELD, COMMA_SYMBOL, IDENTIFIER, STOP);
4885 }
4886 }
4887 for (q = p; q != NO_NODE; FORWARD (q)) {
4888 siga = A68_TRUE;
4889 while (siga) {
4890 siga = A68_FALSE;
4891 reduce (q, NO_NOTE, &siga, STRUCTURED_FIELD_LIST, STRUCTURED_FIELD, STOP);
4892 reduce (q, NO_NOTE, &siga, STRUCTURED_FIELD_LIST, STRUCTURED_FIELD_LIST, COMMA_SYMBOL, STRUCTURED_FIELD, STOP);
4893 reduce (q, strange_separator, &siga, STRUCTURED_FIELD_LIST, STRUCTURED_FIELD_LIST, STRUCTURED_FIELD, STOP);
4894 reduce (q, strange_separator, &siga, STRUCTURED_FIELD_LIST, STRUCTURED_FIELD_LIST, SEMI_SYMBOL, STRUCTURED_FIELD, STOP);
4895 }
4896 }
4897 q = p;
4898 reduce (q, NO_NOTE, NO_TICK, STRUCTURE_PACK, OPEN_SYMBOL, STRUCTURED_FIELD_LIST, CLOSE_SYMBOL, STOP);
4899 } else if (expect == PARAMETER_PACK) {
4900 for (q = p; q != NO_NODE; FORWARD (q)) {
4901 siga = A68_TRUE;
4902 while (siga) {
4903 siga = A68_FALSE;
4904 reduce (q, NO_NOTE, &siga, PARAMETER, DECLARER, IDENTIFIER, STOP);
4905 reduce (q, NO_NOTE, &siga, PARAMETER, PARAMETER, COMMA_SYMBOL, IDENTIFIER, STOP);
4906 }
4907 }
4908 for (q = p; q != NO_NODE; FORWARD (q)) {
4909 siga = A68_TRUE;
4910 while (siga) {
4911 siga = A68_FALSE;
4912 reduce (q, NO_NOTE, &siga, PARAMETER_LIST, PARAMETER, STOP);
4913 reduce (q, NO_NOTE, &siga, PARAMETER_LIST, PARAMETER_LIST, COMMA_SYMBOL, PARAMETER, STOP);
4914 }
4915 }
4916 q = p;
4917 reduce (q, NO_NOTE, NO_TICK, PARAMETER_PACK, OPEN_SYMBOL, PARAMETER_LIST, CLOSE_SYMBOL, STOP);
4918 } else if (expect == FORMAL_DECLARERS) {
4919 for (q = p; q != NO_NODE; FORWARD (q)) {
4920 siga = A68_TRUE;
4921 while (siga) {
4922 siga = A68_FALSE;
4923 reduce (q, NO_NOTE, &siga, FORMAL_DECLARERS_LIST, DECLARER, STOP);
4924 reduce (q, NO_NOTE, &siga, FORMAL_DECLARERS_LIST, FORMAL_DECLARERS_LIST, COMMA_SYMBOL, DECLARER, STOP);
4925 reduce (q, strange_separator, &siga, FORMAL_DECLARERS_LIST, FORMAL_DECLARERS_LIST, SEMI_SYMBOL, DECLARER, STOP);
4926 reduce (q, strange_separator, &siga, FORMAL_DECLARERS_LIST, FORMAL_DECLARERS_LIST, DECLARER, STOP);
4927 }
4928 }
4929 q = p;
4930 reduce (q, NO_NOTE, NO_TICK, FORMAL_DECLARERS, OPEN_SYMBOL, FORMAL_DECLARERS_LIST, CLOSE_SYMBOL, STOP);
4931 } else if (expect == UNION_PACK) {
4932 for (q = p; q != NO_NODE; FORWARD (q)) {
4933 siga = A68_TRUE;
4934 while (siga) {
4935 siga = A68_FALSE;
4936 reduce (q, NO_NOTE, &siga, UNION_DECLARER_LIST, DECLARER, STOP);
4937 reduce (q, NO_NOTE, &siga, UNION_DECLARER_LIST, VOID_SYMBOL, STOP);
4938 reduce (q, NO_NOTE, &siga, UNION_DECLARER_LIST, UNION_DECLARER_LIST, COMMA_SYMBOL, DECLARER, STOP);
4939 reduce (q, NO_NOTE, &siga, UNION_DECLARER_LIST, UNION_DECLARER_LIST, COMMA_SYMBOL, VOID_SYMBOL, STOP);
4940 reduce (q, strange_separator, &siga, UNION_DECLARER_LIST, UNION_DECLARER_LIST, SEMI_SYMBOL, DECLARER, STOP);
4941 reduce (q, strange_separator, &siga, UNION_DECLARER_LIST, UNION_DECLARER_LIST, SEMI_SYMBOL, VOID_SYMBOL, STOP);
4942 reduce (q, strange_separator, &siga, UNION_DECLARER_LIST, UNION_DECLARER_LIST, DECLARER, STOP);
4943 reduce (q, strange_separator, &siga, UNION_DECLARER_LIST, UNION_DECLARER_LIST, VOID_SYMBOL, STOP);
4944 }
4945 }
4946 q = p;
4947 reduce (q, NO_NOTE, NO_TICK, UNION_PACK, OPEN_SYMBOL, UNION_DECLARER_LIST, CLOSE_SYMBOL, STOP);
4948 } else if (expect == SPECIFIER) {
4949 reduce (p, NO_NOTE, NO_TICK, SPECIFIER, OPEN_SYMBOL, DECLARER, IDENTIFIER, CLOSE_SYMBOL, STOP);
4950 reduce (p, NO_NOTE, NO_TICK, SPECIFIER, OPEN_SYMBOL, DECLARER, CLOSE_SYMBOL, STOP);
4951 reduce (p, NO_NOTE, NO_TICK, SPECIFIER, OPEN_SYMBOL, VOID_SYMBOL, CLOSE_SYMBOL, STOP);
4952 } else {
4953 for (q = p; q != NO_NODE; FORWARD (q)) {
4954 if (whether (q, OPEN_SYMBOL, COLON_SYMBOL, STOP) && !(expect == GENERIC_ARGUMENT || expect == BOUNDS)) {
4955 if (is_one_of (p, IN_SYMBOL, THEN_BAR_SYMBOL, STOP)) {
4956 reduce_branch (q, SPECIFIER);
4957 }
4958 }
4959 if (whether (q, OPEN_SYMBOL, DECLARER, COLON_SYMBOL, STOP)) {
4960 reduce_branch (q, PARAMETER_PACK);
4961 }
4962 if (whether (q, OPEN_SYMBOL, VOID_SYMBOL, COLON_SYMBOL, STOP)) {
4963 reduce_branch (q, PARAMETER_PACK);
4964 }
4965 }
4966 }
4967 }
4968
4969 /**
4970 @brief Handle cases that need reducing from right-to-left.
4971 @param p Node in syntax tree.
4972 **/
4973
4974 static void
reduce_right_to_left_constructs(NODE_T * p)4975 reduce_right_to_left_constructs (NODE_T * p)
4976 {
4977 /*
4978 Here are cases that need reducing from right-to-left whereas many things
4979 can be reduced left-to-right. Assignations are a notable example; one could
4980 discuss whether it would not be more natural to write 1 =: k in stead of
4981 k := 1. The latter is said to be more natural, or it could be just computing
4982 history. Meanwhile we use this routine.
4983 */
4984 if (p != NO_NODE) {
4985 reduce_right_to_left_constructs (NEXT (p));
4986 /* Assignations */
4987 if (IS (p, TERTIARY)) {
4988 reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, TERTIARY, STOP);
4989 reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, IDENTITY_RELATION, STOP);
4990 reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, AND_FUNCTION, STOP);
4991 reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, OR_FUNCTION, STOP);
4992 reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, ROUTINE_TEXT, STOP);
4993 reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, JUMP, STOP);
4994 reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, SKIP, STOP);
4995 reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, ASSIGNATION, STOP);
4996 reduce (p, NO_NOTE, NO_TICK, ASSIGNATION, TERTIARY, ASSIGN_SYMBOL, CODE_CLAUSE, STOP);
4997 }
4998 /* Routine texts with parameter pack */
4999 else if (IS (p, PARAMETER_PACK)) {
5000 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, ASSIGNATION, STOP);
5001 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, IDENTITY_RELATION, STOP);
5002 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, AND_FUNCTION, STOP);
5003 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, OR_FUNCTION, STOP);
5004 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, JUMP, STOP);
5005 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, SKIP, STOP);
5006 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, TERTIARY, STOP);
5007 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, ROUTINE_TEXT, STOP);
5008 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, DECLARER, COLON_SYMBOL, CODE_CLAUSE, STOP);
5009 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, ASSIGNATION, STOP);
5010 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, IDENTITY_RELATION, STOP);
5011 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, AND_FUNCTION, STOP);
5012 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, OR_FUNCTION, STOP);
5013 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, JUMP, STOP);
5014 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, SKIP, STOP);
5015 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, TERTIARY, STOP);
5016 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, ROUTINE_TEXT, STOP);
5017 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, PARAMETER_PACK, VOID_SYMBOL, COLON_SYMBOL, CODE_CLAUSE, STOP);
5018 }
5019 /* Routine texts without parameter pack */
5020 else if (IS (p, DECLARER)) {
5021 if (!(PREVIOUS (p) != NO_NODE && IS (PREVIOUS (p), PARAMETER_PACK))) {
5022 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, ASSIGNATION, STOP);
5023 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, IDENTITY_RELATION, STOP);
5024 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, AND_FUNCTION, STOP);
5025 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, OR_FUNCTION, STOP);
5026 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, JUMP, STOP);
5027 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, SKIP, STOP);
5028 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, TERTIARY, STOP);
5029 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, ROUTINE_TEXT, STOP);
5030 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, DECLARER, COLON_SYMBOL, CODE_CLAUSE, STOP);
5031 }
5032 } else if (IS (p, VOID_SYMBOL)) {
5033 if (!(PREVIOUS (p) != NO_NODE && IS (PREVIOUS (p), PARAMETER_PACK))) {
5034 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, ASSIGNATION, STOP);
5035 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, IDENTITY_RELATION, STOP);
5036 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, AND_FUNCTION, STOP);
5037 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, OR_FUNCTION, STOP);
5038 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, JUMP, STOP);
5039 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, SKIP, STOP);
5040 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, TERTIARY, STOP);
5041 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, ROUTINE_TEXT, STOP);
5042 reduce (p, NO_NOTE, NO_TICK, ROUTINE_TEXT, VOID_SYMBOL, COLON_SYMBOL, CODE_CLAUSE, STOP);
5043 }
5044 }
5045 }
5046 }
5047
5048 /**
5049 @brief Reduce primary elements.
5050 @param p Node in syntax tree.
5051 @param expect Information the parser may have on what is expected.
5052 **/
5053
5054 static void
reduce_primary_parts(NODE_T * p,int expect)5055 reduce_primary_parts (NODE_T * p, int expect)
5056 {
5057 NODE_T *q = p;
5058 for (; q != NO_NODE; FORWARD (q)) {
5059 if (whether (q, IDENTIFIER, OF_SYMBOL, STOP)) {
5060 ATTRIBUTE (q) = FIELD_IDENTIFIER;
5061 }
5062 reduce (q, NO_NOTE, NO_TICK, ENVIRON_NAME, ENVIRON_SYMBOL, ROW_CHAR_DENOTATION, STOP);
5063 reduce (q, NO_NOTE, NO_TICK, NIHIL, NIL_SYMBOL, STOP);
5064 reduce (q, NO_NOTE, NO_TICK, SKIP, SKIP_SYMBOL, STOP);
5065 reduce (q, NO_NOTE, NO_TICK, SELECTOR, FIELD_IDENTIFIER, OF_SYMBOL, STOP);
5066 /* JUMPs without GOTO are resolved later */
5067 reduce (q, NO_NOTE, NO_TICK, JUMP, GOTO_SYMBOL, IDENTIFIER, STOP);
5068 reduce (q, NO_NOTE, NO_TICK, DENOTATION, LONGETY, INT_DENOTATION, STOP);
5069 reduce (q, NO_NOTE, NO_TICK, DENOTATION, LONGETY, REAL_DENOTATION, STOP);
5070 reduce (q, NO_NOTE, NO_TICK, DENOTATION, LONGETY, BITS_DENOTATION, STOP);
5071 reduce (q, NO_NOTE, NO_TICK, DENOTATION, SHORTETY, INT_DENOTATION, STOP);
5072 reduce (q, NO_NOTE, NO_TICK, DENOTATION, SHORTETY, REAL_DENOTATION, STOP);
5073 reduce (q, NO_NOTE, NO_TICK, DENOTATION, SHORTETY, BITS_DENOTATION, STOP);
5074 reduce (q, NO_NOTE, NO_TICK, DENOTATION, INT_DENOTATION, STOP);
5075 reduce (q, NO_NOTE, NO_TICK, DENOTATION, REAL_DENOTATION, STOP);
5076 reduce (q, NO_NOTE, NO_TICK, DENOTATION, BITS_DENOTATION, STOP);
5077 reduce (q, NO_NOTE, NO_TICK, DENOTATION, ROW_CHAR_DENOTATION, STOP);
5078 reduce (q, NO_NOTE, NO_TICK, DENOTATION, TRUE_SYMBOL, STOP);
5079 reduce (q, NO_NOTE, NO_TICK, DENOTATION, FALSE_SYMBOL, STOP);
5080 reduce (q, NO_NOTE, NO_TICK, DENOTATION, EMPTY_SYMBOL, STOP);
5081 if (expect == SERIAL_CLAUSE || expect == ENQUIRY_CLAUSE || expect == SOME_CLAUSE) {
5082 BOOL_T siga = A68_TRUE;
5083 while (siga) {
5084 siga = A68_FALSE;
5085 reduce (q, NO_NOTE, &siga, LABEL, DEFINING_IDENTIFIER, COLON_SYMBOL, STOP);
5086 reduce (q, NO_NOTE, &siga, LABEL, LABEL, DEFINING_IDENTIFIER, COLON_SYMBOL, STOP);
5087 }
5088 }
5089 }
5090 for (q = p; q != NO_NODE; FORWARD (q)) {
5091 #if defined HAVE_PARALLEL_CLAUSE
5092 reduce (q, NO_NOTE, NO_TICK, PARALLEL_CLAUSE, PAR_SYMBOL, COLLATERAL_CLAUSE, STOP);
5093 #else
5094 reduce (q, par_clause, NO_TICK, PARALLEL_CLAUSE, PAR_SYMBOL, COLLATERAL_CLAUSE, STOP);
5095 #endif
5096 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, PARALLEL_CLAUSE, STOP);
5097 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CLOSED_CLAUSE, STOP);
5098 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, COLLATERAL_CLAUSE, STOP);
5099 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CONDITIONAL_CLAUSE, STOP);
5100 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CASE_CLAUSE, STOP);
5101 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CONFORMITY_CLAUSE, STOP);
5102 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, LOOP_CLAUSE, STOP);
5103 }
5104 }
5105
5106 /**
5107 @brief Reduce primaries completely.
5108 @param p Node in syntax tree.
5109 @param expect Information the parser may have on what is expected.
5110 **/
5111
5112 static void
reduce_primaries(NODE_T * p,int expect)5113 reduce_primaries (NODE_T * p, int expect)
5114 {
5115 NODE_T *q = p;
5116 while (q != NO_NODE) {
5117 BOOL_T fwd = A68_TRUE, siga;
5118 /* Primaries excepts call and slice */
5119 reduce (q, NO_NOTE, NO_TICK, PRIMARY, IDENTIFIER, STOP);
5120 reduce (q, NO_NOTE, NO_TICK, PRIMARY, DENOTATION, STOP);
5121 reduce (q, NO_NOTE, NO_TICK, CAST, DECLARER, ENCLOSED_CLAUSE, STOP);
5122 reduce (q, NO_NOTE, NO_TICK, CAST, VOID_SYMBOL, ENCLOSED_CLAUSE, STOP);
5123 reduce (q, NO_NOTE, NO_TICK, ASSERTION, ASSERT_SYMBOL, ENCLOSED_CLAUSE, STOP);
5124 reduce (q, NO_NOTE, NO_TICK, PRIMARY, CAST, STOP);
5125 reduce (q, NO_NOTE, NO_TICK, PRIMARY, ENCLOSED_CLAUSE, STOP);
5126 reduce (q, NO_NOTE, NO_TICK, PRIMARY, FORMAT_TEXT, STOP);
5127 /* Call and slice */
5128 siga = A68_TRUE;
5129 while (siga) {
5130 NODE_T *x = NEXT (q);
5131 siga = A68_FALSE;
5132 if (IS (q, PRIMARY) && x != NO_NODE) {
5133 if (IS (x, OPEN_SYMBOL)) {
5134 reduce_branch (NEXT (q), GENERIC_ARGUMENT);
5135 reduce (q, NO_NOTE, &siga, SPECIFICATION, PRIMARY, GENERIC_ARGUMENT, STOP);
5136 reduce (q, NO_NOTE, &siga, PRIMARY, SPECIFICATION, STOP);
5137 } else if (IS (x, SUB_SYMBOL)) {
5138 reduce_branch (NEXT (q), GENERIC_ARGUMENT);
5139 reduce (q, NO_NOTE, &siga, SPECIFICATION, PRIMARY, GENERIC_ARGUMENT, STOP);
5140 reduce (q, NO_NOTE, &siga, PRIMARY, SPECIFICATION, STOP);
5141 }
5142 }
5143 }
5144 /* Now that call and slice are known, reduce remaining ( .. ) */
5145 if (IS (q, OPEN_SYMBOL) && SUB (q) != NO_NODE) {
5146 reduce_branch (q, SOME_CLAUSE);
5147 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CLOSED_CLAUSE, STOP);
5148 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, COLLATERAL_CLAUSE, STOP);
5149 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CONDITIONAL_CLAUSE, STOP);
5150 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CASE_CLAUSE, STOP);
5151 reduce (q, NO_NOTE, NO_TICK, ENCLOSED_CLAUSE, CONFORMITY_CLAUSE, STOP);
5152 if (PREVIOUS (q) != NO_NODE) {
5153 BACKWARD (q);
5154 fwd = A68_FALSE;
5155 }
5156 }
5157 /* Format text items */
5158 if (expect == FORMAT_TEXT) {
5159 NODE_T *r;
5160 for (r = p; r != NO_NODE; FORWARD (r)) {
5161 reduce (r, NO_NOTE, NO_TICK, DYNAMIC_REPLICATOR, FORMAT_ITEM_N, ENCLOSED_CLAUSE, STOP);
5162 reduce (r, NO_NOTE, NO_TICK, GENERAL_PATTERN, FORMAT_ITEM_G, ENCLOSED_CLAUSE, STOP);
5163 reduce (r, NO_NOTE, NO_TICK, GENERAL_PATTERN, FORMAT_ITEM_H, ENCLOSED_CLAUSE, STOP);
5164 reduce (r, NO_NOTE, NO_TICK, FORMAT_PATTERN, FORMAT_ITEM_F, ENCLOSED_CLAUSE, STOP);
5165 }
5166 }
5167 if (fwd) {
5168 FORWARD (q);
5169 }
5170 }
5171 }
5172
5173 /**
5174 @brief Enforce that ambiguous patterns are separated by commas.
5175 @param p Node in syntax tree.
5176 **/
5177
5178 static void
ambiguous_patterns(NODE_T * p)5179 ambiguous_patterns (NODE_T * p)
5180 {
5181 /*
5182 Example: printf (($+d.2d +d.2d$, 1, 2)) can produce either "+1.00 +2.00" or
5183 "+1+002.00". A comma must be supplied to resolve the ambiguity.
5184
5185 The obvious thing would be to weave this into the syntax, letting the BU parser
5186 sort it out. But the C-style patterns do not suffer from Algol 68 pattern
5187 ambiguity, so by solving it this way we maximise freedom in writing the patterns
5188 as we want without introducing two "kinds" of patterns, and so we have shorter
5189 routines for implementing formatted transput. This is a pragmatic system.
5190 */
5191 NODE_T *q, *last_pat = NO_NODE;
5192 for (q = p; q != NO_NODE; FORWARD (q)) {
5193 switch (ATTRIBUTE (q)) {
5194 case INTEGRAL_PATTERN: /* These are the potentially ambiguous patterns */
5195 case REAL_PATTERN:
5196 case COMPLEX_PATTERN:
5197 case BITS_PATTERN:
5198 {
5199 if (last_pat != NO_NODE) {
5200 diagnostic_node (A68_SYNTAX_ERROR, q, ERROR_COMMA_MUST_SEPARATE, ATTRIBUTE (last_pat), ATTRIBUTE (q));
5201 }
5202 last_pat = q;
5203 break;
5204 }
5205 case COMMA_SYMBOL:
5206 {
5207 last_pat = NO_NODE;
5208 break;
5209 }
5210 }
5211 }
5212 }
5213
5214 /**
5215 @brief Reduce format texts completely.
5216 @param p Node in syntax tree.
5217 @param pr Production rule.
5218 @param let Letter.
5219 **/
5220
5221 void
reduce_c_pattern(NODE_T * p,int pr,int let)5222 reduce_c_pattern (NODE_T * p, int pr, int let)
5223 {
5224 NODE_T *q;
5225 for (q = p; q != NO_NODE; FORWARD (q)) {
5226 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, let, STOP);
5227 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
5228 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, REPLICATOR, let, STOP);
5229 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, REPLICATOR, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
5230 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_PLUS, let, STOP);
5231 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_PLUS, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
5232 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_PLUS, REPLICATOR, let, STOP);
5233 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_PLUS, REPLICATOR, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
5234 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, let, STOP);
5235 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
5236 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, REPLICATOR, let, STOP);
5237 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, REPLICATOR, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
5238 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, FORMAT_ITEM_PLUS, let, STOP);
5239 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, FORMAT_ITEM_PLUS, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
5240 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, FORMAT_ITEM_PLUS, REPLICATOR, let, STOP);
5241 reduce (q, NO_NOTE, NO_TICK, pr, FORMAT_ITEM_ESCAPE, FORMAT_ITEM_MINUS, FORMAT_ITEM_PLUS, REPLICATOR, FORMAT_ITEM_POINT, REPLICATOR, let, STOP);
5242 }
5243 }
5244
5245 /**
5246 @brief Reduce format texts completely.
5247 @param p Node in syntax tree.
5248 **/
5249
5250 static void
reduce_format_texts(NODE_T * p)5251 reduce_format_texts (NODE_T * p)
5252 {
5253 NODE_T *q;
5254 /* Replicators */
5255 for (q = p; q != NO_NODE; FORWARD (q)) {
5256 reduce (q, NO_NOTE, NO_TICK, REPLICATOR, STATIC_REPLICATOR, STOP);
5257 reduce (q, NO_NOTE, NO_TICK, REPLICATOR, DYNAMIC_REPLICATOR, STOP);
5258 }
5259 /* "OTHER" patterns */
5260 reduce_c_pattern (p, BITS_C_PATTERN, FORMAT_ITEM_B);
5261 reduce_c_pattern (p, BITS_C_PATTERN, FORMAT_ITEM_O);
5262 reduce_c_pattern (p, BITS_C_PATTERN, FORMAT_ITEM_X);
5263 reduce_c_pattern (p, CHAR_C_PATTERN, FORMAT_ITEM_C);
5264 reduce_c_pattern (p, FIXED_C_PATTERN, FORMAT_ITEM_F);
5265 reduce_c_pattern (p, FLOAT_C_PATTERN, FORMAT_ITEM_E);
5266 reduce_c_pattern (p, GENERAL_C_PATTERN, FORMAT_ITEM_G);
5267 reduce_c_pattern (p, INTEGRAL_C_PATTERN, FORMAT_ITEM_D);
5268 reduce_c_pattern (p, INTEGRAL_C_PATTERN, FORMAT_ITEM_I);
5269 reduce_c_pattern (p, STRING_C_PATTERN, FORMAT_ITEM_S);
5270 /* Radix frames */
5271 for (q = p; q != NO_NODE; FORWARD (q)) {
5272 reduce (q, NO_NOTE, NO_TICK, RADIX_FRAME, REPLICATOR, FORMAT_ITEM_R, STOP);
5273 }
5274 /* Insertions */
5275 for (q = p; q != NO_NODE; FORWARD (q)) {
5276 reduce (q, NO_NOTE, NO_TICK, INSERTION, FORMAT_ITEM_X, STOP);
5277 reduce (q, NO_NOTE, NO_TICK, INSERTION, FORMAT_ITEM_Y, STOP);
5278 reduce (q, NO_NOTE, NO_TICK, INSERTION, FORMAT_ITEM_L, STOP);
5279 reduce (q, NO_NOTE, NO_TICK, INSERTION, FORMAT_ITEM_P, STOP);
5280 reduce (q, NO_NOTE, NO_TICK, INSERTION, FORMAT_ITEM_Q, STOP);
5281 reduce (q, NO_NOTE, NO_TICK, INSERTION, FORMAT_ITEM_K, STOP);
5282 reduce (q, NO_NOTE, NO_TICK, INSERTION, LITERAL, STOP);
5283 }
5284 for (q = p; q != NO_NODE; FORWARD (q)) {
5285 reduce (q, NO_NOTE, NO_TICK, INSERTION, REPLICATOR, INSERTION, STOP);
5286 }
5287 for (q = p; q != NO_NODE; FORWARD (q)) {
5288 BOOL_T siga = A68_TRUE;
5289 while (siga) {
5290 siga = A68_FALSE;
5291 reduce (q, NO_NOTE, &siga, INSERTION, INSERTION, INSERTION, STOP);
5292 }
5293 }
5294 /* Replicated suppressible frames */
5295 for (q = p; q != NO_NODE; FORWARD (q)) {
5296 reduce (q, NO_NOTE, NO_TICK, FORMAT_A_FRAME, REPLICATOR, FORMAT_ITEM_S, FORMAT_ITEM_A, STOP);
5297 reduce (q, NO_NOTE, NO_TICK, FORMAT_Z_FRAME, REPLICATOR, FORMAT_ITEM_S, FORMAT_ITEM_Z, STOP);
5298 reduce (q, NO_NOTE, NO_TICK, FORMAT_D_FRAME, REPLICATOR, FORMAT_ITEM_S, FORMAT_ITEM_D, STOP);
5299 }
5300 /* Suppressible frames */
5301 for (q = p; q != NO_NODE; FORWARD (q)) {
5302 reduce (q, NO_NOTE, NO_TICK, FORMAT_A_FRAME, FORMAT_ITEM_S, FORMAT_ITEM_A, STOP);
5303 reduce (q, NO_NOTE, NO_TICK, FORMAT_Z_FRAME, FORMAT_ITEM_S, FORMAT_ITEM_Z, STOP);
5304 reduce (q, NO_NOTE, NO_TICK, FORMAT_D_FRAME, FORMAT_ITEM_S, FORMAT_ITEM_D, STOP);
5305 reduce (q, NO_NOTE, NO_TICK, FORMAT_E_FRAME, FORMAT_ITEM_S, FORMAT_ITEM_E, STOP);
5306 reduce (q, NO_NOTE, NO_TICK, FORMAT_POINT_FRAME, FORMAT_ITEM_S, FORMAT_ITEM_POINT, STOP);
5307 reduce (q, NO_NOTE, NO_TICK, FORMAT_I_FRAME, FORMAT_ITEM_S, FORMAT_ITEM_I, STOP);
5308 }
5309 /* Replicated frames */
5310 for (q = p; q != NO_NODE; FORWARD (q)) {
5311 reduce (q, NO_NOTE, NO_TICK, FORMAT_A_FRAME, REPLICATOR, FORMAT_ITEM_A, STOP);
5312 reduce (q, NO_NOTE, NO_TICK, FORMAT_Z_FRAME, REPLICATOR, FORMAT_ITEM_Z, STOP);
5313 reduce (q, NO_NOTE, NO_TICK, FORMAT_D_FRAME, REPLICATOR, FORMAT_ITEM_D, STOP);
5314 }
5315 /* Frames */
5316 for (q = p; q != NO_NODE; FORWARD (q)) {
5317 reduce (q, NO_NOTE, NO_TICK, FORMAT_A_FRAME, FORMAT_ITEM_A, STOP);
5318 reduce (q, NO_NOTE, NO_TICK, FORMAT_Z_FRAME, FORMAT_ITEM_Z, STOP);
5319 reduce (q, NO_NOTE, NO_TICK, FORMAT_D_FRAME, FORMAT_ITEM_D, STOP);
5320 reduce (q, NO_NOTE, NO_TICK, FORMAT_E_FRAME, FORMAT_ITEM_E, STOP);
5321 reduce (q, NO_NOTE, NO_TICK, FORMAT_POINT_FRAME, FORMAT_ITEM_POINT, STOP);
5322 reduce (q, NO_NOTE, NO_TICK, FORMAT_I_FRAME, FORMAT_ITEM_I, STOP);
5323 }
5324 /* Frames with an insertion */
5325 for (q = p; q != NO_NODE; FORWARD (q)) {
5326 reduce (q, NO_NOTE, NO_TICK, FORMAT_A_FRAME, INSERTION, FORMAT_A_FRAME, STOP);
5327 reduce (q, NO_NOTE, NO_TICK, FORMAT_Z_FRAME, INSERTION, FORMAT_Z_FRAME, STOP);
5328 reduce (q, NO_NOTE, NO_TICK, FORMAT_D_FRAME, INSERTION, FORMAT_D_FRAME, STOP);
5329 reduce (q, NO_NOTE, NO_TICK, FORMAT_E_FRAME, INSERTION, FORMAT_E_FRAME, STOP);
5330 reduce (q, NO_NOTE, NO_TICK, FORMAT_POINT_FRAME, INSERTION, FORMAT_POINT_FRAME, STOP);
5331 reduce (q, NO_NOTE, NO_TICK, FORMAT_I_FRAME, INSERTION, FORMAT_I_FRAME, STOP);
5332 }
5333 /* String patterns */
5334 for (q = p; q != NO_NODE; FORWARD (q)) {
5335 reduce (q, NO_NOTE, NO_TICK, STRING_PATTERN, REPLICATOR, FORMAT_A_FRAME, STOP);
5336 }
5337 for (q = p; q != NO_NODE; FORWARD (q)) {
5338 reduce (q, NO_NOTE, NO_TICK, STRING_PATTERN, FORMAT_A_FRAME, STOP);
5339 }
5340 for (q = p; q != NO_NODE; FORWARD (q)) {
5341 BOOL_T siga = A68_TRUE;
5342 while (siga) {
5343 siga = A68_FALSE;
5344 reduce (q, NO_NOTE, &siga, STRING_PATTERN, STRING_PATTERN, STRING_PATTERN, STOP);
5345 reduce (q, NO_NOTE, &siga, STRING_PATTERN, STRING_PATTERN, INSERTION, STRING_PATTERN, STOP);
5346 }
5347 }
5348 /* Integral moulds */
5349 for (q = p; q != NO_NODE; FORWARD (q)) {
5350 reduce (q, NO_NOTE, NO_TICK, INTEGRAL_MOULD, FORMAT_Z_FRAME, STOP);
5351 reduce (q, NO_NOTE, NO_TICK, INTEGRAL_MOULD, FORMAT_D_FRAME, STOP);
5352 }
5353 for (q = p; q != NO_NODE; FORWARD (q)) {
5354 BOOL_T siga = A68_TRUE;
5355 while (siga) {
5356 siga = A68_FALSE;
5357 reduce (q, NO_NOTE, &siga, INTEGRAL_MOULD, INTEGRAL_MOULD, INTEGRAL_MOULD, STOP);
5358 reduce (q, NO_NOTE, &siga, INTEGRAL_MOULD, INTEGRAL_MOULD, INSERTION, STOP);
5359 }
5360 }
5361 /* Sign moulds */
5362 for (q = p; q != NO_NODE; FORWARD (q)) {
5363 reduce (q, NO_NOTE, NO_TICK, SIGN_MOULD, INTEGRAL_MOULD, FORMAT_ITEM_PLUS, STOP);
5364 reduce (q, NO_NOTE, NO_TICK, SIGN_MOULD, INTEGRAL_MOULD, FORMAT_ITEM_MINUS, STOP);
5365 }
5366 for (q = p; q != NO_NODE; FORWARD (q)) {
5367 reduce (q, NO_NOTE, NO_TICK, SIGN_MOULD, FORMAT_ITEM_PLUS, STOP);
5368 reduce (q, NO_NOTE, NO_TICK, SIGN_MOULD, FORMAT_ITEM_MINUS, STOP);
5369 }
5370 /* Exponent frames */
5371 for (q = p; q != NO_NODE; FORWARD (q)) {
5372 reduce (q, NO_NOTE, NO_TICK, EXPONENT_FRAME, FORMAT_E_FRAME, SIGN_MOULD, INTEGRAL_MOULD, STOP);
5373 reduce (q, NO_NOTE, NO_TICK, EXPONENT_FRAME, FORMAT_E_FRAME, INTEGRAL_MOULD, STOP);
5374 }
5375 /* Real patterns */
5376 for (q = p; q != NO_NODE; FORWARD (q)) {
5377 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, INTEGRAL_MOULD, FORMAT_POINT_FRAME, INTEGRAL_MOULD, EXPONENT_FRAME, STOP);
5378 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, INTEGRAL_MOULD, FORMAT_POINT_FRAME, INTEGRAL_MOULD, STOP);
5379 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, INTEGRAL_MOULD, FORMAT_POINT_FRAME, EXPONENT_FRAME, STOP);
5380 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, INTEGRAL_MOULD, FORMAT_POINT_FRAME, STOP);
5381 }
5382 for (q = p; q != NO_NODE; FORWARD (q)) {
5383 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, FORMAT_POINT_FRAME, INTEGRAL_MOULD, EXPONENT_FRAME, STOP);
5384 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, FORMAT_POINT_FRAME, INTEGRAL_MOULD, STOP);
5385 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, FORMAT_POINT_FRAME, EXPONENT_FRAME, STOP);
5386 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, FORMAT_POINT_FRAME, STOP);
5387 }
5388 for (q = p; q != NO_NODE; FORWARD (q)) {
5389 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, INTEGRAL_MOULD, FORMAT_POINT_FRAME, INTEGRAL_MOULD, EXPONENT_FRAME, STOP);
5390 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, INTEGRAL_MOULD, FORMAT_POINT_FRAME, INTEGRAL_MOULD, STOP);
5391 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, INTEGRAL_MOULD, FORMAT_POINT_FRAME, EXPONENT_FRAME, STOP);
5392 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, INTEGRAL_MOULD, FORMAT_POINT_FRAME, STOP);
5393 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, FORMAT_POINT_FRAME, INTEGRAL_MOULD, EXPONENT_FRAME, STOP);
5394 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, FORMAT_POINT_FRAME, INTEGRAL_MOULD, STOP);
5395 }
5396 for (q = p; q != NO_NODE; FORWARD (q)) {
5397 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, SIGN_MOULD, INTEGRAL_MOULD, EXPONENT_FRAME, STOP);
5398 reduce (q, NO_NOTE, NO_TICK, REAL_PATTERN, INTEGRAL_MOULD, EXPONENT_FRAME, STOP);
5399 }
5400 /* Complex patterns */
5401 for (q = p; q != NO_NODE; FORWARD (q)) {
5402 reduce (q, NO_NOTE, NO_TICK, COMPLEX_PATTERN, REAL_PATTERN, FORMAT_I_FRAME, REAL_PATTERN, STOP);
5403 }
5404 /* Bits patterns */
5405 for (q = p; q != NO_NODE; FORWARD (q)) {
5406 reduce (q, NO_NOTE, NO_TICK, BITS_PATTERN, RADIX_FRAME, INTEGRAL_MOULD, STOP);
5407 }
5408 /* Integral patterns */
5409 for (q = p; q != NO_NODE; FORWARD (q)) {
5410 reduce (q, NO_NOTE, NO_TICK, INTEGRAL_PATTERN, SIGN_MOULD, INTEGRAL_MOULD, STOP);
5411 reduce (q, NO_NOTE, NO_TICK, INTEGRAL_PATTERN, INTEGRAL_MOULD, STOP);
5412 }
5413 /* Patterns */
5414 for (q = p; q != NO_NODE; FORWARD (q)) {
5415 reduce (q, NO_NOTE, NO_TICK, BOOLEAN_PATTERN, FORMAT_ITEM_B, COLLECTION, STOP);
5416 reduce (q, NO_NOTE, NO_TICK, CHOICE_PATTERN, FORMAT_ITEM_C, COLLECTION, STOP);
5417 }
5418 for (q = p; q != NO_NODE; FORWARD (q)) {
5419 reduce (q, NO_NOTE, NO_TICK, BOOLEAN_PATTERN, FORMAT_ITEM_B, STOP);
5420 reduce (q, NO_NOTE, NO_TICK, GENERAL_PATTERN, FORMAT_ITEM_G, STOP);
5421 reduce (q, NO_NOTE, NO_TICK, GENERAL_PATTERN, FORMAT_ITEM_H, STOP);
5422 }
5423 ambiguous_patterns (p);
5424 for (q = p; q != NO_NODE; FORWARD (q)) {
5425 reduce (q, a68_extension, NO_TICK, A68_PATTERN, BITS_C_PATTERN, STOP);
5426 reduce (q, a68_extension, NO_TICK, A68_PATTERN, CHAR_C_PATTERN, STOP);
5427 reduce (q, a68_extension, NO_TICK, A68_PATTERN, FIXED_C_PATTERN, STOP);
5428 reduce (q, a68_extension, NO_TICK, A68_PATTERN, FLOAT_C_PATTERN, STOP);
5429 reduce (q, a68_extension, NO_TICK, A68_PATTERN, GENERAL_C_PATTERN, STOP);
5430 reduce (q, a68_extension, NO_TICK, A68_PATTERN, INTEGRAL_C_PATTERN, STOP);
5431 reduce (q, a68_extension, NO_TICK, A68_PATTERN, STRING_C_PATTERN, STOP);
5432 reduce (q, NO_NOTE, NO_TICK, A68_PATTERN, BITS_PATTERN, STOP);
5433 reduce (q, NO_NOTE, NO_TICK, A68_PATTERN, BOOLEAN_PATTERN, STOP);
5434 reduce (q, NO_NOTE, NO_TICK, A68_PATTERN, CHOICE_PATTERN, STOP);
5435 reduce (q, NO_NOTE, NO_TICK, A68_PATTERN, COMPLEX_PATTERN, STOP);
5436 reduce (q, NO_NOTE, NO_TICK, A68_PATTERN, FORMAT_PATTERN, STOP);
5437 reduce (q, NO_NOTE, NO_TICK, A68_PATTERN, GENERAL_PATTERN, STOP);
5438 reduce (q, NO_NOTE, NO_TICK, A68_PATTERN, INTEGRAL_PATTERN, STOP);
5439 reduce (q, NO_NOTE, NO_TICK, A68_PATTERN, REAL_PATTERN, STOP);
5440 reduce (q, NO_NOTE, NO_TICK, A68_PATTERN, STRING_PATTERN, STOP);
5441 }
5442 /* Pictures */
5443 for (q = p; q != NO_NODE; FORWARD (q)) {
5444 reduce (q, NO_NOTE, NO_TICK, PICTURE, INSERTION, STOP);
5445 reduce (q, NO_NOTE, NO_TICK, PICTURE, A68_PATTERN, STOP);
5446 reduce (q, NO_NOTE, NO_TICK, PICTURE, COLLECTION, STOP);
5447 reduce (q, NO_NOTE, NO_TICK, PICTURE, REPLICATOR, COLLECTION, STOP);
5448 }
5449 /* Picture lists */
5450 for (q = p; q != NO_NODE; FORWARD (q)) {
5451 if (IS (q, PICTURE)) {
5452 BOOL_T siga = A68_TRUE;
5453 reduce (q, NO_NOTE, NO_TICK, PICTURE_LIST, PICTURE, STOP);
5454 while (siga) {
5455 siga = A68_FALSE;
5456 reduce (q, NO_NOTE, &siga, PICTURE_LIST, PICTURE_LIST, COMMA_SYMBOL, PICTURE, STOP);
5457 /* We filtered ambiguous patterns, so commas may be omitted */
5458 reduce (q, NO_NOTE, &siga, PICTURE_LIST, PICTURE_LIST, PICTURE, STOP);
5459 }
5460 }
5461 }
5462 }
5463
5464 /**
5465 @brief Reduce secondaries completely.
5466 @param p Node in syntax tree.
5467 **/
5468
5469 static void
reduce_secondaries(NODE_T * p)5470 reduce_secondaries (NODE_T * p)
5471 {
5472 NODE_T *q;
5473 BOOL_T siga;
5474 for (q = p; q != NO_NODE; FORWARD (q)) {
5475 reduce (q, NO_NOTE, NO_TICK, SECONDARY, PRIMARY, STOP);
5476 reduce (q, NO_NOTE, NO_TICK, GENERATOR, LOC_SYMBOL, DECLARER, STOP);
5477 reduce (q, NO_NOTE, NO_TICK, GENERATOR, HEAP_SYMBOL, DECLARER, STOP);
5478 reduce (q, NO_NOTE, NO_TICK, GENERATOR, NEW_SYMBOL, DECLARER, STOP);
5479 reduce (q, NO_NOTE, NO_TICK, SECONDARY, GENERATOR, STOP);
5480 }
5481 siga = A68_TRUE;
5482 while (siga) {
5483 siga = A68_FALSE;
5484 for (q = p; NEXT (q) != NO_NODE; FORWARD (q)) {
5485 ;
5486 }
5487 for (; q != NO_NODE; BACKWARD (q)) {
5488 reduce (q, NO_NOTE, &siga, SELECTION, SELECTOR, SECONDARY, STOP);
5489 reduce (q, NO_NOTE, &siga, SECONDARY, SELECTION, STOP);
5490 }
5491 }
5492 }
5493
5494 /**
5495 @brief Whether "q" is an operator with priority "k".
5496 @param q Operator token.
5497 @param k Priority.
5498 @return Whether "q" is an operator with priority "k".
5499 **/
5500
5501 static int
operator_with_priority(NODE_T * q,int k)5502 operator_with_priority (NODE_T * q, int k)
5503 {
5504 return (NEXT (q) != NO_NODE && ATTRIBUTE (NEXT (q)) == OPERATOR && PRIO (INFO (NEXT (q))) == k);
5505 }
5506
5507 /**
5508 @brief Reduce formulae.
5509 @param p Node in syntax tree.
5510 **/
5511
5512 static void
reduce_formulae(NODE_T * p)5513 reduce_formulae (NODE_T * p)
5514 {
5515 NODE_T *q = p;
5516 int priority;
5517 while (q != NO_NODE) {
5518 if (is_one_of (q, OPERATOR, SECONDARY, STOP)) {
5519 q = reduce_dyadic (q, STOP);
5520 } else {
5521 FORWARD (q);
5522 }
5523 }
5524 /* Reduce the expression */
5525 for (priority = MAX_PRIORITY; priority >= 0; priority--) {
5526 for (q = p; q != NO_NODE; FORWARD (q)) {
5527 if (operator_with_priority (q, priority)) {
5528 BOOL_T siga = A68_FALSE;
5529 NODE_T *op = NEXT (q);
5530 if (IS (q, SECONDARY)) {
5531 reduce (q, NO_NOTE, &siga, FORMULA, SECONDARY, OPERATOR, SECONDARY, STOP);
5532 reduce (q, NO_NOTE, &siga, FORMULA, SECONDARY, OPERATOR, MONADIC_FORMULA, STOP);
5533 reduce (q, NO_NOTE, &siga, FORMULA, SECONDARY, OPERATOR, FORMULA, STOP);
5534 } else if (IS (q, MONADIC_FORMULA)) {
5535 reduce (q, NO_NOTE, &siga, FORMULA, MONADIC_FORMULA, OPERATOR, SECONDARY, STOP);
5536 reduce (q, NO_NOTE, &siga, FORMULA, MONADIC_FORMULA, OPERATOR, MONADIC_FORMULA, STOP);
5537 reduce (q, NO_NOTE, &siga, FORMULA, MONADIC_FORMULA, OPERATOR, FORMULA, STOP);
5538 }
5539 if (priority == 0 && siga) {
5540 diagnostic_node (A68_SYNTAX_ERROR, op, ERROR_NO_PRIORITY);
5541 }
5542 siga = A68_TRUE;
5543 while (siga) {
5544 NODE_T *op2 = NEXT (q);
5545 siga = A68_FALSE;
5546 if (operator_with_priority (q, priority)) {
5547 reduce (q, NO_NOTE, &siga, FORMULA, FORMULA, OPERATOR, SECONDARY, STOP);
5548 }
5549 if (operator_with_priority (q, priority)) {
5550 reduce (q, NO_NOTE, &siga, FORMULA, FORMULA, OPERATOR, MONADIC_FORMULA, STOP);
5551 }
5552 if (operator_with_priority (q, priority)) {
5553 reduce (q, NO_NOTE, &siga, FORMULA, FORMULA, OPERATOR, FORMULA, STOP);
5554 }
5555 if (priority == 0 && siga) {
5556 diagnostic_node (A68_SYNTAX_ERROR, op2, ERROR_NO_PRIORITY);
5557 }
5558 }
5559 }
5560 }
5561 }
5562 }
5563
5564 /**
5565 @brief Reduce dyadic expressions.
5566 @param p Node in syntax tree.
5567 @param u Current priority.
5568 @return Token from where to continue.
5569 **/
5570
5571 static NODE_T *
reduce_dyadic(NODE_T * p,int u)5572 reduce_dyadic (NODE_T * p, int u)
5573 {
5574 /* We work inside out - higher priority expressions get reduced first */
5575 if (u > MAX_PRIORITY) {
5576 if (p == NO_NODE) {
5577 return (NO_NODE);
5578 } else if (IS (p, OPERATOR)) {
5579 /* Reduce monadic formulas */
5580 NODE_T *q = p;
5581 BOOL_T siga;
5582 do {
5583 PRIO (INFO (q)) = 10;
5584 siga = (BOOL_T) ((NEXT (q) != NO_NODE) && (IS (NEXT (q), OPERATOR)));
5585 if (siga) {
5586 FORWARD (q);
5587 }
5588 } while (siga);
5589 reduce (q, NO_NOTE, NO_TICK, MONADIC_FORMULA, OPERATOR, SECONDARY, STOP);
5590 while (q != p) {
5591 BACKWARD (q);
5592 reduce (q, NO_NOTE, NO_TICK, MONADIC_FORMULA, OPERATOR, MONADIC_FORMULA, STOP);
5593 }
5594 }
5595 FORWARD (p);
5596 } else {
5597 p = reduce_dyadic (p, u + 1);
5598 while (p != NO_NODE && IS (p, OPERATOR) && PRIO (INFO (p)) == u) {
5599 FORWARD (p);
5600 p = reduce_dyadic (p, u + 1);
5601 }
5602 }
5603 return (p);
5604 }
5605
5606 /**
5607 @brief Reduce tertiaries completely.
5608 @param p Node in syntax tree.
5609 **/
5610
5611 static void
reduce_tertiaries(NODE_T * p)5612 reduce_tertiaries (NODE_T * p)
5613 {
5614 NODE_T *q;
5615 BOOL_T siga;
5616 for (q = p; q != NO_NODE; FORWARD (q)) {
5617 reduce (q, NO_NOTE, NO_TICK, TERTIARY, NIHIL, STOP);
5618 reduce (q, NO_NOTE, NO_TICK, FORMULA, MONADIC_FORMULA, STOP);
5619 reduce (q, NO_NOTE, NO_TICK, TERTIARY, FORMULA, STOP);
5620 reduce (q, NO_NOTE, NO_TICK, TERTIARY, SECONDARY, STOP);
5621 }
5622 siga = A68_TRUE;
5623 while (siga) {
5624 siga = A68_FALSE;
5625 for (q = p; q != NO_NODE; FORWARD (q)) {
5626 reduce (q, NO_NOTE, &siga, TRANSPOSE_FUNCTION, TRANSPOSE_SYMBOL, TERTIARY, STOP);
5627 reduce (q, NO_NOTE, &siga, DIAGONAL_FUNCTION, TERTIARY, DIAGONAL_SYMBOL, TERTIARY, STOP);
5628 reduce (q, NO_NOTE, &siga, DIAGONAL_FUNCTION, DIAGONAL_SYMBOL, TERTIARY, STOP);
5629 reduce (q, NO_NOTE, &siga, COLUMN_FUNCTION, TERTIARY, COLUMN_SYMBOL, TERTIARY, STOP);
5630 reduce (q, NO_NOTE, &siga, COLUMN_FUNCTION, COLUMN_SYMBOL, TERTIARY, STOP);
5631 reduce (q, NO_NOTE, &siga, ROW_FUNCTION, TERTIARY, ROW_SYMBOL, TERTIARY, STOP);
5632 reduce (q, NO_NOTE, &siga, ROW_FUNCTION, ROW_SYMBOL, TERTIARY, STOP);
5633 }
5634 for (q = p; q != NO_NODE; FORWARD (q)) {
5635 reduce (q, a68_extension, &siga, TERTIARY, TRANSPOSE_FUNCTION, STOP);
5636 reduce (q, a68_extension, &siga, TERTIARY, DIAGONAL_FUNCTION, STOP);
5637 reduce (q, a68_extension, &siga, TERTIARY, COLUMN_FUNCTION, STOP);
5638 reduce (q, a68_extension, &siga, TERTIARY, ROW_FUNCTION, STOP);
5639 }
5640 }
5641 for (q = p; q != NO_NODE; FORWARD (q)) {
5642 reduce (q, NO_NOTE, NO_TICK, IDENTITY_RELATION, TERTIARY, IS_SYMBOL, TERTIARY, STOP);
5643 reduce (q, NO_NOTE, NO_TICK, IDENTITY_RELATION, TERTIARY, ISNT_SYMBOL, TERTIARY, STOP);
5644 }
5645 for (q = p; q != NO_NODE; FORWARD (q)) {
5646 reduce (q, NO_NOTE, NO_TICK, AND_FUNCTION, TERTIARY, ANDF_SYMBOL, TERTIARY, STOP);
5647 reduce (q, NO_NOTE, NO_TICK, OR_FUNCTION, TERTIARY, ORF_SYMBOL, TERTIARY, STOP);
5648 }
5649 }
5650
5651 /**
5652 @brief Reduce units.
5653 @param p Node in syntax tree.
5654 **/
5655
5656 static void
reduce_units(NODE_T * p)5657 reduce_units (NODE_T * p)
5658 {
5659 NODE_T *q;
5660 /* Stray ~ is a SKIP */
5661 for (q = p; q != NO_NODE; FORWARD (q)) {
5662 if (IS (q, OPERATOR) && IS_LITERALLY (q, "~")) {
5663 ATTRIBUTE (q) = SKIP;
5664 }
5665 }
5666 /* Reduce units */
5667 for (q = p; q != NO_NODE; FORWARD (q)) {
5668 reduce (q, NO_NOTE, NO_TICK, UNIT, ASSIGNATION, STOP);
5669 reduce (q, NO_NOTE, NO_TICK, UNIT, IDENTITY_RELATION, STOP);
5670 reduce (q, a68_extension, NO_TICK, UNIT, AND_FUNCTION, STOP);
5671 reduce (q, a68_extension, NO_TICK, UNIT, OR_FUNCTION, STOP);
5672 reduce (q, NO_NOTE, NO_TICK, UNIT, ROUTINE_TEXT, STOP);
5673 reduce (q, NO_NOTE, NO_TICK, UNIT, JUMP, STOP);
5674 reduce (q, NO_NOTE, NO_TICK, UNIT, SKIP, STOP);
5675 reduce (q, NO_NOTE, NO_TICK, UNIT, TERTIARY, STOP);
5676 reduce (q, NO_NOTE, NO_TICK, UNIT, ASSERTION, STOP);
5677 reduce (q, NO_NOTE, NO_TICK, UNIT, CODE_CLAUSE, STOP);
5678 }
5679 }
5680
5681 /**
5682 @brief Reduce_generic arguments.
5683 @param p Node in syntax tree.
5684 **/
5685
5686 static void
reduce_generic_arguments(NODE_T * p)5687 reduce_generic_arguments (NODE_T * p)
5688 {
5689 NODE_T *q;
5690 BOOL_T siga;
5691 for (q = p; q != NO_NODE; FORWARD (q)) {
5692 if (IS (q, UNIT)) {
5693 reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, COLON_SYMBOL, UNIT, AT_SYMBOL, UNIT, STOP);
5694 reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, COLON_SYMBOL, UNIT, STOP);
5695 reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, COLON_SYMBOL, AT_SYMBOL, UNIT, STOP);
5696 reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, COLON_SYMBOL, STOP);
5697 reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, DOTDOT_SYMBOL, UNIT, AT_SYMBOL, UNIT, STOP);
5698 reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, DOTDOT_SYMBOL, UNIT, STOP);
5699 reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, DOTDOT_SYMBOL, AT_SYMBOL, UNIT, STOP);
5700 reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, DOTDOT_SYMBOL, STOP);
5701 } else if (IS (q, COLON_SYMBOL)) {
5702 reduce (q, NO_NOTE, NO_TICK, TRIMMER, COLON_SYMBOL, UNIT, AT_SYMBOL, UNIT, STOP);
5703 reduce (q, NO_NOTE, NO_TICK, TRIMMER, COLON_SYMBOL, UNIT, STOP);
5704 reduce (q, NO_NOTE, NO_TICK, TRIMMER, COLON_SYMBOL, AT_SYMBOL, UNIT, STOP);
5705 reduce (q, NO_NOTE, NO_TICK, TRIMMER, COLON_SYMBOL, STOP);
5706 } else if (IS (q, DOTDOT_SYMBOL)) {
5707 reduce (q, NO_NOTE, NO_TICK, TRIMMER, DOTDOT_SYMBOL, UNIT, AT_SYMBOL, UNIT, STOP);
5708 reduce (q, NO_NOTE, NO_TICK, TRIMMER, DOTDOT_SYMBOL, UNIT, STOP);
5709 reduce (q, NO_NOTE, NO_TICK, TRIMMER, DOTDOT_SYMBOL, AT_SYMBOL, UNIT, STOP);
5710 reduce (q, NO_NOTE, NO_TICK, TRIMMER, DOTDOT_SYMBOL, STOP);
5711 }
5712 }
5713 for (q = p; q != NO_NODE; FORWARD (q)) {
5714 reduce (q, NO_NOTE, NO_TICK, TRIMMER, UNIT, AT_SYMBOL, UNIT, STOP);
5715 }
5716 for (q = p; q != NO_NODE; FORWARD (q)) {
5717 reduce (q, NO_NOTE, NO_TICK, TRIMMER, AT_SYMBOL, UNIT, STOP);
5718 }
5719 for (q = p; q && NEXT (q); FORWARD (q)) {
5720 if (IS (q, COMMA_SYMBOL)) {
5721 if (!(ATTRIBUTE (NEXT (q)) == UNIT || ATTRIBUTE (NEXT (q)) == TRIMMER)) {
5722 pad_node (q, TRIMMER);
5723 }
5724 } else {
5725 if (IS (NEXT (q), COMMA_SYMBOL)) {
5726 if (ISNT (q, UNIT) && ISNT (q, TRIMMER)) {
5727 pad_node (q, TRIMMER);
5728 }
5729 }
5730 }
5731 }
5732 q = NEXT (p);
5733 ABEND (q == NO_NODE, "erroneous parser state", NO_TEXT);
5734 reduce (q, NO_NOTE, NO_TICK, GENERIC_ARGUMENT_LIST, UNIT, STOP);
5735 reduce (q, NO_NOTE, NO_TICK, GENERIC_ARGUMENT_LIST, TRIMMER, STOP);
5736 do {
5737 siga = A68_FALSE;
5738 reduce (q, NO_NOTE, &siga, GENERIC_ARGUMENT_LIST, GENERIC_ARGUMENT_LIST, COMMA_SYMBOL, UNIT, STOP);
5739 reduce (q, NO_NOTE, &siga, GENERIC_ARGUMENT_LIST, GENERIC_ARGUMENT_LIST, COMMA_SYMBOL, TRIMMER, STOP);
5740 reduce (q, strange_separator, &siga, GENERIC_ARGUMENT_LIST, GENERIC_ARGUMENT_LIST, UNIT, STOP);
5741 reduce (q, strange_separator, &siga, GENERIC_ARGUMENT_LIST, GENERIC_ARGUMENT_LIST, TRIMMER, STOP);
5742 } while (siga);
5743 }
5744
5745 /**
5746 @brief Reduce bounds.
5747 @param p Node in syntax tree.
5748 **/
5749
5750 static void
reduce_bounds(NODE_T * p)5751 reduce_bounds (NODE_T * p)
5752 {
5753 NODE_T *q;
5754 BOOL_T siga;
5755 for (q = p; q != NO_NODE; FORWARD (q)) {
5756 reduce (q, NO_NOTE, NO_TICK, BOUND, UNIT, COLON_SYMBOL, UNIT, STOP);
5757 reduce (q, NO_NOTE, NO_TICK, BOUND, UNIT, DOTDOT_SYMBOL, UNIT, STOP);
5758 reduce (q, NO_NOTE, NO_TICK, BOUND, UNIT, STOP);
5759 }
5760 q = NEXT (p);
5761 reduce (q, NO_NOTE, NO_TICK, BOUNDS_LIST, BOUND, STOP);
5762 reduce (q, NO_NOTE, NO_TICK, FORMAL_BOUNDS_LIST, COMMA_SYMBOL, STOP);
5763 reduce (q, NO_NOTE, NO_TICK, ALT_FORMAL_BOUNDS_LIST, COLON_SYMBOL, STOP);
5764 reduce (q, NO_NOTE, NO_TICK, ALT_FORMAL_BOUNDS_LIST, DOTDOT_SYMBOL, STOP);
5765 do {
5766 siga = A68_FALSE;
5767 reduce (q, NO_NOTE, &siga, BOUNDS_LIST, BOUNDS_LIST, COMMA_SYMBOL, BOUND, STOP);
5768 reduce (q, NO_NOTE, &siga, FORMAL_BOUNDS_LIST, FORMAL_BOUNDS_LIST, COMMA_SYMBOL, STOP);
5769 reduce (q, NO_NOTE, &siga, ALT_FORMAL_BOUNDS_LIST, FORMAL_BOUNDS_LIST, COLON_SYMBOL, STOP);
5770 reduce (q, NO_NOTE, &siga, ALT_FORMAL_BOUNDS_LIST, FORMAL_BOUNDS_LIST, DOTDOT_SYMBOL, STOP);
5771 reduce (q, NO_NOTE, &siga, FORMAL_BOUNDS_LIST, ALT_FORMAL_BOUNDS_LIST, COMMA_SYMBOL, STOP);
5772 reduce (q, strange_separator, &siga, BOUNDS_LIST, BOUNDS_LIST, BOUND, STOP);
5773 } while (siga);
5774 }
5775
5776 /**
5777 @brief Reduce argument packs.
5778 @param p Node in syntax tree.
5779 **/
5780
5781 static void
reduce_arguments(NODE_T * p)5782 reduce_arguments (NODE_T * p)
5783 {
5784 if (NEXT (p) != NO_NODE) {
5785 NODE_T *q = NEXT (p);
5786 BOOL_T siga;
5787 reduce (q, NO_NOTE, NO_TICK, ARGUMENT_LIST, UNIT, STOP);
5788 do {
5789 siga = A68_FALSE;
5790 reduce (q, NO_NOTE, &siga, ARGUMENT_LIST, ARGUMENT_LIST, COMMA_SYMBOL, UNIT, STOP);
5791 reduce (q, strange_separator, &siga, ARGUMENT_LIST, ARGUMENT_LIST, UNIT, STOP);
5792 } while (siga);
5793 }
5794 }
5795
5796 /**
5797 @brief Reduce declarations.
5798 @param p Node in syntax tree.
5799 **/
5800
5801 static void
reduce_basic_declarations(NODE_T * p)5802 reduce_basic_declarations (NODE_T * p)
5803 {
5804 NODE_T *q;
5805 for (q = p; q != NO_NODE; FORWARD (q)) {
5806 reduce (q, NO_NOTE, NO_TICK, ENVIRON_NAME, ENVIRON_SYMBOL, ROW_CHAR_DENOTATION, STOP);
5807 reduce (q, NO_NOTE, NO_TICK, PRIORITY_DECLARATION, PRIO_SYMBOL, DEFINING_OPERATOR, EQUALS_SYMBOL, PRIORITY, STOP);
5808 reduce (q, NO_NOTE, NO_TICK, MODE_DECLARATION, MODE_SYMBOL, DEFINING_INDICANT, EQUALS_SYMBOL, DECLARER, STOP);
5809 reduce (q, NO_NOTE, NO_TICK, MODE_DECLARATION, MODE_SYMBOL, DEFINING_INDICANT, EQUALS_SYMBOL, VOID_SYMBOL, STOP);
5810 reduce (q, NO_NOTE, NO_TICK, PROCEDURE_DECLARATION, PROC_SYMBOL, DEFINING_IDENTIFIER, EQUALS_SYMBOL, ROUTINE_TEXT, STOP);
5811 reduce (q, NO_NOTE, NO_TICK, PROCEDURE_VARIABLE_DECLARATION, PROC_SYMBOL, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, ROUTINE_TEXT, STOP);
5812 reduce (q, NO_NOTE, NO_TICK, PROCEDURE_VARIABLE_DECLARATION, QUALIFIER, PROC_SYMBOL, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, ROUTINE_TEXT, STOP);
5813 reduce (q, NO_NOTE, NO_TICK, BRIEF_OPERATOR_DECLARATION, OP_SYMBOL, DEFINING_OPERATOR, EQUALS_SYMBOL, ROUTINE_TEXT, STOP);
5814 /* Errors */
5815 reduce (q, strange_tokens, NO_TICK, PRIORITY_DECLARATION, PRIO_SYMBOL, -DEFINING_OPERATOR, -EQUALS_SYMBOL, -PRIORITY, STOP);
5816 reduce (q, strange_tokens, NO_TICK, MODE_DECLARATION, MODE_SYMBOL, DEFINING_INDICANT, EQUALS_SYMBOL, -DECLARER, STOP);
5817 reduce (q, strange_tokens, NO_TICK, PROCEDURE_DECLARATION, PROC_SYMBOL, DEFINING_IDENTIFIER, EQUALS_SYMBOL, -ROUTINE_TEXT, STOP);
5818 reduce (q, strange_tokens, NO_TICK, PROCEDURE_VARIABLE_DECLARATION, PROC_SYMBOL, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, -ROUTINE_TEXT, STOP);
5819 reduce (q, strange_tokens, NO_TICK, PROCEDURE_VARIABLE_DECLARATION, QUALIFIER, PROC_SYMBOL, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, -ROUTINE_TEXT, STOP);
5820 reduce (q, strange_tokens, NO_TICK, BRIEF_OPERATOR_DECLARATION, OP_SYMBOL, DEFINING_OPERATOR, EQUALS_SYMBOL, -ROUTINE_TEXT, STOP);
5821 /* Errors. WILDCARD catches TERTIARY which catches IDENTIFIER */
5822 reduce (q, strange_tokens, NO_TICK, PROCEDURE_DECLARATION, PROC_SYMBOL, WILDCARD, ROUTINE_TEXT, STOP);
5823 }
5824 for (q = p; q != NO_NODE; FORWARD (q)) {
5825 BOOL_T siga;
5826 do {
5827 siga = A68_FALSE;
5828 reduce (q, NO_NOTE, &siga, ENVIRON_NAME, ENVIRON_NAME, COMMA_SYMBOL, ROW_CHAR_DENOTATION, STOP);
5829 reduce (q, NO_NOTE, &siga, PRIORITY_DECLARATION, PRIORITY_DECLARATION, COMMA_SYMBOL, DEFINING_OPERATOR, EQUALS_SYMBOL, PRIORITY, STOP);
5830 reduce (q, NO_NOTE, &siga, MODE_DECLARATION, MODE_DECLARATION, COMMA_SYMBOL, DEFINING_INDICANT, EQUALS_SYMBOL, DECLARER, STOP);
5831 reduce (q, NO_NOTE, &siga, MODE_DECLARATION, MODE_DECLARATION, COMMA_SYMBOL, DEFINING_INDICANT, EQUALS_SYMBOL, VOID_SYMBOL, STOP);
5832 reduce (q, NO_NOTE, &siga, PROCEDURE_DECLARATION, PROCEDURE_DECLARATION, COMMA_SYMBOL, DEFINING_IDENTIFIER, EQUALS_SYMBOL, ROUTINE_TEXT, STOP);
5833 reduce (q, NO_NOTE, &siga, PROCEDURE_VARIABLE_DECLARATION, PROCEDURE_VARIABLE_DECLARATION, COMMA_SYMBOL, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, ROUTINE_TEXT, STOP);
5834 reduce (q, NO_NOTE, &siga, BRIEF_OPERATOR_DECLARATION, BRIEF_OPERATOR_DECLARATION, COMMA_SYMBOL, DEFINING_OPERATOR, EQUALS_SYMBOL, ROUTINE_TEXT, STOP);
5835 /* Errors. WILDCARD catches TERTIARY which catches IDENTIFIER */
5836 reduce (q, strange_tokens, &siga, PROCEDURE_DECLARATION, PROCEDURE_DECLARATION, COMMA_SYMBOL, WILDCARD, ROUTINE_TEXT, STOP);
5837 } while (siga);
5838 }
5839 }
5840
5841 /**
5842 @brief Reduce declaration lists.
5843 @param p Node in syntax tree.
5844 **/
5845
5846 static void
reduce_declaration_lists(NODE_T * p)5847 reduce_declaration_lists (NODE_T * p)
5848 {
5849 NODE_T *q;
5850 for (q = p; q != NO_NODE; FORWARD (q)) {
5851 reduce (q, NO_NOTE, NO_TICK, IDENTITY_DECLARATION, DECLARER, DEFINING_IDENTIFIER, EQUALS_SYMBOL, UNIT, STOP);
5852 reduce (q, NO_NOTE, NO_TICK, VARIABLE_DECLARATION, QUALIFIER, DECLARER, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, UNIT, STOP);
5853 reduce (q, NO_NOTE, NO_TICK, VARIABLE_DECLARATION, QUALIFIER, DECLARER, DEFINING_IDENTIFIER, STOP);
5854 reduce (q, NO_NOTE, NO_TICK, VARIABLE_DECLARATION, DECLARER, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, UNIT, STOP);
5855 reduce (q, NO_NOTE, NO_TICK, VARIABLE_DECLARATION, DECLARER, DEFINING_IDENTIFIER, STOP);
5856 }
5857 for (q = p; q != NO_NODE; FORWARD (q)) {
5858 BOOL_T siga;
5859 do {
5860 siga = A68_FALSE;
5861 reduce (q, NO_NOTE, &siga, IDENTITY_DECLARATION, IDENTITY_DECLARATION, COMMA_SYMBOL, DEFINING_IDENTIFIER, EQUALS_SYMBOL, UNIT, STOP);
5862 reduce (q, NO_NOTE, &siga, VARIABLE_DECLARATION, VARIABLE_DECLARATION, COMMA_SYMBOL, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, UNIT, STOP);
5863 if (!whether (q, VARIABLE_DECLARATION, COMMA_SYMBOL, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, UNIT, STOP)) {
5864 reduce (q, NO_NOTE, &siga, VARIABLE_DECLARATION, VARIABLE_DECLARATION, COMMA_SYMBOL, DEFINING_IDENTIFIER, STOP);
5865 }
5866 } while (siga);
5867 }
5868 for (q = p; q != NO_NODE; FORWARD (q)) {
5869 reduce (q, NO_NOTE, NO_TICK, OPERATOR_DECLARATION, OPERATOR_PLAN, DEFINING_OPERATOR, EQUALS_SYMBOL, UNIT, STOP);
5870 }
5871 for (q = p; q != NO_NODE; FORWARD (q)) {
5872 BOOL_T siga;
5873 do {
5874 siga = A68_FALSE;
5875 reduce (q, NO_NOTE, &siga, OPERATOR_DECLARATION, OPERATOR_DECLARATION, COMMA_SYMBOL, DEFINING_OPERATOR, EQUALS_SYMBOL, UNIT, STOP);
5876 } while (siga);
5877 }
5878 for (q = p; q != NO_NODE; FORWARD (q)) {
5879 reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, MODE_DECLARATION, STOP);
5880 reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, PRIORITY_DECLARATION, STOP);
5881 reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, BRIEF_OPERATOR_DECLARATION, STOP);
5882 reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, OPERATOR_DECLARATION, STOP);
5883 reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, IDENTITY_DECLARATION, STOP);
5884 reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, PROCEDURE_DECLARATION, STOP);
5885 reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, PROCEDURE_VARIABLE_DECLARATION, STOP);
5886 reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, VARIABLE_DECLARATION, STOP);
5887 reduce (q, NO_NOTE, NO_TICK, DECLARATION_LIST, ENVIRON_NAME, STOP);
5888 }
5889 for (q = p; q != NO_NODE; FORWARD (q)) {
5890 BOOL_T siga;
5891 do {
5892 siga = A68_FALSE;
5893 reduce (q, NO_NOTE, &siga, DECLARATION_LIST, DECLARATION_LIST, COMMA_SYMBOL, DECLARATION_LIST, STOP);
5894 } while (siga);
5895 }
5896 }
5897
5898 /**
5899 @brief Reduce serial clauses.
5900 @param p Node in syntax tree.
5901 **/
5902
5903 static void
reduce_serial_clauses(NODE_T * p)5904 reduce_serial_clauses (NODE_T * p)
5905 {
5906 if (NEXT (p) != NO_NODE) {
5907 NODE_T *q = NEXT (p), *u;
5908 BOOL_T siga, label_seen;
5909 /* Check wrong exits */
5910 for (u = q; u != NO_NODE; FORWARD (u)) {
5911 if (IS (u, EXIT_SYMBOL)) {
5912 if (NEXT (u) == NO_NODE || ISNT (NEXT (u), LABELED_UNIT)) {
5913 diagnostic_node (A68_SYNTAX_ERROR, u, ERROR_LABELED_UNIT_MUST_FOLLOW);
5914 }
5915 }
5916 }
5917 /* Check wrong jumps and declarations */
5918 for (u = q, label_seen = A68_FALSE; u != NO_NODE; FORWARD (u)) {
5919 if (IS (u, LABELED_UNIT)) {
5920 label_seen = A68_TRUE;
5921 } else if (IS (u, DECLARATION_LIST)) {
5922 if (label_seen) {
5923 diagnostic_node (A68_SYNTAX_ERROR, u, ERROR_LABEL_BEFORE_DECLARATION);
5924 }
5925 }
5926 }
5927 /* Reduce serial clauses */
5928 reduce (q, NO_NOTE, NO_TICK, SERIAL_CLAUSE, LABELED_UNIT, STOP);
5929 reduce (q, NO_NOTE, NO_TICK, SERIAL_CLAUSE, UNIT, STOP);
5930 reduce (q, NO_NOTE, NO_TICK, INITIALISER_SERIES, DECLARATION_LIST, STOP);
5931 do {
5932 siga = A68_FALSE;
5933 if (IS (q, SERIAL_CLAUSE)) {
5934 reduce (q, NO_NOTE, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, SEMI_SYMBOL, UNIT, STOP);
5935 reduce (q, NO_NOTE, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, EXIT_SYMBOL, LABELED_UNIT, STOP);
5936 reduce (q, NO_NOTE, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, SEMI_SYMBOL, LABELED_UNIT, STOP);
5937 reduce (q, NO_NOTE, &siga, INITIALISER_SERIES, SERIAL_CLAUSE, SEMI_SYMBOL, DECLARATION_LIST, STOP);
5938 /* Errors */
5939 reduce (q, strange_separator, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, COMMA_SYMBOL, UNIT, STOP);
5940 reduce (q, strange_separator, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, COMMA_SYMBOL, LABELED_UNIT, STOP);
5941 reduce (q, strange_separator, &siga, INITIALISER_SERIES, SERIAL_CLAUSE, COMMA_SYMBOL, DECLARATION_LIST, STOP);
5942 reduce (q, strange_separator, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, COLON_SYMBOL, UNIT, STOP);
5943 reduce (q, strange_separator, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, COLON_SYMBOL, LABELED_UNIT, STOP);
5944 reduce (q, strange_separator, &siga, INITIALISER_SERIES, SERIAL_CLAUSE, COLON_SYMBOL, DECLARATION_LIST, STOP);
5945 reduce (q, strange_separator, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, UNIT, STOP);
5946 reduce (q, strange_separator, &siga, SERIAL_CLAUSE, SERIAL_CLAUSE, LABELED_UNIT, STOP);
5947 reduce (q, strange_separator, &siga, INITIALISER_SERIES, SERIAL_CLAUSE, DECLARATION_LIST, STOP);
5948 } else if (IS (q, INITIALISER_SERIES)) {
5949 reduce (q, NO_NOTE, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, SEMI_SYMBOL, UNIT, STOP);
5950 reduce (q, NO_NOTE, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, SEMI_SYMBOL, LABELED_UNIT, STOP);
5951 reduce (q, NO_NOTE, &siga, INITIALISER_SERIES, INITIALISER_SERIES, SEMI_SYMBOL, DECLARATION_LIST, STOP);
5952 /* Errors */
5953 reduce (q, strange_separator, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, COMMA_SYMBOL, UNIT, STOP);
5954 reduce (q, strange_separator, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, COMMA_SYMBOL, LABELED_UNIT, STOP);
5955 reduce (q, strange_separator, &siga, INITIALISER_SERIES, INITIALISER_SERIES, COMMA_SYMBOL, DECLARATION_LIST, STOP);
5956 reduce (q, strange_separator, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, COLON_SYMBOL, UNIT, STOP);
5957 reduce (q, strange_separator, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, COLON_SYMBOL, LABELED_UNIT, STOP);
5958 reduce (q, strange_separator, &siga, INITIALISER_SERIES, INITIALISER_SERIES, COLON_SYMBOL, DECLARATION_LIST, STOP);
5959 reduce (q, strange_separator, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, UNIT, STOP);
5960 reduce (q, strange_separator, &siga, SERIAL_CLAUSE, INITIALISER_SERIES, LABELED_UNIT, STOP);
5961 reduce (q, strange_separator, &siga, INITIALISER_SERIES, INITIALISER_SERIES, DECLARATION_LIST, STOP);
5962 }
5963 }
5964 while (siga);
5965 }
5966 }
5967
5968 /**
5969 @brief Reduce enquiry clauses.
5970 @param p Node in syntax tree.
5971 **/
5972
5973 static void
reduce_enquiry_clauses(NODE_T * p)5974 reduce_enquiry_clauses (NODE_T * p)
5975 {
5976 if (NEXT (p) != NO_NODE) {
5977 NODE_T *q = NEXT (p);
5978 BOOL_T siga;
5979 reduce (q, NO_NOTE, NO_TICK, ENQUIRY_CLAUSE, UNIT, STOP);
5980 reduce (q, NO_NOTE, NO_TICK, INITIALISER_SERIES, DECLARATION_LIST, STOP);
5981 do {
5982 siga = A68_FALSE;
5983 if (IS (q, ENQUIRY_CLAUSE)) {
5984 reduce (q, NO_NOTE, &siga, ENQUIRY_CLAUSE, ENQUIRY_CLAUSE, SEMI_SYMBOL, UNIT, STOP);
5985 reduce (q, NO_NOTE, &siga, INITIALISER_SERIES, ENQUIRY_CLAUSE, SEMI_SYMBOL, DECLARATION_LIST, STOP);
5986 reduce (q, strange_separator, &siga, ENQUIRY_CLAUSE, ENQUIRY_CLAUSE, COMMA_SYMBOL, UNIT, STOP);
5987 reduce (q, strange_separator, &siga, INITIALISER_SERIES, ENQUIRY_CLAUSE, COMMA_SYMBOL, DECLARATION_LIST, STOP);
5988 reduce (q, strange_separator, &siga, ENQUIRY_CLAUSE, ENQUIRY_CLAUSE, COLON_SYMBOL, UNIT, STOP);
5989 reduce (q, strange_separator, &siga, INITIALISER_SERIES, ENQUIRY_CLAUSE, COLON_SYMBOL, DECLARATION_LIST, STOP);
5990 reduce (q, strange_separator, &siga, ENQUIRY_CLAUSE, ENQUIRY_CLAUSE, UNIT, STOP);
5991 reduce (q, strange_separator, &siga, INITIALISER_SERIES, ENQUIRY_CLAUSE, DECLARATION_LIST, STOP);
5992 } else if (IS (q, INITIALISER_SERIES)) {
5993 reduce (q, NO_NOTE, &siga, ENQUIRY_CLAUSE, INITIALISER_SERIES, SEMI_SYMBOL, UNIT, STOP);
5994 reduce (q, NO_NOTE, &siga, INITIALISER_SERIES, INITIALISER_SERIES, SEMI_SYMBOL, DECLARATION_LIST, STOP);
5995 reduce (q, strange_separator, &siga, ENQUIRY_CLAUSE, INITIALISER_SERIES, COMMA_SYMBOL, UNIT, STOP);
5996 reduce (q, strange_separator, &siga, INITIALISER_SERIES, INITIALISER_SERIES, COMMA_SYMBOL, DECLARATION_LIST, STOP);
5997 reduce (q, strange_separator, &siga, ENQUIRY_CLAUSE, INITIALISER_SERIES, COLON_SYMBOL, UNIT, STOP);
5998 reduce (q, strange_separator, &siga, INITIALISER_SERIES, INITIALISER_SERIES, COLON_SYMBOL, DECLARATION_LIST, STOP);
5999 reduce (q, strange_separator, &siga, ENQUIRY_CLAUSE, INITIALISER_SERIES, UNIT, STOP);
6000 reduce (q, strange_separator, &siga, INITIALISER_SERIES, INITIALISER_SERIES, DECLARATION_LIST, STOP);
6001 }
6002 }
6003 while (siga);
6004 }
6005 }
6006
6007 /**
6008 @brief Reduce collateral clauses.
6009 @param p Node in syntax tree.
6010 **/
6011
6012 static void
reduce_collateral_clauses(NODE_T * p)6013 reduce_collateral_clauses (NODE_T * p)
6014 {
6015 if (NEXT (p) != NO_NODE) {
6016 NODE_T *q = NEXT (p);
6017 if (IS (q, UNIT)) {
6018 BOOL_T siga;
6019 reduce (q, NO_NOTE, NO_TICK, UNIT_LIST, UNIT, STOP);
6020 do {
6021 siga = A68_FALSE;
6022 reduce (q, NO_NOTE, &siga, UNIT_LIST, UNIT_LIST, COMMA_SYMBOL, UNIT, STOP);
6023 reduce (q, strange_separator, &siga, UNIT_LIST, UNIT_LIST, UNIT, STOP);
6024 } while (siga);
6025 } else if (IS (q, SPECIFIED_UNIT)) {
6026 BOOL_T siga;
6027 reduce (q, NO_NOTE, NO_TICK, SPECIFIED_UNIT_LIST, SPECIFIED_UNIT, STOP);
6028 do {
6029 siga = A68_FALSE;
6030 reduce (q, NO_NOTE, &siga, SPECIFIED_UNIT_LIST, SPECIFIED_UNIT_LIST, COMMA_SYMBOL, SPECIFIED_UNIT, STOP);
6031 reduce (q, strange_separator, &siga, SPECIFIED_UNIT_LIST, SPECIFIED_UNIT_LIST, SPECIFIED_UNIT, STOP);
6032 } while (siga);
6033 }
6034 }
6035 }
6036
6037 /**
6038 @brief Reduces enclosed clauses.
6039 @param q Node in syntax tree.
6040 @param expect Information the parser may have on what is expected.
6041 **/
6042
6043 static void
reduce_enclosed_clauses(NODE_T * q,int expect)6044 reduce_enclosed_clauses (NODE_T * q, int expect)
6045 {
6046 NODE_T *p = q;
6047 if (SUB (p) == NO_NODE) {
6048 if (IS (p, FOR_SYMBOL)) {
6049 reduce (p, NO_NOTE, NO_TICK, FOR_PART, FOR_SYMBOL, DEFINING_IDENTIFIER, STOP);
6050 } else if (IS (p, OPEN_SYMBOL)) {
6051 if (expect == ENQUIRY_CLAUSE) {
6052 reduce (p, NO_NOTE, NO_TICK, OPEN_PART, OPEN_SYMBOL, ENQUIRY_CLAUSE, STOP);
6053 } else if (expect == ARGUMENT) {
6054 reduce (p, NO_NOTE, NO_TICK, ARGUMENT, OPEN_SYMBOL, CLOSE_SYMBOL, STOP);
6055 reduce (p, NO_NOTE, NO_TICK, ARGUMENT, OPEN_SYMBOL, ARGUMENT_LIST, CLOSE_SYMBOL, STOP);
6056 reduce (p, empty_clause, NO_TICK, ARGUMENT, OPEN_SYMBOL, INITIALISER_SERIES, CLOSE_SYMBOL, STOP);
6057 } else if (expect == GENERIC_ARGUMENT) {
6058 if (whether (p, OPEN_SYMBOL, CLOSE_SYMBOL, STOP)) {
6059 pad_node (p, TRIMMER);
6060 reduce (p, NO_NOTE, NO_TICK, GENERIC_ARGUMENT, OPEN_SYMBOL, TRIMMER, CLOSE_SYMBOL, STOP);
6061 }
6062 reduce (p, NO_NOTE, NO_TICK, GENERIC_ARGUMENT, OPEN_SYMBOL, GENERIC_ARGUMENT_LIST, CLOSE_SYMBOL, STOP);
6063 } else if (expect == BOUNDS) {
6064 reduce (p, NO_NOTE, NO_TICK, FORMAL_BOUNDS, OPEN_SYMBOL, CLOSE_SYMBOL, STOP);
6065 reduce (p, NO_NOTE, NO_TICK, BOUNDS, OPEN_SYMBOL, BOUNDS_LIST, CLOSE_SYMBOL, STOP);
6066 reduce (p, NO_NOTE, NO_TICK, FORMAL_BOUNDS, OPEN_SYMBOL, FORMAL_BOUNDS_LIST, CLOSE_SYMBOL, STOP);
6067 reduce (p, NO_NOTE, NO_TICK, FORMAL_BOUNDS, OPEN_SYMBOL, ALT_FORMAL_BOUNDS_LIST, CLOSE_SYMBOL, STOP);
6068 } else {
6069 reduce (p, NO_NOTE, NO_TICK, CLOSED_CLAUSE, OPEN_SYMBOL, SERIAL_CLAUSE, CLOSE_SYMBOL, STOP);
6070 reduce (p, NO_NOTE, NO_TICK, COLLATERAL_CLAUSE, OPEN_SYMBOL, UNIT_LIST, CLOSE_SYMBOL, STOP);
6071 reduce (p, NO_NOTE, NO_TICK, COLLATERAL_CLAUSE, OPEN_SYMBOL, CLOSE_SYMBOL, STOP);
6072 reduce (p, empty_clause, NO_TICK, CLOSED_CLAUSE, OPEN_SYMBOL, INITIALISER_SERIES, CLOSE_SYMBOL, STOP);
6073 }
6074 } else if (IS (p, SUB_SYMBOL)) {
6075 if (expect == GENERIC_ARGUMENT) {
6076 if (whether (p, SUB_SYMBOL, BUS_SYMBOL, STOP)) {
6077 pad_node (p, TRIMMER);
6078 reduce (p, NO_NOTE, NO_TICK, GENERIC_ARGUMENT, SUB_SYMBOL, TRIMMER, BUS_SYMBOL, STOP);
6079 }
6080 reduce (p, NO_NOTE, NO_TICK, GENERIC_ARGUMENT, SUB_SYMBOL, GENERIC_ARGUMENT_LIST, BUS_SYMBOL, STOP);
6081 } else if (expect == BOUNDS) {
6082 reduce (p, NO_NOTE, NO_TICK, FORMAL_BOUNDS, SUB_SYMBOL, BUS_SYMBOL, STOP);
6083 reduce (p, NO_NOTE, NO_TICK, BOUNDS, SUB_SYMBOL, BOUNDS_LIST, BUS_SYMBOL, STOP);
6084 reduce (p, NO_NOTE, NO_TICK, FORMAL_BOUNDS, SUB_SYMBOL, FORMAL_BOUNDS_LIST, BUS_SYMBOL, STOP);
6085 reduce (p, NO_NOTE, NO_TICK, FORMAL_BOUNDS, SUB_SYMBOL, ALT_FORMAL_BOUNDS_LIST, BUS_SYMBOL, STOP);
6086 }
6087 } else if (IS (p, BEGIN_SYMBOL)) {
6088 reduce (p, NO_NOTE, NO_TICK, COLLATERAL_CLAUSE, BEGIN_SYMBOL, UNIT_LIST, END_SYMBOL, STOP);
6089 reduce (p, NO_NOTE, NO_TICK, COLLATERAL_CLAUSE, BEGIN_SYMBOL, END_SYMBOL, STOP);
6090 reduce (p, NO_NOTE, NO_TICK, CLOSED_CLAUSE, BEGIN_SYMBOL, SERIAL_CLAUSE, END_SYMBOL, STOP);
6091 reduce (p, empty_clause, NO_TICK, CLOSED_CLAUSE, BEGIN_SYMBOL, INITIALISER_SERIES, END_SYMBOL, STOP);
6092 } else if (IS (p, FORMAT_DELIMITER_SYMBOL)) {
6093 reduce (p, NO_NOTE, NO_TICK, FORMAT_TEXT, FORMAT_DELIMITER_SYMBOL, PICTURE_LIST, FORMAT_DELIMITER_SYMBOL, STOP);
6094 reduce (p, NO_NOTE, NO_TICK, FORMAT_TEXT, FORMAT_DELIMITER_SYMBOL, FORMAT_DELIMITER_SYMBOL, STOP);
6095 } else if (IS (p, FORMAT_OPEN_SYMBOL)) {
6096 reduce (p, NO_NOTE, NO_TICK, COLLECTION, FORMAT_OPEN_SYMBOL, PICTURE_LIST, FORMAT_CLOSE_SYMBOL, STOP);
6097 } else if (IS (p, IF_SYMBOL)) {
6098 reduce (p, NO_NOTE, NO_TICK, IF_PART, IF_SYMBOL, ENQUIRY_CLAUSE, STOP);
6099 reduce (p, empty_clause, NO_TICK, IF_PART, IF_SYMBOL, INITIALISER_SERIES, STOP);
6100 } else if (IS (p, THEN_SYMBOL)) {
6101 reduce (p, NO_NOTE, NO_TICK, THEN_PART, THEN_SYMBOL, SERIAL_CLAUSE, STOP);
6102 reduce (p, empty_clause, NO_TICK, THEN_PART, THEN_SYMBOL, INITIALISER_SERIES, STOP);
6103 } else if (IS (p, ELSE_SYMBOL)) {
6104 reduce (p, NO_NOTE, NO_TICK, ELSE_PART, ELSE_SYMBOL, SERIAL_CLAUSE, STOP);
6105 reduce (p, empty_clause, NO_TICK, ELSE_PART, ELSE_SYMBOL, INITIALISER_SERIES, STOP);
6106 } else if (IS (p, ELIF_SYMBOL)) {
6107 reduce (p, NO_NOTE, NO_TICK, ELIF_IF_PART, ELIF_SYMBOL, ENQUIRY_CLAUSE, STOP);
6108 } else if (IS (p, CASE_SYMBOL)) {
6109 reduce (p, NO_NOTE, NO_TICK, CASE_PART, CASE_SYMBOL, ENQUIRY_CLAUSE, STOP);
6110 reduce (p, empty_clause, NO_TICK, CASE_PART, CASE_SYMBOL, INITIALISER_SERIES, STOP);
6111 } else if (IS (p, IN_SYMBOL)) {
6112 reduce (p, NO_NOTE, NO_TICK, CASE_IN_PART, IN_SYMBOL, UNIT_LIST, STOP);
6113 reduce (p, NO_NOTE, NO_TICK, CONFORMITY_IN_PART, IN_SYMBOL, SPECIFIED_UNIT_LIST, STOP);
6114 } else if (IS (p, OUT_SYMBOL)) {
6115 reduce (p, NO_NOTE, NO_TICK, OUT_PART, OUT_SYMBOL, SERIAL_CLAUSE, STOP);
6116 reduce (p, empty_clause, NO_TICK, OUT_PART, OUT_SYMBOL, INITIALISER_SERIES, STOP);
6117 } else if (IS (p, OUSE_SYMBOL)) {
6118 reduce (p, NO_NOTE, NO_TICK, OUSE_PART, OUSE_SYMBOL, ENQUIRY_CLAUSE, STOP);
6119 } else if (IS (p, THEN_BAR_SYMBOL)) {
6120 reduce (p, NO_NOTE, NO_TICK, CHOICE, THEN_BAR_SYMBOL, SERIAL_CLAUSE, STOP);
6121 reduce (p, NO_NOTE, NO_TICK, CASE_CHOICE_CLAUSE, THEN_BAR_SYMBOL, UNIT_LIST, STOP);
6122 reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CHOICE, THEN_BAR_SYMBOL, SPECIFIED_UNIT_LIST, STOP);
6123 reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CHOICE, THEN_BAR_SYMBOL, SPECIFIED_UNIT, STOP);
6124 reduce (p, empty_clause, NO_TICK, CHOICE, THEN_BAR_SYMBOL, INITIALISER_SERIES, STOP);
6125 } else if (IS (p, ELSE_BAR_SYMBOL)) {
6126 reduce (p, NO_NOTE, NO_TICK, ELSE_OPEN_PART, ELSE_BAR_SYMBOL, ENQUIRY_CLAUSE, STOP);
6127 reduce (p, empty_clause, NO_TICK, ELSE_OPEN_PART, ELSE_BAR_SYMBOL, INITIALISER_SERIES, STOP);
6128 } else if (IS (p, FROM_SYMBOL)) {
6129 reduce (p, NO_NOTE, NO_TICK, FROM_PART, FROM_SYMBOL, UNIT, STOP);
6130 } else if (IS (p, BY_SYMBOL)) {
6131 reduce (p, NO_NOTE, NO_TICK, BY_PART, BY_SYMBOL, UNIT, STOP);
6132 } else if (IS (p, TO_SYMBOL)) {
6133 reduce (p, NO_NOTE, NO_TICK, TO_PART, TO_SYMBOL, UNIT, STOP);
6134 } else if (IS (p, DOWNTO_SYMBOL)) {
6135 reduce (p, NO_NOTE, NO_TICK, TO_PART, DOWNTO_SYMBOL, UNIT, STOP);
6136 } else if (IS (p, WHILE_SYMBOL)) {
6137 reduce (p, NO_NOTE, NO_TICK, WHILE_PART, WHILE_SYMBOL, ENQUIRY_CLAUSE, STOP);
6138 reduce (p, empty_clause, NO_TICK, WHILE_PART, WHILE_SYMBOL, INITIALISER_SERIES, STOP);
6139 } else if (IS (p, UNTIL_SYMBOL)) {
6140 reduce (p, NO_NOTE, NO_TICK, UNTIL_PART, UNTIL_SYMBOL, ENQUIRY_CLAUSE, STOP);
6141 reduce (p, empty_clause, NO_TICK, UNTIL_PART, UNTIL_SYMBOL, INITIALISER_SERIES, STOP);
6142 } else if (IS (p, DO_SYMBOL)) {
6143 reduce (p, NO_NOTE, NO_TICK, DO_PART, DO_SYMBOL, SERIAL_CLAUSE, UNTIL_PART, OD_SYMBOL, STOP);
6144 reduce (p, NO_NOTE, NO_TICK, DO_PART, DO_SYMBOL, SERIAL_CLAUSE, OD_SYMBOL, STOP);
6145 reduce (p, NO_NOTE, NO_TICK, DO_PART, DO_SYMBOL, UNTIL_PART, OD_SYMBOL, STOP);
6146 } else if (IS (p, ALT_DO_SYMBOL)) {
6147 reduce (p, NO_NOTE, NO_TICK, ALT_DO_PART, ALT_DO_SYMBOL, SERIAL_CLAUSE, UNTIL_PART, OD_SYMBOL, STOP);
6148 reduce (p, NO_NOTE, NO_TICK, ALT_DO_PART, ALT_DO_SYMBOL, SERIAL_CLAUSE, OD_SYMBOL, STOP);
6149 reduce (p, NO_NOTE, NO_TICK, ALT_DO_PART, ALT_DO_SYMBOL, UNTIL_PART, OD_SYMBOL, STOP);
6150 }
6151 }
6152 p = q;
6153 if (SUB (p) != NO_NODE) {
6154 if (IS (p, OPEN_PART)) {
6155 reduce (p, NO_NOTE, NO_TICK, CONDITIONAL_CLAUSE, OPEN_PART, CHOICE, CHOICE, CLOSE_SYMBOL, STOP);
6156 reduce (p, NO_NOTE, NO_TICK, CONDITIONAL_CLAUSE, OPEN_PART, CHOICE, CLOSE_SYMBOL, STOP);
6157 reduce (p, NO_NOTE, NO_TICK, CONDITIONAL_CLAUSE, OPEN_PART, CHOICE, BRIEF_ELIF_PART, STOP);
6158 reduce (p, NO_NOTE, NO_TICK, CASE_CLAUSE, OPEN_PART, CASE_CHOICE_CLAUSE, CHOICE, CLOSE_SYMBOL, STOP);
6159 reduce (p, NO_NOTE, NO_TICK, CASE_CLAUSE, OPEN_PART, CASE_CHOICE_CLAUSE, CLOSE_SYMBOL, STOP);
6160 reduce (p, NO_NOTE, NO_TICK, CASE_CLAUSE, OPEN_PART, CASE_CHOICE_CLAUSE, BRIEF_OUSE_PART, STOP);
6161 reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CLAUSE, OPEN_PART, CONFORMITY_CHOICE, CHOICE, CLOSE_SYMBOL, STOP);
6162 reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CLAUSE, OPEN_PART, CONFORMITY_CHOICE, CLOSE_SYMBOL, STOP);
6163 reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CLAUSE, OPEN_PART, CONFORMITY_CHOICE, BRIEF_CONFORMITY_OUSE_PART, STOP);
6164 } else if (IS (p, ELSE_OPEN_PART)) {
6165 reduce (p, NO_NOTE, NO_TICK, BRIEF_ELIF_PART, ELSE_OPEN_PART, CHOICE, CHOICE, CLOSE_SYMBOL, STOP);
6166 reduce (p, NO_NOTE, NO_TICK, BRIEF_ELIF_PART, ELSE_OPEN_PART, CHOICE, CLOSE_SYMBOL, STOP);
6167 reduce (p, NO_NOTE, NO_TICK, BRIEF_ELIF_PART, ELSE_OPEN_PART, CHOICE, BRIEF_ELIF_PART, STOP);
6168 reduce (p, NO_NOTE, NO_TICK, BRIEF_OUSE_PART, ELSE_OPEN_PART, CASE_CHOICE_CLAUSE, CHOICE, CLOSE_SYMBOL, STOP);
6169 reduce (p, NO_NOTE, NO_TICK, BRIEF_OUSE_PART, ELSE_OPEN_PART, CASE_CHOICE_CLAUSE, CLOSE_SYMBOL, STOP);
6170 reduce (p, NO_NOTE, NO_TICK, BRIEF_OUSE_PART, ELSE_OPEN_PART, CASE_CHOICE_CLAUSE, BRIEF_OUSE_PART, STOP);
6171 reduce (p, NO_NOTE, NO_TICK, BRIEF_CONFORMITY_OUSE_PART, ELSE_OPEN_PART, CONFORMITY_CHOICE, CHOICE, CLOSE_SYMBOL, STOP);
6172 reduce (p, NO_NOTE, NO_TICK, BRIEF_CONFORMITY_OUSE_PART, ELSE_OPEN_PART, CONFORMITY_CHOICE, CLOSE_SYMBOL, STOP);
6173 reduce (p, NO_NOTE, NO_TICK, BRIEF_CONFORMITY_OUSE_PART, ELSE_OPEN_PART, CONFORMITY_CHOICE, BRIEF_CONFORMITY_OUSE_PART, STOP);
6174 } else if (IS (p, IF_PART)) {
6175 reduce (p, NO_NOTE, NO_TICK, CONDITIONAL_CLAUSE, IF_PART, THEN_PART, ELSE_PART, FI_SYMBOL, STOP);
6176 reduce (p, NO_NOTE, NO_TICK, CONDITIONAL_CLAUSE, IF_PART, THEN_PART, ELIF_PART, STOP);
6177 reduce (p, NO_NOTE, NO_TICK, CONDITIONAL_CLAUSE, IF_PART, THEN_PART, FI_SYMBOL, STOP);
6178 } else if (IS (p, ELIF_IF_PART)) {
6179 reduce (p, NO_NOTE, NO_TICK, ELIF_PART, ELIF_IF_PART, THEN_PART, ELSE_PART, FI_SYMBOL, STOP);
6180 reduce (p, NO_NOTE, NO_TICK, ELIF_PART, ELIF_IF_PART, THEN_PART, FI_SYMBOL, STOP);
6181 reduce (p, NO_NOTE, NO_TICK, ELIF_PART, ELIF_IF_PART, THEN_PART, ELIF_PART, STOP);
6182 } else if (IS (p, CASE_PART)) {
6183 reduce (p, NO_NOTE, NO_TICK, CASE_CLAUSE, CASE_PART, CASE_IN_PART, OUT_PART, ESAC_SYMBOL, STOP);
6184 reduce (p, NO_NOTE, NO_TICK, CASE_CLAUSE, CASE_PART, CASE_IN_PART, ESAC_SYMBOL, STOP);
6185 reduce (p, NO_NOTE, NO_TICK, CASE_CLAUSE, CASE_PART, CASE_IN_PART, CASE_OUSE_PART, STOP);
6186 reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CLAUSE, CASE_PART, CONFORMITY_IN_PART, OUT_PART, ESAC_SYMBOL, STOP);
6187 reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CLAUSE, CASE_PART, CONFORMITY_IN_PART, ESAC_SYMBOL, STOP);
6188 reduce (p, NO_NOTE, NO_TICK, CONFORMITY_CLAUSE, CASE_PART, CONFORMITY_IN_PART, CONFORMITY_OUSE_PART, STOP);
6189 } else if (IS (p, OUSE_PART)) {
6190 reduce (p, NO_NOTE, NO_TICK, CASE_OUSE_PART, OUSE_PART, CASE_IN_PART, OUT_PART, ESAC_SYMBOL, STOP);
6191 reduce (p, NO_NOTE, NO_TICK, CASE_OUSE_PART, OUSE_PART, CASE_IN_PART, ESAC_SYMBOL, STOP);
6192 reduce (p, NO_NOTE, NO_TICK, CASE_OUSE_PART, OUSE_PART, CASE_IN_PART, CASE_OUSE_PART, STOP);
6193 reduce (p, NO_NOTE, NO_TICK, CONFORMITY_OUSE_PART, OUSE_PART, CONFORMITY_IN_PART, OUT_PART, ESAC_SYMBOL, STOP);
6194 reduce (p, NO_NOTE, NO_TICK, CONFORMITY_OUSE_PART, OUSE_PART, CONFORMITY_IN_PART, ESAC_SYMBOL, STOP);
6195 reduce (p, NO_NOTE, NO_TICK, CONFORMITY_OUSE_PART, OUSE_PART, CONFORMITY_IN_PART, CONFORMITY_OUSE_PART, STOP);
6196 } else if (IS (p, FOR_PART)) {
6197 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, BY_PART, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
6198 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, BY_PART, WHILE_PART, ALT_DO_PART, STOP);
6199 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
6200 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, WHILE_PART, ALT_DO_PART, STOP);
6201 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, BY_PART, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
6202 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, BY_PART, WHILE_PART, ALT_DO_PART, STOP);
6203 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
6204 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, WHILE_PART, ALT_DO_PART, STOP);
6205 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, BY_PART, TO_PART, ALT_DO_PART, STOP);
6206 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, BY_PART, ALT_DO_PART, STOP);
6207 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, TO_PART, ALT_DO_PART, STOP);
6208 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, FROM_PART, ALT_DO_PART, STOP);
6209 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, BY_PART, TO_PART, ALT_DO_PART, STOP);
6210 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, BY_PART, ALT_DO_PART, STOP);
6211 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, TO_PART, ALT_DO_PART, STOP);
6212 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FOR_PART, ALT_DO_PART, STOP);
6213 } else if (IS (p, FROM_PART)) {
6214 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, BY_PART, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
6215 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, BY_PART, WHILE_PART, ALT_DO_PART, STOP);
6216 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
6217 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, WHILE_PART, ALT_DO_PART, STOP);
6218 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, BY_PART, TO_PART, ALT_DO_PART, STOP);
6219 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, BY_PART, ALT_DO_PART, STOP);
6220 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, TO_PART, ALT_DO_PART, STOP);
6221 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, FROM_PART, ALT_DO_PART, STOP);
6222 } else if (IS (p, BY_PART)) {
6223 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, BY_PART, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
6224 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, BY_PART, WHILE_PART, ALT_DO_PART, STOP);
6225 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, BY_PART, TO_PART, ALT_DO_PART, STOP);
6226 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, BY_PART, ALT_DO_PART, STOP);
6227 } else if (IS (p, TO_PART)) {
6228 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, TO_PART, WHILE_PART, ALT_DO_PART, STOP);
6229 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, TO_PART, ALT_DO_PART, STOP);
6230 } else if (IS (p, WHILE_PART)) {
6231 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, WHILE_PART, ALT_DO_PART, STOP);
6232 } else if (IS (p, DO_PART)) {
6233 reduce (p, NO_NOTE, NO_TICK, LOOP_CLAUSE, DO_PART, STOP);
6234 }
6235 }
6236 }
6237
6238 /**
6239 @brief Substitute reduction when a phrase could not be parsed.
6240 @param p Node in syntax tree.
6241 @param expect Information the parser may have on what is expected.
6242 @param suppress Suppresses a diagnostic_node message (nested c.q. related diagnostics).
6243 **/
6244
6245 static void
recover_from_error(NODE_T * p,int expect,BOOL_T suppress)6246 recover_from_error (NODE_T * p, int expect, BOOL_T suppress)
6247 {
6248 /* This routine does not do fancy things as that might introduce more errors */
6249 NODE_T *q = p;
6250 if (p == NO_NODE) {
6251 return;
6252 }
6253 if (expect == SOME_CLAUSE) {
6254 expect = serial_or_collateral (p);
6255 }
6256 if (!suppress) {
6257 /* Give an error message */
6258 NODE_T *w = p;
6259 char *seq = phrase_to_text (p, &w);
6260 if (strlen (seq) == 0) {
6261 if (ERROR_COUNT (&program) == 0) {
6262 diagnostic_node (A68_SYNTAX_ERROR, w, ERROR_SYNTAX_EXPECTED, expect);
6263 }
6264 } else {
6265 diagnostic_node (A68_SYNTAX_ERROR, w, ERROR_INVALID_SEQUENCE, seq, expect);
6266 }
6267 if (ERROR_COUNT (&program) >= MAX_ERRORS) {
6268 longjmp (bottom_up_crash_exit, 1);
6269 }
6270 }
6271 /* Try to prevent spurious diagnostics by guessing what was expected */
6272 while (NEXT (q) != NO_NODE) {
6273 FORWARD (q);
6274 }
6275 if (is_one_of (p, BEGIN_SYMBOL, OPEN_SYMBOL, STOP)) {
6276 if (expect == ARGUMENT || expect == COLLATERAL_CLAUSE || expect == PARAMETER_PACK || expect == STRUCTURE_PACK || expect == UNION_PACK) {
6277 make_sub (p, q, expect);
6278 } else if (expect == ENQUIRY_CLAUSE) {
6279 make_sub (p, q, OPEN_PART);
6280 } else if (expect == FORMAL_DECLARERS) {
6281 make_sub (p, q, FORMAL_DECLARERS);
6282 } else {
6283 make_sub (p, q, CLOSED_CLAUSE);
6284 }
6285 } else if (IS (p, FORMAT_DELIMITER_SYMBOL) && expect == FORMAT_TEXT) {
6286 make_sub (p, q, FORMAT_TEXT);
6287 } else if (IS (p, CODE_SYMBOL)) {
6288 make_sub (p, q, CODE_CLAUSE);
6289 } else if (is_one_of (p, THEN_BAR_SYMBOL, CHOICE, STOP)) {
6290 make_sub (p, q, CHOICE);
6291 } else if (is_one_of (p, IF_SYMBOL, IF_PART, STOP)) {
6292 make_sub (p, q, IF_PART);
6293 } else if (is_one_of (p, THEN_SYMBOL, THEN_PART, STOP)) {
6294 make_sub (p, q, THEN_PART);
6295 } else if (is_one_of (p, ELSE_SYMBOL, ELSE_PART, STOP)) {
6296 make_sub (p, q, ELSE_PART);
6297 } else if (is_one_of (p, ELIF_SYMBOL, ELIF_IF_PART, STOP)) {
6298 make_sub (p, q, ELIF_IF_PART);
6299 } else if (is_one_of (p, CASE_SYMBOL, CASE_PART, STOP)) {
6300 make_sub (p, q, CASE_PART);
6301 } else if (is_one_of (p, OUT_SYMBOL, OUT_PART, STOP)) {
6302 make_sub (p, q, OUT_PART);
6303 } else if (is_one_of (p, OUSE_SYMBOL, OUSE_PART, STOP)) {
6304 make_sub (p, q, OUSE_PART);
6305 } else if (is_one_of (p, FOR_SYMBOL, FOR_PART, STOP)) {
6306 make_sub (p, q, FOR_PART);
6307 } else if (is_one_of (p, FROM_SYMBOL, FROM_PART, STOP)) {
6308 make_sub (p, q, FROM_PART);
6309 } else if (is_one_of (p, BY_SYMBOL, BY_PART, STOP)) {
6310 make_sub (p, q, BY_PART);
6311 } else if (is_one_of (p, TO_SYMBOL, DOWNTO_SYMBOL, TO_PART, STOP)) {
6312 make_sub (p, q, TO_PART);
6313 } else if (is_one_of (p, WHILE_SYMBOL, WHILE_PART, STOP)) {
6314 make_sub (p, q, WHILE_PART);
6315 } else if (is_one_of (p, UNTIL_SYMBOL, UNTIL_PART, STOP)) {
6316 make_sub (p, q, UNTIL_PART);
6317 } else if (is_one_of (p, DO_SYMBOL, DO_PART, STOP)) {
6318 make_sub (p, q, DO_PART);
6319 } else if (is_one_of (p, ALT_DO_SYMBOL, ALT_DO_PART, STOP)) {
6320 make_sub (p, q, ALT_DO_PART);
6321 } else if (non_terminal_string (edit_line, expect) != NO_TEXT) {
6322 make_sub (p, q, expect);
6323 }
6324 }
6325
6326 /**
6327 @brief Heuristic aid in pinpointing errors.
6328 @param p Node in syntax tree.
6329 **/
6330
6331 static void
reduce_erroneous_units(NODE_T * p)6332 reduce_erroneous_units (NODE_T * p)
6333 {
6334 /* Constructs are reduced to units in an attempt to limit spurious diagnostics */
6335 NODE_T *q;
6336 for (q = p; q != NO_NODE; FORWARD (q)) {
6337 /* Some implementations allow selection from a tertiary, when there is no risk
6338 of ambiguity. Algol68G follows RR, so some extra attention here to guide an
6339 unsuspecting user */
6340 if (whether (q, SELECTOR, -SECONDARY, STOP)) {
6341 diagnostic_node (A68_SYNTAX_ERROR, NEXT (q), ERROR_SYNTAX_EXPECTED, SECONDARY);
6342 reduce (q, NO_NOTE, NO_TICK, UNIT, SELECTOR, WILDCARD, STOP);
6343 }
6344 /* Attention for identity relations that require tertiaries */
6345 if (whether (q, -TERTIARY, IS_SYMBOL, TERTIARY, STOP) || whether (q, TERTIARY, IS_SYMBOL, -TERTIARY, STOP) || whether (q, -TERTIARY, IS_SYMBOL, -TERTIARY, STOP)) {
6346 diagnostic_node (A68_SYNTAX_ERROR, NEXT (q), ERROR_SYNTAX_EXPECTED, TERTIARY);
6347 reduce (q, NO_NOTE, NO_TICK, UNIT, WILDCARD, IS_SYMBOL, WILDCARD, STOP);
6348 } else if (whether (q, -TERTIARY, ISNT_SYMBOL, TERTIARY, STOP) || whether (q, TERTIARY, ISNT_SYMBOL, -TERTIARY, STOP) || whether (q, -TERTIARY, ISNT_SYMBOL, -TERTIARY, STOP)) {
6349 diagnostic_node (A68_SYNTAX_ERROR, NEXT (q), ERROR_SYNTAX_EXPECTED, TERTIARY);
6350 reduce (q, NO_NOTE, NO_TICK, UNIT, WILDCARD, ISNT_SYMBOL, WILDCARD, STOP);
6351 }
6352 }
6353 }
6354
6355 /* A posteriori checks of the syntax tree built by the BU parser */
6356
6357 /**
6358 @brief Driver for a posteriori error checking.
6359 @param p Node in syntax tree.
6360 **/
6361
6362 void
bottom_up_error_check(NODE_T * p)6363 bottom_up_error_check (NODE_T * p)
6364 {
6365 for (; p != NO_NODE; FORWARD (p)) {
6366 if (IS (p, BOOLEAN_PATTERN)) {
6367 int k = 0;
6368 count_pictures (SUB (p), &k);
6369 if (!(k == 0 || k == 2)) {
6370 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_FORMAT_PICTURE_NUMBER, ATTRIBUTE (p));
6371 }
6372 } else {
6373 bottom_up_error_check (SUB (p));
6374 }
6375 }
6376 }
6377
6378 /* Next part rearranges and checks the tree after the symbol tables are finished */
6379
6380 /**
6381 @brief Transfer IDENTIFIER to JUMP where appropriate.
6382 @param p Node in syntax tree.
6383 **/
6384
6385 void
rearrange_goto_less_jumps(NODE_T * p)6386 rearrange_goto_less_jumps (NODE_T * p)
6387 {
6388 for (; p != NO_NODE; FORWARD (p)) {
6389 if (IS (p, UNIT)) {
6390 NODE_T *q = SUB (p);
6391 if (IS (q, TERTIARY)) {
6392 NODE_T *tertiary = q;
6393 q = SUB (q);
6394 if (q != NO_NODE && IS (q, SECONDARY)) {
6395 q = SUB (q);
6396 if (q != NO_NODE && IS (q, PRIMARY)) {
6397 q = SUB (q);
6398 if (q != NO_NODE && IS (q, IDENTIFIER)) {
6399 if (is_identifier_or_label_global (TABLE (q), NSYMBOL (q)) == LABEL) {
6400 ATTRIBUTE (tertiary) = JUMP;
6401 SUB (tertiary) = q;
6402 }
6403 }
6404 }
6405 }
6406 }
6407 } else if (IS (p, TERTIARY)) {
6408 NODE_T *q = SUB (p);
6409 if (q != NO_NODE && IS (q, SECONDARY)) {
6410 NODE_T *secondary = q;
6411 q = SUB (q);
6412 if (q != NO_NODE && IS (q, PRIMARY)) {
6413 q = SUB (q);
6414 if (q != NO_NODE && IS (q, IDENTIFIER)) {
6415 if (is_identifier_or_label_global (TABLE (q), NSYMBOL (q)) == LABEL) {
6416 ATTRIBUTE (secondary) = JUMP;
6417 SUB (secondary) = q;
6418 }
6419 }
6420 }
6421 }
6422 } else if (IS (p, SECONDARY)) {
6423 NODE_T *q = SUB (p);
6424 if (q != NO_NODE && IS (q, PRIMARY)) {
6425 NODE_T *primary = q;
6426 q = SUB (q);
6427 if (q != NO_NODE && IS (q, IDENTIFIER)) {
6428 if (is_identifier_or_label_global (TABLE (q), NSYMBOL (q)) == LABEL) {
6429 ATTRIBUTE (primary) = JUMP;
6430 SUB (primary) = q;
6431 }
6432 }
6433 }
6434 } else if (IS (p, PRIMARY)) {
6435 NODE_T *q = SUB (p);
6436 if (q != NO_NODE && IS (q, IDENTIFIER)) {
6437 if (is_identifier_or_label_global (TABLE (q), NSYMBOL (q)) == LABEL) {
6438 make_sub (q, q, JUMP);
6439 }
6440 }
6441 }
6442 rearrange_goto_less_jumps (SUB (p));
6443 }
6444 }
6445
6446 /***********************************************************/
6447 /* VICTAL checker for formal, actual and virtual declarers */
6448 /***********************************************************/
6449
6450 /**
6451 @brief Check generator.
6452 @param p Node in syntax tree.
6453 **/
6454
6455 static void
victal_check_generator(NODE_T * p)6456 victal_check_generator (NODE_T * p)
6457 {
6458 if (!victal_check_declarer (NEXT (p), ACTUAL_DECLARER_MARK)) {
6459 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_EXPECTED, "actual declarer");
6460 }
6461 }
6462
6463 /**
6464 @brief Check formal pack.
6465 @param p Node in syntax tree.
6466 @param x Expected attribute.
6467 @param z Flag.
6468 **/
6469
6470 static void
victal_check_formal_pack(NODE_T * p,int x,BOOL_T * z)6471 victal_check_formal_pack (NODE_T * p, int x, BOOL_T * z)
6472 {
6473 if (p != NO_NODE) {
6474 if (IS (p, FORMAL_DECLARERS)) {
6475 victal_check_formal_pack (SUB (p), x, z);
6476 } else if (is_one_of (p, OPEN_SYMBOL, COMMA_SYMBOL, STOP)) {
6477 victal_check_formal_pack (NEXT (p), x, z);
6478 } else if (IS (p, FORMAL_DECLARERS_LIST)) {
6479 victal_check_formal_pack (NEXT (p), x, z);
6480 victal_check_formal_pack (SUB (p), x, z);
6481 } else if (IS (p, DECLARER)) {
6482 victal_check_formal_pack (NEXT (p), x, z);
6483 (*z) &= victal_check_declarer (SUB (p), x);
6484 }
6485 }
6486 }
6487
6488 /**
6489 @brief Check operator declaration.
6490 @param p Node in syntax tree.
6491 **/
6492
6493 static void
victal_check_operator_dec(NODE_T * p)6494 victal_check_operator_dec (NODE_T * p)
6495 {
6496 if (IS (NEXT (p), FORMAL_DECLARERS)) {
6497 BOOL_T z = A68_TRUE;
6498 victal_check_formal_pack (NEXT (p), FORMAL_DECLARER_MARK, &z);
6499 if (!z) {
6500 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_EXPECTED, "formal declarers");
6501 }
6502 FORWARD (p);
6503 }
6504 if (!victal_check_declarer (NEXT (p), FORMAL_DECLARER_MARK)) {
6505 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_EXPECTED, "formal declarer");
6506 }
6507 }
6508
6509 /**
6510 @brief Check mode declaration.
6511 @param p Node in syntax tree.
6512 **/
6513
6514 static void
victal_check_mode_dec(NODE_T * p)6515 victal_check_mode_dec (NODE_T * p)
6516 {
6517 if (p != NO_NODE) {
6518 if (IS (p, MODE_DECLARATION)) {
6519 victal_check_mode_dec (SUB (p));
6520 victal_check_mode_dec (NEXT (p));
6521 } else if (is_one_of (p, MODE_SYMBOL, DEFINING_INDICANT, STOP)
6522 || is_one_of (p, EQUALS_SYMBOL, COMMA_SYMBOL, STOP)) {
6523 victal_check_mode_dec (NEXT (p));
6524 } else if (IS (p, DECLARER)) {
6525 if (!victal_check_declarer (p, ACTUAL_DECLARER_MARK)) {
6526 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_EXPECTED, "actual declarer");
6527 }
6528 }
6529 }
6530 }
6531
6532 /**
6533 @brief Check variable declaration.
6534 @param p Node in syntax tree.
6535 **/
6536
6537 static void
victal_check_variable_dec(NODE_T * p)6538 victal_check_variable_dec (NODE_T * p)
6539 {
6540 if (p != NO_NODE) {
6541 if (IS (p, VARIABLE_DECLARATION)) {
6542 victal_check_variable_dec (SUB (p));
6543 victal_check_variable_dec (NEXT (p));
6544 } else if (is_one_of (p, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, STOP)
6545 || IS (p, COMMA_SYMBOL)) {
6546 victal_check_variable_dec (NEXT (p));
6547 } else if (IS (p, UNIT)) {
6548 victal_checker (SUB (p));
6549 } else if (IS (p, DECLARER)) {
6550 if (!victal_check_declarer (p, ACTUAL_DECLARER_MARK)) {
6551 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_EXPECTED, "actual declarer");
6552 }
6553 victal_check_variable_dec (NEXT (p));
6554 }
6555 }
6556 }
6557
6558 /**
6559 @brief Check identity declaration.
6560 @param p Node in syntax tree.
6561 **/
6562
6563 static void
victal_check_identity_dec(NODE_T * p)6564 victal_check_identity_dec (NODE_T * p)
6565 {
6566 if (p != NO_NODE) {
6567 if (IS (p, IDENTITY_DECLARATION)) {
6568 victal_check_identity_dec (SUB (p));
6569 victal_check_identity_dec (NEXT (p));
6570 } else if (is_one_of (p, DEFINING_IDENTIFIER, EQUALS_SYMBOL, COMMA_SYMBOL, STOP)) {
6571 victal_check_identity_dec (NEXT (p));
6572 } else if (IS (p, UNIT)) {
6573 victal_checker (SUB (p));
6574 } else if (IS (p, DECLARER)) {
6575 if (!victal_check_declarer (p, FORMAL_DECLARER_MARK)) {
6576 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_EXPECTED, "formal declarer");
6577 }
6578 victal_check_identity_dec (NEXT (p));
6579 }
6580 }
6581 }
6582
6583 /**
6584 @brief Check routine pack.
6585 @param p Node in syntax tree.
6586 @param x Expected attribute.
6587 @param z Flag.
6588 **/
6589
6590 static void
victal_check_routine_pack(NODE_T * p,int x,BOOL_T * z)6591 victal_check_routine_pack (NODE_T * p, int x, BOOL_T * z)
6592 {
6593 if (p != NO_NODE) {
6594 if (IS (p, PARAMETER_PACK)) {
6595 victal_check_routine_pack (SUB (p), x, z);
6596 } else if (is_one_of (p, OPEN_SYMBOL, COMMA_SYMBOL, STOP)) {
6597 victal_check_routine_pack (NEXT (p), x, z);
6598 } else if (is_one_of (p, PARAMETER_LIST, PARAMETER, STOP)) {
6599 victal_check_routine_pack (NEXT (p), x, z);
6600 victal_check_routine_pack (SUB (p), x, z);
6601 } else if (IS (p, DECLARER)) {
6602 *z &= victal_check_declarer (SUB (p), x);
6603 }
6604 }
6605 }
6606
6607 /**
6608 @brief Check routine text.
6609 @param p Node in syntax tree.
6610 **/
6611
6612 static void
victal_check_routine_text(NODE_T * p)6613 victal_check_routine_text (NODE_T * p)
6614 {
6615 if (IS (p, PARAMETER_PACK)) {
6616 BOOL_T z = A68_TRUE;
6617 victal_check_routine_pack (p, FORMAL_DECLARER_MARK, &z);
6618 if (!z) {
6619 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_EXPECTED, "formal declarers");
6620 }
6621 FORWARD (p);
6622 }
6623 if (!victal_check_declarer (p, FORMAL_DECLARER_MARK)) {
6624 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_EXPECTED, "formal declarer");
6625 }
6626 victal_checker (NEXT (p));
6627 }
6628
6629 /**
6630 @brief Check structure pack.
6631 @param p Node in syntax tree.
6632 @param x Expected attribute.
6633 @param z Flag.
6634 **/
6635
6636 static void
victal_check_structure_pack(NODE_T * p,int x,BOOL_T * z)6637 victal_check_structure_pack (NODE_T * p, int x, BOOL_T * z)
6638 {
6639 if (p != NO_NODE) {
6640 if (IS (p, STRUCTURE_PACK)) {
6641 victal_check_structure_pack (SUB (p), x, z);
6642 } else if (is_one_of (p, OPEN_SYMBOL, COMMA_SYMBOL, STOP)) {
6643 victal_check_structure_pack (NEXT (p), x, z);
6644 } else if (is_one_of (p, STRUCTURED_FIELD_LIST, STRUCTURED_FIELD, STOP)) {
6645 victal_check_structure_pack (NEXT (p), x, z);
6646 victal_check_structure_pack (SUB (p), x, z);
6647 } else if (IS (p, DECLARER)) {
6648 (*z) &= victal_check_declarer (SUB (p), x);
6649 }
6650 }
6651 }
6652
6653 /**
6654 @brief Check union pack.
6655 @param p Node in syntax tree.
6656 @param x Expected attribute.
6657 @param z Flag.
6658 **/
6659
6660 static void
victal_check_union_pack(NODE_T * p,int x,BOOL_T * z)6661 victal_check_union_pack (NODE_T * p, int x, BOOL_T * z)
6662 {
6663 if (p != NO_NODE) {
6664 if (IS (p, UNION_PACK)) {
6665 victal_check_union_pack (SUB (p), x, z);
6666 } else if (is_one_of (p, OPEN_SYMBOL, COMMA_SYMBOL, VOID_SYMBOL, STOP)) {
6667 victal_check_union_pack (NEXT (p), x, z);
6668 } else if (IS (p, UNION_DECLARER_LIST)) {
6669 victal_check_union_pack (NEXT (p), x, z);
6670 victal_check_union_pack (SUB (p), x, z);
6671 } else if (IS (p, DECLARER)) {
6672 victal_check_union_pack (NEXT (p), x, z);
6673 (*z) &= victal_check_declarer (SUB (p), FORMAL_DECLARER_MARK);
6674 }
6675 }
6676 }
6677
6678 /**
6679 @brief Check declarer.
6680 @param p Node in syntax tree.
6681 @param x Expected attribute.
6682 **/
6683
6684 static BOOL_T
victal_check_declarer(NODE_T * p,int x)6685 victal_check_declarer (NODE_T * p, int x)
6686 {
6687 if (p == NO_NODE) {
6688 return (A68_FALSE);
6689 } else if (IS (p, DECLARER)) {
6690 return (victal_check_declarer (SUB (p), x));
6691 } else if (is_one_of (p, LONGETY, SHORTETY, STOP)) {
6692 return (A68_TRUE);
6693 } else if (is_one_of (p, VOID_SYMBOL, INDICANT, STANDARD, STOP)) {
6694 return (A68_TRUE);
6695 } else if (IS (p, REF_SYMBOL)) {
6696 return (victal_check_declarer (NEXT (p), VIRTUAL_DECLARER_MARK));
6697 } else if (IS (p, FLEX_SYMBOL)) {
6698 return (victal_check_declarer (NEXT (p), x));
6699 } else if (IS (p, BOUNDS)) {
6700 victal_checker (SUB (p));
6701 if (x == FORMAL_DECLARER_MARK) {
6702 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_EXPECTED, "formal bounds");
6703 (void) victal_check_declarer (NEXT (p), x);
6704 return (A68_TRUE);
6705 } else if (x == VIRTUAL_DECLARER_MARK) {
6706 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_EXPECTED, "virtual bounds");
6707 (void) victal_check_declarer (NEXT (p), x);
6708 return (A68_TRUE);
6709 } else {
6710 return (victal_check_declarer (NEXT (p), x));
6711 }
6712 } else if (IS (p, FORMAL_BOUNDS)) {
6713 victal_checker (SUB (p));
6714 if (x == ACTUAL_DECLARER_MARK) {
6715 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_EXPECTED, "actual bounds");
6716 (void) victal_check_declarer (NEXT (p), x);
6717 return (A68_TRUE);
6718 } else {
6719 return (victal_check_declarer (NEXT (p), x));
6720 }
6721 } else if (IS (p, STRUCT_SYMBOL)) {
6722 BOOL_T z = A68_TRUE;
6723 victal_check_structure_pack (NEXT (p), x, &z);
6724 return (z);
6725 } else if (IS (p, UNION_SYMBOL)) {
6726 BOOL_T z = A68_TRUE;
6727 victal_check_union_pack (NEXT (p), FORMAL_DECLARER_MARK, &z);
6728 if (!z) {
6729 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_EXPECTED, "formal declarer pack");
6730 }
6731 return (A68_TRUE);
6732 } else if (IS (p, PROC_SYMBOL)) {
6733 if (IS (NEXT (p), FORMAL_DECLARERS)) {
6734 BOOL_T z = A68_TRUE;
6735 victal_check_formal_pack (NEXT (p), FORMAL_DECLARER_MARK, &z);
6736 if (!z) {
6737 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_EXPECTED, "formal declarer");
6738 }
6739 FORWARD (p);
6740 }
6741 if (!victal_check_declarer (NEXT (p), FORMAL_DECLARER_MARK)) {
6742 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_EXPECTED, "formal declarer");
6743 }
6744 return (A68_TRUE);
6745 } else {
6746 return (A68_FALSE);
6747 }
6748 }
6749
6750 /**
6751 @brief Check cast.
6752 @param p Node in syntax tree.
6753 **/
6754
6755 static void
victal_check_cast(NODE_T * p)6756 victal_check_cast (NODE_T * p)
6757 {
6758 if (!victal_check_declarer (p, FORMAL_DECLARER_MARK)) {
6759 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_EXPECTED, "formal declarer");
6760 victal_checker (NEXT (p));
6761 }
6762 }
6763
6764 /**
6765 @brief Driver for checking VICTALITY of declarers.
6766 @param p Node in syntax tree.
6767 **/
6768
6769 void
victal_checker(NODE_T * p)6770 victal_checker (NODE_T * p)
6771 {
6772 for (; p != NO_NODE; FORWARD (p)) {
6773 if (IS (p, MODE_DECLARATION)) {
6774 victal_check_mode_dec (SUB (p));
6775 } else if (IS (p, VARIABLE_DECLARATION)) {
6776 victal_check_variable_dec (SUB (p));
6777 } else if (IS (p, IDENTITY_DECLARATION)) {
6778 victal_check_identity_dec (SUB (p));
6779 } else if (IS (p, GENERATOR)) {
6780 victal_check_generator (SUB (p));
6781 } else if (IS (p, ROUTINE_TEXT)) {
6782 victal_check_routine_text (SUB (p));
6783 } else if (IS (p, OPERATOR_PLAN)) {
6784 victal_check_operator_dec (SUB (p));
6785 } else if (IS (p, CAST)) {
6786 victal_check_cast (SUB (p));
6787 } else {
6788 victal_checker (SUB (p));
6789 }
6790 }
6791 }
6792
6793 /****************************************************/
6794 /* Mode collection, equivalencing and derived modes */
6795 /****************************************************/
6796
6797 /*************************/
6798 /* Mode service routines */
6799 /*************************/
6800
6801 /**
6802 @brief Reset moid.
6803 @param p Node in syntax tree.
6804 **/
6805
6806 static void
reset_moid_tree(NODE_T * p)6807 reset_moid_tree (NODE_T * p)
6808 {
6809 for (; p != NO_NODE; FORWARD (p)) {
6810 MOID (p) = NO_MOID;
6811 reset_moid_tree (SUB (p));
6812 }
6813 }
6814
6815 /**
6816 @brief Renumber moids.
6817 @param p Moid list.
6818 @param n Index.
6819 **/
6820
6821 void
renumber_moids(MOID_T * p,int n)6822 renumber_moids (MOID_T * p, int n)
6823 {
6824 if (p != NO_MOID) {
6825 NUMBER (p) = n;
6826 renumber_moids (NEXT (p), n + 1);
6827 }
6828 }
6829
6830 /**************************************************/
6831 /* Routines for establishing equivalence of modes */
6832 /* Routines for adding modes */
6833 /**************************************************/
6834
6835 /*
6836 After the initial version of the mode equivalencer was made to work (1993), I
6837 found: Algol Bulletin 30.3.3 C.H.A. Koster: On infinite modes, 86-89 [1969],
6838 which essentially concurs with the algorithm on mode equivalence I wrote (and
6839 which is still here). It is basic logic anyway: prove equivalence of things
6840 assuming their equivalence.
6841 */
6842
6843 /**
6844 @brief Whether packs are equivalent, same sequence of equivalence modes.
6845 @param s Pack 1.
6846 @param t Pack 2.
6847 @return See brief description.
6848 **/
6849
6850 static BOOL_T
is_packs_equivalent(PACK_T * s,PACK_T * t)6851 is_packs_equivalent (PACK_T * s, PACK_T * t)
6852 {
6853 for (; s != NO_PACK && t != NO_PACK; FORWARD (s), FORWARD (t)) {
6854 if (!is_modes_equivalent (MOID (s), MOID (t))) {
6855 return (A68_FALSE);
6856 }
6857 if (TEXT (s) != TEXT (t)) {
6858 return (A68_FALSE);
6859 }
6860 }
6861 return ((BOOL_T) (s == NO_PACK && t == NO_PACK));
6862 }
6863
6864 /**
6865 @brief Whether packs are equivalent, must be subsets.
6866 @param s Pack 1.
6867 @param t Pack 2.
6868 @return See brief description.
6869 **/
6870
6871 static BOOL_T
is_united_packs_equivalent(PACK_T * s,PACK_T * t)6872 is_united_packs_equivalent (PACK_T * s, PACK_T * t)
6873 {
6874 PACK_T *p, *q;
6875 BOOL_T f;
6876 /* whether s is a subset of t ... */
6877 for (p = s; p != NO_PACK; FORWARD (p)) {
6878 for (f = A68_FALSE, q = t; q != NO_PACK && !f; FORWARD (q)) {
6879 f = is_modes_equivalent (MOID (p), MOID (q));
6880 }
6881 if (!f) {
6882 return (A68_FALSE);
6883 }
6884 }
6885 /* ... and whether t is a subset of s */
6886 for (p = t; p != NO_PACK; FORWARD (p)) {
6887 for (f = A68_FALSE, q = s; q != NO_PACK && !f; FORWARD (q)) {
6888 f = is_modes_equivalent (MOID (p), MOID (q));
6889 }
6890 if (!f) {
6891 return (A68_FALSE);
6892 }
6893 }
6894 return (A68_TRUE);
6895 }
6896
6897 /**
6898 @brief Whether moids a and b are structurally equivalent.
6899 @param a Moid.
6900 @param b Moid.
6901 @return See brief description.
6902 **/
6903
6904 BOOL_T
is_modes_equivalent(MOID_T * a,MOID_T * b)6905 is_modes_equivalent (MOID_T * a, MOID_T * b)
6906 {
6907 if (a == NO_MOID || b == NO_MOID) {
6908 /* Modes can be NO_MOID in partial argument lists */
6909 return (A68_FALSE);
6910 } else if (a == b) {
6911 return (A68_TRUE);
6912 } else if (a == MODE (ERROR) || b == MODE (ERROR)) {
6913 return (A68_FALSE);
6914 } else if (ATTRIBUTE (a) != ATTRIBUTE (b)) {
6915 return (A68_FALSE);
6916 } else if (DIM (a) != DIM (b)) {
6917 return (A68_FALSE);
6918 } else if (IS (a, STANDARD)) {
6919 return ((BOOL_T) (a == b));
6920 } else if (EQUIVALENT (a) == b || EQUIVALENT (b) == a) {
6921 return (A68_TRUE);
6922 } else if (is_postulated_pair (top_postulate, a, b) || is_postulated_pair (top_postulate, b, a)) {
6923 return (A68_TRUE);
6924 } else if (IS (a, INDICANT)) {
6925 if (NODE (a) == NO_NODE || NODE (b) == NO_NODE) {
6926 return (A68_FALSE);
6927 } else {
6928 return (NODE (a) == NODE (b));
6929 }
6930 }
6931 switch (ATTRIBUTE (a)) {
6932 case REF_SYMBOL:
6933 case ROW_SYMBOL:
6934 case FLEX_SYMBOL:{
6935 return (is_modes_equivalent (SUB (a), SUB (b)));
6936 }
6937 }
6938 if (IS (a, PROC_SYMBOL) && PACK (a) == NO_PACK && PACK (b) == NO_PACK) {
6939 return (is_modes_equivalent (SUB (a), SUB (b)));
6940 } else if (IS (a, STRUCT_SYMBOL)) {
6941 POSTULATE_T *save;
6942 BOOL_T z;
6943 save = top_postulate;
6944 make_postulate (&top_postulate, a, b);
6945 z = is_packs_equivalent (PACK (a), PACK (b));
6946 free_postulate_list (top_postulate, save);
6947 top_postulate = save;
6948 return (z);
6949 } else if (IS (a, UNION_SYMBOL)) {
6950 return (is_united_packs_equivalent (PACK (a), PACK (b)));
6951 } else if (IS (a, PROC_SYMBOL) && PACK (a) != NO_PACK && PACK (b) != NO_PACK) {
6952 POSTULATE_T *save;
6953 BOOL_T z;
6954 save = top_postulate;
6955 make_postulate (&top_postulate, a, b);
6956 z = is_modes_equivalent (SUB (a), SUB (b));
6957 if (z) {
6958 z = is_packs_equivalent (PACK (a), PACK (b));
6959 }
6960 free_postulate_list (top_postulate, save);
6961 top_postulate = save;
6962 return (z);
6963 } else if (IS (a, SERIES_MODE) || IS (a, STOWED_MODE)) {
6964 return (is_packs_equivalent (PACK (a), PACK (b)));
6965 }
6966 return (A68_FALSE);
6967 }
6968
6969 /**
6970 @brief Whether modes 1 and 2 are structurally equivalent.
6971 @param p Mode 1.
6972 @param q Mode 2.
6973 @return See brief description.
6974 **/
6975
6976 static BOOL_T
prove_moid_equivalence(MOID_T * p,MOID_T * q)6977 prove_moid_equivalence (MOID_T * p, MOID_T * q)
6978 {
6979 /* Prove two modes to be equivalent under assumption that they indeed are */
6980 POSTULATE_T *save = top_postulate;
6981 BOOL_T z = is_modes_equivalent (p, q);
6982 free_postulate_list (top_postulate, save);
6983 top_postulate = save;
6984 return (z);
6985 }
6986
6987 /**
6988 @brief Register mode in the global mode table, if mode is unique.
6989 @param z Mode table.
6990 @param u Mode to enter.
6991 @return Mode table entry.
6992 **/
6993
6994 static MOID_T *
register_extra_mode(MOID_T ** z,MOID_T * u)6995 register_extra_mode (MOID_T ** z, MOID_T * u)
6996 {
6997 MOID_T *head = TOP_MOID (&program);
6998 /* If we already know this mode, return the existing entry; otherwise link it in */
6999 for (; head != NO_MOID; FORWARD (head)) {
7000 if (prove_moid_equivalence (head, u)) {
7001 return (head);
7002 }
7003 }
7004 /* Link to chain and exit */
7005 NUMBER (u) = mode_count++;
7006 NEXT (u) = (*z);
7007 return (*z = u);
7008 }
7009
7010 /**
7011 @brief Add mode "sub" to chain "z".
7012 @param z Chain to insert into.
7013 @param att Attribute.
7014 @param dim Dimension.
7015 @param node Node.
7016 @param sub Subordinate mode.
7017 @param pack Pack.
7018 @return New entry.
7019 **/
7020
7021 MOID_T *
add_mode(MOID_T ** z,int att,int dim,NODE_T * node,MOID_T * sub,PACK_T * pack)7022 add_mode (MOID_T ** z, int att, int dim, NODE_T * node, MOID_T * sub, PACK_T * pack)
7023 {
7024 MOID_T *new_mode = new_moid ();
7025 ABEND (att == REF_SYMBOL && sub == NO_MOID, ERROR_INTERNAL_CONSISTENCY, "store REF NULL");
7026 ABEND (att == FLEX_SYMBOL && sub == NO_MOID, ERROR_INTERNAL_CONSISTENCY, "store FLEX NULL");
7027 ABEND (att == ROW_SYMBOL && sub == NO_MOID, ERROR_INTERNAL_CONSISTENCY, "store [] NULL");
7028 USE (new_mode) = A68_FALSE;
7029 SIZE (new_mode) = 0;
7030 ATTRIBUTE (new_mode) = att;
7031 DIM (new_mode) = dim;
7032 NODE (new_mode) = node;
7033 HAS_ROWS (new_mode) = (BOOL_T) (att == ROW_SYMBOL);
7034 SUB (new_mode) = sub;
7035 PACK (new_mode) = pack;
7036 NEXT (new_mode) = NO_MOID;
7037 EQUIVALENT (new_mode) = NO_MOID;
7038 SLICE (new_mode) = NO_MOID;
7039 DEFLEXED (new_mode) = NO_MOID;
7040 NAME (new_mode) = NO_MOID;
7041 MULTIPLE (new_mode) = NO_MOID;
7042 ROWED (new_mode) = NO_MOID;
7043 return (register_extra_mode (z, new_mode));
7044 }
7045
7046 /**
7047 @brief Contract a UNION.
7048 @param u United mode.
7049 **/
7050
7051 static void
contract_union(MOID_T * u)7052 contract_union (MOID_T * u)
7053 {
7054 PACK_T *s = PACK (u);
7055 for (; s != NO_PACK; FORWARD (s)) {
7056 PACK_T *t = s;
7057 while (t != NO_PACK) {
7058 if (NEXT (t) != NO_PACK && MOID (NEXT (t)) == MOID (s)) {
7059 MOID (t) = MOID (t);
7060 NEXT (t) = NEXT_NEXT (t);
7061 } else {
7062 FORWARD (t);
7063 }
7064 }
7065 }
7066 }
7067
7068 /**
7069 @brief Absorb UNION pack.
7070 @param u Pack.
7071 @return Absorbed pack.
7072 **/
7073
7074 static PACK_T *
absorb_union_pack(PACK_T * u)7075 absorb_union_pack (PACK_T * u)
7076 {
7077 BOOL_T go_on;
7078 PACK_T *t, *z;
7079 do {
7080 z = NO_PACK;
7081 go_on = A68_FALSE;
7082 for (t = u; t != NO_PACK; FORWARD (t)) {
7083 if (IS (MOID (t), UNION_SYMBOL)) {
7084 PACK_T *s;
7085 go_on = A68_TRUE;
7086 for (s = PACK (MOID (t)); s != NO_PACK; FORWARD (s)) {
7087 (void) add_mode_to_pack (&z, MOID (s), NO_TEXT, NODE (s));
7088 }
7089 } else {
7090 (void) add_mode_to_pack (&z, MOID (t), NO_TEXT, NODE (t));
7091 }
7092 }
7093 u = z;
7094 } while (go_on);
7095 return (z);
7096 }
7097
7098 /**
7099 @brief Absorb nested series modes recursively.
7100 @param p Mode.
7101 **/
7102
7103 static void
absorb_series_pack(MOID_T ** p)7104 absorb_series_pack (MOID_T ** p)
7105 {
7106 BOOL_T go_on;
7107 do {
7108 PACK_T *z = NO_PACK, *t;
7109 go_on = A68_FALSE;
7110 for (t = PACK (*p); t != NO_PACK; FORWARD (t)) {
7111 if (MOID (t) != NO_MOID && IS (MOID (t), SERIES_MODE)) {
7112 PACK_T *s;
7113 go_on = A68_TRUE;
7114 for (s = PACK (MOID (t)); s != NO_PACK; FORWARD (s)) {
7115 add_mode_to_pack (&z, MOID (s), NO_TEXT, NODE (s));
7116 }
7117 } else {
7118 add_mode_to_pack (&z, MOID (t), NO_TEXT, NODE (t));
7119 }
7120 }
7121 PACK (*p) = z;
7122 } while (go_on);
7123 }
7124
7125 /**
7126 @brief Absorb nested series and united modes recursively.
7127 @param p Mode.
7128 **/
7129
7130 static void
absorb_series_union_pack(MOID_T ** p)7131 absorb_series_union_pack (MOID_T ** p)
7132 {
7133 BOOL_T go_on;
7134 do {
7135 PACK_T *z = NO_PACK, *t;
7136 go_on = A68_FALSE;
7137 for (t = PACK (*p); t != NO_PACK; FORWARD (t)) {
7138 if (MOID (t) != NO_MOID && (IS (MOID (t), SERIES_MODE) || IS (MOID (t), UNION_SYMBOL))) {
7139 PACK_T *s;
7140 go_on = A68_TRUE;
7141 for (s = PACK (MOID (t)); s != NO_PACK; FORWARD (s)) {
7142 add_mode_to_pack (&z, MOID (s), NO_TEXT, NODE (s));
7143 }
7144 } else {
7145 add_mode_to_pack (&z, MOID (t), NO_TEXT, NODE (t));
7146 }
7147 }
7148 PACK (*p) = z;
7149 } while (go_on);
7150 }
7151
7152 /**
7153 @brief Make SERIES (u, v).
7154 @param u Mode 1.
7155 @param v Mode 2.
7156 \return SERIES (u, v)
7157 **/
7158
7159 static MOID_T *
make_series_from_moids(MOID_T * u,MOID_T * v)7160 make_series_from_moids (MOID_T * u, MOID_T * v)
7161 {
7162 MOID_T *x = new_moid ();
7163 ATTRIBUTE (x) = SERIES_MODE;
7164 add_mode_to_pack (&(PACK (x)), u, NO_TEXT, NODE (u));
7165 add_mode_to_pack (&(PACK (x)), v, NO_TEXT, NODE (v));
7166 absorb_series_pack (&x);
7167 DIM (x) = count_pack_members (PACK (x));
7168 (void) register_extra_mode (&TOP_MOID (&program), x);
7169 if (DIM (x) == 1) {
7170 return (MOID (PACK (x)));
7171 } else {
7172 return (x);
7173 }
7174 }
7175
7176 /**
7177 @brief Absorb firmly related unions in mode.
7178 @param m United mode.
7179 @return Absorbed "m".
7180 **/
7181
7182 static MOID_T *
absorb_related_subsets(MOID_T * m)7183 absorb_related_subsets (MOID_T * m)
7184 {
7185 /*
7186 For instance invalid UNION (PROC REF UNION (A, B), A, B) -> valid UNION (A, B),
7187 which is used in balancing conformity clauses.
7188 */
7189 int mods;
7190 do {
7191 PACK_T *u = NO_PACK, *v;
7192 mods = 0;
7193 for (v = PACK (m); v != NO_PACK; FORWARD (v)) {
7194 MOID_T *n = depref_completely (MOID (v));
7195 if (IS (n, UNION_SYMBOL) && is_subset (n, m, SAFE_DEFLEXING)) {
7196 /* Unpack it */
7197 PACK_T *w;
7198 for (w = PACK (n); w != NO_PACK; FORWARD (w)) {
7199 add_mode_to_pack (&u, MOID (w), NO_TEXT, NODE (w));
7200 }
7201 mods++;
7202 } else {
7203 add_mode_to_pack (&u, MOID (v), NO_TEXT, NODE (v));
7204 }
7205 }
7206 PACK (m) = absorb_union_pack (u);
7207 } while (mods != 0);
7208 return (m);
7209 }
7210
7211 /**
7212 @brief Make united mode, from mode that is a SERIES (..).
7213 @param m Series mode.
7214 @return Mode table entry.
7215 **/
7216
7217 static MOID_T *
make_united_mode(MOID_T * m)7218 make_united_mode (MOID_T * m)
7219 {
7220 MOID_T *u;
7221 PACK_T *w;
7222 int mods;
7223 if (m == NO_MOID) {
7224 return (MODE (ERROR));
7225 } else if (ATTRIBUTE (m) != SERIES_MODE) {
7226 return (m);
7227 }
7228 /* Do not unite a single UNION */
7229 if (DIM (m) == 1 && IS (MOID (PACK (m)), UNION_SYMBOL)) {
7230 return (MOID (PACK (m)));
7231 }
7232 /* Straighten the series */
7233 absorb_series_union_pack (&m);
7234 /* Copy the series into a UNION */
7235 u = new_moid ();
7236 ATTRIBUTE (u) = UNION_SYMBOL;
7237 PACK (u) = NO_PACK;
7238 w = PACK (m);
7239 for (w = PACK (m); w != NO_PACK; FORWARD (w)) {
7240 add_mode_to_pack (&(PACK (u)), MOID (w), NO_TEXT, NODE (m));
7241 }
7242 /* Absorb and contract the new UNION */
7243 do {
7244 mods = 0;
7245 absorb_series_union_pack (&u);
7246 DIM (u) = count_pack_members (PACK (u));
7247 PACK (u) = absorb_union_pack (PACK (u));
7248 contract_union (u);
7249 } while (mods != 0);
7250 /* A UNION of one mode is that mode itself */
7251 if (DIM (u) == 1) {
7252 return (MOID (PACK (u)));
7253 } else {
7254 return (register_extra_mode (&TOP_MOID (&program), u));
7255 }
7256 }
7257
7258 /**
7259 @brief Add row and its slices to chain, recursively.
7260 @param p Chain to insert into.
7261 @param dim Dimension.
7262 @param sub Mode of slice.
7263 @param n Node in syntax tree.
7264 @param derivate Whether derived, ie. not in the source.
7265 @return Pointer to entry.
7266 **/
7267
7268 static MOID_T *
add_row(MOID_T ** p,int dim,MOID_T * sub,NODE_T * n,BOOL_T derivate)7269 add_row (MOID_T ** p, int dim, MOID_T * sub, NODE_T * n, BOOL_T derivate)
7270 {
7271 MOID_T *q = add_mode (p, ROW_SYMBOL, dim, n, sub, NO_PACK);
7272 DERIVATE (q) |= derivate;
7273 if (dim > 1) {
7274 SLICE (q) = add_row (&NEXT (q), dim - 1, sub, n, derivate);
7275 } else {
7276 SLICE (q) = sub;
7277 }
7278 return (q);
7279 }
7280
7281 /**
7282 @brief Add a moid to a pack, maybe with a (field) name.
7283 @param p Pack.
7284 @param m Moid to add.
7285 @param text Field name.
7286 @param node Node in syntax tree.
7287 **/
7288
7289 void
add_mode_to_pack(PACK_T ** p,MOID_T * m,char * text,NODE_T * node)7290 add_mode_to_pack (PACK_T ** p, MOID_T * m, char *text, NODE_T * node)
7291 {
7292 PACK_T *z = new_pack ();
7293 MOID (z) = m;
7294 TEXT (z) = text;
7295 NODE (z) = node;
7296 NEXT (z) = *p;
7297 PREVIOUS (z) = NO_PACK;
7298 if (NEXT (z) != NO_PACK) {
7299 PREVIOUS (NEXT (z)) = z;
7300 }
7301 /* Link in chain */
7302 *p = z;
7303 }
7304
7305 /**
7306 @brief Add a moid to a pack, maybe with a (field) name.
7307 @param p Pack.
7308 @param m Moid to add.
7309 @param text Field name.
7310 @param node Node in syntax tree.
7311 **/
7312
7313 void
add_mode_to_pack_end(PACK_T ** p,MOID_T * m,char * text,NODE_T * node)7314 add_mode_to_pack_end (PACK_T ** p, MOID_T * m, char *text, NODE_T * node)
7315 {
7316 PACK_T *z = new_pack ();
7317 MOID (z) = m;
7318 TEXT (z) = text;
7319 NODE (z) = node;
7320 NEXT (z) = NO_PACK;
7321 if (NEXT (z) != NO_PACK) {
7322 PREVIOUS (NEXT (z)) = z;
7323 }
7324 /* Link in chain */
7325 while ((*p) != NO_PACK) {
7326 p = &(NEXT (*p));
7327 }
7328 PREVIOUS (z) = (*p);
7329 (*p) = z;
7330 }
7331
7332 /**
7333 @brief Absorb UNION members.
7334 @param m First MOID.
7335 **/
7336
7337 static void
absorb_unions(MOID_T * m)7338 absorb_unions (MOID_T * m)
7339 {
7340 /*
7341 UNION (A, UNION (B, C)) = UNION (A, B, C) or
7342 UNION (A, UNION (A, B)) = UNION (A, B).
7343 */
7344 for (; m != NO_MOID; FORWARD (m)) {
7345 if (IS (m, UNION_SYMBOL)) {
7346 PACK (m) = absorb_union_pack (PACK (m));
7347 }
7348 }
7349 }
7350
7351
7352 /**
7353 @brief Contract UNIONs .
7354 @param m First MOID.
7355 **/
7356
7357 static void
contract_unions(MOID_T * m)7358 contract_unions (MOID_T * m)
7359 {
7360 /* UNION (A, B, A) -> UNION (A, B) */
7361 for (; m != NO_MOID; FORWARD (m)) {
7362 if (IS (m, UNION_SYMBOL) && EQUIVALENT (m) == NO_MOID) {
7363 contract_union (m);
7364 }
7365 }
7366 }
7367
7368 /***************************************************/
7369 /* Routines to collect MOIDs from the program text */
7370 /***************************************************/
7371
7372 /**
7373 @brief Search standard mode in standard environ.
7374 @param sizety Sizety.
7375 @param indicant Node in syntax tree.
7376 @return Moid entry in standard environ.
7377 **/
7378
7379 static MOID_T *
search_standard_mode(int sizety,NODE_T * indicant)7380 search_standard_mode (int sizety, NODE_T * indicant)
7381 {
7382 MOID_T *p = TOP_MOID (&program);
7383 /* Search standard mode */
7384 for (; p != NO_MOID; FORWARD (p)) {
7385 if (IS (p, STANDARD) && DIM (p) == sizety && NSYMBOL (NODE (p)) == NSYMBOL (indicant)) {
7386 return (p);
7387 }
7388 }
7389 /* Sanity check
7390 if (sizety == -2 || sizety == 2) {
7391 return (NO_MOID);
7392 }
7393 */
7394 /* Map onto greater precision */
7395 if (sizety < 0) {
7396 return (search_standard_mode (sizety + 1, indicant));
7397 } else if (sizety > 0) {
7398 return (search_standard_mode (sizety - 1, indicant));
7399 } else {
7400 return (NO_MOID);
7401 }
7402 }
7403
7404 /**
7405 @brief Collect mode from STRUCT field.
7406 @param p Node in syntax tree.
7407 @param u Pack to insert to.
7408 **/
7409
7410 static void
get_mode_from_struct_field(NODE_T * p,PACK_T ** u)7411 get_mode_from_struct_field (NODE_T * p, PACK_T ** u)
7412 {
7413 if (p != NO_NODE) {
7414 if (IS (p, IDENTIFIER)) {
7415 ATTRIBUTE (p) = FIELD_IDENTIFIER;
7416 (void) add_mode_to_pack (u, NO_MOID, NSYMBOL (p), p);
7417 } else if (IS (p, DECLARER)) {
7418 MOID_T *new_one = get_mode_from_declarer (p);
7419 PACK_T *t;
7420 get_mode_from_struct_field (NEXT (p), u);
7421 for (t = *u; t && MOID (t) == NO_MOID; FORWARD (t)) {
7422 MOID (t) = new_one;
7423 MOID (NODE (t)) = new_one;
7424 }
7425 } else {
7426 get_mode_from_struct_field (NEXT (p), u);
7427 get_mode_from_struct_field (SUB (p), u);
7428 }
7429 }
7430 }
7431
7432 /**
7433 @brief Collect MODE from formal pack.
7434 @param p Node in syntax tree.
7435 @param u Pack to insert to.
7436 **/
7437
7438 static void
get_mode_from_formal_pack(NODE_T * p,PACK_T ** u)7439 get_mode_from_formal_pack (NODE_T * p, PACK_T ** u)
7440 {
7441 if (p != NO_NODE) {
7442 if (IS (p, DECLARER)) {
7443 MOID_T *z;
7444 get_mode_from_formal_pack (NEXT (p), u);
7445 z = get_mode_from_declarer (p);
7446 (void) add_mode_to_pack (u, z, NO_TEXT, p);
7447 } else {
7448 get_mode_from_formal_pack (NEXT (p), u);
7449 get_mode_from_formal_pack (SUB (p), u);
7450 }
7451 }
7452 }
7453
7454 /**
7455 @brief Collect MODE or VOID from formal UNION pack.
7456 @param p Node in syntax tree.
7457 @param u Pack to insert to.
7458 **/
7459
7460 static void
get_mode_from_union_pack(NODE_T * p,PACK_T ** u)7461 get_mode_from_union_pack (NODE_T * p, PACK_T ** u)
7462 {
7463 if (p != NO_NODE) {
7464 if (IS (p, DECLARER) || IS (p, VOID_SYMBOL)) {
7465 MOID_T *z;
7466 get_mode_from_union_pack (NEXT (p), u);
7467 z = get_mode_from_declarer (p);
7468 (void) add_mode_to_pack (u, z, NO_TEXT, p);
7469 } else {
7470 get_mode_from_union_pack (NEXT (p), u);
7471 get_mode_from_union_pack (SUB (p), u);
7472 }
7473 }
7474 }
7475
7476 /**
7477 @brief Collect mode from PROC, OP pack.
7478 @param p Node in syntax tree.
7479 @param u Pack to insert to.
7480 **/
7481
7482 static void
get_mode_from_routine_pack(NODE_T * p,PACK_T ** u)7483 get_mode_from_routine_pack (NODE_T * p, PACK_T ** u)
7484 {
7485 if (p != NO_NODE) {
7486 if (IS (p, IDENTIFIER)) {
7487 (void) add_mode_to_pack (u, NO_MOID, NO_TEXT, p);
7488 } else if (IS (p, DECLARER)) {
7489 MOID_T *z = get_mode_from_declarer (p);
7490 PACK_T *t = *u;
7491 for (; t != NO_PACK && MOID (t) == NO_MOID; FORWARD (t)) {
7492 MOID (t) = z;
7493 MOID (NODE (t)) = z;
7494 }
7495 (void) add_mode_to_pack (u, z, NO_TEXT, p);
7496 } else {
7497 get_mode_from_routine_pack (NEXT (p), u);
7498 get_mode_from_routine_pack (SUB (p), u);
7499 }
7500 }
7501 }
7502
7503 /**
7504 @brief Collect MODE from DECLARER.
7505 @param p Node in syntax tree.
7506 @return Mode table entry.
7507 **/
7508
7509 static MOID_T *
get_mode_from_declarer(NODE_T * p)7510 get_mode_from_declarer (NODE_T * p)
7511 {
7512 if (p == NO_NODE) {
7513 return (NO_MOID);
7514 } else {
7515 if (IS (p, DECLARER)) {
7516 if (MOID (p) != NO_MOID) {
7517 return (MOID (p));
7518 } else {
7519 return (MOID (p) = get_mode_from_declarer (SUB (p)));
7520 }
7521 } else {
7522 if (IS (p, VOID_SYMBOL)) {
7523 MOID (p) = MODE (VOID);
7524 return (MOID (p));
7525 } else if (IS (p, LONGETY)) {
7526 if (whether (p, LONGETY, INDICANT, STOP)) {
7527 int k = count_sizety (SUB (p));
7528 MOID (p) = search_standard_mode (k, NEXT (p));
7529 return (MOID (p));
7530 } else {
7531 return (NO_MOID);
7532 }
7533 } else if (IS (p, SHORTETY)) {
7534 if (whether (p, SHORTETY, INDICANT, STOP)) {
7535 int k = count_sizety (SUB (p));
7536 MOID (p) = search_standard_mode (k, NEXT (p));
7537 return (MOID (p));
7538 } else {
7539 return (NO_MOID);
7540 }
7541 } else if (IS (p, INDICANT)) {
7542 MOID_T *q = search_standard_mode (0, p);
7543 if (q != NO_MOID) {
7544 MOID (p) = q;
7545 } else {
7546 /* Position of definition tells indicants apart */
7547 TAG_T *y = find_tag_global (TABLE (p), INDICANT, NSYMBOL (p));
7548 if (y == NO_TAG) {
7549 diagnostic_node (A68_ERROR, p, ERROR_UNDECLARED_TAG_2, NSYMBOL (p));
7550 } else {
7551 MOID (p) = add_mode (&TOP_MOID (&program), INDICANT, 0, NODE (y), NO_MOID, NO_PACK);
7552 }
7553 }
7554 return (MOID (p));
7555 } else if (IS (p, REF_SYMBOL)) {
7556 MOID_T *new_one = get_mode_from_declarer (NEXT (p));
7557 MOID (p) = add_mode (&TOP_MOID (&program), REF_SYMBOL, 0, p, new_one, NO_PACK);
7558 return (MOID (p));
7559 } else if (IS (p, FLEX_SYMBOL)) {
7560 MOID_T *new_one = get_mode_from_declarer (NEXT (p));
7561 MOID (p) = add_mode (&TOP_MOID (&program), FLEX_SYMBOL, 0, p, new_one, NO_PACK);
7562 SLICE (MOID (p)) = SLICE (new_one);
7563 return (MOID (p));
7564 } else if (IS (p, FORMAL_BOUNDS)) {
7565 MOID_T *new_one = get_mode_from_declarer (NEXT (p));
7566 MOID (p) = add_row (&TOP_MOID (&program), 1 + count_formal_bounds (SUB (p)), new_one, p, A68_FALSE);
7567 return (MOID (p));
7568 } else if (IS (p, BOUNDS)) {
7569 MOID_T *new_one = get_mode_from_declarer (NEXT (p));
7570 MOID (p) = add_row (&TOP_MOID (&program), count_bounds (SUB (p)), new_one, p, A68_FALSE);
7571 return (MOID (p));
7572 } else if (IS (p, STRUCT_SYMBOL)) {
7573 PACK_T *u = NO_PACK;
7574 get_mode_from_struct_field (NEXT (p), &u);
7575 MOID (p) = add_mode (&TOP_MOID (&program), STRUCT_SYMBOL, count_pack_members (u), p, NO_MOID, u);
7576 return (MOID (p));
7577 } else if (IS (p, UNION_SYMBOL)) {
7578 PACK_T *u = NO_PACK;
7579 get_mode_from_union_pack (NEXT (p), &u);
7580 MOID (p) = add_mode (&TOP_MOID (&program), UNION_SYMBOL, count_pack_members (u), p, NO_MOID, u);
7581 return (MOID (p));
7582 } else if (IS (p, PROC_SYMBOL)) {
7583 NODE_T *save = p;
7584 PACK_T *u = NO_PACK;
7585 MOID_T *new_one;
7586 if (IS (NEXT (p), FORMAL_DECLARERS)) {
7587 get_mode_from_formal_pack (SUB_NEXT (p), &u);
7588 FORWARD (p);
7589 }
7590 new_one = get_mode_from_declarer (NEXT (p));
7591 MOID (p) = add_mode (&TOP_MOID (&program), PROC_SYMBOL, count_pack_members (u), save, new_one, u);
7592 MOID (save) = MOID (p);
7593 return (MOID (p));
7594 } else {
7595 return (NO_MOID);
7596 }
7597 }
7598 }
7599 }
7600
7601 /**
7602 @brief Collect MODEs from a routine-text header.
7603 @param p Node in syntax tree.
7604 @return Mode table entry.
7605 **/
7606
7607 static MOID_T *
get_mode_from_routine_text(NODE_T * p)7608 get_mode_from_routine_text (NODE_T * p)
7609 {
7610 PACK_T *u = NO_PACK;
7611 MOID_T *n;
7612 NODE_T *q = p;
7613 if (IS (p, PARAMETER_PACK)) {
7614 get_mode_from_routine_pack (SUB (p), &u);
7615 FORWARD (p);
7616 }
7617 n = get_mode_from_declarer (p);
7618 return (add_mode (&TOP_MOID (&program), PROC_SYMBOL, count_pack_members (u), q, n, u));
7619 }
7620
7621 /**
7622 @brief Collect modes from operator-plan.
7623 @param p Node in syntax tree.
7624 @return Mode table entry.
7625 **/
7626
7627 static MOID_T *
get_mode_from_operator(NODE_T * p)7628 get_mode_from_operator (NODE_T * p)
7629 {
7630 PACK_T *u = NO_PACK;
7631 MOID_T *new_one;
7632 NODE_T *save = p;
7633 if (IS (NEXT (p), FORMAL_DECLARERS)) {
7634 get_mode_from_formal_pack (SUB_NEXT (p), &u);
7635 FORWARD (p);
7636 }
7637 new_one = get_mode_from_declarer (NEXT (p));
7638 MOID (p) = add_mode (&TOP_MOID (&program), PROC_SYMBOL, count_pack_members (u), save, new_one, u);
7639 return (MOID (p));
7640 }
7641
7642 /**
7643 @brief Collect mode from denotation.
7644 @param p Node in syntax tree.
7645 @param sizety Size of denotation.
7646 @return Mode table entry.
7647 **/
7648
7649 static void
get_mode_from_denotation(NODE_T * p,int sizety)7650 get_mode_from_denotation (NODE_T * p, int sizety)
7651 {
7652 if (p != NO_NODE) {
7653 if (IS (p, ROW_CHAR_DENOTATION)) {
7654 if (strlen (NSYMBOL (p)) == 1) {
7655 MOID (p) = MODE (CHAR);
7656 } else {
7657 MOID (p) = MODE (ROW_CHAR);
7658 }
7659 } else if (IS (p, TRUE_SYMBOL) || IS (p, FALSE_SYMBOL)) {
7660 MOID (p) = MODE (BOOL);
7661 } else if (IS (p, INT_DENOTATION)) {
7662 if (sizety == 0) {
7663 MOID (p) = MODE (INT);
7664 } else if (sizety == 1) {
7665 MOID (p) = MODE (LONG_INT);
7666 } else if (sizety == 2) {
7667 MOID (p) = MODE (LONGLONG_INT);
7668 } else {
7669 MOID (p) = (sizety > 0 ? MODE (LONGLONG_INT) : MODE (INT));
7670 }
7671 } else if (IS (p, REAL_DENOTATION)) {
7672 if (sizety == 0) {
7673 MOID (p) = MODE (REAL);
7674 } else if (sizety == 1) {
7675 MOID (p) = MODE (LONG_REAL);
7676 } else if (sizety == 2) {
7677 MOID (p) = MODE (LONGLONG_REAL);
7678 } else {
7679 MOID (p) = (sizety > 0 ? MODE (LONGLONG_REAL) : MODE (REAL));
7680 }
7681 } else if (IS (p, BITS_DENOTATION)) {
7682 if (sizety == 0) {
7683 MOID (p) = MODE (BITS);
7684 } else if (sizety == 1) {
7685 MOID (p) = MODE (LONG_BITS);
7686 } else if (sizety == 2) {
7687 MOID (p) = MODE (LONGLONG_BITS);
7688 } else {
7689 MOID (p) = (sizety > 0 ? MODE (LONGLONG_BITS) : MODE (BITS));
7690 }
7691 } else if (IS (p, LONGETY) || IS (p, SHORTETY)) {
7692 get_mode_from_denotation (NEXT (p), count_sizety (SUB (p)));
7693 MOID (p) = MOID (NEXT (p));
7694 } else if (IS (p, EMPTY_SYMBOL)) {
7695 MOID (p) = MODE (VOID);
7696 }
7697 }
7698 }
7699
7700 /**
7701 @brief Collect modes from the syntax tree.
7702 @param p Node in syntax tree.
7703 @param attribute
7704 **/
7705
7706 static void
get_modes_from_tree(NODE_T * p,int attribute)7707 get_modes_from_tree (NODE_T * p, int attribute)
7708 {
7709 NODE_T *q;
7710 for (q = p; q != NO_NODE; FORWARD (q)) {
7711 if (IS (q, VOID_SYMBOL)) {
7712 MOID (q) = MODE (VOID);
7713 } else if (IS (q, DECLARER)) {
7714 if (attribute == VARIABLE_DECLARATION) {
7715 MOID_T *new_one = get_mode_from_declarer (q);
7716 MOID (q) = add_mode (&TOP_MOID (&program), REF_SYMBOL, 0, NO_NODE, new_one, NO_PACK);
7717 } else {
7718 MOID (q) = get_mode_from_declarer (q);
7719 }
7720 } else if (IS (q, ROUTINE_TEXT)) {
7721 MOID (q) = get_mode_from_routine_text (SUB (q));
7722 } else if (IS (q, OPERATOR_PLAN)) {
7723 MOID (q) = get_mode_from_operator (SUB (q));
7724 } else if (is_one_of (q, LOC_SYMBOL, HEAP_SYMBOL, NEW_SYMBOL, STOP)) {
7725 if (attribute == GENERATOR) {
7726 MOID_T *new_one = get_mode_from_declarer (NEXT (q));
7727 MOID (NEXT (q)) = new_one;
7728 MOID (q) = add_mode (&TOP_MOID (&program), REF_SYMBOL, 0, NO_NODE, new_one, NO_PACK);
7729 }
7730 } else {
7731 if (attribute == DENOTATION) {
7732 get_mode_from_denotation (q, 0);
7733 }
7734 }
7735 }
7736 if (attribute != DENOTATION) {
7737 for (q = p; q != NO_NODE; FORWARD (q)) {
7738 if (SUB (q) != NO_NODE) {
7739 get_modes_from_tree (SUB (q), ATTRIBUTE (q));
7740 }
7741 }
7742 }
7743 }
7744
7745 /**
7746 @brief Collect modes from proc variables.
7747 @param p Node in syntax tree.
7748 **/
7749
7750 static void
get_mode_from_proc_variables(NODE_T * p)7751 get_mode_from_proc_variables (NODE_T * p)
7752 {
7753 if (p != NO_NODE) {
7754 if (IS (p, PROCEDURE_VARIABLE_DECLARATION)) {
7755 get_mode_from_proc_variables (SUB (p));
7756 get_mode_from_proc_variables (NEXT (p));
7757 } else if (IS (p, QUALIFIER) || IS (p, PROC_SYMBOL) || IS (p, COMMA_SYMBOL)) {
7758 get_mode_from_proc_variables (NEXT (p));
7759 } else if (IS (p, DEFINING_IDENTIFIER)) {
7760 MOID_T *new_one = MOID (NEXT_NEXT (p));
7761 MOID (p) = add_mode (&TOP_MOID (&program), REF_SYMBOL, 0, p, new_one, NO_PACK);
7762 }
7763 }
7764 }
7765
7766 /**
7767 @brief Collect modes from proc variable declarations.
7768 @param p Node in syntax tree.
7769 **/
7770
7771 static void
get_mode_from_proc_var_declarations_tree(NODE_T * p)7772 get_mode_from_proc_var_declarations_tree (NODE_T * p)
7773 {
7774 for (; p != NO_NODE; FORWARD (p)) {
7775 get_mode_from_proc_var_declarations_tree (SUB (p));
7776 if (IS (p, PROCEDURE_VARIABLE_DECLARATION)) {
7777 get_mode_from_proc_variables (p);
7778 }
7779 }
7780 }
7781
7782 /**********************************/
7783 /* Various routines to test modes */
7784 /**********************************/
7785
7786 /**
7787 @brief Whether a mode declaration refers to self or relates to void.
7788 @param def Entry of indicant in mode table, NO_MOID if z is an applied mode.
7789 @param z Mode to check.
7790 @param yin Whether shields YIN.
7791 @param yang Whether shields YANG.
7792 @param video Whether shields VOID .
7793 @return See brief description.
7794 **/
7795
7796 static BOOL_T
is_well_formed(MOID_T * def,MOID_T * z,BOOL_T yin,BOOL_T yang,BOOL_T video)7797 is_well_formed (MOID_T * def, MOID_T * z, BOOL_T yin, BOOL_T yang, BOOL_T video)
7798 {
7799 if (z == NO_MOID) {
7800 return (A68_FALSE);
7801 } else if (yin && yang) {
7802 return (z == MODE (VOID) ? video : A68_TRUE);
7803 } else if (z == MODE (VOID)) {
7804 return (video);
7805 } else if (IS (z, STANDARD)) {
7806 return (A68_TRUE);
7807 } else if (IS (z, INDICANT)) {
7808 if (def == NO_MOID) {
7809 /* Check an applied indicant for relation to VOID */
7810 while (z != NO_MOID) {
7811 z = EQUIVALENT (z);
7812 }
7813 if (z == MODE (VOID)) {
7814 return (video);
7815 } else {
7816 return (A68_TRUE);
7817 }
7818 } else {
7819 if (z == def || USE (z)) {
7820 return (yin && yang);
7821 } else {
7822 BOOL_T wwf;
7823 USE (z) = A68_TRUE;
7824 wwf = is_well_formed (def, EQUIVALENT (z), yin, yang, video);
7825 USE (z) = A68_FALSE;
7826 return (wwf);
7827 }
7828 }
7829 } else if (IS (z, REF_SYMBOL)) {
7830 return (is_well_formed (def, SUB (z), A68_TRUE, yang, A68_FALSE));
7831 } else if (IS (z, PROC_SYMBOL)) {
7832 return (PACK (z) != NO_PACK ? A68_TRUE : is_well_formed (def, SUB (z), A68_TRUE, yang, A68_TRUE));
7833 } else if (IS (z, ROW_SYMBOL)) {
7834 return (is_well_formed (def, SUB (z), yin, yang, A68_FALSE));
7835 } else if (IS (z, FLEX_SYMBOL)) {
7836 return (is_well_formed (def, SUB (z), yin, yang, A68_FALSE));
7837 } else if (IS (z, STRUCT_SYMBOL)) {
7838 PACK_T *s = PACK (z);
7839 for (; s != NO_PACK; FORWARD (s)) {
7840 if (!is_well_formed (def, MOID (s), yin, A68_TRUE, A68_FALSE)) {
7841 return (A68_FALSE);
7842 }
7843 }
7844 return (A68_TRUE);
7845 } else if (IS (z, UNION_SYMBOL)) {
7846 PACK_T *s = PACK (z);
7847 for (; s != NO_PACK; FORWARD (s)) {
7848 if (!is_well_formed (def, MOID (s), yin, yang, A68_TRUE)) {
7849 return (A68_FALSE);
7850 }
7851 }
7852 return (A68_TRUE);
7853 } else {
7854 return (A68_FALSE);
7855 }
7856 }
7857
7858 /**
7859 @brief Replace a mode by its equivalent mode (walk chain).
7860 @param q Mode to track.
7861 **/
7862
7863 static void
resolve_eq_members(MOID_T * q)7864 resolve_eq_members (MOID_T * q)
7865 {
7866 PACK_T *p;
7867 resolve_equivalent (&SUB (q));
7868 resolve_equivalent (&DEFLEXED (q));
7869 resolve_equivalent (&MULTIPLE (q));
7870 resolve_equivalent (&NAME (q));
7871 resolve_equivalent (&SLICE (q));
7872 resolve_equivalent (&TRIM (q));
7873 resolve_equivalent (&ROWED (q));
7874 for (p = PACK (q); p != NO_PACK; FORWARD (p)) {
7875 resolve_equivalent (&MOID (p));
7876 }
7877 }
7878
7879 /**
7880 @brief Track equivalent tags.
7881 @param z Tag to track.
7882 **/
7883
7884 static void
resolve_eq_tags(TAG_T * z)7885 resolve_eq_tags (TAG_T * z)
7886 {
7887 for (; z != NO_TAG; FORWARD (z)) {
7888 if (MOID (z) != NO_MOID) {
7889 resolve_equivalent (&MOID (z));
7890 }
7891 }
7892 }
7893
7894 /**
7895 @brief Bind modes in syntax tree.
7896 @param p Node in syntax tree.
7897 **/
7898
7899 static void
bind_modes(NODE_T * p)7900 bind_modes (NODE_T * p)
7901 {
7902 for (; p != NO_NODE; FORWARD (p)) {
7903 resolve_equivalent (&MOID (p));
7904 if (SUB (p) != NO_NODE && is_new_lexical_level (p)) {
7905 TABLE_T *s = TABLE (SUB (p));
7906 TAG_T *z = INDICANTS (s);
7907 for (; z != NO_TAG; FORWARD (z)) {
7908 if (NODE (z) != NO_NODE) {
7909 resolve_equivalent (&MOID (NEXT_NEXT (NODE (z))));
7910 MOID (z) = MOID (NEXT_NEXT (NODE (z)));
7911 MOID (NODE (z)) = MOID (z);
7912 }
7913 }
7914 }
7915 bind_modes (SUB (p));
7916 }
7917 }
7918
7919 /*
7920 Routines for calculating subordinates for selections, for instance selection
7921 from REF STRUCT (A) yields REF A fields and selection from [] STRUCT (A) yields
7922 [] A fields.
7923 */
7924
7925 /**
7926 @brief Make name pack.
7927 @param src Source pack.
7928 @param dst Destination pack with REF modes.
7929 @param p Chain to insert new modes into.
7930 **/
7931
7932 static void
make_name_pack(PACK_T * src,PACK_T ** dst,MOID_T ** p)7933 make_name_pack (PACK_T * src, PACK_T ** dst, MOID_T ** p)
7934 {
7935 if (src != NO_PACK) {
7936 MOID_T *z;
7937 make_name_pack (NEXT (src), dst, p);
7938 z = add_mode (p, REF_SYMBOL, 0, NO_NODE, MOID (src), NO_PACK);
7939 (void) add_mode_to_pack (dst, z, TEXT (src), NODE (src));
7940 }
7941 }
7942
7943 /**
7944 @brief Make flex multiple row pack.
7945 @param src Source pack.
7946 @param dst Destination pack with REF modes.
7947 @param p Chain to insert new modes into.
7948 @param dim Dimension.
7949 **/
7950
7951 static void
make_flex_multiple_row_pack(PACK_T * src,PACK_T ** dst,MOID_T ** p,int dim)7952 make_flex_multiple_row_pack (PACK_T * src, PACK_T ** dst, MOID_T ** p, int dim)
7953 {
7954 if (src != NO_PACK) {
7955 MOID_T *z;
7956 make_flex_multiple_row_pack (NEXT (src), dst, p, dim);
7957 z = add_row (p, dim, MOID (src), NO_NODE, A68_FALSE);
7958 z = add_mode (p, FLEX_SYMBOL, 0, NO_NODE, z, NO_PACK);
7959 (void) add_mode_to_pack (dst, z, TEXT (src), NODE (src));
7960 }
7961 }
7962
7963 /**
7964 @brief Make name struct.
7965 @param m Structured mode.
7966 @param p Chain to insert new modes into.
7967 @return Mode table entry.
7968 **/
7969
7970 static MOID_T *
make_name_struct(MOID_T * m,MOID_T ** p)7971 make_name_struct (MOID_T * m, MOID_T ** p)
7972 {
7973 PACK_T *u = NO_PACK;
7974 make_name_pack (PACK (m), &u, p);
7975 return (add_mode (p, STRUCT_SYMBOL, DIM (m), NO_NODE, NO_MOID, u));
7976 }
7977
7978 /**
7979 @brief Make name row.
7980 @param m Rowed mode.
7981 @param p Chain to insert new modes into.
7982 @return Mode table entry.
7983 **/
7984
7985 static MOID_T *
make_name_row(MOID_T * m,MOID_T ** p)7986 make_name_row (MOID_T * m, MOID_T ** p)
7987 {
7988 if (SLICE (m) != NO_MOID) {
7989 return (add_mode (p, REF_SYMBOL, 0, NO_NODE, SLICE (m), NO_PACK));
7990 } else if (SUB (m) != NO_MOID) {
7991 return (add_mode (p, REF_SYMBOL, 0, NO_NODE, SUB (m), NO_PACK));
7992 } else {
7993 return (NO_MOID); /* weird, FLEX INT or so ... */
7994 }
7995 }
7996
7997 /**
7998 @brief Make multiple row pack.
7999 @param src Source pack.
8000 @param dst Destination pack with REF modes.
8001 @param p Chain to insert new modes into.
8002 @param dim Dimension.
8003 **/
8004
8005 static void
make_multiple_row_pack(PACK_T * src,PACK_T ** dst,MOID_T ** p,int dim)8006 make_multiple_row_pack (PACK_T * src, PACK_T ** dst, MOID_T ** p, int dim)
8007 {
8008 if (src != NO_PACK) {
8009 make_multiple_row_pack (NEXT (src), dst, p, dim);
8010 (void) add_mode_to_pack (dst, add_row (p, dim, MOID (src), NO_NODE, A68_FALSE), TEXT (src), NODE (src));
8011 }
8012 }
8013
8014 /**
8015 @brief Make flex multiple struct.
8016 @param m Structured mode.
8017 @param p Chain to insert new modes into.
8018 @param dim Dimension.
8019 @return Mode table entry.
8020 **/
8021
8022 static MOID_T *
make_flex_multiple_struct(MOID_T * m,MOID_T ** p,int dim)8023 make_flex_multiple_struct (MOID_T * m, MOID_T ** p, int dim)
8024 {
8025 PACK_T *u = NO_PACK;
8026 make_flex_multiple_row_pack (PACK (m), &u, p, dim);
8027 return (add_mode (p, STRUCT_SYMBOL, DIM (m), NO_NODE, NO_MOID, u));
8028 }
8029
8030 /**
8031 @brief Make multiple struct.
8032 @param m Structured mode.
8033 @param p Chain to insert new modes into.
8034 @param dim Dimension.
8035 @return Mode table entry.
8036 **/
8037
8038 static MOID_T *
make_multiple_struct(MOID_T * m,MOID_T ** p,int dim)8039 make_multiple_struct (MOID_T * m, MOID_T ** p, int dim)
8040 {
8041 PACK_T *u = NO_PACK;
8042 make_multiple_row_pack (PACK (m), &u, p, dim);
8043 return (add_mode (p, STRUCT_SYMBOL, DIM (m), NO_NODE, NO_MOID, u));
8044 }
8045
8046 /**
8047 @brief Whether mode has row.
8048 @param m Mode under test.
8049 @return See brief description.
8050 **/
8051
8052 static BOOL_T
is_mode_has_row(MOID_T * m)8053 is_mode_has_row (MOID_T * m)
8054 {
8055 if (IS (m, STRUCT_SYMBOL) || IS (m, UNION_SYMBOL)) {
8056 BOOL_T k = A68_FALSE;
8057 PACK_T *p = PACK (m);
8058 for (; p != NO_PACK && k == A68_FALSE; FORWARD (p)) {
8059 HAS_ROWS (MOID (p)) = is_mode_has_row (MOID (p));
8060 k |= (HAS_ROWS (MOID (p)));
8061 }
8062 return (k);
8063 } else {
8064 return ((BOOL_T) (HAS_ROWS (m) || IS (m, ROW_SYMBOL) || IS (m, FLEX_SYMBOL)));
8065 }
8066 }
8067
8068 /**
8069 @brief Compute derived modes.
8070 @param mod Module.
8071 **/
8072
8073 static void
compute_derived_modes(MODULE_T * mod)8074 compute_derived_modes (MODULE_T * mod)
8075 {
8076 MOID_T *z;
8077 int k, len = 0, nlen = 1;
8078 /* UNION things */
8079 absorb_unions (TOP_MOID (mod));
8080 contract_unions (TOP_MOID (mod));
8081 /* The for-statement below prevents an endless loop */
8082 for (k = 1; k <= 10 && len != nlen; k++) {
8083 /* Make deflexed modes */
8084 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8085 if (SUB (z) != NO_MOID) {
8086 if (IS_REF_FLEX (z) && DEFLEXED (SUB_SUB (z)) != NO_MOID) {
8087 DEFLEXED (z) = add_mode (&TOP_MOID (mod), REF_SYMBOL, 0, NODE (z), DEFLEXED (SUB_SUB (z)), NO_PACK);
8088 } else if (IS (z, REF_SYMBOL) && DEFLEXED (SUB (z)) != NO_MOID) {
8089 DEFLEXED (z) = add_mode (&TOP_MOID (mod), REF_SYMBOL, 0, NODE (z), DEFLEXED (SUB (z)), NO_PACK);
8090 } else if (IS (z, ROW_SYMBOL) && DEFLEXED (SUB (z)) != NO_MOID) {
8091 DEFLEXED (z) = add_mode (&TOP_MOID (mod), ROW_SYMBOL, DIM (z), NODE (z), DEFLEXED (SUB (z)), NO_PACK);
8092 } else if (IS (z, FLEX_SYMBOL) && DEFLEXED (SUB (z)) != NO_MOID) {
8093 DEFLEXED (z) = DEFLEXED (SUB (z));
8094 } else if (IS (z, FLEX_SYMBOL)) {
8095 DEFLEXED (z) = SUB (z);
8096 } else {
8097 DEFLEXED (z) = z;
8098 }
8099 }
8100 }
8101 /* Derived modes for stowed modes */
8102 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8103 if (NAME (z) == NO_MOID && IS (z, REF_SYMBOL)) {
8104 if (IS (SUB (z), STRUCT_SYMBOL)) {
8105 NAME (z) = make_name_struct (SUB (z), &TOP_MOID (mod));
8106 } else if (IS (SUB (z), ROW_SYMBOL)) {
8107 NAME (z) = make_name_row (SUB (z), &TOP_MOID (mod));
8108 } else if (IS (SUB (z), FLEX_SYMBOL) && SUB_SUB (z) != NO_MOID) {
8109 NAME (z) = make_name_row (SUB_SUB (z), &TOP_MOID (mod));
8110 }
8111 }
8112 if (MULTIPLE (z) != NO_MOID) {
8113 ;
8114 } else if (IS (z, REF_SYMBOL)) {
8115 if (MULTIPLE (SUB (z)) != NO_MOID) {
8116 MULTIPLE (z) = make_name_struct (MULTIPLE (SUB (z)), &TOP_MOID (mod));
8117 }
8118 } else if (IS (z, ROW_SYMBOL)) {
8119 if (IS (SUB (z), STRUCT_SYMBOL)) {
8120 MULTIPLE (z) = make_multiple_struct (SUB (z), &TOP_MOID (mod), DIM (z));
8121 }
8122 }
8123 }
8124 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8125 if (TRIM (z) == NO_MOID && IS (z, FLEX_SYMBOL)) {
8126 TRIM (z) = SUB (z);
8127 }
8128 if (TRIM (z) == NO_MOID && IS_REF_FLEX (z)) {
8129 TRIM (z) = add_mode (&TOP_MOID (mod), REF_SYMBOL, 0, NODE (z), SUB_SUB (z), NO_PACK);
8130 }
8131 }
8132 /* Fill out stuff for rows, f.i. inverse relations */
8133 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8134 if (IS (z, ROW_SYMBOL) && DIM (z) > 0 && SUB (z) != NO_MOID && !DERIVATE (z)) {
8135 (void) add_row (&TOP_MOID (mod), DIM (z) + 1, SUB (z), NODE (z), A68_TRUE);
8136 } else if (IS (z, REF_SYMBOL) && IS (SUB (z), ROW_SYMBOL) && !DERIVATE (SUB (z))) {
8137 MOID_T *x = add_row (&TOP_MOID (mod), DIM (SUB (z)) + 1, SUB_SUB (z), NODE (SUB (z)), A68_TRUE);
8138 MOID_T *y = add_mode (&TOP_MOID (mod), REF_SYMBOL, 0, NODE (z), x, NO_PACK);
8139 NAME (y) = z;
8140 }
8141 }
8142 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8143 if (IS (z, ROW_SYMBOL) && SLICE (z) != NO_MOID) {
8144 ROWED (SLICE (z)) = z;
8145 }
8146 if (IS (z, REF_SYMBOL)) {
8147 MOID_T *y = SUB (z);
8148 if (SLICE (y) != NO_MOID && IS (SLICE (y), ROW_SYMBOL) && NAME (z) != NO_MOID) {
8149 ROWED (NAME (z)) = z;
8150 }
8151 }
8152 }
8153 bind_modes (TOP_NODE (mod));
8154 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8155 if (IS (z, INDICANT) && NODE (z) != NO_NODE) {
8156 EQUIVALENT (z) = MOID (NODE (z));
8157 }
8158 }
8159 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8160 resolve_eq_members (z);
8161 }
8162 resolve_eq_tags (INDICANTS (a68g_standenv));
8163 resolve_eq_tags (IDENTIFIERS (a68g_standenv));
8164 resolve_eq_tags (OPERATORS (a68g_standenv));
8165 resolve_equivalent (&MODE (STRING));
8166 resolve_equivalent (&MODE (COMPLEX));
8167 resolve_equivalent (&MODE (COMPL));
8168 resolve_equivalent (&MODE (LONG_COMPLEX));
8169 resolve_equivalent (&MODE (LONG_COMPL));
8170 resolve_equivalent (&MODE (LONGLONG_COMPLEX));
8171 resolve_equivalent (&MODE (LONGLONG_COMPL));
8172 resolve_equivalent (&MODE (SEMA));
8173 resolve_equivalent (&MODE (PIPE));
8174 /* UNION members could be resolved */
8175 absorb_unions (TOP_MOID (mod));
8176 contract_unions (TOP_MOID (mod));
8177 /* FLEX INDICANT could be resolved */
8178 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8179 if (IS (z, FLEX_SYMBOL) && SUB (z) != NO_MOID) {
8180 if (SUB_SUB (z) != NO_MOID && IS (SUB_SUB (z), STRUCT_SYMBOL)) {
8181 MULTIPLE (z) = make_flex_multiple_struct (SUB_SUB (z), &TOP_MOID (mod), DIM (SUB (z)));
8182 }
8183 }
8184 }
8185 /* See what new known modes we have generated by resolving. */
8186 for (z = TOP_MOID (mod); z != STANDENV_MOID (&program); FORWARD (z)) {
8187 MOID_T *v;
8188 for (v = NEXT (z); v != NO_MOID; FORWARD (v)) {
8189 if (prove_moid_equivalence (z, v)) {
8190 EQUIVALENT (z) = v;
8191 EQUIVALENT (v) = NO_MOID;
8192 }
8193 }
8194 }
8195 /* Count the modes to check self consistency */
8196 len = nlen;
8197 for (nlen = 0, z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8198 nlen++;
8199 }
8200 }
8201 ABEND (MODE (STRING) != MODE (FLEX_ROW_CHAR), "equivalencing is broken", NO_TEXT);
8202 /* Find out what modes contain rows */
8203 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8204 HAS_ROWS (z) = is_mode_has_row (z);
8205 }
8206 /* Check flexible modes */
8207 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8208 if (IS (z, FLEX_SYMBOL) && ISNT (SUB (z), ROW_SYMBOL)) {
8209 diagnostic_node (A68_ERROR, NODE (z), ERROR_NOT_WELL_FORMED, z);
8210 }
8211 }
8212 /* Check on fields in structured modes f.i. STRUCT (REAL x, INT n, REAL x) is wrong */
8213 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8214 if (IS (z, STRUCT_SYMBOL) && EQUIVALENT (z) == NO_MOID) {
8215 PACK_T *s = PACK (z);
8216 for (; s != NO_PACK; FORWARD (s)) {
8217 PACK_T *t = NEXT (s);
8218 BOOL_T x = A68_TRUE;
8219 for (t = NEXT (s); t != NO_PACK && x; FORWARD (t)) {
8220 if (TEXT (s) == TEXT (t)) {
8221 diagnostic_node (A68_ERROR, NODE (z), ERROR_MULTIPLE_FIELD);
8222 while (NEXT (s) != NO_PACK && TEXT (NEXT (s)) == TEXT (t)) {
8223 FORWARD (s);
8224 }
8225 x = A68_FALSE;
8226 }
8227 }
8228 }
8229 }
8230 }
8231 /* Various union test */
8232 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8233 if (IS (z, UNION_SYMBOL) && EQUIVALENT (z) == NO_MOID) {
8234 PACK_T *s = PACK (z);
8235 /* Discard unions with one member */
8236 if (count_pack_members (s) == 1) {
8237 diagnostic_node (A68_ERROR, NODE (z), ERROR_COMPONENT_NUMBER, z);
8238 }
8239 /* Discard incestuous unions with firmly related modes */
8240 for (; s != NO_PACK; FORWARD (s)) {
8241 PACK_T *t;
8242 for (t = NEXT (s); t != NO_PACK; FORWARD (t)) {
8243 if (MOID (t) != MOID (s)) {
8244 if (is_firm (MOID (s), MOID (t))) {
8245 diagnostic_node (A68_ERROR, NODE (z), ERROR_COMPONENT_RELATED, z);
8246 }
8247 }
8248 }
8249 }
8250 /* Discard incestuous unions with firmly related subsets */
8251 for (s = PACK (z); s != NO_PACK; FORWARD (s)) {
8252 MOID_T *n = depref_completely (MOID (s));
8253 if (IS (n, UNION_SYMBOL) && is_subset (n, z, NO_DEFLEXING)) {
8254 diagnostic_node (A68_ERROR, NODE (z), ERROR_SUBSET_RELATED, z, n);
8255 }
8256 }
8257 }
8258 }
8259 /* Wrap up and exit */
8260 /* Overwrite old equivalent modes now */
8261 /*
8262 for (u = &TOP_MOID (mod); (*u) != NO_MOID; u = & NEXT (*u)) {
8263 while ((*u) != NO_MOID && EQUIVALENT (*u) != NO_MOID) {
8264 (*u) = NEXT (*u);
8265 }
8266 }
8267 */
8268 free_postulate_list (top_postulate, NO_POSTULATE);
8269 top_postulate = NO_POSTULATE;
8270 }
8271
8272 /**
8273 @brief Make list of all modes in the program.
8274 @param mod Module to list modes of.
8275 **/
8276
8277 void
make_moid_list(MODULE_T * mod)8278 make_moid_list (MODULE_T * mod)
8279 {
8280 MOID_T *z;
8281 BOOL_T cont = A68_TRUE;
8282 /* Collect modes from the syntax tree */
8283 reset_moid_tree (TOP_NODE (mod));
8284 get_modes_from_tree (TOP_NODE (mod), STOP);
8285 get_mode_from_proc_var_declarations_tree (TOP_NODE (mod));
8286 /* Connect indicants to their declarers */
8287 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8288 if (IS (z, INDICANT)) {
8289 NODE_T *u = NODE (z);
8290 ABEND (NEXT (u) == NO_NODE, "error in mode table", NO_TEXT);
8291 ABEND (NEXT_NEXT (u) == NO_NODE, "error in mode table", NO_TEXT);
8292 ABEND (MOID (NEXT_NEXT (u)) == NO_MOID, "error in mode table", NO_TEXT);
8293 EQUIVALENT (z) = MOID (NEXT_NEXT (u));
8294 }
8295 }
8296 /* Checks on wrong declarations */
8297 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8298 USE (z) = A68_FALSE;
8299 }
8300 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8301 if (IS (z, INDICANT) && EQUIVALENT (z) != NO_MOID) {
8302 if (!is_well_formed (z, EQUIVALENT (z), A68_FALSE, A68_FALSE, A68_TRUE)) {
8303 diagnostic_node (A68_ERROR, NODE (z), ERROR_NOT_WELL_FORMED, z);
8304 cont = A68_FALSE;
8305 }
8306 }
8307 }
8308 for (z = TOP_MOID (mod); cont && z != NO_MOID; FORWARD (z)) {
8309 if (IS (z, INDICANT) && EQUIVALENT (z) != NO_MOID) {
8310 ;
8311 } else if (NODE (z) != NO_NODE) {
8312 if (!is_well_formed (NO_MOID, z, A68_FALSE, A68_FALSE, A68_TRUE)) {
8313 diagnostic_node (A68_ERROR, NODE (z), ERROR_NOT_WELL_FORMED, z);
8314 }
8315 }
8316 }
8317 for (z = TOP_MOID (mod); z != NO_MOID; FORWARD (z)) {
8318 ABEND (USE (z), ERROR_INTERNAL_CONSISTENCY, NO_TEXT);
8319 }
8320 if (ERROR_COUNT (mod) != 0) {
8321 return;
8322 }
8323 compute_derived_modes (mod);
8324 init_postulates ();
8325 }
8326
8327 /****************************************/
8328 /* Symbol table handling, managing TAGS */
8329 /****************************************/
8330
8331 /**
8332 @brief Set level for procedures.
8333 @param p Node in syntax tree.
8334 @param n Proc level number.
8335 **/
8336
8337 void
set_proc_level(NODE_T * p,int n)8338 set_proc_level (NODE_T * p, int n)
8339 {
8340 for (; p != NO_NODE; FORWARD (p)) {
8341 PROCEDURE_LEVEL (INFO (p)) = n;
8342 if (IS (p, ROUTINE_TEXT)) {
8343 set_proc_level (SUB (p), n + 1);
8344 } else {
8345 set_proc_level (SUB (p), n);
8346 }
8347 }
8348 }
8349
8350 /**
8351 @brief Set nests for diagnostics.
8352 @param p Node in syntax tree.
8353 @param s Start of enclosing nest.
8354 **/
8355
8356 void
set_nest(NODE_T * p,NODE_T * s)8357 set_nest (NODE_T * p, NODE_T * s)
8358 {
8359 for (; p != NO_NODE; FORWARD (p)) {
8360 NEST (p) = s;
8361 if (IS (p, PARTICULAR_PROGRAM)) {
8362 set_nest (SUB (p), p);
8363 } else if (IS (p, CLOSED_CLAUSE) && LINE_NUMBER (p) != 0) {
8364 set_nest (SUB (p), p);
8365 } else if (IS (p, COLLATERAL_CLAUSE) && LINE_NUMBER (p) != 0) {
8366 set_nest (SUB (p), p);
8367 } else if (IS (p, CONDITIONAL_CLAUSE) && LINE_NUMBER (p) != 0) {
8368 set_nest (SUB (p), p);
8369 } else if (IS (p, CASE_CLAUSE) && LINE_NUMBER (p) != 0) {
8370 set_nest (SUB (p), p);
8371 } else if (IS (p, CONFORMITY_CLAUSE) && LINE_NUMBER (p) != 0) {
8372 set_nest (SUB (p), p);
8373 } else if (IS (p, LOOP_CLAUSE) && LINE_NUMBER (p) != 0) {
8374 set_nest (SUB (p), p);
8375 } else {
8376 set_nest (SUB (p), s);
8377 }
8378 }
8379 }
8380
8381 /* Routines that work with tags and symbol tables */
8382
8383 static void tax_tags (NODE_T *);
8384 static void tax_specifier_list (NODE_T *);
8385 static void tax_parameter_list (NODE_T *);
8386 static void tax_format_texts (NODE_T *);
8387
8388 /**
8389 @brief Find a tag, searching symbol tables towards the root.
8390 @param table Symbol table to search.
8391 @param name Name of tag.
8392 @return Type of tag, identifier or label or ....
8393 **/
8394
8395 int
first_tag_global(TABLE_T * table,char * name)8396 first_tag_global (TABLE_T * table, char *name)
8397 {
8398 if (table != NO_TABLE) {
8399 TAG_T *s = NO_TAG;
8400 for (s = IDENTIFIERS (table); s != NO_TAG; FORWARD (s)) {
8401 if (NSYMBOL (NODE (s)) == name) {
8402 return (IDENTIFIER);
8403 }
8404 }
8405 for (s = INDICANTS (table); s != NO_TAG; FORWARD (s)) {
8406 if (NSYMBOL (NODE (s)) == name) {
8407 return (INDICANT);
8408 }
8409 }
8410 for (s = LABELS (table); s != NO_TAG; FORWARD (s)) {
8411 if (NSYMBOL (NODE (s)) == name) {
8412 return (LABEL);
8413 }
8414 }
8415 for (s = OPERATORS (table); s != NO_TAG; FORWARD (s)) {
8416 if (NSYMBOL (NODE (s)) == name) {
8417 return (OP_SYMBOL);
8418 }
8419 }
8420 for (s = PRIO (table); s != NO_TAG; FORWARD (s)) {
8421 if (NSYMBOL (NODE (s)) == name) {
8422 return (PRIO_SYMBOL);
8423 }
8424 }
8425 return (first_tag_global (PREVIOUS (table), name));
8426 } else {
8427 return (STOP);
8428 }
8429 }
8430
8431 #define PORTCHECK_TAX(p, q) {\
8432 if (q == A68_FALSE) {\
8433 diagnostic_node (A68_WARNING | A68_FORCE_DIAGNOSTICS, p, WARNING_TAG_NOT_PORTABLE);\
8434 }}
8435
8436 /**
8437 @brief Check portability of sub tree.
8438 @param p Node in syntax tree.
8439 **/
8440
8441 void
portcheck(NODE_T * p)8442 portcheck (NODE_T * p)
8443 {
8444 for (; p != NO_NODE; FORWARD (p)) {
8445 portcheck (SUB (p));
8446 if (OPTION_PORTCHECK (&program)) {
8447 if (IS (p, INDICANT) && MOID (p) != NO_MOID) {
8448 PORTCHECK_TAX (p, PORTABLE (MOID (p)));
8449 PORTABLE (MOID (p)) = A68_TRUE;
8450 } else if (IS (p, IDENTIFIER)) {
8451 PORTCHECK_TAX (p, PORTABLE (TAX (p)));
8452 PORTABLE (TAX (p)) = A68_TRUE;
8453 } else if (IS (p, OPERATOR)) {
8454 PORTCHECK_TAX (p, PORTABLE (TAX (p)));
8455 PORTABLE (TAX (p)) = A68_TRUE;
8456 } else if (IS (p, ASSERTION)) {
8457 diagnostic_node (A68_WARNING | A68_FORCE_DIAGNOSTICS, p, WARNING_TAG_NOT_PORTABLE);
8458 }
8459 }
8460 }
8461 }
8462
8463 /**
8464 @brief Whether routine can be "lengthety-mapped".
8465 @param z Name of routine.
8466 @return See brief description.
8467 **/
8468
8469 static BOOL_T
is_mappable_routine(char * z)8470 is_mappable_routine (char *z)
8471 {
8472 #define ACCEPT(u, v) {\
8473 if (strlen (u) >= strlen (v)) {\
8474 if (strcmp (&u[strlen (u) - strlen (v)], v) == 0) {\
8475 return (A68_TRUE);\
8476 }}}
8477 /* Math routines */
8478 ACCEPT (z, "arccos");
8479 ACCEPT (z, "arcsin");
8480 ACCEPT (z, "arctan");
8481 ACCEPT (z, "cbrt");
8482 ACCEPT (z, "cos");
8483 ACCEPT (z, "curt");
8484 ACCEPT (z, "exp");
8485 ACCEPT (z, "ln");
8486 ACCEPT (z, "log");
8487 ACCEPT (z, "pi");
8488 ACCEPT (z, "sin");
8489 ACCEPT (z, "sqrt");
8490 ACCEPT (z, "tan");
8491 /* Random generator */
8492 ACCEPT (z, "nextrandom");
8493 ACCEPT (z, "random");
8494 /* BITS */
8495 ACCEPT (z, "bitspack");
8496 /* Enquiries */
8497 ACCEPT (z, "maxint");
8498 ACCEPT (z, "intwidth");
8499 ACCEPT (z, "maxreal");
8500 ACCEPT (z, "realwidth");
8501 ACCEPT (z, "expwidth");
8502 ACCEPT (z, "maxbits");
8503 ACCEPT (z, "bitswidth");
8504 ACCEPT (z, "byteswidth");
8505 ACCEPT (z, "smallreal");
8506 return (A68_FALSE);
8507 #undef ACCEPT
8508 }
8509
8510 /**
8511 @brief Map "short sqrt" onto "sqrt" etcetera.
8512 @param u Name of routine.
8513 @return Tag to map onto.
8514 **/
8515
8516 static TAG_T *
bind_lengthety_identifier(char * u)8517 bind_lengthety_identifier (char *u)
8518 {
8519 #define CAR(u, v) (strncmp (u, v, strlen(v)) == 0)
8520 /*
8521 We can only map routines blessed by "is_mappable_routine", so there is no
8522 "short print" or "long char in string".
8523 */
8524 if (CAR (u, "short")) {
8525 do {
8526 char *v;
8527 TAG_T *w;
8528 u = &u[strlen ("short")];
8529 v = TEXT (add_token (&top_token, u));
8530 w = find_tag_local (a68g_standenv, IDENTIFIER, v);
8531 if (w != NO_TAG && is_mappable_routine (v)) {
8532 return (w);
8533 }
8534 } while (CAR (u, "short"));
8535 } else if (CAR (u, "long")) {
8536 do {
8537 char *v;
8538 TAG_T *w;
8539 u = &u[strlen ("long")];
8540 v = TEXT (add_token (&top_token, u));
8541 w = find_tag_local (a68g_standenv, IDENTIFIER, v);
8542 if (w != NO_TAG && is_mappable_routine (v)) {
8543 return (w);
8544 }
8545 } while (CAR (u, "long"));
8546 }
8547 return (NO_TAG);
8548 #undef CAR
8549 }
8550
8551 /**
8552 @brief Bind identifier tags to the symbol table.
8553 @param p Node in syntax tree.
8554 **/
8555
8556 static void
bind_identifier_tag_to_symbol_table(NODE_T * p)8557 bind_identifier_tag_to_symbol_table (NODE_T * p)
8558 {
8559 for (; p != NO_NODE; FORWARD (p)) {
8560 bind_identifier_tag_to_symbol_table (SUB (p));
8561 if (is_one_of (p, IDENTIFIER, DEFINING_IDENTIFIER, STOP)) {
8562 int att = first_tag_global (TABLE (p), NSYMBOL (p));
8563 TAG_T *z;
8564 if (att == STOP) {
8565 if ((z = bind_lengthety_identifier (NSYMBOL (p))) != NO_TAG) {
8566 MOID (p) = MOID (z);
8567 /*
8568 } else {
8569 diagnostic_node (A68_ERROR, p, ERROR_UNDECLARED_TAG);
8570 z = add_tag (TABLE (p), IDENTIFIER, p, MODE (ERROR), NORMAL_IDENTIFIER);
8571 MOID (p) = MODE (ERROR);
8572 */
8573 }
8574 TAX (p) = z;
8575 } else {
8576 z = find_tag_global (TABLE (p), att, NSYMBOL (p));
8577 if (att == IDENTIFIER && z != NO_TAG) {
8578 MOID (p) = MOID (z);
8579 } else if (att == LABEL && z != NO_TAG) {
8580 ;
8581 } else if ((z = bind_lengthety_identifier (NSYMBOL (p))) != NO_TAG) {
8582 MOID (p) = MOID (z);
8583 } else {
8584 diagnostic_node (A68_ERROR, p, ERROR_UNDECLARED_TAG);
8585 z = add_tag (TABLE (p), IDENTIFIER, p, MODE (ERROR), NORMAL_IDENTIFIER);
8586 MOID (p) = MODE (ERROR);
8587 }
8588 TAX (p) = z;
8589 if (IS (p, DEFINING_IDENTIFIER)) {
8590 NODE (z) = p;
8591 }
8592 }
8593 }
8594 }
8595 }
8596
8597 /**
8598 @brief Bind indicant tags to the symbol table.
8599 @param p Node in syntax tree.
8600 **/
8601
8602 static void
bind_indicant_tag_to_symbol_table(NODE_T * p)8603 bind_indicant_tag_to_symbol_table (NODE_T * p)
8604 {
8605 for (; p != NO_NODE; FORWARD (p)) {
8606 bind_indicant_tag_to_symbol_table (SUB (p));
8607 if (is_one_of (p, INDICANT, DEFINING_INDICANT, STOP)) {
8608 TAG_T *z = find_tag_global (TABLE (p), INDICANT, NSYMBOL (p));
8609 if (z != NO_TAG) {
8610 MOID (p) = MOID (z);
8611 TAX (p) = z;
8612 if (IS (p, DEFINING_INDICANT)) {
8613 NODE (z) = p;
8614 }
8615 }
8616 }
8617 }
8618 }
8619
8620 /**
8621 @brief Enter specifier identifiers in the symbol table.
8622 @param p Node in syntax tree.
8623 **/
8624
8625 static void
tax_specifiers(NODE_T * p)8626 tax_specifiers (NODE_T * p)
8627 {
8628 for (; p != NO_NODE; FORWARD (p)) {
8629 tax_specifiers (SUB (p));
8630 if (SUB (p) != NO_NODE && IS (p, SPECIFIER)) {
8631 tax_specifier_list (SUB (p));
8632 }
8633 }
8634 }
8635
8636 /**
8637 @brief Enter specifier identifiers in the symbol table.
8638 @param p Node in syntax tree.
8639 **/
8640
8641 static void
tax_specifier_list(NODE_T * p)8642 tax_specifier_list (NODE_T * p)
8643 {
8644 if (p != NO_NODE) {
8645 if (IS (p, OPEN_SYMBOL)) {
8646 tax_specifier_list (NEXT (p));
8647 } else if (is_one_of (p, CLOSE_SYMBOL, VOID_SYMBOL, STOP)) {
8648 ;
8649 } else if (IS (p, IDENTIFIER)) {
8650 TAG_T *z = add_tag (TABLE (p), IDENTIFIER, p, NO_MOID, SPECIFIER_IDENTIFIER);
8651 HEAP (z) = LOC_SYMBOL;
8652 } else if (IS (p, DECLARER)) {
8653 tax_specifiers (SUB (p));
8654 tax_specifier_list (NEXT (p));
8655 /* last identifier entry is identifier with this declarer */
8656 if (IDENTIFIERS (TABLE (p)) != NO_TAG && PRIO (IDENTIFIERS (TABLE (p))) == SPECIFIER_IDENTIFIER)
8657 MOID (IDENTIFIERS (TABLE (p))) = MOID (p);
8658 }
8659 }
8660 }
8661
8662 /**
8663 @brief Enter parameter identifiers in the symbol table.
8664 @param p Node in syntax tree.
8665 **/
8666
8667 static void
tax_parameters(NODE_T * p)8668 tax_parameters (NODE_T * p)
8669 {
8670 for (; p != NO_NODE; FORWARD (p)) {
8671 if (SUB (p) != NO_NODE) {
8672 tax_parameters (SUB (p));
8673 if (IS (p, PARAMETER_PACK)) {
8674 tax_parameter_list (SUB (p));
8675 }
8676 }
8677 }
8678 }
8679
8680 /**
8681 @brief Enter parameter identifiers in the symbol table.
8682 @param p Node in syntax tree.
8683 **/
8684
8685 static void
tax_parameter_list(NODE_T * p)8686 tax_parameter_list (NODE_T * p)
8687 {
8688 if (p != NO_NODE) {
8689 if (is_one_of (p, OPEN_SYMBOL, COMMA_SYMBOL, STOP)) {
8690 tax_parameter_list (NEXT (p));
8691 } else if (IS (p, CLOSE_SYMBOL)) {
8692 ;
8693 } else if (is_one_of (p, PARAMETER_LIST, PARAMETER, STOP)) {
8694 tax_parameter_list (NEXT (p));
8695 tax_parameter_list (SUB (p));
8696 } else if (IS (p, IDENTIFIER)) {
8697 /* parameters are always local */
8698 HEAP (add_tag (TABLE (p), IDENTIFIER, p, NO_MOID, PARAMETER_IDENTIFIER)) = LOC_SYMBOL;
8699 } else if (IS (p, DECLARER)) {
8700 TAG_T *s;
8701 tax_parameter_list (NEXT (p));
8702 /* last identifier entries are identifiers with this declarer */
8703 for (s = IDENTIFIERS (TABLE (p)); s != NO_TAG && MOID (s) == NO_MOID; FORWARD (s)) {
8704 MOID (s) = MOID (p);
8705 }
8706 tax_parameters (SUB (p));
8707 }
8708 }
8709 }
8710
8711 /**
8712 @brief Enter FOR identifiers in the symbol table.
8713 @param p Node in syntax tree.
8714 **/
8715
8716 static void
tax_for_identifiers(NODE_T * p)8717 tax_for_identifiers (NODE_T * p)
8718 {
8719 for (; p != NO_NODE; FORWARD (p)) {
8720 tax_for_identifiers (SUB (p));
8721 if (IS (p, FOR_SYMBOL)) {
8722 if ((FORWARD (p)) != NO_NODE) {
8723 (void) add_tag (TABLE (p), IDENTIFIER, p, MODE (INT), LOOP_IDENTIFIER);
8724 }
8725 }
8726 }
8727 }
8728
8729 /**
8730 @brief Enter routine texts in the symbol table.
8731 @param p Node in syntax tree.
8732 **/
8733
8734 static void
tax_routine_texts(NODE_T * p)8735 tax_routine_texts (NODE_T * p)
8736 {
8737 for (; p != NO_NODE; FORWARD (p)) {
8738 tax_routine_texts (SUB (p));
8739 if (IS (p, ROUTINE_TEXT)) {
8740 TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, MOID (p), ROUTINE_TEXT);
8741 TAX (p) = z;
8742 HEAP (z) = LOC_SYMBOL;
8743 USE (z) = A68_TRUE;
8744 }
8745 }
8746 }
8747
8748 /**
8749 @brief Enter format texts in the symbol table.
8750 @param p Node in syntax tree.
8751 **/
8752
8753 static void
tax_format_texts(NODE_T * p)8754 tax_format_texts (NODE_T * p)
8755 {
8756 for (; p != NO_NODE; FORWARD (p)) {
8757 tax_format_texts (SUB (p));
8758 if (IS (p, FORMAT_TEXT)) {
8759 TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, MODE (FORMAT), FORMAT_TEXT);
8760 TAX (p) = z;
8761 USE (z) = A68_TRUE;
8762 } else if (IS (p, FORMAT_DELIMITER_SYMBOL) && NEXT (p) != NO_NODE) {
8763 TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, MODE (FORMAT), FORMAT_IDENTIFIER);
8764 TAX (p) = z;
8765 USE (z) = A68_TRUE;
8766 }
8767 }
8768 }
8769
8770 /**
8771 @brief Enter FORMAT pictures in the symbol table.
8772 @param p Node in syntax tree.
8773 **/
8774
8775 static void
tax_pictures(NODE_T * p)8776 tax_pictures (NODE_T * p)
8777 {
8778 for (; p != NO_NODE; FORWARD (p)) {
8779 tax_pictures (SUB (p));
8780 if (IS (p, PICTURE)) {
8781 TAX (p) = add_tag (TABLE (p), ANONYMOUS, p, MODE (COLLITEM), FORMAT_IDENTIFIER);
8782 }
8783 }
8784 }
8785
8786 /**
8787 @brief Enter generators in the symbol table.
8788 @param p Node in syntax tree.
8789 **/
8790
8791 static void
tax_generators(NODE_T * p)8792 tax_generators (NODE_T * p)
8793 {
8794 for (; p != NO_NODE; FORWARD (p)) {
8795 tax_generators (SUB (p));
8796 if (IS (p, GENERATOR)) {
8797 if (IS (SUB (p), LOC_SYMBOL)) {
8798 TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, SUB_MOID (SUB (p)), GENERATOR);
8799 HEAP (z) = LOC_SYMBOL;
8800 USE (z) = A68_TRUE;
8801 TAX (p) = z;
8802 }
8803 }
8804 }
8805 }
8806
8807 /**
8808 @brief Find a firmly related operator for operands.
8809 @param c Symbol table.
8810 @param n Name of operator.
8811 @param l Left operand mode.
8812 @param r Right operand mode.
8813 @param self Own tag of "n", as to not relate to itself.
8814 @return Pointer to entry in table.
8815 **/
8816
8817 static TAG_T *
find_firmly_related_op(TABLE_T * c,char * n,MOID_T * l,MOID_T * r,TAG_T * self)8818 find_firmly_related_op (TABLE_T * c, char *n, MOID_T * l, MOID_T * r, TAG_T * self)
8819 {
8820 if (c != NO_TABLE) {
8821 TAG_T *s = OPERATORS (c);
8822 for (; s != NO_TAG; FORWARD (s)) {
8823 if (s != self && NSYMBOL (NODE (s)) == n) {
8824 PACK_T *t = PACK (MOID (s));
8825 if (t != NO_PACK && is_firm (MOID (t), l)) {
8826 /* catch monadic operator */
8827 if ((FORWARD (t)) == NO_PACK) {
8828 if (r == NO_MOID) {
8829 return (s);
8830 }
8831 } else {
8832 /* catch dyadic operator */
8833 if (r != NO_MOID && is_firm (MOID (t), r)) {
8834 return (s);
8835 }
8836 }
8837 }
8838 }
8839 }
8840 }
8841 return (NO_TAG);
8842 }
8843
8844 /**
8845 @brief Check for firmly related operators in this range.
8846 @param p Node in syntax tree.
8847 @param s Operator tag to start from.
8848 **/
8849
8850 static void
test_firmly_related_ops_local(NODE_T * p,TAG_T * s)8851 test_firmly_related_ops_local (NODE_T * p, TAG_T * s)
8852 {
8853 if (s != NO_TAG) {
8854 PACK_T *u = PACK (MOID (s));
8855 if (u != NO_PACK) {
8856 MOID_T *l = MOID (u);
8857 MOID_T *r = (NEXT (u) != NO_PACK ? MOID (NEXT (u)) : NO_MOID);
8858 TAG_T *t = find_firmly_related_op (TAG_TABLE (s), NSYMBOL (NODE (s)), l, r, s);
8859 if (t != NO_TAG) {
8860 if (TAG_TABLE (t) == a68g_standenv) {
8861 diagnostic_node (A68_ERROR, p, ERROR_OPERATOR_RELATED, MOID (s), NSYMBOL (NODE (s)), MOID (t), NSYMBOL (NODE (t)));
8862 ABEND (A68_TRUE, "standard environ error", NO_TEXT);
8863 } else {
8864 diagnostic_node (A68_ERROR, p, ERROR_OPERATOR_RELATED, MOID (s), NSYMBOL (NODE (s)), MOID (t), NSYMBOL (NODE (t)));
8865 }
8866 }
8867 }
8868 if (NEXT (s) != NO_TAG) {
8869 test_firmly_related_ops_local ((p == NO_NODE ? NO_NODE : NODE (NEXT (s))), NEXT (s));
8870 }
8871 }
8872 }
8873
8874 /**
8875 @brief Find firmly related operators in this program.
8876 @param p Node in syntax tree.
8877 **/
8878
8879 static void
test_firmly_related_ops(NODE_T * p)8880 test_firmly_related_ops (NODE_T * p)
8881 {
8882 for (; p != NO_NODE; FORWARD (p)) {
8883 if (SUB (p) != NO_NODE && is_new_lexical_level (p)) {
8884 TAG_T *oops = OPERATORS (TABLE (SUB (p)));
8885 if (oops != NO_TAG) {
8886 test_firmly_related_ops_local (NODE (oops), oops);
8887 }
8888 }
8889 test_firmly_related_ops (SUB (p));
8890 }
8891 }
8892
8893 /**
8894 @brief Driver for the processing of TAXes.
8895 @param p Node in syntax tree.
8896 **/
8897
8898 void
collect_taxes(NODE_T * p)8899 collect_taxes (NODE_T * p)
8900 {
8901 tax_tags (p);
8902 tax_specifiers (p);
8903 tax_parameters (p);
8904 tax_for_identifiers (p);
8905 tax_routine_texts (p);
8906 tax_pictures (p);
8907 tax_format_texts (p);
8908 tax_generators (p);
8909 bind_identifier_tag_to_symbol_table (p);
8910 bind_indicant_tag_to_symbol_table (p);
8911 test_firmly_related_ops (p);
8912 test_firmly_related_ops_local (NO_NODE, OPERATORS (a68g_standenv));
8913 }
8914
8915 /**
8916 @brief Whether tag has already been declared in this range.
8917 @param n Name of tag.
8918 @param a Attribute of tag.
8919 **/
8920
8921 static void
already_declared(NODE_T * n,int a)8922 already_declared (NODE_T * n, int a)
8923 {
8924 if (find_tag_local (TABLE (n), a, NSYMBOL (n)) != NO_TAG) {
8925 diagnostic_node (A68_ERROR, n, ERROR_MULTIPLE_TAG);
8926 }
8927 }
8928
8929 /**
8930 @brief Whether tag has already been declared in this range.
8931 @param n Name of tag.
8932 @param a Attribute of tag.
8933 **/
8934
8935 static void
already_declared_hidden(NODE_T * n,int a)8936 already_declared_hidden (NODE_T * n, int a)
8937 {
8938 TAG_T *s;
8939 if (find_tag_local (TABLE (n), a, NSYMBOL (n)) != NO_TAG) {
8940 diagnostic_node (A68_ERROR, n, ERROR_MULTIPLE_TAG);
8941 }
8942 if ((s = find_tag_global (PREVIOUS (TABLE (n)), a, NSYMBOL (n))) != NO_TAG) {
8943 if (TAG_TABLE (s) == a68g_standenv) {
8944 diagnostic_node (A68_WARNING, n, WARNING_HIDES_PRELUDE, MOID (s), NSYMBOL (n));
8945 } else {
8946 diagnostic_node (A68_WARNING, n, WARNING_HIDES, NSYMBOL (n));
8947 }
8948 }
8949 }
8950
8951 /**
8952 @brief Add tag to local symbol table.
8953 @param s Table where to insert.
8954 @param a Attribute.
8955 @param n Name of tag.
8956 @param m Mode of tag.
8957 @param p Node in syntax tree.
8958 @return Entry in symbol table.
8959 **/
8960
8961 TAG_T *
add_tag(TABLE_T * s,int a,NODE_T * n,MOID_T * m,int p)8962 add_tag (TABLE_T * s, int a, NODE_T * n, MOID_T * m, int p)
8963 {
8964 #define INSERT_TAG(l, n) {NEXT (n) = *(l); *(l) = (n);}
8965 if (s != NO_TABLE) {
8966 TAG_T *z = new_tag ();
8967 TAG_TABLE (z) = s;
8968 PRIO (z) = p;
8969 MOID (z) = m;
8970 NODE (z) = n;
8971 /* TAX(n) = z; */
8972 switch (a) {
8973 case IDENTIFIER:{
8974 already_declared_hidden (n, IDENTIFIER);
8975 already_declared_hidden (n, LABEL);
8976 INSERT_TAG (&IDENTIFIERS (s), z);
8977 break;
8978 }
8979 case INDICANT:{
8980 already_declared_hidden (n, INDICANT);
8981 already_declared (n, OP_SYMBOL);
8982 already_declared (n, PRIO_SYMBOL);
8983 INSERT_TAG (&INDICANTS (s), z);
8984 break;
8985 }
8986 case LABEL:{
8987 already_declared_hidden (n, LABEL);
8988 already_declared_hidden (n, IDENTIFIER);
8989 INSERT_TAG (&LABELS (s), z);
8990 break;
8991 }
8992 case OP_SYMBOL:{
8993 already_declared (n, INDICANT);
8994 INSERT_TAG (&OPERATORS (s), z);
8995 break;
8996 }
8997 case PRIO_SYMBOL:{
8998 already_declared (n, PRIO_SYMBOL);
8999 already_declared (n, INDICANT);
9000 INSERT_TAG (&PRIO (s), z);
9001 break;
9002 }
9003 case ANONYMOUS:{
9004 INSERT_TAG (&ANONYMOUS (s), z);
9005 break;
9006 }
9007 default:{
9008 ABEND (A68_TRUE, ERROR_INTERNAL_CONSISTENCY, "add tag");
9009 }
9010 }
9011 return (z);
9012 } else {
9013 return (NO_TAG);
9014 }
9015 }
9016
9017 /**
9018 @brief Find a tag, searching symbol tables towards the root.
9019 @param table Symbol table to search.
9020 @param a Attribute of tag.
9021 @param name Name of tag.
9022 @return Entry in symbol table.
9023 **/
9024
9025 TAG_T *
find_tag_global(TABLE_T * table,int a,char * name)9026 find_tag_global (TABLE_T * table, int a, char *name)
9027 {
9028 if (table != NO_TABLE) {
9029 TAG_T *s = NO_TAG;
9030 switch (a) {
9031 case IDENTIFIER:{
9032 s = IDENTIFIERS (table);
9033 break;
9034 }
9035 case INDICANT:{
9036 s = INDICANTS (table);
9037 break;
9038 }
9039 case LABEL:{
9040 s = LABELS (table);
9041 break;
9042 }
9043 case OP_SYMBOL:{
9044 s = OPERATORS (table);
9045 break;
9046 }
9047 case PRIO_SYMBOL:{
9048 s = PRIO (table);
9049 break;
9050 }
9051 default:{
9052 ABEND (A68_TRUE, "impossible state in find_tag_global", NO_TEXT);
9053 break;
9054 }
9055 }
9056 for (; s != NO_TAG; FORWARD (s)) {
9057 if (NSYMBOL (NODE (s)) == name) {
9058 return (s);
9059 }
9060 }
9061 return (find_tag_global (PREVIOUS (table), a, name));
9062 } else {
9063 return (NO_TAG);
9064 }
9065 }
9066
9067 /**
9068 @brief Whether identifier or label global.
9069 @param table Symbol table to search.
9070 @param name Name of tag.
9071 @return Attribute of tag.
9072 **/
9073
9074 int
is_identifier_or_label_global(TABLE_T * table,char * name)9075 is_identifier_or_label_global (TABLE_T * table, char *name)
9076 {
9077 if (table != NO_TABLE) {
9078 TAG_T *s;
9079 for (s = IDENTIFIERS (table); s != NO_TAG; FORWARD (s)) {
9080 if (NSYMBOL (NODE (s)) == name) {
9081 return (IDENTIFIER);
9082 }
9083 }
9084 for (s = LABELS (table); s != NO_TAG; FORWARD (s)) {
9085 if (NSYMBOL (NODE (s)) == name) {
9086 return (LABEL);
9087 }
9088 }
9089 return (is_identifier_or_label_global (PREVIOUS (table), name));
9090 } else {
9091 return (0);
9092 }
9093 }
9094
9095 /**
9096 @brief Find a tag, searching only local symbol table.
9097 @param table Symbol table to search.
9098 @param a Attribute of tag.
9099 @param name Name of tag.
9100 @return Entry in symbol table.
9101 **/
9102
9103 TAG_T *
find_tag_local(TABLE_T * table,int a,char * name)9104 find_tag_local (TABLE_T * table, int a, char *name)
9105 {
9106 if (table != NO_TABLE) {
9107 TAG_T *s = NO_TAG;
9108 if (a == OP_SYMBOL) {
9109 s = OPERATORS (table);
9110 } else if (a == PRIO_SYMBOL) {
9111 s = PRIO (table);
9112 } else if (a == IDENTIFIER) {
9113 s = IDENTIFIERS (table);
9114 } else if (a == INDICANT) {
9115 s = INDICANTS (table);
9116 } else if (a == LABEL) {
9117 s = LABELS (table);
9118 } else {
9119 ABEND (A68_TRUE, "impossible state in find_tag_local", NO_TEXT);
9120 }
9121 for (; s != NO_TAG; FORWARD (s)) {
9122 if (NSYMBOL (NODE (s)) == name) {
9123 return (s);
9124 }
9125 }
9126 }
9127 return (NO_TAG);
9128 }
9129
9130 /**
9131 @brief Whether context specifies HEAP or LOC for an identifier.
9132 @param p Node in syntax tree.
9133 @return Attribute of generator.
9134 **/
9135
9136 static int
tab_qualifier(NODE_T * p)9137 tab_qualifier (NODE_T * p)
9138 {
9139 if (p != NO_NODE) {
9140 if (is_one_of (p, UNIT, ASSIGNATION, TERTIARY, SECONDARY, GENERATOR, STOP)) {
9141 return (tab_qualifier (SUB (p)));
9142 } else if (is_one_of (p, LOC_SYMBOL, HEAP_SYMBOL, NEW_SYMBOL, STOP)) {
9143 return (ATTRIBUTE (p) == LOC_SYMBOL ? LOC_SYMBOL : HEAP_SYMBOL);
9144 } else {
9145 return (LOC_SYMBOL);
9146 }
9147 } else {
9148 return (LOC_SYMBOL);
9149 }
9150 }
9151
9152 /**
9153 @brief Enter identity declarations in the symbol table.
9154 @param p Node in syntax tree.
9155 @param m Mode of identifiers to enter (picked from the left-most one in fi. INT i = 1, j = 2).
9156 **/
9157
9158 static void
tax_identity_dec(NODE_T * p,MOID_T ** m)9159 tax_identity_dec (NODE_T * p, MOID_T ** m)
9160 {
9161 if (p != NO_NODE) {
9162 if (IS (p, IDENTITY_DECLARATION)) {
9163 tax_identity_dec (SUB (p), m);
9164 tax_identity_dec (NEXT (p), m);
9165 } else if (IS (p, DECLARER)) {
9166 tax_tags (SUB (p));
9167 *m = MOID (p);
9168 tax_identity_dec (NEXT (p), m);
9169 } else if (IS (p, COMMA_SYMBOL)) {
9170 tax_identity_dec (NEXT (p), m);
9171 } else if (IS (p, DEFINING_IDENTIFIER)) {
9172 TAG_T *entry = find_tag_local (TABLE (p), IDENTIFIER, NSYMBOL (p));
9173 MOID (p) = *m;
9174 HEAP (entry) = LOC_SYMBOL;
9175 TAX (p) = entry;
9176 MOID (entry) = *m;
9177 if (ATTRIBUTE (*m) == REF_SYMBOL) {
9178 HEAP (entry) = tab_qualifier (NEXT_NEXT (p));
9179 }
9180 tax_identity_dec (NEXT_NEXT (p), m);
9181 } else {
9182 tax_tags (p);
9183 }
9184 }
9185 }
9186
9187 /**
9188 @brief Enter variable declarations in the symbol table.
9189 @param p Node in syntax tree.
9190 @param q Qualifier of generator (HEAP, LOC) picked from left-most identifier.
9191 @param m Mode of identifiers to enter (picked from the left-most one in fi. INT i, j, k).
9192 **/
9193
9194 static void
tax_variable_dec(NODE_T * p,int * q,MOID_T ** m)9195 tax_variable_dec (NODE_T * p, int *q, MOID_T ** m)
9196 {
9197 if (p != NO_NODE) {
9198 if (IS (p, VARIABLE_DECLARATION)) {
9199 tax_variable_dec (SUB (p), q, m);
9200 tax_variable_dec (NEXT (p), q, m);
9201 } else if (IS (p, DECLARER)) {
9202 tax_tags (SUB (p));
9203 *m = MOID (p);
9204 tax_variable_dec (NEXT (p), q, m);
9205 } else if (IS (p, QUALIFIER)) {
9206 *q = ATTRIBUTE (SUB (p));
9207 tax_variable_dec (NEXT (p), q, m);
9208 } else if (IS (p, COMMA_SYMBOL)) {
9209 tax_variable_dec (NEXT (p), q, m);
9210 } else if (IS (p, DEFINING_IDENTIFIER)) {
9211 TAG_T *entry = find_tag_local (TABLE (p), IDENTIFIER, NSYMBOL (p));
9212 MOID (p) = *m;
9213 TAX (p) = entry;
9214 HEAP (entry) = *q;
9215 if (*q == LOC_SYMBOL) {
9216 TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, SUB (*m), GENERATOR);
9217 HEAP (z) = LOC_SYMBOL;
9218 USE (z) = A68_TRUE;
9219 BODY (entry) = z;
9220 } else {
9221 BODY (entry) = NO_TAG;
9222 }
9223 MOID (entry) = *m;
9224 tax_variable_dec (NEXT (p), q, m);
9225 } else {
9226 tax_tags (p);
9227 }
9228 }
9229 }
9230
9231 /**
9232 @brief Enter procedure variable declarations in the symbol table.
9233 @param p Node in syntax tree.
9234 @param q Qualifier of generator (HEAP, LOC) picked from left-most identifier.
9235 **/
9236
9237 static void
tax_proc_variable_dec(NODE_T * p,int * q)9238 tax_proc_variable_dec (NODE_T * p, int *q)
9239 {
9240 if (p != NO_NODE) {
9241 if (IS (p, PROCEDURE_VARIABLE_DECLARATION)) {
9242 tax_proc_variable_dec (SUB (p), q);
9243 tax_proc_variable_dec (NEXT (p), q);
9244 } else if (IS (p, QUALIFIER)) {
9245 *q = ATTRIBUTE (SUB (p));
9246 tax_proc_variable_dec (NEXT (p), q);
9247 } else if (is_one_of (p, PROC_SYMBOL, COMMA_SYMBOL, STOP)) {
9248 tax_proc_variable_dec (NEXT (p), q);
9249 } else if (IS (p, DEFINING_IDENTIFIER)) {
9250 TAG_T *entry = find_tag_local (TABLE (p), IDENTIFIER, NSYMBOL (p));
9251 TAX (p) = entry;
9252 HEAP (entry) = *q;
9253 MOID (entry) = MOID (p);
9254 if (*q == LOC_SYMBOL) {
9255 TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, SUB_MOID (p), GENERATOR);
9256 HEAP (z) = LOC_SYMBOL;
9257 USE (z) = A68_TRUE;
9258 BODY (entry) = z;
9259 } else {
9260 BODY (entry) = NO_TAG;
9261 }
9262 tax_proc_variable_dec (NEXT (p), q);
9263 } else {
9264 tax_tags (p);
9265 }
9266 }
9267 }
9268
9269 /**
9270 @brief Enter procedure declarations in the symbol table.
9271 @param p Node in syntax tree.
9272 **/
9273
9274 static void
tax_proc_dec(NODE_T * p)9275 tax_proc_dec (NODE_T * p)
9276 {
9277 if (p != NO_NODE) {
9278 if (IS (p, PROCEDURE_DECLARATION)) {
9279 tax_proc_dec (SUB (p));
9280 tax_proc_dec (NEXT (p));
9281 } else if (is_one_of (p, PROC_SYMBOL, COMMA_SYMBOL, STOP)) {
9282 tax_proc_dec (NEXT (p));
9283 } else if (IS (p, DEFINING_IDENTIFIER)) {
9284 TAG_T *entry = find_tag_local (TABLE (p), IDENTIFIER, NSYMBOL (p));
9285 MOID_T *m = MOID (NEXT_NEXT (p));
9286 MOID (p) = m;
9287 TAX (p) = entry;
9288 CODEX (entry) |= PROC_DECLARATION_MASK;
9289 HEAP (entry) = LOC_SYMBOL;
9290 MOID (entry) = m;
9291 tax_proc_dec (NEXT (p));
9292 } else {
9293 tax_tags (p);
9294 }
9295 }
9296 }
9297
9298 /**
9299 @brief Check validity of operator declaration.
9300 @param p Node in syntax tree.
9301 @param u Moid for a operator-plan.
9302 **/
9303
9304 static void
check_operator_dec(NODE_T * p,MOID_T * u)9305 check_operator_dec (NODE_T * p, MOID_T * u)
9306 {
9307 int k = 0;
9308 if (u == NO_MOID) {
9309 NODE_T *pack = SUB_SUB (NEXT_NEXT (p)); /* Where the parameter pack is */
9310 if (ATTRIBUTE (NEXT_NEXT (p)) != ROUTINE_TEXT) {
9311 pack = SUB (pack);
9312 }
9313 k = 1 + count_operands (pack);
9314 } else {
9315 k = count_pack_members (PACK (u));
9316 }
9317 if (k < 1 && k > 2) {
9318 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_OPERAND_NUMBER);
9319 k = 0;
9320 }
9321 if (k == 1 && a68g_strchr (NOMADS, NSYMBOL (p)[0]) != NO_TEXT) {
9322 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_OPERATOR_INVALID, NOMADS);
9323 } else if (k == 2 && !find_tag_global (TABLE (p), PRIO_SYMBOL, NSYMBOL (p))) {
9324 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_DYADIC_PRIORITY);
9325 }
9326 }
9327
9328 /**
9329 @brief Enter operator declarations in the symbol table.
9330 @param p Node in syntax tree.
9331 @param m Mode of operators to enter (picked from the left-most one).
9332 **/
9333
9334 static void
tax_op_dec(NODE_T * p,MOID_T ** m)9335 tax_op_dec (NODE_T * p, MOID_T ** m)
9336 {
9337 if (p != NO_NODE) {
9338 if (IS (p, OPERATOR_DECLARATION)) {
9339 tax_op_dec (SUB (p), m);
9340 tax_op_dec (NEXT (p), m);
9341 } else if (IS (p, OPERATOR_PLAN)) {
9342 tax_tags (SUB (p));
9343 *m = MOID (p);
9344 tax_op_dec (NEXT (p), m);
9345 } else if (IS (p, OP_SYMBOL)) {
9346 tax_op_dec (NEXT (p), m);
9347 } else if (IS (p, COMMA_SYMBOL)) {
9348 tax_op_dec (NEXT (p), m);
9349 } else if (IS (p, DEFINING_OPERATOR)) {
9350 TAG_T *entry = OPERATORS (TABLE (p));
9351 check_operator_dec (p, *m);
9352 while (entry != NO_TAG && NODE (entry) != p) {
9353 FORWARD (entry);
9354 }
9355 MOID (p) = *m;
9356 TAX (p) = entry;
9357 HEAP (entry) = LOC_SYMBOL;
9358 MOID (entry) = *m;
9359 tax_op_dec (NEXT (p), m);
9360 } else {
9361 tax_tags (p);
9362 }
9363 }
9364 }
9365
9366 /**
9367 @brief Enter brief operator declarations in the symbol table.
9368 @param p Node in syntax tree.
9369 **/
9370
9371 static void
tax_brief_op_dec(NODE_T * p)9372 tax_brief_op_dec (NODE_T * p)
9373 {
9374 if (p != NO_NODE) {
9375 if (IS (p, BRIEF_OPERATOR_DECLARATION)) {
9376 tax_brief_op_dec (SUB (p));
9377 tax_brief_op_dec (NEXT (p));
9378 } else if (is_one_of (p, OP_SYMBOL, COMMA_SYMBOL, STOP)) {
9379 tax_brief_op_dec (NEXT (p));
9380 } else if (IS (p, DEFINING_OPERATOR)) {
9381 TAG_T *entry = OPERATORS (TABLE (p));
9382 MOID_T *m = MOID (NEXT_NEXT (p));
9383 check_operator_dec (p, NO_MOID);
9384 while (entry != NO_TAG && NODE (entry) != p) {
9385 FORWARD (entry);
9386 }
9387 MOID (p) = m;
9388 TAX (p) = entry;
9389 HEAP (entry) = LOC_SYMBOL;
9390 MOID (entry) = m;
9391 tax_brief_op_dec (NEXT (p));
9392 } else {
9393 tax_tags (p);
9394 }
9395 }
9396 }
9397
9398 /**
9399 @brief Enter priority declarations in the symbol table.
9400 @param p Node in syntax tree.
9401 **/
9402
9403 static void
tax_prio_dec(NODE_T * p)9404 tax_prio_dec (NODE_T * p)
9405 {
9406 if (p != NO_NODE) {
9407 if (IS (p, PRIORITY_DECLARATION)) {
9408 tax_prio_dec (SUB (p));
9409 tax_prio_dec (NEXT (p));
9410 } else if (is_one_of (p, PRIO_SYMBOL, COMMA_SYMBOL, STOP)) {
9411 tax_prio_dec (NEXT (p));
9412 } else if (IS (p, DEFINING_OPERATOR)) {
9413 TAG_T *entry = PRIO (TABLE (p));
9414 while (entry != NO_TAG && NODE (entry) != p) {
9415 FORWARD (entry);
9416 }
9417 MOID (p) = NO_MOID;
9418 TAX (p) = entry;
9419 HEAP (entry) = LOC_SYMBOL;
9420 tax_prio_dec (NEXT (p));
9421 } else {
9422 tax_tags (p);
9423 }
9424 }
9425 }
9426
9427 /**
9428 @brief Enter TAXes in the symbol table.
9429 @param p Node in syntax tree.
9430 **/
9431
9432 static void
tax_tags(NODE_T * p)9433 tax_tags (NODE_T * p)
9434 {
9435 for (; p != NO_NODE; FORWARD (p)) {
9436 int heap = LOC_SYMBOL;
9437 MOID_T *m = NO_MOID;
9438 if (IS (p, IDENTITY_DECLARATION)) {
9439 tax_identity_dec (p, &m);
9440 } else if (IS (p, VARIABLE_DECLARATION)) {
9441 tax_variable_dec (p, &heap, &m);
9442 } else if (IS (p, PROCEDURE_DECLARATION)) {
9443 tax_proc_dec (p);
9444 } else if (IS (p, PROCEDURE_VARIABLE_DECLARATION)) {
9445 tax_proc_variable_dec (p, &heap);
9446 } else if (IS (p, OPERATOR_DECLARATION)) {
9447 tax_op_dec (p, &m);
9448 } else if (IS (p, BRIEF_OPERATOR_DECLARATION)) {
9449 tax_brief_op_dec (p);
9450 } else if (IS (p, PRIORITY_DECLARATION)) {
9451 tax_prio_dec (p);
9452 } else {
9453 tax_tags (SUB (p));
9454 }
9455 }
9456 }
9457
9458 /**
9459 @brief Reset symbol table nest count.
9460 @param p Node in syntax tree.
9461 **/
9462
9463 void
reset_symbol_table_nest_count(NODE_T * p)9464 reset_symbol_table_nest_count (NODE_T * p)
9465 {
9466 for (; p != NO_NODE; FORWARD (p)) {
9467 if (SUB (p) != NO_NODE && is_new_lexical_level (p)) {
9468 NEST (TABLE (SUB (p))) = symbol_table_count++;
9469 }
9470 reset_symbol_table_nest_count (SUB (p));
9471 }
9472 }
9473
9474 /**
9475 @brief Bind routines in symbol table to the tree.
9476 @param p Node in syntax tree.
9477 **/
9478
9479 void
bind_routine_tags_to_tree(NODE_T * p)9480 bind_routine_tags_to_tree (NODE_T * p)
9481 {
9482 /* By inserting coercions etc. some may have shifted */
9483 for (; p != NO_NODE; FORWARD (p)) {
9484 if (IS (p, ROUTINE_TEXT) && TAX (p) != NO_TAG) {
9485 NODE (TAX (p)) = p;
9486 }
9487 bind_routine_tags_to_tree (SUB (p));
9488 }
9489 }
9490
9491 /**
9492 @brief Bind formats in symbol table to tree.
9493 @param p Node in syntax tree.
9494 **/
9495
9496 void
bind_format_tags_to_tree(NODE_T * p)9497 bind_format_tags_to_tree (NODE_T * p)
9498 {
9499 /* By inserting coercions etc. some may have shifted */
9500 for (; p != NO_NODE; FORWARD (p)) {
9501 if (IS (p, FORMAT_TEXT) && TAX (p) != NO_TAG) {
9502 NODE (TAX (p)) = p;
9503 } else if (IS (p, FORMAT_DELIMITER_SYMBOL) && NEXT (p) != NO_NODE && TAX (p) != NO_TAG) {
9504 NODE (TAX (p)) = p;
9505 }
9506 bind_format_tags_to_tree (SUB (p));
9507 }
9508 }
9509
9510 /**
9511 @brief Fill outer level of symbol table.
9512 @param p Node in syntax tree.
9513 @param s Parent symbol table.
9514 **/
9515
9516 void
fill_symbol_table_outer(NODE_T * p,TABLE_T * s)9517 fill_symbol_table_outer (NODE_T * p, TABLE_T * s)
9518 {
9519 for (; p != NO_NODE; FORWARD (p)) {
9520 if (TABLE (p) != NO_TABLE) {
9521 OUTER (TABLE (p)) = s;
9522 }
9523 if (SUB (p) != NO_NODE && IS (p, ROUTINE_TEXT)) {
9524 fill_symbol_table_outer (SUB (p), TABLE (SUB (p)));
9525 } else if (SUB (p) != NO_NODE && IS (p, FORMAT_TEXT)) {
9526 fill_symbol_table_outer (SUB (p), TABLE (SUB (p)));
9527 } else {
9528 fill_symbol_table_outer (SUB (p), s);
9529 }
9530 }
9531 }
9532
9533 /**
9534 @brief Flood branch in tree with local symbol table "s".
9535 @param p Node in syntax tree.
9536 @param s Parent symbol table.
9537 **/
9538
9539 static void
flood_with_symbol_table_restricted(NODE_T * p,TABLE_T * s)9540 flood_with_symbol_table_restricted (NODE_T * p, TABLE_T * s)
9541 {
9542 for (; p != NO_NODE; FORWARD (p)) {
9543 TABLE (p) = s;
9544 if (ATTRIBUTE (p) != ROUTINE_TEXT && ATTRIBUTE (p) != SPECIFIED_UNIT) {
9545 if (is_new_lexical_level (p)) {
9546 PREVIOUS (TABLE (SUB (p))) = s;
9547 } else {
9548 flood_with_symbol_table_restricted (SUB (p), s);
9549 }
9550 }
9551 }
9552 }
9553
9554 /**
9555 @brief Final structure of symbol table after parsing.
9556 @param p Node in syntax tree.
9557 @param l Current lexical level.
9558 **/
9559
9560 void
finalise_symbol_table_setup(NODE_T * p,int l)9561 finalise_symbol_table_setup (NODE_T * p, int l)
9562 {
9563 TABLE_T *s = TABLE (p);
9564 NODE_T *q = p;
9565 while (q != NO_NODE) {
9566 /* routine texts are ranges */
9567 if (IS (q, ROUTINE_TEXT)) {
9568 flood_with_symbol_table_restricted (SUB (q), new_symbol_table (s));
9569 }
9570 /* specifiers are ranges */
9571 else if (IS (q, SPECIFIED_UNIT)) {
9572 flood_with_symbol_table_restricted (SUB (q), new_symbol_table (s));
9573 }
9574 /* level count and recursion */
9575 if (SUB (q) != NO_NODE) {
9576 if (is_new_lexical_level (q)) {
9577 LEX_LEVEL (SUB (q)) = l + 1;
9578 PREVIOUS (TABLE (SUB (q))) = s;
9579 finalise_symbol_table_setup (SUB (q), l + 1);
9580 if (IS (q, WHILE_PART)) {
9581 /* This was a bug that went unnoticed for 15 years! */
9582 TABLE_T *s2 = TABLE (SUB (q));
9583 if ((FORWARD (q)) == NO_NODE) {
9584 return;
9585 }
9586 if (IS (q, ALT_DO_PART)) {
9587 PREVIOUS (TABLE (SUB (q))) = s2;
9588 LEX_LEVEL (SUB (q)) = l + 2;
9589 finalise_symbol_table_setup (SUB (q), l + 2);
9590 }
9591 }
9592 } else {
9593 TABLE (SUB (q)) = s;
9594 finalise_symbol_table_setup (SUB (q), l);
9595 }
9596 }
9597 TABLE (q) = s;
9598 if (IS (q, FOR_SYMBOL)) {
9599 FORWARD (q);
9600 }
9601 FORWARD (q);
9602 }
9603 /* FOR identifiers are in the DO ... OD range */
9604 for (q = p; q != NO_NODE; FORWARD (q)) {
9605 if (IS (q, FOR_SYMBOL)) {
9606 TABLE (NEXT (q)) = TABLE (SEQUENCE (NEXT (q)));
9607 }
9608 }
9609 }
9610
9611 /**
9612 @brief First structure of symbol table for parsing.
9613 @param p Node in syntax tree.
9614 **/
9615
9616 void
preliminary_symbol_table_setup(NODE_T * p)9617 preliminary_symbol_table_setup (NODE_T * p)
9618 {
9619 NODE_T *q;
9620 TABLE_T *s = TABLE (p);
9621 BOOL_T not_a_for_range = A68_FALSE;
9622 /* let the tree point to the current symbol table */
9623 for (q = p; q != NO_NODE; FORWARD (q)) {
9624 TABLE (q) = s;
9625 }
9626 /* insert new tables when required */
9627 for (q = p; q != NO_NODE && !not_a_for_range; FORWARD (q)) {
9628 if (SUB (q) != NO_NODE) {
9629 /* BEGIN ... END, CODE ... EDOC, DEF ... FED, DO ... OD, $ ... $, { ... } are ranges */
9630 if (is_one_of (q, BEGIN_SYMBOL, DO_SYMBOL, ALT_DO_SYMBOL, FORMAT_DELIMITER_SYMBOL, ACCO_SYMBOL, STOP)) {
9631 TABLE (SUB (q)) = new_symbol_table (s);
9632 preliminary_symbol_table_setup (SUB (q));
9633 }
9634 /* ( ... ) is a range */
9635 else if (IS (q, OPEN_SYMBOL)) {
9636 if (whether (q, OPEN_SYMBOL, THEN_BAR_SYMBOL, STOP)) {
9637 TABLE (SUB (q)) = s;
9638 preliminary_symbol_table_setup (SUB (q));
9639 FORWARD (q);
9640 TABLE (SUB (q)) = new_symbol_table (s);
9641 preliminary_symbol_table_setup (SUB (q));
9642 if ((FORWARD (q)) == NO_NODE) {
9643 not_a_for_range = A68_TRUE;
9644 } else {
9645 if (IS (q, THEN_BAR_SYMBOL)) {
9646 TABLE (SUB (q)) = new_symbol_table (s);
9647 preliminary_symbol_table_setup (SUB (q));
9648 }
9649 if (IS (q, OPEN_SYMBOL)) {
9650 TABLE (SUB (q)) = new_symbol_table (s);
9651 preliminary_symbol_table_setup (SUB (q));
9652 }
9653 }
9654 } else {
9655 /* don't worry about STRUCT (...), UNION (...), PROC (...) yet */
9656 TABLE (SUB (q)) = new_symbol_table (s);
9657 preliminary_symbol_table_setup (SUB (q));
9658 }
9659 }
9660 /* IF ... THEN ... ELSE ... FI are ranges */
9661 else if (IS (q, IF_SYMBOL)) {
9662 if (whether (q, IF_SYMBOL, THEN_SYMBOL, STOP)) {
9663 TABLE (SUB (q)) = s;
9664 preliminary_symbol_table_setup (SUB (q));
9665 FORWARD (q);
9666 TABLE (SUB (q)) = new_symbol_table (s);
9667 preliminary_symbol_table_setup (SUB (q));
9668 if ((FORWARD (q)) == NO_NODE) {
9669 not_a_for_range = A68_TRUE;
9670 } else {
9671 if (IS (q, ELSE_SYMBOL)) {
9672 TABLE (SUB (q)) = new_symbol_table (s);
9673 preliminary_symbol_table_setup (SUB (q));
9674 }
9675 if (IS (q, IF_SYMBOL)) {
9676 TABLE (SUB (q)) = new_symbol_table (s);
9677 preliminary_symbol_table_setup (SUB (q));
9678 }
9679 }
9680 } else {
9681 TABLE (SUB (q)) = new_symbol_table (s);
9682 preliminary_symbol_table_setup (SUB (q));
9683 }
9684 }
9685 /* CASE ... IN ... OUT ... ESAC are ranges */
9686 else if (IS (q, CASE_SYMBOL)) {
9687 if (whether (q, CASE_SYMBOL, IN_SYMBOL, STOP)) {
9688 TABLE (SUB (q)) = s;
9689 preliminary_symbol_table_setup (SUB (q));
9690 FORWARD (q);
9691 TABLE (SUB (q)) = new_symbol_table (s);
9692 preliminary_symbol_table_setup (SUB (q));
9693 if ((FORWARD (q)) == NO_NODE) {
9694 not_a_for_range = A68_TRUE;
9695 } else {
9696 if (IS (q, OUT_SYMBOL)) {
9697 TABLE (SUB (q)) = new_symbol_table (s);
9698 preliminary_symbol_table_setup (SUB (q));
9699 }
9700 if (IS (q, CASE_SYMBOL)) {
9701 TABLE (SUB (q)) = new_symbol_table (s);
9702 preliminary_symbol_table_setup (SUB (q));
9703 }
9704 }
9705 } else {
9706 TABLE (SUB (q)) = new_symbol_table (s);
9707 preliminary_symbol_table_setup (SUB (q));
9708 }
9709 }
9710 /* UNTIL ... OD is a range */
9711 else if (IS (q, UNTIL_SYMBOL) && SUB (q) != NO_NODE) {
9712 TABLE (SUB (q)) = new_symbol_table (s);
9713 preliminary_symbol_table_setup (SUB (q));
9714 /* WHILE ... DO ... OD are ranges */
9715 } else if (IS (q, WHILE_SYMBOL)) {
9716 TABLE_T *u = new_symbol_table (s);
9717 TABLE (SUB (q)) = u;
9718 preliminary_symbol_table_setup (SUB (q));
9719 if ((FORWARD (q)) == NO_NODE) {
9720 not_a_for_range = A68_TRUE;
9721 } else if (IS (q, ALT_DO_SYMBOL)) {
9722 TABLE (SUB (q)) = new_symbol_table (u);
9723 preliminary_symbol_table_setup (SUB (q));
9724 }
9725 } else {
9726 TABLE (SUB (q)) = s;
9727 preliminary_symbol_table_setup (SUB (q));
9728 }
9729 }
9730 }
9731 /* FOR identifiers will go to the DO ... OD range */
9732 if (!not_a_for_range) {
9733 for (q = p; q != NO_NODE; FORWARD (q)) {
9734 if (IS (q, FOR_SYMBOL)) {
9735 NODE_T *r = q;
9736 TABLE (NEXT (q)) = NO_TABLE;
9737 for (; r != NO_NODE && TABLE (NEXT (q)) == NO_TABLE; FORWARD (r)) {
9738 if ((is_one_of (r, WHILE_SYMBOL, ALT_DO_SYMBOL, STOP)) && (NEXT (q) != NO_NODE && SUB (r) != NO_NODE)) {
9739 TABLE (NEXT (q)) = TABLE (SUB (r));
9740 SEQUENCE (NEXT (q)) = SUB (r);
9741 }
9742 }
9743 }
9744 }
9745 }
9746 }
9747
9748 /**
9749 @brief Mark a mode as in use.
9750 @param m Mode to mark.
9751 **/
9752
9753 static void
mark_mode(MOID_T * m)9754 mark_mode (MOID_T * m)
9755 {
9756 if (m != NO_MOID && USE (m) == A68_FALSE) {
9757 PACK_T *p = PACK (m);
9758 USE (m) = A68_TRUE;
9759 for (; p != NO_PACK; FORWARD (p)) {
9760 mark_mode (MOID (p));
9761 mark_mode (SUB (m));
9762 mark_mode (SLICE (m));
9763 }
9764 }
9765 }
9766
9767 /**
9768 @brief Traverse tree and mark modes as used.
9769 @param p Node in syntax tree.
9770 **/
9771
9772 void
mark_moids(NODE_T * p)9773 mark_moids (NODE_T * p)
9774 {
9775 for (; p != NO_NODE; FORWARD (p)) {
9776 mark_moids (SUB (p));
9777 if (MOID (p) != NO_MOID) {
9778 mark_mode (MOID (p));
9779 }
9780 }
9781 }
9782
9783 /**
9784 @brief Mark various tags as used.
9785 @param p Node in syntax tree.
9786 **/
9787
9788 void
mark_auxilliary(NODE_T * p)9789 mark_auxilliary (NODE_T * p)
9790 {
9791 for (; p != NO_NODE; FORWARD (p)) {
9792 if (SUB (p) != NO_NODE) {
9793 /*
9794 You get no warnings on unused PROC parameters. That is ok since A68 has some
9795 parameters that you may not use at all - think of PROC (REF FILE) BOOL event
9796 routines in transput.
9797 */
9798 mark_auxilliary (SUB (p));
9799 } else if (IS (p, OPERATOR)) {
9800 TAG_T *z;
9801 if (TAX (p) != NO_TAG) {
9802 USE (TAX (p)) = A68_TRUE;
9803 }
9804 if ((z = find_tag_global (TABLE (p), PRIO_SYMBOL, NSYMBOL (p))) != NO_TAG) {
9805 USE (z) = A68_TRUE;
9806 }
9807 } else if (IS (p, INDICANT)) {
9808 TAG_T *z = find_tag_global (TABLE (p), INDICANT, NSYMBOL (p));
9809 if (z != NO_TAG) {
9810 TAX (p) = z;
9811 USE (z) = A68_TRUE;
9812 }
9813 } else if (IS (p, IDENTIFIER)) {
9814 if (TAX (p) != NO_TAG) {
9815 USE (TAX (p)) = A68_TRUE;
9816 }
9817 }
9818 }
9819 }
9820
9821 /**
9822 @brief Check a single tag.
9823 @param s Tag to check.
9824 **/
9825
9826 static void
unused(TAG_T * s)9827 unused (TAG_T * s)
9828 {
9829 for (; s != NO_TAG; FORWARD (s)) {
9830 if (LINE_NUMBER (NODE (s)) > 0 && !USE (s)) {
9831 diagnostic_node (A68_WARNING, NODE (s), WARNING_TAG_UNUSED, NODE (s));
9832 }
9833 }
9834 }
9835
9836 /**
9837 @brief Driver for traversing tree and warn for unused tags.
9838 @param p Node in syntax tree.
9839 **/
9840
9841 void
warn_for_unused_tags(NODE_T * p)9842 warn_for_unused_tags (NODE_T * p)
9843 {
9844 for (; p != NO_NODE; FORWARD (p)) {
9845 if (SUB (p) != NO_NODE) {
9846 if (is_new_lexical_level (p) && ATTRIBUTE (TABLE (SUB (p))) != ENVIRON_SYMBOL) {
9847 unused (OPERATORS (TABLE (SUB (p))));
9848 unused (PRIO (TABLE (SUB (p))));
9849 unused (IDENTIFIERS (TABLE (SUB (p))));
9850 unused (LABELS (TABLE (SUB (p))));
9851 unused (INDICANTS (TABLE (SUB (p))));
9852 }
9853 }
9854 warn_for_unused_tags (SUB (p));
9855 }
9856 }
9857
9858 /**
9859 @brief Mark jumps and procedured jumps.
9860 @param p Node in syntax tree.
9861 **/
9862
9863 void
jumps_from_procs(NODE_T * p)9864 jumps_from_procs (NODE_T * p)
9865 {
9866 for (; p != NO_NODE; FORWARD (p)) {
9867 if (IS (p, PROCEDURING)) {
9868 NODE_T *u = SUB_SUB (p);
9869 if (IS (u, GOTO_SYMBOL)) {
9870 FORWARD (u);
9871 }
9872 USE (TAX (u)) = A68_TRUE;
9873 } else if (IS (p, JUMP)) {
9874 NODE_T *u = SUB (p);
9875 if (IS (u, GOTO_SYMBOL)) {
9876 FORWARD (u);
9877 }
9878 if ((TAX (u) == NO_TAG) && (MOID (u) == NO_MOID) && (find_tag_global (TABLE (u), LABEL, NSYMBOL (u)) == NO_TAG)) {
9879 (void) add_tag (TABLE (u), LABEL, u, NO_MOID, LOCAL_LABEL);
9880 diagnostic_node (A68_ERROR, u, ERROR_UNDECLARED_TAG);
9881 } else {
9882 USE (TAX (u)) = A68_TRUE;
9883 }
9884 } else {
9885 jumps_from_procs (SUB (p));
9886 }
9887 }
9888 }
9889
9890 /**
9891 @brief Assign offset tags.
9892 @param t Tag to start from.
9893 @param base First (base) address.
9894 @return End address.
9895 **/
9896
9897 static ADDR_T
assign_offset_tags(TAG_T * t,ADDR_T base)9898 assign_offset_tags (TAG_T * t, ADDR_T base)
9899 {
9900 ADDR_T sum = base;
9901 for (; t != NO_TAG; FORWARD (t)) {
9902 ABEND (MOID (t) == NO_MOID, "tag has no mode", NSYMBOL (NODE (t)));
9903 SIZE (t) = moid_size (MOID (t));
9904 if (VALUE (t) == NO_TEXT) {
9905 OFFSET (t) = sum;
9906 sum += SIZE (t);
9907 }
9908 }
9909 return (sum);
9910 }
9911
9912 /**
9913 @brief Assign offsets table.
9914 @param c Symbol table .
9915 **/
9916
9917 void
assign_offsets_table(TABLE_T * c)9918 assign_offsets_table (TABLE_T * c)
9919 {
9920 AP_INCREMENT (c) = assign_offset_tags (IDENTIFIERS (c), 0);
9921 AP_INCREMENT (c) = assign_offset_tags (OPERATORS (c), AP_INCREMENT (c));
9922 AP_INCREMENT (c) = assign_offset_tags (ANONYMOUS (c), AP_INCREMENT (c));
9923 AP_INCREMENT (c) = A68_ALIGN (AP_INCREMENT (c));
9924 }
9925
9926 /**
9927 @brief Assign offsets.
9928 @param p Node in syntax tree.
9929 **/
9930
9931 void
assign_offsets(NODE_T * p)9932 assign_offsets (NODE_T * p)
9933 {
9934 for (; p != NO_NODE; FORWARD (p)) {
9935 if (SUB (p) != NO_NODE && is_new_lexical_level (p)) {
9936 assign_offsets_table (TABLE (SUB (p)));
9937 }
9938 assign_offsets (SUB (p));
9939 }
9940 }
9941
9942 /**
9943 @brief Assign offsets packs in moid list.
9944 @param q Moid to start from.
9945 **/
9946
9947 void
assign_offsets_packs(MOID_T * q)9948 assign_offsets_packs (MOID_T * q)
9949 {
9950 for (; q != NO_MOID; FORWARD (q)) {
9951 if (EQUIVALENT (q) == NO_MOID && IS (q, STRUCT_SYMBOL)) {
9952 PACK_T *p = PACK (q);
9953 ADDR_T offset = 0;
9954 for (; p != NO_PACK; FORWARD (p)) {
9955 SIZE (p) = moid_size (MOID (p));
9956 OFFSET (p) = offset;
9957 offset += SIZE (p);
9958 }
9959 }
9960 }
9961 }
9962
9963 /**************************************/
9964 /* MODE checker and coercion inserter */
9965 /**************************************/
9966
9967
9968 /**
9969 @brief Give accurate error message.
9970 @param n Node in syntax tree.
9971 @param p Mode 1.
9972 @param q Mode 2.
9973 @param context Context.
9974 @param deflex Deflexing regime.
9975 @param depth Depth of recursion.
9976 @return Error text.
9977 **/
9978
9979 static char *
mode_error_text(NODE_T * n,MOID_T * p,MOID_T * q,int context,int deflex,int depth)9980 mode_error_text (NODE_T * n, MOID_T * p, MOID_T * q, int context, int deflex, int depth)
9981 {
9982 #define TAIL(z) (&(z)[strlen (z)])
9983 static char txt[BUFFER_SIZE];
9984 if (depth == 1) {
9985 txt[0] = NULL_CHAR;
9986 }
9987 if (IS (p, SERIES_MODE)) {
9988 PACK_T *u = PACK (p);
9989 if (u == NO_PACK) {
9990 ASSERT (snprintf (txt, SNPRINTF_SIZE, "empty mode-list") >= 0);
9991 } else {
9992 for (; u != NO_PACK; FORWARD (u)) {
9993 if (MOID (u) != NO_MOID) {
9994 if (IS (MOID (u), SERIES_MODE)) {
9995 (void) mode_error_text (n, MOID (u), q, context, deflex, depth + 1);
9996 } else if (!is_coercible (MOID (u), q, context, deflex)) {
9997 int len = (int) strlen (txt);
9998 if (len > BUFFER_SIZE / 2) {
9999 ASSERT (snprintf (TAIL (txt), SNPRINTF_SIZE, " etcetera") >= 0);
10000 } else {
10001 if (strlen (txt) > 0) {
10002 ASSERT (snprintf (TAIL (txt), SNPRINTF_SIZE, " and ") >= 0);
10003 }
10004 ASSERT (snprintf (TAIL (txt), SNPRINTF_SIZE, "%s", moid_to_string (MOID (u), MOID_ERROR_WIDTH, n)) >= 0);
10005 }
10006 }
10007 }
10008 }
10009 }
10010 if (depth == 1) {
10011 ASSERT (snprintf (TAIL (txt), SNPRINTF_SIZE, " cannot be coerced to %s", moid_to_string (q, MOID_ERROR_WIDTH, n)) >= 0);
10012 }
10013 } else if (IS (p, STOWED_MODE) && IS (q, FLEX_SYMBOL)) {
10014 PACK_T *u = PACK (p);
10015 if (u == NO_PACK) {
10016 ASSERT (snprintf (txt, SNPRINTF_SIZE, "empty mode-list") >= 0);
10017 } else {
10018 for (; u != NO_PACK; FORWARD (u)) {
10019 if (!is_coercible (MOID (u), SLICE (SUB (q)), context, deflex)) {
10020 int len = (int) strlen (txt);
10021 if (len > BUFFER_SIZE / 2) {
10022 ASSERT (snprintf (TAIL (txt), SNPRINTF_SIZE, " etcetera") >= 0);
10023 } else {
10024 if (strlen (txt) > 0) {
10025 ASSERT (snprintf (TAIL (txt), SNPRINTF_SIZE, " and ") >= 0);
10026 }
10027 ASSERT (snprintf (TAIL (txt), SNPRINTF_SIZE, "%s", moid_to_string (MOID (u), MOID_ERROR_WIDTH, n)) >= 0);
10028 }
10029 }
10030 }
10031 ASSERT (snprintf (TAIL (txt), SNPRINTF_SIZE, " cannot be coerced to %s", moid_to_string (SLICE (SUB (q)), MOID_ERROR_WIDTH, n)) >= 0);
10032 }
10033 } else if (IS (p, STOWED_MODE) && IS (q, ROW_SYMBOL)) {
10034 PACK_T *u = PACK (p);
10035 if (u == NO_PACK) {
10036 ASSERT (snprintf (txt, SNPRINTF_SIZE, "empty mode-list") >= 0);
10037 } else {
10038 for (; u != NO_PACK; FORWARD (u)) {
10039 if (!is_coercible (MOID (u), SLICE (q), context, deflex)) {
10040 int len = (int) strlen (txt);
10041 if (len > BUFFER_SIZE / 2) {
10042 ASSERT (snprintf (TAIL (txt), SNPRINTF_SIZE, " etcetera") >= 0);
10043 } else {
10044 if (strlen (txt) > 0) {
10045 ASSERT (snprintf (TAIL (txt), SNPRINTF_SIZE, " and ") >= 0);
10046 }
10047 ASSERT (snprintf (TAIL (txt), SNPRINTF_SIZE, "%s", moid_to_string (MOID (u), MOID_ERROR_WIDTH, n)) >= 0);
10048 }
10049 }
10050 }
10051 ASSERT (snprintf (TAIL (txt), SNPRINTF_SIZE, " cannot be coerced to %s", moid_to_string (SLICE (q), MOID_ERROR_WIDTH, n)) >= 0);
10052 }
10053 } else if (IS (p, STOWED_MODE) && (IS (q, PROC_SYMBOL) || IS (q, STRUCT_SYMBOL))) {
10054 PACK_T *u = PACK (p), *v = PACK (q);
10055 if (u == NO_PACK) {
10056 ASSERT (snprintf (txt, SNPRINTF_SIZE, "empty mode-list") >= 0);
10057 } else {
10058 for (; u != NO_PACK && v != NO_PACK; FORWARD (u), FORWARD (v)) {
10059 if (!is_coercible (MOID (u), MOID (v), context, deflex)) {
10060 int len = (int) strlen (txt);
10061 if (len > BUFFER_SIZE / 2) {
10062 ASSERT (snprintf (TAIL (txt), SNPRINTF_SIZE, " etcetera") >= 0);
10063 } else {
10064 if (strlen (txt) > 0) {
10065 ASSERT (snprintf (TAIL (txt), SNPRINTF_SIZE, " and ") >= 0);
10066 }
10067 ASSERT (snprintf (TAIL (txt), SNPRINTF_SIZE, "%s cannot be coerced to %s", moid_to_string (MOID (u), MOID_ERROR_WIDTH, n), moid_to_string (MOID (v), MOID_ERROR_WIDTH, n)) >= 0);
10068 }
10069 }
10070 }
10071 }
10072 }
10073 return (txt);
10074 #undef TAIL
10075 }
10076
10077 /**
10078 @brief Cannot coerce error.
10079 @param p Node in syntax tree.
10080 @param from Mode 1.
10081 @param to Mode 2.
10082 @param context Context.
10083 @param deflex Deflexing regime.
10084 @param att Attribute of context.
10085 **/
10086
10087 static void
cannot_coerce(NODE_T * p,MOID_T * from,MOID_T * to,int context,int deflex,int att)10088 cannot_coerce (NODE_T * p, MOID_T * from, MOID_T * to, int context, int deflex, int att)
10089 {
10090 char *txt = mode_error_text (p, from, to, context, deflex, 1);
10091 if (att == STOP) {
10092 if (strlen (txt) == 0) {
10093 diagnostic_node (A68_ERROR, p, "M cannot be coerced to M in C context", from, to, context);
10094 } else {
10095 diagnostic_node (A68_ERROR, p, "Y in C context", txt, context);
10096 }
10097 } else {
10098 if (strlen (txt) == 0) {
10099 diagnostic_node (A68_ERROR, p, "M cannot be coerced to M in C-A", from, to, context, att);
10100 } else {
10101 diagnostic_node (A68_ERROR, p, "Y in C-A", txt, context, att);
10102 }
10103 }
10104 }
10105
10106 /**
10107 @brief Make SOID data structure.
10108 @param s Soid buffer.
10109 @param sort Sort.
10110 @param type Mode.
10111 @param attribute Attribute.
10112 **/
10113
10114 static void
make_soid(SOID_T * s,int sort,MOID_T * type,int attribute)10115 make_soid (SOID_T * s, int sort, MOID_T * type, int attribute)
10116 {
10117 ATTRIBUTE (s) = attribute;
10118 SORT (s) = sort;
10119 MOID (s) = type;
10120 CAST (s) = A68_FALSE;
10121 }
10122
10123 /**
10124 @brief Driver for mode checker.
10125 @param p Node in syntax tree.
10126 **/
10127
10128 void
mode_checker(NODE_T * p)10129 mode_checker (NODE_T * p)
10130 {
10131 if (IS (p, PARTICULAR_PROGRAM)) {
10132 SOID_T x, y;
10133 top_soid_list = NO_SOID;
10134 make_soid (&x, STRONG, MODE (VOID), 0);
10135 mode_check_enclosed (SUB (p), &x, &y);
10136 MOID (p) = MOID (&y);
10137 }
10138 }
10139
10140 /**
10141 @brief Driver for coercion inserions.
10142 @param p Node in syntax tree.
10143 **/
10144
10145 void
coercion_inserter(NODE_T * p)10146 coercion_inserter (NODE_T * p)
10147 {
10148 if (IS (p, PARTICULAR_PROGRAM)) {
10149 SOID_T q;
10150 make_soid (&q, STRONG, MODE (VOID), 0);
10151 coerce_enclosed (SUB (p), &q);
10152 }
10153 }
10154
10155 /**
10156 @brief Whether mode is not well defined.
10157 @param p Mode.
10158 @return See brief description.
10159 **/
10160
10161 static BOOL_T
is_mode_isnt_well(MOID_T * p)10162 is_mode_isnt_well (MOID_T * p)
10163 {
10164 if (p == NO_MOID) {
10165 return (A68_TRUE);
10166 } else if (!IF_MODE_IS_WELL (p)) {
10167 return (A68_TRUE);
10168 } else if (PACK (p) != NO_PACK) {
10169 PACK_T *q = PACK (p);
10170 for (; q != NO_PACK; FORWARD (q)) {
10171 if (!IF_MODE_IS_WELL (MOID (q))) {
10172 return (A68_TRUE);
10173 }
10174 }
10175 }
10176 return (A68_FALSE);
10177 }
10178
10179 /**
10180 @brief Add SOID data to free chain.
10181 @param root Top soid list.
10182 **/
10183
10184 void
free_soid_list(SOID_T * root)10185 free_soid_list (SOID_T * root)
10186 {
10187 if (root != NO_SOID) {
10188 SOID_T *q;
10189 for (q = root; NEXT (q) != NO_SOID; FORWARD (q)) {
10190 /* skip */ ;
10191 }
10192 NEXT (q) = top_soid_list;
10193 top_soid_list = root;
10194 }
10195 }
10196
10197 /**
10198 @brief Add SOID data structure to soid list.
10199 @param root Top soid list.
10200 @param where Node in syntax tree.
10201 @param soid Entry to add.
10202 **/
10203
10204 static void
add_to_soid_list(SOID_T ** root,NODE_T * where,SOID_T * soid)10205 add_to_soid_list (SOID_T ** root, NODE_T * where, SOID_T * soid)
10206 {
10207 if (*root != NO_SOID) {
10208 add_to_soid_list (&(NEXT (*root)), where, soid);
10209 } else {
10210 SOID_T *new_one;
10211 if (top_soid_list == NO_SOID) {
10212 new_one = (SOID_T *) get_temp_heap_space ((size_t) SIZE_AL (SOID_T));
10213 } else {
10214 new_one = top_soid_list;
10215 FORWARD (top_soid_list);
10216 }
10217 make_soid (new_one, SORT (soid), MOID (soid), 0);
10218 NODE (new_one) = where;
10219 NEXT (new_one) = NO_SOID;
10220 *root = new_one;
10221 }
10222 }
10223
10224 /**
10225 @brief Pack soids in moid, gather resulting moids from terminators in a clause.
10226 @param top_sl Top soid list.
10227 @param attribute Mode attribute.
10228 @return Mode table entry.
10229 **/
10230
10231 static MOID_T *
pack_soids_in_moid(SOID_T * top_sl,int attribute)10232 pack_soids_in_moid (SOID_T * top_sl, int attribute)
10233 {
10234 MOID_T *x = new_moid ();
10235 PACK_T *t, **p;
10236 ATTRIBUTE (x) = attribute;
10237 DIM (x) = 0;
10238 SUB (x) = NO_MOID;
10239 EQUIVALENT (x) = NO_MOID;
10240 SLICE (x) = NO_MOID;
10241 DEFLEXED (x) = NO_MOID;
10242 NAME (x) = NO_MOID;
10243 NEXT (x) = NO_MOID;
10244 PACK (x) = NO_PACK;
10245 p = &(PACK (x));
10246 for (; top_sl != NO_SOID; FORWARD (top_sl)) {
10247 t = new_pack ();
10248 MOID (t) = MOID (top_sl);
10249 TEXT (t) = NO_TEXT;
10250 NODE (t) = NODE (top_sl);
10251 NEXT (t) = NO_PACK;
10252 DIM (x)++;
10253 *p = t;
10254 p = &NEXT (t);
10255 }
10256 (void) register_extra_mode (&TOP_MOID (&program), x);
10257 return (x);
10258 }
10259
10260 /**
10261 @brief Whether "p" is compatible with "q".
10262 @param p Mode.
10263 @param q Mode.
10264 @param deflex Deflexing regime.
10265 @return See brief description.
10266 **/
10267
10268 static BOOL_T
is_equal_modes(MOID_T * p,MOID_T * q,int deflex)10269 is_equal_modes (MOID_T * p, MOID_T * q, int deflex)
10270 {
10271 if (deflex == FORCE_DEFLEXING) {
10272 return (DEFLEX (p) == DEFLEX (q));
10273 } else if (deflex == ALIAS_DEFLEXING) {
10274 if (IS (p, REF_SYMBOL) && IS (q, REF_SYMBOL)) {
10275 return (p == q || DEFLEX (p) == q);
10276 } else if (ISNT (p, REF_SYMBOL) && ISNT (q, REF_SYMBOL)) {
10277 return (DEFLEX (p) == DEFLEX (q));
10278 }
10279 } else if (deflex == SAFE_DEFLEXING) {
10280 if (ISNT (p, REF_SYMBOL) && ISNT (q, REF_SYMBOL)) {
10281 return (DEFLEX (p) == DEFLEX (q));
10282 }
10283 }
10284 return (p == q);
10285 }
10286
10287 /**
10288 @brief Whether mode is deprefable.
10289 @param p Mode.
10290 @return See brief description.
10291 **/
10292
10293 BOOL_T
is_deprefable(MOID_T * p)10294 is_deprefable (MOID_T * p)
10295 {
10296 if (IS (p, REF_SYMBOL)) {
10297 return (A68_TRUE);
10298 } else {
10299 return ((BOOL_T) (IS (p, PROC_SYMBOL) && PACK (p) == NO_PACK));
10300 }
10301 }
10302
10303 /**
10304 @brief Depref mode once.
10305 @param p Mode.
10306 @return Single-depreffed mode.
10307 **/
10308
10309 static MOID_T *
depref_once(MOID_T * p)10310 depref_once (MOID_T * p)
10311 {
10312 if (IS_REF_FLEX (p)) {
10313 return (SUB_SUB (p));
10314 } else if (IS (p, REF_SYMBOL)) {
10315 return (SUB (p));
10316 } else if (IS (p, PROC_SYMBOL) && PACK (p) == NO_PACK) {
10317 return (SUB (p));
10318 } else {
10319 return (NO_MOID);
10320 }
10321 }
10322
10323 /**
10324 @brief Depref mode completely.
10325 @param p Mode.
10326 @return Completely depreffed mode.
10327 **/
10328
10329 MOID_T *
depref_completely(MOID_T * p)10330 depref_completely (MOID_T * p)
10331 {
10332 while (is_deprefable (p)) {
10333 p = depref_once (p);
10334 }
10335 return (p);
10336 }
10337
10338 /**
10339 @brief Deproc_completely.
10340 @param p Mode.
10341 @return Completely deprocedured mode.
10342 **/
10343
10344 static MOID_T *
deproc_completely(MOID_T * p)10345 deproc_completely (MOID_T * p)
10346 {
10347 while (IS (p, PROC_SYMBOL) && PACK (p) == NO_PACK) {
10348 p = depref_once (p);
10349 }
10350 return (p);
10351 }
10352
10353 /**
10354 @brief Depref rows.
10355 @param p Mode.
10356 @param q Mode.
10357 @return Possibly depreffed mode.
10358 **/
10359
10360 static MOID_T *
depref_rows(MOID_T * p,MOID_T * q)10361 depref_rows (MOID_T * p, MOID_T * q)
10362 {
10363 if (q == MODE (ROWS)) {
10364 while (is_deprefable (p)) {
10365 p = depref_once (p);
10366 }
10367 return (p);
10368 } else {
10369 return (q);
10370 }
10371 }
10372
10373 /**
10374 @brief Derow mode, strip FLEX and BOUNDS.
10375 @param p Mode.
10376 @return See brief description.
10377 **/
10378
10379 static MOID_T *
derow(MOID_T * p)10380 derow (MOID_T * p)
10381 {
10382 if (IS (p, ROW_SYMBOL) || IS (p, FLEX_SYMBOL)) {
10383 return (derow (SUB (p)));
10384 } else {
10385 return (p);
10386 }
10387 }
10388
10389 /**
10390 @brief Whether rows type.
10391 @param p Mode.
10392 @return See brief description.
10393 **/
10394
10395 static BOOL_T
is_rows_type(MOID_T * p)10396 is_rows_type (MOID_T * p)
10397 {
10398 switch (ATTRIBUTE (p)) {
10399 case ROW_SYMBOL:
10400 case FLEX_SYMBOL:
10401 {
10402 return (A68_TRUE);
10403 }
10404 case UNION_SYMBOL:
10405 {
10406 PACK_T *t = PACK (p);
10407 BOOL_T go_on = A68_TRUE;
10408 while (t != NO_PACK && go_on) {
10409 go_on &= is_rows_type (MOID (t));
10410 FORWARD (t);
10411 }
10412 return (go_on);
10413 }
10414 default:
10415 {
10416 return (A68_FALSE);
10417 }
10418 }
10419 }
10420
10421 /**
10422 @brief Whether mode is PROC (REF FILE) VOID or FORMAT.
10423 @param p Mode.
10424 @return See brief description.
10425 **/
10426
10427 static BOOL_T
is_proc_ref_file_void_or_format(MOID_T * p)10428 is_proc_ref_file_void_or_format (MOID_T * p)
10429 {
10430 if (p == MODE (PROC_REF_FILE_VOID)) {
10431 return (A68_TRUE);
10432 } else if (p == MODE (FORMAT)) {
10433 return (A68_TRUE);
10434 } else {
10435 return (A68_FALSE);
10436 }
10437 }
10438
10439 /**
10440 @brief Whether mode can be transput.
10441 @param p Mode.
10442 @param rw Indicates Read or Write.
10443 @return See brief description.
10444 **/
10445
10446 static BOOL_T
is_transput_mode(MOID_T * p,char rw)10447 is_transput_mode (MOID_T * p, char rw)
10448 {
10449 if (p == MODE (INT)) {
10450 return (A68_TRUE);
10451 } else if (p == MODE (LONG_INT)) {
10452 return (A68_TRUE);
10453 } else if (p == MODE (LONGLONG_INT)) {
10454 return (A68_TRUE);
10455 } else if (p == MODE (REAL)) {
10456 return (A68_TRUE);
10457 } else if (p == MODE (LONG_REAL)) {
10458 return (A68_TRUE);
10459 } else if (p == MODE (LONGLONG_REAL)) {
10460 return (A68_TRUE);
10461 } else if (p == MODE (BOOL)) {
10462 return (A68_TRUE);
10463 } else if (p == MODE (CHAR)) {
10464 return (A68_TRUE);
10465 } else if (p == MODE (BITS)) {
10466 return (A68_TRUE);
10467 } else if (p == MODE (LONG_BITS)) {
10468 return (A68_TRUE);
10469 } else if (p == MODE (LONGLONG_BITS)) {
10470 return (A68_TRUE);
10471 } else if (p == MODE (COMPLEX)) {
10472 return (A68_TRUE);
10473 } else if (p == MODE (LONG_COMPLEX)) {
10474 return (A68_TRUE);
10475 } else if (p == MODE (LONGLONG_COMPLEX)) {
10476 return (A68_TRUE);
10477 } else if (p == MODE (ROW_CHAR)) {
10478 return (A68_TRUE);
10479 } else if (p == MODE (STRING)) {
10480 return (A68_TRUE);
10481 } else if (p == MODE (SOUND)) {
10482 return (A68_TRUE);
10483 } else if (IS (p, UNION_SYMBOL) || IS (p, STRUCT_SYMBOL)) {
10484 PACK_T *q = PACK (p);
10485 BOOL_T k = A68_TRUE;
10486 for (; q != NO_PACK && k; FORWARD (q)) {
10487 k = (BOOL_T) (k & (is_transput_mode (MOID (q), rw) || is_proc_ref_file_void_or_format (MOID (q))));
10488 }
10489 return (k);
10490 } else if (IS (p, FLEX_SYMBOL)) {
10491 if (SUB (p) == MODE (ROW_CHAR)) {
10492 return (A68_TRUE);
10493 } else {
10494 return ((BOOL_T) (rw == 'w' ? is_transput_mode (SUB (p), rw) : A68_FALSE));
10495 }
10496 } else if (IS (p, ROW_SYMBOL)) {
10497 return ((BOOL_T) (is_transput_mode (SUB (p), rw) || is_proc_ref_file_void_or_format (SUB (p))));
10498 } else {
10499 return (A68_FALSE);
10500 }
10501 }
10502
10503 /**
10504 @brief Whether mode is printable.
10505 @param p Mode.
10506 @return See brief description.
10507 **/
10508
10509 static BOOL_T
is_printable_mode(MOID_T * p)10510 is_printable_mode (MOID_T * p)
10511 {
10512 if (is_proc_ref_file_void_or_format (p)) {
10513 return (A68_TRUE);
10514 } else {
10515 return (is_transput_mode (p, 'w'));
10516 }
10517 }
10518
10519 /**
10520 @brief Whether mode is readable.
10521 @param p Mode.
10522 @return See brief description.
10523 **/
10524
10525 static BOOL_T
is_readable_mode(MOID_T * p)10526 is_readable_mode (MOID_T * p)
10527 {
10528 if (is_proc_ref_file_void_or_format (p)) {
10529 return (A68_TRUE);
10530 } else {
10531 return ((BOOL_T) (IS (p, REF_SYMBOL) ? is_transput_mode (SUB (p), 'r') : A68_FALSE));
10532 }
10533 }
10534
10535 /**
10536 @brief Whether name struct.
10537 @param p Mode.
10538 @return See brief description.
10539 **/
10540
10541 static BOOL_T
is_name_struct(MOID_T * p)10542 is_name_struct (MOID_T * p)
10543 {
10544 return ((BOOL_T) (NAME (p) != NO_MOID ? IS (DEFLEX (SUB (p)), STRUCT_SYMBOL) : A68_FALSE));
10545 }
10546
10547 /**
10548 @brief Yield mode to unite to.
10549 @param m Mode.
10550 @param u United mode.
10551 @return See brief description.
10552 **/
10553
10554 MOID_T *
unites_to(MOID_T * m,MOID_T * u)10555 unites_to (MOID_T * m, MOID_T * u)
10556 {
10557 /* Uniting U (m) */
10558 MOID_T *v = NO_MOID;
10559 PACK_T *p;
10560 if (u == MODE (SIMPLIN) || u == MODE (SIMPLOUT)) {
10561 return (m);
10562 }
10563 for (p = PACK (u); p != NO_PACK; FORWARD (p)) {
10564 /* Prefer []->[] over []->FLEX [] */
10565 if (m == MOID (p)) {
10566 v = MOID (p);
10567 } else if (v == NO_MOID && DEFLEX (m) == DEFLEX (MOID (p))) {
10568 v = MOID (p);
10569 }
10570 }
10571 return (v);
10572 }
10573
10574 /**
10575 @brief Whether moid in pack.
10576 @param u Mode.
10577 @param v Pack.
10578 @param deflex Deflexing regime.
10579 @return See brief description.
10580 **/
10581
10582 static BOOL_T
is_moid_in_pack(MOID_T * u,PACK_T * v,int deflex)10583 is_moid_in_pack (MOID_T * u, PACK_T * v, int deflex)
10584 {
10585 for (; v != NO_PACK; FORWARD (v)) {
10586 if (is_equal_modes (u, MOID (v), deflex)) {
10587 return (A68_TRUE);
10588 }
10589 }
10590 return (A68_FALSE);
10591 }
10592
10593 /**
10594 @brief Whether "p" is a subset of "q".
10595 @param p Mode.
10596 @param q Mode.
10597 @param deflex Deflexing regime.
10598 @return See brief description.
10599 **/
10600
10601 BOOL_T
is_subset(MOID_T * p,MOID_T * q,int deflex)10602 is_subset (MOID_T * p, MOID_T * q, int deflex)
10603 {
10604 PACK_T *u = PACK (p);
10605 BOOL_T j = A68_TRUE;
10606 for (; u != NO_PACK && j; FORWARD (u)) {
10607 j = (BOOL_T) (j && is_moid_in_pack (MOID (u), PACK (q), deflex));
10608 }
10609 return (j);
10610 }
10611
10612 /**
10613 @brief Whether "p" can be united to UNION "q".
10614 @param p Mode.
10615 @param q Mode.
10616 @param deflex Deflexing regime.
10617 @return See brief description.
10618 **/
10619
10620 BOOL_T
is_unitable(MOID_T * p,MOID_T * q,int deflex)10621 is_unitable (MOID_T * p, MOID_T * q, int deflex)
10622 {
10623 if (IS (q, UNION_SYMBOL)) {
10624 if (IS (p, UNION_SYMBOL)) {
10625 return (is_subset (p, q, deflex));
10626 } else {
10627 return (is_moid_in_pack (p, PACK (q), deflex));
10628 }
10629 }
10630 return (A68_FALSE);
10631 }
10632
10633 /**
10634 @brief Whether all or some components of "u" can be firmly coerced to a component mode of "v"..
10635 @param u Mode.
10636 @param v Mode .
10637 @param all All coercible.
10638 @param some Some coercible.
10639 **/
10640
10641 static void
investigate_firm_relations(PACK_T * u,PACK_T * v,BOOL_T * all,BOOL_T * some)10642 investigate_firm_relations (PACK_T * u, PACK_T * v, BOOL_T * all, BOOL_T * some)
10643 {
10644 *all = A68_TRUE;
10645 *some = A68_FALSE;
10646 for (; v != NO_PACK; FORWARD (v)) {
10647 PACK_T *w;
10648 BOOL_T k = A68_FALSE;
10649 for (w = u; w != NO_PACK; FORWARD (w)) {
10650 k |= is_coercible (MOID (w), MOID (v), FIRM, FORCE_DEFLEXING);
10651 }
10652 *some |= k;
10653 *all &= k;
10654 }
10655 }
10656
10657 /**
10658 @brief Whether there is a soft path from "p" to "q".
10659 @param p Mode.
10660 @param q Mode.
10661 @param deflex Deflexing regime.
10662 @return See brief description.
10663 **/
10664
10665 static BOOL_T
is_softly_coercible(MOID_T * p,MOID_T * q,int deflex)10666 is_softly_coercible (MOID_T * p, MOID_T * q, int deflex)
10667 {
10668 if (is_equal_modes (p, q, deflex)) {
10669 return (A68_TRUE);
10670 } else if (IS (p, PROC_SYMBOL) && PACK (p) == NO_PACK) {
10671 return (is_softly_coercible (SUB (p), q, deflex));
10672 } else {
10673 return (A68_FALSE);
10674 }
10675 }
10676
10677 /**
10678 @brief Whether there is a weak path from "p" to "q".
10679 @param p Mode.
10680 @param q Mode.
10681 @param deflex Deflexing regime.
10682 @return See brief description.
10683 **/
10684
10685 static BOOL_T
is_weakly_coercible(MOID_T * p,MOID_T * q,int deflex)10686 is_weakly_coercible (MOID_T * p, MOID_T * q, int deflex)
10687 {
10688 if (is_equal_modes (p, q, deflex)) {
10689 return (A68_TRUE);
10690 } else if (is_deprefable (p)) {
10691 return (is_weakly_coercible (depref_once (p), q, deflex));
10692 } else {
10693 return (A68_FALSE);
10694 }
10695 }
10696
10697 /**
10698 @brief Whether there is a meek path from "p" to "q".
10699 @param p Mode.
10700 @param q Mode.
10701 @param deflex Deflexing regime.
10702 @return See brief description.
10703 **/
10704
10705 static BOOL_T
is_meekly_coercible(MOID_T * p,MOID_T * q,int deflex)10706 is_meekly_coercible (MOID_T * p, MOID_T * q, int deflex)
10707 {
10708 if (is_equal_modes (p, q, deflex)) {
10709 return (A68_TRUE);
10710 } else if (is_deprefable (p)) {
10711 return (is_meekly_coercible (depref_once (p), q, deflex));
10712 } else {
10713 return (A68_FALSE);
10714 }
10715 }
10716
10717 /**
10718 @brief Whether there is a firm path from "p" to "q".
10719 @param p Mode.
10720 @param q Mode.
10721 @param deflex Deflexing regime.
10722 @return See brief description.
10723 **/
10724
10725 static BOOL_T
is_firmly_coercible(MOID_T * p,MOID_T * q,int deflex)10726 is_firmly_coercible (MOID_T * p, MOID_T * q, int deflex)
10727 {
10728 if (is_equal_modes (p, q, deflex)) {
10729 return (A68_TRUE);
10730 } else if (q == MODE (ROWS) && is_rows_type (p)) {
10731 return (A68_TRUE);
10732 } else if (is_unitable (p, q, deflex)) {
10733 return (A68_TRUE);
10734 } else if (is_deprefable (p)) {
10735 return (is_firmly_coercible (depref_once (p), q, deflex));
10736 } else {
10737 return (A68_FALSE);
10738 }
10739 }
10740
10741 /**
10742 @brief Whether "p" widens to "q".
10743 @param p Mode.
10744 @param q Mode.
10745 @return See brief description.
10746 **/
10747
10748 static MOID_T *
widens_to(MOID_T * p,MOID_T * q)10749 widens_to (MOID_T * p, MOID_T * q)
10750 {
10751 if (p == MODE (INT)) {
10752 if (q == MODE (LONG_INT) || q == MODE (LONGLONG_INT) || q == MODE (LONG_REAL) || q == MODE (LONGLONG_REAL) || q == MODE (LONG_COMPLEX) || q == MODE (LONGLONG_COMPLEX)) {
10753 return (MODE (LONG_INT));
10754 } else if (q == MODE (REAL) || q == MODE (COMPLEX)) {
10755 return (MODE (REAL));
10756 } else {
10757 return (NO_MOID);
10758 }
10759 } else if (p == MODE (LONG_INT)) {
10760 if (q == MODE (LONGLONG_INT)) {
10761 return (MODE (LONGLONG_INT));
10762 } else if (q == MODE (LONG_REAL) || q == MODE (LONGLONG_REAL) || q == MODE (LONG_COMPLEX) || q == MODE (LONGLONG_COMPLEX)) {
10763 return (MODE (LONG_REAL));
10764 } else {
10765 return (NO_MOID);
10766 }
10767 } else if (p == MODE (LONGLONG_INT)) {
10768 if (q == MODE (LONGLONG_REAL) || q == MODE (LONGLONG_COMPLEX)) {
10769 return (MODE (LONGLONG_REAL));
10770 } else {
10771 return (NO_MOID);
10772 }
10773 } else if (p == MODE (REAL)) {
10774 if (q == MODE (LONG_REAL) || q == MODE (LONGLONG_REAL) || q == MODE (LONG_COMPLEX) || q == MODE (LONGLONG_COMPLEX)) {
10775 return (MODE (LONG_REAL));
10776 } else if (q == MODE (COMPLEX)) {
10777 return (MODE (COMPLEX));
10778 } else {
10779 return (NO_MOID);
10780 }
10781 } else if (p == MODE (COMPLEX)) {
10782 if (q == MODE (LONG_COMPLEX) || q == MODE (LONGLONG_COMPLEX)) {
10783 return (MODE (LONG_COMPLEX));
10784 } else {
10785 return (NO_MOID);
10786 }
10787 } else if (p == MODE (LONG_REAL)) {
10788 if (q == MODE (LONGLONG_REAL) || q == MODE (LONGLONG_COMPLEX)) {
10789 return (MODE (LONGLONG_REAL));
10790 } else if (q == MODE (LONG_COMPLEX)) {
10791 return (MODE (LONG_COMPLEX));
10792 } else {
10793 return (NO_MOID);
10794 }
10795 } else if (p == MODE (LONG_COMPLEX)) {
10796 if (q == MODE (LONGLONG_COMPLEX)) {
10797 return (MODE (LONGLONG_COMPLEX));
10798 } else {
10799 return (NO_MOID);
10800 }
10801 } else if (p == MODE (LONGLONG_REAL)) {
10802 if (q == MODE (LONGLONG_COMPLEX)) {
10803 return (MODE (LONGLONG_COMPLEX));
10804 } else {
10805 return (NO_MOID);
10806 }
10807 } else if (p == MODE (BITS)) {
10808 if (q == MODE (LONG_BITS) || q == MODE (LONGLONG_BITS)) {
10809 return (MODE (LONG_BITS));
10810 } else if (q == MODE (ROW_BOOL)) {
10811 return (MODE (ROW_BOOL));
10812 } else if (q == MODE (FLEX_ROW_BOOL)) {
10813 return (MODE (FLEX_ROW_BOOL));
10814 } else {
10815 return (NO_MOID);
10816 }
10817 } else if (p == MODE (LONG_BITS)) {
10818 if (q == MODE (LONGLONG_BITS)) {
10819 return (MODE (LONGLONG_BITS));
10820 } else if (q == MODE (ROW_BOOL)) {
10821 return (MODE (ROW_BOOL));
10822 } else if (q == MODE (FLEX_ROW_BOOL)) {
10823 return (MODE (FLEX_ROW_BOOL));
10824 } else {
10825 return (NO_MOID);
10826 }
10827 } else if (p == MODE (LONGLONG_BITS)) {
10828 if (q == MODE (ROW_BOOL)) {
10829 return (MODE (ROW_BOOL));
10830 } else if (q == MODE (FLEX_ROW_BOOL)) {
10831 return (MODE (FLEX_ROW_BOOL));
10832 } else {
10833 return (NO_MOID);
10834 }
10835 } else if (p == MODE (BYTES) && q == MODE (ROW_CHAR)) {
10836 return (MODE (ROW_CHAR));
10837 } else if (p == MODE (LONG_BYTES) && q == MODE (ROW_CHAR)) {
10838 return (MODE (ROW_CHAR));
10839 } else if (p == MODE (BYTES) && q == MODE (FLEX_ROW_CHAR)) {
10840 return (MODE (FLEX_ROW_CHAR));
10841 } else if (p == MODE (LONG_BYTES) && q == MODE (FLEX_ROW_CHAR)) {
10842 return (MODE (FLEX_ROW_CHAR));
10843 } else {
10844 return (NO_MOID);
10845 }
10846 }
10847
10848 /**
10849 @brief Whether "p" widens to "q".
10850 @param p Mode.
10851 @param q Mode.
10852 @return See brief description.
10853 **/
10854
10855 static BOOL_T
is_widenable(MOID_T * p,MOID_T * q)10856 is_widenable (MOID_T * p, MOID_T * q)
10857 {
10858 MOID_T *z = widens_to (p, q);
10859 if (z != NO_MOID) {
10860 return ((BOOL_T) (z == q ? A68_TRUE : is_widenable (z, q)));
10861 } else {
10862 return (A68_FALSE);
10863 }
10864 }
10865
10866 /**
10867 @brief Whether "p" is a REF ROW.
10868 @param p Mode.
10869 @return See brief description.
10870 **/
10871
10872 static BOOL_T
is_ref_row(MOID_T * p)10873 is_ref_row (MOID_T * p)
10874 {
10875 return ((BOOL_T) (NAME (p) != NO_MOID ? IS (DEFLEX (SUB (p)), ROW_SYMBOL) : A68_FALSE));
10876 }
10877
10878 /**
10879 @brief Whether strong name.
10880 @param p Mode.
10881 @param q Mode.
10882 @return See brief description.
10883 **/
10884
10885 static BOOL_T
is_strong_name(MOID_T * p,MOID_T * q)10886 is_strong_name (MOID_T * p, MOID_T * q)
10887 {
10888 if (p == q) {
10889 return (A68_TRUE);
10890 } else if (is_ref_row (q)) {
10891 return (is_strong_name (p, NAME (q)));
10892 } else {
10893 return (A68_FALSE);
10894 }
10895 }
10896
10897 /**
10898 @brief Whether strong slice.
10899 @param p Mode.
10900 @param q Mode.
10901 @return See brief description.
10902 **/
10903
10904 static BOOL_T
is_strong_slice(MOID_T * p,MOID_T * q)10905 is_strong_slice (MOID_T * p, MOID_T * q)
10906 {
10907 if (p == q || is_widenable (p, q)) {
10908 return (A68_TRUE);
10909 } else if (SLICE (q) != NO_MOID) {
10910 return (is_strong_slice (p, SLICE (q)));
10911 } else if (IS (q, FLEX_SYMBOL)) {
10912 return (is_strong_slice (p, SUB (q)));
10913 } else if (is_ref_row (q)) {
10914 return (is_strong_name (p, q));
10915 } else {
10916 return (A68_FALSE);
10917 }
10918 }
10919
10920 /**
10921 @brief Whether strongly coercible.
10922 @param p Mode.
10923 @param q Mode.
10924 @param deflex Deflexing regime.
10925 @return See brief description.
10926 **/
10927
10928 static BOOL_T
is_strongly_coercible(MOID_T * p,MOID_T * q,int deflex)10929 is_strongly_coercible (MOID_T * p, MOID_T * q, int deflex)
10930 {
10931 /* Keep this sequence of statements */
10932 if (is_equal_modes (p, q, deflex)) {
10933 return (A68_TRUE);
10934 } else if (q == MODE (VOID)) {
10935 return (A68_TRUE);
10936 } else if ((q == MODE (SIMPLIN) || q == MODE (ROW_SIMPLIN)) && is_readable_mode (p)) {
10937 return (A68_TRUE);
10938 } else if (q == MODE (ROWS) && is_rows_type (p)) {
10939 return (A68_TRUE);
10940 } else if (is_unitable (p, derow (q), deflex)) {
10941 return (A68_TRUE);
10942 }
10943 if (is_ref_row (q) && is_strong_name (p, q)) {
10944 return (A68_TRUE);
10945 } else if (SLICE (q) != NO_MOID && is_strong_slice (p, q)) {
10946 return (A68_TRUE);
10947 } else if (IS (q, FLEX_SYMBOL) && is_strong_slice (p, q)) {
10948 return (A68_TRUE);
10949 } else if (is_widenable (p, q)) {
10950 return (A68_TRUE);
10951 } else if (is_deprefable (p)) {
10952 return (is_strongly_coercible (depref_once (p), q, deflex));
10953 } else if (q == MODE (SIMPLOUT) || q == MODE (ROW_SIMPLOUT)) {
10954 return (is_printable_mode (p));
10955 } else {
10956 return (A68_FALSE);
10957 }
10958 }
10959
10960 /**
10961 @brief Whether firm.
10962 @param p Mode.
10963 @param q Mode.
10964 @return See brief description.
10965 **/
10966
10967 BOOL_T
is_firm(MOID_T * p,MOID_T * q)10968 is_firm (MOID_T * p, MOID_T * q)
10969 {
10970 return ((BOOL_T) (is_firmly_coercible (p, q, SAFE_DEFLEXING) || is_firmly_coercible (q, p, SAFE_DEFLEXING)));
10971 }
10972
10973 /**
10974 @brief Whether coercible stowed.
10975 @param p Mode.
10976 @param q Mode.
10977 @param c Context.
10978 @param deflex Deflexing regime.
10979 @return See brief description.
10980 **/
10981
10982 static BOOL_T
is_coercible_stowed(MOID_T * p,MOID_T * q,int c,int deflex)10983 is_coercible_stowed (MOID_T * p, MOID_T * q, int c, int deflex)
10984 {
10985 if (c == STRONG) {
10986 if (q == MODE (VOID)) {
10987 return (A68_TRUE);
10988 } else if (IS (q, FLEX_SYMBOL)) {
10989 PACK_T *u = PACK (p);
10990 BOOL_T j = A68_TRUE;
10991 for (; u != NO_PACK && j; FORWARD (u)) {
10992 j &= is_coercible (MOID (u), SLICE (SUB (q)), c, deflex);
10993 }
10994 return (j);
10995 } else if (IS (q, ROW_SYMBOL)) {
10996 PACK_T *u = PACK (p);
10997 BOOL_T j = A68_TRUE;
10998 for (; u != NO_PACK && j; FORWARD (u)) {
10999 j &= is_coercible (MOID (u), SLICE (q), c, deflex);
11000 }
11001 return (j);
11002 } else if (IS (q, PROC_SYMBOL) || IS (q, STRUCT_SYMBOL)) {
11003 PACK_T *u = PACK (p), *v = PACK (q);
11004 if (DIM (p) != DIM (q)) {
11005 return (A68_FALSE);
11006 } else {
11007 BOOL_T j = A68_TRUE;
11008 while (u != NO_PACK && v != NO_PACK && j) {
11009 j &= is_coercible (MOID (u), MOID (v), c, deflex);
11010 FORWARD (u);
11011 FORWARD (v);
11012 }
11013 return (j);
11014 }
11015 } else {
11016 return (A68_FALSE);
11017 }
11018 } else {
11019 return (A68_FALSE);
11020 }
11021 }
11022
11023 /**
11024 @brief Whether coercible series.
11025 @param p Mode.
11026 @param q Mode.
11027 @param c Context.
11028 @param deflex Deflexing regime.
11029 @return See brief description.
11030 **/
11031
11032 static BOOL_T
is_coercible_series(MOID_T * p,MOID_T * q,int c,int deflex)11033 is_coercible_series (MOID_T * p, MOID_T * q, int c, int deflex)
11034 {
11035 if (c != STRONG) {
11036 return (A68_FALSE);
11037 } else if (p == NO_MOID || q == NO_MOID) {
11038 return (A68_FALSE);
11039 } else if (IS (p, SERIES_MODE) && PACK (p) == NO_PACK) {
11040 return (A68_FALSE);
11041 } else if (IS (q, SERIES_MODE) && PACK (q) == NO_PACK) {
11042 return (A68_FALSE);
11043 } else if (PACK (p) == NO_PACK) {
11044 return (is_coercible (p, q, c, deflex));
11045 } else {
11046 PACK_T *u = PACK (p);
11047 BOOL_T j = A68_TRUE;
11048 for (; u != NO_PACK && j; FORWARD (u)) {
11049 if (MOID (u) != NO_MOID) {
11050 j &= is_coercible (MOID (u), q, c, deflex);
11051 }
11052 }
11053 return (j);
11054 }
11055 }
11056
11057 /**
11058 @brief Basic coercions.
11059 @param p Mode.
11060 @param q Mode.
11061 @param c Context.
11062 @param deflex Deflexing regime.
11063 @return See brief description.
11064 **/
11065
11066 static BOOL_T
basic_coercions(MOID_T * p,MOID_T * q,int c,int deflex)11067 basic_coercions (MOID_T * p, MOID_T * q, int c, int deflex)
11068 {
11069 if (is_equal_modes (p, q, deflex)) {
11070 return (A68_TRUE);
11071 } else if (c == NO_SORT) {
11072 return ((BOOL_T) (p == q));
11073 } else if (c == SOFT) {
11074 return (is_softly_coercible (p, q, deflex));
11075 } else if (c == WEAK) {
11076 return (is_weakly_coercible (p, q, deflex));
11077 } else if (c == MEEK) {
11078 return (is_meekly_coercible (p, q, deflex));
11079 } else if (c == FIRM) {
11080 return (is_firmly_coercible (p, q, deflex));
11081 } else if (c == STRONG) {
11082 return (is_strongly_coercible (p, q, deflex));
11083 } else {
11084 return (A68_FALSE);
11085 }
11086 }
11087
11088 /**
11089 @brief Whether "p" can be coerced to "q" in a "c" context.
11090 @param p Mode.
11091 @param q Mode.
11092 @param c Context.
11093 @param deflex Deflexing regime.
11094 @return See brief description.
11095 **/
11096
11097 BOOL_T
is_coercible(MOID_T * p,MOID_T * q,int c,int deflex)11098 is_coercible (MOID_T * p, MOID_T * q, int c, int deflex)
11099 {
11100 if (is_mode_isnt_well (p) || is_mode_isnt_well (q)) {
11101 return (A68_TRUE);
11102 } else if (is_equal_modes (p, q, deflex)) {
11103 return (A68_TRUE);
11104 } else if (p == MODE (HIP)) {
11105 return (A68_TRUE);
11106 } else if (IS (p, STOWED_MODE)) {
11107 return (is_coercible_stowed (p, q, c, deflex));
11108 } else if (IS (p, SERIES_MODE)) {
11109 return (is_coercible_series (p, q, c, deflex));
11110 } else if (p == MODE (VACUUM) && IS (DEFLEX (q), ROW_SYMBOL)) {
11111 return (A68_TRUE);
11112 } else {
11113 return (basic_coercions (p, q, c, deflex));
11114 }
11115 }
11116
11117 /**
11118 @brief Whether coercible in context.
11119 @param p Soid.
11120 @param q Soid.
11121 @param deflex Deflexing regime.
11122 @return See brief description.
11123 **/
11124
11125 static BOOL_T
is_coercible_in_context(SOID_T * p,SOID_T * q,int deflex)11126 is_coercible_in_context (SOID_T * p, SOID_T * q, int deflex)
11127 {
11128 if (SORT (p) != SORT (q)) {
11129 return (A68_FALSE);
11130 } else if (MOID (p) == MOID (q)) {
11131 return (A68_TRUE);
11132 } else {
11133 return (is_coercible (MOID (p), MOID (q), SORT (q), deflex));
11134 }
11135 }
11136
11137 /**
11138 @brief Whether list "y" is balanced.
11139 @param n Node in syntax tree.
11140 @param y Soid list.
11141 @param sort Sort.
11142 @return See brief description.
11143 **/
11144
11145 static BOOL_T
is_balanced(NODE_T * n,SOID_T * y,int sort)11146 is_balanced (NODE_T * n, SOID_T * y, int sort)
11147 {
11148 if (sort == STRONG) {
11149 return (A68_TRUE);
11150 } else {
11151 BOOL_T k = A68_FALSE;
11152 for (; y != NO_SOID && !k; FORWARD (y)) {
11153 k = (BOOL_T) (ISNT (MOID (y), STOWED_MODE));
11154 }
11155 if (k == A68_FALSE) {
11156 diagnostic_node (A68_ERROR, n, ERROR_NO_UNIQUE_MODE);
11157 }
11158 return (k);
11159 }
11160 }
11161
11162 /**
11163 @brief A moid from "m" to which all other members can be coerced.
11164 @param m Mode.
11165 @param sort Sort.
11166 @param return_depreffed Whether to depref.
11167 @param deflex Deflexing regime.
11168 @return See brief description.
11169 **/
11170
11171 MOID_T *
get_balanced_mode(MOID_T * m,int sort,BOOL_T return_depreffed,int deflex)11172 get_balanced_mode (MOID_T * m, int sort, BOOL_T return_depreffed, int deflex)
11173 {
11174 MOID_T *common = NO_MOID;
11175 if (m != NO_MOID && !is_mode_isnt_well (m) && IS (m, UNION_SYMBOL)) {
11176 int depref_level;
11177 BOOL_T go_on = A68_TRUE;
11178 /* Test for increasing depreffing */
11179 for (depref_level = 0; go_on; depref_level++) {
11180 PACK_T *p;
11181 go_on = A68_FALSE;
11182 /* Test the whole pack */
11183 for (p = PACK (m); p != NO_PACK; FORWARD (p)) {
11184 /* HIPs are not eligible of course */
11185 if (MOID (p) != MODE (HIP)) {
11186 MOID_T *candidate = MOID (p);
11187 int k;
11188 /* Depref as far as allowed */
11189 for (k = depref_level; k > 0 && is_deprefable (candidate); k--) {
11190 candidate = depref_once (candidate);
11191 }
11192 /* Only need testing if all allowed deprefs succeeded */
11193 if (k == 0) {
11194 PACK_T *q;
11195 MOID_T *to = (return_depreffed ? depref_completely (candidate) : candidate);
11196 BOOL_T all_coercible = A68_TRUE;
11197 go_on = A68_TRUE;
11198 for (q = PACK (m); q != NO_PACK && all_coercible; FORWARD (q)) {
11199 MOID_T *from = MOID (q);
11200 if (p != q && from != to) {
11201 all_coercible &= is_coercible (from, to, sort, deflex);
11202 }
11203 }
11204 /* If the pack is coercible to the candidate, we mark the candidate.
11205 We continue searching for longest series of REF REF PROC REF . */
11206 if (all_coercible) {
11207 MOID_T *mark = (return_depreffed ? MOID (p) : candidate);
11208 if (common == NO_MOID) {
11209 common = mark;
11210 } else if (IS (candidate, FLEX_SYMBOL) && DEFLEX (candidate) == common) {
11211 /* We prefer FLEX */
11212 common = mark;
11213 }
11214 }
11215 }
11216 }
11217 } /* for */
11218 } /* for */
11219 }
11220 return (common == NO_MOID ? m : common);
11221 }
11222
11223 /**
11224 @brief Whether we can search a common mode from a clause or not.
11225 @param att Attribute.
11226 @return See brief description.
11227 **/
11228
11229 static BOOL_T
clause_allows_balancing(int att)11230 clause_allows_balancing (int att)
11231 {
11232 switch (att) {
11233 case CLOSED_CLAUSE:
11234 case CONDITIONAL_CLAUSE:
11235 case CASE_CLAUSE:
11236 case SERIAL_CLAUSE:
11237 case CONFORMITY_CLAUSE:
11238 {
11239 return (A68_TRUE);
11240 }
11241 }
11242 return (A68_FALSE);
11243 }
11244
11245 /**
11246 @brief A unique mode from "z".
11247 @param z Soid.
11248 @param deflex Deflexing regime.
11249 @return See brief description.
11250 **/
11251
11252 static MOID_T *
determine_unique_mode(SOID_T * z,int deflex)11253 determine_unique_mode (SOID_T * z, int deflex)
11254 {
11255 if (z == NO_SOID) {
11256 return (NO_MOID);
11257 } else {
11258 MOID_T *x = MOID (z);
11259 if (is_mode_isnt_well (x)) {
11260 return (MODE (ERROR));
11261 }
11262 x = make_united_mode (x);
11263 if (clause_allows_balancing (ATTRIBUTE (z))) {
11264 return (get_balanced_mode (x, STRONG, NO_DEPREF, deflex));
11265 } else {
11266 return (x);
11267 }
11268 }
11269 }
11270
11271 /**
11272 @brief Give a warning when a value is silently discarded.
11273 @param p Node in syntax tree.
11274 @param x Soid.
11275 @param y Soid.
11276 @param c Context.
11277 **/
11278
11279 static void
warn_for_voiding(NODE_T * p,SOID_T * x,SOID_T * y,int c)11280 warn_for_voiding (NODE_T * p, SOID_T * x, SOID_T * y, int c)
11281 {
11282 (void) c;
11283 if (CAST (x) == A68_FALSE) {
11284 if (MOID (x) == MODE (VOID) && MOID (y) != MODE (ERROR) && !(MOID (y) == MODE (VOID) || !is_nonproc (MOID (y)))) {
11285 if (IS (p, FORMULA)) {
11286 diagnostic_node (A68_WARNING | A68_FORCE_DIAGNOSTICS, p, WARNING_VOIDED, MOID (y));
11287 } else {
11288 diagnostic_node (A68_WARNING, p, WARNING_VOIDED, MOID (y));
11289 }
11290 }
11291 }
11292 }
11293
11294 /**
11295 @brief Warn for things that are likely unintended.
11296 @param p Node in syntax tree.
11297 @param m Moid.
11298 @param c Context.
11299 @param u Attribute.
11300 **/
11301
11302 static void
semantic_pitfall(NODE_T * p,MOID_T * m,int c,int u)11303 semantic_pitfall (NODE_T * p, MOID_T * m, int c, int u)
11304 {
11305 /*
11306 semantic_pitfall: warn for things that are likely unintended, for instance
11307 REF INT i := LOC INT := 0, which should probably be
11308 REF INT i = LOC INT := 0.
11309 */
11310 if (IS (p, u)) {
11311 diagnostic_node (A68_WARNING, p, WARNING_UNINTENDED, MOID (p), u, m, c);
11312 } else if (is_one_of (p, UNIT, TERTIARY, SECONDARY, PRIMARY, STOP)) {
11313 semantic_pitfall (SUB (p), m, c, u);
11314 }
11315 }
11316
11317 /**
11318 @brief Insert coercion "a" in the tree.
11319 @param l Node in syntax tree.
11320 @param a Attribute.
11321 @param m (coerced) moid
11322 **/
11323
11324 static void
make_coercion(NODE_T * l,int a,MOID_T * m)11325 make_coercion (NODE_T * l, int a, MOID_T * m)
11326 {
11327 make_sub (l, l, a);
11328 MOID (l) = depref_rows (MOID (l), m);
11329 }
11330
11331 /**
11332 @brief Make widening coercion.
11333 @param n Node in syntax tree.
11334 @param p Mode.
11335 @param q Mode.
11336 **/
11337
11338 static void
make_widening_coercion(NODE_T * n,MOID_T * p,MOID_T * q)11339 make_widening_coercion (NODE_T * n, MOID_T * p, MOID_T * q)
11340 {
11341 MOID_T *z = widens_to (p, q);
11342 make_coercion (n, WIDENING, z);
11343 if (z != q) {
11344 make_widening_coercion (n, z, q);
11345 }
11346 }
11347
11348 /**
11349 @brief Make ref rowing coercion.
11350 @param n Node in syntax tree.
11351 @param p Mode.
11352 @param q Mode.
11353 **/
11354
11355 static void
make_ref_rowing_coercion(NODE_T * n,MOID_T * p,MOID_T * q)11356 make_ref_rowing_coercion (NODE_T * n, MOID_T * p, MOID_T * q)
11357 {
11358 if (DEFLEX (p) != DEFLEX (q)) {
11359 if (is_widenable (p, q)) {
11360 make_widening_coercion (n, p, q);
11361 } else if (is_ref_row (q)) {
11362 make_ref_rowing_coercion (n, p, NAME (q));
11363 make_coercion (n, ROWING, q);
11364 }
11365 }
11366 }
11367
11368 /**
11369 @brief Make rowing coercion.
11370 @param n Node in syntax tree.
11371 @param p Mode.
11372 @param q Mode.
11373 **/
11374
11375 static void
make_rowing_coercion(NODE_T * n,MOID_T * p,MOID_T * q)11376 make_rowing_coercion (NODE_T * n, MOID_T * p, MOID_T * q)
11377 {
11378 if (DEFLEX (p) != DEFLEX (q)) {
11379 if (is_widenable (p, q)) {
11380 make_widening_coercion (n, p, q);
11381 } else if (SLICE (q) != NO_MOID) {
11382 make_rowing_coercion (n, p, SLICE (q));
11383 make_coercion (n, ROWING, q);
11384 } else if (IS (q, FLEX_SYMBOL)) {
11385 make_rowing_coercion (n, p, SUB (q));
11386 } else if (is_ref_row (q)) {
11387 make_ref_rowing_coercion (n, p, q);
11388 }
11389 }
11390 }
11391
11392 /**
11393 @brief Make uniting coercion.
11394 @param n Node in syntax tree.
11395 @param q Mode.
11396 **/
11397
11398 static void
make_uniting_coercion(NODE_T * n,MOID_T * q)11399 make_uniting_coercion (NODE_T * n, MOID_T * q)
11400 {
11401 make_coercion (n, UNITING, derow (q));
11402 if (IS (q, ROW_SYMBOL) || IS (q, FLEX_SYMBOL)) {
11403 make_rowing_coercion (n, derow (q), q);
11404 }
11405 }
11406
11407 /**
11408 @brief Make depreffing coercion.
11409 @param n Node in syntax tree.
11410 @param p Mode.
11411 @param q Mode.
11412 **/
11413
11414 static void
make_depreffing_coercion(NODE_T * n,MOID_T * p,MOID_T * q)11415 make_depreffing_coercion (NODE_T * n, MOID_T * p, MOID_T * q)
11416 {
11417 if (DEFLEX (p) == DEFLEX (q)) {
11418 return;
11419 } else if (q == MODE (SIMPLOUT) && is_printable_mode (p)) {
11420 make_coercion (n, UNITING, q);
11421 } else if (q == MODE (ROW_SIMPLOUT) && is_printable_mode (p)) {
11422 make_coercion (n, UNITING, MODE (SIMPLOUT));
11423 make_coercion (n, ROWING, MODE (ROW_SIMPLOUT));
11424 } else if (q == MODE (SIMPLIN) && is_readable_mode (p)) {
11425 make_coercion (n, UNITING, q);
11426 } else if (q == MODE (ROW_SIMPLIN) && is_readable_mode (p)) {
11427 make_coercion (n, UNITING, MODE (SIMPLIN));
11428 make_coercion (n, ROWING, MODE (ROW_SIMPLIN));
11429 } else if (q == MODE (ROWS) && is_rows_type (p)) {
11430 make_coercion (n, UNITING, MODE (ROWS));
11431 MOID (n) = MODE (ROWS);
11432 } else if (is_widenable (p, q)) {
11433 make_widening_coercion (n, p, q);
11434 } else if (is_unitable (p, derow (q), SAFE_DEFLEXING)) {
11435 make_uniting_coercion (n, q);
11436 } else if (is_ref_row (q) && is_strong_name (p, q)) {
11437 make_ref_rowing_coercion (n, p, q);
11438 } else if (SLICE (q) != NO_MOID && is_strong_slice (p, q)) {
11439 make_rowing_coercion (n, p, q);
11440 } else if (IS (q, FLEX_SYMBOL) && is_strong_slice (p, q)) {
11441 make_rowing_coercion (n, p, q);
11442 } else if (IS (p, REF_SYMBOL)) {
11443 MOID_T *r = depref_once (p);
11444 make_coercion (n, DEREFERENCING, r);
11445 make_depreffing_coercion (n, r, q);
11446 } else if (IS (p, PROC_SYMBOL) && PACK (p) == NO_PACK) {
11447 MOID_T *r = SUB (p);
11448 make_coercion (n, DEPROCEDURING, r);
11449 make_depreffing_coercion (n, r, q);
11450 } else if (p != q) {
11451 cannot_coerce (n, p, q, NO_SORT, SKIP_DEFLEXING, 0);
11452 }
11453 }
11454
11455 /**
11456 @brief Whether p is a nonproc mode (that is voided directly).
11457 @param p Mode.
11458 @return See brief description.
11459 **/
11460
11461 static BOOL_T
is_nonproc(MOID_T * p)11462 is_nonproc (MOID_T * p)
11463 {
11464 if (IS (p, PROC_SYMBOL) && PACK (p) == NO_PACK) {
11465 return (A68_FALSE);
11466 } else if (IS (p, REF_SYMBOL)) {
11467 return (is_nonproc (SUB (p)));
11468 } else {
11469 return (A68_TRUE);
11470 }
11471 }
11472
11473 /**
11474 @brief Make_void: voiden in an appropriate way.
11475 @param p Node in syntax tree.
11476 @param q Mode.
11477 **/
11478
11479 static void
make_void(NODE_T * p,MOID_T * q)11480 make_void (NODE_T * p, MOID_T * q)
11481 {
11482 switch (ATTRIBUTE (p)) {
11483 case ASSIGNATION:
11484 case IDENTITY_RELATION:
11485 case GENERATOR:
11486 case CAST:
11487 case DENOTATION:
11488 {
11489 make_coercion (p, VOIDING, MODE (VOID));
11490 return;
11491 }
11492 }
11493 /* MORFs are an involved case */
11494 switch (ATTRIBUTE (p)) {
11495 case SELECTION:
11496 case SLICE:
11497 case ROUTINE_TEXT:
11498 case FORMULA:
11499 case CALL:
11500 case IDENTIFIER:
11501 {
11502 /* A nonproc moid value is eliminated directly */
11503 if (is_nonproc (q)) {
11504 make_coercion (p, VOIDING, MODE (VOID));
11505 return;
11506 } else {
11507 /* Descend the chain of e.g. REF PROC .. until a nonproc moid remains */
11508 MOID_T *z = q;
11509 while (!is_nonproc (z)) {
11510 if (IS (z, REF_SYMBOL)) {
11511 make_coercion (p, DEREFERENCING, SUB (z));
11512 }
11513 if (IS (z, PROC_SYMBOL) && NODE_PACK (p) == NO_PACK) {
11514 make_coercion (p, DEPROCEDURING, SUB (z));
11515 }
11516 z = SUB (z);
11517 }
11518 if (z != MODE (VOID)) {
11519 make_coercion (p, VOIDING, MODE (VOID));
11520 }
11521 return;
11522 }
11523 }
11524 }
11525 /* All other is voided straight away */
11526 make_coercion (p, VOIDING, MODE (VOID));
11527 }
11528
11529 /**
11530 @brief Make strong coercion.
11531 @param n Node in syntax tree.
11532 @param p Mode.
11533 @param q Mode.
11534 **/
11535
11536 static void
make_strong(NODE_T * n,MOID_T * p,MOID_T * q)11537 make_strong (NODE_T * n, MOID_T * p, MOID_T * q)
11538 {
11539 if (q == MODE (VOID) && p != MODE (VOID)) {
11540 make_void (n, p);
11541 } else {
11542 make_depreffing_coercion (n, p, q);
11543 }
11544 }
11545
11546 /**
11547 @brief Mode check on bounds.
11548 @param p Node in syntax tree.
11549 **/
11550
11551 static void
mode_check_bounds(NODE_T * p)11552 mode_check_bounds (NODE_T * p)
11553 {
11554 if (p == NO_NODE) {
11555 return;
11556 } else if (IS (p, UNIT)) {
11557 SOID_T x, y;
11558 make_soid (&x, STRONG, MODE (INT), 0);
11559 mode_check_unit (p, &x, &y);
11560 if (!is_coercible_in_context (&y, &x, SAFE_DEFLEXING)) {
11561 cannot_coerce (p, MOID (&y), MODE (INT), MEEK, SAFE_DEFLEXING, UNIT);
11562 }
11563 mode_check_bounds (NEXT (p));
11564 } else {
11565 mode_check_bounds (SUB (p));
11566 mode_check_bounds (NEXT (p));
11567 }
11568 }
11569
11570 /**
11571 @brief Mode check declarer.
11572 @param p Node in syntax tree.
11573 **/
11574
11575 static void
mode_check_declarer(NODE_T * p)11576 mode_check_declarer (NODE_T * p)
11577 {
11578 if (p == NO_NODE) {
11579 return;
11580 } else if (IS (p, BOUNDS)) {
11581 mode_check_bounds (SUB (p));
11582 mode_check_declarer (NEXT (p));
11583 } else {
11584 mode_check_declarer (SUB (p));
11585 mode_check_declarer (NEXT (p));
11586 }
11587 }
11588
11589 /**
11590 @brief Mode check identity declaration.
11591 @param p Node in syntax tree.
11592 **/
11593
11594 static void
mode_check_identity_declaration(NODE_T * p)11595 mode_check_identity_declaration (NODE_T * p)
11596 {
11597 if (p != NO_NODE) {
11598 switch (ATTRIBUTE (p)) {
11599 case DECLARER:
11600 {
11601 mode_check_declarer (SUB (p));
11602 mode_check_identity_declaration (NEXT (p));
11603 break;
11604 }
11605 case DEFINING_IDENTIFIER:
11606 {
11607 SOID_T x, y;
11608 make_soid (&x, STRONG, MOID (p), 0);
11609 mode_check_unit (NEXT_NEXT (p), &x, &y);
11610 if (!is_coercible_in_context (&y, &x, SAFE_DEFLEXING)) {
11611 cannot_coerce (NEXT_NEXT (p), MOID (&y), MOID (&x), STRONG, SAFE_DEFLEXING, UNIT);
11612 } else if (MOID (&x) != MOID (&y)) {
11613 /* Check for instance, REF INT i = LOC REF INT */
11614 semantic_pitfall (NEXT_NEXT (p), MOID (&x), IDENTITY_DECLARATION, GENERATOR);
11615 }
11616 break;
11617 }
11618 default:
11619 {
11620 mode_check_identity_declaration (SUB (p));
11621 mode_check_identity_declaration (NEXT (p));
11622 break;
11623 }
11624 }
11625 }
11626 }
11627
11628 /**
11629 @brief Mode check variable declaration.
11630 @param p Node in syntax tree.
11631 **/
11632
11633 static void
mode_check_variable_declaration(NODE_T * p)11634 mode_check_variable_declaration (NODE_T * p)
11635 {
11636 if (p != NO_NODE) {
11637 switch (ATTRIBUTE (p)) {
11638 case DECLARER:
11639 {
11640 mode_check_declarer (SUB (p));
11641 mode_check_variable_declaration (NEXT (p));
11642 break;
11643 }
11644 case DEFINING_IDENTIFIER:
11645 {
11646 if (whether (p, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, UNIT, STOP)) {
11647 SOID_T x, y;
11648 make_soid (&x, STRONG, SUB_MOID (p), 0);
11649 mode_check_unit (NEXT_NEXT (p), &x, &y);
11650 if (!is_coercible_in_context (&y, &x, FORCE_DEFLEXING)) {
11651 cannot_coerce (p, MOID (&y), MOID (&x), STRONG, FORCE_DEFLEXING, UNIT);
11652 } else if (SUB_MOID (&x) != MOID (&y)) {
11653 /* Check for instance, REF INT i = LOC REF INT */
11654 semantic_pitfall (NEXT_NEXT (p), MOID (&x), VARIABLE_DECLARATION, GENERATOR);
11655 }
11656 }
11657 break;
11658 }
11659 default:
11660 {
11661 mode_check_variable_declaration (SUB (p));
11662 mode_check_variable_declaration (NEXT (p));
11663 break;
11664 }
11665 }
11666 }
11667 }
11668
11669 /**
11670 @brief Mode check routine text.
11671 @param p Node in syntax tree.
11672 @param y Resulting soid.
11673 **/
11674
11675 static void
mode_check_routine_text(NODE_T * p,SOID_T * y)11676 mode_check_routine_text (NODE_T * p, SOID_T * y)
11677 {
11678 SOID_T w;
11679 if (IS (p, PARAMETER_PACK)) {
11680 mode_check_declarer (SUB (p));
11681 FORWARD (p);
11682 }
11683 mode_check_declarer (SUB (p));
11684 make_soid (&w, STRONG, MOID (p), 0);
11685 mode_check_unit (NEXT_NEXT (p), &w, y);
11686 if (!is_coercible_in_context (y, &w, FORCE_DEFLEXING)) {
11687 cannot_coerce (NEXT_NEXT (p), MOID (y), MOID (&w), STRONG, FORCE_DEFLEXING, UNIT);
11688 }
11689 }
11690
11691 /**
11692 @brief Mode check proc declaration.
11693 @param p Node in syntax tree.
11694 **/
11695
11696 static void
mode_check_proc_declaration(NODE_T * p)11697 mode_check_proc_declaration (NODE_T * p)
11698 {
11699 if (p == NO_NODE) {
11700 return;
11701 } else if (IS (p, ROUTINE_TEXT)) {
11702 SOID_T x, y;
11703 make_soid (&x, STRONG, NO_MOID, 0);
11704 mode_check_routine_text (SUB (p), &y);
11705 } else {
11706 mode_check_proc_declaration (SUB (p));
11707 mode_check_proc_declaration (NEXT (p));
11708 }
11709 }
11710
11711 /**
11712 @brief Mode check brief op declaration.
11713 @param p Node in syntax tree.
11714 **/
11715
11716 static void
mode_check_brief_op_declaration(NODE_T * p)11717 mode_check_brief_op_declaration (NODE_T * p)
11718 {
11719 if (p == NO_NODE) {
11720 return;
11721 } else if (IS (p, DEFINING_OPERATOR)) {
11722 SOID_T y;
11723 if (MOID (p) != MOID (NEXT_NEXT (p))) {
11724 SOID_T y2, x;
11725 make_soid (&y2, NO_SORT, MOID (NEXT_NEXT (p)), 0);
11726 make_soid (&x, NO_SORT, MOID (p), 0);
11727 cannot_coerce (NEXT_NEXT (p), MOID (&y2), MOID (&x), STRONG, SKIP_DEFLEXING, ROUTINE_TEXT);
11728 }
11729 mode_check_routine_text (SUB (NEXT_NEXT (p)), &y);
11730 } else {
11731 mode_check_brief_op_declaration (SUB (p));
11732 mode_check_brief_op_declaration (NEXT (p));
11733 }
11734 }
11735
11736 /**
11737 @brief Mode check op declaration.
11738 @param p Node in syntax tree.
11739 **/
11740
11741 static void
mode_check_op_declaration(NODE_T * p)11742 mode_check_op_declaration (NODE_T * p)
11743 {
11744 if (p == NO_NODE) {
11745 return;
11746 } else if (IS (p, DEFINING_OPERATOR)) {
11747 SOID_T y, x;
11748 make_soid (&x, STRONG, MOID (p), 0);
11749 mode_check_unit (NEXT_NEXT (p), &x, &y);
11750 if (!is_coercible_in_context (&y, &x, SAFE_DEFLEXING)) {
11751 cannot_coerce (NEXT_NEXT (p), MOID (&y), MOID (&x), STRONG, SAFE_DEFLEXING, UNIT);
11752 }
11753 } else {
11754 mode_check_op_declaration (SUB (p));
11755 mode_check_op_declaration (NEXT (p));
11756 }
11757 }
11758
11759 /**
11760 @brief Mode check declaration list.
11761 @param p Node in syntax tree.
11762 **/
11763
11764 static void
mode_check_declaration_list(NODE_T * p)11765 mode_check_declaration_list (NODE_T * p)
11766 {
11767 if (p != NO_NODE) {
11768 switch (ATTRIBUTE (p)) {
11769 case IDENTITY_DECLARATION:
11770 {
11771 mode_check_identity_declaration (SUB (p));
11772 break;
11773 }
11774 case VARIABLE_DECLARATION:
11775 {
11776 mode_check_variable_declaration (SUB (p));
11777 break;
11778 }
11779 case MODE_DECLARATION:
11780 {
11781 mode_check_declarer (SUB (p));
11782 break;
11783 }
11784 case PROCEDURE_DECLARATION:
11785 case PROCEDURE_VARIABLE_DECLARATION:
11786 {
11787 mode_check_proc_declaration (SUB (p));
11788 break;
11789 }
11790 case BRIEF_OPERATOR_DECLARATION:
11791 {
11792 mode_check_brief_op_declaration (SUB (p));
11793 break;
11794 }
11795 case OPERATOR_DECLARATION:
11796 {
11797 mode_check_op_declaration (SUB (p));
11798 break;
11799 }
11800 default:
11801 {
11802 mode_check_declaration_list (SUB (p));
11803 mode_check_declaration_list (NEXT (p));
11804 break;
11805 }
11806 }
11807 }
11808 }
11809
11810 /**
11811 @brief Mode check serial clause.
11812 @param r Resulting soids.
11813 @param p Node in syntax tree.
11814 @param x Expected soid.
11815 @param k Whether statement yields a value other than VOID.
11816 **/
11817
11818 static void
mode_check_serial(SOID_T ** r,NODE_T * p,SOID_T * x,BOOL_T k)11819 mode_check_serial (SOID_T ** r, NODE_T * p, SOID_T * x, BOOL_T k)
11820 {
11821 if (p == NO_NODE) {
11822 return;
11823 } else if (IS (p, INITIALISER_SERIES)) {
11824 mode_check_serial (r, SUB (p), x, A68_FALSE);
11825 mode_check_serial (r, NEXT (p), x, k);
11826 } else if (IS (p, DECLARATION_LIST)) {
11827 mode_check_declaration_list (SUB (p));
11828 } else if (is_one_of (p, LABEL, SEMI_SYMBOL, EXIT_SYMBOL, STOP)) {
11829 mode_check_serial (r, NEXT (p), x, k);
11830 } else if (is_one_of (p, SERIAL_CLAUSE, ENQUIRY_CLAUSE, STOP)) {
11831 if (NEXT (p) != NO_NODE) {
11832 if (IS (NEXT (p), EXIT_SYMBOL) || IS (NEXT (p), END_SYMBOL) || IS (NEXT (p), CLOSE_SYMBOL)) {
11833 mode_check_serial (r, SUB (p), x, A68_TRUE);
11834 } else {
11835 mode_check_serial (r, SUB (p), x, A68_FALSE);
11836 }
11837 mode_check_serial (r, NEXT (p), x, k);
11838 } else {
11839 mode_check_serial (r, SUB (p), x, A68_TRUE);
11840 }
11841 } else if (IS (p, LABELED_UNIT)) {
11842 mode_check_serial (r, SUB (p), x, k);
11843 } else if (IS (p, UNIT)) {
11844 SOID_T y;
11845 if (k) {
11846 mode_check_unit (p, x, &y);
11847 } else {
11848 SOID_T w;
11849 make_soid (&w, STRONG, MODE (VOID), 0);
11850 mode_check_unit (p, &w, &y);
11851 }
11852 if (NEXT (p) != NO_NODE) {
11853 mode_check_serial (r, NEXT (p), x, k);
11854 } else {
11855 if (k) {
11856 add_to_soid_list (r, p, &y);
11857 }
11858 }
11859 }
11860 }
11861
11862 /**
11863 @brief Mode check serial clause units.
11864 @param p Node in syntax tree.
11865 @param x Expected soid.
11866 @param y Resulting soid.
11867 @param att Attribute (SERIAL or ENQUIRY).
11868 **/
11869
11870 static void
mode_check_serial_units(NODE_T * p,SOID_T * x,SOID_T * y,int att)11871 mode_check_serial_units (NODE_T * p, SOID_T * x, SOID_T * y, int att)
11872 {
11873 SOID_T *top_sl = NO_SOID;
11874 (void) att;
11875 mode_check_serial (&top_sl, SUB (p), x, A68_TRUE);
11876 if (is_balanced (p, top_sl, SORT (x))) {
11877 MOID_T *result = pack_soids_in_moid (top_sl, SERIES_MODE);
11878 make_soid (y, SORT (x), result, SERIAL_CLAUSE);
11879 } else {
11880 make_soid (y, SORT (x), (MOID (x) != NO_MOID ? MOID (x) : MODE (ERROR)), 0);
11881 }
11882 free_soid_list (top_sl);
11883 }
11884
11885 /**
11886 @brief Mode check unit list.
11887 @param r Resulting soids.
11888 @param p Node in syntax tree.
11889 @param x Expected soid.
11890 **/
11891
11892 static void
mode_check_unit_list(SOID_T ** r,NODE_T * p,SOID_T * x)11893 mode_check_unit_list (SOID_T ** r, NODE_T * p, SOID_T * x)
11894 {
11895 if (p == NO_NODE) {
11896 return;
11897 } else if (IS (p, UNIT_LIST)) {
11898 mode_check_unit_list (r, SUB (p), x);
11899 mode_check_unit_list (r, NEXT (p), x);
11900 } else if (IS (p, COMMA_SYMBOL)) {
11901 mode_check_unit_list (r, NEXT (p), x);
11902 } else if (IS (p, UNIT)) {
11903 SOID_T y;
11904 mode_check_unit (p, x, &y);
11905 add_to_soid_list (r, p, &y);
11906 mode_check_unit_list (r, NEXT (p), x);
11907 }
11908 }
11909
11910 /**
11911 @brief Mode check struct display.
11912 @param r Resulting soids.
11913 @param p Node in syntax tree.
11914 @param fields Pack.
11915 **/
11916
11917 static void
mode_check_struct_display(SOID_T ** r,NODE_T * p,PACK_T ** fields)11918 mode_check_struct_display (SOID_T ** r, NODE_T * p, PACK_T ** fields)
11919 {
11920 if (p == NO_NODE) {
11921 return;
11922 } else if (IS (p, UNIT_LIST)) {
11923 mode_check_struct_display (r, SUB (p), fields);
11924 mode_check_struct_display (r, NEXT (p), fields);
11925 } else if (IS (p, COMMA_SYMBOL)) {
11926 mode_check_struct_display (r, NEXT (p), fields);
11927 } else if (IS (p, UNIT)) {
11928 SOID_T x, y;
11929 if (*fields != NO_PACK) {
11930 make_soid (&x, STRONG, MOID (*fields), 0);
11931 FORWARD (*fields);
11932 } else {
11933 make_soid (&x, STRONG, NO_MOID, 0);
11934 }
11935 mode_check_unit (p, &x, &y);
11936 add_to_soid_list (r, p, &y);
11937 mode_check_struct_display (r, NEXT (p), fields);
11938 }
11939 }
11940
11941 /**
11942 @brief Mode check get specified moids.
11943 @param p Node in syntax tree.
11944 @param u United mode to add to.
11945 **/
11946
11947 static void
mode_check_get_specified_moids(NODE_T * p,MOID_T * u)11948 mode_check_get_specified_moids (NODE_T * p, MOID_T * u)
11949 {
11950 for (; p != NO_NODE; FORWARD (p)) {
11951 if (is_one_of (p, SPECIFIED_UNIT_LIST, SPECIFIED_UNIT, STOP)) {
11952 mode_check_get_specified_moids (SUB (p), u);
11953 } else if (IS (p, SPECIFIER)) {
11954 MOID_T *m = MOID (NEXT_SUB (p));
11955 add_mode_to_pack (&(PACK (u)), m, NO_TEXT, NODE (m));
11956 }
11957 }
11958 }
11959
11960 /**
11961 @brief Mode check specified unit list.
11962 @param r Resulting soids.
11963 @param p Node in syntax tree.
11964 @param x Expected soid.
11965 @param u Resulting united mode.
11966 **/
11967
11968 static void
mode_check_specified_unit_list(SOID_T ** r,NODE_T * p,SOID_T * x,MOID_T * u)11969 mode_check_specified_unit_list (SOID_T ** r, NODE_T * p, SOID_T * x, MOID_T * u)
11970 {
11971 for (; p != NO_NODE; FORWARD (p)) {
11972 if (is_one_of (p, SPECIFIED_UNIT_LIST, SPECIFIED_UNIT, STOP)) {
11973 mode_check_specified_unit_list (r, SUB (p), x, u);
11974 } else if (IS (p, SPECIFIER)) {
11975 MOID_T *m = MOID (NEXT_SUB (p));
11976 if (u != NO_MOID && !is_unitable (m, u, SAFE_DEFLEXING)) {
11977 diagnostic_node (A68_ERROR, p, ERROR_NO_COMPONENT, m, u);
11978 }
11979 } else if (IS (p, UNIT)) {
11980 SOID_T y;
11981 mode_check_unit (p, x, &y);
11982 add_to_soid_list (r, p, &y);
11983 }
11984 }
11985 }
11986
11987 /**
11988 @brief Mode check united case parts.
11989 @param ry Resulting soids.
11990 @param p Node in syntax tree.
11991 @param x Expected soid.
11992 **/
11993
11994 static void
mode_check_united_case_parts(SOID_T ** ry,NODE_T * p,SOID_T * x)11995 mode_check_united_case_parts (SOID_T ** ry, NODE_T * p, SOID_T * x)
11996 {
11997 SOID_T enq_expct, enq_yield;
11998 MOID_T *u = NO_MOID, *v = NO_MOID, *w = NO_MOID;
11999 /* Check the CASE part and deduce the united mode */
12000 make_soid (&enq_expct, STRONG, NO_MOID, 0);
12001 mode_check_serial_units (NEXT_SUB (p), &enq_expct, &enq_yield, ENQUIRY_CLAUSE);
12002 /* Deduce the united mode from the enquiry clause */
12003 u = depref_completely (MOID (&enq_yield));
12004 u = make_united_mode (u);
12005 u = depref_completely (u);
12006 /* Also deduce the united mode from the specifiers */
12007 v = new_moid ();
12008 ATTRIBUTE (v) = SERIES_MODE;
12009 mode_check_get_specified_moids (NEXT_SUB (NEXT (p)), v);
12010 v = make_united_mode (v);
12011 /* Determine a resulting union */
12012 if (u == MODE (HIP)) {
12013 w = v;
12014 } else {
12015 if (IS (u, UNION_SYMBOL)) {
12016 BOOL_T uv, vu, some;
12017 investigate_firm_relations (PACK (u), PACK (v), &uv, &some);
12018 investigate_firm_relations (PACK (v), PACK (u), &vu, &some);
12019 if (uv && vu) {
12020 /* Every component has a specifier */
12021 w = u;
12022 } else if (!uv && !vu) {
12023 /* Hmmmm ... let the coercer sort it out */
12024 w = u;
12025 } else {
12026 /* This is all the balancing we allow here for the moment. Firmly related
12027 subsets are not valid so we absorb them. If this doesn't solve it then we
12028 get a coercion-error later */
12029 w = absorb_related_subsets (u);
12030 }
12031 } else {
12032 diagnostic_node (A68_ERROR, NEXT_SUB (p), ERROR_NO_UNION, u);
12033 return;
12034 }
12035 }
12036 MOID (SUB (p)) = w;
12037 FORWARD (p);
12038 /* Check the IN part */
12039 mode_check_specified_unit_list (ry, NEXT_SUB (p), x, w);
12040 /* OUSE, OUT, ESAC */
12041 if ((FORWARD (p)) != NO_NODE) {
12042 if (is_one_of (p, OUT_PART, CHOICE, STOP)) {
12043 mode_check_serial (ry, NEXT_SUB (p), x, A68_TRUE);
12044 } else if (is_one_of (p, CONFORMITY_OUSE_PART, BRIEF_CONFORMITY_OUSE_PART, STOP)) {
12045 mode_check_united_case_parts (ry, SUB (p), x);
12046 }
12047 }
12048 }
12049
12050 /**
12051 @brief Mode check united case.
12052 @param p Node in syntax tree.
12053 @param x Expected soid.
12054 @param y Resulting soid.
12055 **/
12056
12057 static void
mode_check_united_case(NODE_T * p,SOID_T * x,SOID_T * y)12058 mode_check_united_case (NODE_T * p, SOID_T * x, SOID_T * y)
12059 {
12060 SOID_T *top_sl = NO_SOID;
12061 MOID_T *z;
12062 mode_check_united_case_parts (&top_sl, p, x);
12063 if (!is_balanced (p, top_sl, SORT (x))) {
12064 if (MOID (x) != NO_MOID) {
12065 make_soid (y, SORT (x), MOID (x), CONFORMITY_CLAUSE);
12066
12067 } else {
12068 make_soid (y, SORT (x), MODE (ERROR), 0);
12069 }
12070 } else {
12071 z = pack_soids_in_moid (top_sl, SERIES_MODE);
12072 make_soid (y, SORT (x), z, CONFORMITY_CLAUSE);
12073 }
12074 free_soid_list (top_sl);
12075 }
12076
12077 /**
12078 @brief Mode check unit list 2.
12079 @param p Node in syntax tree.
12080 @param x Expected soid.
12081 @param y Resulting soid.
12082 **/
12083
12084 static void
mode_check_unit_list_2(NODE_T * p,SOID_T * x,SOID_T * y)12085 mode_check_unit_list_2 (NODE_T * p, SOID_T * x, SOID_T * y)
12086 {
12087 SOID_T *top_sl = NO_SOID;
12088 if (MOID (x) != NO_MOID) {
12089 if (IS (MOID (x), FLEX_SYMBOL)) {
12090 SOID_T y2;
12091 make_soid (&y2, SORT (x), SLICE (SUB_MOID (x)), 0);
12092 mode_check_unit_list (&top_sl, SUB (p), &y2);
12093 } else if (IS (MOID (x), ROW_SYMBOL)) {
12094 SOID_T y2;
12095 make_soid (&y2, SORT (x), SLICE (MOID (x)), 0);
12096 mode_check_unit_list (&top_sl, SUB (p), &y2);
12097 } else if (IS (MOID (x), STRUCT_SYMBOL)) {
12098 PACK_T *y2 = PACK (MOID (x));
12099 mode_check_struct_display (&top_sl, SUB (p), &y2);
12100 } else {
12101 mode_check_unit_list (&top_sl, SUB (p), x);
12102 }
12103 } else {
12104 mode_check_unit_list (&top_sl, SUB (p), x);
12105 }
12106 make_soid (y, STRONG, pack_soids_in_moid (top_sl, STOWED_MODE), 0);
12107 free_soid_list (top_sl);
12108 }
12109
12110 /**
12111 @brief Mode check closed.
12112 @param p Node in syntax tree.
12113 @param x Expected soid.
12114 @param y Resulting soid.
12115 **/
12116
12117 static void
mode_check_closed(NODE_T * p,SOID_T * x,SOID_T * y)12118 mode_check_closed (NODE_T * p, SOID_T * x, SOID_T * y)
12119 {
12120 if (p == NO_NODE) {
12121 return;
12122 } else if (IS (p, SERIAL_CLAUSE)) {
12123 mode_check_serial_units (p, x, y, SERIAL_CLAUSE);
12124 } else if (is_one_of (p, OPEN_SYMBOL, BEGIN_SYMBOL, STOP)) {
12125 mode_check_closed (NEXT (p), x, y);
12126 }
12127 MOID (p) = MOID (y);
12128 }
12129
12130 /**
12131 @brief Mode check collateral.
12132 @param p Node in syntax tree.
12133 @param x Expected soid.
12134 @param y Resulting soid.
12135 **/
12136
12137 static void
mode_check_collateral(NODE_T * p,SOID_T * x,SOID_T * y)12138 mode_check_collateral (NODE_T * p, SOID_T * x, SOID_T * y)
12139 {
12140 if (p == NO_NODE) {
12141 return;
12142 } else if (whether (p, BEGIN_SYMBOL, END_SYMBOL, STOP)
12143 || whether (p, OPEN_SYMBOL, CLOSE_SYMBOL, STOP)) {
12144 if (SORT (x) == STRONG) {
12145 if (MOID (x) == NO_MOID) {
12146 diagnostic_node (A68_ERROR, p, ERROR_VACUO, "REF MODE");
12147 } else {
12148 MOID_T *z = (IS (MOID (x), FLEX_SYMBOL) ? SUB_MOID (x) : MOID (x));
12149 make_soid (y, STRONG, MODE (VACUUM), 0);
12150 if (SUB (z) != NO_MOID && HAS_ROWS (SUB (z))) {
12151 diagnostic_node (A68_ERROR, p, ERROR_VACUUM, "REF", MOID (x));
12152 }
12153 }
12154 } else {
12155 make_soid (y, STRONG, MODE (UNDEFINED), 0);
12156 }
12157 } else {
12158 if (IS (p, UNIT_LIST)) {
12159 mode_check_unit_list_2 (p, x, y);
12160 } else if (is_one_of (p, OPEN_SYMBOL, BEGIN_SYMBOL, STOP)) {
12161 mode_check_collateral (NEXT (p), x, y);
12162 }
12163 MOID (p) = MOID (y);
12164 }
12165 }
12166
12167 /**
12168 @brief Mode check conditional 2.
12169 @param ry Resulting soids.
12170 @param p Node in syntax tree.
12171 @param x Expected soid.
12172 **/
12173
12174 static void
mode_check_conditional_2(SOID_T ** ry,NODE_T * p,SOID_T * x)12175 mode_check_conditional_2 (SOID_T ** ry, NODE_T * p, SOID_T * x)
12176 {
12177 SOID_T enq_expct, enq_yield;
12178 make_soid (&enq_expct, STRONG, MODE (BOOL), 0);
12179 mode_check_serial_units (NEXT_SUB (p), &enq_expct, &enq_yield, ENQUIRY_CLAUSE);
12180 if (!is_coercible_in_context (&enq_yield, &enq_expct, SAFE_DEFLEXING)) {
12181 cannot_coerce (p, MOID (&enq_yield), MOID (&enq_expct), MEEK, SAFE_DEFLEXING, ENQUIRY_CLAUSE);
12182 }
12183 FORWARD (p);
12184 mode_check_serial (ry, NEXT_SUB (p), x, A68_TRUE);
12185 if ((FORWARD (p)) != NO_NODE) {
12186 if (is_one_of (p, ELSE_PART, CHOICE, STOP)) {
12187 mode_check_serial (ry, NEXT_SUB (p), x, A68_TRUE);
12188 } else if (is_one_of (p, ELIF_PART, BRIEF_ELIF_PART, STOP)) {
12189 mode_check_conditional_2 (ry, SUB (p), x);
12190 }
12191 }
12192 }
12193
12194 /**
12195 @brief Mode check conditional.
12196 @param p Node in syntax tree.
12197 @param x Expected soid.
12198 @param y Resulting soid.
12199 **/
12200
12201 static void
mode_check_conditional(NODE_T * p,SOID_T * x,SOID_T * y)12202 mode_check_conditional (NODE_T * p, SOID_T * x, SOID_T * y)
12203 {
12204 SOID_T *top_sl = NO_SOID;
12205 MOID_T *z;
12206 mode_check_conditional_2 (&top_sl, p, x);
12207 if (!is_balanced (p, top_sl, SORT (x))) {
12208 if (MOID (x) != NO_MOID) {
12209 make_soid (y, SORT (x), MOID (x), CONDITIONAL_CLAUSE);
12210 } else {
12211 make_soid (y, SORT (x), MODE (ERROR), 0);
12212 }
12213 } else {
12214 z = pack_soids_in_moid (top_sl, SERIES_MODE);
12215 make_soid (y, SORT (x), z, CONDITIONAL_CLAUSE);
12216 }
12217 free_soid_list (top_sl);
12218 }
12219
12220 /**
12221 @brief Mode check int case 2.
12222 @param ry Resulting soids.
12223 @param p Node in syntax tree.
12224 @param x Expected soid.
12225 **/
12226
12227 static void
mode_check_int_case_2(SOID_T ** ry,NODE_T * p,SOID_T * x)12228 mode_check_int_case_2 (SOID_T ** ry, NODE_T * p, SOID_T * x)
12229 {
12230 SOID_T enq_expct, enq_yield;
12231 make_soid (&enq_expct, STRONG, MODE (INT), 0);
12232 mode_check_serial_units (NEXT_SUB (p), &enq_expct, &enq_yield, ENQUIRY_CLAUSE);
12233 if (!is_coercible_in_context (&enq_yield, &enq_expct, SAFE_DEFLEXING)) {
12234 cannot_coerce (p, MOID (&enq_yield), MOID (&enq_expct), MEEK, SAFE_DEFLEXING, ENQUIRY_CLAUSE);
12235 }
12236 FORWARD (p);
12237 mode_check_unit_list (ry, NEXT_SUB (p), x);
12238 if ((FORWARD (p)) != NO_NODE) {
12239 if (is_one_of (p, OUT_PART, CHOICE, STOP)) {
12240 mode_check_serial (ry, NEXT_SUB (p), x, A68_TRUE);
12241 } else if (is_one_of (p, CASE_OUSE_PART, BRIEF_OUSE_PART, STOP)) {
12242 mode_check_int_case_2 (ry, SUB (p), x);
12243 }
12244 }
12245 }
12246
12247 /**
12248 @brief Mode check int case.
12249 @param p Node in syntax tree.
12250 @param x Expected soid.
12251 @param y Resulting soid.
12252 **/
12253
12254 static void
mode_check_int_case(NODE_T * p,SOID_T * x,SOID_T * y)12255 mode_check_int_case (NODE_T * p, SOID_T * x, SOID_T * y)
12256 {
12257 SOID_T *top_sl = NO_SOID;
12258 MOID_T *z;
12259 mode_check_int_case_2 (&top_sl, p, x);
12260 if (!is_balanced (p, top_sl, SORT (x))) {
12261 if (MOID (x) != NO_MOID) {
12262 make_soid (y, SORT (x), MOID (x), CASE_CLAUSE);
12263 } else {
12264 make_soid (y, SORT (x), MODE (ERROR), 0);
12265 }
12266 } else {
12267 z = pack_soids_in_moid (top_sl, SERIES_MODE);
12268 make_soid (y, SORT (x), z, CASE_CLAUSE);
12269 }
12270 free_soid_list (top_sl);
12271 }
12272
12273 /**
12274 @brief Mode check loop 2.
12275 @param p Node in syntax tree.
12276 @param y Resulting soid.
12277 **/
12278
12279 static void
mode_check_loop_2(NODE_T * p,SOID_T * y)12280 mode_check_loop_2 (NODE_T * p, SOID_T * y)
12281 {
12282 if (p == NO_NODE) {
12283 return;
12284 } else if (IS (p, FOR_PART)) {
12285 mode_check_loop_2 (NEXT (p), y);
12286 } else if (is_one_of (p, FROM_PART, BY_PART, TO_PART, STOP)) {
12287 SOID_T ix, iy;
12288 make_soid (&ix, STRONG, MODE (INT), 0);
12289 mode_check_unit (NEXT_SUB (p), &ix, &iy);
12290 if (!is_coercible_in_context (&iy, &ix, SAFE_DEFLEXING)) {
12291 cannot_coerce (NEXT_SUB (p), MOID (&iy), MODE (INT), MEEK, SAFE_DEFLEXING, ENQUIRY_CLAUSE);
12292 }
12293 mode_check_loop_2 (NEXT (p), y);
12294 } else if (IS (p, WHILE_PART)) {
12295 SOID_T enq_expct, enq_yield;
12296 make_soid (&enq_expct, STRONG, MODE (BOOL), 0);
12297 mode_check_serial_units (NEXT_SUB (p), &enq_expct, &enq_yield, ENQUIRY_CLAUSE);
12298 if (!is_coercible_in_context (&enq_yield, &enq_expct, SAFE_DEFLEXING)) {
12299 cannot_coerce (p, MOID (&enq_yield), MOID (&enq_expct), MEEK, SAFE_DEFLEXING, ENQUIRY_CLAUSE);
12300 }
12301 mode_check_loop_2 (NEXT (p), y);
12302 } else if (is_one_of (p, DO_PART, ALT_DO_PART, STOP)) {
12303 SOID_T *z = NO_SOID;
12304 SOID_T ix;
12305 NODE_T *do_p = NEXT_SUB (p), *un_p;
12306 make_soid (&ix, STRONG, MODE (VOID), 0);
12307 if (IS (do_p, SERIAL_CLAUSE)) {
12308 mode_check_serial (&z, do_p, &ix, A68_TRUE);
12309 un_p = NEXT (do_p);
12310 } else {
12311 un_p = do_p;
12312 }
12313 if (un_p != NO_NODE && IS (un_p, UNTIL_PART)) {
12314 SOID_T enq_expct, enq_yield;
12315 make_soid (&enq_expct, STRONG, MODE (BOOL), 0);
12316 mode_check_serial_units (NEXT_SUB (un_p), &enq_expct, &enq_yield, ENQUIRY_CLAUSE);
12317 if (!is_coercible_in_context (&enq_yield, &enq_expct, SAFE_DEFLEXING)) {
12318 cannot_coerce (un_p, MOID (&enq_yield), MOID (&enq_expct), MEEK, SAFE_DEFLEXING, ENQUIRY_CLAUSE);
12319 }
12320 }
12321 free_soid_list (z);
12322 }
12323 }
12324
12325 /**
12326 @brief Mode check loop.
12327 @param p Node in syntax tree.
12328 @param y Resulting soid.
12329 **/
12330
12331 static void
mode_check_loop(NODE_T * p,SOID_T * y)12332 mode_check_loop (NODE_T * p, SOID_T * y)
12333 {
12334 SOID_T *z = NO_SOID;
12335 mode_check_loop_2 (p, /* y */ z);
12336 make_soid (y, STRONG, MODE (VOID), 0);
12337 }
12338
12339 /**
12340 @brief Mode check enclosed.
12341 @param p Node in syntax tree.
12342 @param x Expected soid.
12343 @param y Resulting soid.
12344 **/
12345
12346 void
mode_check_enclosed(NODE_T * p,SOID_T * x,SOID_T * y)12347 mode_check_enclosed (NODE_T * p, SOID_T * x, SOID_T * y)
12348 {
12349 if (p == NO_NODE) {
12350 return;
12351 } else if (IS (p, ENCLOSED_CLAUSE)) {
12352 mode_check_enclosed (SUB (p), x, y);
12353 } else if (IS (p, CLOSED_CLAUSE)) {
12354 mode_check_closed (SUB (p), x, y);
12355 } else if (IS (p, PARALLEL_CLAUSE)) {
12356 mode_check_collateral (SUB (NEXT_SUB (p)), x, y);
12357 make_soid (y, STRONG, MODE (VOID), 0);
12358 MOID (NEXT_SUB (p)) = MODE (VOID);
12359 } else if (IS (p, COLLATERAL_CLAUSE)) {
12360 mode_check_collateral (SUB (p), x, y);
12361 } else if (IS (p, CONDITIONAL_CLAUSE)) {
12362 mode_check_conditional (SUB (p), x, y);
12363 } else if (IS (p, CASE_CLAUSE)) {
12364 mode_check_int_case (SUB (p), x, y);
12365 } else if (IS (p, CONFORMITY_CLAUSE)) {
12366 mode_check_united_case (SUB (p), x, y);
12367 } else if (IS (p, LOOP_CLAUSE)) {
12368 mode_check_loop (SUB (p), y);
12369 }
12370 MOID (p) = MOID (y);
12371 }
12372
12373 /**
12374 @brief Search table for operator.
12375 @param t Tag chain to search.
12376 @param n Name of operator.
12377 @param x Lhs mode.
12378 @param y Rhs mode.
12379 @return Tag entry.
12380 **/
12381
12382 static TAG_T *
search_table_for_operator(TAG_T * t,char * n,MOID_T * x,MOID_T * y)12383 search_table_for_operator (TAG_T * t, char *n, MOID_T * x, MOID_T * y)
12384 {
12385 if (is_mode_isnt_well (x)) {
12386 return (error_tag);
12387 } else if (y != NO_MOID && is_mode_isnt_well (y)) {
12388 return (error_tag);
12389 }
12390 for (; t != NO_TAG; FORWARD (t)) {
12391 if (NSYMBOL (NODE (t)) == n) {
12392 PACK_T *p = PACK (MOID (t));
12393 if (is_coercible (x, MOID (p), FIRM, ALIAS_DEFLEXING)) {
12394 FORWARD (p);
12395 if (p == NO_PACK && y == NO_MOID) {
12396 /* Matched in case of a monadic */
12397 return (t);
12398 } else if (p != NO_PACK && y != NO_MOID && is_coercible (y, MOID (p), FIRM, ALIAS_DEFLEXING)) {
12399 /* Matched in case of a dyadic */
12400 return (t);
12401 }
12402 }
12403 }
12404 }
12405 return (NO_TAG);
12406 }
12407
12408 /**
12409 @brief Search chain of symbol tables and return matching operator "x n y" or "n x".
12410 @param s Symbol table to start search.
12411 @param n Name of token.
12412 @param x Lhs mode.
12413 @param y Rhs mode.
12414 @return Tag entry.
12415 **/
12416
12417 static TAG_T *
search_table_chain_for_operator(TABLE_T * s,char * n,MOID_T * x,MOID_T * y)12418 search_table_chain_for_operator (TABLE_T * s, char *n, MOID_T * x, MOID_T * y)
12419 {
12420 if (is_mode_isnt_well (x)) {
12421 return (error_tag);
12422 } else if (y != NO_MOID && is_mode_isnt_well (y)) {
12423 return (error_tag);
12424 }
12425 while (s != NO_TABLE) {
12426 TAG_T *z = search_table_for_operator (OPERATORS (s), n, x, y);
12427 if (z != NO_TAG) {
12428 return (z);
12429 }
12430 BACKWARD (s);
12431 }
12432 return (NO_TAG);
12433 }
12434
12435 /**
12436 @brief Return a matching operator "x n y".
12437 @param s Symbol table to start search.
12438 @param n Name of token.
12439 @param x Lhs mode.
12440 @param y Rhs mode.
12441 @return Tag entry.
12442 **/
12443
12444 static TAG_T *
find_operator(TABLE_T * s,char * n,MOID_T * x,MOID_T * y)12445 find_operator (TABLE_T * s, char *n, MOID_T * x, MOID_T * y)
12446 {
12447 /* Coercions to operand modes are FIRM */
12448 TAG_T *z;
12449 MOID_T *u, *v;
12450 /* (A) Catch exceptions first */
12451 if (x == NO_MOID && y == NO_MOID) {
12452 return (NO_TAG);
12453 } else if (is_mode_isnt_well (x)) {
12454 return (error_tag);
12455 } else if (y != NO_MOID && is_mode_isnt_well (y)) {
12456 return (error_tag);
12457 }
12458 /* (B) MONADs */
12459 if (x != NO_MOID && y == NO_MOID) {
12460 z = search_table_chain_for_operator (s, n, x, NO_MOID);
12461 if (z != NO_TAG) {
12462 return (z);
12463 } else {
12464 /* (B.2) A little trick to allow - (0, 1) or ABS (1, long pi) */
12465 if (is_coercible (x, MODE (COMPLEX), STRONG, SAFE_DEFLEXING)) {
12466 z = search_table_for_operator (OPERATORS (a68g_standenv), n, MODE (COMPLEX), NO_MOID);
12467 if (z != NO_TAG) {
12468 return (z);
12469 }
12470 }
12471 if (is_coercible (x, MODE (LONG_COMPLEX), STRONG, SAFE_DEFLEXING)) {
12472 z = search_table_for_operator (OPERATORS (a68g_standenv), n, MODE (LONG_COMPLEX), NO_MOID);
12473 if (z != NO_TAG) {
12474 return (z);
12475 }
12476 }
12477 if (is_coercible (x, MODE (LONGLONG_COMPLEX), STRONG, SAFE_DEFLEXING)) {
12478 z = search_table_for_operator (OPERATORS (a68g_standenv), n, MODE (LONGLONG_COMPLEX), NO_MOID);
12479 }
12480 }
12481 return (NO_TAG);
12482 }
12483 /* (C) DYADs */
12484 z = search_table_chain_for_operator (s, n, x, y);
12485 if (z != NO_TAG) {
12486 return (z);
12487 }
12488 /* (C.2) Vector and matrix "strong coercions" in standard environ */
12489 u = depref_completely (x);
12490 v = depref_completely (y);
12491 if ((u == MODE (ROW_REAL) || u == MODE (ROWROW_REAL))
12492 || (v == MODE (ROW_REAL) || v == MODE (ROWROW_REAL))
12493 || (u == MODE (ROW_COMPLEX) || u == MODE (ROWROW_COMPLEX))
12494 || (v == MODE (ROW_COMPLEX) || v == MODE (ROWROW_COMPLEX))) {
12495 if (u == MODE (INT)) {
12496 z = search_table_for_operator (OPERATORS (a68g_standenv), n, MODE (REAL), y);
12497 if (z != NO_TAG) {
12498 return (z);
12499 }
12500 z = search_table_for_operator (OPERATORS (a68g_standenv), n, MODE (COMPLEX), y);
12501 if (z != NO_TAG) {
12502 return (z);
12503 }
12504 } else if (v == MODE (INT)) {
12505 z = search_table_for_operator (OPERATORS (a68g_standenv), n, x, MODE (REAL));
12506 if (z != NO_TAG) {
12507 return (z);
12508 }
12509 z = search_table_for_operator (OPERATORS (a68g_standenv), n, x, MODE (COMPLEX));
12510 if (z != NO_TAG) {
12511 return (z);
12512 }
12513 } else if (u == MODE (REAL)) {
12514 z = search_table_for_operator (OPERATORS (a68g_standenv), n, MODE (COMPLEX), y);
12515 if (z != NO_TAG) {
12516 return (z);
12517 }
12518 } else if (v == MODE (REAL)) {
12519 z = search_table_for_operator (OPERATORS (a68g_standenv), n, x, MODE (COMPLEX));
12520 if (z != NO_TAG) {
12521 return (z);
12522 }
12523 }
12524 }
12525 /* (C.3) Look in standenv for an appropriate cross-term */
12526 u = make_series_from_moids (x, y);
12527 u = make_united_mode (u);
12528 v = get_balanced_mode (u, STRONG, NO_DEPREF, SAFE_DEFLEXING);
12529 z = search_table_for_operator (OPERATORS (a68g_standenv), n, v, v);
12530 if (z != NO_TAG) {
12531 return (z);
12532 }
12533 if (is_coercible_series (u, MODE (REAL), STRONG, SAFE_DEFLEXING)) {
12534 z = search_table_for_operator (OPERATORS (a68g_standenv), n, MODE (REAL), MODE (REAL));
12535 if (z != NO_TAG) {
12536 return (z);
12537 }
12538 }
12539 if (is_coercible_series (u, MODE (LONG_REAL), STRONG, SAFE_DEFLEXING)) {
12540 z = search_table_for_operator (OPERATORS (a68g_standenv), n, MODE (LONG_REAL), MODE (LONG_REAL));
12541 if (z != NO_TAG) {
12542 return (z);
12543 }
12544 }
12545 if (is_coercible_series (u, MODE (LONGLONG_REAL), STRONG, SAFE_DEFLEXING)) {
12546 z = search_table_for_operator (OPERATORS (a68g_standenv), n, MODE (LONGLONG_REAL), MODE (LONGLONG_REAL));
12547 if (z != NO_TAG) {
12548 return (z);
12549 }
12550 }
12551 if (is_coercible_series (u, MODE (COMPLEX), STRONG, SAFE_DEFLEXING)) {
12552 z = search_table_for_operator (OPERATORS (a68g_standenv), n, MODE (COMPLEX), MODE (COMPLEX));
12553 if (z != NO_TAG) {
12554 return (z);
12555 }
12556 }
12557 if (is_coercible_series (u, MODE (LONG_COMPLEX), STRONG, SAFE_DEFLEXING)) {
12558 z = search_table_for_operator (OPERATORS (a68g_standenv), n, MODE (LONG_COMPLEX), MODE (LONG_COMPLEX));
12559 if (z != NO_TAG) {
12560 return (z);
12561 }
12562 }
12563 if (is_coercible_series (u, MODE (LONGLONG_COMPLEX), STRONG, SAFE_DEFLEXING)) {
12564 z = search_table_for_operator (OPERATORS (a68g_standenv), n, MODE (LONGLONG_COMPLEX), MODE (LONGLONG_COMPLEX));
12565 if (z != NO_TAG) {
12566 return (z);
12567 }
12568 }
12569 /* (C.4) Now allow for depreffing for REF REAL +:= INT and alike */
12570 v = get_balanced_mode (u, STRONG, DEPREF, SAFE_DEFLEXING);
12571 z = search_table_for_operator (OPERATORS (a68g_standenv), n, v, v);
12572 if (z != NO_TAG) {
12573 return (z);
12574 }
12575 return (NO_TAG);
12576 }
12577
12578 /**
12579 @brief Mode check monadic operator.
12580 @param p Node in syntax tree.
12581 @param x Expected soid.
12582 @param y Resulting soid.
12583 **/
12584
12585 static void
mode_check_monadic_operator(NODE_T * p,SOID_T * x,SOID_T * y)12586 mode_check_monadic_operator (NODE_T * p, SOID_T * x, SOID_T * y)
12587 {
12588 if (p != NO_NODE) {
12589 TAG_T *t;
12590 MOID_T *u;
12591 u = determine_unique_mode (y, SAFE_DEFLEXING);
12592 if (is_mode_isnt_well (u)) {
12593 make_soid (y, SORT (x), MODE (ERROR), 0);
12594 } else if (u == MODE (HIP)) {
12595 diagnostic_node (A68_ERROR, NEXT (p), ERROR_INVALID_OPERAND, u);
12596 make_soid (y, SORT (x), MODE (ERROR), 0);
12597 } else {
12598 if (a68g_strchr (NOMADS, *(NSYMBOL (p))) != NO_TEXT) {
12599 t = NO_TAG;
12600 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_OPERATOR_INVALID, NOMADS);
12601 make_soid (y, SORT (x), MODE (ERROR), 0);
12602 } else {
12603 t = find_operator (TABLE (p), NSYMBOL (p), u, NO_MOID);
12604 if (t == NO_TAG) {
12605 diagnostic_node (A68_ERROR, p, ERROR_NO_MONADIC, u);
12606 make_soid (y, SORT (x), MODE (ERROR), 0);
12607 }
12608 }
12609 if (t != NO_TAG) {
12610 MOID (p) = MOID (t);
12611 }
12612 TAX (p) = t;
12613 if (t != NO_TAG && t != error_tag) {
12614 MOID (p) = MOID (t);
12615 make_soid (y, SORT (x), SUB_MOID (t), 0);
12616 } else {
12617 MOID (p) = MODE (ERROR);
12618 make_soid (y, SORT (x), MODE (ERROR), 0);
12619 }
12620 }
12621 }
12622 }
12623
12624 /**
12625 @brief Mode check monadic formula.
12626 @param p Node in syntax tree.
12627 @param x Expected soid.
12628 @param y Resulting soid.
12629 **/
12630
12631 static void
mode_check_monadic_formula(NODE_T * p,SOID_T * x,SOID_T * y)12632 mode_check_monadic_formula (NODE_T * p, SOID_T * x, SOID_T * y)
12633 {
12634 SOID_T e;
12635 make_soid (&e, FIRM, NO_MOID, 0);
12636 mode_check_formula (NEXT (p), &e, y);
12637 mode_check_monadic_operator (p, &e, y);
12638 make_soid (y, SORT (x), MOID (y), 0);
12639 }
12640
12641 /**
12642 @brief Mode check formula.
12643 @param p Node in syntax tree.
12644 @param x Expected soid.
12645 @param y Resulting soid.
12646 **/
12647
12648 static void
mode_check_formula(NODE_T * p,SOID_T * x,SOID_T * y)12649 mode_check_formula (NODE_T * p, SOID_T * x, SOID_T * y)
12650 {
12651 SOID_T ls, rs;
12652 TAG_T *op;
12653 MOID_T *u, *v;
12654 if (IS (p, MONADIC_FORMULA)) {
12655 mode_check_monadic_formula (SUB (p), x, &ls);
12656 } else if (IS (p, FORMULA)) {
12657 mode_check_formula (SUB (p), x, &ls);
12658 } else if (IS (p, SECONDARY)) {
12659 SOID_T e;
12660 make_soid (&e, FIRM, NO_MOID, 0);
12661 mode_check_unit (SUB (p), &e, &ls);
12662 }
12663 u = determine_unique_mode (&ls, SAFE_DEFLEXING);
12664 MOID (p) = u;
12665 if (NEXT (p) == NO_NODE) {
12666 make_soid (y, SORT (x), u, 0);
12667 } else {
12668 NODE_T *q = NEXT_NEXT (p);
12669 if (IS (q, MONADIC_FORMULA)) {
12670 mode_check_monadic_formula (SUB (NEXT_NEXT (p)), x, &rs);
12671 } else if (IS (q, FORMULA)) {
12672 mode_check_formula (SUB (NEXT_NEXT (p)), x, &rs);
12673 } else if (IS (q, SECONDARY)) {
12674 SOID_T e;
12675 make_soid (&e, FIRM, NO_MOID, 0);
12676 mode_check_unit (SUB (q), &e, &rs);
12677 }
12678 v = determine_unique_mode (&rs, SAFE_DEFLEXING);
12679 MOID (q) = v;
12680 if (is_mode_isnt_well (u) || is_mode_isnt_well (v)) {
12681 make_soid (y, SORT (x), MODE (ERROR), 0);
12682 } else if (u == MODE (HIP)) {
12683 diagnostic_node (A68_ERROR, p, ERROR_INVALID_OPERAND, u);
12684 make_soid (y, SORT (x), MODE (ERROR), 0);
12685 } else if (v == MODE (HIP)) {
12686 diagnostic_node (A68_ERROR, q, ERROR_INVALID_OPERAND, u);
12687 make_soid (y, SORT (x), MODE (ERROR), 0);
12688 } else {
12689 op = find_operator (TABLE (NEXT (p)), NSYMBOL (NEXT (p)), u, v);
12690 if (op == NO_TAG) {
12691 diagnostic_node (A68_ERROR, NEXT (p), ERROR_NO_DYADIC, u, v);
12692 make_soid (y, SORT (x), MODE (ERROR), 0);
12693 }
12694 if (op != NO_TAG) {
12695 MOID (NEXT (p)) = MOID (op);
12696 }
12697 TAX (NEXT (p)) = op;
12698 if (op != NO_TAG && op != error_tag) {
12699 make_soid (y, SORT (x), SUB_MOID (op), 0);
12700 } else {
12701 make_soid (y, SORT (x), MODE (ERROR), 0);
12702 }
12703 }
12704 }
12705 }
12706
12707 /**
12708 @brief Mode check assignation.
12709 @param p Node in syntax tree.
12710 @param x Expected soid.
12711 @param y Resulting soid.
12712 **/
12713
12714 static void
mode_check_assignation(NODE_T * p,SOID_T * x,SOID_T * y)12715 mode_check_assignation (NODE_T * p, SOID_T * x, SOID_T * y)
12716 {
12717 SOID_T name, tmp, value;
12718 MOID_T *name_moid, *ori;
12719 /* Get destination mode */
12720 make_soid (&name, SOFT, NO_MOID, 0);
12721 mode_check_unit (SUB (p), &name, &tmp);
12722 /* SOFT coercion */
12723 ori = determine_unique_mode (&tmp, SAFE_DEFLEXING);
12724 name_moid = deproc_completely (ori);
12725 if (ATTRIBUTE (name_moid) != REF_SYMBOL) {
12726 if (IF_MODE_IS_WELL (name_moid)) {
12727 diagnostic_node (A68_ERROR, p, ERROR_NO_NAME, ori, ATTRIBUTE (SUB (p)));
12728 }
12729 make_soid (y, SORT (x), MODE (ERROR), 0);
12730 return;
12731 }
12732 MOID (p) = name_moid;
12733 /* Get source mode */
12734 make_soid (&name, STRONG, SUB (name_moid), 0);
12735 mode_check_unit (NEXT_NEXT (p), &name, &value);
12736 if (!is_coercible_in_context (&value, &name, FORCE_DEFLEXING)) {
12737 cannot_coerce (p, MOID (&value), MOID (&name), STRONG, FORCE_DEFLEXING, UNIT);
12738 make_soid (y, SORT (x), MODE (ERROR), 0);
12739 } else {
12740 make_soid (y, SORT (x), name_moid, 0);
12741 }
12742 }
12743
12744 /**
12745 @brief Mode check identity relation.
12746 @param p Node in syntax tree.
12747 @param x Expected soid.
12748 @param y Resulting soid.
12749 **/
12750
12751 static void
mode_check_identity_relation(NODE_T * p,SOID_T * x,SOID_T * y)12752 mode_check_identity_relation (NODE_T * p, SOID_T * x, SOID_T * y)
12753 {
12754 SOID_T e, l, r;
12755 MOID_T *lhs, *rhs, *oril, *orir;
12756 NODE_T *ln = p, *rn = NEXT_NEXT (p);
12757 make_soid (&e, SOFT, NO_MOID, 0);
12758 mode_check_unit (SUB (ln), &e, &l);
12759 mode_check_unit (SUB (rn), &e, &r);
12760 /* SOFT coercion */
12761 oril = determine_unique_mode (&l, SAFE_DEFLEXING);
12762 orir = determine_unique_mode (&r, SAFE_DEFLEXING);
12763 lhs = deproc_completely (oril);
12764 rhs = deproc_completely (orir);
12765 if (IF_MODE_IS_WELL (lhs) && lhs != MODE (HIP) && ATTRIBUTE (lhs) != REF_SYMBOL) {
12766 diagnostic_node (A68_ERROR, ln, ERROR_NO_NAME, oril, ATTRIBUTE (SUB (ln)));
12767 lhs = MODE (ERROR);
12768 }
12769 if (IF_MODE_IS_WELL (rhs) && rhs != MODE (HIP) && ATTRIBUTE (rhs) != REF_SYMBOL) {
12770 diagnostic_node (A68_ERROR, rn, ERROR_NO_NAME, orir, ATTRIBUTE (SUB (rn)));
12771 rhs = MODE (ERROR);
12772 }
12773 if (lhs == MODE (HIP) && rhs == MODE (HIP)) {
12774 diagnostic_node (A68_ERROR, p, ERROR_NO_UNIQUE_MODE);
12775 }
12776 if (is_coercible (lhs, rhs, STRONG, SAFE_DEFLEXING)) {
12777 lhs = rhs;
12778 } else if (is_coercible (rhs, lhs, STRONG, SAFE_DEFLEXING)) {
12779 rhs = lhs;
12780 } else {
12781 cannot_coerce (NEXT (p), rhs, lhs, SOFT, SKIP_DEFLEXING, TERTIARY);
12782 lhs = rhs = MODE (ERROR);
12783 }
12784 MOID (ln) = lhs;
12785 MOID (rn) = rhs;
12786 make_soid (y, SORT (x), MODE (BOOL), 0);
12787 }
12788
12789 /**
12790 @brief Mode check bool functions ANDF and ORF.
12791 @param p Node in syntax tree.
12792 @param x Expected soid.
12793 @param y Resulting soid.
12794 **/
12795
12796 static void
mode_check_bool_function(NODE_T * p,SOID_T * x,SOID_T * y)12797 mode_check_bool_function (NODE_T * p, SOID_T * x, SOID_T * y)
12798 {
12799 SOID_T e, l, r;
12800 NODE_T *ln = p, *rn = NEXT_NEXT (p);
12801 make_soid (&e, STRONG, MODE (BOOL), 0);
12802 mode_check_unit (SUB (ln), &e, &l);
12803 if (!is_coercible_in_context (&l, &e, SAFE_DEFLEXING)) {
12804 cannot_coerce (ln, MOID (&l), MOID (&e), MEEK, SAFE_DEFLEXING, TERTIARY);
12805 }
12806 mode_check_unit (SUB (rn), &e, &r);
12807 if (!is_coercible_in_context (&r, &e, SAFE_DEFLEXING)) {
12808 cannot_coerce (rn, MOID (&r), MOID (&e), MEEK, SAFE_DEFLEXING, TERTIARY);
12809 }
12810 MOID (ln) = MODE (BOOL);
12811 MOID (rn) = MODE (BOOL);
12812 make_soid (y, SORT (x), MODE (BOOL), 0);
12813 }
12814
12815 /**
12816 @brief Mode check cast.
12817 @param p Node in syntax tree.
12818 @param x Expected soid.
12819 @param y Resulting soid.
12820 **/
12821
12822 static void
mode_check_cast(NODE_T * p,SOID_T * x,SOID_T * y)12823 mode_check_cast (NODE_T * p, SOID_T * x, SOID_T * y)
12824 {
12825 SOID_T w;
12826 mode_check_declarer (p);
12827 make_soid (&w, STRONG, MOID (p), 0);
12828 CAST (&w) = A68_TRUE;
12829 mode_check_enclosed (SUB_NEXT (p), &w, y);
12830 if (!is_coercible_in_context (y, &w, SAFE_DEFLEXING)) {
12831 cannot_coerce (NEXT (p), MOID (y), MOID (&w), STRONG, SAFE_DEFLEXING, ENCLOSED_CLAUSE);
12832 }
12833 make_soid (y, SORT (x), MOID (p), 0);
12834 }
12835
12836 /**
12837 @brief Mode check assertion.
12838 @param p Node in syntax tree.
12839 **/
12840
12841 static void
mode_check_assertion(NODE_T * p)12842 mode_check_assertion (NODE_T * p)
12843 {
12844 SOID_T w, y;
12845 make_soid (&w, STRONG, MODE (BOOL), 0);
12846 mode_check_enclosed (SUB_NEXT (p), &w, &y);
12847 SORT (&y) = SORT (&w); /* Patch */
12848 if (!is_coercible_in_context (&y, &w, NO_DEFLEXING)) {
12849 cannot_coerce (NEXT (p), MOID (&y), MOID (&w), MEEK, NO_DEFLEXING, ENCLOSED_CLAUSE);
12850 }
12851 }
12852
12853 /**
12854 @brief Mode check argument list.
12855 @param r Resulting soids.
12856 @param p Node in syntax tree.
12857 @param x Proc argument pack.
12858 @param v Partial locale pack.
12859 @param w Partial proc pack.
12860 **/
12861
12862 static void
mode_check_argument_list(SOID_T ** r,NODE_T * p,PACK_T ** x,PACK_T ** v,PACK_T ** w)12863 mode_check_argument_list (SOID_T ** r, NODE_T * p, PACK_T ** x, PACK_T ** v, PACK_T ** w)
12864 {
12865 for (; p != NO_NODE; FORWARD (p)) {
12866 if (IS (p, GENERIC_ARGUMENT_LIST)) {
12867 ATTRIBUTE (p) = ARGUMENT_LIST;
12868 }
12869 if (IS (p, ARGUMENT_LIST)) {
12870 mode_check_argument_list (r, SUB (p), x, v, w);
12871 } else if (IS (p, UNIT)) {
12872 SOID_T y, z;
12873 if (*x != NO_PACK) {
12874 make_soid (&z, STRONG, MOID (*x), 0);
12875 add_mode_to_pack_end (v, MOID (*x), NO_TEXT, p);
12876 FORWARD (*x);
12877 } else {
12878 make_soid (&z, STRONG, NO_MOID, 0);
12879 }
12880 mode_check_unit (p, &z, &y);
12881 add_to_soid_list (r, p, &y);
12882 } else if (IS (p, TRIMMER)) {
12883 SOID_T z;
12884 if (SUB (p) != NO_NODE) {
12885 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_SYNTAX, ARGUMENT);
12886 make_soid (&z, STRONG, MODE (ERROR), 0);
12887 add_mode_to_pack_end (v, MODE (VOID), NO_TEXT, p);
12888 add_mode_to_pack_end (w, MOID (*x), NO_TEXT, p);
12889 FORWARD (*x);
12890 } else if (*x != NO_PACK) {
12891 make_soid (&z, STRONG, MOID (*x), 0);
12892 add_mode_to_pack_end (v, MODE (VOID), NO_TEXT, p);
12893 add_mode_to_pack_end (w, MOID (*x), NO_TEXT, p);
12894 FORWARD (*x);
12895 } else {
12896 make_soid (&z, STRONG, NO_MOID, 0);
12897 }
12898 add_to_soid_list (r, p, &z);
12899 } else if (IS (p, SUB_SYMBOL) && !OPTION_BRACKETS (&program)) {
12900 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_SYNTAX, CALL);
12901 }
12902 }
12903 }
12904
12905 /**
12906 @brief Mode check argument list 2.
12907 @param p Node in syntax tree.
12908 @param x Proc argument pack.
12909 @param y Soid.
12910 @param v Partial locale pack.
12911 @param w Partial proc pack.
12912 **/
12913
12914 static void
mode_check_argument_list_2(NODE_T * p,PACK_T * x,SOID_T * y,PACK_T ** v,PACK_T ** w)12915 mode_check_argument_list_2 (NODE_T * p, PACK_T * x, SOID_T * y, PACK_T ** v, PACK_T ** w)
12916 {
12917 SOID_T *top_sl = NO_SOID;
12918 mode_check_argument_list (&top_sl, SUB (p), &x, v, w);
12919 make_soid (y, STRONG, pack_soids_in_moid (top_sl, STOWED_MODE), 0);
12920 free_soid_list (top_sl);
12921 }
12922
12923 /**
12924 @brief Mode check meek int.
12925 @param p Node in syntax tree.
12926 **/
12927
12928 static void
mode_check_meek_int(NODE_T * p)12929 mode_check_meek_int (NODE_T * p)
12930 {
12931 SOID_T x, y;
12932 make_soid (&x, STRONG, MODE (INT), 0);
12933 mode_check_unit (p, &x, &y);
12934 if (!is_coercible_in_context (&y, &x, SAFE_DEFLEXING)) {
12935 cannot_coerce (p, MOID (&y), MOID (&x), MEEK, SAFE_DEFLEXING, 0);
12936 }
12937 }
12938
12939 /**
12940 @brief Mode check trimmer.
12941 @param p Node in syntax tree.
12942 **/
12943
12944 static void
mode_check_trimmer(NODE_T * p)12945 mode_check_trimmer (NODE_T * p)
12946 {
12947 if (p == NO_NODE) {
12948 return;
12949 } else if (IS (p, TRIMMER)) {
12950 mode_check_trimmer (SUB (p));
12951 } else if (IS (p, UNIT)) {
12952 mode_check_meek_int (p);
12953 mode_check_trimmer (NEXT (p));
12954 } else {
12955 mode_check_trimmer (NEXT (p));
12956 }
12957 }
12958
12959 /**
12960 @brief Mode check indexer.
12961 @param p Node in syntax tree.
12962 @param subs Subscript counter.
12963 @param trims Trimmer counter.
12964 **/
12965
12966 static void
mode_check_indexer(NODE_T * p,int * subs,int * trims)12967 mode_check_indexer (NODE_T * p, int *subs, int *trims)
12968 {
12969 if (p == NO_NODE) {
12970 return;
12971 } else if (IS (p, TRIMMER)) {
12972 (*trims)++;
12973 mode_check_trimmer (SUB (p));
12974 } else if (IS (p, UNIT)) {
12975 (*subs)++;
12976 mode_check_meek_int (p);
12977 } else {
12978 mode_check_indexer (SUB (p), subs, trims);
12979 mode_check_indexer (NEXT (p), subs, trims);
12980 }
12981 }
12982
12983 /**
12984 @brief Mode check call.
12985 @param p Node in syntax tree.
12986 @param n Mode.
12987 @param x Expected soid.
12988 @param y Resulting soid.
12989 **/
12990
12991 static void
mode_check_call(NODE_T * p,MOID_T * n,SOID_T * x,SOID_T * y)12992 mode_check_call (NODE_T * p, MOID_T * n, SOID_T * x, SOID_T * y)
12993 {
12994 SOID_T d;
12995 MOID (p) = n;
12996 /* "partial_locale" is the mode of the locale */
12997 PARTIAL_LOCALE (GINFO (p)) = new_moid ();
12998 ATTRIBUTE (PARTIAL_LOCALE (GINFO (p))) = PROC_SYMBOL;
12999 PACK (PARTIAL_LOCALE (GINFO (p))) = NO_PACK;
13000 SUB (PARTIAL_LOCALE (GINFO (p))) = SUB (n);
13001 /* "partial_proc" is the mode of the resulting proc */
13002 PARTIAL_PROC (GINFO (p)) = new_moid ();
13003 ATTRIBUTE (PARTIAL_PROC (GINFO (p))) = PROC_SYMBOL;
13004 PACK (PARTIAL_PROC (GINFO (p))) = NO_PACK;
13005 SUB (PARTIAL_PROC (GINFO (p))) = SUB (n);
13006 /* Check arguments and construct modes */
13007 mode_check_argument_list_2 (NEXT (p), PACK (n), &d, &PACK (PARTIAL_LOCALE (GINFO (p))), &PACK (PARTIAL_PROC (GINFO (p))));
13008 DIM (PARTIAL_PROC (GINFO (p))) = count_pack_members (PACK (PARTIAL_PROC (GINFO (p))));
13009 DIM (PARTIAL_LOCALE (GINFO (p))) = count_pack_members (PACK (PARTIAL_LOCALE (GINFO (p))));
13010 PARTIAL_PROC (GINFO (p)) = register_extra_mode (&TOP_MOID (&program), PARTIAL_PROC (GINFO (p)));
13011 PARTIAL_LOCALE (GINFO (p)) = register_extra_mode (&TOP_MOID (&program), PARTIAL_LOCALE (GINFO (p)));
13012 if (DIM (MOID (&d)) != DIM (n)) {
13013 diagnostic_node (A68_ERROR, p, ERROR_ARGUMENT_NUMBER, n);
13014 make_soid (y, SORT (x), SUB (n), 0);
13015 /* make_soid (y, SORT (x), MODE (ERROR), 0); */
13016 } else {
13017 if (!is_coercible (MOID (&d), n, STRONG, ALIAS_DEFLEXING)) {
13018 cannot_coerce (p, MOID (&d), n, STRONG, ALIAS_DEFLEXING, ARGUMENT);
13019 }
13020 if (DIM (PARTIAL_PROC (GINFO (p))) == 0) {
13021 make_soid (y, SORT (x), SUB (n), 0);
13022 } else {
13023 if (OPTION_PORTCHECK (&program)) {
13024 diagnostic_node (A68_WARNING | A68_FORCE_DIAGNOSTICS, NEXT (p), WARNING_EXTENSION);
13025 }
13026 make_soid (y, SORT (x), PARTIAL_PROC (GINFO (p)), 0);
13027 }
13028 }
13029 }
13030
13031 /**
13032 @brief Mode check slice.
13033 @param p Node in syntax tree.
13034 @param ori Original MODE.
13035 @param x Expected soid.
13036 @param y Resulting soid.
13037 @return Whether construct is a CALL or a SLICE.
13038 **/
13039
13040 static void
mode_check_slice(NODE_T * p,MOID_T * ori,SOID_T * x,SOID_T * y)13041 mode_check_slice (NODE_T * p, MOID_T * ori, SOID_T * x, SOID_T * y)
13042 {
13043 BOOL_T is_ref;
13044 int rowdim, subs, trims;
13045 MOID_T *m = depref_completely (ori), *n = ori;
13046 /* WEAK coercion */
13047 while ((IS (n, REF_SYMBOL) && !is_ref_row (n)) || (IS (n, PROC_SYMBOL) && PACK (n) == NO_PACK)) {
13048 n = depref_once (n);
13049 }
13050 if (n == NO_MOID || !(SLICE (DEFLEX (n)) != NO_MOID || is_ref_row (n))) {
13051 if (IF_MODE_IS_WELL (n)) {
13052 diagnostic_node (A68_ERROR, p, ERROR_NO_ROW_OR_PROC, n, ATTRIBUTE (SUB (p)));
13053 }
13054 make_soid (y, SORT (x), MODE (ERROR), 0);
13055 }
13056
13057 MOID (p) = n;
13058 subs = trims = 0;
13059 mode_check_indexer (SUB_NEXT (p), &subs, &trims);
13060 if ((is_ref = is_ref_row (n)) != 0) {
13061 rowdim = DIM (DEFLEX (SUB (n)));
13062 } else {
13063 rowdim = DIM (DEFLEX (n));
13064 }
13065 if ((subs + trims) != rowdim) {
13066 diagnostic_node (A68_ERROR, p, ERROR_INDEXER_NUMBER, n);
13067 make_soid (y, SORT (x), MODE (ERROR), 0);
13068 } else {
13069 if (subs > 0 && trims == 0) {
13070 ANNOTATION (NEXT (p)) = SLICE;
13071 m = n;
13072 } else {
13073 ANNOTATION (NEXT (p)) = TRIMMER;
13074 m = n;
13075 }
13076 while (subs > 0) {
13077 if (is_ref) {
13078 m = NAME (m);
13079 } else {
13080 if (IS (m, FLEX_SYMBOL)) {
13081 m = SUB (m);
13082 }
13083 m = SLICE (m);
13084 }
13085 ABEND (m == NO_MOID, "No mode in mode_check_slice", NO_TEXT);
13086 subs--;
13087 }
13088 /* A trim cannot be but deflexed */
13089 if (ANNOTATION (NEXT (p)) == TRIMMER && TRIM (m) != NO_MOID) {
13090 ABEND (TRIM (m) == NO_MOID, ERROR_INTERNAL_CONSISTENCY, NO_TEXT);
13091 make_soid (y, SORT (x), TRIM (m), 0);
13092 } else {
13093 make_soid (y, SORT (x), m, 0);
13094 }
13095 }
13096 }
13097
13098 /**
13099 @brief Mode check specification.
13100 @param p Node in syntax tree.
13101 @param x Expected soid.
13102 @param y Resulting soid.
13103 @return Whether construct is a CALL or SLICE.
13104 **/
13105
13106 static int
mode_check_specification(NODE_T * p,SOID_T * x,SOID_T * y)13107 mode_check_specification (NODE_T * p, SOID_T * x, SOID_T * y)
13108 {
13109 SOID_T w, d;
13110 MOID_T *m, *ori;
13111 make_soid (&w, WEAK, NO_MOID, 0);
13112 mode_check_unit (SUB (p), &w, &d);
13113 ori = determine_unique_mode (&d, SAFE_DEFLEXING);
13114 m = depref_completely (ori);
13115 if (IS (m, PROC_SYMBOL)) {
13116 /* Assume CALL */
13117 mode_check_call (p, m, x, y);
13118 return (CALL);
13119 } else if (IS (m, ROW_SYMBOL) || IS (m, FLEX_SYMBOL)) {
13120 /* Assume SLICE */
13121 mode_check_slice (p, ori, x, y);
13122 return (SLICE);
13123 } else {
13124 if (m != MODE (ERROR)) {
13125 diagnostic_node (A68_SYNTAX_ERROR, p, ERROR_MODE_SPECIFICATION, m);
13126 }
13127 make_soid (y, SORT (x), MODE (ERROR), 0);
13128 return (PRIMARY);
13129 }
13130 }
13131
13132 /**
13133 @brief Mode check selection.
13134 @param p Node in syntax tree.
13135 @param x Expected soid.
13136 @param y Resulting soid.
13137 **/
13138
13139 static void
mode_check_selection(NODE_T * p,SOID_T * x,SOID_T * y)13140 mode_check_selection (NODE_T * p, SOID_T * x, SOID_T * y)
13141 {
13142 SOID_T w, d;
13143 BOOL_T coerce;
13144 MOID_T *n, *str, *ori;
13145 PACK_T *t, *t_2;
13146 char *fs;
13147 BOOL_T deflex = A68_FALSE;
13148 NODE_T *secondary = SUB_NEXT (p);
13149 make_soid (&w, WEAK, NO_MOID, 0);
13150 mode_check_unit (secondary, &w, &d);
13151 n = ori = determine_unique_mode (&d, SAFE_DEFLEXING);
13152 coerce = A68_TRUE;
13153 while (coerce) {
13154 if (IS (n, STRUCT_SYMBOL)) {
13155 coerce = A68_FALSE;
13156 t = PACK (n);
13157 } else if (IS (n, REF_SYMBOL) && (IS (SUB (n), ROW_SYMBOL) || IS (SUB (n), FLEX_SYMBOL)) && MULTIPLE (n) != NO_MOID) {
13158 coerce = A68_FALSE;
13159 deflex = A68_TRUE;
13160 t = PACK (MULTIPLE (n));
13161 } else if ((IS (n, ROW_SYMBOL) || IS (n, FLEX_SYMBOL)) && MULTIPLE (n) != NO_MOID) {
13162 coerce = A68_FALSE;
13163 deflex = A68_TRUE;
13164 t = PACK (MULTIPLE (n));
13165 } else if (IS (n, REF_SYMBOL) && is_name_struct (n)) {
13166 coerce = A68_FALSE;
13167 t = PACK (NAME (n));
13168 } else if (is_deprefable (n)) {
13169 coerce = A68_TRUE;
13170 n = SUB (n);
13171 t = NO_PACK;
13172 } else {
13173 coerce = A68_FALSE;
13174 t = NO_PACK;
13175 }
13176 }
13177 if (t == NO_PACK) {
13178 if (IF_MODE_IS_WELL (MOID (&d))) {
13179 diagnostic_node (A68_ERROR, secondary, ERROR_NO_STRUCT, ori, ATTRIBUTE (secondary));
13180 }
13181 make_soid (y, SORT (x), MODE (ERROR), 0);
13182 return;
13183 }
13184 MOID (NEXT (p)) = n;
13185 fs = NSYMBOL (SUB (p));
13186 str = n;
13187 while (IS (str, REF_SYMBOL)) {
13188 str = SUB (str);
13189 }
13190 if (IS (str, FLEX_SYMBOL)) {
13191 str = SUB (str);
13192 }
13193 if (IS (str, ROW_SYMBOL)) {
13194 str = SUB (str);
13195 }
13196 t_2 = PACK (str);
13197 while (t != NO_PACK && t_2 != NO_PACK) {
13198 if (TEXT (t) == fs) {
13199 MOID_T *ret = MOID (t);
13200 if (deflex && TRIM (ret) != NO_MOID) {
13201 ret = TRIM (ret);
13202 }
13203 make_soid (y, SORT (x), ret, 0);
13204 MOID (p) = ret;
13205 NODE_PACK (SUB (p)) = t_2;
13206 return;
13207 }
13208 FORWARD (t);
13209 FORWARD (t_2);
13210 }
13211 make_soid (&d, NO_SORT, n, 0);
13212 diagnostic_node (A68_ERROR, p, ERROR_NO_FIELD, str, fs);
13213 make_soid (y, SORT (x), MODE (ERROR), 0);
13214 }
13215
13216 /**
13217 @brief Mode check diagonal.
13218 @param p Node in syntax tree.
13219 @param x Expected soid.
13220 @param y Resulting soid.
13221 **/
13222
13223 static void
mode_check_diagonal(NODE_T * p,SOID_T * x,SOID_T * y)13224 mode_check_diagonal (NODE_T * p, SOID_T * x, SOID_T * y)
13225 {
13226 SOID_T w, d;
13227 NODE_T *tert;
13228 MOID_T *n, *ori;
13229 int rowdim;
13230 BOOL_T is_ref;
13231 if (IS (p, TERTIARY)) {
13232 make_soid (&w, STRONG, MODE (INT), 0);
13233 mode_check_unit (p, &w, &d);
13234 if (!is_coercible_in_context (&d, &w, SAFE_DEFLEXING)) {
13235 cannot_coerce (p, MOID (&d), MOID (&w), MEEK, SAFE_DEFLEXING, 0);
13236 }
13237 tert = NEXT_NEXT (p);
13238 } else {
13239 tert = NEXT (p);
13240 }
13241 make_soid (&w, WEAK, NO_MOID, 0);
13242 mode_check_unit (tert, &w, &d);
13243 n = ori = determine_unique_mode (&d, SAFE_DEFLEXING);
13244 while (IS (n, REF_SYMBOL) && !is_ref_row (n)) {
13245 n = depref_once (n);
13246 }
13247 if (n != NO_MOID && (IS (n, FLEX_SYMBOL) || IS_REF_FLEX (n))) {
13248 if (IF_MODE_IS_WELL (n)) {
13249 diagnostic_node (A68_ERROR, p, ERROR_NO_FLEX_ARGUMENT, ori, TERTIARY);
13250 }
13251 make_soid (y, SORT (x), MODE (ERROR), 0);
13252 return;
13253 }
13254 if (n == NO_MOID || !(SLICE (DEFLEX (n)) != NO_MOID || is_ref_row (n))) {
13255 if (IF_MODE_IS_WELL (n)) {
13256 diagnostic_node (A68_ERROR, p, ERROR_NO_MATRIX, ori, TERTIARY);
13257 }
13258 make_soid (y, SORT (x), MODE (ERROR), 0);
13259 return;
13260 }
13261 if ((is_ref = is_ref_row (n)) != A68_FALSE) {
13262 rowdim = DIM (DEFLEX (SUB (n)));
13263 } else {
13264 rowdim = DIM (DEFLEX (n));
13265 }
13266 if (rowdim != 2) {
13267 diagnostic_node (A68_ERROR, p, ERROR_NO_MATRIX, ori, TERTIARY);
13268 make_soid (y, SORT (x), MODE (ERROR), 0);
13269 return;
13270 }
13271 MOID (tert) = n;
13272 if (is_ref) {
13273 n = NAME (n);
13274 ABEND (ISNT (n, REF_SYMBOL), "mode table error", PM (n));
13275 } else {
13276 n = SLICE (n);
13277 }
13278 ABEND (n == NO_MOID, "No mode in mode_check_diagonal", NO_TEXT);
13279 make_soid (y, SORT (x), n, 0);
13280 }
13281
13282 /**
13283 @brief Mode check transpose.
13284 @param p Node in syntax tree.
13285 @param x Expected soid.
13286 @param y Resulting soid.
13287 **/
13288
13289 static void
mode_check_transpose(NODE_T * p,SOID_T * x,SOID_T * y)13290 mode_check_transpose (NODE_T * p, SOID_T * x, SOID_T * y)
13291 {
13292 SOID_T w, d;
13293 NODE_T *tert = NEXT (p);
13294 MOID_T *n, *ori;
13295 int rowdim;
13296 BOOL_T is_ref;
13297 make_soid (&w, WEAK, NO_MOID, 0);
13298 mode_check_unit (tert, &w, &d);
13299 n = ori = determine_unique_mode (&d, SAFE_DEFLEXING);
13300 while (IS (n, REF_SYMBOL) && !is_ref_row (n)) {
13301 n = depref_once (n);
13302 }
13303 if (n != NO_MOID && (IS (n, FLEX_SYMBOL) || IS_REF_FLEX (n))) {
13304 if (IF_MODE_IS_WELL (n)) {
13305 diagnostic_node (A68_ERROR, p, ERROR_NO_FLEX_ARGUMENT, ori, TERTIARY);
13306 }
13307 make_soid (y, SORT (x), MODE (ERROR), 0);
13308 return;
13309 }
13310 if (n == NO_MOID || !(SLICE (DEFLEX (n)) != NO_MOID || is_ref_row (n))) {
13311 if (IF_MODE_IS_WELL (n)) {
13312 diagnostic_node (A68_ERROR, p, ERROR_NO_MATRIX, ori, TERTIARY);
13313 }
13314 make_soid (y, SORT (x), MODE (ERROR), 0);
13315 return;
13316 }
13317 if ((is_ref = is_ref_row (n)) != A68_FALSE) {
13318 rowdim = DIM (DEFLEX (SUB (n)));
13319 } else {
13320 rowdim = DIM (DEFLEX (n));
13321 }
13322 if (rowdim != 2) {
13323 diagnostic_node (A68_ERROR, p, ERROR_NO_MATRIX, ori, TERTIARY);
13324 make_soid (y, SORT (x), MODE (ERROR), 0);
13325 return;
13326 }
13327 MOID (tert) = n;
13328 ABEND (n == NO_MOID, "No mode in mode_check_transpose", NO_TEXT);
13329 make_soid (y, SORT (x), n, 0);
13330 }
13331
13332 /**
13333 @brief Mode check row or column function.
13334 @param p Node in syntax tree.
13335 @param x Expected soid.
13336 @param y Resulting soid.
13337 **/
13338
13339 static void
mode_check_row_column_function(NODE_T * p,SOID_T * x,SOID_T * y)13340 mode_check_row_column_function (NODE_T * p, SOID_T * x, SOID_T * y)
13341 {
13342 SOID_T w, d;
13343 NODE_T *tert;
13344 MOID_T *n, *ori;
13345 int rowdim;
13346 BOOL_T is_ref;
13347 if (IS (p, TERTIARY)) {
13348 make_soid (&w, STRONG, MODE (INT), 0);
13349 mode_check_unit (p, &w, &d);
13350 if (!is_coercible_in_context (&d, &w, SAFE_DEFLEXING)) {
13351 cannot_coerce (p, MOID (&d), MOID (&w), MEEK, SAFE_DEFLEXING, 0);
13352 }
13353 tert = NEXT_NEXT (p);
13354 } else {
13355 tert = NEXT (p);
13356 }
13357 make_soid (&w, WEAK, NO_MOID, 0);
13358 mode_check_unit (tert, &w, &d);
13359 n = ori = determine_unique_mode (&d, SAFE_DEFLEXING);
13360 while (IS (n, REF_SYMBOL) && !is_ref_row (n)) {
13361 n = depref_once (n);
13362 }
13363 if (n != NO_MOID && (IS (n, FLEX_SYMBOL) || IS_REF_FLEX (n))) {
13364 if (IF_MODE_IS_WELL (n)) {
13365 diagnostic_node (A68_ERROR, p, ERROR_NO_FLEX_ARGUMENT, ori, TERTIARY);
13366 }
13367 make_soid (y, SORT (x), MODE (ERROR), 0);
13368 return;
13369 }
13370 if (n == NO_MOID || !(SLICE (DEFLEX (n)) != NO_MOID || is_ref_row (n))) {
13371 if (IF_MODE_IS_WELL (n)) {
13372 diagnostic_node (A68_ERROR, p, ERROR_NO_VECTOR, ori, TERTIARY);
13373 }
13374 make_soid (y, SORT (x), MODE (ERROR), 0);
13375 return;
13376 }
13377 if ((is_ref = is_ref_row (n)) != A68_FALSE) {
13378 rowdim = DIM (DEFLEX (SUB (n)));
13379 } else {
13380 rowdim = DIM (DEFLEX (n));
13381 }
13382 if (rowdim != 1) {
13383 diagnostic_node (A68_ERROR, p, ERROR_NO_VECTOR, ori, TERTIARY);
13384 make_soid (y, SORT (x), MODE (ERROR), 0);
13385 return;
13386 }
13387 MOID (tert) = n;
13388 ABEND (n == NO_MOID, "No mode in mode_check_diagonal", NO_TEXT);
13389 make_soid (y, SORT (x), ROWED (n), 0);
13390 }
13391
13392 /**
13393 @brief Mode check format text.
13394 @param p Node in syntax tree.
13395 **/
13396
13397 static void
mode_check_format_text(NODE_T * p)13398 mode_check_format_text (NODE_T * p)
13399 {
13400 for (; p != NO_NODE; FORWARD (p)) {
13401 mode_check_format_text (SUB (p));
13402 if (IS (p, FORMAT_PATTERN)) {
13403 SOID_T x, y;
13404 make_soid (&x, STRONG, MODE (FORMAT), 0);
13405 mode_check_enclosed (SUB (NEXT_SUB (p)), &x, &y);
13406 if (!is_coercible_in_context (&y, &x, SAFE_DEFLEXING)) {
13407 cannot_coerce (p, MOID (&y), MOID (&x), STRONG, SAFE_DEFLEXING, ENCLOSED_CLAUSE);
13408 }
13409 } else if (IS (p, GENERAL_PATTERN) && NEXT_SUB (p) != NO_NODE) {
13410 SOID_T x, y;
13411 make_soid (&x, STRONG, MODE (ROW_INT), 0);
13412 mode_check_enclosed (SUB (NEXT_SUB (p)), &x, &y);
13413 if (!is_coercible_in_context (&y, &x, SAFE_DEFLEXING)) {
13414 cannot_coerce (p, MOID (&y), MOID (&x), STRONG, SAFE_DEFLEXING, ENCLOSED_CLAUSE);
13415 }
13416 } else if (IS (p, DYNAMIC_REPLICATOR)) {
13417 SOID_T x, y;
13418 make_soid (&x, STRONG, MODE (INT), 0);
13419 mode_check_enclosed (SUB (NEXT_SUB (p)), &x, &y);
13420 if (!is_coercible_in_context (&y, &x, SAFE_DEFLEXING)) {
13421 cannot_coerce (p, MOID (&y), MOID (&x), STRONG, SAFE_DEFLEXING, ENCLOSED_CLAUSE);
13422 }
13423 }
13424 }
13425 }
13426
13427 /**
13428 @brief Mode check unit.
13429 @param p Node in syntax tree.
13430 @param x Expected soid.
13431 @param y Resulting soid.
13432 **/
13433
13434 static void
mode_check_unit(NODE_T * p,SOID_T * x,SOID_T * y)13435 mode_check_unit (NODE_T * p, SOID_T * x, SOID_T * y)
13436 {
13437 if (p == NO_NODE) {
13438 return;
13439 } else if (is_one_of (p, UNIT, TERTIARY, SECONDARY, PRIMARY, STOP)) {
13440 mode_check_unit (SUB (p), x, y);
13441 /* Ex primary */
13442 } else if (IS (p, SPECIFICATION)) {
13443 ATTRIBUTE (p) = mode_check_specification (SUB (p), x, y);
13444 warn_for_voiding (p, x, y, ATTRIBUTE (p));
13445 } else if (IS (p, CAST)) {
13446 mode_check_cast (SUB (p), x, y);
13447 warn_for_voiding (p, x, y, CAST);
13448 } else if (IS (p, DENOTATION)) {
13449 make_soid (y, SORT (x), MOID (SUB (p)), 0);
13450 warn_for_voiding (p, x, y, DENOTATION);
13451 } else if (IS (p, IDENTIFIER)) {
13452 if ((TAX (p) == NO_TAG) && (MOID (p) == NO_MOID)) {
13453 int att = first_tag_global (TABLE (p), NSYMBOL (p));
13454 if (att == STOP) {
13455 (void) add_tag (TABLE (p), IDENTIFIER, p, MODE (ERROR), NORMAL_IDENTIFIER);
13456 diagnostic_node (A68_ERROR, p, ERROR_UNDECLARED_TAG);
13457 MOID (p) = MODE (ERROR);
13458 } else {
13459 TAG_T *z = find_tag_global (TABLE (p), att, NSYMBOL (p));
13460 if (att == IDENTIFIER && z != NO_TAG) {
13461 MOID (p) = MOID (z);
13462 } else {
13463 (void) add_tag (TABLE (p), IDENTIFIER, p, MODE (ERROR), NORMAL_IDENTIFIER);
13464 diagnostic_node (A68_ERROR, p, ERROR_UNDECLARED_TAG);
13465 MOID (p) = MODE (ERROR);
13466 }
13467 }
13468 }
13469 make_soid (y, SORT (x), MOID (p), 0);
13470 warn_for_voiding (p, x, y, IDENTIFIER);
13471 } else if (IS (p, ENCLOSED_CLAUSE)) {
13472 mode_check_enclosed (SUB (p), x, y);
13473 } else if (IS (p, FORMAT_TEXT)) {
13474 mode_check_format_text (p);
13475 make_soid (y, SORT (x), MODE (FORMAT), 0);
13476 warn_for_voiding (p, x, y, FORMAT_TEXT);
13477 /* Ex secondary */
13478 } else if (IS (p, GENERATOR)) {
13479 mode_check_declarer (SUB (p));
13480 make_soid (y, SORT (x), MOID (SUB (p)), 0);
13481 warn_for_voiding (p, x, y, GENERATOR);
13482 } else if (IS (p, SELECTION)) {
13483 mode_check_selection (SUB (p), x, y);
13484 warn_for_voiding (p, x, y, SELECTION);
13485 /* Ex tertiary */
13486 } else if (IS (p, NIHIL)) {
13487 make_soid (y, STRONG, MODE (HIP), 0);
13488 } else if (IS (p, FORMULA)) {
13489 mode_check_formula (p, x, y);
13490 if (ISNT (MOID (y), REF_SYMBOL)) {
13491 warn_for_voiding (p, x, y, FORMULA);
13492 }
13493 } else if (IS (p, DIAGONAL_FUNCTION)) {
13494 mode_check_diagonal (SUB (p), x, y);
13495 warn_for_voiding (p, x, y, DIAGONAL_FUNCTION);
13496 } else if (IS (p, TRANSPOSE_FUNCTION)) {
13497 mode_check_transpose (SUB (p), x, y);
13498 warn_for_voiding (p, x, y, TRANSPOSE_FUNCTION);
13499 } else if (IS (p, ROW_FUNCTION)) {
13500 mode_check_row_column_function (SUB (p), x, y);
13501 warn_for_voiding (p, x, y, ROW_FUNCTION);
13502 } else if (IS (p, COLUMN_FUNCTION)) {
13503 mode_check_row_column_function (SUB (p), x, y);
13504 warn_for_voiding (p, x, y, COLUMN_FUNCTION);
13505 /* Ex unit */
13506 } else if (is_one_of (p, JUMP, SKIP, STOP)) {
13507 make_soid (y, STRONG, MODE (HIP), 0);
13508 } else if (IS (p, ASSIGNATION)) {
13509 mode_check_assignation (SUB (p), x, y);
13510 } else if (IS (p, IDENTITY_RELATION)) {
13511 mode_check_identity_relation (SUB (p), x, y);
13512 warn_for_voiding (p, x, y, IDENTITY_RELATION);
13513 } else if (IS (p, ROUTINE_TEXT)) {
13514 mode_check_routine_text (SUB (p), y);
13515 make_soid (y, SORT (x), MOID (p), 0);
13516 warn_for_voiding (p, x, y, ROUTINE_TEXT);
13517 } else if (IS (p, ASSERTION)) {
13518 mode_check_assertion (SUB (p));
13519 make_soid (y, STRONG, MODE (VOID), 0);
13520 } else if (IS (p, AND_FUNCTION)) {
13521 mode_check_bool_function (SUB (p), x, y);
13522 warn_for_voiding (p, x, y, AND_FUNCTION);
13523 } else if (IS (p, OR_FUNCTION)) {
13524 mode_check_bool_function (SUB (p), x, y);
13525 warn_for_voiding (p, x, y, OR_FUNCTION);
13526 } else if (IS (p, CODE_CLAUSE)) {
13527 make_soid (y, STRONG, MODE (HIP), 0);
13528 }
13529 MOID (p) = MOID (y);
13530 }
13531
13532 /**
13533 @brief Coerce bounds.
13534 @param p Node in syntax tree.
13535 **/
13536
13537 static void
coerce_bounds(NODE_T * p)13538 coerce_bounds (NODE_T * p)
13539 {
13540 for (; p != NO_NODE; FORWARD (p)) {
13541 if (IS (p, UNIT)) {
13542 SOID_T q;
13543 make_soid (&q, MEEK, MODE (INT), 0);
13544 coerce_unit (p, &q);
13545 } else {
13546 coerce_bounds (SUB (p));
13547 }
13548 }
13549 }
13550
13551 /**
13552 @brief Coerce declarer.
13553 @param p Node in syntax tree.
13554 **/
13555
13556 static void
coerce_declarer(NODE_T * p)13557 coerce_declarer (NODE_T * p)
13558 {
13559 for (; p != NO_NODE; FORWARD (p)) {
13560 if (IS (p, BOUNDS)) {
13561 coerce_bounds (SUB (p));
13562 } else {
13563 coerce_declarer (SUB (p));
13564 }
13565 }
13566 }
13567
13568 /**
13569 @brief Coerce identity declaration.
13570 @param p Node in syntax tree.
13571 **/
13572
13573 static void
coerce_identity_declaration(NODE_T * p)13574 coerce_identity_declaration (NODE_T * p)
13575 {
13576 if (p != NO_NODE) {
13577 switch (ATTRIBUTE (p)) {
13578 case DECLARER:
13579 {
13580 coerce_declarer (SUB (p));
13581 coerce_identity_declaration (NEXT (p));
13582 break;
13583 }
13584 case DEFINING_IDENTIFIER:
13585 {
13586 SOID_T q;
13587 make_soid (&q, STRONG, MOID (p), 0);
13588 coerce_unit (NEXT_NEXT (p), &q);
13589 break;
13590 }
13591 default:
13592 {
13593 coerce_identity_declaration (SUB (p));
13594 coerce_identity_declaration (NEXT (p));
13595 break;
13596 }
13597 }
13598 }
13599 }
13600
13601 /**
13602 @brief Coerce variable declaration.
13603 @param p Node in syntax tree.
13604 **/
13605
13606 static void
coerce_variable_declaration(NODE_T * p)13607 coerce_variable_declaration (NODE_T * p)
13608 {
13609 if (p != NO_NODE) {
13610 switch (ATTRIBUTE (p)) {
13611 case DECLARER:
13612 {
13613 coerce_declarer (SUB (p));
13614 coerce_variable_declaration (NEXT (p));
13615 break;
13616 }
13617 case DEFINING_IDENTIFIER:
13618 {
13619 if (whether (p, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, UNIT, STOP)) {
13620 SOID_T q;
13621 make_soid (&q, STRONG, SUB_MOID (p), 0);
13622 coerce_unit (NEXT_NEXT (p), &q);
13623 break;
13624 }
13625 }
13626 default:
13627 {
13628 coerce_variable_declaration (SUB (p));
13629 coerce_variable_declaration (NEXT (p));
13630 break;
13631 }
13632 }
13633 }
13634 }
13635
13636 /**
13637 @brief Coerce routine text.
13638 @param p Node in syntax tree.
13639 **/
13640
13641 static void
coerce_routine_text(NODE_T * p)13642 coerce_routine_text (NODE_T * p)
13643 {
13644 SOID_T w;
13645 if (IS (p, PARAMETER_PACK)) {
13646 FORWARD (p);
13647 }
13648 make_soid (&w, STRONG, MOID (p), 0);
13649 coerce_unit (NEXT_NEXT (p), &w);
13650 }
13651
13652 /**
13653 @brief Coerce proc declaration.
13654 @param p Node in syntax tree.
13655 **/
13656
13657 static void
coerce_proc_declaration(NODE_T * p)13658 coerce_proc_declaration (NODE_T * p)
13659 {
13660 if (p == NO_NODE) {
13661 return;
13662 } else if (IS (p, ROUTINE_TEXT)) {
13663 coerce_routine_text (SUB (p));
13664 } else {
13665 coerce_proc_declaration (SUB (p));
13666 coerce_proc_declaration (NEXT (p));
13667 }
13668 }
13669
13670 /**
13671 @brief Coerce_op_declaration.
13672 @param p Node in syntax tree.
13673 **/
13674
13675 static void
coerce_op_declaration(NODE_T * p)13676 coerce_op_declaration (NODE_T * p)
13677 {
13678 if (p == NO_NODE) {
13679 return;
13680 } else if (IS (p, DEFINING_OPERATOR)) {
13681 SOID_T q;
13682 make_soid (&q, STRONG, MOID (p), 0);
13683 coerce_unit (NEXT_NEXT (p), &q);
13684 } else {
13685 coerce_op_declaration (SUB (p));
13686 coerce_op_declaration (NEXT (p));
13687 }
13688 }
13689
13690 /**
13691 @brief Coerce brief op declaration.
13692 @param p Node in syntax tree.
13693 **/
13694
13695 static void
coerce_brief_op_declaration(NODE_T * p)13696 coerce_brief_op_declaration (NODE_T * p)
13697 {
13698 if (p == NO_NODE) {
13699 return;
13700 } else if (IS (p, DEFINING_OPERATOR)) {
13701 coerce_routine_text (SUB (NEXT_NEXT (p)));
13702 } else {
13703 coerce_brief_op_declaration (SUB (p));
13704 coerce_brief_op_declaration (NEXT (p));
13705 }
13706 }
13707
13708 /**
13709 @brief Coerce declaration list.
13710 @param p Node in syntax tree.
13711 **/
13712
13713 static void
coerce_declaration_list(NODE_T * p)13714 coerce_declaration_list (NODE_T * p)
13715 {
13716 if (p != NO_NODE) {
13717 switch (ATTRIBUTE (p)) {
13718 case IDENTITY_DECLARATION:
13719 {
13720 coerce_identity_declaration (SUB (p));
13721 break;
13722 }
13723 case VARIABLE_DECLARATION:
13724 {
13725 coerce_variable_declaration (SUB (p));
13726 break;
13727 }
13728 case MODE_DECLARATION:
13729 {
13730 coerce_declarer (SUB (p));
13731 break;
13732 }
13733 case PROCEDURE_DECLARATION:
13734 case PROCEDURE_VARIABLE_DECLARATION:
13735 {
13736 coerce_proc_declaration (SUB (p));
13737 break;
13738 }
13739 case BRIEF_OPERATOR_DECLARATION:
13740 {
13741 coerce_brief_op_declaration (SUB (p));
13742 break;
13743 }
13744 case OPERATOR_DECLARATION:
13745 {
13746 coerce_op_declaration (SUB (p));
13747 break;
13748 }
13749 default:
13750 {
13751 coerce_declaration_list (SUB (p));
13752 coerce_declaration_list (NEXT (p));
13753 break;
13754 }
13755 }
13756 }
13757 }
13758
13759 /**
13760 @brief Coerce serial.
13761 @param p Node in syntax tree.
13762 @param q Soid.
13763 @param k Whether k yields value other than VOID.
13764 **/
13765
13766 static void
coerce_serial(NODE_T * p,SOID_T * q,BOOL_T k)13767 coerce_serial (NODE_T * p, SOID_T * q, BOOL_T k)
13768 {
13769 if (p == NO_NODE) {
13770 return;
13771 } else if (IS (p, INITIALISER_SERIES)) {
13772 coerce_serial (SUB (p), q, A68_FALSE);
13773 coerce_serial (NEXT (p), q, k);
13774 } else if (IS (p, DECLARATION_LIST)) {
13775 coerce_declaration_list (SUB (p));
13776 } else if (is_one_of (p, LABEL, SEMI_SYMBOL, EXIT_SYMBOL, STOP)) {
13777 coerce_serial (NEXT (p), q, k);
13778 } else if (is_one_of (p, SERIAL_CLAUSE, ENQUIRY_CLAUSE, STOP)) {
13779 NODE_T *z = NEXT (p);
13780 if (z != NO_NODE) {
13781 if (IS (z, EXIT_SYMBOL) || IS (z, END_SYMBOL) || IS (z, CLOSE_SYMBOL) || IS (z, OCCA_SYMBOL)) {
13782 coerce_serial (SUB (p), q, A68_TRUE);
13783 } else {
13784 coerce_serial (SUB (p), q, A68_FALSE);
13785 }
13786 } else {
13787 coerce_serial (SUB (p), q, A68_TRUE);
13788 }
13789 coerce_serial (NEXT (p), q, k);
13790 } else if (IS (p, LABELED_UNIT)) {
13791 coerce_serial (SUB (p), q, k);
13792 } else if (IS (p, UNIT)) {
13793 if (k) {
13794 coerce_unit (p, q);
13795 } else {
13796 SOID_T strongvoid;
13797 make_soid (&strongvoid, STRONG, MODE (VOID), 0);
13798 coerce_unit (p, &strongvoid);
13799 }
13800 }
13801 }
13802
13803 /**
13804 @brief Coerce closed.
13805 @param p Node in syntax tree.
13806 @param q Soid.
13807 **/
13808
13809 static void
coerce_closed(NODE_T * p,SOID_T * q)13810 coerce_closed (NODE_T * p, SOID_T * q)
13811 {
13812 if (IS (p, SERIAL_CLAUSE)) {
13813 coerce_serial (p, q, A68_TRUE);
13814 } else if (is_one_of (p, OPEN_SYMBOL, BEGIN_SYMBOL, STOP)) {
13815 coerce_closed (NEXT (p), q);
13816 }
13817 }
13818
13819 /**
13820 @brief Coerce conditional.
13821 @param p Node in syntax tree.
13822 @param q Soid.
13823 **/
13824
13825 static void
coerce_conditional(NODE_T * p,SOID_T * q)13826 coerce_conditional (NODE_T * p, SOID_T * q)
13827 {
13828 SOID_T w;
13829 make_soid (&w, MEEK, MODE (BOOL), 0);
13830 coerce_serial (NEXT_SUB (p), &w, A68_TRUE);
13831 FORWARD (p);
13832 coerce_serial (NEXT_SUB (p), q, A68_TRUE);
13833 if ((FORWARD (p)) != NO_NODE) {
13834 if (is_one_of (p, ELSE_PART, CHOICE, STOP)) {
13835 coerce_serial (NEXT_SUB (p), q, A68_TRUE);
13836 } else if (is_one_of (p, ELIF_PART, BRIEF_ELIF_PART, STOP)) {
13837 coerce_conditional (SUB (p), q);
13838 }
13839 }
13840 }
13841
13842 /**
13843 @brief Coerce unit list.
13844 @param p Node in syntax tree.
13845 @param q Soid.
13846 **/
13847
13848 static void
coerce_unit_list(NODE_T * p,SOID_T * q)13849 coerce_unit_list (NODE_T * p, SOID_T * q)
13850 {
13851 if (p == NO_NODE) {
13852 return;
13853 } else if (IS (p, UNIT_LIST)) {
13854 coerce_unit_list (SUB (p), q);
13855 coerce_unit_list (NEXT (p), q);
13856 } else if (is_one_of (p, OPEN_SYMBOL, BEGIN_SYMBOL, COMMA_SYMBOL, STOP)) {
13857 coerce_unit_list (NEXT (p), q);
13858 } else if (IS (p, UNIT)) {
13859 coerce_unit (p, q);
13860 coerce_unit_list (NEXT (p), q);
13861 }
13862 }
13863
13864 /**
13865 @brief Coerce int case.
13866 @param p Node in syntax tree.
13867 @param q Soid.
13868 **/
13869
13870 static void
coerce_int_case(NODE_T * p,SOID_T * q)13871 coerce_int_case (NODE_T * p, SOID_T * q)
13872 {
13873 SOID_T w;
13874 make_soid (&w, MEEK, MODE (INT), 0);
13875 coerce_serial (NEXT_SUB (p), &w, A68_TRUE);
13876 FORWARD (p);
13877 coerce_unit_list (NEXT_SUB (p), q);
13878 if ((FORWARD (p)) != NO_NODE) {
13879 if (is_one_of (p, OUT_PART, CHOICE, STOP)) {
13880 coerce_serial (NEXT_SUB (p), q, A68_TRUE);
13881 } else if (is_one_of (p, CASE_OUSE_PART, BRIEF_OUSE_PART, STOP)) {
13882 coerce_int_case (SUB (p), q);
13883 }
13884 }
13885 }
13886
13887 /**
13888 @brief Coerce spec unit list.
13889 @param p Node in syntax tree.
13890 @param q Soid.
13891 **/
13892
13893 static void
coerce_spec_unit_list(NODE_T * p,SOID_T * q)13894 coerce_spec_unit_list (NODE_T * p, SOID_T * q)
13895 {
13896 for (; p != NO_NODE; FORWARD (p)) {
13897 if (is_one_of (p, SPECIFIED_UNIT_LIST, SPECIFIED_UNIT, STOP)) {
13898 coerce_spec_unit_list (SUB (p), q);
13899 } else if (IS (p, UNIT)) {
13900 coerce_unit (p, q);
13901 }
13902 }
13903 }
13904
13905 /**
13906 @brief Coerce united case.
13907 @param p Node in syntax tree.
13908 @param q Soid.
13909 **/
13910
13911 static void
coerce_united_case(NODE_T * p,SOID_T * q)13912 coerce_united_case (NODE_T * p, SOID_T * q)
13913 {
13914 SOID_T w;
13915 make_soid (&w, MEEK, MOID (SUB (p)), 0);
13916 coerce_serial (NEXT_SUB (p), &w, A68_TRUE);
13917 FORWARD (p);
13918 coerce_spec_unit_list (NEXT_SUB (p), q);
13919 if ((FORWARD (p)) != NO_NODE) {
13920 if (is_one_of (p, OUT_PART, CHOICE, STOP)) {
13921 coerce_serial (NEXT_SUB (p), q, A68_TRUE);
13922 } else if (is_one_of (p, CONFORMITY_OUSE_PART, BRIEF_CONFORMITY_OUSE_PART, STOP)) {
13923 coerce_united_case (SUB (p), q);
13924 }
13925 }
13926 }
13927
13928 /**
13929 @brief Coerce loop.
13930 @param p Node in syntax tree.
13931 **/
13932
13933 static void
coerce_loop(NODE_T * p)13934 coerce_loop (NODE_T * p)
13935 {
13936 if (IS (p, FOR_PART)) {
13937 coerce_loop (NEXT (p));
13938 } else if (is_one_of (p, FROM_PART, BY_PART, TO_PART, STOP)) {
13939 SOID_T w;
13940 make_soid (&w, MEEK, MODE (INT), 0);
13941 coerce_unit (NEXT_SUB (p), &w);
13942 coerce_loop (NEXT (p));
13943 } else if (IS (p, WHILE_PART)) {
13944 SOID_T w;
13945 make_soid (&w, MEEK, MODE (BOOL), 0);
13946 coerce_serial (NEXT_SUB (p), &w, A68_TRUE);
13947 coerce_loop (NEXT (p));
13948 } else if (is_one_of (p, DO_PART, ALT_DO_PART, STOP)) {
13949 SOID_T w;
13950 NODE_T *do_p = NEXT_SUB (p), *un_p;
13951 make_soid (&w, STRONG, MODE (VOID), 0);
13952 coerce_serial (do_p, &w, A68_TRUE);
13953 if (IS (do_p, SERIAL_CLAUSE)) {
13954 un_p = NEXT (do_p);
13955 } else {
13956 un_p = do_p;
13957 }
13958 if (un_p != NO_NODE && IS (un_p, UNTIL_PART)) {
13959 SOID_T sw;
13960 make_soid (&sw, MEEK, MODE (BOOL), 0);
13961 coerce_serial (NEXT_SUB (un_p), &sw, A68_TRUE);
13962 }
13963 }
13964 }
13965
13966 /**
13967 @brief Coerce struct display.
13968 @param r Pack.
13969 @param p Node in syntax tree.
13970 **/
13971
13972 static void
coerce_struct_display(PACK_T ** r,NODE_T * p)13973 coerce_struct_display (PACK_T ** r, NODE_T * p)
13974 {
13975 if (p == NO_NODE) {
13976 return;
13977 } else if (IS (p, UNIT_LIST)) {
13978 coerce_struct_display (r, SUB (p));
13979 coerce_struct_display (r, NEXT (p));
13980 } else if (is_one_of (p, OPEN_SYMBOL, BEGIN_SYMBOL, COMMA_SYMBOL, STOP)) {
13981 coerce_struct_display (r, NEXT (p));
13982 } else if (IS (p, UNIT)) {
13983 SOID_T s;
13984 make_soid (&s, STRONG, MOID (*r), 0);
13985 coerce_unit (p, &s);
13986 FORWARD (*r);
13987 coerce_struct_display (r, NEXT (p));
13988 }
13989 }
13990
13991 /**
13992 @brief Coerce collateral.
13993 @param p Node in syntax tree.
13994 @param q Soid.
13995 **/
13996
13997 static void
coerce_collateral(NODE_T * p,SOID_T * q)13998 coerce_collateral (NODE_T * p, SOID_T * q)
13999 {
14000 if (!(whether (p, BEGIN_SYMBOL, END_SYMBOL, STOP) || whether (p, OPEN_SYMBOL, CLOSE_SYMBOL, STOP))) {
14001 if (IS (MOID (q), STRUCT_SYMBOL)) {
14002 PACK_T *t = PACK (MOID (q));
14003 coerce_struct_display (&t, p);
14004 } else if (IS (MOID (q), FLEX_SYMBOL)) {
14005 SOID_T w;
14006 make_soid (&w, STRONG, SLICE (SUB_MOID (q)), 0);
14007 coerce_unit_list (p, &w);
14008 } else if (IS (MOID (q), ROW_SYMBOL)) {
14009 SOID_T w;
14010 make_soid (&w, STRONG, SLICE (MOID (q)), 0);
14011 coerce_unit_list (p, &w);
14012 } else {
14013 /* if (MOID (q) != MODE (VOID)) */
14014 coerce_unit_list (p, q);
14015 }
14016 }
14017 }
14018
14019 /**
14020 @brief Coerce_enclosed.
14021 @param p Node in syntax tree.
14022 @param q Soid.
14023 **/
14024
14025 void
coerce_enclosed(NODE_T * p,SOID_T * q)14026 coerce_enclosed (NODE_T * p, SOID_T * q)
14027 {
14028 if (IS (p, ENCLOSED_CLAUSE)) {
14029 coerce_enclosed (SUB (p), q);
14030 } else if (IS (p, CLOSED_CLAUSE)) {
14031 coerce_closed (SUB (p), q);
14032 } else if (IS (p, COLLATERAL_CLAUSE)) {
14033 coerce_collateral (SUB (p), q);
14034 } else if (IS (p, PARALLEL_CLAUSE)) {
14035 coerce_collateral (SUB (NEXT_SUB (p)), q);
14036 } else if (IS (p, CONDITIONAL_CLAUSE)) {
14037 coerce_conditional (SUB (p), q);
14038 } else if (IS (p, CASE_CLAUSE)) {
14039 coerce_int_case (SUB (p), q);
14040 } else if (IS (p, CONFORMITY_CLAUSE)) {
14041 coerce_united_case (SUB (p), q);
14042 } else if (IS (p, LOOP_CLAUSE)) {
14043 coerce_loop (SUB (p));
14044 }
14045 MOID (p) = depref_rows (MOID (p), MOID (q));
14046 }
14047
14048 /**
14049 @brief Get monad moid.
14050 @param p Node in syntax tree.
14051 **/
14052
14053 static MOID_T *
get_monad_moid(NODE_T * p)14054 get_monad_moid (NODE_T * p)
14055 {
14056 if (TAX (p) != NO_TAG && TAX (p) != error_tag) {
14057 MOID (p) = MOID (TAX (p));
14058 return (MOID (PACK (MOID (p))));
14059 } else {
14060 return (MODE (ERROR));
14061 }
14062 }
14063
14064 /**
14065 @brief Coerce monad oper.
14066 @param p Node in syntax tree.
14067 @param q Soid.
14068 **/
14069
14070 static void
coerce_monad_oper(NODE_T * p,SOID_T * q)14071 coerce_monad_oper (NODE_T * p, SOID_T * q)
14072 {
14073 if (p != NO_NODE) {
14074 SOID_T z;
14075 make_soid (&z, FIRM, MOID (PACK (MOID (TAX (p)))), 0);
14076 INSERT_COERCIONS (NEXT (p), MOID (q), &z);
14077 }
14078 }
14079
14080 /**
14081 @brief Coerce monad formula.
14082 @param p Node in syntax tree.
14083 **/
14084
14085 static void
coerce_monad_formula(NODE_T * p)14086 coerce_monad_formula (NODE_T * p)
14087 {
14088 SOID_T e;
14089 make_soid (&e, STRONG, get_monad_moid (p), 0);
14090 coerce_operand (NEXT (p), &e);
14091 coerce_monad_oper (p, &e);
14092 }
14093
14094 /**
14095 @brief Coerce operand.
14096 @param p Node in syntax tree.
14097 @param q Soid.
14098 **/
14099
14100 static void
coerce_operand(NODE_T * p,SOID_T * q)14101 coerce_operand (NODE_T * p, SOID_T * q)
14102 {
14103 if (IS (p, MONADIC_FORMULA)) {
14104 coerce_monad_formula (SUB (p));
14105 if (MOID (p) != MOID (q)) {
14106 make_sub (p, p, FORMULA);
14107 INSERT_COERCIONS (p, MOID (p), q);
14108 make_sub (p, p, TERTIARY);
14109 }
14110 MOID (p) = depref_rows (MOID (p), MOID (q));
14111 } else if (IS (p, FORMULA)) {
14112 coerce_formula (SUB (p), q);
14113 INSERT_COERCIONS (p, MOID (p), q);
14114 MOID (p) = depref_rows (MOID (p), MOID (q));
14115 } else if (IS (p, SECONDARY)) {
14116 coerce_unit (SUB (p), q);
14117 MOID (p) = MOID (SUB (p));
14118 }
14119 }
14120
14121 /**
14122 @brief Coerce formula.
14123 @param p Node in syntax tree.
14124 @param q Soid.
14125 **/
14126
14127 static void
coerce_formula(NODE_T * p,SOID_T * q)14128 coerce_formula (NODE_T * p, SOID_T * q)
14129 {
14130 (void) q;
14131 if (IS (p, MONADIC_FORMULA) && NEXT (p) == NO_NODE) {
14132 coerce_monad_formula (SUB (p));
14133 } else {
14134 if (TAX (NEXT (p)) != NO_TAG && TAX (NEXT (p)) != error_tag) {
14135 SOID_T s;
14136 NODE_T *op = NEXT (p), *nq = NEXT_NEXT (p);
14137 MOID_T *w = MOID (op);
14138 MOID_T *u = MOID (PACK (w)), *v = MOID (NEXT (PACK (w)));
14139 make_soid (&s, STRONG, u, 0);
14140 coerce_operand (p, &s);
14141 make_soid (&s, STRONG, v, 0);
14142 coerce_operand (nq, &s);
14143 }
14144 }
14145 }
14146
14147 /**
14148 @brief Coerce assignation.
14149 @param p Node in syntax tree.
14150 **/
14151
14152 static void
coerce_assignation(NODE_T * p)14153 coerce_assignation (NODE_T * p)
14154 {
14155 SOID_T w;
14156 make_soid (&w, SOFT, MOID (p), 0);
14157 coerce_unit (SUB (p), &w);
14158 make_soid (&w, STRONG, SUB_MOID (p), 0);
14159 coerce_unit (NEXT_NEXT (p), &w);
14160 }
14161
14162 /**
14163 @brief Coerce relation.
14164 @param p Node in syntax tree.
14165 **/
14166
14167 static void
coerce_relation(NODE_T * p)14168 coerce_relation (NODE_T * p)
14169 {
14170 SOID_T w;
14171 make_soid (&w, STRONG, MOID (p), 0);
14172 coerce_unit (SUB (p), &w);
14173 make_soid (&w, STRONG, MOID (NEXT_NEXT (p)), 0);
14174 coerce_unit (SUB (NEXT_NEXT (p)), &w);
14175 }
14176
14177 /**
14178 @brief Coerce bool function.
14179 @param p Node in syntax tree.
14180 **/
14181
14182 static void
coerce_bool_function(NODE_T * p)14183 coerce_bool_function (NODE_T * p)
14184 {
14185 SOID_T w;
14186 make_soid (&w, STRONG, MODE (BOOL), 0);
14187 coerce_unit (SUB (p), &w);
14188 coerce_unit (SUB (NEXT_NEXT (p)), &w);
14189 }
14190
14191 /**
14192 @brief Coerce assertion.
14193 @param p Node in syntax tree.
14194 **/
14195
14196 static void
coerce_assertion(NODE_T * p)14197 coerce_assertion (NODE_T * p)
14198 {
14199 SOID_T w;
14200 make_soid (&w, MEEK, MODE (BOOL), 0);
14201 coerce_enclosed (SUB_NEXT (p), &w);
14202 }
14203
14204 /**
14205 @brief Coerce selection.
14206 @param p Node in syntax tree.
14207 **/
14208
14209 static void
coerce_selection(NODE_T * p)14210 coerce_selection (NODE_T * p)
14211 {
14212 SOID_T w;
14213 make_soid (&w, /* WEAK */ STRONG, MOID (NEXT (p)), 0);
14214 coerce_unit (SUB_NEXT (p), &w);
14215 }
14216
14217 /**
14218 @brief Coerce cast.
14219 @param p Node in syntax tree.
14220 **/
14221
14222 static void
coerce_cast(NODE_T * p)14223 coerce_cast (NODE_T * p)
14224 {
14225 SOID_T w;
14226 coerce_declarer (p);
14227 make_soid (&w, STRONG, MOID (p), 0);
14228 coerce_enclosed (NEXT (p), &w);
14229 }
14230
14231 /**
14232 @brief Coerce argument list.
14233 @param r Pack.
14234 @param p Node in syntax tree.
14235 **/
14236
14237 static void
coerce_argument_list(PACK_T ** r,NODE_T * p)14238 coerce_argument_list (PACK_T ** r, NODE_T * p)
14239 {
14240 for (; p != NO_NODE; FORWARD (p)) {
14241 if (IS (p, ARGUMENT_LIST)) {
14242 coerce_argument_list (r, SUB (p));
14243 } else if (IS (p, UNIT)) {
14244 SOID_T s;
14245 make_soid (&s, STRONG, MOID (*r), 0);
14246 coerce_unit (p, &s);
14247 FORWARD (*r);
14248 } else if (IS (p, TRIMMER)) {
14249 FORWARD (*r);
14250 }
14251 }
14252 }
14253
14254 /**
14255 @brief Coerce call.
14256 @param p Node in syntax tree.
14257 **/
14258
14259 static void
coerce_call(NODE_T * p)14260 coerce_call (NODE_T * p)
14261 {
14262 MOID_T *proc = MOID (p);
14263 SOID_T w;
14264 PACK_T *t;
14265 make_soid (&w, MEEK, proc, 0);
14266 coerce_unit (SUB (p), &w);
14267 FORWARD (p);
14268 t = PACK (proc);
14269 coerce_argument_list (&t, SUB (p));
14270 }
14271
14272 /**
14273 @brief Coerce meek int.
14274 @param p Node in syntax tree.
14275 **/
14276
14277 static void
coerce_meek_int(NODE_T * p)14278 coerce_meek_int (NODE_T * p)
14279 {
14280 SOID_T x;
14281 make_soid (&x, MEEK, MODE (INT), 0);
14282 coerce_unit (p, &x);
14283 }
14284
14285 /**
14286 @brief Coerce trimmer.
14287 @param p Node in syntax tree.
14288 **/
14289
14290 static void
coerce_trimmer(NODE_T * p)14291 coerce_trimmer (NODE_T * p)
14292 {
14293 if (p != NO_NODE) {
14294 if (IS (p, UNIT)) {
14295 coerce_meek_int (p);
14296 coerce_trimmer (NEXT (p));
14297 } else {
14298 coerce_trimmer (NEXT (p));
14299 }
14300 }
14301 }
14302
14303 /**
14304 @brief Coerce indexer.
14305 @param p Node in syntax tree.
14306 **/
14307
14308 static void
coerce_indexer(NODE_T * p)14309 coerce_indexer (NODE_T * p)
14310 {
14311 if (p != NO_NODE) {
14312 if (IS (p, TRIMMER)) {
14313 coerce_trimmer (SUB (p));
14314 } else if (IS (p, UNIT)) {
14315 coerce_meek_int (p);
14316 } else {
14317 coerce_indexer (SUB (p));
14318 coerce_indexer (NEXT (p));
14319 }
14320 }
14321 }
14322
14323 /**
14324 @brief Coerce_slice.
14325 @param p Node in syntax tree.
14326 **/
14327
14328 static void
coerce_slice(NODE_T * p)14329 coerce_slice (NODE_T * p)
14330 {
14331 SOID_T w;
14332 MOID_T *row;
14333 row = MOID (p);
14334 make_soid (&w, /* WEAK */ STRONG, row, 0);
14335 coerce_unit (SUB (p), &w);
14336 coerce_indexer (SUB_NEXT (p));
14337 }
14338
14339 /**
14340 @brief Mode coerce diagonal.
14341 @param p Node in syntax tree.
14342 **/
14343
14344 static void
coerce_diagonal(NODE_T * p)14345 coerce_diagonal (NODE_T * p)
14346 {
14347 SOID_T w;
14348 if (IS (p, TERTIARY)) {
14349 make_soid (&w, MEEK, MODE (INT), 0);
14350 coerce_unit (SUB (p), &w);
14351 FORWARD (p);
14352 }
14353 make_soid (&w, /* WEAK */ STRONG, MOID (NEXT (p)), 0);
14354 coerce_unit (SUB_NEXT (p), &w);
14355 }
14356
14357 /**
14358 @brief Mode coerce transpose.
14359 @param p Node in syntax tree.
14360 **/
14361
14362 static void
coerce_transpose(NODE_T * p)14363 coerce_transpose (NODE_T * p)
14364 {
14365 SOID_T w;
14366 make_soid (&w, /* WEAK */ STRONG, MOID (NEXT (p)), 0);
14367 coerce_unit (SUB_NEXT (p), &w);
14368 }
14369
14370 /**
14371 @brief Mode coerce row or column function.
14372 @param p Node in syntax tree.
14373 **/
14374
14375 static void
coerce_row_column_function(NODE_T * p)14376 coerce_row_column_function (NODE_T * p)
14377 {
14378 SOID_T w;
14379 if (IS (p, TERTIARY)) {
14380 make_soid (&w, MEEK, MODE (INT), 0);
14381 coerce_unit (SUB (p), &w);
14382 FORWARD (p);
14383 }
14384 make_soid (&w, /* WEAK */ STRONG, MOID (NEXT (p)), 0);
14385 coerce_unit (SUB_NEXT (p), &w);
14386 }
14387
14388 /**
14389 @brief Coerce format text.
14390 @param p Node in syntax tree.
14391 **/
14392
14393 static void
coerce_format_text(NODE_T * p)14394 coerce_format_text (NODE_T * p)
14395 {
14396 for (; p != NO_NODE; FORWARD (p)) {
14397 coerce_format_text (SUB (p));
14398 if (IS (p, FORMAT_PATTERN)) {
14399 SOID_T x;
14400 make_soid (&x, STRONG, MODE (FORMAT), 0);
14401 coerce_enclosed (SUB (NEXT_SUB (p)), &x);
14402 } else if (IS (p, GENERAL_PATTERN) && NEXT_SUB (p) != NO_NODE) {
14403 SOID_T x;
14404 make_soid (&x, STRONG, MODE (ROW_INT), 0);
14405 coerce_enclosed (SUB (NEXT_SUB (p)), &x);
14406 } else if (IS (p, DYNAMIC_REPLICATOR)) {
14407 SOID_T x;
14408 make_soid (&x, STRONG, MODE (INT), 0);
14409 coerce_enclosed (SUB (NEXT_SUB (p)), &x);
14410 }
14411 }
14412 }
14413
14414 /**
14415 @brief Coerce unit.
14416 @param p Node in syntax tree.
14417 @param q Soid.
14418 **/
14419
14420 static void
coerce_unit(NODE_T * p,SOID_T * q)14421 coerce_unit (NODE_T * p, SOID_T * q)
14422 {
14423 if (p == NO_NODE) {
14424 return;
14425 } else if (is_one_of (p, UNIT, TERTIARY, SECONDARY, PRIMARY, STOP)) {
14426 coerce_unit (SUB (p), q);
14427 MOID (p) = MOID (SUB (p));
14428 /* Ex primary */
14429 } else if (IS (p, CALL)) {
14430 coerce_call (SUB (p));
14431 INSERT_COERCIONS (p, MOID (p), q);
14432 } else if (IS (p, SLICE)) {
14433 coerce_slice (SUB (p));
14434 INSERT_COERCIONS (p, MOID (p), q);
14435 } else if (IS (p, CAST)) {
14436 coerce_cast (SUB (p));
14437 INSERT_COERCIONS (p, MOID (p), q);
14438 } else if (is_one_of (p, DENOTATION, IDENTIFIER, STOP)) {
14439 INSERT_COERCIONS (p, MOID (p), q);
14440 } else if (IS (p, FORMAT_TEXT)) {
14441 coerce_format_text (SUB (p));
14442 INSERT_COERCIONS (p, MOID (p), q);
14443 } else if (IS (p, ENCLOSED_CLAUSE)) {
14444 coerce_enclosed (p, q);
14445 /* Ex secondary */
14446 } else if (IS (p, SELECTION)) {
14447 coerce_selection (SUB (p));
14448 INSERT_COERCIONS (p, MOID (p), q);
14449 } else if (IS (p, GENERATOR)) {
14450 coerce_declarer (SUB (p));
14451 INSERT_COERCIONS (p, MOID (p), q);
14452 /* Ex tertiary */
14453 } else if (IS (p, NIHIL)) {
14454 if (ATTRIBUTE (MOID (q)) != REF_SYMBOL && MOID (q) != MODE (VOID)) {
14455 diagnostic_node (A68_ERROR, p, ERROR_NO_NAME_REQUIRED);
14456 }
14457 MOID (p) = depref_rows (MOID (p), MOID (q));
14458 } else if (IS (p, FORMULA)) {
14459 coerce_formula (SUB (p), q);
14460 INSERT_COERCIONS (p, MOID (p), q);
14461 } else if (IS (p, DIAGONAL_FUNCTION)) {
14462 coerce_diagonal (SUB (p));
14463 INSERT_COERCIONS (p, MOID (p), q);
14464 } else if (IS (p, TRANSPOSE_FUNCTION)) {
14465 coerce_transpose (SUB (p));
14466 INSERT_COERCIONS (p, MOID (p), q);
14467 } else if (IS (p, ROW_FUNCTION)) {
14468 coerce_row_column_function (SUB (p));
14469 INSERT_COERCIONS (p, MOID (p), q);
14470 } else if (IS (p, COLUMN_FUNCTION)) {
14471 coerce_row_column_function (SUB (p));
14472 INSERT_COERCIONS (p, MOID (p), q);
14473 /* Ex unit */
14474 } else if (IS (p, JUMP)) {
14475 if (MOID (q) == MODE (PROC_VOID)) {
14476 make_sub (p, p, PROCEDURING);
14477 }
14478 MOID (p) = depref_rows (MOID (p), MOID (q));
14479 } else if (IS (p, SKIP)) {
14480 MOID (p) = depref_rows (MOID (p), MOID (q));
14481 } else if (IS (p, ASSIGNATION)) {
14482 coerce_assignation (SUB (p));
14483 INSERT_COERCIONS (p, MOID (p), q);
14484 MOID (p) = depref_rows (MOID (p), MOID (q));
14485 } else if (IS (p, IDENTITY_RELATION)) {
14486 coerce_relation (SUB (p));
14487 INSERT_COERCIONS (p, MOID (p), q);
14488 } else if (IS (p, ROUTINE_TEXT)) {
14489 coerce_routine_text (SUB (p));
14490 INSERT_COERCIONS (p, MOID (p), q);
14491 } else if (is_one_of (p, AND_FUNCTION, OR_FUNCTION, STOP)) {
14492 coerce_bool_function (SUB (p));
14493 INSERT_COERCIONS (p, MOID (p), q);
14494 } else if (IS (p, ASSERTION)) {
14495 coerce_assertion (SUB (p));
14496 INSERT_COERCIONS (p, MOID (p), q);
14497 }
14498 }
14499
14500 /**
14501 @brief Widen denotation depending on mode required, this is an extension to A68.
14502 @param p Node in syntax tree.
14503 **/
14504
14505 void
widen_denotation(NODE_T * p)14506 widen_denotation (NODE_T * p)
14507 {
14508 #define WIDEN {\
14509 *q = *(SUB (q));\
14510 ATTRIBUTE (q) = DENOTATION;\
14511 MOID (q) = lm;\
14512 STATUS_SET (q, OPTIMAL_MASK);\
14513 }
14514 #define WARN_WIDENING\
14515 if (OPTION_PORTCHECK (&program) && !(STATUS_TEST (SUB (q), OPTIMAL_MASK))) {\
14516 diagnostic_node (A68_WARNING | A68_FORCE_DIAGNOSTICS, q, WARNING_WIDENING_NOT_PORTABLE);\
14517 }
14518 NODE_T *q;
14519 for (q = p; q != NO_NODE; FORWARD (q)) {
14520 widen_denotation (SUB (q));
14521 if (IS (q, WIDENING) && IS (SUB (q), DENOTATION)) {
14522 MOID_T *lm = MOID (q), *m = MOID (SUB (q));
14523 if (lm == MODE (LONGLONG_INT) && m == MODE (LONG_INT)) {
14524 WARN_WIDENING;
14525 WIDEN;
14526 }
14527 if (lm == MODE (LONG_INT) && m == MODE (INT)) {
14528 WARN_WIDENING;
14529 WIDEN;
14530 }
14531 if (lm == MODE (LONGLONG_REAL) && m == MODE (LONG_REAL)) {
14532 WARN_WIDENING;
14533 WIDEN;
14534 }
14535 if (lm == MODE (LONG_REAL) && m == MODE (REAL)) {
14536 WARN_WIDENING;
14537 WIDEN;
14538 }
14539 if (lm == MODE (LONG_REAL) && m == MODE (LONG_INT)) {
14540 WIDEN;
14541 }
14542 if (lm == MODE (REAL) && m == MODE (INT)) {
14543 WIDEN;
14544 }
14545 if (lm == MODE (LONGLONG_BITS) && m == MODE (LONG_BITS)) {
14546 WARN_WIDENING;
14547 WIDEN;
14548 }
14549 if (lm == MODE (LONG_BITS) && m == MODE (BITS)) {
14550 WARN_WIDENING;
14551 WIDEN;
14552 }
14553 return;
14554 }
14555 }
14556 #undef WIDEN
14557 #undef WARN_WIDENING
14558 }
14559
14560 /********************************************************************/
14561 /* Static scope checker, at run time we check dynamic scope as well */
14562 /********************************************************************/
14563
14564 /*
14565 Static scope checker.
14566 Also a little preparation for the monitor:
14567 - indicates UNITs that can be interrupted.
14568 */
14569
14570
14571 /**
14572 @brief Scope_make_tuple.
14573 @param e Level.
14574 @param t Whether transient.
14575 @return Tuple (e, t).
14576 **/
14577
14578 static TUPLE_T
scope_make_tuple(int e,int t)14579 scope_make_tuple (int e, int t)
14580 {
14581 static TUPLE_T z;
14582 LEVEL (&z) = e;
14583 TRANSIENT (&z) = (BOOL_T) t;
14584 return (z);
14585 }
14586
14587 /**
14588 @brief Link scope information into the list.
14589 @param sl Chain to link into.
14590 @param p Node in syntax tree.
14591 @param tup Tuple to link.
14592 **/
14593
14594 static void
scope_add(SCOPE_T ** sl,NODE_T * p,TUPLE_T tup)14595 scope_add (SCOPE_T ** sl, NODE_T * p, TUPLE_T tup)
14596 {
14597 if (sl != NO_VAR) {
14598 SCOPE_T *ns = (SCOPE_T *) get_temp_heap_space ((unsigned) SIZE_AL (SCOPE_T));
14599 WHERE (ns) = p;
14600 TUPLE (ns) = tup;
14601 NEXT (ns) = *sl;
14602 *sl = ns;
14603 }
14604 }
14605
14606 /**
14607 @brief Scope_check.
14608 @param top Top of scope chain.
14609 @param mask What to check.
14610 @param dest Level to check against.
14611 @return Whether errors were detected.
14612 **/
14613
14614 static BOOL_T
scope_check(SCOPE_T * top,int mask,int dest)14615 scope_check (SCOPE_T * top, int mask, int dest)
14616 {
14617 SCOPE_T *s;
14618 int errors = 0;
14619 /* Transient names cannot be stored */
14620 if (mask & TRANSIENT) {
14621 for (s = top; s != NO_SCOPE; FORWARD (s)) {
14622 if (TRANSIENT (&TUPLE (s)) & TRANSIENT) {
14623 diagnostic_node (A68_ERROR, WHERE (s), ERROR_TRANSIENT_NAME);
14624 STATUS_SET (WHERE (s), SCOPE_ERROR_MASK);
14625 errors++;
14626 }
14627 }
14628 }
14629 for (s = top; s != NO_SCOPE; FORWARD (s)) {
14630 if (dest < LEVEL (&TUPLE (s)) && !STATUS_TEST (WHERE (s), SCOPE_ERROR_MASK)) {
14631 /* Potential scope violations */
14632 MOID_T *sw = MOID (WHERE (s));
14633 if (sw != NO_MOID) {
14634 if (IS (sw, REF_SYMBOL) || IS (sw, PROC_SYMBOL)
14635 || IS (sw, FORMAT_SYMBOL) || IS (sw, UNION_SYMBOL)) {
14636 diagnostic_node (A68_WARNING, WHERE (s), WARNING_SCOPE_STATIC, MOID (WHERE (s)), ATTRIBUTE (WHERE (s)));
14637 }
14638 }
14639 STATUS_SET (WHERE (s), SCOPE_ERROR_MASK);
14640 errors++;
14641 }
14642 }
14643 return ((BOOL_T) (errors == 0));
14644 }
14645
14646 /**
14647 @brief Scope_check_multiple.
14648 @param top Top of scope chain.
14649 @param mask What to check.
14650 @param dest Level to check against.
14651 @return Whether error.
14652 **/
14653
14654 static BOOL_T
scope_check_multiple(SCOPE_T * top,int mask,SCOPE_T * dest)14655 scope_check_multiple (SCOPE_T * top, int mask, SCOPE_T * dest)
14656 {
14657 BOOL_T no_err = A68_TRUE;
14658 for (; dest != NO_SCOPE; FORWARD (dest)) {
14659 no_err &= scope_check (top, mask, LEVEL (&TUPLE (dest)));
14660 }
14661 return (no_err);
14662 }
14663
14664 /**
14665 @brief Check_identifier_usage.
14666 @param t Tag.
14667 @param p Node in syntax tree.
14668 **/
14669
14670 static void
check_identifier_usage(TAG_T * t,NODE_T * p)14671 check_identifier_usage (TAG_T * t, NODE_T * p)
14672 {
14673 for (; p != NO_NODE; FORWARD (p)) {
14674 if (IS (p, IDENTIFIER) && TAX (p) == t && ATTRIBUTE (MOID (t)) != PROC_SYMBOL) {
14675 diagnostic_node (A68_WARNING, p, WARNING_UNINITIALISED);
14676 }
14677 check_identifier_usage (t, SUB (p));
14678 }
14679 }
14680
14681 /**
14682 @brief Scope_find_youngest_outside.
14683 @param s Chain to link into.
14684 @param treshold Threshold level.
14685 @return Youngest tuple outside.
14686 **/
14687
14688 static TUPLE_T
scope_find_youngest_outside(SCOPE_T * s,int treshold)14689 scope_find_youngest_outside (SCOPE_T * s, int treshold)
14690 {
14691 TUPLE_T z = scope_make_tuple (PRIMAL_SCOPE, NOT_TRANSIENT);
14692 for (; s != NO_SCOPE; FORWARD (s)) {
14693 if (LEVEL (&TUPLE (s)) > LEVEL (&z) && LEVEL (&TUPLE (s)) <= treshold) {
14694 z = TUPLE (s);
14695 }
14696 }
14697 return (z);
14698 }
14699
14700 /**
14701 @brief Scope_find_youngest.
14702 @param s Chain to link into.
14703 @return Youngest tuple outside.
14704 **/
14705
14706 static TUPLE_T
scope_find_youngest(SCOPE_T * s)14707 scope_find_youngest (SCOPE_T * s)
14708 {
14709 return (scope_find_youngest_outside (s, A68_MAX_INT));
14710 }
14711
14712 /* Routines for determining scope of ROUTINE TEXT or FORMAT TEXT */
14713
14714 /**
14715 @brief Get_declarer_elements.
14716 @param p Node in syntax tree.
14717 @param r Chain to link into.
14718 @param no_ref Whether no REF seen yet.
14719 **/
14720
14721 static void
get_declarer_elements(NODE_T * p,SCOPE_T ** r,BOOL_T no_ref)14722 get_declarer_elements (NODE_T * p, SCOPE_T ** r, BOOL_T no_ref)
14723 {
14724 if (p != NO_NODE) {
14725 if (IS (p, BOUNDS)) {
14726 gather_scopes_for_youngest (SUB (p), r);
14727 } else if (IS (p, INDICANT)) {
14728 if (MOID (p) != NO_MOID && TAX (p) != NO_TAG && HAS_ROWS (MOID (p)) && no_ref) {
14729 scope_add (r, p, scope_make_tuple (TAG_LEX_LEVEL (TAX (p)), NOT_TRANSIENT));
14730 }
14731 } else if (IS (p, REF_SYMBOL)) {
14732 get_declarer_elements (NEXT (p), r, A68_FALSE);
14733 } else if (is_one_of (p, PROC_SYMBOL, UNION_SYMBOL, STOP)) {
14734 ;
14735 } else {
14736 get_declarer_elements (SUB (p), r, no_ref);
14737 get_declarer_elements (NEXT (p), r, no_ref);
14738 }
14739 }
14740 }
14741
14742 /**
14743 @brief Gather_scopes_for_youngest.
14744 @param p Node in syntax tree.
14745 @param s Chain to link into.
14746 **/
14747
14748 static void
gather_scopes_for_youngest(NODE_T * p,SCOPE_T ** s)14749 gather_scopes_for_youngest (NODE_T * p, SCOPE_T ** s)
14750 {
14751 for (; p != NO_NODE; FORWARD (p)) {
14752 if ((is_one_of (p, ROUTINE_TEXT, FORMAT_TEXT, STOP)) && (YOUNGEST_ENVIRON (TAX (p)) == PRIMAL_SCOPE)) {
14753 SCOPE_T *t = NO_SCOPE;
14754 TUPLE_T tup;
14755 gather_scopes_for_youngest (SUB (p), &t);
14756 tup = scope_find_youngest_outside (t, LEX_LEVEL (p));
14757 YOUNGEST_ENVIRON (TAX (p)) = LEVEL (&tup);
14758 /* Direct link into list iso "gather_scopes_for_youngest (SUB (p), s);" */
14759 if (t != NO_SCOPE) {
14760 SCOPE_T *u = t;
14761 while (NEXT (u) != NO_SCOPE) {
14762 FORWARD (u);
14763 }
14764 NEXT (u) = *s;
14765 (*s) = t;
14766 }
14767 } else if (is_one_of (p, IDENTIFIER, OPERATOR, STOP)) {
14768 if (TAX (p) != NO_TAG && TAG_LEX_LEVEL (TAX (p)) != PRIMAL_SCOPE) {
14769 scope_add (s, p, scope_make_tuple (TAG_LEX_LEVEL (TAX (p)), NOT_TRANSIENT));
14770 }
14771 } else if (IS (p, DECLARER)) {
14772 get_declarer_elements (p, s, A68_TRUE);
14773 } else {
14774 gather_scopes_for_youngest (SUB (p), s);
14775 }
14776 }
14777 }
14778
14779 /**
14780 @brief Get_youngest_environs.
14781 @param p Node in syntax tree.
14782 **/
14783
14784 static void
get_youngest_environs(NODE_T * p)14785 get_youngest_environs (NODE_T * p)
14786 {
14787 for (; p != NO_NODE; FORWARD (p)) {
14788 if (is_one_of (p, ROUTINE_TEXT, FORMAT_TEXT, STOP)) {
14789 SCOPE_T *s = NO_SCOPE;
14790 TUPLE_T tup;
14791 gather_scopes_for_youngest (SUB (p), &s);
14792 tup = scope_find_youngest_outside (s, LEX_LEVEL (p));
14793 YOUNGEST_ENVIRON (TAX (p)) = LEVEL (&tup);
14794 } else {
14795 get_youngest_environs (SUB (p));
14796 }
14797 }
14798 }
14799
14800 /**
14801 @brief Bind_scope_to_tag.
14802 @param p Node in syntax tree.
14803 **/
14804
14805 static void
bind_scope_to_tag(NODE_T * p)14806 bind_scope_to_tag (NODE_T * p)
14807 {
14808 for (; p != NO_NODE; FORWARD (p)) {
14809 if (IS (p, DEFINING_IDENTIFIER) && MOID (p) == MODE (FORMAT)) {
14810 if (IS (NEXT_NEXT (p), FORMAT_TEXT)) {
14811 SCOPE (TAX (p)) = YOUNGEST_ENVIRON (TAX (NEXT_NEXT (p)));
14812 SCOPE_ASSIGNED (TAX (p)) = A68_TRUE;
14813 }
14814 return;
14815 } else if (IS (p, DEFINING_IDENTIFIER)) {
14816 if (IS (NEXT_NEXT (p), ROUTINE_TEXT)) {
14817 SCOPE (TAX (p)) = YOUNGEST_ENVIRON (TAX (NEXT_NEXT (p)));
14818 SCOPE_ASSIGNED (TAX (p)) = A68_TRUE;
14819 }
14820 return;
14821 } else {
14822 bind_scope_to_tag (SUB (p));
14823 }
14824 }
14825 }
14826
14827 /**
14828 @brief Bind_scope_to_tags.
14829 @param p Node in syntax tree.
14830 **/
14831
14832 static void
bind_scope_to_tags(NODE_T * p)14833 bind_scope_to_tags (NODE_T * p)
14834 {
14835 for (; p != NO_NODE; FORWARD (p)) {
14836 if (is_one_of (p, PROCEDURE_DECLARATION, IDENTITY_DECLARATION, STOP)) {
14837 bind_scope_to_tag (SUB (p));
14838 } else {
14839 bind_scope_to_tags (SUB (p));
14840 }
14841 }
14842 }
14843
14844 /**
14845 @brief Scope_bounds.
14846 @param p Node in syntax tree.
14847 **/
14848
14849 static void
scope_bounds(NODE_T * p)14850 scope_bounds (NODE_T * p)
14851 {
14852 for (; p != NO_NODE; FORWARD (p)) {
14853 if (IS (p, UNIT)) {
14854 scope_statement (p, NO_VAR);
14855 } else {
14856 scope_bounds (SUB (p));
14857 }
14858 }
14859 }
14860
14861 /**
14862 @brief Scope_declarer.
14863 @param p Node in syntax tree.
14864 **/
14865
14866 static void
scope_declarer(NODE_T * p)14867 scope_declarer (NODE_T * p)
14868 {
14869 if (p != NO_NODE) {
14870 if (IS (p, BOUNDS)) {
14871 scope_bounds (SUB (p));
14872 } else if (IS (p, INDICANT)) {
14873 ;
14874 } else if (IS (p, REF_SYMBOL)) {
14875 scope_declarer (NEXT (p));
14876 } else if (is_one_of (p, PROC_SYMBOL, UNION_SYMBOL, STOP)) {
14877 ;
14878 } else {
14879 scope_declarer (SUB (p));
14880 scope_declarer (NEXT (p));
14881 }
14882 }
14883 }
14884
14885 /**
14886 @brief Scope_identity_declaration.
14887 @param p Node in syntax tree.
14888 **/
14889
14890 static void
scope_identity_declaration(NODE_T * p)14891 scope_identity_declaration (NODE_T * p)
14892 {
14893 for (; p != NO_NODE; FORWARD (p)) {
14894 scope_identity_declaration (SUB (p));
14895 if (IS (p, DEFINING_IDENTIFIER)) {
14896 NODE_T *unit = NEXT_NEXT (p);
14897 SCOPE_T *s = NO_SCOPE;
14898 TUPLE_T tup;
14899 int z = PRIMAL_SCOPE;
14900 if (ATTRIBUTE (MOID (TAX (p))) != PROC_SYMBOL) {
14901 check_identifier_usage (TAX (p), unit);
14902 }
14903 scope_statement (unit, &s);
14904 (void) scope_check (s, TRANSIENT, LEX_LEVEL (p));
14905 tup = scope_find_youngest (s);
14906 z = LEVEL (&tup);
14907 if (z < LEX_LEVEL (p)) {
14908 SCOPE (TAX (p)) = z;
14909 SCOPE_ASSIGNED (TAX (p)) = A68_TRUE;
14910 }
14911 STATUS_SET (unit, INTERRUPTIBLE_MASK);
14912 return;
14913 }
14914 }
14915 }
14916
14917 /**
14918 @brief Scope_variable_declaration.
14919 @param p Node in syntax tree.
14920 **/
14921
14922 static void
scope_variable_declaration(NODE_T * p)14923 scope_variable_declaration (NODE_T * p)
14924 {
14925 for (; p != NO_NODE; FORWARD (p)) {
14926 scope_variable_declaration (SUB (p));
14927 if (IS (p, DECLARER)) {
14928 scope_declarer (SUB (p));
14929 } else if (IS (p, DEFINING_IDENTIFIER)) {
14930 if (whether (p, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, UNIT, STOP)) {
14931 NODE_T *unit = NEXT_NEXT (p);
14932 SCOPE_T *s = NO_SCOPE;
14933 check_identifier_usage (TAX (p), unit);
14934 scope_statement (unit, &s);
14935 (void) scope_check (s, TRANSIENT, LEX_LEVEL (p));
14936 STATUS_SET (unit, INTERRUPTIBLE_MASK);
14937 return;
14938 }
14939 }
14940 }
14941 }
14942
14943 /**
14944 @brief Scope_procedure_declaration.
14945 @param p Node in syntax tree.
14946 **/
14947
14948 static void
scope_procedure_declaration(NODE_T * p)14949 scope_procedure_declaration (NODE_T * p)
14950 {
14951 for (; p != NO_NODE; FORWARD (p)) {
14952 scope_procedure_declaration (SUB (p));
14953 if (is_one_of (p, DEFINING_IDENTIFIER, DEFINING_OPERATOR, STOP)) {
14954 NODE_T *unit = NEXT_NEXT (p);
14955 SCOPE_T *s = NO_SCOPE;
14956 scope_statement (unit, &s);
14957 (void) scope_check (s, NOT_TRANSIENT, LEX_LEVEL (p));
14958 STATUS_SET (unit, INTERRUPTIBLE_MASK);
14959 return;
14960 }
14961 }
14962 }
14963
14964 /**
14965 @brief Scope_declaration_list.
14966 @param p Node in syntax tree.
14967 **/
14968
14969 static void
scope_declaration_list(NODE_T * p)14970 scope_declaration_list (NODE_T * p)
14971 {
14972 if (p != NO_NODE) {
14973 if (IS (p, IDENTITY_DECLARATION)) {
14974 scope_identity_declaration (SUB (p));
14975 } else if (IS (p, VARIABLE_DECLARATION)) {
14976 scope_variable_declaration (SUB (p));
14977 } else if (IS (p, MODE_DECLARATION)) {
14978 scope_declarer (SUB (p));
14979 } else if (IS (p, PRIORITY_DECLARATION)) {
14980 ;
14981 } else if (IS (p, PROCEDURE_DECLARATION)) {
14982 scope_procedure_declaration (SUB (p));
14983 } else if (IS (p, PROCEDURE_VARIABLE_DECLARATION)) {
14984 scope_procedure_declaration (SUB (p));
14985 } else if (is_one_of (p, BRIEF_OPERATOR_DECLARATION, OPERATOR_DECLARATION, STOP)) {
14986 scope_procedure_declaration (SUB (p));
14987 } else {
14988 scope_declaration_list (SUB (p));
14989 scope_declaration_list (NEXT (p));
14990 }
14991 }
14992 }
14993
14994 /**
14995 @brief Scope_arguments.
14996 @param p Node in syntax tree.
14997 **/
14998
14999 static void
scope_arguments(NODE_T * p)15000 scope_arguments (NODE_T * p)
15001 {
15002 for (; p != NO_NODE; FORWARD (p)) {
15003 if (IS (p, UNIT)) {
15004 SCOPE_T *s = NO_SCOPE;
15005 scope_statement (p, &s);
15006 (void) scope_check (s, TRANSIENT, LEX_LEVEL (p));
15007 } else {
15008 scope_arguments (SUB (p));
15009 }
15010 }
15011 }
15012
15013 /**
15014 @brief Is_coercion.
15015 @param p Node in syntax tree.
15016 **/
15017
15018 BOOL_T
is_coercion(NODE_T * p)15019 is_coercion (NODE_T * p)
15020 {
15021 if (p != NO_NODE) {
15022 switch (ATTRIBUTE (p)) {
15023 case DEPROCEDURING:
15024 case DEREFERENCING:
15025 case UNITING:
15026 case ROWING:
15027 case WIDENING:
15028 case VOIDING:
15029 case PROCEDURING:
15030 {
15031 return (A68_TRUE);
15032 }
15033 default:
15034 {
15035 return (A68_FALSE);
15036 }
15037 }
15038 } else {
15039 return (A68_FALSE);
15040 }
15041 }
15042
15043 /**
15044 @brief Scope_coercion.
15045 @param p Node in syntax tree.
15046 @param s Chain to link into.
15047 **/
15048
15049 static void
scope_coercion(NODE_T * p,SCOPE_T ** s)15050 scope_coercion (NODE_T * p, SCOPE_T ** s)
15051 {
15052 if (is_coercion (p)) {
15053 if (IS (p, VOIDING)) {
15054 scope_coercion (SUB (p), NO_VAR);
15055 } else if (IS (p, DEREFERENCING)) {
15056 /* Leave this to the dynamic scope checker */
15057 scope_coercion (SUB (p), NO_VAR);
15058 } else if (IS (p, DEPROCEDURING)) {
15059 scope_coercion (SUB (p), NO_VAR);
15060 } else if (IS (p, ROWING)) {
15061 SCOPE_T *z = NO_SCOPE;
15062 scope_coercion (SUB (p), &z);
15063 (void) scope_check (z, TRANSIENT, LEX_LEVEL (p));
15064 if (IS_REF_FLEX (MOID (SUB (p)))) {
15065 scope_add (s, p, scope_make_tuple (LEX_LEVEL (p), TRANSIENT));
15066 } else {
15067 scope_add (s, p, scope_make_tuple (LEX_LEVEL (p), NOT_TRANSIENT));
15068 }
15069 } else if (IS (p, PROCEDURING)) {
15070 /* Can only be a JUMP */
15071 NODE_T *q = SUB_SUB (p);
15072 if (IS (q, GOTO_SYMBOL)) {
15073 FORWARD (q);
15074 }
15075 scope_add (s, q, scope_make_tuple (TAG_LEX_LEVEL (TAX (q)), NOT_TRANSIENT));
15076 } else if (IS (p, UNITING)) {
15077 SCOPE_T *z = NO_SCOPE;
15078 scope_coercion (SUB (p), &z);
15079 (void) scope_check (z, TRANSIENT, LEX_LEVEL (p));
15080 scope_add (s, p, scope_make_tuple (LEX_LEVEL (p), NOT_TRANSIENT));
15081 } else {
15082 scope_coercion (SUB (p), s);
15083 }
15084 } else {
15085 scope_statement (p, s);
15086 }
15087 }
15088
15089 /**
15090 @brief Scope_format_text.
15091 @param p Node in syntax tree.
15092 @param s Chain to link into.
15093 **/
15094
15095 static void
scope_format_text(NODE_T * p,SCOPE_T ** s)15096 scope_format_text (NODE_T * p, SCOPE_T ** s)
15097 {
15098 for (; p != NO_NODE; FORWARD (p)) {
15099 if (IS (p, FORMAT_PATTERN)) {
15100 scope_enclosed_clause (SUB (NEXT_SUB (p)), s);
15101 } else if (IS (p, FORMAT_ITEM_G) && NEXT (p) != NO_NODE) {
15102 scope_enclosed_clause (SUB_NEXT (p), s);
15103 } else if (IS (p, DYNAMIC_REPLICATOR)) {
15104 scope_enclosed_clause (SUB (NEXT_SUB (p)), s);
15105 } else {
15106 scope_format_text (SUB (p), s);
15107 }
15108 }
15109 }
15110
15111 /**
15112 @brief Scope_operand.
15113 @param p Node in syntax tree.
15114 @param s Chain to link into.
15115 **/
15116
15117 static void
scope_operand(NODE_T * p,SCOPE_T ** s)15118 scope_operand (NODE_T * p, SCOPE_T ** s)
15119 {
15120 if (IS (p, MONADIC_FORMULA)) {
15121 scope_operand (NEXT_SUB (p), s);
15122 } else if (IS (p, FORMULA)) {
15123 scope_formula (p, s);
15124 } else if (IS (p, SECONDARY)) {
15125 scope_statement (SUB (p), s);
15126 }
15127 }
15128
15129 /**
15130 @brief Scope_formula.
15131 @param p Node in syntax tree.
15132 @param s Chain to link into.
15133 **/
15134
15135 static void
scope_formula(NODE_T * p,SCOPE_T ** s)15136 scope_formula (NODE_T * p, SCOPE_T ** s)
15137 {
15138 NODE_T *q = SUB (p);
15139 SCOPE_T *s2 = NO_SCOPE;
15140 scope_operand (q, &s2);
15141 (void) scope_check (s2, TRANSIENT, LEX_LEVEL (p));
15142 if (NEXT (q) != NO_NODE) {
15143 SCOPE_T *s3 = NO_SCOPE;
15144 scope_operand (NEXT_NEXT (q), &s3);
15145 (void) scope_check (s3, TRANSIENT, LEX_LEVEL (p));
15146 }
15147 (void) s;
15148 }
15149
15150 /**
15151 @brief Scope_routine_text.
15152 @param p Node in syntax tree.
15153 @param s Chain to link into.
15154 **/
15155
15156 static void
scope_routine_text(NODE_T * p,SCOPE_T ** s)15157 scope_routine_text (NODE_T * p, SCOPE_T ** s)
15158 {
15159 NODE_T *q = SUB (p), *routine = (IS (q, PARAMETER_PACK) ? NEXT (q) : q);
15160 SCOPE_T *x = NO_SCOPE;
15161 TUPLE_T routine_tuple;
15162 scope_statement (NEXT_NEXT (routine), &x);
15163 (void) scope_check (x, TRANSIENT, LEX_LEVEL (p));
15164 routine_tuple = scope_make_tuple (YOUNGEST_ENVIRON (TAX (p)), NOT_TRANSIENT);
15165 scope_add (s, p, routine_tuple);
15166 }
15167
15168 /**
15169 @brief Scope_statement.
15170 @param p Node in syntax tree.
15171 @param s Chain to link into.
15172 **/
15173
15174 static void
scope_statement(NODE_T * p,SCOPE_T ** s)15175 scope_statement (NODE_T * p, SCOPE_T ** s)
15176 {
15177 if (is_coercion (p)) {
15178 scope_coercion (p, s);
15179 } else if (is_one_of (p, PRIMARY, SECONDARY, TERTIARY, UNIT, STOP)) {
15180 scope_statement (SUB (p), s);
15181 } else if (is_one_of (p, DENOTATION, NIHIL, STOP)) {
15182 scope_add (s, p, scope_make_tuple (PRIMAL_SCOPE, NOT_TRANSIENT));
15183 } else if (IS (p, IDENTIFIER)) {
15184 if (IS (MOID (p), REF_SYMBOL)) {
15185 if (PRIO (TAX (p)) == PARAMETER_IDENTIFIER) {
15186 scope_add (s, p, scope_make_tuple (TAG_LEX_LEVEL (TAX (p)) - 1, NOT_TRANSIENT));
15187 } else {
15188 if (HEAP (TAX (p)) == HEAP_SYMBOL) {
15189 scope_add (s, p, scope_make_tuple (PRIMAL_SCOPE, NOT_TRANSIENT));
15190 } else if (SCOPE_ASSIGNED (TAX (p))) {
15191 scope_add (s, p, scope_make_tuple (SCOPE (TAX (p)), NOT_TRANSIENT));
15192 } else {
15193 scope_add (s, p, scope_make_tuple (TAG_LEX_LEVEL (TAX (p)), NOT_TRANSIENT));
15194 }
15195 }
15196 } else if (ATTRIBUTE (MOID (p)) == PROC_SYMBOL && SCOPE_ASSIGNED (TAX (p)) == A68_TRUE) {
15197 scope_add (s, p, scope_make_tuple (SCOPE (TAX (p)), NOT_TRANSIENT));
15198 } else if (MOID (p) == MODE (FORMAT) && SCOPE_ASSIGNED (TAX (p)) == A68_TRUE) {
15199 scope_add (s, p, scope_make_tuple (SCOPE (TAX (p)), NOT_TRANSIENT));
15200 }
15201 } else if (IS (p, ENCLOSED_CLAUSE)) {
15202 scope_enclosed_clause (SUB (p), s);
15203 } else if (IS (p, CALL)) {
15204 SCOPE_T *x = NO_SCOPE;
15205 scope_statement (SUB (p), &x);
15206 (void) scope_check (x, NOT_TRANSIENT, LEX_LEVEL (p));
15207 scope_arguments (NEXT_SUB (p));
15208 } else if (IS (p, SLICE)) {
15209 SCOPE_T *x = NO_SCOPE;
15210 MOID_T *m = MOID (SUB (p));
15211 if (IS (m, REF_SYMBOL)) {
15212 if (ATTRIBUTE (SUB (p)) == PRIMARY && ATTRIBUTE (SUB_SUB (p)) == SLICE) {
15213 scope_statement (SUB (p), s);
15214 } else {
15215 scope_statement (SUB (p), &x);
15216 (void) scope_check (x, NOT_TRANSIENT, LEX_LEVEL (p));
15217 }
15218 if (IS (SUB (m), FLEX_SYMBOL)) {
15219 scope_add (s, SUB (p), scope_make_tuple (LEX_LEVEL (p), TRANSIENT));
15220 }
15221 scope_bounds (SUB (NEXT_SUB (p)));
15222 }
15223 if (IS (MOID (p), REF_SYMBOL)) {
15224 scope_add (s, p, scope_find_youngest (x));
15225 }
15226 } else if (IS (p, FORMAT_TEXT)) {
15227 SCOPE_T *x = NO_SCOPE;
15228 scope_format_text (SUB (p), &x);
15229 scope_add (s, p, scope_find_youngest (x));
15230 } else if (IS (p, CAST)) {
15231 SCOPE_T *x = NO_SCOPE;
15232 scope_enclosed_clause (SUB (NEXT_SUB (p)), &x);
15233 (void) scope_check (x, NOT_TRANSIENT, LEX_LEVEL (p));
15234 scope_add (s, p, scope_find_youngest (x));
15235 } else if (IS (p, SELECTION)) {
15236 SCOPE_T *ns = NO_SCOPE;
15237 scope_statement (NEXT_SUB (p), &ns);
15238 (void) scope_check (ns, NOT_TRANSIENT, LEX_LEVEL (p));
15239 if (is_ref_refety_flex (MOID (NEXT_SUB (p)))) {
15240 scope_add (s, p, scope_make_tuple (LEX_LEVEL (p), TRANSIENT));
15241 }
15242 scope_add (s, p, scope_find_youngest (ns));
15243 } else if (IS (p, GENERATOR)) {
15244 if (IS (SUB (p), LOC_SYMBOL)) {
15245 if (NON_LOCAL (p) != NO_TABLE) {
15246 scope_add (s, p, scope_make_tuple (LEVEL (NON_LOCAL (p)), NOT_TRANSIENT));
15247 } else {
15248 scope_add (s, p, scope_make_tuple (LEX_LEVEL (p), NOT_TRANSIENT));
15249 }
15250 } else {
15251 scope_add (s, p, scope_make_tuple (PRIMAL_SCOPE, NOT_TRANSIENT));
15252 }
15253 scope_declarer (SUB (NEXT_SUB (p)));
15254 } else if (IS (p, DIAGONAL_FUNCTION)) {
15255 NODE_T *q = SUB (p);
15256 SCOPE_T *ns = NO_SCOPE;
15257 if (IS (q, TERTIARY)) {
15258 scope_statement (SUB (q), &ns);
15259 (void) scope_check (ns, NOT_TRANSIENT, LEX_LEVEL (q));
15260 ns = NO_SCOPE;
15261 FORWARD (q);
15262 }
15263 scope_statement (SUB_NEXT (q), &ns);
15264 (void) scope_check (ns, NOT_TRANSIENT, LEX_LEVEL (q));
15265 scope_add (s, p, scope_find_youngest (ns));
15266 } else if (IS (p, TRANSPOSE_FUNCTION)) {
15267 NODE_T *q = SUB (p);
15268 SCOPE_T *ns = NO_SCOPE;
15269 scope_statement (SUB_NEXT (q), &ns);
15270 (void) scope_check (ns, NOT_TRANSIENT, LEX_LEVEL (q));
15271 scope_add (s, p, scope_find_youngest (ns));
15272 } else if (IS (p, ROW_FUNCTION)) {
15273 NODE_T *q = SUB (p);
15274 SCOPE_T *ns = NO_SCOPE;
15275 if (IS (q, TERTIARY)) {
15276 scope_statement (SUB (q), &ns);
15277 (void) scope_check (ns, NOT_TRANSIENT, LEX_LEVEL (q));
15278 ns = NO_SCOPE;
15279 FORWARD (q);
15280 }
15281 scope_statement (SUB_NEXT (q), &ns);
15282 (void) scope_check (ns, NOT_TRANSIENT, LEX_LEVEL (q));
15283 scope_add (s, p, scope_find_youngest (ns));
15284 } else if (IS (p, COLUMN_FUNCTION)) {
15285 NODE_T *q = SUB (p);
15286 SCOPE_T *ns = NO_SCOPE;
15287 if (IS (q, TERTIARY)) {
15288 scope_statement (SUB (q), &ns);
15289 (void) scope_check (ns, NOT_TRANSIENT, LEX_LEVEL (q));
15290 ns = NO_SCOPE;
15291 FORWARD (q);
15292 }
15293 scope_statement (SUB_NEXT (q), &ns);
15294 (void) scope_check (ns, NOT_TRANSIENT, LEX_LEVEL (q));
15295 scope_add (s, p, scope_find_youngest (ns));
15296 } else if (IS (p, FORMULA)) {
15297 scope_formula (p, s);
15298 } else if (IS (p, ASSIGNATION)) {
15299 NODE_T *unit = NEXT (NEXT_SUB (p));
15300 SCOPE_T *ns = NO_SCOPE, *nd = NO_SCOPE;
15301 TUPLE_T tup;
15302 scope_statement (SUB_SUB (p), &nd);
15303 scope_statement (unit, &ns);
15304 (void) scope_check_multiple (ns, TRANSIENT, nd);
15305 tup = scope_find_youngest (nd);
15306 scope_add (s, p, scope_make_tuple (LEVEL (&tup), NOT_TRANSIENT));
15307 } else if (IS (p, ROUTINE_TEXT)) {
15308 scope_routine_text (p, s);
15309 } else if (is_one_of (p, IDENTITY_RELATION, AND_FUNCTION, OR_FUNCTION, STOP)) {
15310 SCOPE_T *n = NO_SCOPE;
15311 scope_statement (SUB (p), &n);
15312 scope_statement (NEXT (NEXT_SUB (p)), &n);
15313 (void) scope_check (n, NOT_TRANSIENT, LEX_LEVEL (p));
15314 } else if (IS (p, ASSERTION)) {
15315 SCOPE_T *n = NO_SCOPE;
15316 scope_enclosed_clause (SUB (NEXT_SUB (p)), &n);
15317 (void) scope_check (n, NOT_TRANSIENT, LEX_LEVEL (p));
15318 } else if (is_one_of (p, JUMP, SKIP, STOP)) {
15319 ;
15320 }
15321 }
15322
15323 /**
15324 @brief Scope_statement_list.
15325 @param p Node in syntax tree.
15326 @param s Chain to link into.
15327 **/
15328
15329 static void
scope_statement_list(NODE_T * p,SCOPE_T ** s)15330 scope_statement_list (NODE_T * p, SCOPE_T ** s)
15331 {
15332 for (; p != NO_NODE; FORWARD (p)) {
15333 if (IS (p, UNIT)) {
15334 STATUS_SET (p, INTERRUPTIBLE_MASK);
15335 scope_statement (p, s);
15336 } else {
15337 scope_statement_list (SUB (p), s);
15338 }
15339 }
15340 }
15341
15342 /**
15343 @brief Scope_serial_clause.
15344 @param p Node in syntax tree.
15345 @param s Chain to link into.
15346 @param terminator Whether unit terminates clause.
15347 **/
15348
15349 static void
scope_serial_clause(NODE_T * p,SCOPE_T ** s,BOOL_T terminator)15350 scope_serial_clause (NODE_T * p, SCOPE_T ** s, BOOL_T terminator)
15351 {
15352 if (p != NO_NODE) {
15353 if (IS (p, INITIALISER_SERIES)) {
15354 scope_serial_clause (SUB (p), s, A68_FALSE);
15355 scope_serial_clause (NEXT (p), s, terminator);
15356 } else if (IS (p, DECLARATION_LIST)) {
15357 scope_declaration_list (SUB (p));
15358 } else if (is_one_of (p, LABEL, SEMI_SYMBOL, EXIT_SYMBOL, STOP)) {
15359 scope_serial_clause (NEXT (p), s, terminator);
15360 } else if (is_one_of (p, SERIAL_CLAUSE, ENQUIRY_CLAUSE, STOP)) {
15361 if (NEXT (p) != NO_NODE) {
15362 int j = ATTRIBUTE (NEXT (p));
15363 if (j == EXIT_SYMBOL || j == END_SYMBOL || j == CLOSE_SYMBOL) {
15364 scope_serial_clause (SUB (p), s, A68_TRUE);
15365 } else {
15366 scope_serial_clause (SUB (p), s, A68_FALSE);
15367 }
15368 } else {
15369 scope_serial_clause (SUB (p), s, A68_TRUE);
15370 }
15371 scope_serial_clause (NEXT (p), s, terminator);
15372 } else if (IS (p, LABELED_UNIT)) {
15373 scope_serial_clause (SUB (p), s, terminator);
15374 } else if (IS (p, UNIT)) {
15375 STATUS_SET (p, INTERRUPTIBLE_MASK);
15376 if (terminator) {
15377 scope_statement (p, s);
15378 } else {
15379 scope_statement (p, NO_VAR);
15380 }
15381 }
15382 }
15383 }
15384
15385 /**
15386 @brief Scope_closed_clause.
15387 @param p Node in syntax tree.
15388 @param s Chain to link into.
15389 **/
15390
15391 static void
scope_closed_clause(NODE_T * p,SCOPE_T ** s)15392 scope_closed_clause (NODE_T * p, SCOPE_T ** s)
15393 {
15394 if (p != NO_NODE) {
15395 if (IS (p, SERIAL_CLAUSE)) {
15396 scope_serial_clause (p, s, A68_TRUE);
15397 } else if (is_one_of (p, OPEN_SYMBOL, BEGIN_SYMBOL, STOP)) {
15398 scope_closed_clause (NEXT (p), s);
15399 }
15400 }
15401 }
15402
15403 /**
15404 @brief Scope_collateral_clause.
15405 @param p Node in syntax tree.
15406 @param s Chain to link into.
15407 **/
15408
15409 static void
scope_collateral_clause(NODE_T * p,SCOPE_T ** s)15410 scope_collateral_clause (NODE_T * p, SCOPE_T ** s)
15411 {
15412 if (p != NO_NODE) {
15413 if (!(whether (p, BEGIN_SYMBOL, END_SYMBOL, STOP) || whether (p, OPEN_SYMBOL, CLOSE_SYMBOL, STOP))) {
15414 scope_statement_list (p, s);
15415 }
15416 }
15417 }
15418
15419 /**
15420 @brief Scope_conditional_clause.
15421 @param p Node in syntax tree.
15422 @param s Chain to link into.
15423 **/
15424
15425 static void
scope_conditional_clause(NODE_T * p,SCOPE_T ** s)15426 scope_conditional_clause (NODE_T * p, SCOPE_T ** s)
15427 {
15428 scope_serial_clause (NEXT_SUB (p), NO_VAR, A68_TRUE);
15429 FORWARD (p);
15430 scope_serial_clause (NEXT_SUB (p), s, A68_TRUE);
15431 if ((FORWARD (p)) != NO_NODE) {
15432 if (is_one_of (p, ELSE_PART, CHOICE, STOP)) {
15433 scope_serial_clause (NEXT_SUB (p), s, A68_TRUE);
15434 } else if (is_one_of (p, ELIF_PART, BRIEF_ELIF_PART, STOP)) {
15435 scope_conditional_clause (SUB (p), s);
15436 }
15437 }
15438 }
15439
15440 /**
15441 @brief Scope_case_clause.
15442 @param p Node in syntax tree.
15443 @param s Chain to link into.
15444 **/
15445
15446 static void
scope_case_clause(NODE_T * p,SCOPE_T ** s)15447 scope_case_clause (NODE_T * p, SCOPE_T ** s)
15448 {
15449 SCOPE_T *n = NO_SCOPE;
15450 scope_serial_clause (NEXT_SUB (p), &n, A68_TRUE);
15451 (void) scope_check (n, NOT_TRANSIENT, LEX_LEVEL (p));
15452 FORWARD (p);
15453 scope_statement_list (NEXT_SUB (p), s);
15454 if ((FORWARD (p)) != NO_NODE) {
15455 if (is_one_of (p, OUT_PART, CHOICE, STOP)) {
15456 scope_serial_clause (NEXT_SUB (p), s, A68_TRUE);
15457 } else if (is_one_of (p, CASE_OUSE_PART, BRIEF_OUSE_PART, STOP)) {
15458 scope_case_clause (SUB (p), s);
15459 } else if (is_one_of (p, CONFORMITY_OUSE_PART, BRIEF_CONFORMITY_OUSE_PART, STOP)) {
15460 scope_case_clause (SUB (p), s);
15461 }
15462 }
15463 }
15464
15465 /**
15466 @brief Scope_loop_clause.
15467 @param p Node in syntax tree.
15468 **/
15469
15470 static void
scope_loop_clause(NODE_T * p)15471 scope_loop_clause (NODE_T * p)
15472 {
15473 if (p != NO_NODE) {
15474 if (IS (p, FOR_PART)) {
15475 scope_loop_clause (NEXT (p));
15476 } else if (is_one_of (p, FROM_PART, BY_PART, TO_PART, STOP)) {
15477 scope_statement (NEXT_SUB (p), NO_VAR);
15478 scope_loop_clause (NEXT (p));
15479 } else if (IS (p, WHILE_PART)) {
15480 scope_serial_clause (NEXT_SUB (p), NO_VAR, A68_TRUE);
15481 scope_loop_clause (NEXT (p));
15482 } else if (is_one_of (p, DO_PART, ALT_DO_PART, STOP)) {
15483 NODE_T *do_p = NEXT_SUB (p), *un_p;
15484 if (IS (do_p, SERIAL_CLAUSE)) {
15485 scope_serial_clause (do_p, NO_VAR, A68_TRUE);
15486 un_p = NEXT (do_p);
15487 } else {
15488 un_p = do_p;
15489 }
15490 if (un_p != NO_NODE && IS (un_p, UNTIL_PART)) {
15491 scope_serial_clause (NEXT_SUB (un_p), NO_VAR, A68_TRUE);
15492 }
15493 }
15494 }
15495 }
15496
15497 /**
15498 @brief Scope_enclosed_clause.
15499 @param p Node in syntax tree.
15500 @param s Chain to link into.
15501 **/
15502
15503 static void
scope_enclosed_clause(NODE_T * p,SCOPE_T ** s)15504 scope_enclosed_clause (NODE_T * p, SCOPE_T ** s)
15505 {
15506 if (IS (p, ENCLOSED_CLAUSE)) {
15507 scope_enclosed_clause (SUB (p), s);
15508 } else if (IS (p, CLOSED_CLAUSE)) {
15509 scope_closed_clause (SUB (p), s);
15510 } else if (is_one_of (p, COLLATERAL_CLAUSE, PARALLEL_CLAUSE, STOP)) {
15511 scope_collateral_clause (SUB (p), s);
15512 } else if (IS (p, CONDITIONAL_CLAUSE)) {
15513 scope_conditional_clause (SUB (p), s);
15514 } else if (is_one_of (p, CASE_CLAUSE, CONFORMITY_CLAUSE, STOP)) {
15515 scope_case_clause (SUB (p), s);
15516 } else if (IS (p, LOOP_CLAUSE)) {
15517 scope_loop_clause (SUB (p));
15518 }
15519 }
15520
15521 /**
15522 @brief Whether a symbol table contains no (anonymous) definition.
15523 @param t Symbol table.
15524 \return TRUE or FALSE
15525 **/
15526
15527 static BOOL_T
empty_table(TABLE_T * t)15528 empty_table (TABLE_T * t)
15529 {
15530 if (IDENTIFIERS (t) == NO_TAG) {
15531 return ((BOOL_T) (OPERATORS (t) == NO_TAG && INDICANTS (t) == NO_TAG));
15532 } else if (PRIO (IDENTIFIERS (t)) == LOOP_IDENTIFIER && NEXT (IDENTIFIERS (t)) == NO_TAG) {
15533 return ((BOOL_T) (OPERATORS (t) == NO_TAG && INDICANTS (t) == NO_TAG));
15534 } else if (PRIO (IDENTIFIERS (t)) == SPECIFIER_IDENTIFIER && NEXT (IDENTIFIERS (t)) == NO_TAG) {
15535 return ((BOOL_T) (OPERATORS (t) == NO_TAG && INDICANTS (t) == NO_TAG));
15536 } else {
15537 return (A68_FALSE);
15538 }
15539 }
15540
15541 /**
15542 @brief Indicate non-local environs.
15543 @param p Node in syntax tree.
15544 @param max Lex level threshold.
15545 **/
15546
15547 static void
get_non_local_environs(NODE_T * p,int max)15548 get_non_local_environs (NODE_T * p, int max)
15549 {
15550 for (; p != NO_NODE; FORWARD (p)) {
15551 if (IS (p, ROUTINE_TEXT)) {
15552 get_non_local_environs (SUB (p), LEX_LEVEL (SUB (p)));
15553 } else if (IS (p, FORMAT_TEXT)) {
15554 get_non_local_environs (SUB (p), LEX_LEVEL (SUB (p)));
15555 } else {
15556 get_non_local_environs (SUB (p), max);
15557 NON_LOCAL (p) = NO_TABLE;
15558 if (TABLE (p) != NO_TABLE) {
15559 TABLE_T *q = TABLE (p);
15560 while (q != NO_TABLE && empty_table (q)
15561 && PREVIOUS (q) != NO_TABLE && LEVEL (PREVIOUS (q)) >= max) {
15562 NON_LOCAL (p) = PREVIOUS (q);
15563 q = PREVIOUS (q);
15564 }
15565 }
15566 }
15567 }
15568 }
15569
15570 /**
15571 @brief Scope_checker.
15572 @param p Node in syntax tree.
15573 **/
15574
15575 void
scope_checker(NODE_T * p)15576 scope_checker (NODE_T * p)
15577 {
15578 /* Establish scopes of routine texts and format texts */
15579 get_youngest_environs (p);
15580 /* Find non-local environs */
15581 get_non_local_environs (p, PRIMAL_SCOPE);
15582 /* PROC and FORMAT identities can now be assigned a scope */
15583 bind_scope_to_tags (p);
15584 /* Now check evertyhing else */
15585 scope_enclosed_clause (SUB (p), NO_VAR);
15586 }
15587
15588 /* syntax.c*/
15589