parser-extract.c
1 //! @file parser-extract.c
2 //! @author J. Marcel van der Veer
3
4 //! @section Copyright
5 //!
6 //! This file is part of Algol68G - an Algol 68 compiler-interpreter.
7 //! Copyright 2001-2025 J. Marcel van der Veer [algol68g@xs4all.nl].
8
9 //! @section License
10 //!
11 //! This program is free software; you can redistribute it and/or modify it
12 //! under the terms of the GNU General Public License as published by the
13 //! Free Software Foundation; either version 3 of the License, or
14 //! (at your option) any later version.
15 //!
16 //! This program is distributed in the hope that it will be useful, but
17 //! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 //! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 //! more details. You should have received a copy of the GNU General Public
20 //! License along with this program. If not, see [http://www.gnu.org/licenses/].
21
22 //! @section Synopsis
23 //!
24 //! Extract tags from phrases.
25
26 #include "a68g.h"
27 #include "a68g-parser.h"
28
29 // This is part of the bottom-up parser.
30 // Here is a set of routines that gather definitions from phrases.
31 //
32 // This way we can apply tags before defining them, but more importantly,
33 // with this information the Algol 68 two level Van Wijngaarden grammar
34 // reduces to LALR.
35 //
36 // These routines do not look very elegant as they have to scan through all
37 // kind of symbols to find a pattern that they recognise.
38
39 //! @brief Insert alt equals symbol.
40
41 void insert_alt_equals (NODE_T * p)
42 {
43 NODE_T *q = new_node ();
44 *q = *p;
45 INFO (q) = new_node_info ();
46 *INFO (q) = *INFO (p);
47 GINFO (q) = new_genie_info ();
48 *GINFO (q) = *GINFO (p);
49 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
50 NSYMBOL (q) = TEXT (add_token (&A68G (top_token), "="));
51 NEXT (p) = q;
52 PREVIOUS (q) = p;
53 if (NEXT (q) != NO_NODE) {
54 PREVIOUS (NEXT (q)) = q;
55 }
56 }
57
58 //! @brief Detect redefined keyword.
59
60 void detect_redefined_keyword (NODE_T * p, int construct)
61 {
62 if (p != NO_NODE && whether (p, KEYWORD, EQUALS_SYMBOL, STOP)) {
63 diagnostic (A68G_SYNTAX_ERROR, p, ERROR_REDEFINED_KEYWORD, NSYMBOL (p), construct);
64 }
65 }
66
67 //! @brief Skip anything until a comma, semicolon or EXIT is found.
68
69 NODE_T *skip_unit (NODE_T * p)
70 {
71 for (; p != NO_NODE; FORWARD (p)) {
72 if (IS (p, COMMA_SYMBOL)) {
73 return p;
74 } else if (IS (p, SEMI_SYMBOL)) {
75 return p;
76 } else if (IS (p, EXIT_SYMBOL)) {
77 return p;
78 }
79 }
80 return NO_NODE;
81 }
82
83 //! @brief Attribute of entry in symbol table.
84
85 int find_tag_definition (TABLE_T * table, char *name)
86 {
87 if (table != NO_TABLE) {
88 int ret = 0;
89 BOOL_T found = A68G_FALSE;
90 for (TAG_T *s = INDICANTS (table); s != NO_TAG && !found; FORWARD (s)) {
91 if (NSYMBOL (NODE (s)) == name) {
92 ret += INDICANT;
93 found = A68G_TRUE;
94 }
95 }
96 found = A68G_FALSE;
97 for (TAG_T *s = OPERATORS (table); s != NO_TAG && !found; FORWARD (s)) {
98 if (NSYMBOL (NODE (s)) == name) {
99 ret += OPERATOR;
100 found = A68G_TRUE;
101 }
102 }
103 if (ret == 0) {
104 return find_tag_definition (PREVIOUS (table), name);
105 } else {
106 return ret;
107 }
108 } else {
109 return 0;
110 }
111 }
112
113 //! @brief Fill in whether bold tag is operator or indicant.
114
115 void elaborate_bold_tags (NODE_T * p)
116 {
117 for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
118 if (IS (q, BOLD_TAG)) {
119 switch (find_tag_definition (TABLE (q), NSYMBOL (q))) {
120 case 0: {
121 diagnostic (A68G_SYNTAX_ERROR, q, ERROR_UNDECLARED_TAG);
122 break;
123 }
124 case INDICANT: {
125 ATTRIBUTE (q) = INDICANT;
126 break;
127 }
128 case OPERATOR: {
129 ATTRIBUTE (q) = OPERATOR;
130 break;
131 }
132 }
133 }
134 }
135 }
136
137 //! @brief Skip declarer, or argument pack and declarer.
138
139 NODE_T *skip_pack_declarer (NODE_T * p)
140 {
141 // Skip () REF [] REF FLEX [] [] ...
142 while (p != NO_NODE && (is_one_of (p, SUB_SYMBOL, OPEN_SYMBOL, REF_SYMBOL, FLEX_SYMBOL, SHORT_SYMBOL, LONG_SYMBOL, STOP))) {
143 FORWARD (p);
144 }
145 // Skip STRUCT (), UNION () or PROC [()].
146 if (p != NO_NODE && (is_one_of (p, STRUCT_SYMBOL, UNION_SYMBOL, STOP))) {
147 return NEXT (p);
148 } else if (p != NO_NODE && IS (p, PROC_SYMBOL)) {
149 return skip_pack_declarer (NEXT (p));
150 } else {
151 return p;
152 }
153 }
154
155 //! @brief Search MODE A = .., B = .. and store indicants.
156
157 void extract_indicants (NODE_T * p)
158 {
159 NODE_T *q = p;
160 while (q != NO_NODE) {
161 if (IS (q, MODE_SYMBOL)) {
162 BOOL_T siga = A68G_TRUE;
163 do {
164 FORWARD (q);
165 detect_redefined_keyword (q, MODE_DECLARATION);
166 if (whether (q, BOLD_TAG, EQUALS_SYMBOL, STOP)) {
167 // Store in the symbol table, but also in the moid list.
168 // Position of definition (q) connects to this lexical level!
169 ASSERT (add_tag (TABLE (p), INDICANT, q, NO_MOID, STOP) != NO_TAG);
170 ASSERT (add_mode (&TOP_MOID (&A68G_JOB), INDICANT, 0, q, NO_MOID, NO_PACK) != NO_MOID);
171 ATTRIBUTE (q) = DEFINING_INDICANT;
172 FORWARD (q);
173 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
174 q = skip_pack_declarer (NEXT (q));
175 FORWARD (q);
176 } else {
177 siga = A68G_FALSE;
178 }
179 } while (siga && q != NO_NODE && IS (q, COMMA_SYMBOL));
180 } else {
181 FORWARD (q);
182 }
183 }
184 }
185
186 #define GET_PRIORITY(q, k)\
187 errno=0;\
188 (k) = atoi (NSYMBOL (q));\
189 if (errno != 0) {\
190 diagnostic (A68G_SYNTAX_ERROR, (q), ERROR_INVALID_PRIORITY);\
191 (k) = MAX_PRIORITY;\
192 } else if ((k) < 1 || (k) > MAX_PRIORITY) {\
193 diagnostic (A68G_SYNTAX_ERROR, (q), ERROR_INVALID_PRIORITY);\
194 (k) = MAX_PRIORITY;\
195 }
196
197 //! @brief Search PRIO X = .., Y = .. and store priorities.
198
199 void extract_priorities (NODE_T * p)
200 {
201 NODE_T *q = p;
202 while (q != NO_NODE) {
203 if (IS (q, PRIO_SYMBOL)) {
204 BOOL_T siga = A68G_TRUE;
205 do {
206 FORWARD (q);
207 detect_redefined_keyword (q, PRIORITY_DECLARATION);
208 // An operator tag like ++ or && gives strange errors so we catch it here.
209 if (whether (q, OPERATOR, OPERATOR, STOP)) {
210 NODE_T *y = q;
211 diagnostic (A68G_SYNTAX_ERROR, q, ERROR_INVALID_OPERATOR_TAG);
212 ATTRIBUTE (q) = DEFINING_OPERATOR;
213 // Remove one superfluous operator, and hope it was only one. .
214 NEXT (q) = NEXT_NEXT (q);
215 PREVIOUS (NEXT (q)) = q;
216 FORWARD (q);
217 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
218 FORWARD (q);
219 int k;
220 GET_PRIORITY (q, k);
221 ATTRIBUTE (q) = PRIORITY;
222 ASSERT (add_tag (TABLE (p), PRIO_SYMBOL, y, NO_MOID, k) != NO_TAG);
223 FORWARD (q);
224 } else if (whether (q, OPERATOR, EQUALS_SYMBOL, INT_DENOTATION, STOP) || whether (q, EQUALS_SYMBOL, EQUALS_SYMBOL, INT_DENOTATION, STOP)) {
225 NODE_T *y = q;
226 ATTRIBUTE (q) = DEFINING_OPERATOR;
227 FORWARD (q);
228 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
229 FORWARD (q);
230 int k;
231 GET_PRIORITY (q, k);
232 ATTRIBUTE (q) = PRIORITY;
233 ASSERT (add_tag (TABLE (p), PRIO_SYMBOL, y, NO_MOID, k) != NO_TAG);
234 FORWARD (q);
235 } else if (whether (q, BOLD_TAG, IDENTIFIER, STOP)) {
236 siga = A68G_FALSE;
237 } else if (whether (q, BOLD_TAG, EQUALS_SYMBOL, INT_DENOTATION, STOP)) {
238 NODE_T *y = q;
239 ATTRIBUTE (q) = DEFINING_OPERATOR;
240 FORWARD (q);
241 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
242 FORWARD (q);
243 int k;
244 GET_PRIORITY (q, k);
245 ATTRIBUTE (q) = PRIORITY;
246 ASSERT (add_tag (TABLE (p), PRIO_SYMBOL, y, NO_MOID, k) != NO_TAG);
247 FORWARD (q);
248 } else if (whether (q, BOLD_TAG, INT_DENOTATION, STOP) || whether (q, OPERATOR, INT_DENOTATION, STOP) || whether (q, EQUALS_SYMBOL, INT_DENOTATION, STOP)) {
249 // The scanner cannot separate operator and "=" sign so we do this here.
250 size_t len = strlen (NSYMBOL (q));
251 if (len > 1 && NSYMBOL (q)[len - 1] == '=') {
252 NODE_T *y = q;
253 char *sym = (char *) get_temp_heap_space ((size_t) (len + 1));
254 a68g_bufcpy (sym, NSYMBOL (q), len + 1);
255 sym[len - 1] = NULL_CHAR;
256 NSYMBOL (q) = TEXT (add_token (&A68G (top_token), sym));
257 if (len > 2 && NSYMBOL (q)[len - 2] == ':' && NSYMBOL (q)[len - 3] != '=') {
258 diagnostic (A68G_SYNTAX_ERROR, q, ERROR_OPERATOR_INVALID_END);
259 }
260 ATTRIBUTE (q) = DEFINING_OPERATOR;
261 insert_alt_equals (q);
262 q = NEXT_NEXT (q);
263 int k;
264 GET_PRIORITY (q, k);
265 ATTRIBUTE (q) = PRIORITY;
266 ASSERT (add_tag (TABLE (p), PRIO_SYMBOL, y, NO_MOID, k) != NO_TAG);
267 FORWARD (q);
268 } else {
269 siga = A68G_FALSE;
270 }
271 } else {
272 siga = A68G_FALSE;
273 }
274 } while (siga && q != NO_NODE && IS (q, COMMA_SYMBOL));
275 } else {
276 FORWARD (q);
277 }
278 }
279 }
280
281 //! @brief Search OP [( .. ) ..] X = .., Y = .. and store operators.
282
283 void extract_operators (NODE_T * p)
284 {
285 NODE_T *q = p;
286 while (q != NO_NODE) {
287 if (!IS (q, OP_SYMBOL)) {
288 FORWARD (q);
289 } else {
290 BOOL_T siga = A68G_TRUE;
291 // Skip operator plan.
292 if (NEXT (q) != NO_NODE && IS (NEXT (q), OPEN_SYMBOL)) {
293 q = skip_pack_declarer (NEXT (q));
294 }
295 // Sample operators.
296 if (q != NO_NODE) {
297 do {
298 FORWARD (q);
299 detect_redefined_keyword (q, OPERATOR_DECLARATION);
300 // Unacceptable operator tags like ++ or && could give strange errors.
301 if (whether (q, OPERATOR, OPERATOR, STOP)) {
302 diagnostic (A68G_SYNTAX_ERROR, q, ERROR_INVALID_OPERATOR_TAG);
303 ATTRIBUTE (q) = DEFINING_OPERATOR;
304 ASSERT (add_tag (TABLE (p), OP_SYMBOL, q, NO_MOID, STOP) != NO_TAG);
305 NEXT (q) = NEXT_NEXT (q); // Remove one superfluous operator, and hope it was only one
306 PREVIOUS (NEXT (q)) = q;
307 FORWARD (q);
308 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
309 q = skip_unit (q);
310 } else if (whether (q, OPERATOR, EQUALS_SYMBOL, STOP) || whether (q, EQUALS_SYMBOL, EQUALS_SYMBOL, STOP)) {
311 ATTRIBUTE (q) = DEFINING_OPERATOR;
312 ASSERT (add_tag (TABLE (p), OP_SYMBOL, q, NO_MOID, STOP) != NO_TAG);
313 FORWARD (q);
314 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
315 q = skip_unit (q);
316 } else if (whether (q, BOLD_TAG, IDENTIFIER, STOP)) {
317 siga = A68G_FALSE;
318 } else if (whether (q, BOLD_TAG, EQUALS_SYMBOL, STOP)) {
319 ATTRIBUTE (q) = DEFINING_OPERATOR;
320 ASSERT (add_tag (TABLE (p), OP_SYMBOL, q, NO_MOID, STOP) != NO_TAG);
321 FORWARD (q);
322 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
323 q = skip_unit (q);
324 } else if (q != NO_NODE && (is_one_of (q, OPERATOR, BOLD_TAG, EQUALS_SYMBOL, STOP))) {
325 // The scanner cannot separate operator and "=" sign so we do this here.
326 size_t len = strlen (NSYMBOL (q));
327 if (len > 1 && NSYMBOL (q)[len - 1] == '=') {
328 char *sym = (char *) get_temp_heap_space ((size_t) (len + 1));
329 a68g_bufcpy (sym, NSYMBOL (q), len + 1);
330 sym[len - 1] = NULL_CHAR;
331 NSYMBOL (q) = TEXT (add_token (&A68G (top_token), sym));
332 if (len > 2 && NSYMBOL (q)[len - 2] == ':' && NSYMBOL (q)[len - 3] != '=') {
333 diagnostic (A68G_SYNTAX_ERROR, q, ERROR_OPERATOR_INVALID_END);
334 }
335 ATTRIBUTE (q) = DEFINING_OPERATOR;
336 insert_alt_equals (q);
337 ASSERT (add_tag (TABLE (p), OP_SYMBOL, q, NO_MOID, STOP) != NO_TAG);
338 FORWARD (q);
339 q = skip_unit (q);
340 } else {
341 siga = A68G_FALSE;
342 }
343 } else {
344 siga = A68G_FALSE;
345 }
346 } while (siga && q != NO_NODE && IS (q, COMMA_SYMBOL));
347 }
348 }
349 }
350 }
351
352 //! @brief Search and store labels.
353
354 void extract_labels (NODE_T * p, int expect)
355 {
356 // Only handle candidate phrases as not to search indexers!.
357 if (expect == SERIAL_CLAUSE || expect == ENQUIRY_CLAUSE || expect == SOME_CLAUSE) {
358 for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
359 if (whether (q, IDENTIFIER, COLON_SYMBOL, STOP)) {
360 TAG_T *z = add_tag (TABLE (p), LABEL, q, NO_MOID, LOCAL_LABEL);
361 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
362 UNIT (z) = NO_NODE;
363 }
364 }
365 }
366 }
367
368 //! @brief Search MOID x = .., y = .. and store identifiers.
369
370 void extract_identities (NODE_T * p)
371 {
372 NODE_T *q = p;
373 while (q != NO_NODE) {
374 if (whether (q, DECLARER, IDENTIFIER, EQUALS_SYMBOL, STOP)) {
375 BOOL_T siga = A68G_TRUE;
376 do {
377 if (whether ((FORWARD (q)), IDENTIFIER, EQUALS_SYMBOL, STOP)) {
378 ASSERT (add_tag (TABLE (p), IDENTIFIER, q, NO_MOID, NORMAL_IDENTIFIER) != NO_TAG);
379 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
380 FORWARD (q);
381 ATTRIBUTE (q) = ALT_EQUALS_SYMBOL;
382 q = skip_unit (q);
383 } else if (whether (q, IDENTIFIER, ASSIGN_SYMBOL, STOP)) {
384 // Handle common error in ALGOL 68 programs.
385 diagnostic (A68G_SYNTAX_ERROR, q, ERROR_SYNTAX_MIXED_DECLARATION);
386 ASSERT (add_tag (TABLE (p), IDENTIFIER, q, NO_MOID, NORMAL_IDENTIFIER) != NO_TAG);
387 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
388 ATTRIBUTE (FORWARD (q)) = ALT_EQUALS_SYMBOL;
389 q = skip_unit (q);
390 } else {
391 siga = A68G_FALSE;
392 }
393 } while (siga && q != NO_NODE && IS (q, COMMA_SYMBOL));
394 } else {
395 FORWARD (q);
396 }
397 }
398 }
399
400 //! @brief Search MOID x [:= ..], y [:= ..] and store identifiers.
401
402 void extract_variables (NODE_T * p)
403 {
404 NODE_T *q = p;
405 while (q != NO_NODE) {
406 if (whether (q, DECLARER, IDENTIFIER, STOP)) {
407 BOOL_T siga = A68G_TRUE;
408 do {
409 FORWARD (q);
410 if (whether (q, IDENTIFIER, STOP)) {
411 if (whether (q, IDENTIFIER, EQUALS_SYMBOL, STOP)) {
412 // Handle common error in ALGOL 68 programs.
413 diagnostic (A68G_SYNTAX_ERROR, q, ERROR_SYNTAX_MIXED_DECLARATION);
414 ATTRIBUTE (NEXT (q)) = ASSIGN_SYMBOL;
415 }
416 ASSERT (add_tag (TABLE (p), IDENTIFIER, q, NO_MOID, NORMAL_IDENTIFIER) != NO_TAG);
417 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
418 q = skip_unit (q);
419 } else {
420 siga = A68G_FALSE;
421 }
422 } while (siga && q != NO_NODE && IS (q, COMMA_SYMBOL));
423 } else {
424 FORWARD (q);
425 }
426 }
427 }
428
429 //! @brief Search PROC x = .., y = .. and stores identifiers.
430
431 void extract_proc_identities (NODE_T * p)
432 {
433 NODE_T *q = p;
434 while (q != NO_NODE) {
435 if (whether (q, PROC_SYMBOL, IDENTIFIER, EQUALS_SYMBOL, STOP)) {
436 BOOL_T siga = A68G_TRUE;
437 do {
438 FORWARD (q);
439 if (whether (q, IDENTIFIER, EQUALS_SYMBOL, STOP)) {
440 TAG_T *t = add_tag (TABLE (p), IDENTIFIER, q, NO_MOID, NORMAL_IDENTIFIER);
441 IN_PROC (t) = A68G_TRUE;
442 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
443 ATTRIBUTE (FORWARD (q)) = ALT_EQUALS_SYMBOL;
444 q = skip_unit (q);
445 } else if (whether (q, IDENTIFIER, ASSIGN_SYMBOL, STOP)) {
446 // Handle common error in ALGOL 68 programs.
447 diagnostic (A68G_SYNTAX_ERROR, q, ERROR_SYNTAX_MIXED_DECLARATION);
448 ASSERT (add_tag (TABLE (p), IDENTIFIER, q, NO_MOID, NORMAL_IDENTIFIER) != NO_TAG);
449 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
450 ATTRIBUTE (FORWARD (q)) = ALT_EQUALS_SYMBOL;
451 q = skip_unit (q);
452 } else {
453 siga = A68G_FALSE;
454 }
455 } while (siga && q != NO_NODE && IS (q, COMMA_SYMBOL));
456 } else {
457 FORWARD (q);
458 }
459 }
460 }
461
462 //! @brief Search PROC x [:= ..], y [:= ..]; store identifiers.
463
464 void extract_proc_variables (NODE_T * p)
465 {
466 NODE_T *q = p;
467 while (q != NO_NODE) {
468 if (whether (q, PROC_SYMBOL, IDENTIFIER, STOP)) {
469 BOOL_T siga = A68G_TRUE;
470 do {
471 FORWARD (q);
472 if (whether (q, IDENTIFIER, ASSIGN_SYMBOL, STOP)) {
473 ASSERT (add_tag (TABLE (p), IDENTIFIER, q, NO_MOID, NORMAL_IDENTIFIER) != NO_TAG);
474 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
475 q = skip_unit (FORWARD (q));
476 } else if (whether (q, IDENTIFIER, EQUALS_SYMBOL, STOP)) {
477 // Handle common error in ALGOL 68 programs.
478 diagnostic (A68G_SYNTAX_ERROR, q, ERROR_SYNTAX_MIXED_DECLARATION);
479 ASSERT (add_tag (TABLE (p), IDENTIFIER, q, NO_MOID, NORMAL_IDENTIFIER) != NO_TAG);
480 ATTRIBUTE (q) = DEFINING_IDENTIFIER;
481 ATTRIBUTE (FORWARD (q)) = ASSIGN_SYMBOL;
482 q = skip_unit (q);
483 } else {
484 siga = A68G_FALSE;
485 }
486 } while (siga && q != NO_NODE && IS (q, COMMA_SYMBOL));
487 } else {
488 FORWARD (q);
489 }
490 }
491 }
492
493 //! @brief Schedule gathering of definitions in a phrase.
494
495 void extract_declarations (NODE_T * p)
496 {
497 // Get definitions so we know what is defined in this range.
498 extract_identities (p);
499 extract_variables (p);
500 extract_proc_identities (p);
501 extract_proc_variables (p);
502 // By now we know whether "=" is an operator or not.
503 for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
504 if (IS (q, EQUALS_SYMBOL)) {
505 ATTRIBUTE (q) = OPERATOR;
506 } else if (IS (q, ALT_EQUALS_SYMBOL)) {
507 ATTRIBUTE (q) = EQUALS_SYMBOL;
508 }
509 }
510 // Get qualifiers.
511 for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
512 if (whether (q, LOC_SYMBOL, DECLARER, DEFINING_IDENTIFIER, STOP)) {
513 make_sub (q, q, QUALIFIER);
514 }
515 if (whether (q, HEAP_SYMBOL, DECLARER, DEFINING_IDENTIFIER, STOP)) {
516 make_sub (q, q, QUALIFIER);
517 }
518 if (whether (q, NEW_SYMBOL, DECLARER, DEFINING_IDENTIFIER, STOP)) {
519 make_sub (q, q, QUALIFIER);
520 }
521 if (whether (q, LOC_SYMBOL, PROC_SYMBOL, DEFINING_IDENTIFIER, STOP)) {
522 make_sub (q, q, QUALIFIER);
523 }
524 if (whether (q, HEAP_SYMBOL, PROC_SYMBOL, DEFINING_IDENTIFIER, STOP)) {
525 make_sub (q, q, QUALIFIER);
526 }
527 if (whether (q, NEW_SYMBOL, PROC_SYMBOL, DEFINING_IDENTIFIER, STOP)) {
528 make_sub (q, q, QUALIFIER);
529 }
530 }
531 // Give priorities to operators.
532 for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
533 if (IS (q, OPERATOR)) {
534 if (find_tag_global (TABLE (q), OP_SYMBOL, NSYMBOL (q))) {
535 TAG_T *s = find_tag_global (TABLE (q), PRIO_SYMBOL, NSYMBOL (q));
536 if (s != NO_TAG) {
537 PRIO (INFO (q)) = PRIO (s);
538 } else {
539 PRIO (INFO (q)) = 0;
540 }
541 } else {
542 diagnostic (A68G_SYNTAX_ERROR, q, ERROR_UNDECLARED_TAG);
543 PRIO (INFO (q)) = 1;
544 }
545 }
546 }
547 }
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|