home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.pdx.edu / 2014.02.ftp.ee.pdx.edu.tar / ftp.ee.pdx.edu / pub / users / Harry / Blitz / version-1-0 / Beta / parser.cc < prev    next >
C/C++ Source or Header  |  2007-09-04  |  124KB  |  4,292 lines

  1. // parser.cc  --  Functions related to parsing
  2. //
  3. // KPL Compiler
  4. //
  5. // Copyright 2002-2007, Harry H. Porter III
  6. //
  7. // This file may be freely copied, modified and compiled, on the sole
  8. // condition that if you modify it...
  9. //   (1) Your name and the date of modification is added to this comment
  10. //       under "Modifications by", and
  11. //   (2) Your name and the date of modification is added to the printHelp()
  12. //       routine in file "main.cc" under "Modifications by".
  13. //
  14. // Original Author:
  15. //   06/15/02 - Harry H. Porter III
  16. //
  17. // Modifcations by:
  18. //   03/15/06 - Harry H. Porter III
  19. //
  20. //
  21.  
  22. #include "main.h"
  23.  
  24.  
  25.  
  26. // nextTokenIsID (msg)
  27. //
  28. // This routine checks to see if the next token is an ID, and returns true
  29. // or false.  If not, it also prints a message.  If an ID happens to occur
  30. // in the next couple of tokens, it advances to it and returns true.
  31. //
  32. int nextTokenIsID (char * msg) {
  33.   if (token.type == ID) {
  34.     return 1;
  35.   } else {
  36.     syntaxError (msg);
  37.     // See if the desired token happens to occur really soon;
  38.     // If so, scan the extra tokens.
  39.     if (token2.type == ID) {
  40.       scan ();
  41.       checkTokenSkipping (1);
  42.       return 1;
  43.     } else if (token3.type == ID) {
  44.       scan ();
  45.       scan ();
  46.       checkTokenSkipping (2);
  47.       return 1;
  48.     } else {
  49.       checkTokenSkipping (0);
  50.       return 0;
  51.     }
  52.   }
  53. }
  54.  
  55.  
  56.  
  57. // mustHaveID (msg)
  58. //
  59. // This routine checks to see if the next token is an ID.  If not, it
  60. // prints the message.  In any case, it returns a valid String.  It
  61. // may scan zero tokens, if there is an error.
  62. //
  63. String * mustHaveID (char * msg) {
  64.   String * retVal;
  65.   if (nextTokenIsID (msg)) {
  66.     retVal = token.value.svalue;
  67.     scan ();
  68.     return retVal;
  69.   } else {
  70.     return lookupAndAdd ("<missingIdSyntaxError>", ID);
  71.   }
  72. }
  73.  
  74.  
  75.  
  76. // mustHave (tok, msg)
  77. //
  78. // The next token must be 'tok'.  If so, scan it.  If not, print a syntax
  79. // error.
  80. //
  81. // THIS ROUTINE MAY NOT SCAN ANY TOKENS!!!  Therefore, the caller MUST ensure that
  82. // the parser will scan at least one token in any loop calling this routine.
  83. //
  84. void mustHave (int tok, char * msg) {
  85.   if (token.type == tok) {
  86.     scan ();
  87.   } else {
  88.     syntaxError (msg);
  89.     // See if the desired token happens to occur really soon;
  90.     // If so, scan the extra tokens and get it.
  91.     if (token2.type == tok) {
  92.       scan ();
  93.       scan ();
  94.       checkTokenSkipping (1);
  95.     } else if (token3.type == tok) {
  96.       scan ();
  97.       scan ();
  98.       scan ();
  99.       checkTokenSkipping (2);
  100.     } else {
  101.       checkTokenSkipping (0);
  102.     }
  103.   }
  104. }
  105.  
  106.  
  107.  
  108. // mustHaveOrScanUntilInScanSet (tok, msg)  --> bool
  109. //
  110. // The next token must be 'tok'.  If so, scan it.  If not, print a syntax
  111. // error and keep scanning until we get it or we hit EOF or something that
  112. // is in the "scan set" of tokens.
  113. //
  114. // THIS ROUTINE MAY NOT SCAN ANY TOKENS!!!  (...if we are already positioned
  115. // on a token that is in the "scan set".)  Therefore, the caller MUST ensure that
  116. // the parser will scan at least one token in any loop calling this routine.
  117. //
  118. // This routine returns TRUE if we got the token we were searching for (even if
  119. // there was an error and we had to scan some tokens) and FALSE if we stopped on
  120. // some other token.
  121. //
  122. int mustHaveOrScanUntilInScanSet (int tok, char * msg) {
  123.   int count;
  124.   int retValue = 0;
  125.   printf ("**********  OBSOLETE ROUTINE  **********\n");
  126.   if (token.type == tok) {
  127.     scan ();
  128.     return 1;
  129.   } else {
  130.     syntaxError (msg);
  131.     count = 0;
  132.     while (1) {
  133.       if (token.type == EOF) {
  134.         break;
  135.       } else if (token.type == tok) {
  136.         scan ();
  137.         count++;
  138.         retValue = 1;
  139.         break;
  140.       } else if (inScanSet ()) {
  141.         if (token.type == tok) {
  142.           scan ();
  143.           count++;
  144.         }
  145.         break;
  146.       }
  147.       scan ();
  148.       count++;
  149.     }
  150.     checkTokenSkipping (count);
  151.     return retValue;
  152.   }
  153. }
  154.  
  155.  
  156.  
  157. // scanToFollowType ()
  158. //
  159. // This routine scans until we hit a token that can follow a Type.  It may
  160. // scan zero tokens.
  161. //
  162. void scanToFollowType () {
  163.   int count = 0;
  164.   while ((token.type != EOF) && !inFollowType ()) {
  165.     scan ();
  166.     count++;
  167.   }
  168.   checkTokenSkipping (count);
  169.   return;
  170. }
  171.  
  172.  
  173.  
  174. // inScanSet () --> bool
  175. //
  176. // Return true if the next token could follow a Statement or StmtList, or is one of
  177. // the tokens listed in the first section of misc. tokens:
  178. //   
  179. int inScanSet () {
  180.   switch (token.type) {
  181.     // First section of token of misc. tokens...
  182.     case RETURNS:
  183.     case HEADER:
  184.     case END_HEADER:
  185.     case CODE:
  186.     case END_CODE:
  187.     case INTERFACE:
  188.     case EXTENDS:
  189.     case MESSAGES:
  190.     case END_INTERFACE:
  191.     case CLASS:
  192.     case IMPLEMENTS:
  193.     case SUPER_CLASS:
  194.     case RENAMING:
  195.     case FIELDS:
  196.     case METHODS:
  197.     case END_CLASS:
  198.     case BEHAVIOR:
  199.     case END_BEHAVIOR:
  200.     case USES:
  201.     case TO:
  202.     case CONST:
  203.     case ERRORS:
  204.     case VAR:
  205.     case TYPE:
  206.     case ENUM:
  207.     case FUNCTIONS:
  208. //  case FUNCTION:          // listed below
  209. //  case END_FUNCTION:      // listed below
  210.     case INFIX:
  211.     case PREFIX:
  212.     case METHOD:
  213. //  case END_METHOD:        // listed below
  214.     case COLON:
  215.     // These are from FIRST(TYPE)...
  216.     case INT:
  217.     case BOOL:
  218.     case CHAR:
  219.     case DOUBLE:
  220.     case TYPE_OF_NULL:
  221.     case ANY_TYPE:
  222.     case VOID:
  223.     case RECORD:
  224.     case PTR:
  225.     case ARRAY:
  226. //  case FUNCTION:
  227. //  case ID:
  228.     // These are from FOLLOW(STMT)...
  229.     case ELSE_IF:
  230.     case ELSE:
  231.     case END_IF:
  232.     case END_WHILE:
  233.     case END_FOR:
  234.     case CASE:
  235.     case DEFAULT:
  236.     case END_SWITCH:
  237.     case CATCH:
  238.     case END_TRY:
  239.     case END_FUNCTION:
  240.     case END_METHOD:
  241.     case SEMI_COLON:
  242.     case R_PAREN:
  243.     case UNTIL:
  244.     // These are from FIRST(STMT)...
  245.     case IF:
  246.     case WHILE:
  247.     case DO:
  248.     case BREAK:
  249.     case CONTINUE:
  250.     case RETURN:
  251.     case FOR:
  252.     case SWITCH:
  253.     case TRY:
  254.     case THROW:
  255.     // These are from FIRST(EXPR)...
  256.     case TRUE:
  257.     case FALSE:
  258.     case NULL_KEYWORD:
  259.     case SELF:
  260.     case SUPER:
  261.     case INT_CONST:
  262.     case DOUBLE_CONST:
  263.     case CHAR_CONST:
  264.     case STRING_CONST:
  265.     case FUNCTION:
  266.     case ID:
  267.     case NEW:
  268.     case ALLOC:
  269.     case FREE:
  270.     case DEBUG:
  271.     case SIZE_OF:
  272.     case L_PAREN:
  273.     case OPERATOR:
  274.       return 1;
  275.     default:
  276.       return 0;
  277.   }
  278. }
  279.  
  280.  
  281.  
  282. // inFirstStmt () --> bool
  283. //
  284. // Return true if the next token could be the first token in a Statement or StmtList.
  285. //
  286. int inFirstStmt () {
  287.   switch (token.type) {
  288.     case IF:
  289.     case WHILE:
  290.     case DO:
  291.     case BREAK:
  292.     case CONTINUE:
  293.     case RETURN:
  294.     case FOR:
  295.     case SWITCH:
  296.     case TRY:
  297.     case THROW:
  298.     // These are from FIRST(EXPR)...
  299.     case TRUE:
  300.     case FALSE:
  301.     case NULL_KEYWORD:
  302.     case SELF:
  303.     case SUPER:
  304.     case INT_CONST:
  305.     case DOUBLE_CONST:
  306.     case CHAR_CONST:
  307.     case STRING_CONST:
  308.     case FUNCTION:
  309.     case ID:
  310.     case NEW:
  311.     case ALLOC:
  312.     case FREE:
  313.     case DEBUG:
  314.     case SIZE_OF:
  315.     case L_PAREN:
  316.     case OPERATOR:
  317.       return 1;
  318.     default:
  319.       return 0;
  320.   }
  321. }
  322.  
  323.  
  324.  
  325. // inFollowStmt () --> bool
  326. //
  327. // Return true if the next token could follow a Statement or StmtList.
  328. //
  329. int inFollowStmt () {
  330.   switch (token.type) {
  331.     case ELSE_IF:
  332.     case ELSE:
  333.     case END_IF:
  334.     case END_WHILE:
  335.     case END_FOR:
  336.     case CASE:
  337.     case DEFAULT:
  338.     case END_SWITCH:
  339.     case CATCH:
  340.     case END_TRY:
  341.     case END_FUNCTION:
  342.     case END_METHOD:
  343.     case SEMI_COLON:
  344.     case R_PAREN:
  345.     case UNTIL:
  346.     // These are from FIRST(STMT)...
  347.     case IF:
  348.     case WHILE:
  349.     case DO:
  350.     case BREAK:
  351.     case CONTINUE:
  352.     case RETURN:
  353.     case FOR:
  354.     case SWITCH:
  355.     case TRY:
  356.     case THROW:
  357.     // These are from FIRST(EXPR)...
  358.     case TRUE:
  359.     case FALSE:
  360.     case NULL_KEYWORD:
  361.     case SELF:
  362.     case SUPER:
  363.     case INT_CONST:
  364.     case DOUBLE_CONST:
  365.     case CHAR_CONST:
  366.     case STRING_CONST:
  367.     case FUNCTION:
  368.     case ID:
  369.     case NEW:
  370.     case ALLOC:
  371.     case FREE:
  372.     case DEBUG:
  373.     case SIZE_OF:
  374.     case L_PAREN:
  375.     case OPERATOR:
  376.       return 1;
  377.     default:
  378.       return 0;
  379.   }
  380. }
  381.  
  382.  
  383.  
  384. // inFirstExpr (tok) --> bool
  385. //
  386. // Return true if the given token could be the first token in an Expression.
  387. //
  388. int inFirstExpr (Token tok) {
  389.   switch (tok.type) {
  390.     case TRUE:
  391.     case FALSE:
  392.     case NULL_KEYWORD:
  393.     case SELF:
  394.     case SUPER:
  395.     case INT_CONST:
  396.     case DOUBLE_CONST:
  397.     case CHAR_CONST:
  398.     case STRING_CONST:
  399.     case FUNCTION:
  400.     case ID:
  401.     case NEW:
  402.     case ALLOC:
  403.     case FREE:
  404.     case DEBUG:
  405.     case SIZE_OF:
  406.     case L_PAREN:
  407.     case OPERATOR:
  408.       return 1;
  409.     default:
  410.       return 0;
  411.   }
  412. }
  413.  
  414.  
  415.  
  416. // inFollowExpr () --> bool
  417. //
  418. // Return true if the next token could follow an Expression.
  419. //
  420. int inFollowExpr () {
  421.   switch (token.type) {
  422. //  case R_PAREN:
  423.     case COMMA:
  424.     case EQUAL:
  425.     case COLON:
  426.     case PERIOD:
  427.     case R_BRACE:
  428.     case R_BRACK:
  429.     case TO:
  430.     case BY:
  431.     case AS_PTR_TO:
  432.     case AS_INTEGER:
  433.     case ARRAY_SIZE:
  434.     case IS_INSTANCE_OF:
  435.     case IS_KIND_OF:
  436.     case OF:
  437.     case CONST:
  438.     case ERRORS:
  439.     case VAR:
  440.     case ENUM:
  441.     case TYPE:
  442.     case FUNCTIONS:
  443. //  case FUNCTION:      // listed below
  444.     case INTERFACE:
  445.     case CLASS:
  446.     case END_HEADER:
  447.     case END_CODE:
  448.     case BEHAVIOR:
  449.     // These are from FOLLOW(STMT)...
  450.     case ELSE_IF:
  451.     case ELSE:
  452.     case END_IF:
  453.     case END_WHILE:
  454.     case END_FOR:
  455.     case CASE:
  456.     case DEFAULT:
  457.     case END_SWITCH:
  458.     case CATCH:
  459.     case END_TRY:
  460.     case END_FUNCTION:
  461.     case END_METHOD:
  462.     case SEMI_COLON:
  463.     case R_PAREN:
  464.     case UNTIL:
  465.     // These are from FIRST(STMT)...
  466.     case IF:
  467.     case WHILE:
  468.     case DO:
  469.     case BREAK:
  470.     case CONTINUE:
  471.     case RETURN:
  472.     case FOR:
  473.     case SWITCH:
  474.     case TRY:
  475.     case THROW:
  476.     // These are from FIRST(EXPR)...
  477.     case TRUE:
  478.     case FALSE:
  479.     case NULL_KEYWORD:
  480.     case SELF:
  481.     case SUPER:
  482.     case INT_CONST:
  483.     case DOUBLE_CONST:
  484.     case CHAR_CONST:
  485.     case STRING_CONST:
  486.     case FUNCTION:
  487.     case ID:
  488.     case NEW:
  489.     case ALLOC:
  490.     case FREE:
  491.     case DEBUG:
  492.     case SIZE_OF:
  493.     case L_PAREN:
  494.     case OPERATOR:
  495.       return 1;
  496.     default:
  497.       return 0;
  498.   }
  499. }
  500.  
  501.  
  502.  
  503. // inFirstType (tok) --> bool
  504. //
  505. // Return true if the given token could be the first token in a Type.
  506. //
  507. int inFirstType (Token tok) {
  508.   switch (tok.type) {
  509.     case CHAR:
  510.     case INT:
  511.     case DOUBLE:
  512.     case BOOL:
  513.     case VOID:
  514.     case TYPE_OF_NULL:
  515.     case ANY_TYPE:
  516.     case ID:
  517.     case PTR:
  518.     case RECORD:
  519.     case ARRAY:
  520.     case FUNCTION:
  521.       return 1;
  522.     default:
  523.       return 0;
  524.   }
  525. }
  526.  
  527.  
  528.  
  529. // inFollowType () --> bool
  530. //
  531. // Return true if the next token could follow a Type.
  532. //
  533. // [I'm not 100% sure that this set is correct, but since it is only used for
  534. // an intelligent recovery from syntax errors, it should be adequate.]
  535. //
  536. int inFollowType () {
  537.   switch (token.type) {
  538. //  case COMMA:
  539. //  case R_BRACK:
  540. //  case ID:
  541. //  case VAR:
  542. //  case END_FUNCTION:
  543. //  case R_PAREN:
  544.     case END_RECORD:
  545. //  case EQUAL:
  546.     case EXTERNAL:
  547.     case END_CLASS:
  548.     // These are from FOLLOW(EXPR)...
  549. //  case R_PAREN:
  550.     case COMMA:
  551.     case EQUAL:
  552.     case COLON:
  553.     case PERIOD:
  554.     case R_BRACE:
  555.     case R_BRACK:
  556.     case TO:
  557.     case BY:
  558.     case AS_PTR_TO:
  559.     case AS_INTEGER:
  560.     case ARRAY_SIZE:
  561.     case IS_INSTANCE_OF:
  562.     case IS_KIND_OF:
  563.     case OF:
  564.     case CONST:
  565.     case ERRORS:
  566.     case VAR:
  567.     case ENUM:
  568.     case TYPE:
  569.     case FUNCTIONS:
  570. //  case FUNCTION:      // listed below
  571.     case INTERFACE:
  572.     case CLASS:
  573.     case END_HEADER:
  574.     case END_CODE:
  575.     case BEHAVIOR:
  576.     // These are from FOLLOW(STMT)...
  577.     case ELSE_IF:
  578.     case ELSE:
  579.     case END_IF:
  580.     case END_WHILE:
  581.     case END_FOR:
  582.     case CASE:
  583.     case DEFAULT:
  584.     case END_SWITCH:
  585.     case CATCH:
  586.     case END_TRY:
  587.     case END_FUNCTION:
  588.     case END_METHOD:
  589.     case SEMI_COLON:
  590.     case R_PAREN:
  591.     case UNTIL:
  592.     // These are from FIRST(STMT)...
  593.     case IF:
  594.     case WHILE:
  595.     case DO:
  596.     case BREAK:
  597.     case CONTINUE:
  598.     case RETURN:
  599.     case FOR:
  600.     case SWITCH:
  601.     case TRY:
  602.     case THROW:
  603.     // These are from FIRST(EXPR)...
  604.     case TRUE:
  605.     case FALSE:
  606.     case NULL_KEYWORD:
  607.     case SELF:
  608.     case SUPER:
  609.     case INT_CONST:
  610.     case DOUBLE_CONST:
  611.     case CHAR_CONST:
  612.     case STRING_CONST:
  613.     case FUNCTION:
  614.     case ID:
  615.     case NEW:
  616.     case ALLOC:
  617.     case FREE:
  618.     case DEBUG:
  619.     case SIZE_OF:
  620.     case L_PAREN:
  621.     case OPERATOR:
  622.       return 1;
  623.     default:
  624.       return 0;
  625.   }
  626. }
  627.  
  628.  
  629.  
  630. // inHeaderSet () --> bool
  631. //
  632. // Return true if the next token could be something in a header file, or it is EOF.
  633. //
  634. int inHeaderSet () {
  635.   switch (token.type) {
  636.     case CONST:
  637.     case ERRORS:
  638.     case VAR:
  639.     case ENUM:
  640.     case TYPE:
  641.     case FUNCTIONS:
  642.     case INTERFACE:
  643.     case CLASS:
  644.     case END_HEADER:
  645.     case EOF:
  646.       return 1;
  647.     default:
  648.       return 0;
  649.   }
  650. }
  651.  
  652.  
  653.  
  654. // inCodeSet () --> bool
  655. //
  656. // Return true if the next token could be something in a code file, or it is EOF.
  657. //
  658. int inCodeSet () {
  659.   switch (token.type) {
  660.     case CONST:
  661.     case ERRORS:
  662.     case VAR:
  663.     case ENUM:
  664.     case TYPE:
  665.     case FUNCTION:
  666.     case INTERFACE:
  667.     case CLASS:
  668.     case BEHAVIOR:
  669.     case END_CODE:
  670.     case EOF:
  671.       return 1;
  672.     default:
  673.       return 0;
  674.   }
  675. }
  676.  
  677.  
  678.  
  679. // appendStmtLists (stmtList1, stmtList2) --> stmtList
  680. //
  681. // This routine is passed 2 lists of statements.  It appends them and returns
  682. // the result.  Either input list may be NULL.
  683. //
  684. Statement * appendStmtLists (Statement * stmtList1,
  685.                            Statement * stmtList2) {
  686.   Statement * p;
  687.  
  688.   if (stmtList1 == NULL) return stmtList2;
  689.   if (stmtList2 == NULL) return stmtList1;
  690.   for (p = stmtList1; p->next; p = p->next) {
  691.   }
  692.   p->next = stmtList2;
  693.   return stmtList1;
  694.  
  695. }
  696.  
  697.  
  698.  
  699. // parseStmtList (enclosingStmtForBreak,
  700. //                enclosingStmtForContinue,
  701. //                enclosingMethOrFunction,
  702. //                endsWithSemiColon)
  703. //
  704. // This routine parses zero or more consequtive statements and returns
  705. // a pointer to a statement list, possibly NULL.  This routine may scan
  706. // ZERO tokens.
  707. //
  708. // Normally statements are not followed by semi-colons, but it one case they
  709. // are.  (E.g., 'FOR (stmtList; expr; stmtList) stmtList END_FOR')  It is a common
  710. // mistake (from C/Java) to terminate a statement with a semi-colon.  The
  711. // 'endsWithSemiColon' is true only in the 'FOR' case; it is used to print an
  712. // appropriate error and continue otherwise.
  713. //
  714. Statement * parseStmtList (Statement * enclosingStmtForBreak,
  715.                            Statement * enclosingStmtForContinue,
  716.                            MethOrFunction * enclosingMethOrFunction,
  717.                            int endsWithSemiColon) {
  718.   Statement *firstStmt, *lastStmt, *nextStmt;
  719.   firstStmt = NULL;
  720.   lastStmt = NULL;
  721.   int count2;
  722.   int count = 0;
  723.       
  724.   while (1) {
  725.     count++;
  726.     if (count > 100) {
  727.       programLogicError ("Looping in parseStmtList");
  728.     }
  729.     if (token.type == EOF) {
  730.       syntaxError ("Expecting a statement here - EOF encountered");
  731.       return firstStmt;
  732.     } else if (inFirstStmt ()) {
  733.       nextStmt = parseStmt (enclosingStmtForBreak,
  734.                             enclosingStmtForContinue,
  735.                             enclosingMethOrFunction);
  736.       if (token.type == SEMI_COLON && !endsWithSemiColon) {
  737.         syntaxError ("Unexpected SEMI_COLON; statements are not terminated with ';' in this language");
  738.         scan ();
  739.       }
  740.       if (nextStmt != NULL) {
  741.         count = 0;
  742.         if (firstStmt == NULL) {
  743.           firstStmt = nextStmt;
  744.         }
  745.         if (lastStmt != NULL) {
  746.           lastStmt->next = nextStmt;
  747.         }
  748.         lastStmt = nextStmt;
  749.         while (lastStmt->next != NULL) {
  750.           lastStmt = lastStmt->next;
  751.         }
  752.       }
  753.     } else if (inFollowStmt ()) {
  754.       return firstStmt;
  755.     } else {
  756.       syntaxError ("Expecting a statement here");
  757.       count2 = 0;
  758.       while (1) {
  759.         if (inFollowStmt ()) break;
  760.         if (token.type == EOF) break;
  761.         scan ();
  762.         count2++;
  763.       }
  764.       checkTokenSkipping (count2);
  765.     }
  766.   }
  767. }
  768.  
  769.  
  770.  
  771. // parseStmt (enclosingStmtForBreak, enclosingStmtForContinue, enclosingMethOrFunction)
  772. //
  773. // This routine parses a single statement and returns a pointer to it.
  774. // It is assumed that we know that the next token is really the first token
  775. // of a statement.  If it runs into problems, it may return NULL.
  776. //
  777. // The 'enclosingStmtForBreak' points to the innermost FOR, WHILE, DO,
  778. // or SWITCH statement, containing the statement we are parsing.  The
  779. // 'enclosingStmtForContinue' points to the innermost FOR, WHILE, or DO
  780. // statement, containing the statement we are parsing.  The purpose of these
  781. // is to allow us to associate a BREAK or CONTINUE statement with the
  782. // statement it refers to.
  783. //
  784. // The 'enclosingMethOrFunction' points to the lexically surrounding function or
  785. // method.  This is needed when we parse a RETURN statement: we need to know whether
  786. // or not to pick up an expression.
  787. //
  788. Statement * parseStmt (Statement * enclosingStmtForBreak,
  789.                        Statement * enclosingStmtForContinue,
  790.                        MethOrFunction * enclosingMethOrFunction) {
  791.   IfStmt * firstIfStmt, * lastIfStmt, * nextIfStmt;
  792.   WhileStmt * whileStmt;
  793.   DoStmt * doStmt;
  794.   BreakStmt * breakStmt;
  795.   ContinueStmt * continueStmt;
  796.   ReturnStmt * returnStmt;
  797.   ForStmt * forStmt;
  798.   SwitchStmt * switchStmt;
  799.   Case * cas, * lastCase;
  800.   TryStmt * tryStmt;
  801.   Catch * cat, * lastCatch;
  802.   ThrowStmt * throwStmt;
  803.   FreeStmt * freeStmt;
  804.   DebugStmt * debugStmt;
  805.   Function * fun;
  806.   Method * meth;
  807.   CallStmt * callStmt;
  808.   SendStmt * sendStmt;
  809.   AssignStmt * assignStmt;
  810.   Expression * expr1, * expr2;
  811.   Statement * initStmts, * incrStmts, * bodyStmts;
  812.  
  813.   if (token.type == IF) {
  814.     firstIfStmt = new IfStmt ();
  815.     scan ();
  816.     firstIfStmt->expr = parseExpr ("Expecting a boolean expression after 'if'");
  817.     firstIfStmt->thenStmts = parseStmtList (enclosingStmtForBreak,
  818.                                             enclosingStmtForContinue,
  819.                                             enclosingMethOrFunction,
  820.                                             0);
  821.     nextIfStmt = lastIfStmt = firstIfStmt;
  822.     while (token.type == ELSE_IF) {
  823.         nextIfStmt = new IfStmt ();   
  824.         scan (); 
  825.         nextIfStmt->expr = parseExpr ("Expecting a boolean expression after 'elseIf'");
  826.         nextIfStmt->thenStmts = parseStmtList (enclosingStmtForBreak,
  827.                                                enclosingStmtForContinue,
  828.                                                enclosingMethOrFunction,
  829.                                                0);
  830.         lastIfStmt->elseStmts = nextIfStmt;
  831.         lastIfStmt = nextIfStmt;
  832.     }
  833.     if (token.type == ELSE) {
  834.       scan ();
  835.       lastIfStmt->elseStmts = parseStmtList (enclosingStmtForBreak,
  836.                                              enclosingStmtForContinue,
  837.                                              enclosingMethOrFunction,
  838.                                              0);
  839.     }
  840.     mustHave (END_IF, "Expecting 'endIf'");
  841.     return firstIfStmt;
  842.  
  843.   } else if (token.type == WHILE) {
  844.     whileStmt = new WhileStmt ();
  845.     scan ();
  846.     whileStmt->expr = parseExpr ("Expecting a boolean expression after 'while'");
  847.     whileStmt->stmts = parseStmtList (whileStmt, whileStmt, enclosingMethOrFunction, 0);
  848.     mustHave (END_WHILE, "Expecting 'endWhile'");
  849.     return whileStmt;
  850.  
  851.   } else if (token.type == DO) {
  852.     doStmt = new DoStmt ();
  853.     scan ();
  854.     doStmt->stmts = parseStmtList (doStmt, doStmt, enclosingMethOrFunction, 0);
  855.     mustHave (UNTIL, "Expecting 'until' in 'do StmtList until Expr'");
  856.     doStmt->expr = parseExpr ("Expecting a boolean expression after 'until'");
  857.     return doStmt;
  858.  
  859.   } else if ((token.type == FOR) && (token2.type == L_PAREN)) {
  860.     whileStmt = new WhileStmt ();
  861.     scan ();   // FOR
  862.     scan ();   // '('
  863.     initStmts = parseStmtList (whileStmt,
  864.                                whileStmt,
  865.                                enclosingMethOrFunction,
  866.                                1);    // endsWithSemiColon = 1
  867.     mustHave (SEMI_COLON, "Expecting first ';' in 'for ( initStmts ; expr ; incrStmts ) bodyStmts endFor'");
  868.     if (token.type == SEMI_COLON) {
  869.       whileStmt->expr = new BoolConst (1);
  870.     } else {
  871.       whileStmt->expr = parseExpr ("Expecting expr in 'for ( initStmts ; expr ; incrStmts ) bodyStmts endFor'");
  872.     }
  873.     mustHave (SEMI_COLON, "Expecting second ';' in 'for ( initStmts ; expr ; incrStmts ) bodyStmts endFor'");
  874.     incrStmts = parseStmtList (whileStmt,
  875.                                whileStmt,
  876.                                enclosingMethOrFunction,
  877.                                1);    // endsWithSemiColon = 1
  878.     mustHave (R_PAREN, "Expecting ')' in 'for ( initStmts ; expr ; incrStmts ) bodyStmts endFor'");
  879.     bodyStmts = parseStmtList (whileStmt,
  880.                                whileStmt,
  881.                                enclosingMethOrFunction,
  882.                                0);
  883.     mustHave (END_FOR, "Expecting in 'for ( initStmts ; expr ; incrStmts ) bodyStmts endFor'");
  884.     whileStmt->stmts = appendStmtLists (bodyStmts, incrStmts);
  885.     return appendStmtLists (initStmts, whileStmt);
  886.  
  887. /***
  888.     forStmt = new ForStmt ();
  889.     scan ();
  890.     forStmt->lvalue = parseExpr ("Expecting an L-Value after 'for'");
  891.     mustHave (EQUAL, "Expecting '=' in 'for lvalue = Expr to Expr...'");
  892.     forStmt->expr1= parseExpr ("Expecting Expr1 in 'for lvalue = Expr1 to Expr2...");
  893.     mustHave (TO, "Expecting 'to' in 'for lvalue = Expr to Expr...'");
  894.     forStmt->expr2 = parseExpr ("Expecting Expr2 in 'for lvalue = Expr1 to Expr2...");
  895.     if (token.type == BY) {
  896.       scan ();
  897.       forStmt->expr3 = parseExpr ("Expecting Expr3 in 'for lvalue = Expr1 to Expr2 by Expr3");
  898.     }
  899.     forStmt->stmts = parseStmtList (forStmt, forStmt, enclosingMethOrFunction, 0);
  900.     mustHave (END_FOR, "Expecting 'endFor'");
  901.     return forStmt;
  902. ***/
  903.  
  904.   } else if (token.type == FOR) {
  905.     forStmt = new ForStmt ();
  906.     scan ();
  907.     forStmt->lvalue = parseExpr ("Expecting an L-Value after 'for'");
  908.     mustHave (EQUAL, "Expecting '=' in 'for lvalue = Expr to Expr...'");
  909.     forStmt->expr1= parseExpr ("Expecting Expr1 in 'for lvalue = Expr1 to Expr2...");
  910.     mustHave (TO, "Expecting 'to' in 'for lvalue = Expr to Expr...'");
  911.     forStmt->expr2 = parseExpr ("Expecting Expr2 in 'for lvalue = Expr1 to Expr2...");
  912.     if (token.type == BY) {
  913.       scan ();
  914.       forStmt->expr3 = parseExpr ("Expecting Expr3 in 'for lvalue = Expr1 to Expr2 by Expr3");
  915.     }
  916.     forStmt->stmts = parseStmtList (forStmt, forStmt, enclosingMethOrFunction, 0);
  917.     mustHave (END_FOR, "Expecting 'endFor'");
  918.     return forStmt;
  919.  
  920.   } else if (token.type == SWITCH) {
  921.     switchStmt = new SwitchStmt ();
  922.     scan ();
  923.     switchStmt->expr = parseExpr ("Expecting an expression after 'switch'");
  924.     lastCase = NULL;
  925.     while (token.type == CASE) {
  926.       cas = new Case ();
  927.       scan ();
  928.       if (lastCase == NULL) {
  929.         switchStmt->caseList = cas;
  930.       } else {
  931.         lastCase->next = cas;
  932.       }
  933.       lastCase = cas;
  934.       cas->expr = parseExpr ("Expecting an expression after 'case'");
  935.       mustHave (COLON, "Expecting ':' in 'case Expr: ...'");
  936.       cas->stmts = parseStmtList (switchStmt,
  937.                                   enclosingStmtForContinue,
  938.                                   enclosingMethOrFunction,
  939.                                   0);
  940.     }
  941.     if (token.type == DEFAULT) {
  942.       scan ();
  943.       switchStmt->defaultIncluded = 1;
  944.       mustHave (COLON, "Expecting ':' after 'default'");
  945.       switchStmt->defaultStmts = parseStmtList (switchStmt,
  946.                                                 enclosingStmtForContinue,
  947.                                                 enclosingMethOrFunction,
  948.                                                 0);
  949.     }
  950.     mustHave (END_SWITCH, "Expecting 'endSwitch'");
  951.     return switchStmt;
  952.  
  953.   } else if (token.type == TRY) {
  954.     tryStmt = new TryStmt ();
  955.     scan ();
  956.     if (enclosingMethOrFunction == NULL) {
  957.       programLogicError ("enclosingMethOrFunction is NULL for TRY stmt");
  958.     }
  959.     enclosingMethOrFunction->containsTry = 1;
  960.     tryStmt->stmts = parseStmtList (enclosingStmtForBreak,
  961.                                     enclosingStmtForContinue,
  962.                                     enclosingMethOrFunction,
  963.                                     0);
  964.     lastCatch = NULL;
  965.     while (token.type == CATCH) {
  966.       scan ();    // CATCH
  967.       cat = new Catch ();
  968.       if (lastCatch == NULL) {
  969.         tryStmt->catchList = cat;
  970.       } else {
  971.         lastCatch->next = cat;
  972.       }
  973.       lastCatch = cat;
  974.       if (token.type == ID) {
  975.         cat->id = token.value.svalue;
  976.         scan ();
  977.       } else {
  978.         syntaxError ("Expecting ID after 'catch'");
  979.         cat->id = lookupAndAdd ("<missingIdSyntaxError>", ID);
  980.       }
  981.       cat->parmList = parseParmList ();
  982.       mustHave (COLON, "Expecting ':' in 'catch ID (...) : Stmts'");
  983.       cat->stmts = parseStmtList (enclosingStmtForBreak,
  984.                                   enclosingStmtForContinue,
  985.                                   enclosingMethOrFunction,
  986.                                   0);
  987.       cat->enclosingMethOrFunction = enclosingMethOrFunction;
  988.       cat->nextInMethOrFunction = enclosingMethOrFunction->catchList;
  989.       enclosingMethOrFunction->catchList = cat;
  990.     }
  991.     mustHave (END_TRY, "Expecting 'endTry'");
  992.     return tryStmt;
  993.  
  994.   } else if (token.type == BREAK) {
  995.     breakStmt = new BreakStmt ();
  996.     if (enclosingStmtForBreak == NULL) {
  997.       syntaxError ("This BREAK is not within a WHILE, DO, FOR, or SWITCH statement");
  998.       breakStmt = NULL;
  999.     } else {
  1000.       breakStmt->enclosingStmt = enclosingStmtForBreak;
  1001.       // Set "containsAnyBreaks" in WHILE, FOR, or DO.
  1002.       switch (enclosingStmtForBreak->op) {
  1003.         case WHILE_STMT:
  1004.           whileStmt = (WhileStmt *) (breakStmt->enclosingStmt);
  1005.           whileStmt->containsAnyBreaks = 1;
  1006.           break;
  1007.         case FOR_STMT:
  1008.           forStmt = (ForStmt *) (breakStmt->enclosingStmt);
  1009.           forStmt->containsAnyBreaks = 1;
  1010.           break;
  1011.         case DO_STMT:
  1012.           doStmt = (DoStmt *) (breakStmt->enclosingStmt);
  1013.           doStmt->containsAnyBreaks = 1;
  1014.           break;
  1015.         case SWITCH_STMT:
  1016.           switchStmt = (SwitchStmt *) (breakStmt->enclosingStmt);
  1017.           switchStmt->containsAnyBreaks = 1;
  1018.           break;
  1019.         default:
  1020.           printf ("breakStmt->enclosingStmt->op = %s\n",
  1021.                   symbolName (breakStmt->enclosingStmt->op));
  1022.           programLogicError ("Unkown op in fallsThru, breakStmt");
  1023.       }
  1024.     }
  1025.     scan ();  // BREAK
  1026.     return breakStmt;
  1027.   } else if (token.type == CONTINUE) {
  1028.     continueStmt = new ContinueStmt ();
  1029.     continueStmt->enclosingStmt = enclosingStmtForContinue;
  1030.     if (enclosingStmtForContinue == NULL) {
  1031.       syntaxError ("This CONTINUE is not within a WHILE, DO, or FOR statement");
  1032.       continueStmt = NULL;
  1033.     } else {
  1034.       // Set "containsAnyContinues" in WHILE, FOR, or DO
  1035.       switch (enclosingStmtForContinue->op) {
  1036.         case WHILE_STMT:
  1037.           whileStmt = (WhileStmt *) (continueStmt->enclosingStmt);
  1038.           whileStmt->containsAnyContinues = 1;
  1039.           break;
  1040.         case FOR_STMT:
  1041.           forStmt = (ForStmt *) (continueStmt->enclosingStmt);
  1042.           forStmt->containsAnyContinues = 1;
  1043.           break;
  1044.         case DO_STMT:
  1045.           doStmt = (DoStmt *) (continueStmt->enclosingStmt);
  1046.           doStmt->containsAnyContinues = 1;
  1047.           break;
  1048.         default:
  1049.           printf ("enclosingStmtForContinue->op = %s\n",
  1050.                   symbolName (enclosingStmtForContinue->op));
  1051.           programLogicError ("Unkown op in fallsThru, continue stmt");
  1052.       }
  1053.     }
  1054.     scan ();  // CONTINUE
  1055.     return continueStmt;
  1056.   } else if (token.type == RETURN) {
  1057.     returnStmt = new ReturnStmt ();
  1058.     scan ();
  1059.     if (enclosingMethOrFunction == NULL) {
  1060.       programLogicError ("EnclosingMethOrFunction is NULL");
  1061.     }
  1062.     if (! gotVoidType (enclosingMethOrFunction->retType)) {
  1063.       returnStmt->expr = parseExpr ("Expecting a return-value after 'return'");
  1064.     }
  1065.     returnStmt->enclosingMethOrFunction = enclosingMethOrFunction;
  1066.     return returnStmt;
  1067.   } else if (token.type == THROW) {
  1068.     scan ();    // THROW
  1069.     throwStmt = new ThrowStmt ();
  1070.     throwStmt->id = mustHaveID ("Expecting ID after 'throw'");
  1071.     if (token.type == L_PAREN) {
  1072.       scan ();   // L_PAREN
  1073.       throwStmt->argList = parseArgList ();
  1074.     } else {
  1075.       syntaxError ("Expecting '( arglist )' after ID");
  1076.     }
  1077.     return throwStmt;
  1078.   } else if (token.type == FREE) {
  1079.       freeStmt = new FreeStmt ();
  1080.       scan ();     // FREE
  1081.       freeStmt->expr = parseExpr ("Expecting an expression after 'free'");
  1082.       return freeStmt;
  1083.   } else if (token.type == DEBUG) {
  1084.       debugStmt = new DebugStmt ();
  1085.       scan ();     // DEBUG
  1086.       return debugStmt;
  1087.   } else if (inFirstExpr (token)) {
  1088.     expr1 = parseExpr ("In assignment, call, or send statement");
  1089.     if (token.type == EQUAL) {
  1090.       scan ();
  1091.       expr2 = parseExpr ("In expression after '=' in assignment statement");
  1092.     } else {
  1093.       expr2 = NULL;
  1094.     }
  1095.     // printf ("expr1 = ");  pretty (expr1);
  1096.     // printf ("expr2 = ");  pretty (expr2);
  1097.     // printf ("\n");
  1098.     if (expr2 != NULL) {
  1099.       assignStmt = new AssignStmt ();
  1100.       assignStmt->positionAt (expr1);
  1101.       assignStmt->lvalue = expr1;
  1102.       assignStmt->expr = expr2;
  1103.       return assignStmt;
  1104.     } else if (expr1->op == CALL_EXPR) {
  1105.       callStmt = new CallStmt ();
  1106.       callStmt->positionAt (expr1);
  1107.       callStmt->expr = (CallExpr *) expr1;
  1108.       return callStmt;
  1109.     } else if ((expr1->op == SEND_EXPR) &&
  1110.                ((((SendExpr *) expr1)->kind == KEYWORD) ||
  1111.                 (((SendExpr *) expr1)->kind == NORMAL ))) {
  1112.       sendStmt = new SendStmt ();
  1113.       sendStmt->positionAt (expr1);
  1114.       sendStmt->expr = (SendExpr *) expr1;
  1115.       return sendStmt;
  1116.     } else {
  1117.       syntaxErrorWithToken (expr1->tokn,
  1118.                  "Unexpected expression when expecting a statement");
  1119.       return NULL;
  1120.     }
  1121.   } else {
  1122.     return NULL;
  1123.   }
  1124. }
  1125.  
  1126.  
  1127.  
  1128. // gotVoidType (type)
  1129. //
  1130. // Returns true iff this type is 'void'.
  1131. //
  1132. int gotVoidType (Type * type) {
  1133.   if (type == NULL) {
  1134.     programLogicError ("Type is NULL within gotVoidType()");
  1135.   }
  1136.   return (type->op == VOID_TYPE);
  1137. }
  1138.  
  1139.  
  1140.  
  1141. // parseParmList ()
  1142. //
  1143. // This routine parses a ParmList and returns a pointer to linked list of
  1144. // Parameter nodes (or NULL).
  1145. //   ParmList --> '(' ')'
  1146. //            --> '(' Decl { , Decl } ')'
  1147. //   Decl     --> ID { , ID } : Type
  1148. //
  1149. // If syntax errors, this routine may scan ZERO tokens.
  1150. //
  1151. Parameter * parseParmList () {
  1152.   Parameter * first, * last, * idListFirst, * idListLast, * parm;
  1153.   Type * type;
  1154.   first = last = NULL;
  1155.   if (token.type != L_PAREN) {
  1156.     syntaxError ("Expecting '(' in parameter list");
  1157.     return NULL;
  1158.   }
  1159.   scan ();    // L_PAREN
  1160.   while (token.type == ID) {
  1161.     // Pick up a list of ID's
  1162.     idListFirst = idListLast = NULL;
  1163.     while (token.type == ID) {
  1164.       parm = new Parameter ();
  1165.       parm->id = token.value.svalue;
  1166.       scan ();    // ID
  1167.       if (idListFirst == NULL) {
  1168.         idListFirst = parm;
  1169.       } else {
  1170.         idListLast->next = parm;
  1171.       }
  1172.       idListLast = parm;
  1173.       if (token.type != COMMA) {
  1174.         break;
  1175.       }
  1176.       scan ();     // COMMA
  1177.     }
  1178.     // Pick up a type
  1179.     mustHave (COLON, "Expecting ':' in 'parameterID: Type'");
  1180.     type = parseType ("Expecting a type after ':' in 'parameterID: Type'");
  1181.     // Now run through the ID's.  Add in the type and add to the growing parm list.
  1182.     while (idListFirst) {
  1183.       idListFirst->type = type;
  1184.       if (first == NULL) {
  1185.         first = idListFirst;
  1186.       } else {
  1187.         last->next = idListFirst;
  1188.       }
  1189.       last = idListFirst;
  1190.       idListFirst = (Parameter *) idListFirst->next;
  1191.     }
  1192.     last->next = NULL;
  1193.     // Check for COMMA or R_PAREN
  1194.     if (token.type == COMMA) {
  1195.       scan ();
  1196.     } else if (token.type == R_PAREN) {
  1197.       break;
  1198.     } else if (token.type == RETURNS) {
  1199.       syntaxError ("Expecting ')' to terminate parameter list");
  1200.       return first;
  1201.     }
  1202.   }
  1203.   mustHave (R_PAREN, "Expecting next ID or ')' in parameter list");
  1204.   return first;
  1205. }
  1206.  
  1207.  
  1208.  
  1209. // parseFunction (expectingID)
  1210. //
  1211. // This routine parses a Function and returns a pointer to a Function node.
  1212. //
  1213. Function * parseFunction (int expectingID) {
  1214.   Function * fun;
  1215.   fun = new Function ();
  1216.   if (token.type != FUNCTION) {
  1217.     programLogicError ("Already checked for 'function' keyword");
  1218.   }
  1219.   scan ();  // FUNCTION
  1220.   if (expectingID) {    // Normal function defn.
  1221.     if (token.type == ID) {
  1222.       fun->tokn = token;
  1223.       fun->id = token.value.svalue;
  1224.       scan ();    // ID
  1225.     } else {
  1226.       syntaxError ("Expecting ID after 'function'");
  1227.       fun->id = lookupAndAdd ("<missingIdSyntaxError>", ID);
  1228.     }
  1229.   } else {              // Closure
  1230.     if (token.type == ID) {
  1231.       syntaxError ("Not expecting ID after 'function' in closure");
  1232.       scan ();
  1233.     }
  1234.   }
  1235.   fun->parmList = parseParmList ();
  1236.   if (token.type == RETURNS) {
  1237.     scan ();
  1238.     fun->retType = parseType ("Expecting return type after RETURNS");
  1239.     if (gotVoidType (fun->retType)) {
  1240.       syntaxError ("Do not say 'returns void'; just leave it out");
  1241.     }
  1242.   } else if ((token.type == RETURN) &&
  1243.              (token2.type != END_FUNCTION)) {
  1244.     syntaxError ("Expecting RETURNS, not RETURN");
  1245.     scan ();
  1246.     fun->retType = parseType ("Expecting return type after RETURNS");
  1247.   } else {
  1248.     fun->retType = new VoidType ();
  1249.   }
  1250.   fun->locals = parseLocalVarDecls ();
  1251.   fun->stmts = parseStmtList (NULL,     // enclosingStmtForBreak
  1252.                               NULL,     // enclosingStmtForContinue
  1253.                               fun,      // enclosingMethOrFunction
  1254.                               0);
  1255.   mustHave (END_FUNCTION, "Expecting 'endFunction'");
  1256.   return fun;
  1257. }
  1258.  
  1259.  
  1260.  
  1261. // parseFunctionProtos ()
  1262. //
  1263. // This routine parses this syntax rule:
  1264. //    FunctionProtos --> functions { [ external ] FunProto }+//    FunProto       --> ID ParmList [ returns Type ]//
  1265. FunctionProto * parseFunctionProtos () {
  1266.   FunctionProto * first, * last, * funProto;
  1267.   first = last = NULL;
  1268.   if (token.type != FUNCTIONS) {
  1269.     programLogicError ("Already checked for 'functions' keyword");
  1270.   }
  1271.   scan ();   // FUNCTIONS
  1272.   while ((token.type == ID) || (token.type == EXTERNAL)) {
  1273.     funProto = new FunctionProto ();
  1274.     if (token.type == EXTERNAL) {
  1275.       scan ();
  1276.       funProto->isExternal = 1;
  1277.     }
  1278.     if (token.type == ID) {
  1279.       funProto->tokn = token;
  1280.       funProto->id = token.value.svalue;
  1281.       scan ();    // ID
  1282.     } else {
  1283.       syntaxError ("Expecting ID after 'external'");
  1284.       funProto->id = lookupAndAdd ("<missingIdSyntaxError>", ID);
  1285.     }
  1286.     funProto->parmList = parseParmList ();
  1287.     if (token.type == RETURNS) {
  1288.       scan ();
  1289.       funProto->retType = parseType ("Expecting return type after RETURNS");
  1290.       if (gotVoidType (funProto->retType)) {
  1291.         syntaxError ("Do not say 'returns void'; just leave it out");
  1292.       }
  1293.     } else if (token.type == RETURN) {
  1294.       syntaxError ("Expecting RETURNS, not RETURN");
  1295.       scan ();
  1296.       funProto->retType = parseType ("Expecting return type after RETURNS");
  1297.     } else {
  1298.       funProto->retType = new VoidType ();
  1299.     }
  1300.     if (first == NULL) {
  1301.       first = funProto;
  1302.     } else {
  1303.       last->next = funProto;
  1304.     }
  1305.     last = funProto;
  1306.   }
  1307.   return first;
  1308. }
  1309.  
  1310.  
  1311.  
  1312. // parseMethod ()
  1313. //
  1314. // This routine parses a Method and returns a pointer to a Method node.
  1315. //
  1316. Method * parseMethod () {
  1317.   Method * meth;
  1318.   MethodProto * methodProto;
  1319.  
  1320.   if (token.type != METHOD) {
  1321.     programLogicError ("Already checked for 'method' keyword");
  1322.   }
  1323.   scan ();   // METHOD
  1324.   meth = new Method ();
  1325.   methodProto = parseMethodProto ();
  1326.   meth->positionAt (methodProto);
  1327.   meth->kind = methodProto->kind;
  1328.   meth->selector = methodProto->selector;
  1329.   meth->parmList = methodProto-> parmList;
  1330.   meth->retType = methodProto-> retType;
  1331.   if (token.type == METHOD) {
  1332.     syntaxError ("Expecting method body");
  1333.     return meth;
  1334.   }
  1335.   if (token.type == END_BEHAVIOR) {
  1336.     syntaxError ("Expecting method body");
  1337.     return meth;
  1338.   }
  1339.   meth->locals = parseLocalVarDecls ();
  1340.   meth->stmts = parseStmtList (NULL,     // enclosingStmtForBreak
  1341.                                NULL,     // enclosingStmtForContinue
  1342.                                meth,     // enclosingMethOrFunction
  1343.                                0);
  1344.   mustHave (END_METHOD, "Expecting 'endMethod'");
  1345.   return meth;
  1346. }
  1347.  
  1348.  
  1349.  
  1350. // parseMethodProto ()
  1351. //
  1352. // This routine parses this syntax rule:
  1353. //    MethProto  --> ID ParmList [ returns Type ]//               --> infix OPERATOR '(' ID : Type ')' returns Type//               --> prefix OPERATOR '(' ')' returns Type//               --> { ID : '(' ID : Type ')' }+ [ returns Type ]
  1354. //
  1355. // It may scan ZERO tokens if syntax errors.
  1356. //
  1357. MethodProto * parseMethodProto () {
  1358.   MethodProto * methodProto;
  1359.   char * newSelector;
  1360.   Parameter * parm, * lastParm;
  1361.  
  1362.  
  1363.   // Parse a INFIX method prototype...
  1364.   if (token.type == INFIX) {
  1365.     scan ();
  1366.     methodProto = new MethodProto ();
  1367.     methodProto->kind = INFIX;
  1368.     if (token.type != OPERATOR) {
  1369.       syntaxError ("Expecting OPERATOR");
  1370.       methodProto->selector = lookupAndAdd ("<missingSelectorSyntaxError>", ID);
  1371.     } else {
  1372.       methodProto->selector = token.value.svalue;
  1373.       scan ();     // OPERATOR
  1374.     }
  1375.     methodProto->parmList = parseParmList ();
  1376.     if (methodProto->parmList == NULL) {
  1377.       syntaxError ("Expecting exactly one parameter in infix method prototype");
  1378.     } else if (methodProto->parmList->next != NULL) {
  1379.       syntaxError ("Expecting exactly one parameter in infix method prototype");
  1380.     }
  1381.     if (token.type == RETURNS) {
  1382.       scan ();
  1383.       methodProto->retType = parseType ("Expecting return type after RETURNS");
  1384.       if (gotVoidType (methodProto->retType)) {
  1385.         syntaxError ("Infix methods must return a value");
  1386.       }
  1387.     } else {
  1388.       syntaxError ("Expecting 'returns Type' for infix method prototype");
  1389.       methodProto->retType = new VoidType ();
  1390.     }
  1391.  
  1392.   // Parse a PREFIX method prototype...
  1393.   } else if (token.type == PREFIX) {
  1394.     scan ();
  1395.     methodProto = new MethodProto ();
  1396.     methodProto->kind = PREFIX;
  1397.     if (token.type != OPERATOR) {
  1398.       syntaxError ("Expecting OPERATOR");
  1399.       methodProto->selector = lookupAndAdd ("<missingSelectorSyntaxError>", ID);
  1400.     } else {
  1401.       methodProto->selector = lookupAndAdd (appendStrings (
  1402.                                 "_prefix_", token.value.svalue->chars, ""), OPERATOR);
  1403.       scan ();     // OPERATOR
  1404.     }
  1405.     mustHave (L_PAREN, "Expecting '()' after 'prefix OP' in method prototype");
  1406.     mustHave (R_PAREN, "Expecting '()' after 'prefix OP' in method prototype");
  1407.     if (token.type == RETURNS) {
  1408.       scan ();
  1409.       methodProto->retType = parseType ("Expecting return type after RETURNS");
  1410.       if (gotVoidType (methodProto->retType)) {
  1411.         syntaxError ("Prefix methods must return a value");
  1412.       }
  1413.     } else {
  1414.       syntaxError ("Expecting 'returns Type' for prefix method prototype");
  1415.       methodProto->retType = new VoidType ();
  1416.     }
  1417.  
  1418.   // Parse a NORMAL method prototype...
  1419.   } else if ((token.type == ID) && (token2.type == L_PAREN)) {
  1420.     methodProto = new MethodProto ();
  1421.     methodProto->selector = token.value.svalue;
  1422.     methodProto->kind = NORMAL;
  1423.     scan ();     // ID
  1424.     methodProto->parmList = parseParmList ();
  1425.     if (token.type == RETURNS) {
  1426.       scan ();
  1427.       methodProto->retType = parseType ("Expecting return type after RETURNS");
  1428.       if (gotVoidType (methodProto->retType)) {
  1429.         syntaxError ("Do not say 'returns void'; just leave it out");
  1430.       }
  1431.     } else if ((token.type == RETURN) &&
  1432.                (token2.type != END_METHOD)) {
  1433.       syntaxError ("Expecting RETURNS, not RETURN");
  1434.       scan ();
  1435.       methodProto->retType = parseType ("Expecting return type after RETURNS");
  1436.     } else {
  1437.       methodProto->retType = new VoidType ();
  1438.     }
  1439.  
  1440.   // Parse a KEYWORD method prototype...
  1441.   } else if ((token.type == ID) && (token2.type == COLON)) {
  1442.     methodProto = new MethodProto ();
  1443.     methodProto->kind = KEYWORD;
  1444.     newSelector = appendStrings (token.value.svalue->chars, ":", "");
  1445.     scan ();      // ID
  1446.     scan ();      // COLON
  1447.     mustHave (L_PAREN, "Expecting '(ID: Type)' in keyword method prototype");
  1448.     parm = new Parameter ();
  1449.     parm->id =  mustHaveID ("Expecting ID in '(ID: Type)'");
  1450.     mustHave (COLON, "Expecting ':' in '(ID: Type)'");
  1451.     parm->type = parseType ("Expecting type after ':' in '(ID: Type)'");
  1452.     mustHave (R_PAREN, "Expecting ')' in '(ID: Type)'");
  1453.     methodProto->parmList = parm;
  1454.     lastParm = parm;
  1455.     // Each iteration of this loop parses "ID: (ID: Type)"...
  1456.     while (1) {
  1457.       if ((token.type != ID) || (token2.type != COLON)) {
  1458.         break;
  1459.       }
  1460.       newSelector = appendStrings (newSelector, token.value.svalue->chars, ":");
  1461.       scan ();      // ID
  1462.       scan ();      // COLON
  1463.       mustHave (L_PAREN, "Expecting '(ID: Type)' in keyword method prototype");
  1464.       parm = new Parameter ();
  1465.       parm->id =  mustHaveID ("Expecting ID in '(ID: Type)'");
  1466.       mustHave (COLON, "Expecting : in '(ID: Type)'");
  1467.       parm->type = parseType ("Expecting type after ':' in '(ID: Type)'");
  1468.       mustHave (R_PAREN, "Expecting ')' in '(ID: Type)'");
  1469.       lastParm->next = parm;
  1470.       lastParm = parm;
  1471.     }
  1472.     methodProto->selector = lookupAndAdd (newSelector, ID);
  1473.     // Parse "returns Type"...
  1474.     if (token.type == RETURNS) {
  1475.       scan ();
  1476.       methodProto->retType = parseType ("Expecting return type after RETURNS");
  1477.       if (gotVoidType (methodProto->retType)) {
  1478.         syntaxError ("Do not say 'returns void'; just leave it out");
  1479.       }
  1480.     } else if ((token.type == RETURN) &&
  1481.                (token2.type != END_METHOD)) {
  1482.       syntaxError ("Expecting RETURNS, not RETURN");
  1483.       scan ();
  1484.       methodProto->retType = parseType ("Expecting return type after RETURNS");
  1485.     } else {
  1486.       methodProto->retType = new VoidType ();
  1487.     }
  1488.  
  1489.   // Deal with syntax errors...
  1490.   } else if (token.type == ID) {
  1491.     methodProto = new MethodProto ();
  1492.     syntaxError ("Expecting ParmList or ': (ID:Type)' in Method Prototype");
  1493.     methodProto->selector = lookupAndAdd ("<missingSelectorSyntaxError>", ID);
  1494.     methodProto->kind = NORMAL;
  1495.     methodProto->retType = new VoidType ();
  1496.   } else {
  1497.     methodProto = new MethodProto ();
  1498.     syntaxError ("Expecting a Method Prototype");
  1499.     methodProto->selector = lookupAndAdd ("<missingSelectorSyntaxError>", ID);
  1500.     methodProto->kind = NORMAL;
  1501.     methodProto->retType = new VoidType ();
  1502.   }
  1503.  
  1504.   return methodProto;
  1505. }
  1506.  
  1507.  
  1508.  
  1509. // parseHeader ()
  1510. //
  1511. // This routine parses:
  1512. //    HeaderFile   --> header ID//                       Uses//                       { Const |
  1513. //                         Errors |//                         VarDecls |//                         Enum |//                         TypeDef |//                         FunctionProtos |//                         Interface |//                         Class }//                     endHeader
  1514. //
  1515. Header * parseHeader () {
  1516.   Header * header;
  1517.   Global * newGlobals, * lastGlobal;
  1518.   ConstDecl * newConsts, * lastConst;
  1519.   ErrorDecl * newErrors, * lastError;
  1520.   TypeDef * typeDef, * lastTypeDef;
  1521.   FunctionProto * funProto, * lastFunProto;
  1522.   Interface * interface, * lastInterface;
  1523.   ClassDef * cl, * lastClass;
  1524.   int count;
  1525.  
  1526.   if (token.type != HEADER) {
  1527.     syntaxError ("Expecting 'header' at beginning of header file");
  1528.     return NULL;
  1529.   }
  1530.   scan ();    // HEADER
  1531.   header = new Header ();
  1532.  
  1533.   if (token.type == ID) {
  1534.     header->packageName = token.value.svalue;
  1535.     scan ();    // ID
  1536.   } else {
  1537.     syntaxError ("Expecting package name after 'header'");
  1538.     header->packageName = lookupAndAdd ("<missingPackageName>", ID);
  1539.   }
  1540.   header->uses = parseUses ();
  1541.   while (1) {
  1542.     switch (token.type) {
  1543.       case CONST:
  1544.         newConsts = parseConstDecls ();
  1545.         if (header->consts == NULL) {
  1546.           header->consts = newConsts;
  1547.         } else {
  1548.           lastConst = header->consts;
  1549.           while (lastConst->next != NULL) {
  1550.             lastConst = lastConst->next;
  1551.           }
  1552.           lastConst->next = newConsts;
  1553.         }
  1554.         break;
  1555.       case ERRORS:
  1556.         newErrors = parseErrorDecls ();
  1557.         if (header->errors == NULL) {
  1558.           header->errors = newErrors;
  1559.         } else {
  1560.           lastError = header->errors;
  1561.           while (lastError->next != NULL) {
  1562.             lastError = lastError->next;
  1563.           }
  1564.           lastError->next = newErrors;
  1565.         }
  1566.         break;
  1567.       case VAR:
  1568.         newGlobals = parseGlobalVarDecls ();
  1569.         if (header->globals == NULL) {
  1570.           header->globals = newGlobals;
  1571.         } else {
  1572.           lastGlobal = header->globals;
  1573.           while (lastGlobal->next != NULL) {
  1574.             lastGlobal = (Global *) lastGlobal->next;
  1575.           }
  1576.           lastGlobal->next = newGlobals;
  1577.         }
  1578.         break;
  1579.       case ENUM:
  1580.         newConsts = parseEnums ();
  1581.         if (header->consts == NULL) {
  1582.           header->consts = newConsts;
  1583.         } else {
  1584.           lastConst = header->consts;
  1585.           while (lastConst->next != NULL) {
  1586.             lastConst = lastConst->next;
  1587.           }
  1588.           lastConst->next = newConsts;
  1589.         }
  1590.         break;
  1591.       case TYPE:
  1592.         typeDef = parseTypeDefs ();
  1593.         if (header->typeDefs == NULL) {
  1594.           header->typeDefs = typeDef;
  1595.         } else {
  1596.           lastTypeDef = header->typeDefs;
  1597.           while (lastTypeDef->next != NULL) {
  1598.             lastTypeDef = lastTypeDef->next;
  1599.           }
  1600.           lastTypeDef->next = typeDef;
  1601.         }
  1602.         break;
  1603.       case FUNCTIONS:
  1604.         funProto = parseFunctionProtos ();
  1605.         if (header->functionProtos == NULL) {
  1606.           header->functionProtos = funProto;
  1607.         } else {
  1608.           lastFunProto = header->functionProtos;
  1609.           while (lastFunProto->next != NULL) {
  1610.             lastFunProto = lastFunProto->next;
  1611.           }
  1612.           lastFunProto->next = funProto;
  1613.         }
  1614.         break;
  1615.       case INTERFACE:
  1616.         interface = parseInterface ();
  1617.         if (header->interfaces == NULL) {
  1618.           header->interfaces = interface;
  1619.         } else {
  1620.           lastInterface = header->interfaces;
  1621.           while (lastInterface->next != NULL) {
  1622.             lastInterface = lastInterface->next;
  1623.           }
  1624.           lastInterface->next = interface;
  1625.         }
  1626.         break;
  1627.       case CLASS:
  1628.         cl = parseClass ();
  1629.         if (header->classes == NULL) {
  1630.           header->classes = cl;
  1631.         } else {
  1632.           lastClass = header->classes;
  1633.           while (lastClass->next != NULL) {
  1634.             lastClass = lastClass->next;
  1635.           }
  1636.           lastClass->next = cl;
  1637.         }
  1638.         break;
  1639.       case EOF:
  1640.         syntaxError ("Missing 'endHeader'");
  1641.         return header;
  1642.       case END_HEADER:
  1643.         scan ();
  1644.         if (token.type != EOF) {
  1645.           syntaxError ("There should be nothing more after 'endHeader'");
  1646.         }
  1647.         header->hashVal = hashVal;     // Based on token sequence up to now
  1648.         return header;
  1649.       default:
  1650.         if (token.type == BEHAVIOR) {
  1651.           syntaxError ("Behaviors must be placed in a CodeFile, not in a HeaderFile");
  1652.         } else {
  1653.           syntaxError ("Expecting CONST, ERRORS, VAR, ENUM, TYPE, FUNCTIONS, INTERFACE, CLASS, or END_HEADER in HeaderFile");
  1654.         }
  1655.         count = 0;
  1656.         while (1) {
  1657.           if (inHeaderSet ()) break;
  1658.           scan ();
  1659.           count++;
  1660.         }
  1661.         checkTokenSkipping (count);
  1662.     }
  1663.   }
  1664. }
  1665.  
  1666.  
  1667.  
  1668. // parseCode ()
  1669. //
  1670. // This routine parses:
  1671. //    CodeFile     --> code ID//                       { Const |//                         Errors |//                         VarDecls |//                         Enum |//                         TypeDef |//                         Function |//                         Interface |//                         Class |
  1672. //                         Behavior }//                     endCode
  1673. //
  1674. Code * parseCode () {
  1675.   Code * code;
  1676.   Global * newGlobals, * lastGlobal;
  1677.   ErrorDecl * newErrors, * lastError;
  1678.   ConstDecl * newConsts, * lastConst;
  1679.   TypeDef * typeDef, * lastTypeDef;
  1680.   Function * fun, * lastFun;
  1681.   Interface * interface, * lastInterface;
  1682.   ClassDef * cl, * lastClass;
  1683.   Behavior * behavior, * lastBehavior;
  1684.   int count;
  1685.  
  1686.   if (token.type != CODE) {
  1687.     syntaxError ("Expecting 'code' at beginning of code file");
  1688.     return NULL;
  1689.   }
  1690.   scan ();    // CODE
  1691.  
  1692.   code = new Code ();
  1693.  
  1694.   if (token.type == ID) {
  1695.     code->packageName = token.value.svalue;
  1696.     scan ();    // ID
  1697.   } else {
  1698.     syntaxError ("Expecting package name after 'code'");
  1699.     code->packageName = lookupAndAdd ("<missingPackageName>", ID);
  1700.   }
  1701.   while (1) {
  1702.     switch (token.type) {
  1703.       case CONST:
  1704.         newConsts = parseConstDecls ();
  1705.         if (code->consts == NULL) {
  1706.           code->consts = newConsts;
  1707.         } else {
  1708.           lastConst = code->consts;
  1709.           while (lastConst->next != NULL) {
  1710.             lastConst = lastConst->next;
  1711.           }
  1712.           lastConst->next = newConsts;
  1713.         }
  1714.         break;
  1715.       case ERRORS:
  1716.         newErrors = parseErrorDecls ();
  1717.         if (code->errors == NULL) {
  1718.           code->errors = newErrors;
  1719.         } else {
  1720.           lastError = code->errors;
  1721.           while (lastError->next != NULL) {
  1722.             lastError = lastError->next;
  1723.           }
  1724.           lastError->next = newErrors;
  1725.         }
  1726.         break;
  1727.         break;
  1728.       case VAR:
  1729.         newGlobals = parseGlobalVarDecls ();
  1730.         if (code->globals == NULL) {
  1731.           code->globals = newGlobals;
  1732.         } else {
  1733.           lastGlobal = code->globals;
  1734.           while (lastGlobal->next != NULL) {
  1735.             lastGlobal = (Global *) lastGlobal->next;
  1736.           }
  1737.           lastGlobal->next = newGlobals;
  1738.         }
  1739.         break;
  1740.       case ENUM:
  1741.         newConsts = parseEnums ();
  1742.         if (code->consts == NULL) {
  1743.           code->consts = newConsts;
  1744.         } else {
  1745.           lastConst = code->consts;
  1746.           while (lastConst->next != NULL) {
  1747.             lastConst = lastConst->next;
  1748.           }
  1749.           lastConst->next = newConsts;
  1750.         }
  1751.         break;
  1752.       case TYPE:
  1753.         typeDef = parseTypeDefs ();
  1754.         if (code->typeDefs == NULL) {
  1755.           code->typeDefs = typeDef;
  1756.         } else {
  1757.           lastTypeDef = code->typeDefs;
  1758.           while (lastTypeDef->next != NULL) {
  1759.             lastTypeDef = lastTypeDef->next;
  1760.           }
  1761.           lastTypeDef->next = typeDef;
  1762.         }
  1763.         break;
  1764.       case FUNCTION:
  1765.         fun = parseFunction (1);      //  Expecting ID = 1
  1766.         if (code->functions == NULL) {
  1767.           code->functions = fun;
  1768.         } else {
  1769.           lastFun = code->functions;
  1770.           while (lastFun->next != NULL) {
  1771.             lastFun = lastFun->next;
  1772.           }
  1773.           lastFun->next = fun;
  1774.         }
  1775.         break;
  1776.       case INTERFACE:
  1777.         interface = parseInterface ();
  1778.         if (code->interfaces == NULL) {
  1779.           code->interfaces = interface;
  1780.         } else {
  1781.           lastInterface = code->interfaces;
  1782.           while (lastInterface->next != NULL) {
  1783.             lastInterface = lastInterface->next;
  1784.           }
  1785.           lastInterface->next = interface;
  1786.         }
  1787.         break;
  1788.       case CLASS:
  1789.         cl = parseClass ();
  1790.         if (code->classes == NULL) {
  1791.           code->classes = cl;
  1792.         } else {
  1793.           lastClass = code->classes;
  1794.           while (lastClass->next != NULL) {
  1795.             lastClass = lastClass->next;
  1796.           }
  1797.           lastClass->next = cl;
  1798.         }
  1799.         break;
  1800.       case BEHAVIOR:
  1801.         behavior = parseBehavior ();
  1802.         if (code->behaviors == NULL) {
  1803.           code->behaviors = behavior;
  1804.         } else {
  1805.           lastBehavior = code->behaviors;
  1806.           while (lastBehavior->next != NULL) {
  1807.             lastBehavior = lastBehavior->next;
  1808.           }
  1809.           lastBehavior->next = behavior;
  1810.         }
  1811.         break;
  1812.       case EOF:
  1813.         syntaxError ("Missing 'endCode'");
  1814.         return code;
  1815.       case END_CODE:
  1816.         scan ();
  1817.         if (token.type != EOF) {
  1818.           syntaxError ("There should be nothing more after 'endCode'");
  1819.         }
  1820.         code->hashVal = hashVal;     // Based on token sequence up to now
  1821.         return code;
  1822.       default:
  1823.         syntaxError ("Expecting CONST, ERRORS, VAR, ENUM, TYPE, FUNCTION, INTERFACE, CLASS, BEHAVIOR, or END_CODE in CodeFile");
  1824.         count = 0;
  1825.         while (1) {
  1826.           if (inCodeSet ()) break;
  1827.           scan ();
  1828.           count++;
  1829.         }
  1830.         checkTokenSkipping (count);
  1831.     }
  1832.   }
  1833. }
  1834.  
  1835.  
  1836.  
  1837. // parseBehavior ()
  1838. //
  1839. // This routine parses:
  1840. //    Behavior     --> behavior ID//                       { Method }//                     endBehavior
  1841. //
  1842. Behavior * parseBehavior () {
  1843.   Behavior * behavior;
  1844.   Method * meth, * lastMeth;
  1845.   int count;
  1846.  
  1847.   if (token.type != BEHAVIOR) {
  1848.     programLogicError ("Already checked for behavior keyword");
  1849.   }
  1850.   scan ();    // BEHAVIOR
  1851.   behavior = new Behavior ();
  1852.   behavior->id = mustHaveID ("Expecting name of class after 'behavior' keyword");
  1853.   while (1) {
  1854.     switch (token.type) {
  1855.       case METHOD:
  1856.         meth = parseMethod ();
  1857.         if (behavior->methods == NULL) {
  1858.           behavior->methods = meth;
  1859.         } else {
  1860.           lastMeth->next = meth;
  1861.         }
  1862.         lastMeth = meth;
  1863.         break;
  1864.       case EOF:
  1865.         syntaxError ("Missing 'endBehavior'");
  1866.         return behavior;
  1867.       case END_BEHAVIOR:
  1868.         scan ();
  1869.         return behavior;
  1870.       default:
  1871.         syntaxError ("Expecting METHOD, END_CODE, or END_BEHAVIOR");
  1872.         count = 0;
  1873.         while (1) {
  1874.           if (token.type == METHOD) break;
  1875.           if (token.type == END_CODE) break;
  1876.           if (token.type == END_BEHAVIOR) break;
  1877.           if (token.type == EOF) break;
  1878.           scan ();
  1879.           count++;
  1880.         }
  1881.         checkTokenSkipping (count);
  1882.         if (token.type == END_CODE) return behavior;
  1883.     }
  1884.   }
  1885. }
  1886.  
  1887.  
  1888.  
  1889. // parseUses ()
  1890. //
  1891. // This routine parses the following:
  1892. //
  1893. //    Uses         --> [ uses OtherPackage { , OtherPackage } ]
  1894. ////    OtherPackage --> ID ID [ renaming Rename { , Rename } ]//
  1895. Uses * parseUses () {
  1896.   Uses * first, * last, * uses;
  1897.  
  1898.   if (token.type != USES) {
  1899.     return NULL;
  1900.   }
  1901.   first = last = NULL;
  1902.   scan ();     // USES
  1903.  
  1904.   //  Each iteration of this loop picks up another OtherPackage...
  1905.   while (1) {
  1906.     uses = new Uses ();
  1907.     if ((token.type == ID) || (token.type == STRING_CONST)) {
  1908.       uses->id = token.value.svalue;
  1909.       scan ();    // ID or STRING_CONST
  1910.     } else {
  1911.       syntaxError ("Expecting next package name in 'uses' clause");
  1912.       uses->id = lookupAndAdd ("<missingIdSyntaxError>", ID);
  1913.     }
  1914.     if (first) {
  1915.       last->next = uses;
  1916.     } else {
  1917.       first = uses;
  1918.     }
  1919.     last = uses;
  1920.     uses->renamings = parseRenamings ();
  1921.  
  1922.     // See if we have more and scan the comma
  1923.     if (token.type == COMMA) {
  1924.       scan ();       // COMMA
  1925.     } else if (token.type == ID) {
  1926.       syntaxError ("Expecting COMMA before next package name");
  1927.     } else {
  1928.       break;
  1929.     }
  1930.   }
  1931.   return first;
  1932. }
  1933.  
  1934.  
  1935.  
  1936. // parseRenamings ()
  1937. //
  1938. // This routine parses the following:
  1939. //
  1940. //                 --> ID [ renaming Rename { , Rename } ]//    //    Rename       --> ID to ID
  1941. //
  1942. Renaming * parseRenamings () {
  1943.   Renaming * firstRenaming, * lastRenaming, * renaming;
  1944.  
  1945.   if (token.type != RENAMING) {
  1946.     return NULL;
  1947.   }
  1948.   scan ();    // RENAMING
  1949.   // Each iteration of this loop picks up another Renaming...
  1950.   firstRenaming = lastRenaming = NULL;
  1951.   while (1) {
  1952.     renaming = new Renaming ();
  1953.     if (token.type == ID) {
  1954.       renaming->from = token.value.svalue;
  1955.       scan ();    // from-ID
  1956.       mustHave (TO, "Expecting 'to' in Renaming 'xxx to yyy'");
  1957.       renaming->to = mustHaveID ("Expecting ID2 in Renaming 'ID1 to ID2'");
  1958.     } else {
  1959.       syntaxError ("Expecting 'ID' in next renaming 'xxx to yyy'");
  1960.       scan ();
  1961.       if (token.type == TO) {
  1962.         scan ();
  1963.         scan ();
  1964.       }
  1965.       renaming->from = lookupAndAdd ("<missingIdSyntaxError>", ID);
  1966.       renaming->to = lookupAndAdd ("<missingIdSyntaxError>", ID);
  1967.     }
  1968.     if (firstRenaming) {
  1969.       lastRenaming->next = renaming;
  1970.     } else {
  1971.       firstRenaming = renaming;
  1972.     }
  1973.     lastRenaming = renaming;
  1974.     // See if we have more renamings
  1975.     if ( (token.type == COMMA) &&
  1976.          ((token3.type == COLON) || (token3.type == TO)) ) {
  1977.       scan ();       // COMMA
  1978.     } else if ((token2.type == TO) || (token2.type == COLON)) {
  1979.       syntaxError ("Expecting COMMA before next renaming clause");
  1980.     } else {
  1981.       break;
  1982.     }
  1983.   }
  1984.   return firstRenaming;
  1985. }
  1986.  
  1987.  
  1988. // pickupKeywordSelector ()
  1989. //
  1990. // This routine parses
  1991. //     { ID : }+
  1992. // It builds and return a selector.
  1993. //
  1994. String * pickupKeywordSelector () {
  1995.   char * newSelector;
  1996.  
  1997.   if ((token.type != ID) || (token2.type != COLON)) {
  1998.     syntaxError ("Expecting a keyword selector");
  1999.     return lookupAndAdd ("<missingIdSyntaxError>", ID);
  2000.   }
  2001.   newSelector = appendStrings (token.value.svalue->chars, ":", "");
  2002.   scan ();      // ID
  2003.   scan ();      // COLON
  2004.   while ((token.type == ID) && (token2.type == COLON)) {
  2005.     newSelector = appendStrings (newSelector, token.value.svalue->chars, ":");
  2006.     scan ();      // ID
  2007.     scan ();      // COLON
  2008.   }
  2009.   return lookupAndAdd (newSelector, ID);
  2010. }
  2011.  
  2012.  
  2013.  
  2014. // colonCount (char *) --> int
  2015. //
  2016. // This routine returns the number of colons in the given string.
  2017. //
  2018. int colonCount (char * str) {
  2019.   int i = 0;
  2020.   while (*str != '\0') {
  2021.     if (*str == ':') {
  2022.       i++;
  2023.     }
  2024.     str++;
  2025.   }
  2026.   return i;
  2027. }
  2028.  
  2029.  
  2030.  
  2031. // parseInterface ()
  2032. //
  2033. // This routine parses the following:
  2034. //    Interface    --> interface ID [ TypeParms ]//                       [ extends TypeInstanceList ]//                       [ messages { MethProto }+ ]//                     endInterface
  2035. //
  2036. Interface * parseInterface () {
  2037.   Interface * interface;
  2038.   MethodProto * methProto, * lastMethProto;
  2039.   int count;
  2040.   TypeArg * typeArg, * lastTypeArg;
  2041.  
  2042.   if (token.type != INTERFACE) {
  2043.     programLogicError ("Already checked for INTERFACE keyword");
  2044.   }
  2045.   scan ();   // INTERFACE
  2046.   interface = new Interface ();
  2047.   interface->id = mustHaveID ("Expecting interface name after 'interface'");
  2048.   // Pick up TypeParms...
  2049.   interface->typeParms = parseTypeParms ();
  2050.   // Pick up 'extends' clause...
  2051.   if (token.type == EXTENDS) {
  2052.     scan ();
  2053.     lastTypeArg = NULL;
  2054.     while (1) {
  2055.       typeArg = new TypeArg ();
  2056.       typeArg->type = parseNamedType ("Expecting an interface name after 'extends'");
  2057.       if (lastTypeArg == NULL) {
  2058.         interface->extends = typeArg;
  2059.       } else {
  2060.         lastTypeArg->next = typeArg;
  2061.       }
  2062.       lastTypeArg = typeArg;
  2063.       if (token.type != COMMA) {
  2064.         break;
  2065.       }
  2066.       scan ();
  2067.     }
  2068.   }
  2069.   // Pick up 'messages' clause...
  2070.   if (token.type == MESSAGES || token.type == METHODS) {
  2071.     if (token.type == METHODS) {
  2072.       syntaxError ("Expecting 'messages', not 'methods'");
  2073.     }
  2074.     scan ();
  2075.     lastMethProto = parseMethodProto ();
  2076.     interface->methodProtos = lastMethProto;
  2077.     while (1) {
  2078.       if ((token.type == INFIX) ||
  2079.           (token.type == PREFIX) ||
  2080.           ((token.type == ID) && (token2.type == L_PAREN)) ||
  2081.           ((token.type == ID) && (token2.type == COLON)) ) {
  2082.         methProto = parseMethodProto ();
  2083.         lastMethProto->next = methProto;
  2084.         lastMethProto = methProto;
  2085.       } else if (token.type == END_INTERFACE) {
  2086.         break;
  2087.       } else {
  2088.         syntaxError ("Expecting next message prototype or 'endInterface'");
  2089.         count = 0;
  2090.         while (1) {
  2091.           if (inHeaderSet ()) break;
  2092.           if (token.type == INFIX) break;
  2093.           if (token.type == PREFIX) break;
  2094.           if ((token.type == ID) && (token2.type == L_PAREN)) break;
  2095.           if ((token.type == ID) && (token2.type == COLON)) break;
  2096.           if (token.type == END_INTERFACE) break;
  2097.           scan ();
  2098.           count++;
  2099.         }
  2100.         checkTokenSkipping (count);
  2101.         if (inHeaderSet ()) break;
  2102.       }
  2103.     }
  2104.   }
  2105.   mustHave (END_INTERFACE, "Expecting endInterface");
  2106.   return interface;
  2107. }
  2108.  
  2109.  
  2110.  
  2111. // parseTypeParms ()
  2112. //
  2113. // This routine parses...
  2114. //                 --> [ TypeParms ]
  2115. //    TypeParms    --> '[' ID : Type { , ID : Type } ']'
  2116. //
  2117. // It returns a pointer to linked list of TypeParms (or NULL).
  2118. //
  2119. TypeParm * parseTypeParms () {
  2120.   TypeParm * newParm, * first, * last;
  2121.  
  2122.   if (token.type != L_BRACK) {
  2123.     return NULL;
  2124.   }
  2125.   scan ();    // L_BRACK
  2126.   newParm = new TypeParm ();
  2127.   newParm->id = mustHaveID ("Expecting 'ID: Type' after '['");
  2128.   mustHave (COLON, "Expecting ':' in 'ID: Type'");
  2129.   newParm->type = parseType ("Expecting type after ':' in 'ID: Type'");
  2130.   first = last = newParm;
  2131.   while (token.type == COMMA) {
  2132.     scan ();   // COMMA
  2133.     newParm = new TypeParm ();
  2134.     newParm->id = mustHaveID ("Expecting 'ID: Type' after '['");
  2135.     mustHave (COLON, "Expecting ':' in 'ID: Type'");
  2136.     newParm->type = parseType ("Expecting type after ':' in 'ID: Type'");
  2137.     last->next = newParm;
  2138.     last = newParm;
  2139.   }
  2140.   if (token.type == R_BRACK) {
  2141.     scan ();      // R_BRACK
  2142.   } else {
  2143.     syntaxError ("Expecting ',' or ']' in type parameter list");
  2144.     if (token2.type == R_BRACK) {
  2145.       scan ();    // Junk
  2146.       scan ();    // R_BRACK
  2147.     }
  2148.   }
  2149.   return first;
  2150. }
  2151.  
  2152.  
  2153.  
  2154. // parseClass ()
  2155. //
  2156. // This routine parses the following:
  2157. //    Class        --> class ID [ TypeParms ]//                       [ implements TypeInstanceList ]//                         superclass TypeInstance//                       [ fields { Decl }+ ]//                       [ methods { MethProto }+ ]//                     endClass
  2158. //
  2159. ClassDef * parseClass () {
  2160.   ClassDef * cl;
  2161.   MethodProto * methProto, * lastMethProto;
  2162.   int count, gotObject;
  2163.   TypeArg * typeArg, * lastTypeArg;
  2164.  
  2165.   if (token.type != CLASS) {
  2166.     programLogicError ("Already checked for CLASS keyword");
  2167.   }
  2168.   scan ();   // CLASS
  2169.   cl = new ClassDef ();
  2170.   cl->id = mustHaveID ("Expecting class name after 'class'");
  2171.   if (cl->id == stringObject) {
  2172.     gotObject = 1;
  2173.   } else {
  2174.     gotObject = 0;
  2175.   }
  2176.   // Pick up TypeParms...
  2177.   cl->typeParms = parseTypeParms ();
  2178.   if (gotObject && cl->typeParms) {
  2179.     syntaxError ("Not expecting typeParms in class Object");
  2180.   }
  2181.  
  2182.   // Pick up 'implements' clause...
  2183.   while ((token.type != IMPLEMENTS) &&
  2184.       (token.type != SUPER_CLASS) &&
  2185.       (token.type != FIELDS) &&
  2186.       (token.type != MESSAGES) &&
  2187.       (token.type != METHODS) &&
  2188.       (token.type != END_CLASS) &&
  2189.       (token.type != EOF)) {
  2190.     syntaxError ("Expecting IMPLEMENTS, SUPER_CLASS, FIELDS, METHODS, or END_CLASS in a class definition");
  2191.     scan ();
  2192.   }
  2193.   if (token.type == IMPLEMENTS) {
  2194.     scan ();
  2195.     lastTypeArg = NULL;
  2196.     while (1) {
  2197.       typeArg = new TypeArg ();
  2198.       typeArg->type = parseNamedType ("Expecting an interface name after 'implements'");
  2199.       if (lastTypeArg == NULL) {
  2200.         cl->implements = typeArg;
  2201.       } else {
  2202.         lastTypeArg->next = typeArg;
  2203.       }
  2204.       lastTypeArg = typeArg;
  2205.       if (token.type != COMMA) {
  2206.         break;
  2207.       }
  2208.       scan ();
  2209.     }
  2210.   }
  2211.  
  2212.   // Pick up the superclass clause...
  2213.   while ((token.type != SUPER_CLASS) &&
  2214.       (token.type != FIELDS) &&
  2215.       (token.type != MESSAGES) &&
  2216.       (token.type != METHODS) &&
  2217.       (token.type != END_CLASS) &&
  2218.       (token.type != EOF)) {
  2219.     syntaxError ("Expecting SUPER_CLASS, FIELDS, METHODS, or END_CLASS in a class definition");
  2220.     scan ();
  2221.   }
  2222.   if (token.type == SUPER_CLASS) {
  2223.     scan ();
  2224.     cl->superclass = parseNamedType ("Expecting a class name after 'superclass'");
  2225.     if (gotObject) {
  2226.       syntaxError ("Not expecting 'superclass...' in class Object");
  2227.     }
  2228.   } else {
  2229.     if (! gotObject) {
  2230.       syntaxError ("Expecting 'superclass...'; all classes except 'Object' must have a single superclass");
  2231.     }
  2232.   }
  2233.  
  2234.   // Check for common errors...
  2235.   if (token.type == IMPLEMENTS) {
  2236.     syntaxError ("The 'implements' clause should come before the 'superclass' clause");
  2237.   }
  2238.  
  2239.   // Pick up 'fields' clause...
  2240.   while ((token.type != FIELDS) &&
  2241.       (token.type != MESSAGES) &&
  2242.       (token.type != METHODS) &&
  2243.       (token.type != END_CLASS) &&
  2244.       (token.type != EOF)) {
  2245.     syntaxError ("Expecting FIELDS, METHODS, or END_CLASS in a class definition");
  2246.     scan ();
  2247.   }
  2248.   if (token.type == FIELDS) {
  2249.     scan ();
  2250.     cl->fields = parseClassFields ();
  2251.   }
  2252.  
  2253.   // Pick up 'methods' clause...
  2254.   while ((token.type != METHODS) &&
  2255.       (token.type != MESSAGES) &&
  2256.       (token.type != END_CLASS) &&
  2257.       (token.type != EOF)) {
  2258.     syntaxError ("Expecting METHODS or END_CLASS in a class definition");
  2259.     scan ();
  2260.   }
  2261.   if (token.type == METHODS || token.type == MESSAGES) {
  2262.     if (token.type == MESSAGES) {
  2263.       syntaxError ("Use METHODS, not MESSAGES");
  2264.     }
  2265.     scan ();
  2266.     lastMethProto = parseMethodProto ();
  2267.     cl->methodProtos = lastMethProto;
  2268.     while (1) {
  2269.       if ((token.type == INFIX) ||
  2270.           (token.type == PREFIX) ||
  2271.           ((token.type == ID) && (token2.type == L_PAREN)) ||
  2272.           ((token.type == ID) && (token2.type == COLON)) ) {
  2273.         methProto = parseMethodProto ();
  2274.         lastMethProto->next = methProto;
  2275.         lastMethProto = methProto;
  2276.       } else if (token.type == END_CLASS) {
  2277.         break;
  2278.       } else {
  2279.         if (token.type == METHOD) {
  2280.           syntaxError ("Methods must be placed in a 'behavior', not in the class specification");
  2281.         } else {
  2282.           syntaxError ("Expecting next method prototype or 'endClass'");
  2283.         }
  2284.         count = 0;
  2285.         while (1) {
  2286.           if (inHeaderSet ()) break;
  2287.           if (token.type == INFIX) break;
  2288.           if (token.type == PREFIX) break;
  2289.           if ((token.type == ID) && (token2.type == L_PAREN)) break;
  2290.           if ((token.type == ID) && (token2.type == COLON)) break;
  2291.           if (token.type == END_CLASS) break;
  2292.           scan ();
  2293.           count++;
  2294.         }
  2295.         checkTokenSkipping (count);
  2296.         if (inHeaderSet ()) break;
  2297.       }
  2298.     }
  2299.   }
  2300.   mustHave (END_CLASS, "Expecting END_CLASS in a class definition");
  2301.   return cl;
  2302. }
  2303.  
  2304.  
  2305.  
  2306. // parseType (errorMsg)
  2307. //
  2308. // This routine parses a Type and returns a pointer to a Type node.  If problems,
  2309. // it prints the 'msg' and returns a pointer to a VoidType.
  2310. //
  2311. // If syntax errors occur, IT MAY SCAN ZERO TOKENS.
  2312. //
  2313. Type * parseType (char * errorMsg) {
  2314.   Type * type;
  2315.   PtrType * ptrType;
  2316.   RecordType * recordType;
  2317.   ArrayType * arrayType;
  2318.   Token tokenForPos;
  2319.  
  2320.   // If the current token is wrong, try just skipping it.
  2321.   if (!inFirstType (token) && inFirstType (token2)) {
  2322.     syntaxError (errorMsg);
  2323.     scan ();
  2324.   }
  2325.  
  2326.   switch (token.type) {
  2327.   
  2328.     case INT:
  2329.       type = new IntType ();
  2330.       scan ();
  2331.       return type;
  2332.   
  2333.     case DOUBLE:
  2334.       type = new DoubleType ();
  2335.       scan ();
  2336.       return type;
  2337.   
  2338.     case CHAR:
  2339.       type = new CharType ();
  2340.       scan ();
  2341.       return type;
  2342.   
  2343.     case BOOL:
  2344.       type = new BoolType ();
  2345.       scan ();
  2346.       return type;
  2347.   
  2348.     case VOID:
  2349.       type = new VoidType ();
  2350.       scan ();
  2351.       return type;
  2352.   
  2353.     case TYPE_OF_NULL:
  2354.       type = new TypeOfNullType ();
  2355.       scan ();
  2356.       return type;
  2357.    
  2358.     case ANY_TYPE:
  2359.       type = new AnyType ();
  2360.       scan ();
  2361.       return type;
  2362.  
  2363.     case PTR:
  2364.       ptrType = new PtrType ();
  2365.       scan ();
  2366.       mustHave (TO, "Expecting 'to' in 'ptr to Type'");
  2367.       ptrType->baseType = parseType ("Expecting type after 'to' in 'ptr to Type'");
  2368.       return ptrType;
  2369.   
  2370.     case ARRAY:
  2371.       tokenForPos = token;
  2372.       scan ();    // ARRAY
  2373.       if (token.type == L_BRACK) {
  2374.         scan ();
  2375.         return parseArrayType (tokenForPos);
  2376.       } else {
  2377.  
  2378.         // In the old syntax "[*]" was not optional; now it is optional...
  2379.         // syntaxError ("Expecting '[' in 'array [...] of Type'");
  2380.         // scanToFollowType ();
  2381.         // arrayType = new ArrayType ();
  2382.         // arrayType->positionAtToken (tokenForPos);
  2383.         // arrayType->baseType = new VoidType ();
  2384.         // return arrayType;
  2385.  
  2386.         arrayType = new ArrayType ();
  2387.         arrayType->positionAtToken (tokenForPos);
  2388.         if (token.type == OF) {
  2389.           scan ();
  2390.         } else {
  2391.           syntaxError ("Expecting '[' or 'of' in 'array [...] of Type'");
  2392.           scanToFollowType ();
  2393.           arrayType->baseType = new VoidType ();
  2394.           return arrayType;
  2395.         }
  2396.         arrayType->baseType = parseType ("Expecting base type in 'array of BaseType'");
  2397.         return arrayType;
  2398.       }
  2399.   
  2400.     case RECORD:
  2401.       recordType = new RecordType ();
  2402.       scan ();
  2403.       recordType->fields = parseRecordFieldList ();
  2404.       return recordType;
  2405.   
  2406.     case FUNCTION:
  2407.       return parseFunctionType ();
  2408.   
  2409.     case ID:
  2410.       return parseNamedType ("Program Logic Error: only prints error if an ID is not seen");
  2411.   
  2412.     default:
  2413.       syntaxError (errorMsg);
  2414.       type = new VoidType ();
  2415.       return type;
  2416.   }
  2417.   return new VoidType ();
  2418. }
  2419.  
  2420.  
  2421.  
  2422. // parseRecordFieldList ()
  2423. //
  2424. // This routine parses
  2425. //    { Decl }+ endRecord
  2426. // and returns a pointer to linked list of RecordFields.  If problems, it
  2427. // may return NULL.  It may scan zero tokens.
  2428. //
  2429. RecordField * parseRecordFieldList () {
  2430.   RecordField * first, * last, * idListFirst, * idListLast, * field;
  2431.   Type * type;
  2432.   first = last = NULL;
  2433.   while (token.type == ID) {
  2434.     // Pick up a list of ID's
  2435.     idListFirst = idListLast = NULL;
  2436.     while (token.type == ID) {
  2437.       field = new RecordField ();
  2438.       field->id = token.value.svalue;
  2439.       scan ();    // ID
  2440.       if (idListFirst == NULL) {
  2441.         idListFirst = field;
  2442.       } else {
  2443.         idListLast->next = field;
  2444.       }
  2445.       idListLast = field;
  2446.       if (token.type != COMMA) {
  2447.         break;
  2448.       }
  2449.       scan ();     // COMMA
  2450.     }
  2451.     // Pick up a type
  2452.     mustHave (COLON, "Expecting ':' in 'fieldID: Type'");
  2453.     type = parseType ("Expecting type after ':' in 'fieldID: Type'");
  2454.     // Now run through the ID's.  Add in the type and add to the growing field list.
  2455.     while (idListFirst) {
  2456.       idListFirst->type = type;
  2457.       if (first == NULL) {
  2458.         first = idListFirst;
  2459.       } else {
  2460.         last->next = idListFirst;
  2461.       }
  2462.       last = idListFirst;
  2463.       idListFirst = (RecordField *) idListFirst->next;
  2464.     }
  2465.     last->next = NULL;
  2466.   }
  2467.   mustHave (END_RECORD, "Expecting next field or 'endRecord' in record type");
  2468.   if (first == NULL) {
  2469.     syntaxError ("Must have at least one field in a record type");
  2470.   }
  2471.   return first;
  2472. }
  2473.  
  2474.  
  2475.  
  2476. // parseFunctionType ()
  2477. //
  2478. // This routine parses
  2479. //    function '(' [ Type { , Type } ] ')' [ returns Type ]
  2480. // and returns a FunctionType.  It will scan at least one token.
  2481. //
  2482. FunctionType * parseFunctionType () {
  2483.   FunctionType * functionType;
  2484.   TypeArg * typeArg, * last;
  2485.   functionType = new FunctionType ();
  2486.   scan ();     // FUNCTION keyword
  2487.   mustHave (L_PAREN, "Expecting '(Type, Type, ...)' after 'function' in function type");
  2488.   if (token.type != R_PAREN) {
  2489.     last = NULL;
  2490.     while (1) {
  2491.       typeArg = new TypeArg ();
  2492.       typeArg->type = parseType ("Expecting next type in 'function (Type, Type, ...)'");
  2493.       if (last == NULL) {
  2494.         functionType->parmTypes = typeArg;
  2495.       } else {
  2496.         last->next = typeArg;
  2497.       }
  2498.       last = typeArg;
  2499.       if (token.type != COMMA) {
  2500.         break;
  2501.       }
  2502.       scan ();
  2503.     }
  2504.   }
  2505.   if (token.type == COLON) {
  2506.     mustHave (R_PAREN, "Parameter names are not allowed in function types");
  2507.   } else {
  2508.     mustHave (R_PAREN, "Expecting ',' or ')' in parameter type list");
  2509.   }
  2510.   if (token.type == RETURNS) {
  2511.     scan ();
  2512.     functionType->retType = parseType ("Expecting return type after RETURNS");
  2513.   // A common error is to use 'return' instead of 'returns', but we
  2514.   // cannot do a special check for this error.  Consider
  2515.   //      if x isKindOf ptr to function (int)
  2516.   //        return 123
  2517.   //      else
  2518.   //        return 456
  2519.   //      endIf
  2520.   // } else if ((token.type == RETURN) &&
  2521.   //            (token2.type != END_FUNCTION)) {
  2522.   //   syntaxError ("Expecting RETURNS, not RETURN");
  2523.   //   scan ();
  2524.   //   functionType->retType = parseType ("Expecting return type after RETURNS");
  2525.     if (gotVoidType (functionType->retType)) {
  2526.       syntaxError ("Do not say 'returns void'; just leave it out");
  2527.     }
  2528.   } else {
  2529.     functionType->retType = new VoidType ();
  2530.   }
  2531.   return functionType;
  2532. }
  2533.  
  2534.  
  2535.  
  2536. // parseNamedType (errorMsg)
  2537. //
  2538. // This routine parses
  2539. //    ID [ '[' Type { , Type } ']' ]
  2540. // and returns a NamedType.  It may scan zero tokens, if there are errors.
  2541. //
  2542. NamedType * parseNamedType (char * errorMsg) {
  2543.   TypeArg * typeArg, * last;
  2544.   NamedType * namedType;
  2545.   namedType = new NamedType ();
  2546.   namedType->id = mustHaveID (errorMsg);
  2547.   if (token.type == L_BRACK) {
  2548.     scan ();    // L_BRACK
  2549.     last = NULL;
  2550.     while (1) {
  2551.       typeArg = new TypeArg ();
  2552.       typeArg->type = parseType ("Expecting next type in parameterized type 'ID[Type,Type,...]'");
  2553.       if (last == NULL) {
  2554.         namedType->typeArgs = typeArg;
  2555.       } else {
  2556.         last->next = typeArg;
  2557.       }
  2558.       last = typeArg;
  2559.       if (token.type != COMMA) {
  2560.         break;
  2561.       }
  2562.       scan ();   // COMMA
  2563.     }
  2564.     mustHave (R_BRACK, "Expecting ',' or ']' in parameter type list");
  2565.   }
  2566.   return namedType;
  2567. }
  2568.  
  2569.  
  2570.  
  2571. // parseArrayType (tokenForPos)
  2572. //
  2573. // This routine parses according to this syntax:
  2574. //    ( '*' | Expr ) { , ( '*' | Expr ) } ']' of Type
  2575. // and returns an ArrayType.  It calls itself recursively; Each invocation
  2576. // will pick up one sizeExpression and will allocate one ArrayType node.
  2577. //
  2578. // It positions the ArrayType node on the "tokenForPos".
  2579. //
  2580. ArrayType * parseArrayType (Token tokenForPos) {
  2581.   ArrayType * arrayType;
  2582.   arrayType = new ArrayType ();
  2583.   arrayType->positionAtToken (tokenForPos);
  2584.   arrayType->baseType = new VoidType ();
  2585.   if ((token.type == OPERATOR) && (token.value.svalue == stringStar)) {
  2586.     scan ();    // implicitly set arrayType->sizeExpr to NULL
  2587.   } else if (inFirstExpr (token)) {
  2588.     arrayType->sizeExpr = parseExpr ("Expecting a size expression");
  2589.   } else {
  2590.     syntaxError ("Expecting Expr or '*' after '[' or ',' in 'array [...] of Type'");
  2591.     scanToFollowType ();
  2592.     return arrayType;
  2593.   }
  2594.   if (token.type == R_BRACK) {
  2595.     scan ();
  2596.     if (token.type == OF) {
  2597.       scan ();
  2598.     } else {
  2599.       syntaxError ("Expecting 'of' in 'array [...] of Type'");
  2600.       scanToFollowType ();
  2601.       return arrayType;
  2602.     }
  2603.     arrayType->baseType = parseType ("Expecting base type in 'array [...] of BaseType'");
  2604.     return arrayType;
  2605.   } else if (token.type == COMMA) {
  2606.     scan ();
  2607.     arrayType->baseType = parseArrayType (tokenForPos);
  2608.     return arrayType;
  2609.   } else {
  2610.     syntaxError ("Expecting ']' or ',' in 'array [...] of Type'");
  2611.     scanToFollowType ();
  2612.     return arrayType;
  2613.   }
  2614. }
  2615.  
  2616.  
  2617.  
  2618. /*----------  Here is the parsing precedence table.  All are left-associative.  ----------
  2619.  
  2620. 1:   Keyword messages
  2621.  
  2622. 2:   Other Infix
  2623.  
  2624. 3:   |
  2625.  
  2626. 4:   ^
  2627.  
  2628. 5:   &
  2629.  
  2630. 6:   ||
  2631.  
  2632. 7:   ^^   <--- Boolean X-OR was eliminated, since it is the same as !=
  2633.  
  2634. 8:   &&
  2635.  
  2636. 9:   ==  !=
  2637.  
  2638. 10:  <  <=  >  >=
  2639.  
  2640. 11:  <<  >>  >>>
  2641.  
  2642. 12:  +  -
  2643.  
  2644. 13:  *  /  %
  2645.  
  2646. 15:  All Prefix Operators
  2647.  
  2648. 16:  x.m()  x.f  a[...]  special(asPtr2,asInt,arraySize,isInstOf,isKindOf)
  2649.  
  2650. 17:  (expr)  constants  closure  x  foo()  new  alloc  sizeOf
  2651.  
  2652. ----------*/
  2653.  
  2654.  
  2655.  
  2656. // parseExpr (errorMsg)
  2657. //
  2658. // This routine parses the grammar rule:
  2659. //    Expr  -->  Expr1
  2660. //
  2661. // This routine never returns NULL, even if there are parsing errors.
  2662. // This routine may scan ZERO tokens.
  2663. //
  2664. Expression * parseExpr (char * errorMsg) {
  2665.  
  2666.   // If the current token is wrong, try just skipping it.
  2667.   if (!inFirstExpr (token) && inFirstExpr (token2)) {
  2668.     syntaxError (errorMsg);
  2669.     scan ();
  2670.   }
  2671.  
  2672.   return parseExpr1 (errorMsg);
  2673. }
  2674.  
  2675.  
  2676.  
  2677. // parseExpr0 (errorMsg)
  2678. //
  2679. // This routine parses the grammar rule:
  2680. //    Expr  -->  Expr2
  2681. //
  2682. // It has basically the same behavior as "parseExpr", except that keyword messages
  2683. // (which are handled in parseExpr1) are not recognized unless they are in
  2684. // parentheses.  This routine is used in parsing VarDecls (instead of parseExpr),
  2685. // since we have a problem with keyword expressions being confused with additional
  2686. // declarations.
  2687. //
  2688. // Consider
  2689. //    var  x: T = a at: b
  2690. // and
  2691. //    var x: T = a
  2692. //        y: T ...
  2693. // In each case, we have:
  2694. //    VAR ID : Type = ID ID : ...
  2695. // Since it is impossible to distinguish these two rather different interpretations,
  2696. // we needed to do something.  The following changes to the grammar were
  2697. // considered and ruled out.
  2698. //     (1)   var x: T = a at: b;
  2699. //               y: T = ...;
  2700. //     (2)   var x: T = a at: b,
  2701. //               y: T = ...
  2702. //     (3)   var x: T = a at: b
  2703. //               y: T = ...
  2704. //           endVar
  2705. //     (4)   var x: T = a at: b
  2706. //               y: T = ...
  2707. //           do...
  2708. // By using parseExpr0, the user will be required to insert something (namely,
  2709. // parentheses) only for this particular problem case:
  2710. //     var x: T = a + 1
  2711. //         y: T = (a at: b)
  2712. //         z: T = c
  2713. //
  2714. Expression * parseExpr0 (char * errorMsg) {
  2715.  
  2716.   // If the current token is wrong, try just skipping it.
  2717.   if (!inFirstExpr (token) && inFirstExpr (token2)) {
  2718.     syntaxError (errorMsg);
  2719.     scan ();
  2720.   }
  2721.  
  2722.   return parseExpr2 (errorMsg);
  2723. }
  2724.  
  2725.  
  2726.  
  2727. // parseExpr1 (errorMsg)
  2728. //
  2729. // This routine parses the grammar rule:
  2730. //    Expr1  -->  Expr2 { ID ':' Expr2 }*            // SendExpr
  2731. // For example:
  2732. //    x at: y put: z
  2733. //
  2734. // This routine builds up a string such as "at:put:" and (by calling "lookupAndAdd")
  2735. // enters it in the string table as an ID.
  2736. //
  2737. Expression * parseExpr1 (char * errorMsg) {
  2738.   Expression * a;
  2739.   SendExpr * sendExpr;
  2740.   Argument * arg, * lastArg;
  2741.   char * newSelector;
  2742.  
  2743.   a = parseExpr2 (errorMsg);
  2744.   if ((token.type != ID) || (token2.type != COLON)) {
  2745.     return a;
  2746.   }
  2747.   sendExpr = new SendExpr ();
  2748.   newSelector = appendStrings (token.value.svalue->chars, ":", "");
  2749.   sendExpr->kind = KEYWORD;
  2750.   scan ();      // ID
  2751.   scan ();      // COLON
  2752.   sendExpr->receiver = a;
  2753.   arg = new Argument ();
  2754.   arg->expr = parseExpr2 ("Expecting first argument expression after ':'");
  2755.   sendExpr->argList = arg;
  2756.   lastArg = arg;
  2757.   while (1) {
  2758.     if ((token.type != ID) || (token2.type != COLON)) {
  2759.       sendExpr->selector = lookupAndAdd (newSelector, ID);
  2760.       return sendExpr;
  2761.     }
  2762.     newSelector = appendStrings (newSelector, token.value.svalue->chars, ":");
  2763.     arg = new Argument ();
  2764.     scan ();      // ID
  2765.     scan ();      // COLON
  2766.     arg->expr = parseExpr2 ("Expecting next argument expression after ':'");
  2767.     lastArg->next = arg;
  2768.     lastArg = arg;
  2769.   }
  2770. }
  2771.  
  2772.  
  2773.  
  2774. // parseExpr2 (errorMsg)
  2775. //
  2776. // This routine parses the grammar rule:
  2777. //    Expr2  -->  Expr3 { OPERATOR Expr3 }            // SendExpr (INFIX)
  2778. //
  2779. Expression * parseExpr2 (char * errorMsg) {
  2780.   Expression * a;
  2781.   SendExpr * sendExpr;
  2782.   Argument * arg;
  2783.  
  2784.   a = parseExpr3 (errorMsg);
  2785.   while (1) {
  2786.     if ((token.type == OPERATOR) &&
  2787.        (token.value.svalue != stringBarBar) &&
  2788.        (token.value.svalue != stringAmpAmp) &&
  2789.        (token.value.svalue != stringBar) &&
  2790.        (token.value.svalue != stringCaret) &&
  2791.        (token.value.svalue != stringAmp) &&
  2792.        (token.value.svalue != stringEqualEqual) &&
  2793.        (token.value.svalue != stringNotEqual) &&
  2794.        (token.value.svalue != stringLess) &&
  2795.        (token.value.svalue != stringLessEqual) &&
  2796.        (token.value.svalue != stringGreater) &&
  2797.        (token.value.svalue != stringGreaterEqual) &&
  2798.        (token.value.svalue != stringLessLess) &&
  2799.        (token.value.svalue != stringGreaterGreater) &&
  2800.        (token.value.svalue != stringGreaterGreaterGreater) &&
  2801.        (token.value.svalue != stringPlus) &&
  2802.        (token.value.svalue != stringMinus) &&
  2803.        (token.value.svalue != stringStar) &&
  2804.        (token.value.svalue != stringSlash) &&
  2805.        (token.value.svalue != stringPercent)
  2806.       ) {
  2807.       sendExpr = new SendExpr ();
  2808.       sendExpr->selector = token.value.svalue;
  2809.       sendExpr->kind = INFIX;
  2810.       scan ();
  2811.       sendExpr->receiver = a;
  2812.       arg = new Argument ();
  2813.       arg->expr = parseExpr3 (errorMsg);
  2814.       sendExpr->argList = arg;
  2815.       a = sendExpr;
  2816.     } else {
  2817.       return a;
  2818.     }
  2819.   }
  2820. }
  2821.  
  2822.  
  2823.  
  2824. // parseExpr3 (errorMsg)
  2825. //
  2826. // This routine parses the grammar rule:
  2827. //    Expr3  -->  Expr5 { '||' Expr5 }        // SendExpr (INFIX)
  2828. //
  2829. Expression * parseExpr3 (char * errorMsg) {
  2830.   Expression * a;
  2831.   SendExpr * sendExpr;
  2832.   Argument * arg;
  2833.  
  2834.   a = parseExpr5 (errorMsg);
  2835.   while (1) {
  2836.     if ((token.type == OPERATOR) && (
  2837.            (token.value.svalue == stringBarBar)
  2838.                                      )) {
  2839.       sendExpr = new SendExpr ();
  2840.       sendExpr->selector = token.value.svalue;
  2841.       sendExpr->kind = INFIX;
  2842.       scan ();
  2843.       sendExpr->receiver = a;
  2844.       arg = new Argument ();
  2845.       arg->expr = parseExpr5 (errorMsg);
  2846.       sendExpr->argList = arg;
  2847.       a = sendExpr;
  2848.     } else {
  2849.       return a;
  2850.     }
  2851.   }
  2852. }
  2853.  
  2854.  
  2855.  
  2856. // parseExpr5 (errorMsg)
  2857. //
  2858. // This routine parses the grammar rule:
  2859. //    Expr5  -->  Expr6 { '&&' Expr6 }           // SendExpr (INFIX)
  2860. //
  2861. Expression * parseExpr5 (char * errorMsg) {
  2862.   Expression * a;
  2863.   SendExpr * sendExpr;
  2864.   Argument * arg;
  2865.  
  2866.   a = parseExpr6 (errorMsg);
  2867.   while (1) {
  2868.     if ((token.type == OPERATOR) && (
  2869.            (token.value.svalue == stringAmpAmp)
  2870.                                      )) {
  2871.       sendExpr = new SendExpr ();
  2872.       sendExpr->selector = token.value.svalue;
  2873.       sendExpr->kind = INFIX;
  2874.       scan ();
  2875.       sendExpr->receiver = a;
  2876.       arg = new Argument ();
  2877.       arg->expr = parseExpr6 (errorMsg);
  2878.       sendExpr->argList = arg;
  2879.       a = sendExpr;
  2880.     } else {
  2881.       return a;
  2882.     }
  2883.   }
  2884. }
  2885.  
  2886.  
  2887.  
  2888. // parseExpr6 (errorMsg)
  2889. //
  2890. // This routine parses the grammar rule:
  2891. //    Expr6  -->  Expr7 { '|' Expr7 }           // SendExpr (INFIX)
  2892. //
  2893. Expression * parseExpr6 (char * errorMsg) {
  2894.   Expression * a;
  2895.   SendExpr * sendExpr;
  2896.   Argument * arg;
  2897.  
  2898.   a = parseExpr7 (errorMsg);
  2899.   while (1) {
  2900.     if ((token.type == OPERATOR) && (
  2901.            (token.value.svalue == stringBar)
  2902.                                      )) {
  2903.       sendExpr = new SendExpr ();
  2904.       sendExpr->selector = token.value.svalue;
  2905.       sendExpr->kind = INFIX;
  2906.       scan ();
  2907.       sendExpr->receiver = a;
  2908.       arg = new Argument ();
  2909.       arg->expr = parseExpr7 (errorMsg);
  2910.       sendExpr->argList = arg;
  2911.       a = sendExpr;
  2912.     } else {
  2913.       return a;
  2914.     }
  2915.   }
  2916. }
  2917.  
  2918.  
  2919.  
  2920. // parseExpr7 (errorMsg)
  2921. //
  2922. // This routine parses the grammar rule:
  2923. //    Expr7  -->  Expr8 { '^' Expr8 }           // SendExpr (INFIX)
  2924. //
  2925. Expression * parseExpr7 (char * errorMsg) {
  2926.   Expression * a;
  2927.   SendExpr * sendExpr;
  2928.   Argument * arg;
  2929.  
  2930.   a = parseExpr8 (errorMsg);
  2931.   while (1) {
  2932.     if ((token.type == OPERATOR) && (
  2933.            (token.value.svalue == stringCaret)
  2934.                                      )) {
  2935.       sendExpr = new SendExpr ();
  2936.       sendExpr->selector = token.value.svalue;
  2937.       sendExpr->kind = INFIX;
  2938.       scan ();
  2939.       sendExpr->receiver = a;
  2940.       arg = new Argument ();
  2941.       arg->expr = parseExpr8 (errorMsg);
  2942.       sendExpr->argList = arg;
  2943.       a = sendExpr;
  2944.     } else {
  2945.       return a;
  2946.     }
  2947.   }
  2948. }
  2949.  
  2950.  
  2951.  
  2952. // parseExpr8 (errorMsg)
  2953. //
  2954. // This routine parses the grammar rule:
  2955. //    Expr8  -->  Expr9 { '&' Expr9 }           // SendExpr (INFIX)
  2956. //
  2957. Expression * parseExpr8 (char * errorMsg) {
  2958.   Expression * a;
  2959.   SendExpr * sendExpr;
  2960.   Argument * arg;
  2961.  
  2962.   a = parseExpr9 (errorMsg);
  2963.   while (1) {
  2964.     if ((token.type == OPERATOR) && (
  2965.            (token.value.svalue == stringAmp)
  2966.                                      )) {
  2967.       sendExpr = new SendExpr ();
  2968.       sendExpr->selector = token.value.svalue;
  2969.       sendExpr->kind = INFIX;
  2970.       scan ();
  2971.       sendExpr->receiver = a;
  2972.       arg = new Argument ();
  2973.       arg->expr = parseExpr9 (errorMsg);
  2974.       sendExpr->argList = arg;
  2975.       a = sendExpr;
  2976.     } else {
  2977.       return a;
  2978.     }
  2979.   }
  2980. }
  2981.  
  2982.  
  2983.  
  2984. // parseExpr9 (errorMsg)
  2985. //
  2986. // This routine parses the grammar rule:
  2987. //    Expr9  -->  Expr10 {
  2988. //                           '==' Expr10            // SendExpr (INFIX)
  2989. //                           '!=' Expr10            // SendExpr (INFIX)
  2990. //                                       }
  2991. //
  2992. Expression * parseExpr9 (char * errorMsg) {
  2993.   Expression * a;
  2994.   SendExpr * sendExpr;
  2995.   Argument * arg;
  2996.  
  2997.   a = parseExpr10 (errorMsg);
  2998.   while (1) {
  2999.     if ((token.type == OPERATOR) && (
  3000.            (token.value.svalue == stringEqualEqual) ||
  3001.            (token.value.svalue == stringNotEqual)
  3002.                                      )) {
  3003.       sendExpr = new SendExpr ();
  3004.       sendExpr->selector = token.value.svalue;
  3005.       sendExpr->kind = INFIX;
  3006.       scan ();
  3007.       sendExpr->receiver = a;
  3008.       arg = new Argument ();
  3009.       arg->expr = parseExpr10 (errorMsg);
  3010.       sendExpr->argList = arg;
  3011.       a = sendExpr;
  3012.     } else {
  3013.       return a;
  3014.     }
  3015.   }
  3016. }
  3017.  
  3018.  
  3019.  
  3020. // parseExpr10 (errorMsg)
  3021. //
  3022. // This routine parses the grammar rule:
  3023. //    Expr10  -->  Expr11 {
  3024. //                           '<' Expr11            // SendExpr (INFIX)
  3025. //                           '<=' Expr11            // SendExpr (INFIX)
  3026. //                           '>' Expr11            // SendExpr (INFIX)
  3027. //                           '>=' Expr11            // SendExpr (INFIX)
  3028. //                                       }
  3029. //
  3030. Expression * parseExpr10 (char * errorMsg) {
  3031.   Expression * a;
  3032.   SendExpr * sendExpr;
  3033.   Argument * arg;
  3034.  
  3035.   a = parseExpr11 (errorMsg);
  3036.   while (1) {
  3037.     if ((token.type == OPERATOR) && (
  3038.            (token.value.svalue == stringLess) ||
  3039.            (token.value.svalue == stringLessEqual) ||
  3040.            (token.value.svalue == stringGreater) ||
  3041.            (token.value.svalue == stringGreaterEqual)
  3042.                                      )) {
  3043.       sendExpr = new SendExpr ();
  3044.       sendExpr->selector = token.value.svalue;
  3045.       sendExpr->kind = INFIX;
  3046.       scan ();
  3047.       sendExpr->receiver = a;
  3048.       arg = new Argument ();
  3049.       arg->expr = parseExpr11 (errorMsg);
  3050.       sendExpr->argList = arg;
  3051.       a = sendExpr;
  3052.     } else {
  3053.       return a;
  3054.     }
  3055.   }
  3056. }
  3057.  
  3058.  
  3059.  
  3060. // parseExpr11 (errorMsg)
  3061. //
  3062. // This routine parses the grammar rule:
  3063. //    Expr11  -->  Expr12 {
  3064. //                           '<<' Expr12            // SendExpr (INFIX)
  3065. //                           '>>' Expr12            // SendExpr (INFIX)
  3066. //                           '>>>' Expr12            // SendExpr (INFIX)
  3067. //                                       }
  3068. //
  3069. Expression * parseExpr11 (char * errorMsg) {
  3070.   Expression * a;
  3071.   SendExpr * sendExpr;
  3072.   Argument * arg;
  3073.  
  3074.   a = parseExpr12 (errorMsg);
  3075.   while (1) {
  3076.     if ((token.type == OPERATOR) && (
  3077.            (token.value.svalue == stringLessLess) ||
  3078.            (token.value.svalue == stringGreaterGreater) ||
  3079.            (token.value.svalue == stringGreaterGreaterGreater)
  3080.                                      )) {
  3081.       sendExpr = new SendExpr ();
  3082.       sendExpr->selector = token.value.svalue;
  3083.       sendExpr->kind = INFIX;
  3084.       scan ();
  3085.       sendExpr->receiver = a;
  3086.       arg = new Argument ();
  3087.       arg->expr = parseExpr12 (errorMsg);
  3088.       sendExpr->argList = arg;
  3089.       a = sendExpr;
  3090.     } else {
  3091.       return a;
  3092.     }
  3093.   }
  3094. }
  3095.  
  3096.  
  3097.  
  3098. // parseExpr12 (errorMsg)
  3099. //
  3100. // This routine parses the grammar rule:
  3101. //    Expr12  -->  Expr13 {
  3102. //                           '+' Expr13            // SendExpr (INFIX)
  3103. //                           '-' Expr13            // SendExpr (INFIX)
  3104. //                                       }
  3105. //
  3106. Expression * parseExpr12 (char * errorMsg) {
  3107.   Expression * a;
  3108.   SendExpr * sendExpr;
  3109.   Argument * arg;
  3110.  
  3111.   a = parseExpr13 (errorMsg);
  3112.   while (1) {
  3113.     if ((token.type == OPERATOR) && (
  3114.            (token.value.svalue == stringPlus) ||
  3115.            (token.value.svalue == stringMinus)
  3116.                                      )) {
  3117.       sendExpr = new SendExpr ();
  3118.       sendExpr->selector = token.value.svalue;
  3119.       sendExpr->kind = INFIX;
  3120.       scan ();
  3121.       sendExpr->receiver = a;
  3122.       arg = new Argument ();
  3123.       arg->expr = parseExpr13 (errorMsg);
  3124.       sendExpr->argList = arg;
  3125.       a = sendExpr;
  3126.     } else {
  3127.       return a;
  3128.     }
  3129.   }
  3130. }
  3131.  
  3132.  
  3133.  
  3134. // parseExpr13 (errorMsg)
  3135. //
  3136. // This routine parses the grammar rule:
  3137. //    Expr13  -->  Expr15 {
  3138. //                           '*' Expr15            // SendExpr (INFIX)
  3139. //                           '/' Expr15            // SendExpr (INFIX)
  3140. //                           '%' Expr15            // SendExpr (INFIX)
  3141. //                                       }
  3142. //
  3143. // There is an ambiguity in the grammer.  Consider:
  3144. //   expr -->  expr '*' expr
  3145. // Any opertor, such as '*', may be interpreted as infix or prefix.
  3146. // Here are two examples, that *might* look legal.
  3147. //   x = 123 * p.foo()
  3148. //
  3149. //   x = 123
  3150. //   *p.foo()
  3151. //
  3152. // However, the last stmt is not actually legal since it would be interpreted as:
  3153. //   *(p.foo())
  3154. // since prefix binds more loosely than message-send-dot.  This violates the
  3155. // syntax of the language (prefix expressions always returns values, so they cannot
  3156. // be used at the statement level).  If you want the other interpretation, you would
  3157. // have to add parentheses anyway, so it would look like this:
  3158. //   x = 123
  3159. //   (*p).foo()
  3160. // This would preclude the interpretation of * as a binary operator.
  3161. //
  3162. // This applies to all operator symbols, such as +, -, and *.  However, there is a
  3163. // second use of "*" that causes parsing problems.  Consider this sequence of tokens:
  3164. //   x = 123 * p ...
  3165. // This could have two interpretations, as shown by these examples:
  3166. //   x = 123
  3167. //   *p = 456       -- prefix operator (deref is OK for lhs of assignment)
  3168. // or
  3169. //   x = 123 * p    -- binary operator
  3170. //
  3171. // Since "p" could be an arbitrary expression, we must distinguish the cases here in
  3172. // this routine before parsing "p".  We do this with the following (non-CFG)
  3173. // restrictions:
  3174. //
  3175. //   (1) If a "*" is preceded by a newline, it is assumed to be a prefix operator
  3176. //   (2) If a "*" occurs on the same line as the previous token, we assume it is
  3177. //       an infix operator.
  3178. //
  3179. // In the rare case when you want two such statements on the same line, you would have
  3180. // to use parentheses to force the desired interpretation.  For example:
  3181. //   x = 123   (*p) = 456
  3182. // If you have long infix expressions which must be spread over several lines, do it
  3183. // like this:
  3184. //   x = aaaaaa *
  3185. //         bbbbbb *
  3186. //         cccccc
  3187. //
  3188. Expression * parseExpr13 (char * errorMsg) {
  3189.   Expression * a;
  3190.   SendExpr * sendExpr;
  3191.   Argument * arg;
  3192.  
  3193.   a = parseExpr15 (errorMsg);
  3194.   while (1) {
  3195.     // If this token is "*" and it is on the same line as the last token,
  3196.     // or we have "/" or "%"...
  3197.     if ((token.type == OPERATOR) &&
  3198.         (((token.value.svalue == stringStar) &&
  3199.           (extractLineNumber (tokenMinusOne) == extractLineNumber (token))) ||
  3200.          (token.value.svalue == stringSlash) ||
  3201.          (token.value.svalue == stringPercent)
  3202.                                      )) {
  3203.       sendExpr = new SendExpr ();
  3204.       sendExpr->selector = token.value.svalue;
  3205.       sendExpr->kind = INFIX;
  3206.       scan ();
  3207.       sendExpr->receiver = a;
  3208.       arg = new Argument ();
  3209.       arg->expr = parseExpr15 (errorMsg);
  3210.       sendExpr->argList = arg;
  3211.       a = sendExpr;
  3212.     } else {
  3213.       return a;
  3214.     }
  3215.   }
  3216. }
  3217.  
  3218.  
  3219.  
  3220. // parseExpr15 (errorMsg)
  3221. //
  3222. // This routine parses the grammar rule:
  3223. //    Expr15  -->  OPERATOR Expr15       // PREFIX
  3224. //            -->  Expr16
  3225. //
  3226. Expression * parseExpr15 (char * errorMsg) {
  3227.   SendExpr * prefix;
  3228.  
  3229.   switch (token.type) {
  3230.       case OPERATOR:
  3231.         prefix = new SendExpr ();
  3232.         prefix->selector = lookupAndAdd (appendStrings (
  3233.                               "_prefix_", token.value.svalue->chars, ""), OPERATOR);
  3234.         prefix->kind = PREFIX;
  3235.         scan ();
  3236.         prefix->receiver = parseExpr15 (errorMsg);
  3237.         return prefix;
  3238.     default:
  3239.       return parseExpr16 (errorMsg);
  3240.   }
  3241. }
  3242.  
  3243.  
  3244.  
  3245. // parseExpr16 (errorMsg)
  3246. //
  3247. // This routine parses the grammar rule:
  3248. //    Expr16  -->  Expr17 { '.' ID ArgList               // SendExpr
  3249. //                        | '.' ID                       // FieldAccess
  3250. //                        | 'asPtrTo' Type
  3251. //                        | 'asInteger'
  3252. //                        | 'arraySize'
  3253. //                        | 'isInstanceOf' Type
  3254. //                        | 'isKindOf' Type
  3255. //                        | '[' Expr { ',' Expr } ']'     // ArrayAccess
  3256. //                       }
  3257. //
  3258. Expression * parseExpr16 (char * errorMsg) {
  3259.   Expression * a;
  3260.   Expression * newExpr;
  3261.   AsIntegerExpr * asIntegerExpr;
  3262.   ArraySizeExpr * arraySizeExpr;
  3263.   IsInstanceOfExpr * isInstanceOfExpr;
  3264.   IsKindOfExpr * isKindOfExpr;
  3265.   AsPtrToExpr * asPtrToExpr;
  3266.   SendExpr * sendExpr;
  3267.   FieldAccess * fieldAccess;
  3268.   Token tok;
  3269.  
  3270.   a = parseExpr17 (errorMsg);
  3271.   while (1) {
  3272.     switch (token.type) {
  3273.  
  3274.       case PERIOD:
  3275.         if (token2.type == ID) {
  3276.           // If we have ". ID (" and the ID and "(" are on the same line...
  3277.           if (token3.type == L_PAREN &&
  3278.                 extractLineNumber (token2) == extractLineNumber (token3)) {
  3279.             scan ();    // PERIOD
  3280.             sendExpr = new SendExpr ();
  3281.             sendExpr->receiver = a;
  3282.             sendExpr->kind = NORMAL;
  3283.             sendExpr->selector = token.value.svalue;
  3284.             scan ();    // ID
  3285.             scan ();    // L_PAREN
  3286.             sendExpr->argList = parseArgList ();
  3287.             a = sendExpr;
  3288.           } else {
  3289.             scan ();    // PERIOD
  3290.             fieldAccess = new FieldAccess ();
  3291.             fieldAccess->id = token.value.svalue;
  3292.             scan ();    // ID
  3293.             fieldAccess->expr = a;
  3294.             a = fieldAccess;
  3295.           }
  3296.         } else {
  3297.           syntaxError ("Expecting field ID or message selector after '.'");
  3298.           scan ();      // PERIOD
  3299.         }
  3300.         break;
  3301.  
  3302.       case AS_PTR_TO:
  3303.         asPtrToExpr = new AsPtrToExpr ();
  3304.         scan ();
  3305.         asPtrToExpr->expr = a;
  3306.         asPtrToExpr->type = parseType ("Expecting type in 'expr asPtrTo Type'");
  3307.         a = asPtrToExpr;
  3308.         break;
  3309.  
  3310.       case AS_INTEGER:
  3311.         asIntegerExpr = new AsIntegerExpr ();
  3312.         scan ();
  3313.         asIntegerExpr->expr = a;
  3314.         a = asIntegerExpr;
  3315.         break;
  3316.  
  3317.       case ARRAY_SIZE:
  3318.         arraySizeExpr = new ArraySizeExpr ();
  3319.         scan ();
  3320.         arraySizeExpr->expr = a;
  3321.         a = arraySizeExpr;
  3322.         break;
  3323.  
  3324.       case IS_INSTANCE_OF:
  3325.         isInstanceOfExpr = new IsInstanceOfExpr ();
  3326.         scan ();
  3327.         isInstanceOfExpr->expr = a;
  3328.         isInstanceOfExpr->type = parseType ("Expecting type in 'expr isInstanceOf Type'");
  3329.         a = isInstanceOfExpr;
  3330.         break;
  3331.  
  3332.       case IS_KIND_OF:
  3333.         isKindOfExpr = new IsKindOfExpr ();
  3334.         scan ();
  3335.         isKindOfExpr->expr = a;
  3336.         isKindOfExpr->type = parseType ("Expecting type in 'expr isKindOf Type'");
  3337.         a = isKindOfExpr;
  3338.         break;
  3339.  
  3340.       case L_BRACK:
  3341.         tok = token;
  3342.         scan ();      // L_BRACK
  3343.         a = parseArrayAccess (tok, a);
  3344.         break;
  3345.  
  3346.       default:
  3347.         return a;
  3348.     }
  3349.   }
  3350. }
  3351.  
  3352.  
  3353.  
  3354. // parseExpr17 (errorMsg)
  3355. //
  3356. // This routine parses the grammar rule:
  3357. //    Expr17  -->  '(' Expr ')'
  3358. //            -->  'null'
  3359. //            -->  'true'
  3360. //            -->  'false'
  3361. //            -->  'self'
  3362. //            -->  'super'
  3363. //            -->  INTEGER
  3364. //            -->  DOUBLE
  3365. //            -->  CHAR
  3366. //            -->  STRING
  3367. //            -->  Closure
  3368. //            -->  ID                   // Variable
  3369. //            -->  ID ArgList           // Call Expr
  3370. //            -->  'new' Constructor
  3371. //            -->  'alloc' Constructor
  3372. //            -->  'sizeOf' Type
  3373. //
  3374. //
  3375. // There is an ambiguity in the grammar.  Consider this sequence of tokens:
  3376. //     x = f ( ...
  3377. // This could have two interpretations, as suggested by these examples:
  3378. //     x = f (123)      -- function call
  3379. // and
  3380. //     x = f
  3381. //     (p.foo).bar()    -- next stmt begins with a '('
  3382. //
  3383. // Unfortunately, when we get an ID followed by a '(', we can't tell whether we are
  3384. // looking at a function call or some other expression.  We differentiate these
  3385. // two cases by making the following (non-CFG) rules:
  3386. //   (1) For a function call, the '(' must appear on the same line as the function name
  3387. //   (2) Otherwise, we interpret it as a separate expression.
  3388. // If you really must have 2 statements on the same line, but you do not wish the
  3389. // interpretation as a function call, you must insert an extra set of parens, e.g.,
  3390. //     x = (f)     (p.foo).bar()
  3391. // If you really must have a function call that is spread over several lines,
  3392. // do it like this:
  3393. //     x = f (a,
  3394. //            b,
  3395. //            g (x,
  3396. //               y,
  3397. //               z),
  3398. //            c)
  3399. // or like this if you can't get 'f' and 'a' on one line and want to really spread
  3400. // it out:
  3401. //     x = ffffffffff (
  3402. //            a,
  3403. //            b,
  3404. //            ggggggggg (
  3405. //              x,
  3406. //              y,
  3407. //              z
  3408. //            ),
  3409. //            c
  3410. //         )
  3411. //   
  3412. Expression * parseExpr17 (char * errorMsg) {
  3413.   IntConst * e1;
  3414.   DoubleConst * e2;
  3415.   CharConst * e3;
  3416.   StringConst * e4;
  3417.   Expression * exp;
  3418.   SizeOfExpr * sizeOfExpr;
  3419.   VariableExpr * var;
  3420.   CallExpr * callExpr;
  3421.   ClosureExpr * closureExpr;
  3422.  
  3423.   switch (token.type) {
  3424.   
  3425.     case INT_CONST:
  3426.       e1 = new IntConst ();
  3427.       e1->ivalue = token.value.ivalue;
  3428.       scan ();
  3429.       return e1;
  3430.   
  3431.     case DOUBLE_CONST:
  3432.       e2 = new DoubleConst ();
  3433.       e2->rvalue = token.value.rvalue;
  3434.       scan ();
  3435.       return e2;
  3436.   
  3437.     case CHAR_CONST:
  3438.       e3 = new CharConst ();
  3439.       e3->ivalue = token.value.ivalue;
  3440.       scan ();
  3441.       return e3;
  3442.   
  3443.     case STRING_CONST:
  3444.       e4 = new StringConst ();
  3445.       e4->svalue = token.value.svalue;
  3446.       scan ();
  3447.       return e4;
  3448.   
  3449.     case TRUE:
  3450.       exp = new BoolConst (1);
  3451.       scan ();
  3452.       return exp;
  3453.   
  3454.     case FALSE:
  3455.       exp = new BoolConst (0);
  3456.       scan ();
  3457.       return exp;
  3458.   
  3459.     case NULL_KEYWORD:
  3460.       exp = new NullConst ();
  3461.       scan ();
  3462.       return exp;
  3463.   
  3464.     case SELF:
  3465.       exp = new SelfExpr ();
  3466.       scan ();
  3467.       return exp;
  3468.   
  3469.     case SUPER:
  3470.       exp = new SuperExpr ();
  3471.       scan ();
  3472.       return exp;
  3473.  
  3474.     case L_PAREN:
  3475.       scan ();
  3476.       exp = parseExpr ("Expecting an expression after '('");
  3477.       if (token.type == R_PAREN) {
  3478.         scan ();
  3479.       } else if (token2.type == R_PAREN) {
  3480.         syntaxError ("Expecting ')'");
  3481.         scan ();
  3482.         scan ();
  3483.       } else {
  3484.         syntaxError ("Expecting ')'");
  3485.       }
  3486.       return exp;
  3487.  
  3488.     case SIZE_OF:
  3489.       sizeOfExpr = new SizeOfExpr ();
  3490.       scan ();
  3491.       sizeOfExpr->type = parseType ("Expecting type after 'sizeOf'");
  3492.       return sizeOfExpr;
  3493.  
  3494.     case ID:
  3495.       // If we have "ID (" and they are on the same line...
  3496.       if ((token2.type == L_PAREN) &&
  3497.           extractLineNumber (token) == extractLineNumber (token2)) {   // Call Expression
  3498.         callExpr = new CallExpr ();
  3499.         callExpr->id = token.value.svalue;
  3500.         scan ();    // ID
  3501.         scan ();    // L_PAREN
  3502.         callExpr->argList = parseArgList ();
  3503.         return callExpr;
  3504.       } else {                                     // Simple variable
  3505.         var = new VariableExpr ();
  3506.         var->id = token.value.svalue;
  3507.         scan ();
  3508.         return var;
  3509.       }
  3510.  
  3511.     case FUNCTION:       // Closure expression
  3512.       closureExpr = new ClosureExpr ();
  3513.       closureExpr->function = parseFunction (0);    // Expecting ID = False
  3514.       return closureExpr;
  3515.  
  3516.     case NEW:
  3517.     case ALLOC:
  3518.       return parseConstructor ();
  3519.  
  3520.     default:
  3521.       syntaxError (errorMsg);
  3522.       scan ();
  3523.       return new NullConst ();
  3524.   }
  3525. }
  3526.  
  3527.  
  3528.  
  3529. // parseArrayAccess (tokenForPos, soFar)
  3530. //
  3531. // This routine parses according to this syntax:
  3532. //    Expr { , Expr } ']'
  3533. // and returns an ArrayAccess.  It calls itself recursively; Each invocation
  3534. // will pick up one Expression and will allocate one ArrayAccess node.
  3535. //
  3536. // 'soFar' is whatever expression we have parsed so far, e.g., 'a[1,2'.
  3537. //
  3538. // It positions the ArrayAccess node on the "tokenForPos".
  3539. //
  3540. ArrayAccess * parseArrayAccess (Token tokenForPos, Expression * soFar) {
  3541.   int count;
  3542.   ArrayAccess * arrayAccess;
  3543.  
  3544.   arrayAccess = new ArrayAccess ();
  3545.   arrayAccess->positionAtToken (tokenForPos);
  3546.   arrayAccess->arrayExpr = soFar;
  3547.   arrayAccess->indexExpr = parseExpr ("Expecting an index expression here");
  3548.   if (token.type == R_BRACK) {
  3549.     scan ();
  3550.     return arrayAccess;
  3551.   } else if (token.type == COMMA) {
  3552.     scan ();
  3553.     return parseArrayAccess (tokenForPos, arrayAccess);
  3554.   } else {
  3555.     syntaxError ("Expecting ']' or ',' in 'arr [...]'");
  3556.     // Scan until we hit either FIRST-EXPR or , or ]
  3557.     count = 0;
  3558.     while (1) {
  3559.       if (token.type == EOF) {
  3560.         break;
  3561.       } else if (token.type == R_BRACK) {
  3562.         scan ();
  3563.         break;
  3564.       } else if (token.type == COMMA) {
  3565.         scan ();
  3566.         checkTokenSkipping (count);
  3567.         return parseArrayAccess (tokenForPos, arrayAccess);
  3568.       } else if (inFirstExpr (token)) {
  3569.         checkTokenSkipping (count);
  3570.         return parseArrayAccess (tokenForPos, arrayAccess);
  3571.       }
  3572.       scan ();
  3573.       count++;
  3574.     }
  3575.     checkTokenSkipping (count);
  3576.     return arrayAccess;
  3577.   }
  3578. }
  3579.  
  3580.  
  3581.  
  3582. // parseArgList ()
  3583. //
  3584. // Parse a comma separated list of expressions, followed by the closing ')'.
  3585. //     ArgList --> Expr ',' Expr ',' ... ',' Expr ')'
  3586. //             --> ')'
  3587. // This routine builds and returns a linked-list of Argument nodes.
  3588. // If no arguments are present, then it returns NULL.
  3589. //
  3590. // If there are syntax errors, this routine may scan ZERO tokens.
  3591. //
  3592. Argument * parseArgList () {
  3593.   Argument * newArg, * first, * last;
  3594.   if (token.type == R_PAREN) {
  3595.     scan ();
  3596.     return NULL;
  3597.   }
  3598.   newArg = new Argument ();
  3599.   newArg->expr = parseExpr ("Expecting an argument or ')' here");
  3600.   first = last = newArg;
  3601.   while (token.type == COMMA) {
  3602.     scan ();   // COMMA
  3603.     newArg = new Argument ();
  3604.     newArg->expr = parseExpr ("Expecting the next argument after comma");
  3605.     last->next = newArg;
  3606.     last = newArg;
  3607.   }
  3608.   if (token.type == R_PAREN) {
  3609.     scan ();      // R_PAREN
  3610.   } else {
  3611.     syntaxError ("Expecting ',' or ')' in ArgList");
  3612.     if (token2.type == R_PAREN) {
  3613.       scan ();    // Junk
  3614.       scan ();    // R_PAREN
  3615.     }
  3616.   }
  3617.   return first;
  3618. }
  3619.  
  3620.  
  3621.  
  3622. // parseConstructor ()
  3623. //
  3624. // Parse the following syntax rules:
  3625. //
  3626. // Expr            --> NEW Constructor
  3627. //                 --> ALLOC Constructor
  3628. //
  3629. // Constructor     --> Type ( ClassRecordInit | ArrayInit | <none> )
  3630. //
  3631. // ClassRecordInit --> '{'     ID = Expr
  3632. //                         { , ID = Expr }   '}'  ]
  3633. // ArrayInit       --> '{'    [ Expr 'of' ] Expr
  3634. //                        { , [ Expr 'of' ] Expr }   '}'
  3635. //
  3636. // This routine builds a Constructor node.  A constructor can be used to create/
  3637. // initialize either:
  3638. //    a class instance     Person { name = "harry", age = 46 }
  3639. //    a record instance    Node { val = 5, next = p }
  3640. //    an array             array of int { 100 of -1, 100 of -2}
  3641. //
  3642. // It could be that there is no initialization list, for example:
  3643. //    MyType
  3644. // (Note that we never have an empty list like "MyType { }"...)
  3645. // This routine makes no attempt to check that the sort of initialization in any
  3646. // way matches the type; this will be done during semantic checking.
  3647. //
  3648. // Even if errors, this routine will not return NULL.
  3649. //
  3650. Constructor * parseConstructor () {
  3651.   Constructor * constructor;
  3652.   FieldInit * fieldInit, * firstFieldInit, * lastFieldInit;
  3653.   CountValue * countValue, * firstCountValue, * lastCountValue;
  3654.  
  3655.   constructor = new Constructor ();
  3656.   constructor->allocKind = token.type;    // NEW or ALLOC
  3657.   scan ();
  3658.   constructor->type = parseType ("Expecting type in constructor, after NEW or ALLOC");
  3659.  
  3660.   if (token.type != L_BRACE) {
  3661.     return constructor;
  3662.   }
  3663.   scan ();
  3664.  
  3665.   // If we have a Class/Record initialization list...
  3666.   if ((token.type == ID) && (token2.type == EQUAL)) {
  3667.     fieldInit = new FieldInit ();
  3668.     fieldInit->id = token.value.svalue;
  3669.     scan ();    // ID
  3670.     scan ();    // EQUAL
  3671.     fieldInit->expr = parseExpr ("Expecting an initial value after '='");
  3672.     firstFieldInit = lastFieldInit = fieldInit;
  3673.     while (token.type == COMMA) {
  3674.       scan ();   // COMMA
  3675.       fieldInit = new FieldInit ();
  3676.       fieldInit->id = mustHaveID ("Expecting ID after ',' in class/record constructor initialization list");
  3677.       mustHave (EQUAL, "Expecting '=' after ID in class/record constructor initialization list");
  3678.       fieldInit->expr = parseExpr ("Expecting an initial value after '='");
  3679.       lastFieldInit->next = fieldInit;
  3680.       lastFieldInit = fieldInit;
  3681.       if ((token.type != COMMA) && (token.type != R_BRACE)) {
  3682.         syntaxError ("Expecting ',' or '}' in class/record constructor initialization list");
  3683.         if ((token2.type == COMMA) || (token2.type == R_BRACE)) {
  3684.           scan ();    // junk
  3685.         }
  3686.       }
  3687.     }
  3688.     mustHave (R_BRACE, "Expecting ',' or '}' in class/record constructor initialization list");
  3689.     constructor-> fieldInits = firstFieldInit;
  3690.     return constructor;
  3691.  
  3692.   // If we have an Array initialization list...
  3693.   } else {
  3694.     if (token.type == R_BRACE) {
  3695.       syntaxError ("Empty list in constructor is not allowed; just omit the '{}' entirely");
  3696.       scan ();     // R_BRACE
  3697.       return constructor;
  3698.     }
  3699.     countValue = new CountValue ();
  3700.     countValue->value = parseExpr ("Expecting an expression after '[' in array constructor initialization list");
  3701.     if (token.type == OF) {
  3702.       scan ();
  3703.       countValue->count = countValue->value;
  3704.       countValue->value = parseExpr ("Expecting an expression after 'of' in 'CountExpr of ValueExpr'");
  3705.     }
  3706.     firstCountValue = lastCountValue = countValue;
  3707.     while (token.type == COMMA) {
  3708.       scan ();   // COMMA
  3709.       countValue = new CountValue ();
  3710.       countValue->value = parseExpr ("Expecting next expression after ',' in array constructor initialization list");
  3711.       if (token.type == OF) {
  3712.         scan ();
  3713.         countValue->count = countValue->value;
  3714.         countValue->value = parseExpr ("Expecting an expression after 'of' in 'CountExpr of ValueExpr'");
  3715.       }
  3716.       lastCountValue->next = countValue;
  3717.       lastCountValue = countValue;
  3718.       if ((token.type != COMMA) && (token.type != R_BRACE)) {
  3719.         syntaxError ("Expecting ',' or '}' in array constructor");
  3720.         if ((token2.type == COMMA) || (token2.type == R_BRACE)) {
  3721.           scan ();    // junk
  3722.         }
  3723.       }
  3724.     }
  3725.     mustHave (R_BRACE, "Expecting ',' or '}' in array constructor initialization list");
  3726.     constructor->countValueList = firstCountValue;
  3727.     return constructor;
  3728.   }
  3729. }
  3730.  
  3731.  
  3732.  
  3733. //    
  3734. //    
  3735. //    
  3736. //    
  3737. //    // parseConstructor ()
  3738. //    //
  3739. //    // Parse the following syntax rules:
  3740. //    //
  3741. //    // Constructor --> Type ( ClassRecordInit | ArrayInit | <none> )
  3742. //    //
  3743. //    // ClassRecordInit --> '{'     ID = Expr
  3744. //    //                         { , ID = Expr }   '}'  ]
  3745. //    // ArrayInit --> '{'    [ Expr 'of' ] Expr
  3746. //    //                  { , [ Expr 'of' ] Expr }   '}'
  3747. //    //
  3748. //    // This routine builds a Constructor node.  A constructor can be used to create/
  3749. //    // initialize either:
  3750. //    //    a class instance     Person { name = "harry", age = 46 }
  3751. //    //    a record instance    Node { val = 5, next = p }
  3752. //    //    an array             array of int { 100 of -1, 100 of -2}
  3753. //    //
  3754. //    // It could be that there is no initialization list, for example:
  3755. //    //    MyType
  3756. //    // (Note that we never have an empty list like "MyType { }"...)
  3757. //    // This routine makes no attempt to check that the sort of initialization in any
  3758. //    // way matches the type; this will be done during semantic checking.
  3759. //    //
  3760. //    // Even if errors, this routine will not return NULL.
  3761. //    //
  3762. //    Constructor * parseConstructor () {
  3763. //      Constructor * constructor;
  3764. //      FieldInit * fieldInit, * firstFieldInit, * lastFieldInit;
  3765. //      CountValue * countValue, * firstCountValue, * lastCountValue;
  3766. //    
  3767. //      constructor = new Constructor ();
  3768. //      constructor->type = parseType ("Expecting type in constructor, after NEW or ALLOC");
  3769. //    
  3770. //      if (token.type != L_BRACE) {
  3771. //        return constructor;
  3772. //      }
  3773. //      scan ();
  3774. //    
  3775. //      // If we have a Class/Record initialization list...
  3776. //      if ((token.type == ID) && (token2.type == EQUAL)) {
  3777. //        fieldInit = new FieldInit ();
  3778. //        fieldInit->id = token.value.svalue;
  3779. //        scan ();    // ID
  3780. //        scan ();    // EQUAL
  3781. //        fieldInit->expr = parseExpr ("Expecting an initial value after '='");
  3782. //        firstFieldInit = lastFieldInit = fieldInit;
  3783. //        while (token.type == COMMA) {
  3784. //          scan ();   // COMMA
  3785. //          fieldInit = new FieldInit ();
  3786. //          fieldInit->id = mustHaveID ("Expecting ID after ',' in class/record constructor initialization list");
  3787. //          mustHave (EQUAL, "Expecting '=' after ID in class/record constructor initialization list");
  3788. //          fieldInit->expr = parseExpr ("Expecting an initial value after '='");
  3789. //          lastFieldInit->next = fieldInit;
  3790. //          lastFieldInit = fieldInit;
  3791. //          if ((token.type != COMMA) && (token.type != R_BRACE)) {
  3792. //            syntaxError ("Expecting ',' or '}' in class/record constructor initialization list");
  3793. //            if ((token2.type == COMMA) || (token2.type == R_BRACE)) {
  3794. //              scan ();    // junk
  3795. //            }
  3796. //          }
  3797. //        }
  3798. //        mustHave (R_BRACE, "Expecting ',' or '}' in class/record constructor initialization list");
  3799. //        constructor-> fieldInits = firstFieldInit;
  3800. //        return constructor;
  3801. //    
  3802. //      // If we have an Array initialization list...
  3803. //      } else {
  3804. //        if (token.type == R_BRACE) {
  3805. //          syntaxError ("Empty list in constructor is not allowed; just omit the '{}' entirely");
  3806. //          scan ();     // R_BRACE
  3807. //          return constructor;
  3808. //        }
  3809. //        countValue = new CountValue ();
  3810. //        countValue->value = parseExpr ("Expecting an expression after '[' in array constructor initialization list");
  3811. //        if (token.type == OF) {
  3812. //          scan ();
  3813. //          countValue->count = countValue->value;
  3814. //          countValue->value = parseExpr ("Expecting an expression after 'of' in 'CountExpr of ValueExpr'");
  3815. //        }
  3816. //        firstCountValue = lastCountValue = countValue;
  3817. //        while (token.type == COMMA) {
  3818. //          scan ();   // COMMA
  3819. //          countValue = new CountValue ();
  3820. //          countValue->value = parseExpr ("Expecting next expression after ',' in array constructor initialization list");
  3821. //          if (token.type == OF) {
  3822. //            scan ();
  3823. //            countValue->count = countValue->value;
  3824. //            countValue->value = parseExpr ("Expecting an expression after 'of' in 'CountExpr of ValueExpr'");
  3825. //          }
  3826. //          lastCountValue->next = countValue;
  3827. //          lastCountValue = countValue;
  3828. //          if ((token.type != COMMA) && (token.type != R_BRACE)) {
  3829. //            syntaxError ("Expecting ',' or '}' in array constructor");
  3830. //            if ((token2.type == COMMA) || (token2.type == R_BRACE)) {
  3831. //              scan ();    // junk
  3832. //            }
  3833. //          }
  3834. //        }
  3835. //        mustHave (R_BRACE, "Expecting ',' or '}' in array constructor initialization list");
  3836. //        constructor->countValueList = firstCountValue;
  3837. //        return constructor;
  3838. //      }
  3839. //    }
  3840. //    
  3841.  
  3842.  
  3843.  
  3844. // parseLocalVarDecls ()
  3845. //
  3846. // This routine parses the following syntax:
  3847. //     VarDecls --> [ 'var' { VarDecl }+ ]
  3848. //     VarDecl  --> Decl [ '=' Expr0 ]
  3849. //     Decl     --> ID { ',' ID } ':' Type
  3850. //
  3851. // It returns a linked list of Locals.
  3852. //
  3853. // NOTE: THIS ROUTINE IS VERY SIMILAR TO parseGlobalVarDecls.
  3854. //
  3855. Local * parseLocalVarDecls () {
  3856.   Local * first, * last, * idListFirst, * idListLast, * local;
  3857.   Type * type;
  3858.   Expression * init;
  3859.   VariableExpr * var;
  3860.   if (token.type != VAR) {
  3861.     return NULL;
  3862.   }
  3863.   first = last = NULL;
  3864.   scan ();    // VAR
  3865.   do {
  3866.     // Pick up a list of ID's
  3867.     idListFirst = idListLast = NULL;
  3868.     do {
  3869.       local = new Local ();
  3870.       local->id = mustHaveID ("Expecting a variable name ID");
  3871.       if (idListFirst == NULL) {
  3872.         idListFirst = local;
  3873.       } else {
  3874.         idListLast->next = local;
  3875.       }
  3876.       idListLast = local;
  3877.       if (token.type != COMMA) {
  3878.         break;
  3879.       }
  3880.       scan ();     // COMMA
  3881.       // Check for common errors (i.e., use of keyword as a name)...
  3882.       if (token.type != ID) {
  3883.         syntaxError ("Expecting next local variable name ID after COMMA");
  3884.         scan ();
  3885.         if (token.type == COMMA) {
  3886.           scan ();
  3887.         } else if (token.type == COLON) {
  3888.           break;
  3889.         }
  3890.       }
  3891.     } while (token.type == ID);
  3892.     // Pick up a type
  3893.     mustHave (COLON, "Expecting ': Type' in variable decl");
  3894.     type = parseType ("Expecting Type after ':' in variable decl");
  3895.     // See if we have an initializing expression
  3896.     init = NULL;
  3897.     if (token.type == EQUAL) {
  3898.       scan ();    // EQUAL
  3899.       init = parseExpr0 ("Expecting initializing expression after '='");
  3900.     }
  3901.     // Now run through the ID's.  "idListFirst" points to the next one to examine.
  3902.     while (idListFirst) {
  3903.       // Add in a ptr to the (shared) type.
  3904.       idListFirst->type = type;
  3905.       // Add "idListFirst" to the end of the main list.
  3906.       if (first == NULL) {
  3907.         first = idListFirst;
  3908.       } else {
  3909.         last->next = idListFirst;
  3910.       }
  3911.       last = idListFirst;
  3912.       // Move to the next id in the secondary list.
  3913.       idListFirst = (Local *) idListFirst->next;
  3914.       // Add in an initializing expression if there is one.
  3915.       if (init) {
  3916.         last->initExpr = init;
  3917.         // We will treat "x,y,z: int = 123" as "x=123  y=x  z=y"
  3918.         var = new VariableExpr ();
  3919.         var->positionAt (init);
  3920.         var->id = last->id;
  3921.         init = var; 
  3922.       }
  3923.     }
  3924.     last->next = NULL;
  3925.     // Continue looping if we have...
  3926.     //      ID :
  3927.     //      ID ,
  3928.     // Anything else (like a lone ID) might be an expression or stmt...
  3929.   } while ((token.type == ID) && ((token2.type == COMMA) || (token2.type == COLON)));
  3930.   return first;
  3931. }
  3932.  
  3933.  
  3934.  
  3935. // parseGlobalVarDecls ()
  3936. //
  3937. // This routine parses the following syntax:
  3938. //     VarDecls --> [ 'var' { VarDecl }+ ]
  3939. //     VarDecl  --> Decl [ '=' Expr0 ]
  3940. //     Decl     --> ID { ',' ID } ':' Type
  3941. //
  3942. // It returns a linked list of Globals.
  3943. //
  3944. // NOTE: THIS ROUTINE IS VERY SIMILAR TO parseLocalVarDecls.
  3945. //
  3946. Global * parseGlobalVarDecls () {
  3947.   Global * first, * last, * idListFirst, * idListLast, * global;
  3948.   Type * type;
  3949.   Expression * init;
  3950.   VariableExpr * var;
  3951.   if (token.type != VAR) {
  3952.     programLogicError ("Already checked for 'var' keyword");
  3953.   }
  3954.   first = last = NULL;
  3955.   scan ();    // VAR
  3956.   while (1) {
  3957.     // Pick up a list of ID's
  3958.     idListFirst = idListLast = NULL;
  3959.     do {
  3960.       global = new Global ();
  3961.       global->id = mustHaveID ("Expecting a global variable name ID");
  3962.       if (idListFirst == NULL) {
  3963.         idListFirst = global;
  3964.       } else {
  3965.         idListLast->next = global;
  3966.       }
  3967.       idListLast = global;
  3968.       if (token.type != COMMA) {
  3969.         break;
  3970.       }
  3971.       scan ();     // COMMA
  3972.       // Check for common errors (i.e., use of keyword as a name)...
  3973.       if (token.type != ID) {
  3974.         syntaxError ("Expecting next global variable name ID after COMMA");
  3975.         scan ();
  3976.         if (token.type == COMMA) {
  3977.           scan ();
  3978.         } else if (token.type == COLON) {
  3979.           break;
  3980.         }
  3981.       }
  3982.     } while (token.type == ID);
  3983.     // Pick up a type
  3984.     mustHave (COLON, "Expecting ': Type' in variable decl");
  3985.     type = parseType ("Expecting Type after ':' in variable decl");
  3986.     // See if we have an initializing expression
  3987.     init = NULL;
  3988.     if (token.type == EQUAL) {
  3989.       scan ();    // EQUAL
  3990.       init = parseExpr0 ("Expecting initializing expression after '='");
  3991.     }
  3992.     // Now run through the ID's.  "idListFirst" points to the next one to examine.
  3993.     while (idListFirst) {
  3994.       // Add in a ptr to the (shared) type.
  3995.       idListFirst->type = type;
  3996.       // Add "idListFirst" to the end of the main list.
  3997.       if (first == NULL) {
  3998.         first = idListFirst;
  3999.       } else {
  4000.         last->next = idListFirst;
  4001.       }
  4002.       last = idListFirst;
  4003.       // Move to the next id in the secondary list.
  4004.       idListFirst = (Global *) idListFirst->next;
  4005.       // Add in an initializing expression if there is one.
  4006.       if (init) {
  4007.         last->initExpr = init;
  4008.         // We will treat "x,y,z: int = 123" as "x=123  y=x  z=y"
  4009.         var = new VariableExpr ();
  4010.         var->positionAt (init);
  4011.         var->id = last->id;
  4012.         init = var; 
  4013.       }
  4014.     }
  4015.     last->next = NULL;
  4016.     // Continue looping if we have...
  4017.     //      ID
  4018.     //      xxx ,      (E.g., using a keyword as a var name)
  4019.     //      xxx :
  4020.     if ((token.type != ID) && (token2.type != COMMA) && (token2.type != COLON)) {
  4021.       break;
  4022.     }
  4023.   }
  4024.   return first;
  4025. }
  4026.  
  4027.  
  4028.  
  4029. // parseClassFields ()
  4030. //
  4031. // This routine parses the following syntax:
  4032. //     { ID { ',' ID } ':' Type }+
  4033. //
  4034. // It returns a linked list of ClassFields.
  4035. //
  4036. ClassField * parseClassFields () {
  4037.   ClassField * first, * last, * idListFirst, * idListLast, * field;
  4038.   Type * type;
  4039.  
  4040.   first = last = NULL;
  4041.   while (1) {
  4042.     // Pick up a list of ID's
  4043.     idListFirst = idListLast = NULL;
  4044.     do {
  4045.       field = new ClassField ();
  4046.       field->id = mustHaveID ("Expecting a field name ID");
  4047.       if (idListFirst == NULL) {
  4048.         idListFirst = field;
  4049.       } else {
  4050.         idListLast->next = field;
  4051.       }
  4052.       idListLast = field;
  4053.       if (token.type != COMMA) {
  4054.         break;
  4055.       }
  4056.       scan ();     // COMMA
  4057.       // Check for common errors (i.e., use of keyword as a name)...
  4058.       if (token.type != ID) {
  4059.         syntaxError ("Expecting next field name ID after COMMA");
  4060.         scan ();
  4061.         if (token.type == COMMA) {
  4062.           scan ();
  4063.         } else if (token.type == COLON) {
  4064.           break;
  4065.         }
  4066.       }
  4067.     } while (token.type == ID);
  4068.     // Pick up a type
  4069.     mustHave (COLON, "Expecting ': Type' in field decl");
  4070.     type = parseType ("Expecting Type after ':' in field decl");
  4071.     if (token.type == EQUAL) {
  4072.       syntaxError ("Fields may not be initialized; they are always initialized to zero-equivalents");
  4073.       scan ();
  4074.       parseExpr ("Problems after '=' in field declaration");
  4075.     }
  4076.     // Now run through the ID's.  "idListFirst" points to the next one to examine.
  4077.     while (idListFirst) {
  4078.       // Add in a ptr to the (shared) type.
  4079.       idListFirst->type = type;
  4080.       // Add "idListFirst" to the end of the main list.
  4081.       if (first == NULL) {
  4082.         first = idListFirst;
  4083.       } else {
  4084.         last->next = idListFirst;
  4085.       }
  4086.       last = idListFirst;
  4087.       // Move to the next id in the secondary list.
  4088.       idListFirst = (ClassField *) idListFirst->next;
  4089.     }
  4090.     last->next = NULL;
  4091.     // Continue looping if we have...
  4092.     //      ID
  4093.     //      xxx ,      (E.g., using a keyword as a var name)
  4094.     //      xxx :
  4095.     if ((token.type != ID) && (token2.type != COMMA) && (token2.type != COLON)) {
  4096.       break;
  4097.     }
  4098.   }
  4099.   return first;
  4100. }
  4101.  
  4102.  
  4103.  
  4104. // parseErrorDecls ()
  4105. //
  4106. // This routine parses the following syntax:
  4107. //     Errors --> 'errors' { ID ParmList }+
  4108. //
  4109. // It returns a linked list of ConstDecls.
  4110. //
  4111. ErrorDecl * parseErrorDecls () {
  4112.   ErrorDecl * first, * last, * errorDecl;
  4113.   if (token.type != ERRORS) {
  4114.     programLogicError ("Already checked for 'errors' keyword");
  4115.   }
  4116.   first = last = NULL;
  4117.   scan ();    // ERRORS
  4118.   if (token.type != ID) {
  4119.     syntaxError ("Expecting ID after 'errors'");
  4120.     return NULL;
  4121.   }
  4122.   while (token.type == ID) {
  4123.     errorDecl = new ErrorDecl ();
  4124.     errorDecl->id = token.value.svalue;
  4125.     scan ();    // ID
  4126.     errorDecl->parmList = parseParmList ();
  4127.     if (first == NULL) {
  4128.       first = errorDecl;
  4129.     } else {
  4130.       last->next = errorDecl;
  4131.     }
  4132.     last = errorDecl;
  4133.   }
  4134.   return first;
  4135. }
  4136.  
  4137.  
  4138.  
  4139. // parseConstDecls ()
  4140. //
  4141. // This routine parses the following syntax:
  4142. //     Const --> 'const' { ID = Expr }+
  4143. //
  4144. // It returns a linked list of ConstDecls.
  4145. //
  4146. ConstDecl * parseConstDecls () {
  4147.   ConstDecl * first, * last, * constDecl;
  4148.   if (token.type != CONST) {
  4149.     programLogicError ("Already checked for 'const' keyword");
  4150.   }
  4151.   first = last = NULL;
  4152.   scan ();    // CONST
  4153.   if (token.type != ID) {
  4154.     syntaxError ("Expecting ID after 'const'");
  4155.     return NULL;
  4156.   }
  4157.   while (token.type == ID) {
  4158.     constDecl = new ConstDecl ();
  4159.     constDecl->id = token.value.svalue;
  4160.     scan ();    // ID
  4161.     if (first == NULL) {
  4162.       first = constDecl;
  4163.     } else {
  4164.       last->next = constDecl;
  4165.     }
  4166.     last = constDecl;
  4167.     // Pick up the Expression
  4168.     mustHave (EQUAL, "Expecting '= Expr' in const decl");
  4169.     constDecl->expr = parseExpr ("In constant initializing expression");
  4170.   }
  4171.   return first;
  4172. }
  4173.  
  4174.  
  4175.  
  4176. // parseEnums ()
  4177. //
  4178. // This routine parses the following syntax:
  4179. //     Enum --> 'enum' ID [ = Expr ] { , ID }
  4180. //
  4181. // It returns a linked list of ConstDecls.
  4182. //
  4183. ConstDecl * parseEnums () {
  4184.   ConstDecl * first, * last, * constDecl;
  4185.   int counter, gotInitializer;
  4186.   Expression * expr, * junk;
  4187.   IntConst * intConst;
  4188.   SendExpr * sendExpr;
  4189.   Argument * arg;
  4190.   VariableExpr * var;
  4191.   if (token.type != ENUM) {
  4192.     programLogicError ("Already checked for 'enum' keyword");
  4193.   }
  4194.   first = last = NULL;
  4195.   scan ();    // ENUM
  4196.   constDecl = new ConstDecl ();
  4197.   constDecl->id = mustHaveID ("Expecting ID after 'ENUM'");
  4198.  
  4199.   // If there is an expression, pick it up; Else the default is "= 1".
  4200.   counter = 1;
  4201.   if (token.type == EQUAL) {
  4202.     scan ();
  4203.     constDecl->expr = parseExpr ("In initializing expression after 'ENUM ID ='");
  4204.     gotInitializer = 1;
  4205.   } else {
  4206.     intConst = new IntConst ();
  4207.     intConst->positionAt (constDecl);
  4208.     intConst->ivalue = 1;
  4209.     constDecl->expr = intConst;
  4210.     gotInitializer = 0;
  4211.   }
  4212.   first = last = constDecl;
  4213.   while (token.type == COMMA) {
  4214.     scan ();    // COMMA
  4215.     constDecl = new ConstDecl ();
  4216.     constDecl->id = mustHaveID ("Expecting next ID in 'enum ID, ID, ...'");
  4217.     // There should not be "= Expr" here...
  4218.     if (token.type == EQUAL) {
  4219.       syntaxError ("An initial expression is only allowed for the first 'enum ID'");
  4220.       scan ();
  4221.       junk = parseExpr ("In ENUM initializing expression");
  4222.     }
  4223.     last->next = constDecl;
  4224.     last = constDecl;
  4225.     // If we had an initializing expression, then create "firstID + N"...
  4226.     if (gotInitializer) {
  4227.       var = new VariableExpr ();
  4228.       var->positionAt (constDecl);
  4229.       var->id = first->id;
  4230.       intConst = new IntConst ();
  4231.       intConst->positionAt (constDecl);
  4232.       intConst->ivalue = counter;
  4233.       arg = new Argument ();
  4234.       arg->positionAt (constDecl);
  4235.       arg->expr = intConst;
  4236.       sendExpr = new SendExpr ();
  4237.       sendExpr->positionAt (constDecl);
  4238.       sendExpr->receiver = var;
  4239.       sendExpr->selector = lookupAndAdd ("+", OPERATOR);
  4240.       sendExpr->argList = arg;
  4241.       sendExpr->kind = INFIX;
  4242.       constDecl->expr = sendExpr;
  4243.       counter++;
  4244.     } else {    // Else, if no initial expression, then create an integerConst...
  4245.       counter++;
  4246.       intConst = new IntConst ();
  4247.       intConst->positionAt (constDecl);
  4248.       intConst->ivalue = counter;
  4249.       constDecl->expr = intConst;
  4250.     }
  4251.   }
  4252.   return first;
  4253. }
  4254.  
  4255.  
  4256.  
  4257. // parseTypeDefs ()
  4258. //
  4259. // This routine parses the following syntax:
  4260. //     TypeDef --> 'type' { ID = Type }+
  4261. //
  4262. // It returns a linked list of TypeDefs.
  4263. //
  4264. TypeDef * parseTypeDefs () {
  4265.   TypeDef * first, * last, * typeDef;
  4266.   if (token.type != TYPE) {
  4267.     programLogicError ("Already checked for 'type' keyword");
  4268.   }
  4269.   first = last = NULL;
  4270.   scan ();    // TYPE
  4271.   if (token.type != ID) {
  4272.     syntaxError ("Expecting ID after 'type'");
  4273.     return NULL;
  4274.   }
  4275.   while (token.type == ID) {
  4276.     typeDef = new TypeDef ();
  4277.     typeDef->id = token.value.svalue;
  4278.     scan ();    // ID
  4279.     if (first == NULL) {
  4280.       first = typeDef;
  4281.     } else {
  4282.       last->next = typeDef;
  4283.     }
  4284.     last = typeDef;
  4285.     // Pick up the Type
  4286.     mustHave (EQUAL, "Expecting '= Type' in type definition");
  4287.     typeDef->type = parseType ("Expecting Type after '=' in type definition");
  4288.   }
  4289.   return first;
  4290. }
  4291.  
  4292.