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