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 / BlitzSrc / parser.cc < prev    next >
C/C++ Source or Header  |  2007-09-19  |  124KB  |  4,332 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 }+
  1265. //    FunProto       --> ID ParmList [ returns Type ]
  1266. //
  1267. FunctionProto * parseFunctionProtos () {
  1268.   FunctionProto * first, * last, * funProto;
  1269.   first = last = NULL;
  1270.   if (token.type != FUNCTIONS) {
  1271.     programLogicError ("Already checked for 'functions' keyword");
  1272.   }
  1273.   scan ();   // FUNCTIONS
  1274.   while ((token.type == ID) || (token.type == EXTERNAL)) {
  1275.     funProto = new FunctionProto ();
  1276.     if (token.type == EXTERNAL) {
  1277.       scan ();
  1278.       funProto->isExternal = 1;
  1279.     }
  1280.     if (token.type == ID) {
  1281.       funProto->tokn = token;
  1282.       funProto->id = token.value.svalue;
  1283.       scan ();    // ID
  1284.     } else {
  1285.       syntaxError ("Expecting ID after 'external'");
  1286.       funProto->id = lookupAndAdd ("<missingIdSyntaxError>", ID);
  1287.     }
  1288.     funProto->parmList = parseParmList ();
  1289.     if (token.type == RETURNS) {
  1290.       scan ();
  1291.       funProto->retType = parseType ("Expecting return type after RETURNS");
  1292.       if (gotVoidType (funProto->retType)) {
  1293.         syntaxError ("Do not say 'returns void'; just leave it out");
  1294.       }
  1295.     } else if (token.type == RETURN) {
  1296.       syntaxError ("Expecting RETURNS, not RETURN");
  1297.       scan ();
  1298.       funProto->retType = parseType ("Expecting return type after RETURNS");
  1299.     } else {
  1300.       funProto->retType = new VoidType ();
  1301.     }
  1302.     if (first == NULL) {
  1303.       first = funProto;
  1304.     } else {
  1305.       last->next = funProto;
  1306.     }
  1307.     last = funProto;
  1308.   }
  1309.   return first;
  1310. }
  1311.  
  1312.  
  1313.  
  1314. // parseMethod ()
  1315. //
  1316. // This routine parses a Method and returns a pointer to a Method node.
  1317. //
  1318. Method * parseMethod () {
  1319.   Method * meth;
  1320.   MethodProto * methodProto;
  1321.  
  1322.   if (token.type != METHOD) {
  1323.     programLogicError ("Already checked for 'method' keyword");
  1324.   }
  1325.   scan ();   // METHOD
  1326.   meth = new Method ();
  1327.   methodProto = parseMethodProto ();
  1328.   meth->positionAt (methodProto);
  1329.   meth->kind = methodProto->kind;
  1330.   meth->selector = methodProto->selector;
  1331.   meth->parmList = methodProto-> parmList;
  1332.   meth->retType = methodProto-> retType;
  1333.   if (token.type == METHOD) {
  1334.     syntaxError ("Expecting method body");
  1335.     return meth;
  1336.   }
  1337.   if (token.type == END_BEHAVIOR) {
  1338.     syntaxError ("Expecting method body");
  1339.     return meth;
  1340.   }
  1341.   meth->locals = parseLocalVarDecls ();
  1342.   meth->stmts = parseStmtList (NULL,     // enclosingStmtForBreak
  1343.                                NULL,     // enclosingStmtForContinue
  1344.                                meth,     // enclosingMethOrFunction
  1345.                                0);
  1346.   mustHave (END_METHOD, "Expecting 'endMethod'");
  1347.   return meth;
  1348. }
  1349.  
  1350.  
  1351.  
  1352. // parseMethodProto ()
  1353. //
  1354. // This routine parses this syntax rule:
  1355. //    MethProto  --> ID ParmList [ returns Type ]
  1356. //               --> infix OPERATOR '(' ID : Type ')' returns Type
  1357. //               --> prefix OPERATOR '(' ')' returns Type
  1358. //               --> { ID : '(' ID : Type ')' }+ [ returns Type ]
  1359. //
  1360. // It may scan ZERO tokens if syntax errors.
  1361.  
  1362. //
  1363. MethodProto * parseMethodProto () {
  1364.   MethodProto * methodProto;
  1365.   char * newSelector;
  1366.   Parameter * parm, * lastParm;
  1367.  
  1368.  
  1369.   // Parse a INFIX method prototype...
  1370.   if (token.type == INFIX) {
  1371.     scan ();
  1372.     methodProto = new MethodProto ();
  1373.     methodProto->kind = INFIX;
  1374.     if (token.type != OPERATOR) {
  1375.       syntaxError ("Expecting OPERATOR");
  1376.       methodProto->selector = lookupAndAdd ("<missingSelectorSyntaxError>", ID);
  1377.     } else {
  1378.       methodProto->selector = token.value.svalue;
  1379.       scan ();     // OPERATOR
  1380.     }
  1381.     methodProto->parmList = parseParmList ();
  1382.     if (methodProto->parmList == NULL) {
  1383.       syntaxError ("Expecting exactly one parameter in infix method prototype");
  1384.     } else if (methodProto->parmList->next != NULL) {
  1385.       syntaxError ("Expecting exactly one parameter in infix method prototype");
  1386.     }
  1387.     if (token.type == RETURNS) {
  1388.       scan ();
  1389.       methodProto->retType = parseType ("Expecting return type after RETURNS");
  1390.       if (gotVoidType (methodProto->retType)) {
  1391.         syntaxError ("Infix methods must return a value");
  1392.       }
  1393.     } else {
  1394.       syntaxError ("Expecting 'returns Type' for infix method prototype");
  1395.       methodProto->retType = new VoidType ();
  1396.     }
  1397.  
  1398.   // Parse a PREFIX method prototype...
  1399.   } else if (token.type == PREFIX) {
  1400.     scan ();
  1401.     methodProto = new MethodProto ();
  1402.     methodProto->kind = PREFIX;
  1403.     if (token.type != OPERATOR) {
  1404.       syntaxError ("Expecting OPERATOR");
  1405.       methodProto->selector = lookupAndAdd ("<missingSelectorSyntaxError>", ID);
  1406.     } else {
  1407.       methodProto->selector = lookupAndAdd (appendStrings (
  1408.                                 "_prefix_", token.value.svalue->chars, ""), OPERATOR);
  1409.       scan ();     // OPERATOR
  1410.     }
  1411.     mustHave (L_PAREN, "Expecting '()' after 'prefix OP' in method prototype");
  1412.     mustHave (R_PAREN, "Expecting '()' after 'prefix OP' in method prototype");
  1413.     if (token.type == RETURNS) {
  1414.       scan ();
  1415.       methodProto->retType = parseType ("Expecting return type after RETURNS");
  1416.       if (gotVoidType (methodProto->retType)) {
  1417.         syntaxError ("Prefix methods must return a value");
  1418.       }
  1419.     } else {
  1420.       syntaxError ("Expecting 'returns Type' for prefix method prototype");
  1421.       methodProto->retType = new VoidType ();
  1422.     }
  1423.  
  1424.   // Parse a NORMAL method prototype...
  1425.   } else if ((token.type == ID) && (token2.type == L_PAREN)) {
  1426.     methodProto = new MethodProto ();
  1427.     methodProto->selector = token.value.svalue;
  1428.     methodProto->kind = NORMAL;
  1429.     scan ();     // ID
  1430.     methodProto->parmList = parseParmList ();
  1431.     if (token.type == RETURNS) {
  1432.       scan ();
  1433.       methodProto->retType = parseType ("Expecting return type after RETURNS");
  1434.       if (gotVoidType (methodProto->retType)) {
  1435.         syntaxError ("Do not say 'returns void'; just leave it out");
  1436.       }
  1437.     } else if ((token.type == RETURN) &&
  1438.                (token2.type != END_METHOD)) {
  1439.       syntaxError ("Expecting RETURNS, not RETURN");
  1440.       scan ();
  1441.       methodProto->retType = parseType ("Expecting return type after RETURNS");
  1442.     } else {
  1443.       methodProto->retType = new VoidType ();
  1444.     }
  1445.  
  1446.   // Parse a KEYWORD method prototype...
  1447.   } else if ((token.type == ID) && (token2.type == COLON)) {
  1448.     methodProto = new MethodProto ();
  1449.     methodProto->kind = KEYWORD;
  1450.     newSelector = appendStrings (token.value.svalue->chars, ":", "");
  1451.     scan ();      // ID
  1452.     scan ();      // COLON
  1453.     mustHave (L_PAREN, "Expecting '(ID: Type)' in keyword method prototype");
  1454.     parm = new Parameter ();
  1455.     parm->id =  mustHaveID ("Expecting ID in '(ID: Type)'");
  1456.     mustHave (COLON, "Expecting ':' in '(ID: Type)'");
  1457.     parm->type = parseType ("Expecting type after ':' in '(ID: Type)'");
  1458.     mustHave (R_PAREN, "Expecting ')' in '(ID: Type)'");
  1459.     methodProto->parmList = parm;
  1460.     lastParm = parm;
  1461.     // Each iteration of this loop parses "ID: (ID: Type)"...
  1462.     while (1) {
  1463.       if ((token.type != ID) || (token2.type != COLON)) {
  1464.         break;
  1465.       }
  1466.       newSelector = appendStrings (newSelector, token.value.svalue->chars, ":");
  1467.       scan ();      // ID
  1468.       scan ();      // COLON
  1469.       mustHave (L_PAREN, "Expecting '(ID: Type)' in keyword method prototype");
  1470.       parm = new Parameter ();
  1471.       parm->id =  mustHaveID ("Expecting ID in '(ID: Type)'");
  1472.       mustHave (COLON, "Expecting : in '(ID: Type)'");
  1473.       parm->type = parseType ("Expecting type after ':' in '(ID: Type)'");
  1474.       mustHave (R_PAREN, "Expecting ')' in '(ID: Type)'");
  1475.       lastParm->next = parm;
  1476.       lastParm = parm;
  1477.     }
  1478.     methodProto->selector = lookupAndAdd (newSelector, ID);
  1479.     // Parse "returns Type"...
  1480.     if (token.type == RETURNS) {
  1481.       scan ();
  1482.       methodProto->retType = parseType ("Expecting return type after RETURNS");
  1483.       if (gotVoidType (methodProto->retType)) {
  1484.         syntaxError ("Do not say 'returns void'; just leave it out");
  1485.       }
  1486.     } else if ((token.type == RETURN) &&
  1487.                (token2.type != END_METHOD)) {
  1488.       syntaxError ("Expecting RETURNS, not RETURN");
  1489.       scan ();
  1490.       methodProto->retType = parseType ("Expecting return type after RETURNS");
  1491.     } else {
  1492.       methodProto->retType = new VoidType ();
  1493.     }
  1494.  
  1495.   // Deal with syntax errors...
  1496.   } else if (token.type == ID) {
  1497.     methodProto = new MethodProto ();
  1498.     syntaxError ("Expecting ParmList or ': (ID:Type)' in Method Prototype");
  1499.     methodProto->selector = lookupAndAdd ("<missingSelectorSyntaxError>", ID);
  1500.     methodProto->kind = NORMAL;
  1501.     methodProto->retType = new VoidType ();
  1502.   } else {
  1503.     methodProto = new MethodProto ();
  1504.     syntaxError ("Expecting a Method Prototype");
  1505.     methodProto->selector = lookupAndAdd ("<missingSelectorSyntaxError>", ID);
  1506.     methodProto->kind = NORMAL;
  1507.     methodProto->retType = new VoidType ();
  1508.   }
  1509.  
  1510.   return methodProto;
  1511. }
  1512.  
  1513.  
  1514.  
  1515. // parseHeader ()
  1516. //
  1517. // This routine parses:
  1518. //    HeaderFile   --> header ID
  1519. //                       Uses
  1520. //                       { Const |
  1521. //                         Errors |
  1522. //                         VarDecls |
  1523. //                         Enum |
  1524. //                         TypeDef |
  1525. //                         FunctionProtos |
  1526. //                         Interface |
  1527. //                         Class }
  1528. //                     endHeader
  1529. //
  1530. Header * parseHeader () {
  1531.   Header * header;
  1532.   Global * newGlobals, * lastGlobal;
  1533.   ConstDecl * newConsts, * lastConst;
  1534.   ErrorDecl * newErrors, * lastError;
  1535.   TypeDef * typeDef, * lastTypeDef;
  1536.   FunctionProto * funProto, * lastFunProto;
  1537.   Interface * interface, * lastInterface;
  1538.   ClassDef * cl, * lastClass;
  1539.   int count;
  1540.  
  1541.   if (token.type != HEADER) {
  1542.     syntaxError ("Expecting 'header' at beginning of header file");
  1543.     return NULL;
  1544.   }
  1545.   scan ();    // HEADER
  1546.   header = new Header ();
  1547.  
  1548.   if (token.type == ID) {
  1549.     header->packageName = token.value.svalue;
  1550.     scan ();    // ID
  1551.   } else {
  1552.     syntaxError ("Expecting package name after 'header'");
  1553.     header->packageName = lookupAndAdd ("<missingPackageName>", ID);
  1554.   }
  1555.   header->uses = parseUses ();
  1556.   while (1) {
  1557.     switch (token.type) {
  1558.       case CONST:
  1559.         newConsts = parseConstDecls ();
  1560.         if (header->consts == NULL) {
  1561.           header->consts = newConsts;
  1562.         } else {
  1563.           lastConst = header->consts;
  1564.           while (lastConst->next != NULL) {
  1565.             lastConst = lastConst->next;
  1566.           }
  1567.           lastConst->next = newConsts;
  1568.         }
  1569.         break;
  1570.       case ERRORS:
  1571.         newErrors = parseErrorDecls ();
  1572.         if (header->errors == NULL) {
  1573.           header->errors = newErrors;
  1574.         } else {
  1575.           lastError = header->errors;
  1576.           while (lastError->next != NULL) {
  1577.             lastError = lastError->next;
  1578.           }
  1579.           lastError->next = newErrors;
  1580.         }
  1581.         break;
  1582.       case VAR:
  1583.         newGlobals = parseGlobalVarDecls ();
  1584.         if (header->globals == NULL) {
  1585.           header->globals = newGlobals;
  1586.         } else {
  1587.           lastGlobal = header->globals;
  1588.           while (lastGlobal->next != NULL) {
  1589.             lastGlobal = (Global *) lastGlobal->next;
  1590.           }
  1591.           lastGlobal->next = newGlobals;
  1592.         }
  1593.         break;
  1594.       case ENUM:
  1595.         newConsts = parseEnums ();
  1596.         if (header->consts == NULL) {
  1597.           header->consts = newConsts;
  1598.         } else {
  1599.           lastConst = header->consts;
  1600.           while (lastConst->next != NULL) {
  1601.             lastConst = lastConst->next;
  1602.           }
  1603.           lastConst->next = newConsts;
  1604.         }
  1605.         break;
  1606.       case TYPE:
  1607.         typeDef = parseTypeDefs ();
  1608.         if (header->typeDefs == NULL) {
  1609.           header->typeDefs = typeDef;
  1610.         } else {
  1611.           lastTypeDef = header->typeDefs;
  1612.           while (lastTypeDef->next != NULL) {
  1613.             lastTypeDef = lastTypeDef->next;
  1614.           }
  1615.           lastTypeDef->next = typeDef;
  1616.         }
  1617.         break;
  1618.       case FUNCTIONS:
  1619.         funProto = parseFunctionProtos ();
  1620.         if (header->functionProtos == NULL) {
  1621.           header->functionProtos = funProto;
  1622.         } else {
  1623.           lastFunProto = header->functionProtos;
  1624.           while (lastFunProto->next != NULL) {
  1625.             lastFunProto = lastFunProto->next;
  1626.           }
  1627.           lastFunProto->next = funProto;
  1628.         }
  1629.         break;
  1630.       case INTERFACE:
  1631.         interface = parseInterface ();
  1632.         if (header->interfaces == NULL) {
  1633.           header->interfaces = interface;
  1634.         } else {
  1635.           lastInterface = header->interfaces;
  1636.           while (lastInterface->next != NULL) {
  1637.             lastInterface = lastInterface->next;
  1638.           }
  1639.           lastInterface->next = interface;
  1640.         }
  1641.         break;
  1642.       case CLASS:
  1643.         cl = parseClass ();
  1644.         if (header->classes == NULL) {
  1645.           header->classes = cl;
  1646.         } else {
  1647.           lastClass = header->classes;
  1648.           while (lastClass->next != NULL) {
  1649.             lastClass = lastClass->next;
  1650.           }
  1651.           lastClass->next = cl;
  1652.         }
  1653.         break;
  1654.       case EOF:
  1655.         syntaxError ("Missing 'endHeader'");
  1656.         return header;
  1657.       case END_HEADER:
  1658.         scan ();
  1659.         if (token.type != EOF) {
  1660.           syntaxError ("There should be nothing more after 'endHeader'");
  1661.         }
  1662.         header->hashVal = hashVal;     // Based on token sequence up to now
  1663.         return header;
  1664.       default:
  1665.         if (token.type == BEHAVIOR) {
  1666.           syntaxError ("Behaviors must be placed in a CodeFile, not in a HeaderFile");
  1667.         } else {
  1668.           syntaxError ("Expecting CONST, ERRORS, VAR, ENUM, TYPE, FUNCTIONS, INTERFACE, CLASS, or END_HEADER in HeaderFile");
  1669.         }
  1670.         count = 0;
  1671.         while (1) {
  1672.           if (inHeaderSet ()) break;
  1673.           scan ();
  1674.           count++;
  1675.         }
  1676.         checkTokenSkipping (count);
  1677.     }
  1678.   }
  1679. }
  1680.  
  1681.  
  1682.  
  1683. // parseCode ()
  1684. //
  1685. // This routine parses:
  1686. //    CodeFile     --> code ID
  1687. //                       { Const |
  1688. //                         Errors |
  1689. //                         VarDecls |
  1690. //                         Enum |
  1691. //                         TypeDef |
  1692. //                         Function |
  1693. //                         Interface |
  1694. //                         Class |
  1695. //                         Behavior }
  1696. //                     endCode
  1697. //
  1698. Code * parseCode () {
  1699.   Code * code;
  1700.   Global * newGlobals, * lastGlobal;
  1701.   ErrorDecl * newErrors, * lastError;
  1702.   ConstDecl * newConsts, * lastConst;
  1703.   TypeDef * typeDef, * lastTypeDef;
  1704.   Function * fun, * lastFun;
  1705.   Interface * interface, * lastInterface;
  1706.   ClassDef * cl, * lastClass;
  1707.   Behavior * behavior, * lastBehavior;
  1708.   int count;
  1709.  
  1710.   if (token.type != CODE) {
  1711.     syntaxError ("Expecting 'code' at beginning of code file");
  1712.     return NULL;
  1713.   }
  1714.   scan ();    // CODE
  1715.  
  1716.   code = new Code ();
  1717.  
  1718.   if (token.type == ID) {
  1719.     code->packageName = token.value.svalue;
  1720.     scan ();    // ID
  1721.   } else {
  1722.     syntaxError ("Expecting package name after 'code'");
  1723.     code->packageName = lookupAndAdd ("<missingPackageName>", ID);
  1724.   }
  1725.   while (1) {
  1726.     switch (token.type) {
  1727.       case CONST:
  1728.         newConsts = parseConstDecls ();
  1729.         if (code->consts == NULL) {
  1730.           code->consts = newConsts;
  1731.         } else {
  1732.           lastConst = code->consts;
  1733.           while (lastConst->next != NULL) {
  1734.             lastConst = lastConst->next;
  1735.           }
  1736.           lastConst->next = newConsts;
  1737.         }
  1738.         break;
  1739.       case ERRORS:
  1740.         newErrors = parseErrorDecls ();
  1741.         if (code->errors == NULL) {
  1742.           code->errors = newErrors;
  1743.         } else {
  1744.           lastError = code->errors;
  1745.           while (lastError->next != NULL) {
  1746.             lastError = lastError->next;
  1747.           }
  1748.           lastError->next = newErrors;
  1749.         }
  1750.         break;
  1751.         break;
  1752.       case VAR:
  1753.         newGlobals = parseGlobalVarDecls ();
  1754.         if (code->globals == NULL) {
  1755.           code->globals = newGlobals;
  1756.         } else {
  1757.           lastGlobal = code->globals;
  1758.           while (lastGlobal->next != NULL) {
  1759.             lastGlobal = (Global *) lastGlobal->next;
  1760.           }
  1761.           lastGlobal->next = newGlobals;
  1762.         }
  1763.         break;
  1764.       case ENUM:
  1765.         newConsts = parseEnums ();
  1766.         if (code->consts == NULL) {
  1767.           code->consts = newConsts;
  1768.         } else {
  1769.           lastConst = code->consts;
  1770.           while (lastConst->next != NULL) {
  1771.             lastConst = lastConst->next;
  1772.           }
  1773.           lastConst->next = newConsts;
  1774.         }
  1775.         break;
  1776.       case TYPE:
  1777.         typeDef = parseTypeDefs ();
  1778.         if (code->typeDefs == NULL) {
  1779.           code->typeDefs = typeDef;
  1780.         } else {
  1781.           lastTypeDef = code->typeDefs;
  1782.           while (lastTypeDef->next != NULL) {
  1783.             lastTypeDef = lastTypeDef->next;
  1784.           }
  1785.           lastTypeDef->next = typeDef;
  1786.         }
  1787.         break;
  1788.       case FUNCTION:
  1789.         fun = parseFunction (1);      //  Expecting ID = 1
  1790.         if (code->functions == NULL) {
  1791.           code->functions = fun;
  1792.         } else {
  1793.           lastFun = code->functions;
  1794.           while (lastFun->next != NULL) {
  1795.             lastFun = lastFun->next;
  1796.           }
  1797.           lastFun->next = fun;
  1798.         }
  1799.         break;
  1800.       case INTERFACE:
  1801.         interface = parseInterface ();
  1802.         if (code->interfaces == NULL) {
  1803.           code->interfaces = interface;
  1804.         } else {
  1805.           lastInterface = code->interfaces;
  1806.           while (lastInterface->next != NULL) {
  1807.             lastInterface = lastInterface->next;
  1808.           }
  1809.           lastInterface->next = interface;
  1810.         }
  1811.         break;
  1812.       case CLASS:
  1813.         cl = parseClass ();
  1814.         if (code->classes == NULL) {
  1815.           code->classes = cl;
  1816.         } else {
  1817.           lastClass = code->classes;
  1818.           while (lastClass->next != NULL) {
  1819.             lastClass = lastClass->next;
  1820.           }
  1821.           lastClass->next = cl;
  1822.         }
  1823.         break;
  1824.       case BEHAVIOR:
  1825.         behavior = parseBehavior ();
  1826.         if (code->behaviors == NULL) {
  1827.           code->behaviors = behavior;
  1828.         } else {
  1829.           lastBehavior = code->behaviors;
  1830.           while (lastBehavior->next != NULL) {
  1831.             lastBehavior = lastBehavior->next;
  1832.           }
  1833.           lastBehavior->next = behavior;
  1834.         }
  1835.         break;
  1836.       case EOF:
  1837.         syntaxError ("Missing 'endCode'");
  1838.         return code;
  1839.       case END_CODE:
  1840.         scan ();
  1841.         if (token.type != EOF) {
  1842.           syntaxError ("There should be nothing more after 'endCode'");
  1843.         }
  1844.         code->hashVal = hashVal;     // Based on token sequence up to now
  1845.         return code;
  1846.       default:
  1847.         syntaxError ("Expecting CONST, ERRORS, VAR, ENUM, TYPE, FUNCTION, INTERFACE, CLASS, BEHAVIOR, or END_CODE in CodeFile");
  1848.         count = 0;
  1849.         while (1) {
  1850.           if (inCodeSet ()) break;
  1851.           scan ();
  1852.           count++;
  1853.         }
  1854.         checkTokenSkipping (count);
  1855.     }
  1856.   }
  1857. }
  1858.  
  1859.  
  1860.  
  1861. // parseBehavior ()
  1862. //
  1863. // This routine parses:
  1864. //    Behavior     --> behavior ID
  1865. //                       { Method }
  1866. //                     endBehavior
  1867. //
  1868. Behavior * parseBehavior () {
  1869.   Behavior * behavior;
  1870.   Method * meth, * lastMeth;
  1871.   int count;
  1872.  
  1873.   if (token.type != BEHAVIOR) {
  1874.     programLogicError ("Already checked for behavior keyword");
  1875.   }
  1876.   scan ();    // BEHAVIOR
  1877.   behavior = new Behavior ();
  1878.   behavior->id = mustHaveID ("Expecting name of class after 'behavior' keyword");
  1879.   while (1) {
  1880.     switch (token.type) {
  1881.       case METHOD:
  1882.         meth = parseMethod ();
  1883.         if (behavior->methods == NULL) {
  1884.           behavior->methods = meth;
  1885.         } else {
  1886.           lastMeth->next = meth;
  1887.         }
  1888.         lastMeth = meth;
  1889.         break;
  1890.       case EOF:
  1891.         syntaxError ("Missing 'endBehavior'");
  1892.         return behavior;
  1893.       case END_BEHAVIOR:
  1894.         scan ();
  1895.         return behavior;
  1896.       default:
  1897.         syntaxError ("Expecting METHOD, END_CODE, or END_BEHAVIOR");
  1898.         count = 0;
  1899.         while (1) {
  1900.           if (token.type == METHOD) break;
  1901.           if (token.type == END_CODE) break;
  1902.           if (token.type == END_BEHAVIOR) break;
  1903.           if (token.type == EOF) break;
  1904.           scan ();
  1905.           count++;
  1906.         }
  1907.         checkTokenSkipping (count);
  1908.         if (token.type == END_CODE) return behavior;
  1909.     }
  1910.   }
  1911. }
  1912.  
  1913.  
  1914.  
  1915. // parseUses ()
  1916. //
  1917. // This routine parses the following:
  1918. //
  1919. //    Uses         --> [ uses OtherPackage { , OtherPackage } ]
  1920. //
  1921. //    OtherPackage --> ID ID [ renaming Rename { , Rename } ]
  1922. //
  1923. Uses * parseUses () {
  1924.   Uses * first, * last, * uses;
  1925.  
  1926.   if (token.type != USES) {
  1927.     return NULL;
  1928.   }
  1929.   first = last = NULL;
  1930.   scan ();     // USES
  1931.  
  1932.   //  Each iteration of this loop picks up another OtherPackage...
  1933.   while (1) {
  1934.     uses = new Uses ();
  1935.     if ((token.type == ID) || (token.type == STRING_CONST)) {
  1936.       uses->id = token.value.svalue;
  1937.       scan ();    // ID or STRING_CONST
  1938.     } else {
  1939.       syntaxError ("Expecting next package name in 'uses' clause");
  1940.       uses->id = lookupAndAdd ("<missingIdSyntaxError>", ID);
  1941.     }
  1942.     if (first) {
  1943.       last->next = uses;
  1944.     } else {
  1945.       first = uses;
  1946.     }
  1947.     last = uses;
  1948.     uses->renamings = parseRenamings ();
  1949.  
  1950.     // See if we have more and scan the comma
  1951.     if (token.type == COMMA) {
  1952.       scan ();       // COMMA
  1953.     } else if (token.type == ID) {
  1954.       syntaxError ("Expecting COMMA before next package name");
  1955.     } else {
  1956.       break;
  1957.     }
  1958.   }
  1959.   return first;
  1960. }
  1961.  
  1962.  
  1963.  
  1964. // parseRenamings ()
  1965. //
  1966. // This routine parses the following:
  1967. //
  1968. //                 --> ID [ renaming Rename { , Rename } ]
  1969. //    
  1970. //    Rename       --> ID to ID
  1971. //
  1972. Renaming * parseRenamings () {
  1973.   Renaming * firstRenaming, * lastRenaming, * renaming;
  1974.  
  1975.   if (token.type != RENAMING) {
  1976.     return NULL;
  1977.   }
  1978.   scan ();    // RENAMING
  1979.   // Each iteration of this loop picks up another Renaming...
  1980.   firstRenaming = lastRenaming = NULL;
  1981.   while (1) {
  1982.     renaming = new Renaming ();
  1983.     if (token.type == ID) {
  1984.       renaming->from = token.value.svalue;
  1985.       scan ();    // from-ID
  1986.       mustHave (TO, "Expecting 'to' in Renaming 'xxx to yyy'");
  1987.       renaming->to = mustHaveID ("Expecting ID2 in Renaming 'ID1 to ID2'");
  1988.     } else {
  1989.       syntaxError ("Expecting 'ID' in next renaming 'xxx to yyy'");
  1990.       scan ();
  1991.       if (token.type == TO) {
  1992.         scan ();
  1993.         scan ();
  1994.       }
  1995.       renaming->from = lookupAndAdd ("<missingIdSyntaxError>", ID);
  1996.       renaming->to = lookupAndAdd ("<missingIdSyntaxError>", ID);
  1997.     }
  1998.     if (firstRenaming) {
  1999.       lastRenaming->next = renaming;
  2000.     } else {
  2001.       firstRenaming = renaming;
  2002.     }
  2003.     lastRenaming = renaming;
  2004.     // See if we have more renamings
  2005.     if ( (token.type == COMMA) &&
  2006.          ((token3.type == COLON) || (token3.type == TO)) ) {
  2007.       scan ();       // COMMA
  2008.     } else if ((token2.type == TO) || (token2.type == COLON)) {
  2009.       syntaxError ("Expecting COMMA before next renaming clause");
  2010.     } else {
  2011.       break;
  2012.     }
  2013.   }
  2014.   return firstRenaming;
  2015. }
  2016.  
  2017.  
  2018. // pickupKeywordSelector ()
  2019. //
  2020. // This routine parses
  2021. //     { ID : }+
  2022. // It builds and return a selector.
  2023. //
  2024. String * pickupKeywordSelector () {
  2025.   char * newSelector;
  2026.  
  2027.   if ((token.type != ID) || (token2.type != COLON)) {
  2028.     syntaxError ("Expecting a keyword selector");
  2029.     return lookupAndAdd ("<missingIdSyntaxError>", ID);
  2030.   }
  2031.   newSelector = appendStrings (token.value.svalue->chars, ":", "");
  2032.   scan ();      // ID
  2033.   scan ();      // COLON
  2034.   while ((token.type == ID) && (token2.type == COLON)) {
  2035.     newSelector = appendStrings (newSelector, token.value.svalue->chars, ":");
  2036.     scan ();      // ID
  2037.     scan ();      // COLON
  2038.   }
  2039.   return lookupAndAdd (newSelector, ID);
  2040. }
  2041.  
  2042.  
  2043.  
  2044. // colonCount (char *) --> int
  2045. //
  2046. // This routine returns the number of colons in the given string.
  2047. //
  2048. int colonCount (char * str) {
  2049.   int i = 0;
  2050.   while (*str != '\0') {
  2051.     if (*str == ':') {
  2052.       i++;
  2053.     }
  2054.     str++;
  2055.   }
  2056.   return i;
  2057. }
  2058.  
  2059.  
  2060.  
  2061. // parseInterface ()
  2062. //
  2063. // This routine parses the following:
  2064. //    Interface    --> interface ID [ TypeParms ]
  2065. //                       [ extends TypeInstanceList ]
  2066. //                       [ messages { MethProto }+ ]
  2067. //                     endInterface
  2068.  
  2069. //
  2070. Interface * parseInterface () {
  2071.   Interface * interface;
  2072.   MethodProto * methProto, * lastMethProto;
  2073.   int count;
  2074.   TypeArg * typeArg, * lastTypeArg;
  2075.  
  2076.   if (token.type != INTERFACE) {
  2077.     programLogicError ("Already checked for INTERFACE keyword");
  2078.   }
  2079.   scan ();   // INTERFACE
  2080.   interface = new Interface ();
  2081.   interface->id = mustHaveID ("Expecting interface name after 'interface'");
  2082.   // Pick up TypeParms...
  2083.   interface->typeParms = parseTypeParms ();
  2084.   // Pick up 'extends' clause...
  2085.   if (token.type == EXTENDS) {
  2086.     scan ();
  2087.     lastTypeArg = NULL;
  2088.     while (1) {
  2089.       typeArg = new TypeArg ();
  2090.       typeArg->type = parseNamedType ("Expecting an interface name after 'extends'");
  2091.       if (lastTypeArg == NULL) {
  2092.         interface->extends = typeArg;
  2093.       } else {
  2094.         lastTypeArg->next = typeArg;
  2095.       }
  2096.       lastTypeArg = typeArg;
  2097.       if (token.type != COMMA) {
  2098.         break;
  2099.       }
  2100.       scan ();
  2101.     }
  2102.   }
  2103.   // Pick up 'messages' clause...
  2104.   if (token.type == MESSAGES || token.type == METHODS) {
  2105.     if (token.type == METHODS) {
  2106.       syntaxError ("Expecting 'messages', not 'methods'");
  2107.     }
  2108.     scan ();
  2109.     lastMethProto = parseMethodProto ();
  2110.     interface->methodProtos = lastMethProto;
  2111.     while (1) {
  2112.       if ((token.type == INFIX) ||
  2113.           (token.type == PREFIX) ||
  2114.           ((token.type == ID) && (token2.type == L_PAREN)) ||
  2115.           ((token.type == ID) && (token2.type == COLON)) ) {
  2116.         methProto = parseMethodProto ();
  2117.         lastMethProto->next = methProto;
  2118.         lastMethProto = methProto;
  2119.       } else if (token.type == END_INTERFACE) {
  2120.         break;
  2121.       } else {
  2122.         syntaxError ("Expecting next message prototype or 'endInterface'");
  2123.         count = 0;
  2124.         while (1) {
  2125.           if (inHeaderSet ()) break;
  2126.           if (token.type == INFIX) break;
  2127.           if (token.type == PREFIX) break;
  2128.           if ((token.type == ID) && (token2.type == L_PAREN)) break;
  2129.           if ((token.type == ID) && (token2.type == COLON)) break;
  2130.           if (token.type == END_INTERFACE) break;
  2131.           scan ();
  2132.           count++;
  2133.         }
  2134.         checkTokenSkipping (count);
  2135.         if (inHeaderSet ()) break;
  2136.       }
  2137.     }
  2138.   }
  2139.   mustHave (END_INTERFACE, "Expecting endInterface");
  2140.   return interface;
  2141. }
  2142.  
  2143.  
  2144.  
  2145. // parseTypeParms ()
  2146. //
  2147. // This routine parses...
  2148. //                 --> [ TypeParms ]
  2149. //    TypeParms    --> '[' ID : Type { , ID : Type } ']'
  2150. //
  2151. // It returns a pointer to linked list of TypeParms (or NULL).
  2152. //
  2153. TypeParm * parseTypeParms () {
  2154.   TypeParm * newParm, * first, * last;
  2155.  
  2156.   if (token.type != L_BRACK) {
  2157.     return NULL;
  2158.   }
  2159.   scan ();    // L_BRACK
  2160.   newParm = new TypeParm ();
  2161.   newParm->id = mustHaveID ("Expecting 'ID: Type' after '['");
  2162.   mustHave (COLON, "Expecting ':' in 'ID: Type'");
  2163.   newParm->type = parseType ("Expecting type after ':' in 'ID: Type'");
  2164.   first = last = newParm;
  2165.   while (token.type == COMMA) {
  2166.     scan ();   // COMMA
  2167.     newParm = new TypeParm ();
  2168.     newParm->id = mustHaveID ("Expecting 'ID: Type' after '['");
  2169.     mustHave (COLON, "Expecting ':' in 'ID: Type'");
  2170.     newParm->type = parseType ("Expecting type after ':' in 'ID: Type'");
  2171.     last->next = newParm;
  2172.     last = newParm;
  2173.   }
  2174.   if (token.type == R_BRACK) {
  2175.     scan ();      // R_BRACK
  2176.   } else {
  2177.     syntaxError ("Expecting ',' or ']' in type parameter list");
  2178.     if (token2.type == R_BRACK) {
  2179.       scan ();    // Junk
  2180.       scan ();    // R_BRACK
  2181.     }
  2182.   }
  2183.   return first;
  2184. }
  2185.  
  2186.  
  2187.  
  2188. // parseClass ()
  2189. //
  2190. // This routine parses the following:
  2191. //    Class        --> class ID [ TypeParms ]
  2192. //                       [ implements TypeInstanceList ]
  2193. //                         superclass TypeInstance
  2194. //                       [ fields { Decl }+ ]
  2195. //                       [ methods { MethProto }+ ]
  2196. //                     endClass
  2197.  
  2198. //
  2199. ClassDef * parseClass () {
  2200.   ClassDef * cl;
  2201.   MethodProto * methProto, * lastMethProto;
  2202.   int count, gotObject;
  2203.   TypeArg * typeArg, * lastTypeArg;
  2204.  
  2205.   if (token.type != CLASS) {
  2206.     programLogicError ("Already checked for CLASS keyword");
  2207.   }
  2208.   scan ();   // CLASS
  2209.   cl = new ClassDef ();
  2210.   cl->id = mustHaveID ("Expecting class name after 'class'");
  2211.   if (cl->id == stringObject) {
  2212.     gotObject = 1;
  2213.   } else {
  2214.     gotObject = 0;
  2215.   }
  2216.   // Pick up TypeParms...
  2217.   cl->typeParms = parseTypeParms ();
  2218.   if (gotObject && cl->typeParms) {
  2219.     syntaxError ("Not expecting typeParms in class Object");
  2220.   }
  2221.  
  2222.   // Pick up 'implements' clause...
  2223.   while ((token.type != IMPLEMENTS) &&
  2224.       (token.type != SUPER_CLASS) &&
  2225.       (token.type != FIELDS) &&
  2226.       (token.type != MESSAGES) &&
  2227.       (token.type != METHODS) &&
  2228.       (token.type != END_CLASS) &&
  2229.       (token.type != EOF)) {
  2230.     syntaxError ("Expecting IMPLEMENTS, SUPER_CLASS, FIELDS, METHODS, or END_CLASS in a class definition");
  2231.     scan ();
  2232.   }
  2233.   if (token.type == IMPLEMENTS) {
  2234.     scan ();
  2235.     lastTypeArg = NULL;
  2236.     while (1) {
  2237.       typeArg = new TypeArg ();
  2238.       typeArg->type = parseNamedType ("Expecting an interface name after 'implements'");
  2239.       if (lastTypeArg == NULL) {
  2240.         cl->implements = typeArg;
  2241.       } else {
  2242.         lastTypeArg->next = typeArg;
  2243.       }
  2244.       lastTypeArg = typeArg;
  2245.       if (token.type != COMMA) {
  2246.         break;
  2247.       }
  2248.       scan ();
  2249.     }
  2250.   }
  2251.  
  2252.   // Pick up the superclass clause...
  2253.   while ((token.type != SUPER_CLASS) &&
  2254.       (token.type != FIELDS) &&
  2255.       (token.type != MESSAGES) &&
  2256.       (token.type != METHODS) &&
  2257.       (token.type != END_CLASS) &&
  2258.       (token.type != EOF)) {
  2259.     syntaxError ("Expecting SUPER_CLASS, FIELDS, METHODS, or END_CLASS in a class definition");
  2260.     scan ();
  2261.   }
  2262.   if (token.type == SUPER_CLASS) {
  2263.     scan ();
  2264.     cl->superclass = parseNamedType ("Expecting a class name after 'superclass'");
  2265.     if (gotObject) {
  2266.       syntaxError ("Not expecting 'superclass...' in class Object");
  2267.     }
  2268.   } else {
  2269.     if (! gotObject) {
  2270.       syntaxError ("Expecting 'superclass...'; all classes except 'Object' must have a single superclass");
  2271.     }
  2272.   }
  2273.  
  2274.   // Check for common errors...
  2275.   if (token.type == IMPLEMENTS) {
  2276.     syntaxError ("The 'implements' clause should come before the 'superclass' clause");
  2277.   }
  2278.  
  2279.   // Pick up 'fields' clause...
  2280.   while ((token.type != FIELDS) &&
  2281.       (token.type != MESSAGES) &&
  2282.       (token.type != METHODS) &&
  2283.       (token.type != END_CLASS) &&
  2284.       (token.type != EOF)) {
  2285.     syntaxError ("Expecting FIELDS, METHODS, or END_CLASS in a class definition");
  2286.     scan ();
  2287.   }
  2288.   if (token.type == FIELDS) {
  2289.     scan ();
  2290.     cl->fields = parseClassFields ();
  2291.   }
  2292.  
  2293.   // Pick up 'methods' clause...
  2294.   while ((token.type != METHODS) &&
  2295.       (token.type != MESSAGES) &&
  2296.       (token.type != END_CLASS) &&
  2297.       (token.type != EOF)) {
  2298.     syntaxError ("Expecting METHODS or END_CLASS in a class definition");
  2299.     scan ();
  2300.   }
  2301.   if (token.type == METHODS || token.type == MESSAGES) {
  2302.     if (token.type == MESSAGES) {
  2303.       syntaxError ("Use METHODS, not MESSAGES");
  2304.     }
  2305.     scan ();
  2306.     lastMethProto = parseMethodProto ();
  2307.     cl->methodProtos = lastMethProto;
  2308.     while (1) {
  2309.       if ((token.type == INFIX) ||
  2310.           (token.type == PREFIX) ||
  2311.           ((token.type == ID) && (token2.type == L_PAREN)) ||
  2312.           ((token.type == ID) && (token2.type == COLON)) ) {
  2313.         methProto = parseMethodProto ();
  2314.         lastMethProto->next = methProto;
  2315.         lastMethProto = methProto;
  2316.       } else if (token.type == END_CLASS) {
  2317.         break;
  2318.       } else {
  2319.         if (token.type == METHOD) {
  2320.           syntaxError ("Methods must be placed in a 'behavior', not in the class specification");
  2321.         } else {
  2322.           syntaxError ("Expecting next method prototype or 'endClass'");
  2323.         }
  2324.         count = 0;
  2325.         while (1) {
  2326.           if (inHeaderSet ()) break;
  2327.           if (token.type == INFIX) break;
  2328.           if (token.type == PREFIX) break;
  2329.           if ((token.type == ID) && (token2.type == L_PAREN)) break;
  2330.           if ((token.type == ID) && (token2.type == COLON)) break;
  2331.           if (token.type == END_CLASS) break;
  2332.           scan ();
  2333.           count++;
  2334.         }
  2335.         checkTokenSkipping (count);
  2336.         if (inHeaderSet ()) break;
  2337.       }
  2338.     }
  2339.   }
  2340.   mustHave (END_CLASS, "Expecting END_CLASS in a class definition");
  2341.   return cl;
  2342. }
  2343.  
  2344.  
  2345.  
  2346. // parseType (errorMsg)
  2347. //
  2348. // This routine parses a Type and returns a pointer to a Type node.  If problems,
  2349. // it prints the 'msg' and returns a pointer to a VoidType.
  2350. //
  2351. // If syntax errors occur, IT MAY SCAN ZERO TOKENS.
  2352. //
  2353. Type * parseType (char * errorMsg) {
  2354.   Type * type;
  2355.   PtrType * ptrType;
  2356.   RecordType * recordType;
  2357.   ArrayType * arrayType;
  2358.   Token tokenForPos;
  2359.  
  2360.   // If the current token is wrong, try just skipping it.
  2361.   if (!inFirstType (token) && inFirstType (token2)) {
  2362.     syntaxError (errorMsg);
  2363.     scan ();
  2364.   }
  2365.  
  2366.   switch (token.type) {
  2367.   
  2368.     case INT:
  2369.       type = new IntType ();
  2370.       scan ();
  2371.       return type;
  2372.   
  2373.     case DOUBLE:
  2374.       type = new DoubleType ();
  2375.       scan ();
  2376.       return type;
  2377.   
  2378.     case CHAR:
  2379.       type = new CharType ();
  2380.       scan ();
  2381.       return type;
  2382.   
  2383.     case BOOL:
  2384.       type = new BoolType ();
  2385.       scan ();
  2386.       return type;
  2387.   
  2388.     case VOID:
  2389.       type = new VoidType ();
  2390.       scan ();
  2391.       return type;
  2392.   
  2393.     case TYPE_OF_NULL:
  2394.       type = new TypeOfNullType ();
  2395.       scan ();
  2396.       return type;
  2397.    
  2398.     case ANY_TYPE:
  2399.       type = new AnyType ();
  2400.       scan ();
  2401.       return type;
  2402.  
  2403.     case PTR:
  2404.       ptrType = new PtrType ();
  2405.       scan ();
  2406.       mustHave (TO, "Expecting 'to' in 'ptr to Type'");
  2407.       ptrType->baseType = parseType ("Expecting type after 'to' in 'ptr to Type'");
  2408.       return ptrType;
  2409.   
  2410.     case ARRAY:
  2411.       tokenForPos = token;
  2412.       scan ();    // ARRAY
  2413.       if (token.type == L_BRACK) {
  2414.         scan ();
  2415.         return parseArrayType (tokenForPos);
  2416.       } else {
  2417.  
  2418.         // In the old syntax "[*]" was not optional; now it is optional...
  2419.         // syntaxError ("Expecting '[' in 'array [...] of Type'");
  2420.         // scanToFollowType ();
  2421.         // arrayType = new ArrayType ();
  2422.         // arrayType->positionAtToken (tokenForPos);
  2423.         // arrayType->baseType = new VoidType ();
  2424.         // return arrayType;
  2425.  
  2426.         arrayType = new ArrayType ();
  2427.         arrayType->positionAtToken (tokenForPos);
  2428.         if (token.type == OF) {
  2429.           scan ();
  2430.         } else {
  2431.           syntaxError ("Expecting '[' or 'of' in 'array [...] of Type'");
  2432.           scanToFollowType ();
  2433.           arrayType->baseType = new VoidType ();
  2434.           return arrayType;
  2435.         }
  2436.         arrayType->baseType = parseType ("Expecting base type in 'array of BaseType'");
  2437.         return arrayType;
  2438.       }
  2439.   
  2440.     case RECORD:
  2441.       recordType = new RecordType ();
  2442.       scan ();
  2443.       recordType->fields = parseRecordFieldList ();
  2444.       return recordType;
  2445.   
  2446.     case FUNCTION:
  2447.       return parseFunctionType ();
  2448.   
  2449.     case ID:
  2450.       return parseNamedType ("Program Logic Error: only prints error if an ID is not seen");
  2451.   
  2452.     default:
  2453.       syntaxError (errorMsg);
  2454.       type = new VoidType ();
  2455.       return type;
  2456.   }
  2457.   return new VoidType ();
  2458. }
  2459.  
  2460.  
  2461.  
  2462. // parseRecordFieldList ()
  2463. //
  2464. // This routine parses
  2465. //    { Decl }+ endRecord
  2466. // and returns a pointer to linked list of RecordFields.  If problems, it
  2467. // may return NULL.  It may scan zero tokens.
  2468. //
  2469. RecordField * parseRecordFieldList () {
  2470.   RecordField * first, * last, * idListFirst, * idListLast, * field;
  2471.   Type * type;
  2472.   first = last = NULL;
  2473.   while (token.type == ID) {
  2474.     // Pick up a list of ID's
  2475.     idListFirst = idListLast = NULL;
  2476.     while (token.type == ID) {
  2477.       field = new RecordField ();
  2478.       field->id = token.value.svalue;
  2479.       scan ();    // ID
  2480.       if (idListFirst == NULL) {
  2481.         idListFirst = field;
  2482.       } else {
  2483.         idListLast->next = field;
  2484.       }
  2485.       idListLast = field;
  2486.       if (token.type != COMMA) {
  2487.         break;
  2488.       }
  2489.       scan ();     // COMMA
  2490.     }
  2491.     // Pick up a type
  2492.     mustHave (COLON, "Expecting ':' in 'fieldID: Type'");
  2493.     type = parseType ("Expecting type after ':' in 'fieldID: Type'");
  2494.     // Now run through the ID's.  Add in the type and add to the growing field list.
  2495.     while (idListFirst) {
  2496.       idListFirst->type = type;
  2497.       if (first == NULL) {
  2498.         first = idListFirst;
  2499.       } else {
  2500.         last->next = idListFirst;
  2501.       }
  2502.       last = idListFirst;
  2503.       idListFirst = (RecordField *) idListFirst->next;
  2504.     }
  2505.     last->next = NULL;
  2506.   }
  2507.   mustHave (END_RECORD, "Expecting next field or 'endRecord' in record type");
  2508.   if (first == NULL) {
  2509.     syntaxError ("Must have at least one field in a record type");
  2510.   }
  2511.   return first;
  2512. }
  2513.  
  2514.  
  2515.  
  2516. // parseFunctionType ()
  2517. //
  2518. // This routine parses
  2519. //    function '(' [ Type { , Type } ] ')' [ returns Type ]
  2520. // and returns a FunctionType.  It will scan at least one token.
  2521. //
  2522. FunctionType * parseFunctionType () {
  2523.   FunctionType * functionType;
  2524.   TypeArg * typeArg, * last;
  2525.   functionType = new FunctionType ();
  2526.   scan ();     // FUNCTION keyword
  2527.   mustHave (L_PAREN, "Expecting '(Type, Type, ...)' after 'function' in function type");
  2528.   if (token.type != R_PAREN) {
  2529.     last = NULL;
  2530.     while (1) {
  2531.       typeArg = new TypeArg ();
  2532.       typeArg->type = parseType ("Expecting next type in 'function (Type, Type, ...)'");
  2533.       if (last == NULL) {
  2534.         functionType->parmTypes = typeArg;
  2535.       } else {
  2536.         last->next = typeArg;
  2537.       }
  2538.       last = typeArg;
  2539.       if (token.type != COMMA) {
  2540.         break;
  2541.       }
  2542.       scan ();
  2543.     }
  2544.   }
  2545.   if (token.type == COLON) {
  2546.     mustHave (R_PAREN, "Parameter names are not allowed in function types");
  2547.   } else {
  2548.     mustHave (R_PAREN, "Expecting ',' or ')' in parameter type list");
  2549.   }
  2550.   if (token.type == RETURNS) {
  2551.     scan ();
  2552.     functionType->retType = parseType ("Expecting return type after RETURNS");
  2553.   // A common error is to use 'return' instead of 'returns', but we
  2554.   // cannot do a special check for this error.  Consider
  2555.   //      if x isKindOf ptr to function (int)
  2556.   //        return 123
  2557.   //      else
  2558.   //        return 456
  2559.   //      endIf
  2560.   // } else if ((token.type == RETURN) &&
  2561.   //            (token2.type != END_FUNCTION)) {
  2562.   //   syntaxError ("Expecting RETURNS, not RETURN");
  2563.   //   scan ();
  2564.   //   functionType->retType = parseType ("Expecting return type after RETURNS");
  2565.     if (gotVoidType (functionType->retType)) {
  2566.       syntaxError ("Do not say 'returns void'; just leave it out");
  2567.     }
  2568.   } else {
  2569.     functionType->retType = new VoidType ();
  2570.   }
  2571.   return functionType;
  2572. }
  2573.  
  2574.  
  2575.  
  2576. // parseNamedType (errorMsg)
  2577. //
  2578. // This routine parses
  2579. //    ID [ '[' Type { , Type } ']' ]
  2580. // and returns a NamedType.  It may scan zero tokens, if there are errors.
  2581. //
  2582. NamedType * parseNamedType (char * errorMsg) {
  2583.   TypeArg * typeArg, * last;
  2584.   NamedType * namedType;
  2585.   namedType = new NamedType ();
  2586.   namedType->id = mustHaveID (errorMsg);
  2587.   if (token.type == L_BRACK) {
  2588.     scan ();    // L_BRACK
  2589.     last = NULL;
  2590.     while (1) {
  2591.       typeArg = new TypeArg ();
  2592.       typeArg->type = parseType ("Expecting next type in parameterized type 'ID[Type,Type,...]'");
  2593.       if (last == NULL) {
  2594.         namedType->typeArgs = typeArg;
  2595.       } else {
  2596.         last->next = typeArg;
  2597.       }
  2598.       last = typeArg;
  2599.       if (token.type != COMMA) {
  2600.         break;
  2601.       }
  2602.       scan ();   // COMMA
  2603.     }
  2604.     mustHave (R_BRACK, "Expecting ',' or ']' in parameter type list");
  2605.   }
  2606.   return namedType;
  2607. }
  2608.  
  2609.  
  2610.  
  2611. // parseArrayType (tokenForPos)
  2612. //
  2613. // This routine parses according to this syntax:
  2614. //    ( '*' | Expr ) { , ( '*' | Expr ) } ']' of Type
  2615. // and returns an ArrayType.  It calls itself recursively; Each invocation
  2616. // will pick up one sizeExpression and will allocate one ArrayType node.
  2617. //
  2618. // It positions the ArrayType node on the "tokenForPos".
  2619. //
  2620. ArrayType * parseArrayType (Token tokenForPos) {
  2621.   ArrayType * arrayType;
  2622.   arrayType = new ArrayType ();
  2623.   arrayType->positionAtToken (tokenForPos);
  2624.   arrayType->baseType = new VoidType ();
  2625.   if ((token.type == OPERATOR) && (token.value.svalue == stringStar)) {
  2626.     scan ();    // implicitly set arrayType->sizeExpr to NULL
  2627.   } else if (inFirstExpr (token)) {
  2628.     arrayType->sizeExpr = parseExpr ("Expecting a size expression");
  2629.   } else {
  2630.     syntaxError ("Expecting Expr or '*' after '[' or ',' in 'array [...] of Type'");
  2631.     scanToFollowType ();
  2632.     return arrayType;
  2633.   }
  2634.   if (token.type == R_BRACK) {
  2635.     scan ();
  2636.     if (token.type == OF) {
  2637.       scan ();
  2638.     } else {
  2639.       syntaxError ("Expecting 'of' in 'array [...] of Type'");
  2640.       scanToFollowType ();
  2641.       return arrayType;
  2642.     }
  2643.     arrayType->baseType = parseType ("Expecting base type in 'array [...] of BaseType'");
  2644.     return arrayType;
  2645.   } else if (token.type == COMMA) {
  2646.     scan ();
  2647.     arrayType->baseType = parseArrayType (tokenForPos);
  2648.     return arrayType;
  2649.   } else {
  2650.     syntaxError ("Expecting ']' or ',' in 'array [...] of Type'");
  2651.     scanToFollowType ();
  2652.     return arrayType;
  2653.   }
  2654. }
  2655.  
  2656.  
  2657.  
  2658. /*----------  Here is the parsing precedence table.  All are left-associative.  ----------
  2659.  
  2660. 1:   Keyword messages
  2661.  
  2662. 2:   Other Infix
  2663.  
  2664. 3:   |
  2665.  
  2666. 4:   ^
  2667.  
  2668. 5:   &
  2669.  
  2670. 6:   ||
  2671.  
  2672. 7:   ^^   <--- Boolean X-OR was eliminated, since it is the same as !=
  2673.  
  2674. 8:   &&
  2675.  
  2676. 9:   ==  !=
  2677.  
  2678. 10:  <  <=  >  >=
  2679.  
  2680. 11:  <<  >>  >>>
  2681.  
  2682. 12:  +  -
  2683.  
  2684. 13:  *  /  %
  2685.  
  2686. 15:  All Prefix Operators
  2687.  
  2688. 16:  x.m()  x.f  a[...]  special(asPtr2,asInt,arraySize,isInstOf,isKindOf)
  2689.  
  2690. 17:  (expr)  constants  closure  x  foo()  new  alloc  sizeOf
  2691.  
  2692. ----------*/
  2693.  
  2694.  
  2695.  
  2696. // parseExpr (errorMsg)
  2697. //
  2698. // This routine parses the grammar rule:
  2699. //    Expr  -->  Expr1
  2700. //
  2701. // This routine never returns NULL, even if there are parsing errors.
  2702. // This routine may scan ZERO tokens.
  2703. //
  2704. Expression * parseExpr (char * errorMsg) {
  2705.  
  2706.   // If the current token is wrong, try just skipping it.
  2707.   if (!inFirstExpr (token) && inFirstExpr (token2)) {
  2708.     syntaxError (errorMsg);
  2709.     scan ();
  2710.   }
  2711.  
  2712.   return parseExpr1 (errorMsg);
  2713. }
  2714.  
  2715.  
  2716.  
  2717. // parseExpr0 (errorMsg)
  2718. //
  2719. // This routine parses the grammar rule:
  2720. //    Expr  -->  Expr2
  2721. //
  2722. // It has basically the same behavior as "parseExpr", except that keyword messages
  2723. // (which are handled in parseExpr1) are not recognized unless they are in
  2724. // parentheses.  This routine is used in parsing VarDecls (instead of parseExpr),
  2725. // since we have a problem with keyword expressions being confused with additional
  2726. // declarations.
  2727. //
  2728. // Consider
  2729. //    var  x: T = a at: b
  2730. // and
  2731. //    var x: T = a
  2732. //        y: T ...
  2733. // In each case, we have:
  2734. //    VAR ID : Type = ID ID : ...
  2735. // Since it is impossible to distinguish these two rather different interpretations,
  2736. // we needed to do something.  The following changes to the grammar were
  2737. // considered and ruled out.
  2738. //     (1)   var x: T = a at: b;
  2739. //               y: T = ...;
  2740. //     (2)   var x: T = a at: b,
  2741. //               y: T = ...
  2742. //     (3)   var x: T = a at: b
  2743. //               y: T = ...
  2744. //           endVar
  2745. //     (4)   var x: T = a at: b
  2746. //               y: T = ...
  2747. //           do...
  2748. // By using parseExpr0, the user will be required to insert something (namely,
  2749. // parentheses) only for this particular problem case:
  2750. //     var x: T = a + 1
  2751. //         y: T = (a at: b)
  2752. //         z: T = c
  2753. //
  2754. Expression * parseExpr0 (char * errorMsg) {
  2755.  
  2756.   // If the current token is wrong, try just skipping it.
  2757.   if (!inFirstExpr (token) && inFirstExpr (token2)) {
  2758.     syntaxError (errorMsg);
  2759.     scan ();
  2760.   }
  2761.  
  2762.   return parseExpr2 (errorMsg);
  2763. }
  2764.  
  2765.  
  2766.  
  2767. // parseExpr1 (errorMsg)
  2768. //
  2769. // This routine parses the grammar rule:
  2770. //    Expr1  -->  Expr2 { ID ':' Expr2 }*            // SendExpr
  2771. // For example:
  2772. //    x at: y put: z
  2773. //
  2774. // This routine builds up a string such as "at:put:" and (by calling "lookupAndAdd")
  2775. // enters it in the string table as an ID.
  2776. //
  2777. Expression * parseExpr1 (char * errorMsg) {
  2778.   Expression * a;
  2779.   SendExpr * sendExpr;
  2780.   Argument * arg, * lastArg;
  2781.   char * newSelector;
  2782.  
  2783.   a = parseExpr2 (errorMsg);
  2784.   if ((token.type != ID) || (token2.type != COLON)) {
  2785.     return a;
  2786.   }
  2787.   sendExpr = new SendExpr ();
  2788.   newSelector = appendStrings (token.value.svalue->chars, ":", "");
  2789.   sendExpr->kind = KEYWORD;
  2790.   scan ();      // ID
  2791.   scan ();      // COLON
  2792.   sendExpr->receiver = a;
  2793.   arg = new Argument ();
  2794.   arg->expr = parseExpr2 ("Expecting first argument expression after ':'");
  2795.   sendExpr->argList = arg;
  2796.   lastArg = arg;
  2797.   while (1) {
  2798.     if ((token.type != ID) || (token2.type != COLON)) {
  2799.       sendExpr->selector = lookupAndAdd (newSelector, ID);
  2800.       return sendExpr;
  2801.     }
  2802.     newSelector = appendStrings (newSelector, token.value.svalue->chars, ":");
  2803.     arg = new Argument ();
  2804.     scan ();      // ID
  2805.     scan ();      // COLON
  2806.     arg->expr = parseExpr2 ("Expecting next argument expression after ':'");
  2807.     lastArg->next = arg;
  2808.     lastArg = arg;
  2809.   }
  2810. }
  2811.  
  2812.  
  2813.  
  2814. // parseExpr2 (errorMsg)
  2815. //
  2816. // This routine parses the grammar rule:
  2817. //    Expr2  -->  Expr3 { OPERATOR Expr3 }            // SendExpr (INFIX)
  2818. //
  2819. Expression * parseExpr2 (char * errorMsg) {
  2820.   Expression * a;
  2821.   SendExpr * sendExpr;
  2822.   Argument * arg;
  2823.  
  2824.   a = parseExpr3 (errorMsg);
  2825.   while (1) {
  2826.     if ((token.type == OPERATOR) &&
  2827.        (token.value.svalue != stringBarBar) &&
  2828.        (token.value.svalue != stringAmpAmp) &&
  2829.        (token.value.svalue != stringBar) &&
  2830.        (token.value.svalue != stringCaret) &&
  2831.        (token.value.svalue != stringAmp) &&
  2832.        (token.value.svalue != stringEqualEqual) &&
  2833.        (token.value.svalue != stringNotEqual) &&
  2834.        (token.value.svalue != stringLess) &&
  2835.        (token.value.svalue != stringLessEqual) &&
  2836.        (token.value.svalue != stringGreater) &&
  2837.        (token.value.svalue != stringGreaterEqual) &&
  2838.        (token.value.svalue != stringLessLess) &&
  2839.        (token.value.svalue != stringGreaterGreater) &&
  2840.        (token.value.svalue != stringGreaterGreaterGreater) &&
  2841.        (token.value.svalue != stringPlus) &&
  2842.        (token.value.svalue != stringMinus) &&
  2843.        (token.value.svalue != stringStar) &&
  2844.        (token.value.svalue != stringSlash) &&
  2845.        (token.value.svalue != stringPercent)
  2846.       ) {
  2847.       sendExpr = new SendExpr ();
  2848.       sendExpr->selector = token.value.svalue;
  2849.       sendExpr->kind = INFIX;
  2850.       scan ();
  2851.       sendExpr->receiver = a;
  2852.       arg = new Argument ();
  2853.       arg->expr = parseExpr3 (errorMsg);
  2854.       sendExpr->argList = arg;
  2855.       a = sendExpr;
  2856.     } else {
  2857.       return a;
  2858.     }
  2859.   }
  2860. }
  2861.  
  2862.  
  2863.  
  2864. // parseExpr3 (errorMsg)
  2865. //
  2866. // This routine parses the grammar rule:
  2867. //    Expr3  -->  Expr5 { '||' Expr5 }        // SendExpr (INFIX)
  2868. //
  2869. Expression * parseExpr3 (char * errorMsg) {
  2870.   Expression * a;
  2871.   SendExpr * sendExpr;
  2872.   Argument * arg;
  2873.  
  2874.   a = parseExpr5 (errorMsg);
  2875.   while (1) {
  2876.     if ((token.type == OPERATOR) && (
  2877.            (token.value.svalue == stringBarBar)
  2878.                                      )) {
  2879.       sendExpr = new SendExpr ();
  2880.       sendExpr->selector = token.value.svalue;
  2881.       sendExpr->kind = INFIX;
  2882.       scan ();
  2883.       sendExpr->receiver = a;
  2884.       arg = new Argument ();
  2885.       arg->expr = parseExpr5 (errorMsg);
  2886.       sendExpr->argList = arg;
  2887.       a = sendExpr;
  2888.     } else {
  2889.       return a;
  2890.     }
  2891.   }
  2892. }
  2893.  
  2894.  
  2895.  
  2896. // parseExpr5 (errorMsg)
  2897. //
  2898. // This routine parses the grammar rule:
  2899. //    Expr5  -->  Expr6 { '&&' Expr6 }           // SendExpr (INFIX)
  2900. //
  2901. Expression * parseExpr5 (char * errorMsg) {
  2902.   Expression * a;
  2903.   SendExpr * sendExpr;
  2904.   Argument * arg;
  2905.  
  2906.   a = parseExpr6 (errorMsg);
  2907.   while (1) {
  2908.     if ((token.type == OPERATOR) && (
  2909.            (token.value.svalue == stringAmpAmp)
  2910.                                      )) {
  2911.       sendExpr = new SendExpr ();
  2912.       sendExpr->selector = token.value.svalue;
  2913.       sendExpr->kind = INFIX;
  2914.       scan ();
  2915.       sendExpr->receiver = a;
  2916.       arg = new Argument ();
  2917.       arg->expr = parseExpr6 (errorMsg);
  2918.       sendExpr->argList = arg;
  2919.       a = sendExpr;
  2920.     } else {
  2921.       return a;
  2922.     }
  2923.   }
  2924. }
  2925.  
  2926.  
  2927.  
  2928. // parseExpr6 (errorMsg)
  2929. //
  2930. // This routine parses the grammar rule:
  2931. //    Expr6  -->  Expr7 { '|' Expr7 }           // SendExpr (INFIX)
  2932. //
  2933. Expression * parseExpr6 (char * errorMsg) {
  2934.   Expression * a;
  2935.   SendExpr * sendExpr;
  2936.   Argument * arg;
  2937.  
  2938.   a = parseExpr7 (errorMsg);
  2939.   while (1) {
  2940.     if ((token.type == OPERATOR) && (
  2941.            (token.value.svalue == stringBar)
  2942.                                      )) {
  2943.       sendExpr = new SendExpr ();
  2944.       sendExpr->selector = token.value.svalue;
  2945.       sendExpr->kind = INFIX;
  2946.       scan ();
  2947.       sendExpr->receiver = a;
  2948.       arg = new Argument ();
  2949.       arg->expr = parseExpr7 (errorMsg);
  2950.       sendExpr->argList = arg;
  2951.       a = sendExpr;
  2952.     } else {
  2953.       return a;
  2954.     }
  2955.   }
  2956. }
  2957.  
  2958.  
  2959.  
  2960. // parseExpr7 (errorMsg)
  2961. //
  2962. // This routine parses the grammar rule:
  2963. //    Expr7  -->  Expr8 { '^' Expr8 }           // SendExpr (INFIX)
  2964. //
  2965. Expression * parseExpr7 (char * errorMsg) {
  2966.   Expression * a;
  2967.   SendExpr * sendExpr;
  2968.   Argument * arg;
  2969.  
  2970.   a = parseExpr8 (errorMsg);
  2971.   while (1) {
  2972.     if ((token.type == OPERATOR) && (
  2973.            (token.value.svalue == stringCaret)
  2974.                                      )) {
  2975.       sendExpr = new SendExpr ();
  2976.       sendExpr->selector = token.value.svalue;
  2977.       sendExpr->kind = INFIX;
  2978.       scan ();
  2979.       sendExpr->receiver = a;
  2980.       arg = new Argument ();
  2981.       arg->expr = parseExpr8 (errorMsg);
  2982.       sendExpr->argList = arg;
  2983.       a = sendExpr;
  2984.     } else {
  2985.       return a;
  2986.     }
  2987.   }
  2988. }
  2989.  
  2990.  
  2991.  
  2992. // parseExpr8 (errorMsg)
  2993. //
  2994. // This routine parses the grammar rule:
  2995. //    Expr8  -->  Expr9 { '&' Expr9 }           // SendExpr (INFIX)
  2996. //
  2997. Expression * parseExpr8 (char * errorMsg) {
  2998.   Expression * a;
  2999.   SendExpr * sendExpr;
  3000.   Argument * arg;
  3001.  
  3002.   a = parseExpr9 (errorMsg);
  3003.   while (1) {
  3004.     if ((token.type == OPERATOR) && (
  3005.            (token.value.svalue == stringAmp)
  3006.                                      )) {
  3007.       sendExpr = new SendExpr ();
  3008.       sendExpr->selector = token.value.svalue;
  3009.       sendExpr->kind = INFIX;
  3010.       scan ();
  3011.       sendExpr->receiver = a;
  3012.       arg = new Argument ();
  3013.       arg->expr = parseExpr9 (errorMsg);
  3014.       sendExpr->argList = arg;
  3015.       a = sendExpr;
  3016.     } else {
  3017.       return a;
  3018.     }
  3019.   }
  3020. }
  3021.  
  3022.  
  3023.  
  3024. // parseExpr9 (errorMsg)
  3025. //
  3026. // This routine parses the grammar rule:
  3027. //    Expr9  -->  Expr10 {
  3028. //                           '==' Expr10            // SendExpr (INFIX)
  3029. //                           '!=' Expr10            // SendExpr (INFIX)
  3030. //                                       }
  3031. //
  3032. Expression * parseExpr9 (char * errorMsg) {
  3033.   Expression * a;
  3034.   SendExpr * sendExpr;
  3035.   Argument * arg;
  3036.  
  3037.   a = parseExpr10 (errorMsg);
  3038.   while (1) {
  3039.     if ((token.type == OPERATOR) && (
  3040.            (token.value.svalue == stringEqualEqual) ||
  3041.            (token.value.svalue == stringNotEqual)
  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 = parseExpr10 (errorMsg);
  3050.       sendExpr->argList = arg;
  3051.       a = sendExpr;
  3052.     } else {
  3053.       return a;
  3054.     }
  3055.   }
  3056. }
  3057.  
  3058.  
  3059.  
  3060. // parseExpr10 (errorMsg)
  3061. //
  3062. // This routine parses the grammar rule:
  3063. //    Expr10  -->  Expr11 {
  3064. //                           '<' Expr11            // SendExpr (INFIX)
  3065. //                           '<=' Expr11            // SendExpr (INFIX)
  3066. //                           '>' Expr11            // SendExpr (INFIX)
  3067. //                           '>=' Expr11            // SendExpr (INFIX)
  3068. //                                       }
  3069. //
  3070. Expression * parseExpr10 (char * errorMsg) {
  3071.   Expression * a;
  3072.   SendExpr * sendExpr;
  3073.   Argument * arg;
  3074.  
  3075.   a = parseExpr11 (errorMsg);
  3076.   while (1) {
  3077.     if ((token.type == OPERATOR) && (
  3078.            (token.value.svalue == stringLess) ||
  3079.            (token.value.svalue == stringLessEqual) ||
  3080.            (token.value.svalue == stringGreater) ||
  3081.            (token.value.svalue == stringGreaterEqual)
  3082.                                      )) {
  3083.       sendExpr = new SendExpr ();
  3084.       sendExpr->selector = token.value.svalue;
  3085.       sendExpr->kind = INFIX;
  3086.       scan ();
  3087.       sendExpr->receiver = a;
  3088.       arg = new Argument ();
  3089.       arg->expr = parseExpr11 (errorMsg);
  3090.       sendExpr->argList = arg;
  3091.       a = sendExpr;
  3092.     } else {
  3093.       return a;
  3094.     }
  3095.   }
  3096. }
  3097.  
  3098.  
  3099.  
  3100. // parseExpr11 (errorMsg)
  3101. //
  3102. // This routine parses the grammar rule:
  3103. //    Expr11  -->  Expr12 {
  3104. //                           '<<' Expr12            // SendExpr (INFIX)
  3105. //                           '>>' Expr12            // SendExpr (INFIX)
  3106. //                           '>>>' Expr12            // SendExpr (INFIX)
  3107. //                                       }
  3108. //
  3109. Expression * parseExpr11 (char * errorMsg) {
  3110.   Expression * a;
  3111.   SendExpr * sendExpr;
  3112.   Argument * arg;
  3113.  
  3114.   a = parseExpr12 (errorMsg);
  3115.   while (1) {
  3116.     if ((token.type == OPERATOR) && (
  3117.            (token.value.svalue == stringLessLess) ||
  3118.            (token.value.svalue == stringGreaterGreater) ||
  3119.            (token.value.svalue == stringGreaterGreaterGreater)
  3120.                                      )) {
  3121.       sendExpr = new SendExpr ();
  3122.       sendExpr->selector = token.value.svalue;
  3123.       sendExpr->kind = INFIX;
  3124.       scan ();
  3125.       sendExpr->receiver = a;
  3126.       arg = new Argument ();
  3127.       arg->expr = parseExpr12 (errorMsg);
  3128.       sendExpr->argList = arg;
  3129.       a = sendExpr;
  3130.     } else {
  3131.       return a;
  3132.     }
  3133.   }
  3134. }
  3135.  
  3136.  
  3137.  
  3138. // parseExpr12 (errorMsg)
  3139. //
  3140. // This routine parses the grammar rule:
  3141. //    Expr12  -->  Expr13 {
  3142. //                           '+' Expr13            // SendExpr (INFIX)
  3143. //                           '-' Expr13            // SendExpr (INFIX)
  3144. //                                       }
  3145. //
  3146. Expression * parseExpr12 (char * errorMsg) {
  3147.   Expression * a;
  3148.   SendExpr * sendExpr;
  3149.   Argument * arg;
  3150.  
  3151.   a = parseExpr13 (errorMsg);
  3152.   while (1) {
  3153.     if ((token.type == OPERATOR) && (
  3154.            (token.value.svalue == stringPlus) ||
  3155.            (token.value.svalue == stringMinus)
  3156.                                      )) {
  3157.       sendExpr = new SendExpr ();
  3158.       sendExpr->selector = token.value.svalue;
  3159.       sendExpr->kind = INFIX;
  3160.       scan ();
  3161.       sendExpr->receiver = a;
  3162.       arg = new Argument ();
  3163.       arg->expr = parseExpr13 (errorMsg);
  3164.       sendExpr->argList = arg;
  3165.       a = sendExpr;
  3166.     } else {
  3167.       return a;
  3168.     }
  3169.   }
  3170. }
  3171.  
  3172.  
  3173.  
  3174. // parseExpr13 (errorMsg)
  3175. //
  3176. // This routine parses the grammar rule:
  3177. //    Expr13  -->  Expr15 {
  3178. //                           '*' Expr15            // SendExpr (INFIX)
  3179. //                           '/' Expr15            // SendExpr (INFIX)
  3180. //                           '%' Expr15            // SendExpr (INFIX)
  3181. //                                       }
  3182. //
  3183. // There is an ambiguity in the grammer.  Consider:
  3184. //   expr -->  expr '*' expr
  3185. // Any opertor, such as '*', may be interpreted as infix or prefix.
  3186. // Here are two examples, that *might* look legal.
  3187. //   x = 123 * p.foo()
  3188. //
  3189. //   x = 123
  3190. //   *p.foo()
  3191. //
  3192. // However, the last stmt is not actually legal since it would be interpreted as:
  3193. //   *(p.foo())
  3194. // since prefix binds more loosely than message-send-dot.  This violates the
  3195. // syntax of the language (prefix expressions always returns values, so they cannot
  3196. // be used at the statement level).  If you want the other interpretation, you would
  3197. // have to add parentheses anyway, so it would look like this:
  3198. //   x = 123
  3199. //   (*p).foo()
  3200. // This would preclude the interpretation of * as a binary operator.
  3201. //
  3202. // This applies to all operator symbols, such as +, -, and *.  However, there is a
  3203. // second use of "*" that causes parsing problems.  Consider this sequence of tokens:
  3204. //   x = 123 * p ...
  3205. // This could have two interpretations, as shown by these examples:
  3206. //   x = 123
  3207. //   *p = 456       -- prefix operator (deref is OK for lhs of assignment)
  3208. // or
  3209. //   x = 123 * p    -- binary operator
  3210. //
  3211. // Since "p" could be an arbitrary expression, we must distinguish the cases here in
  3212. // this routine before parsing "p".  We do this with the following (non-CFG)
  3213. // restrictions:
  3214. //
  3215. //   (1) If a "*" is preceded by a newline, it is assumed to be a prefix operator
  3216. //   (2) If a "*" occurs on the same line as the previous token, we assume it is
  3217. //       an infix operator.
  3218. //
  3219. // In the rare case when you want two such statements on the same line, you would have
  3220. // to use parentheses to force the desired interpretation.  For example:
  3221. //   x = 123   (*p) = 456
  3222. // If you have long infix expressions which must be spread over several lines, do it
  3223. // like this:
  3224. //   x = aaaaaa *
  3225. //         bbbbbb *
  3226. //         cccccc
  3227. //
  3228. Expression * parseExpr13 (char * errorMsg) {
  3229.   Expression * a;
  3230.   SendExpr * sendExpr;
  3231.   Argument * arg;
  3232.  
  3233.   a = parseExpr15 (errorMsg);
  3234.   while (1) {
  3235.     // If this token is "*" and it is on the same line as the last token,
  3236.     // or we have "/" or "%"...
  3237.     if ((token.type == OPERATOR) &&
  3238.         (((token.value.svalue == stringStar) &&
  3239.           (extractLineNumber (tokenMinusOne) == extractLineNumber (token))) ||
  3240.          (token.value.svalue == stringSlash) ||
  3241.          (token.value.svalue == stringPercent)
  3242.                                      )) {
  3243.       sendExpr = new SendExpr ();
  3244.       sendExpr->selector = token.value.svalue;
  3245.       sendExpr->kind = INFIX;
  3246.       scan ();
  3247.       sendExpr->receiver = a;
  3248.       arg = new Argument ();
  3249.       arg->expr = parseExpr15 (errorMsg);
  3250.       sendExpr->argList = arg;
  3251.       a = sendExpr;
  3252.     } else {
  3253.       return a;
  3254.     }
  3255.   }
  3256. }
  3257.  
  3258.  
  3259.  
  3260. // parseExpr15 (errorMsg)
  3261. //
  3262. // This routine parses the grammar rule:
  3263. //    Expr15  -->  OPERATOR Expr15       // PREFIX
  3264. //            -->  Expr16
  3265. //
  3266. Expression * parseExpr15 (char * errorMsg) {
  3267.   SendExpr * prefix;
  3268.  
  3269.   switch (token.type) {
  3270.       case OPERATOR:
  3271.         prefix = new SendExpr ();
  3272.         prefix->selector = lookupAndAdd (appendStrings (
  3273.                               "_prefix_", token.value.svalue->chars, ""), OPERATOR);
  3274.         prefix->kind = PREFIX;
  3275.         scan ();
  3276.         prefix->receiver = parseExpr15 (errorMsg);
  3277.         return prefix;
  3278.     default:
  3279.       return parseExpr16 (errorMsg);
  3280.   }
  3281. }
  3282.  
  3283.  
  3284.  
  3285. // parseExpr16 (errorMsg)
  3286. //
  3287. // This routine parses the grammar rule:
  3288. //    Expr16  -->  Expr17 { '.' ID ArgList               // SendExpr
  3289. //                        | '.' ID                       // FieldAccess
  3290. //                        | 'asPtrTo' Type
  3291. //                        | 'asInteger'
  3292. //                        | 'arraySize'
  3293. //                        | 'isInstanceOf' Type
  3294. //                        | 'isKindOf' Type
  3295. //                        | '[' Expr { ',' Expr } ']'     // ArrayAccess
  3296. //                       }
  3297. //
  3298. Expression * parseExpr16 (char * errorMsg) {
  3299.   Expression * a;
  3300.   Expression * newExpr;
  3301.   AsIntegerExpr * asIntegerExpr;
  3302.   ArraySizeExpr * arraySizeExpr;
  3303.   IsInstanceOfExpr * isInstanceOfExpr;
  3304.   IsKindOfExpr * isKindOfExpr;
  3305.   AsPtrToExpr * asPtrToExpr;
  3306.   SendExpr * sendExpr;
  3307.   FieldAccess * fieldAccess;
  3308.   Token tok;
  3309.  
  3310.   a = parseExpr17 (errorMsg);
  3311.   while (1) {
  3312.     switch (token.type) {
  3313.  
  3314.       case PERIOD:
  3315.         if (token2.type == ID) {
  3316.           // If we have ". ID (" and the ID and "(" are on the same line...
  3317.           if (token3.type == L_PAREN &&
  3318.                 extractLineNumber (token2) == extractLineNumber (token3)) {
  3319.             scan ();    // PERIOD
  3320.             sendExpr = new SendExpr ();
  3321.             sendExpr->receiver = a;
  3322.             sendExpr->kind = NORMAL;
  3323.             sendExpr->selector = token.value.svalue;
  3324.             scan ();    // ID
  3325.             scan ();    // L_PAREN
  3326.             sendExpr->argList = parseArgList ();
  3327.             a = sendExpr;
  3328.           } else {
  3329.             scan ();    // PERIOD
  3330.             fieldAccess = new FieldAccess ();
  3331.             fieldAccess->id = token.value.svalue;
  3332.             scan ();    // ID
  3333.             fieldAccess->expr = a;
  3334.             a = fieldAccess;
  3335.           }
  3336.         } else {
  3337.           syntaxError ("Expecting field ID or message selector after '.'");
  3338.           scan ();      // PERIOD
  3339.         }
  3340.         break;
  3341.  
  3342.       case AS_PTR_TO:
  3343.         asPtrToExpr = new AsPtrToExpr ();
  3344.         scan ();
  3345.         asPtrToExpr->expr = a;
  3346.         asPtrToExpr->type = parseType ("Expecting type in 'expr asPtrTo Type'");
  3347.         a = asPtrToExpr;
  3348.         break;
  3349.  
  3350.       case AS_INTEGER:
  3351.         asIntegerExpr = new AsIntegerExpr ();
  3352.         scan ();
  3353.         asIntegerExpr->expr = a;
  3354.         a = asIntegerExpr;
  3355.         break;
  3356.  
  3357.       case ARRAY_SIZE:
  3358.         arraySizeExpr = new ArraySizeExpr ();
  3359.         scan ();
  3360.         arraySizeExpr->expr = a;
  3361.         a = arraySizeExpr;
  3362.         break;
  3363.  
  3364.       case IS_INSTANCE_OF:
  3365.         isInstanceOfExpr = new IsInstanceOfExpr ();
  3366.         scan ();
  3367.         isInstanceOfExpr->expr = a;
  3368.         isInstanceOfExpr->type = parseType ("Expecting type in 'expr isInstanceOf Type'");
  3369.         a = isInstanceOfExpr;
  3370.         break;
  3371.  
  3372.       case IS_KIND_OF:
  3373.         isKindOfExpr = new IsKindOfExpr ();
  3374.         scan ();
  3375.         isKindOfExpr->expr = a;
  3376.         isKindOfExpr->type = parseType ("Expecting type in 'expr isKindOf Type'");
  3377.         a = isKindOfExpr;
  3378.         break;
  3379.  
  3380.       case L_BRACK:
  3381.         tok = token;
  3382.         scan ();      // L_BRACK
  3383.         a = parseArrayAccess (tok, a);
  3384.         break;
  3385.  
  3386.       default:
  3387.         return a;
  3388.     }
  3389.   }
  3390. }
  3391.  
  3392.  
  3393.  
  3394. // parseExpr17 (errorMsg)
  3395. //
  3396. // This routine parses the grammar rule:
  3397. //    Expr17  -->  '(' Expr ')'
  3398. //            -->  'null'
  3399. //            -->  'true'
  3400. //            -->  'false'
  3401. //            -->  'self'
  3402. //            -->  'super'
  3403. //            -->  INTEGER
  3404. //            -->  DOUBLE
  3405. //            -->  CHAR
  3406. //            -->  STRING
  3407. //            -->  Closure
  3408. //            -->  ID                   // Variable
  3409. //            -->  ID ArgList           // Call Expr
  3410. //            -->  'new' Constructor
  3411. //            -->  'alloc' Constructor
  3412. //            -->  'sizeOf' Type
  3413. //
  3414. //
  3415. // There is an ambiguity in the grammar.  Consider this sequence of tokens:
  3416. //     x = f ( ...
  3417. // This could have two interpretations, as suggested by these examples:
  3418. //     x = f (123)      -- function call
  3419. // and
  3420. //     x = f
  3421. //     (p.foo).bar()    -- next stmt begins with a '('
  3422. //
  3423. // Unfortunately, when we get an ID followed by a '(', we can't tell whether we are
  3424. // looking at a function call or some other expression.  We differentiate these
  3425. // two cases by making the following (non-CFG) rules:
  3426. //   (1) For a function call, the '(' must appear on the same line as the function name
  3427. //   (2) Otherwise, we interpret it as a separate expression.
  3428. // If you really must have 2 statements on the same line, but you do not wish the
  3429. // interpretation as a function call, you must insert an extra set of parens, e.g.,
  3430. //     x = (f)     (p.foo).bar()
  3431. // If you really must have a function call that is spread over several lines,
  3432. // do it like this:
  3433. //     x = f (a,
  3434. //            b,
  3435. //            g (x,
  3436. //               y,
  3437. //               z),
  3438. //            c)
  3439. // or like this if you can't get 'f' and 'a' on one line and want to really spread
  3440. // it out:
  3441. //     x = ffffffffff (
  3442. //            a,
  3443. //            b,
  3444. //            ggggggggg (
  3445. //              x,
  3446. //              y,
  3447. //              z
  3448. //            ),
  3449. //            c
  3450. //         )
  3451. //   
  3452. Expression * parseExpr17 (char * errorMsg) {
  3453.   IntConst * e1;
  3454.   DoubleConst * e2;
  3455.   CharConst * e3;
  3456.   StringConst * e4;
  3457.   Expression * exp;
  3458.   SizeOfExpr * sizeOfExpr;
  3459.   VariableExpr * var;
  3460.   CallExpr * callExpr;
  3461.   ClosureExpr * closureExpr;
  3462.  
  3463.   switch (token.type) {
  3464.   
  3465.     case INT_CONST:
  3466.       e1 = new IntConst ();
  3467.       e1->ivalue = token.value.ivalue;
  3468.       scan ();
  3469.       return e1;
  3470.   
  3471.     case DOUBLE_CONST:
  3472.       e2 = new DoubleConst ();
  3473.       e2->rvalue = token.value.rvalue;
  3474.       scan ();
  3475.       return e2;
  3476.   
  3477.     case CHAR_CONST:
  3478.       e3 = new CharConst ();
  3479.       e3->ivalue = token.value.ivalue;
  3480.       scan ();
  3481.       return e3;
  3482.   
  3483.     case STRING_CONST:
  3484.       e4 = new StringConst ();
  3485.       e4->svalue = token.value.svalue;
  3486.       scan ();
  3487.       return e4;
  3488.   
  3489.     case TRUE:
  3490.       exp = new BoolConst (1);
  3491.       scan ();
  3492.       return exp;
  3493.   
  3494.     case FALSE:
  3495.       exp = new BoolConst (0);
  3496.       scan ();
  3497.       return exp;
  3498.   
  3499.     case NULL_KEYWORD:
  3500.       exp = new NullConst ();
  3501.       scan ();
  3502.       return exp;
  3503.   
  3504.     case SELF:
  3505.       exp = new SelfExpr ();
  3506.       scan ();
  3507.       return exp;
  3508.   
  3509.     case SUPER:
  3510.       exp = new SuperExpr ();
  3511.       scan ();
  3512.       return exp;
  3513.  
  3514.     case L_PAREN:
  3515.       scan ();
  3516.       exp = parseExpr ("Expecting an expression after '('");
  3517.       if (token.type == R_PAREN) {
  3518.         scan ();
  3519.       } else if (token2.type == R_PAREN) {
  3520.         syntaxError ("Expecting ')'");
  3521.         scan ();
  3522.         scan ();
  3523.       } else {
  3524.         syntaxError ("Expecting ')'");
  3525.       }
  3526.       return exp;
  3527.  
  3528.     case SIZE_OF:
  3529.       sizeOfExpr = new SizeOfExpr ();
  3530.       scan ();
  3531.       sizeOfExpr->type = parseType ("Expecting type after 'sizeOf'");
  3532.       return sizeOfExpr;
  3533.  
  3534.     case ID:
  3535.       // If we have "ID (" and they are on the same line...
  3536.       if ((token2.type == L_PAREN) &&
  3537.           extractLineNumber (token) == extractLineNumber (token2)) {   // Call Expression
  3538.         callExpr = new CallExpr ();
  3539.         callExpr->id = token.value.svalue;
  3540.         scan ();    // ID
  3541.         scan ();    // L_PAREN
  3542.         callExpr->argList = parseArgList ();
  3543.         return callExpr;
  3544.       } else {                                     // Simple variable
  3545.         var = new VariableExpr ();
  3546.         var->id = token.value.svalue;
  3547.         scan ();
  3548.         return var;
  3549.       }
  3550.  
  3551.     case FUNCTION:       // Closure expression
  3552.       closureExpr = new ClosureExpr ();
  3553.       closureExpr->function = parseFunction (0);    // Expecting ID = False
  3554.       return closureExpr;
  3555.  
  3556.     case NEW:
  3557.     case ALLOC:
  3558.       return parseConstructor ();
  3559.  
  3560.     default:
  3561.       syntaxError (errorMsg);
  3562.       scan ();
  3563.       return new NullConst ();
  3564.   }
  3565. }
  3566.  
  3567.  
  3568.  
  3569. // parseArrayAccess (tokenForPos, soFar)
  3570. //
  3571. // This routine parses according to this syntax:
  3572. //    Expr { , Expr } ']'
  3573. // and returns an ArrayAccess.  It calls itself recursively; Each invocation
  3574. // will pick up one Expression and will allocate one ArrayAccess node.
  3575. //
  3576. // 'soFar' is whatever expression we have parsed so far, e.g., 'a[1,2'.
  3577. //
  3578. // It positions the ArrayAccess node on the "tokenForPos".
  3579. //
  3580. ArrayAccess * parseArrayAccess (Token tokenForPos, Expression * soFar) {
  3581.   int count;
  3582.   ArrayAccess * arrayAccess;
  3583.  
  3584.   arrayAccess = new ArrayAccess ();
  3585.   arrayAccess->positionAtToken (tokenForPos);
  3586.   arrayAccess->arrayExpr = soFar;
  3587.   arrayAccess->indexExpr = parseExpr ("Expecting an index expression here");
  3588.   if (token.type == R_BRACK) {
  3589.     scan ();
  3590.     return arrayAccess;
  3591.   } else if (token.type == COMMA) {
  3592.     scan ();
  3593.     return parseArrayAccess (tokenForPos, arrayAccess);
  3594.   } else {
  3595.     syntaxError ("Expecting ']' or ',' in 'arr [...]'");
  3596.     // Scan until we hit either FIRST-EXPR or , or ]
  3597.     count = 0;
  3598.     while (1) {
  3599.       if (token.type == EOF) {
  3600.         break;
  3601.       } else if (token.type == R_BRACK) {
  3602.         scan ();
  3603.         break;
  3604.       } else if (token.type == COMMA) {
  3605.         scan ();
  3606.         checkTokenSkipping (count);
  3607.         return parseArrayAccess (tokenForPos, arrayAccess);
  3608.       } else if (inFirstExpr (token)) {
  3609.         checkTokenSkipping (count);
  3610.         return parseArrayAccess (tokenForPos, arrayAccess);
  3611.       }
  3612.       scan ();
  3613.       count++;
  3614.     }
  3615.     checkTokenSkipping (count);
  3616.     return arrayAccess;
  3617.   }
  3618. }
  3619.  
  3620.  
  3621.  
  3622. // parseArgList ()
  3623. //
  3624. // Parse a comma separated list of expressions, followed by the closing ')'.
  3625. //     ArgList --> Expr ',' Expr ',' ... ',' Expr ')'
  3626. //             --> ')'
  3627. // This routine builds and returns a linked-list of Argument nodes.
  3628. // If no arguments are present, then it returns NULL.
  3629. //
  3630. // If there are syntax errors, this routine may scan ZERO tokens.
  3631. //
  3632. Argument * parseArgList () {
  3633.   Argument * newArg, * first, * last;
  3634.   if (token.type == R_PAREN) {
  3635.     scan ();
  3636.     return NULL;
  3637.   }
  3638.   newArg = new Argument ();
  3639.   newArg->expr = parseExpr ("Expecting an argument or ')' here");
  3640.   first = last = newArg;
  3641.   while (token.type == COMMA) {
  3642.     scan ();   // COMMA
  3643.     newArg = new Argument ();
  3644.     newArg->expr = parseExpr ("Expecting the next argument after comma");
  3645.     last->next = newArg;
  3646.     last = newArg;
  3647.   }
  3648.   if (token.type == R_PAREN) {
  3649.     scan ();      // R_PAREN
  3650.   } else {
  3651.     syntaxError ("Expecting ',' or ')' in ArgList");
  3652.     if (token2.type == R_PAREN) {
  3653.       scan ();    // Junk
  3654.       scan ();    // R_PAREN
  3655.     }
  3656.   }
  3657.   return first;
  3658. }
  3659.  
  3660.  
  3661.  
  3662. // parseConstructor ()
  3663. //
  3664. // Parse the following syntax rules:
  3665. //
  3666. // Expr            --> NEW Constructor
  3667. //                 --> ALLOC Constructor
  3668. //
  3669. // Constructor     --> Type ( ClassRecordInit | ArrayInit | <none> )
  3670. //
  3671. // ClassRecordInit --> '{'     ID = Expr
  3672. //                         { , ID = Expr }   '}'  ]
  3673. // ArrayInit       --> '{'    [ Expr 'of' ] Expr
  3674. //                        { , [ Expr 'of' ] Expr }   '}'
  3675. //
  3676. // This routine builds a Constructor node.  A constructor can be used to create/
  3677. // initialize either:
  3678. //    a class instance     Person { name = "harry", age = 46 }
  3679. //    a record instance    Node { val = 5, next = p }
  3680. //    an array             array of int { 100 of -1, 100 of -2}
  3681. //
  3682. // It could be that there is no initialization list, for example:
  3683. //    MyType
  3684. // (Note that we never have an empty list like "MyType { }"...)
  3685. // This routine makes no attempt to check that the sort of initialization in any
  3686. // way matches the type; this will be done during semantic checking.
  3687. //
  3688. // Even if errors, this routine will not return NULL.
  3689. //
  3690. Constructor * parseConstructor () {
  3691.   Constructor * constructor;
  3692.   FieldInit * fieldInit, * firstFieldInit, * lastFieldInit;
  3693.   CountValue * countValue, * firstCountValue, * lastCountValue;
  3694.  
  3695.   constructor = new Constructor ();
  3696.   constructor->allocKind = token.type;    // NEW or ALLOC
  3697.   scan ();
  3698.   constructor->type = parseType ("Expecting type in constructor, after NEW or ALLOC");
  3699.  
  3700.   if (token.type != L_BRACE) {
  3701.     return constructor;
  3702.   }
  3703.   scan ();
  3704.  
  3705.   // If we have a Class/Record initialization list...
  3706.   if ((token.type == ID) && (token2.type == EQUAL)) {
  3707.     fieldInit = new FieldInit ();
  3708.     fieldInit->id = token.value.svalue;
  3709.     scan ();    // ID
  3710.     scan ();    // EQUAL
  3711.     fieldInit->expr = parseExpr ("Expecting an initial value after '='");
  3712.     firstFieldInit = lastFieldInit = fieldInit;
  3713.     while (token.type == COMMA) {
  3714.       scan ();   // COMMA
  3715.       fieldInit = new FieldInit ();
  3716.       fieldInit->id = mustHaveID ("Expecting ID after ',' in class/record constructor initialization list");
  3717.       mustHave (EQUAL, "Expecting '=' after ID in class/record constructor initialization list");
  3718.       fieldInit->expr = parseExpr ("Expecting an initial value after '='");
  3719.       lastFieldInit->next = fieldInit;
  3720.       lastFieldInit = fieldInit;
  3721.       if ((token.type != COMMA) && (token.type != R_BRACE)) {
  3722.         syntaxError ("Expecting ',' or '}' in class/record constructor initialization list");
  3723.         if ((token2.type == COMMA) || (token2.type == R_BRACE)) {
  3724.           scan ();    // junk
  3725.         }
  3726.       }
  3727.     }
  3728.     mustHave (R_BRACE, "Expecting ',' or '}' in class/record constructor initialization list");
  3729.     constructor-> fieldInits = firstFieldInit;
  3730.     return constructor;
  3731.  
  3732.   // If we have an Array initialization list...
  3733.   } else {
  3734.     if (token.type == R_BRACE) {
  3735.       syntaxError ("Empty list in constructor is not allowed; just omit the '{}' entirely");
  3736.       scan ();     // R_BRACE
  3737.       return constructor;
  3738.     }
  3739.     countValue = new CountValue ();
  3740.     countValue->value = parseExpr ("Expecting an expression after '[' in array constructor initialization list");
  3741.     if (token.type == OF) {
  3742.       scan ();
  3743.       countValue->count = countValue->value;
  3744.       countValue->value = parseExpr ("Expecting an expression after 'of' in 'CountExpr of ValueExpr'");
  3745.     }
  3746.     firstCountValue = lastCountValue = countValue;
  3747.     while (token.type == COMMA) {
  3748.       scan ();   // COMMA
  3749.       countValue = new CountValue ();
  3750.       countValue->value = parseExpr ("Expecting next expression after ',' in array constructor initialization list");
  3751.       if (token.type == OF) {
  3752.         scan ();
  3753.         countValue->count = countValue->value;
  3754.         countValue->value = parseExpr ("Expecting an expression after 'of' in 'CountExpr of ValueExpr'");
  3755.       }
  3756.       lastCountValue->next = countValue;
  3757.       lastCountValue = countValue;
  3758.       if ((token.type != COMMA) && (token.type != R_BRACE)) {
  3759.         syntaxError ("Expecting ',' or '}' in array constructor");
  3760.         if ((token2.type == COMMA) || (token2.type == R_BRACE)) {
  3761.           scan ();    // junk
  3762.         }
  3763.       }
  3764.     }
  3765.     mustHave (R_BRACE, "Expecting ',' or '}' in array constructor initialization list");
  3766.     constructor->countValueList = firstCountValue;
  3767.     return constructor;
  3768.   }
  3769. }
  3770.  
  3771.  
  3772.  
  3773. //    
  3774. //    
  3775. //    
  3776. //    
  3777. //    // parseConstructor ()
  3778. //    //
  3779. //    // Parse the following syntax rules:
  3780. //    //
  3781. //    // Constructor --> Type ( ClassRecordInit | ArrayInit | <none> )
  3782. //    //
  3783. //    // ClassRecordInit --> '{'     ID = Expr
  3784. //    //                         { , ID = Expr }   '}'  ]
  3785. //    // ArrayInit --> '{'    [ Expr 'of' ] Expr
  3786. //    //                  { , [ Expr 'of' ] Expr }   '}'
  3787. //    //
  3788. //    // This routine builds a Constructor node.  A constructor can be used to create/
  3789. //    // initialize either:
  3790. //    //    a class instance     Person { name = "harry", age = 46 }
  3791. //    //    a record instance    Node { val = 5, next = p }
  3792. //    //    an array             array of int { 100 of -1, 100 of -2}
  3793. //    //
  3794. //    // It could be that there is no initialization list, for example:
  3795. //    //    MyType
  3796. //    // (Note that we never have an empty list like "MyType { }"...)
  3797. //    // This routine makes no attempt to check that the sort of initialization in any
  3798. //    // way matches the type; this will be done during semantic checking.
  3799. //    //
  3800. //    // Even if errors, this routine will not return NULL.
  3801. //    //
  3802. //    Constructor * parseConstructor () {
  3803. //      Constructor * constructor;
  3804. //      FieldInit * fieldInit, * firstFieldInit, * lastFieldInit;
  3805. //      CountValue * countValue, * firstCountValue, * lastCountValue;
  3806. //    
  3807. //      constructor = new Constructor ();
  3808. //      constructor->type = parseType ("Expecting type in constructor, after NEW or ALLOC");
  3809. //    
  3810. //      if (token.type != L_BRACE) {
  3811. //        return constructor;
  3812. //      }
  3813. //      scan ();
  3814. //    
  3815. //      // If we have a Class/Record initialization list...
  3816. //      if ((token.type == ID) && (token2.type == EQUAL)) {
  3817. //        fieldInit = new FieldInit ();
  3818. //        fieldInit->id = token.value.svalue;
  3819. //        scan ();    // ID
  3820. //        scan ();    // EQUAL
  3821. //        fieldInit->expr = parseExpr ("Expecting an initial value after '='");
  3822. //        firstFieldInit = lastFieldInit = fieldInit;
  3823. //        while (token.type == COMMA) {
  3824. //          scan ();   // COMMA
  3825. //          fieldInit = new FieldInit ();
  3826. //          fieldInit->id = mustHaveID ("Expecting ID after ',' in class/record constructor initialization list");
  3827. //          mustHave (EQUAL, "Expecting '=' after ID in class/record constructor initialization list");
  3828. //          fieldInit->expr = parseExpr ("Expecting an initial value after '='");
  3829. //          lastFieldInit->next = fieldInit;
  3830. //          lastFieldInit = fieldInit;
  3831. //          if ((token.type != COMMA) && (token.type != R_BRACE)) {
  3832. //            syntaxError ("Expecting ',' or '}' in class/record constructor initialization list");
  3833. //            if ((token2.type == COMMA) || (token2.type == R_BRACE)) {
  3834. //              scan ();    // junk
  3835. //            }
  3836. //          }
  3837. //        }
  3838. //        mustHave (R_BRACE, "Expecting ',' or '}' in class/record constructor initialization list");
  3839. //        constructor-> fieldInits = firstFieldInit;
  3840. //        return constructor;
  3841. //    
  3842. //      // If we have an Array initialization list...
  3843. //      } else {
  3844. //        if (token.type == R_BRACE) {
  3845. //          syntaxError ("Empty list in constructor is not allowed; just omit the '{}' entirely");
  3846. //          scan ();     // R_BRACE
  3847. //          return constructor;
  3848. //        }
  3849. //        countValue = new CountValue ();
  3850. //        countValue->value = parseExpr ("Expecting an expression after '[' in array constructor initialization list");
  3851. //        if (token.type == OF) {
  3852. //          scan ();
  3853. //          countValue->count = countValue->value;
  3854. //          countValue->value = parseExpr ("Expecting an expression after 'of' in 'CountExpr of ValueExpr'");
  3855. //        }
  3856. //        firstCountValue = lastCountValue = countValue;
  3857. //        while (token.type == COMMA) {
  3858. //          scan ();   // COMMA
  3859. //          countValue = new CountValue ();
  3860. //          countValue->value = parseExpr ("Expecting next expression after ',' in array constructor initialization list");
  3861. //          if (token.type == OF) {
  3862. //            scan ();
  3863. //            countValue->count = countValue->value;
  3864. //            countValue->value = parseExpr ("Expecting an expression after 'of' in 'CountExpr of ValueExpr'");
  3865. //          }
  3866. //          lastCountValue->next = countValue;
  3867. //          lastCountValue = countValue;
  3868. //          if ((token.type != COMMA) && (token.type != R_BRACE)) {
  3869. //            syntaxError ("Expecting ',' or '}' in array constructor");
  3870. //            if ((token2.type == COMMA) || (token2.type == R_BRACE)) {
  3871. //              scan ();    // junk
  3872. //            }
  3873. //          }
  3874. //        }
  3875. //        mustHave (R_BRACE, "Expecting ',' or '}' in array constructor initialization list");
  3876. //        constructor->countValueList = firstCountValue;
  3877. //        return constructor;
  3878. //      }
  3879. //    }
  3880. //    
  3881.  
  3882.  
  3883.  
  3884. // parseLocalVarDecls ()
  3885. //
  3886. // This routine parses the following syntax:
  3887. //     VarDecls --> [ 'var' { VarDecl }+ ]
  3888. //     VarDecl  --> Decl [ '=' Expr0 ]
  3889. //     Decl     --> ID { ',' ID } ':' Type
  3890. //
  3891. // It returns a linked list of Locals.
  3892. //
  3893. // NOTE: THIS ROUTINE IS VERY SIMILAR TO parseGlobalVarDecls.
  3894. //
  3895. Local * parseLocalVarDecls () {
  3896.   Local * first, * last, * idListFirst, * idListLast, * local;
  3897.   Type * type;
  3898.   Expression * init;
  3899.   VariableExpr * var;
  3900.   if (token.type != VAR) {
  3901.     return NULL;
  3902.   }
  3903.   first = last = NULL;
  3904.   scan ();    // VAR
  3905.   do {
  3906.     // Pick up a list of ID's
  3907.     idListFirst = idListLast = NULL;
  3908.     do {
  3909.       local = new Local ();
  3910.       local->id = mustHaveID ("Expecting a variable name ID");
  3911.       if (idListFirst == NULL) {
  3912.         idListFirst = local;
  3913.       } else {
  3914.         idListLast->next = local;
  3915.       }
  3916.       idListLast = local;
  3917.       if (token.type != COMMA) {
  3918.         break;
  3919.       }
  3920.       scan ();     // COMMA
  3921.       // Check for common errors (i.e., use of keyword as a name)...
  3922.       if (token.type != ID) {
  3923.         syntaxError ("Expecting next local variable name ID after COMMA");
  3924.         scan ();
  3925.         if (token.type == COMMA) {
  3926.           scan ();
  3927.         } else if (token.type == COLON) {
  3928.           break;
  3929.         }
  3930.       }
  3931.     } while (token.type == ID);
  3932.     // Pick up a type
  3933.     mustHave (COLON, "Expecting ': Type' in variable decl");
  3934.     type = parseType ("Expecting Type after ':' in variable decl");
  3935.     // See if we have an initializing expression
  3936.     init = NULL;
  3937.     if (token.type == EQUAL) {
  3938.       scan ();    // EQUAL
  3939.       init = parseExpr0 ("Expecting initializing expression after '='");
  3940.     }
  3941.     // Now run through the ID's.  "idListFirst" points to the next one to examine.
  3942.     while (idListFirst) {
  3943.       // Add in a ptr to the (shared) type.
  3944.       idListFirst->type = type;
  3945.       // Add "idListFirst" to the end of the main list.
  3946.       if (first == NULL) {
  3947.         first = idListFirst;
  3948.       } else {
  3949.         last->next = idListFirst;
  3950.       }
  3951.       last = idListFirst;
  3952.       // Move to the next id in the secondary list.
  3953.       idListFirst = (Local *) idListFirst->next;
  3954.       // Add in an initializing expression if there is one.
  3955.       if (init) {
  3956.         last->initExpr = init;
  3957.         // We will treat "x,y,z: int = 123" as "x=123  y=x  z=y"
  3958.         var = new VariableExpr ();
  3959.         var->positionAt (init);
  3960.         var->id = last->id;
  3961.         init = var; 
  3962.       }
  3963.     }
  3964.     last->next = NULL;
  3965.     // Continue looping if we have...
  3966.     //      ID :
  3967.     //      ID ,
  3968.     // Anything else (like a lone ID) might be an expression or stmt...
  3969.   } while ((token.type == ID) && ((token2.type == COMMA) || (token2.type == COLON)));
  3970.   return first;
  3971. }
  3972.  
  3973.  
  3974.  
  3975. // parseGlobalVarDecls ()
  3976. //
  3977. // This routine parses the following syntax:
  3978. //     VarDecls --> [ 'var' { VarDecl }+ ]
  3979. //     VarDecl  --> Decl [ '=' Expr0 ]
  3980. //     Decl     --> ID { ',' ID } ':' Type
  3981. //
  3982. // It returns a linked list of Globals.
  3983. //
  3984. // NOTE: THIS ROUTINE IS VERY SIMILAR TO parseLocalVarDecls.
  3985. //
  3986. Global * parseGlobalVarDecls () {
  3987.   Global * first, * last, * idListFirst, * idListLast, * global;
  3988.   Type * type;
  3989.   Expression * init;
  3990.   VariableExpr * var;
  3991.   if (token.type != VAR) {
  3992.     programLogicError ("Already checked for 'var' keyword");
  3993.   }
  3994.   first = last = NULL;
  3995.   scan ();    // VAR
  3996.   while (1) {
  3997.     // Pick up a list of ID's
  3998.     idListFirst = idListLast = NULL;
  3999.     do {
  4000.       global = new Global ();
  4001.       global->id = mustHaveID ("Expecting a global variable name ID");
  4002.       if (idListFirst == NULL) {
  4003.         idListFirst = global;
  4004.       } else {
  4005.         idListLast->next = global;
  4006.       }
  4007.       idListLast = global;
  4008.       if (token.type != COMMA) {
  4009.         break;
  4010.       }
  4011.       scan ();     // COMMA
  4012.       // Check for common errors (i.e., use of keyword as a name)...
  4013.       if (token.type != ID) {
  4014.         syntaxError ("Expecting next global variable name ID after COMMA");
  4015.         scan ();
  4016.         if (token.type == COMMA) {
  4017.           scan ();
  4018.         } else if (token.type == COLON) {
  4019.           break;
  4020.         }
  4021.       }
  4022.     } while (token.type == ID);
  4023.     // Pick up a type
  4024.     mustHave (COLON, "Expecting ': Type' in variable decl");
  4025.     type = parseType ("Expecting Type after ':' in variable decl");
  4026.     // See if we have an initializing expression
  4027.     init = NULL;
  4028.     if (token.type == EQUAL) {
  4029.       scan ();    // EQUAL
  4030.       init = parseExpr0 ("Expecting initializing expression after '='");
  4031.     }
  4032.     // Now run through the ID's.  "idListFirst" points to the next one to examine.
  4033.     while (idListFirst) {
  4034.       // Add in a ptr to the (shared) type.
  4035.       idListFirst->type = type;
  4036.       // Add "idListFirst" to the end of the main list.
  4037.       if (first == NULL) {
  4038.         first = idListFirst;
  4039.       } else {
  4040.         last->next = idListFirst;
  4041.       }
  4042.       last = idListFirst;
  4043.       // Move to the next id in the secondary list.
  4044.       idListFirst = (Global *) idListFirst->next;
  4045.       // Add in an initializing expression if there is one.
  4046.       if (init) {
  4047.         last->initExpr = init;
  4048.         // We will treat "x,y,z: int = 123" as "x=123  y=x  z=y"
  4049.         var = new VariableExpr ();
  4050.         var->positionAt (init);
  4051.         var->id = last->id;
  4052.         init = var; 
  4053.       }
  4054.     }
  4055.     last->next = NULL;
  4056.     // Continue looping if we have...
  4057.     //      ID
  4058.     //      xxx ,      (E.g., using a keyword as a var name)
  4059.     //      xxx :
  4060.     if ((token.type != ID) && (token2.type != COMMA) && (token2.type != COLON)) {
  4061.       break;
  4062.     }
  4063.   }
  4064.   return first;
  4065. }
  4066.  
  4067.  
  4068.  
  4069. // parseClassFields ()
  4070. //
  4071. // This routine parses the following syntax:
  4072. //     { ID { ',' ID } ':' Type }+
  4073. //
  4074. // It returns a linked list of ClassFields.
  4075. //
  4076. ClassField * parseClassFields () {
  4077.   ClassField * first, * last, * idListFirst, * idListLast, * field;
  4078.   Type * type;
  4079.  
  4080.   first = last = NULL;
  4081.   while (1) {
  4082.     // Pick up a list of ID's
  4083.     idListFirst = idListLast = NULL;
  4084.     do {
  4085.       field = new ClassField ();
  4086.       field->id = mustHaveID ("Expecting a field name ID");
  4087.       if (idListFirst == NULL) {
  4088.         idListFirst = field;
  4089.       } else {
  4090.         idListLast->next = field;
  4091.       }
  4092.       idListLast = field;
  4093.       if (token.type != COMMA) {
  4094.         break;
  4095.       }
  4096.       scan ();     // COMMA
  4097.       // Check for common errors (i.e., use of keyword as a name)...
  4098.       if (token.type != ID) {
  4099.         syntaxError ("Expecting next field name ID after COMMA");
  4100.         scan ();
  4101.         if (token.type == COMMA) {
  4102.           scan ();
  4103.         } else if (token.type == COLON) {
  4104.           break;
  4105.         }
  4106.       }
  4107.     } while (token.type == ID);
  4108.     // Pick up a type
  4109.     mustHave (COLON, "Expecting ': Type' in field decl");
  4110.     type = parseType ("Expecting Type after ':' in field decl");
  4111.     if (token.type == EQUAL) {
  4112.       syntaxError ("Fields may not be initialized; they are always initialized to zero-equivalents");
  4113.       scan ();
  4114.       parseExpr ("Problems after '=' in field declaration");
  4115.     }
  4116.     // Now run through the ID's.  "idListFirst" points to the next one to examine.
  4117.     while (idListFirst) {
  4118.       // Add in a ptr to the (shared) type.
  4119.       idListFirst->type = type;
  4120.       // Add "idListFirst" to the end of the main list.
  4121.       if (first == NULL) {
  4122.         first = idListFirst;
  4123.       } else {
  4124.         last->next = idListFirst;
  4125.       }
  4126.       last = idListFirst;
  4127.       // Move to the next id in the secondary list.
  4128.       idListFirst = (ClassField *) idListFirst->next;
  4129.     }
  4130.     last->next = NULL;
  4131.     // Continue looping if we have...
  4132.     //      ID
  4133.     //      xxx ,      (E.g., using a keyword as a var name)
  4134.     //      xxx :
  4135.     if ((token.type != ID) && (token2.type != COMMA) && (token2.type != COLON)) {
  4136.       break;
  4137.     }
  4138.   }
  4139.   return first;
  4140. }
  4141.  
  4142.  
  4143.  
  4144. // parseErrorDecls ()
  4145. //
  4146. // This routine parses the following syntax:
  4147. //     Errors --> 'errors' { ID ParmList }+
  4148. //
  4149. // It returns a linked list of ConstDecls.
  4150. //
  4151. ErrorDecl * parseErrorDecls () {
  4152.   ErrorDecl * first, * last, * errorDecl;
  4153.   if (token.type != ERRORS) {
  4154.     programLogicError ("Already checked for 'errors' keyword");
  4155.   }
  4156.   first = last = NULL;
  4157.   scan ();    // ERRORS
  4158.   if (token.type != ID) {
  4159.     syntaxError ("Expecting ID after 'errors'");
  4160.     return NULL;
  4161.   }
  4162.   while (token.type == ID) {
  4163.     errorDecl = new ErrorDecl ();
  4164.     errorDecl->id = token.value.svalue;
  4165.     scan ();    // ID
  4166.     errorDecl->parmList = parseParmList ();
  4167.     if (first == NULL) {
  4168.       first = errorDecl;
  4169.     } else {
  4170.       last->next = errorDecl;
  4171.     }
  4172.     last = errorDecl;
  4173.   }
  4174.   return first;
  4175. }
  4176.  
  4177.  
  4178.  
  4179. // parseConstDecls ()
  4180. //
  4181. // This routine parses the following syntax:
  4182. //     Const --> 'const' { ID = Expr }+
  4183. //
  4184. // It returns a linked list of ConstDecls.
  4185. //
  4186. ConstDecl * parseConstDecls () {
  4187.   ConstDecl * first, * last, * constDecl;
  4188.   if (token.type != CONST) {
  4189.     programLogicError ("Already checked for 'const' keyword");
  4190.   }
  4191.   first = last = NULL;
  4192.   scan ();    // CONST
  4193.   if (token.type != ID) {
  4194.     syntaxError ("Expecting ID after 'const'");
  4195.     return NULL;
  4196.   }
  4197.   while (token.type == ID) {
  4198.     constDecl = new ConstDecl ();
  4199.     constDecl->id = token.value.svalue;
  4200.     scan ();    // ID
  4201.     if (first == NULL) {
  4202.       first = constDecl;
  4203.     } else {
  4204.       last->next = constDecl;
  4205.     }
  4206.     last = constDecl;
  4207.     // Pick up the Expression
  4208.     mustHave (EQUAL, "Expecting '= Expr' in const decl");
  4209.     constDecl->expr = parseExpr ("In constant initializing expression");
  4210.   }
  4211.   return first;
  4212. }
  4213.  
  4214.  
  4215.  
  4216. // parseEnums ()
  4217. //
  4218. // This routine parses the following syntax:
  4219. //     Enum --> 'enum' ID [ = Expr ] { , ID }
  4220. //
  4221. // It returns a linked list of ConstDecls.
  4222. //
  4223. ConstDecl * parseEnums () {
  4224.   ConstDecl * first, * last, * constDecl;
  4225.   int counter, gotInitializer;
  4226.   Expression * expr, * junk;
  4227.   IntConst * intConst;
  4228.   SendExpr * sendExpr;
  4229.   Argument * arg;
  4230.   VariableExpr * var;
  4231.   if (token.type != ENUM) {
  4232.     programLogicError ("Already checked for 'enum' keyword");
  4233.   }
  4234.   first = last = NULL;
  4235.   scan ();    // ENUM
  4236.   constDecl = new ConstDecl ();
  4237.   constDecl->id = mustHaveID ("Expecting ID after 'ENUM'");
  4238.  
  4239.   // If there is an expression, pick it up; Else the default is "= 1".
  4240.   counter = 1;
  4241.   if (token.type == EQUAL) {
  4242.     scan ();
  4243.     constDecl->expr = parseExpr ("In initializing expression after 'ENUM ID ='");
  4244.     gotInitializer = 1;
  4245.   } else {
  4246.     intConst = new IntConst ();
  4247.     intConst->positionAt (constDecl);
  4248.     intConst->ivalue = 1;
  4249.     constDecl->expr = intConst;
  4250.     gotInitializer = 0;
  4251.   }
  4252.   first = last = constDecl;
  4253.   while (token.type == COMMA) {
  4254.     scan ();    // COMMA
  4255.     constDecl = new ConstDecl ();
  4256.     constDecl->id = mustHaveID ("Expecting next ID in 'enum ID, ID, ...'");
  4257.     // There should not be "= Expr" here...
  4258.     if (token.type == EQUAL) {
  4259.       syntaxError ("An initial expression is only allowed for the first 'enum ID'");
  4260.       scan ();
  4261.       junk = parseExpr ("In ENUM initializing expression");
  4262.     }
  4263.     last->next = constDecl;
  4264.     last = constDecl;
  4265.     // If we had an initializing expression, then create "firstID + N"...
  4266.     if (gotInitializer) {
  4267.       var = new VariableExpr ();
  4268.       var->positionAt (constDecl);
  4269.       var->id = first->id;
  4270.       intConst = new IntConst ();
  4271.       intConst->positionAt (constDecl);
  4272.       intConst->ivalue = counter;
  4273.       arg = new Argument ();
  4274.       arg->positionAt (constDecl);
  4275.       arg->expr = intConst;
  4276.       sendExpr = new SendExpr ();
  4277.       sendExpr->positionAt (constDecl);
  4278.       sendExpr->receiver = var;
  4279.       sendExpr->selector = lookupAndAdd ("+", OPERATOR);
  4280.       sendExpr->argList = arg;
  4281.       sendExpr->kind = INFIX;
  4282.       constDecl->expr = sendExpr;
  4283.       counter++;
  4284.     } else {    // Else, if no initial expression, then create an integerConst...
  4285.       counter++;
  4286.       intConst = new IntConst ();
  4287.       intConst->positionAt (constDecl);
  4288.       intConst->ivalue = counter;
  4289.       constDecl->expr = intConst;
  4290.     }
  4291.   }
  4292.   return first;
  4293. }
  4294.  
  4295.  
  4296.  
  4297. // parseTypeDefs ()
  4298. //
  4299. // This routine parses the following syntax:
  4300. //     TypeDef --> 'type' { ID = Type }+
  4301. //
  4302. // It returns a linked list of TypeDefs.
  4303. //
  4304. TypeDef * parseTypeDefs () {
  4305.   TypeDef * first, * last, * typeDef;
  4306.   if (token.type != TYPE) {
  4307.     programLogicError ("Already checked for 'type' keyword");
  4308.   }
  4309.   first = last = NULL;
  4310.   scan ();    // TYPE
  4311.   if (token.type != ID) {
  4312.     syntaxError ("Expecting ID after 'type'");
  4313.     return NULL;
  4314.   }
  4315.   while (token.type == ID) {
  4316.     typeDef = new TypeDef ();
  4317.     typeDef->id = token.value.svalue;
  4318.     scan ();    // ID
  4319.     if (first == NULL) {
  4320.       first = typeDef;
  4321.     } else {
  4322.       last->next = typeDef;
  4323.     }
  4324.     last = typeDef;
  4325.     // Pick up the Type
  4326.     mustHave (EQUAL, "Expecting '= Type' in type definition");
  4327.     typeDef->type = parseType ("Expecting Type after '=' in type definition");
  4328.   }
  4329.   return first;
  4330. }
  4331.  
  4332.