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)