home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / OutOfPhase1.01Source / OutOfPhase Folder / CompilerParser.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-01  |  113.7 KB  |  3,717 lines  |  [TEXT/KAHL]

  1. /* CompilerParser.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "CompilerParser.h"
  31. #include "CompilerScanner.h"
  32. #include "SymbolTableEntry.h"
  33. #include "ASTExpression.h"
  34. #include "SymbolTable.h"
  35. #include "TrashTracker.h"
  36. #include "SymbolList.h"
  37. #include "PcodeObject.h"
  38. #include "Memory.h"
  39. #include "ASTAssignment.h"
  40. #include "ASTBinaryOperator.h"
  41. #include "ASTErrorForm.h"
  42. #include "ASTLoop.h"
  43. #include "ASTArrayDeclaration.h"
  44. #include "ASTVariableDeclaration.h"
  45. #include "ASTConditional.h"
  46. #include "ASTUnaryOperator.h"
  47. #include "ASTOperand.h"
  48. #include "ASTFuncCall.h"
  49. #include "ASTExpressionList.h"
  50. #include "ASTWaveGetter.h"
  51. #include "FloatingPoint.h"
  52.  
  53.  
  54. /* protoplops */
  55. static CompileErrors    ParseFunction(SymbolRec** FunctionSymbolTableEntryOut,
  56.                                                 ASTExpressionRec** FunctionBodyOut,
  57.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  58.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  59.  
  60. static CompileErrors    ParsePrototype(SymbolRec** PrototypeSymbolTableEntryOut,
  61.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  62.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  63.  
  64. static CompileErrors    ParseFormalParamStart(SymbolListRec** FormalArgListOut,
  65.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  66.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  67.  
  68. static CompileErrors    ParseType(DataTypes* TypeOut, ScannerRec* Scanner,
  69.                                                 long* LineNumberOut);
  70.  
  71. static CompileErrors    ParseFormalParamList(SymbolListRec** FormalArgListOut,
  72.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  73.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  74.  
  75. static CompileErrors    ParseVarTail(ASTExpressionRec** ExpressionOut,
  76.                                                 TokenRec* VariableName, long VariableDeclLine,
  77.                                                 DataTypes VariableType, ScannerRec* Scanner,
  78.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  79.                                                 long* LineNumberOut);
  80.  
  81. static CompileErrors    ParseIfRest(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  82.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  83.                                                 long* LineNumberOut);
  84.  
  85. static CompileErrors    ParseWhileLoop(ASTExpressionRec** ExpressionOut,
  86.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  87.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  88.  
  89. static CompileErrors    ParseLoopWhileUntil(ASTExpressionRec** ExpressionOut,
  90.                                                 ASTExpressionRec* LoopBodyExpression, ScannerRec* Scanner,
  91.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  92.                                                 long* LineNumberOut, long LineNumberOfLoop);
  93.  
  94. static CompileErrors    ParseUntilLoop(ASTExpressionRec** ExpressionOut,
  95.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  96.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  97.  
  98. static CompileErrors    ParseExpr2(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  99.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  100.                                                 long* LineNumberOut);
  101.  
  102. static CompileErrors    ParseFormalArg(SymbolRec** FormalArgOut, ScannerRec* Scanner,
  103.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  104.                                                 long* LineNumberOut);
  105.  
  106. static CompileErrors    ParseFormalArgTail(SymbolListRec** ArgListTailOut,
  107.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  108.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  109.  
  110. static CompileErrors    ParseIfTail(ASTExpressionRec** ExpressionOut,
  111.                                                 ASTExpressionRec* Predicate, ASTExpressionRec* Consequent,
  112.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  113.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  114.  
  115. static CompileErrors    ParseExpr3(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  116.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  117.                                                 long* LineNumberOut);
  118.  
  119. static CompileErrors    ParseExpr2Prime(ASTExpressionRec** ExpressionOut,
  120.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  121.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  122.                                                 long* LineNumberOut);
  123.  
  124. static CompileErrors    ParseExpr4(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  125.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  126.                                                 long* LineNumberOut);
  127.  
  128. static CompileErrors    ParseExpr3Prime(ASTExpressionRec** ExpressionOut,
  129.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  130.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  131.                                                 long* LineNumberOut);
  132.  
  133. static CompileErrors    ParseConjOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  134.                                                 long* LineNumberOut);
  135.  
  136. static CompileErrors    ParseExpr5(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  137.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  138.                                                 long* LineNumberOut);
  139.  
  140. static CompileErrors    ParseExpr4Prime(ASTExpressionRec** ExpressionOut,
  141.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  142.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  143.                                                 long* LineNumberOut);
  144.  
  145. static CompileErrors    ParseRelOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  146.                                                 long* LineNumberOut);
  147.  
  148. static CompileErrors    ParseExpr6(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  149.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  150.                                                 long* LineNumberOut);
  151.  
  152. static CompileErrors    ParseExpr5Prime(ASTExpressionRec** ExpressionOut,
  153.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  154.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  155.                                                 long* LineNumberOut);
  156.  
  157. static CompileErrors    ParseAddOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  158.                                                 long* LineNumberOut);
  159.  
  160. static CompileErrors    ParseExpr7(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  161.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  162.                                                 long* LineNumberOut);
  163.  
  164. static CompileErrors    ParseMultOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  165.                                                 long* LineNumberOut);
  166.  
  167. static CompileErrors    ParseExpr8(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  168.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  169.                                                 long* LineNumberOut);
  170.  
  171. static CompileErrors    ParseExpr7Prime(ASTExpressionRec** ExpressionOut,
  172.                                                 ASTExpressionRec* TheExpr8Thing, ScannerRec* Scanner,
  173.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  174.                                                 long* LineNumberOut);
  175.  
  176. static CompileErrors    ParseFuncCall(ASTExpressionRec** ExpressionOut,
  177.                                                 ASTExpressionRec* FunctionGenerator, ScannerRec* Scanner,
  178.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  179.                                                 long* LineNumberOut);
  180.  
  181. static CompileErrors    ParseArraySubscript(ASTExpressionRec** ExpressionOut,
  182.                                                 ASTExpressionRec* ArrayGenerator, ScannerRec* Scanner,
  183.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  184.                                                 long* LineNumberOut);
  185.  
  186. static CompileErrors    ParseExponentiation(ASTExpressionRec** ExpressionOut,
  187.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  188.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  189.  
  190. static CompileErrors    ParseActualStart(ASTExprListRec** ParamListOut,
  191.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  192.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  193.  
  194. static CompileErrors    ParseActualList(ASTExprListRec** ParamListOut,
  195.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  196.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  197.  
  198. static CompileErrors    ParseActualTail(ASTExprListRec** ParamListOut,
  199.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  200.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  201.  
  202. static CompileErrors    ParseExprListTail(ASTExprListRec** ListOut,
  203.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  204.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  205.  
  206. static CompileErrors    ParseExprListElem(ASTExpressionRec** ExpressionOut,
  207.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  208.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut);
  209.  
  210.  
  211.  
  212.  
  213. /* parse a top-level form, which is either a prototype or a function.  prototypes */
  214. /* are entered into the symbol table and return NIL in *FunctionBodyOut but returns */
  215. /* eCompileNoError. */
  216. /*   1:   <form>             ::= <function> ; */
  217. /*   2:                      ::= <prototype> ; */
  218. /* FIRST SET: */
  219. /* <form>             : {func, proto, <function>, <prototype>} */
  220. /* FOLLOW SET: */
  221. /* <form>             : {$$$} */
  222. CompileErrors                    ParseForm(struct SymbolRec** FunctionSymbolTableEntryOut,
  223.                                                 struct ASTExpressionRec** FunctionBodyOut,
  224.                                                 struct ScannerRec* Scanner, struct SymbolTableRec* SymbolTable,
  225.                                                 struct TrashTrackRec* TrashTracker, long* LineNumberOut)
  226.     {
  227.         TokenRec*                        Token;
  228.         CompileErrors                Error;
  229.  
  230.         Token = GetNextToken(Scanner);
  231.         if (Token == NIL)
  232.             {
  233.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  234.                 return eCompileOutOfMemory;
  235.             }
  236.  
  237.         /* do lookahead on "func" */
  238.         if ((GetTokenType(Token) == eTokenKeyword)
  239.             && (GetTokenKeywordTag(Token) == eKeywordFunc))
  240.             {
  241.                 /* push token back */
  242.                 UngetToken(Scanner,Token);
  243.  
  244.                 /* parse function definition */
  245.                 Error = ParseFunction(FunctionSymbolTableEntryOut,FunctionBodyOut,
  246.                     Scanner,SymbolTable,TrashTracker,LineNumberOut);
  247.                 if (Error != eCompileNoError)
  248.                     {
  249.                         return Error;
  250.                     }
  251.             }
  252.  
  253.         /* do lookahead on "proto" */
  254.         else if ((GetTokenType(Token) == eTokenKeyword)
  255.             && (GetTokenKeywordTag(Token) == eKeywordProto))
  256.             {
  257.                 /* push token back */
  258.                 UngetToken(Scanner,Token);
  259.  
  260.                 /* parse prototype */
  261.                 Error = ParsePrototype(FunctionSymbolTableEntryOut,Scanner,SymbolTable,
  262.                     TrashTracker,LineNumberOut);
  263.                 *FunctionBodyOut = NIL; /* no code body for a prototype */
  264.                 if (Error != eCompileNoError)
  265.                     {
  266.                         return Error;
  267.                     }
  268.             }
  269.  
  270.         /* otherwise, it's an error */
  271.         else
  272.             {
  273.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  274.                 return eCompileExpectedFuncOrProto;
  275.             }
  276.  
  277.  
  278.         /* swallow the semicolon */
  279.         Token = GetNextToken(Scanner);
  280.         if (Token == NIL)
  281.             {
  282.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  283.                 return eCompileOutOfMemory;
  284.             }
  285.         if (GetTokenType(Token) != eTokenSemicolon)
  286.             {
  287.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  288.                 return eCompileExpectedSemicolon;
  289.             }
  290.  
  291.         return eCompileNoError;
  292.     }
  293.  
  294.  
  295.  
  296.  
  297. /* this parses a function declaration, returning the symbol table entry for the */
  298. /* function in *FunctionSymbolTableEntryOut and the expression for the function */
  299. /* in *FunctionBodyOut. */
  300. /*  14:   <function>         ::= func <identifier> ( <formalparamstart> ) : */
  301. /*      <type> <expr> */
  302. /* FIRST SET: */
  303. /* <function>         : {func} */
  304. /* FOLLOW SET: */
  305. /* <function>         : {;} */
  306. static CompileErrors    ParseFunction(SymbolRec** FunctionSymbolTableEntryOut,
  307.                                                 ASTExpressionRec** FunctionBodyOut,
  308.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  309.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  310.     {
  311.         TokenRec*                        Token;
  312.         TokenRec*                        FunctionName;
  313.         SymbolListRec*            FormalArgumentList;
  314.         CompileErrors                Error;
  315.         DataTypes                        ReturnType;
  316.         long                                LineNumberOfIdentifier;
  317.  
  318.         /* swallow "func" */
  319.         Token = GetNextToken(Scanner);
  320.         if (Token == NIL)
  321.             {
  322.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  323.                 return eCompileOutOfMemory;
  324.             }
  325.         if ((GetTokenType(Token) != eTokenKeyword)
  326.             || (GetTokenKeywordTag(Token) != eKeywordFunc))
  327.             {
  328.                 /* this is impossible -- we should be able to do some error checking here, */
  329.                 /* but it seems uncertain since we don't (formally) know whose calling us. */
  330.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  331.                 return eCompileExpectedFunc;
  332.             }
  333.  
  334.         /* get the identifier */
  335.         FunctionName = GetNextToken(Scanner);
  336.         if (FunctionName == NIL)
  337.             {
  338.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  339.                 return eCompileOutOfMemory;
  340.             }
  341.         if (GetTokenType(FunctionName) != eTokenIdentifier)
  342.             {
  343.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  344.                 return eCompileExpectedIdentifier;
  345.             }
  346.         LineNumberOfIdentifier = GetCurrentLineNumber(Scanner);
  347.  
  348.         /* add the identifier to the symbol table */
  349.         *FunctionSymbolTableEntryOut = NewSymbol(TrashTracker,
  350.             GetTokenIdentifierString(FunctionName),
  351.             PtrSize(GetTokenIdentifierString(FunctionName)));
  352.         if (*FunctionSymbolTableEntryOut == NIL)
  353.             {
  354.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  355.                 return eCompileOutOfMemory;
  356.             }
  357.         switch (AddSymbolToTable(SymbolTable,*FunctionSymbolTableEntryOut))
  358.             {
  359.                 case eAddSymbolNoErr:
  360.                     break;
  361.                 case eAddSymbolAlreadyExists:
  362.                     *LineNumberOut = LineNumberOfIdentifier;
  363.                     return eCompileMultiplyDefinedIdentifier;
  364.                 case eAddSymbolNoMemory:
  365.                     *LineNumberOut = LineNumberOfIdentifier;
  366.                     return eCompileOutOfMemory;
  367.                 default:
  368.                     EXECUTE(PRERR(ForceAbort,"ParseFunction:  bad value from AddSymbolToTable"));
  369.                     break;
  370.             }
  371.  
  372.         /* create a new lexical level */
  373.         if (!IncrementSymbolTableLevel(SymbolTable))
  374.             {
  375.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  376.                 return eCompileOutOfMemory;
  377.             }
  378.  
  379.         /* swallow the open parenthesis */
  380.         Token = GetNextToken(Scanner);
  381.         if (Token == NIL)
  382.             {
  383.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  384.                 return eCompileOutOfMemory;
  385.             }
  386.         if (GetTokenType(Token) != eTokenOpenParen)
  387.             {
  388.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  389.                 return eCompileExpectedOpenParen;
  390.             }
  391.  
  392.         /* parse <formalparamstart> */
  393.         Error = ParseFormalParamStart(&FormalArgumentList,Scanner,SymbolTable,
  394.             TrashTracker,LineNumberOut);
  395.         if (Error != eCompileNoError)
  396.             {
  397.                 return Error;
  398.             }
  399.  
  400.         /* swallow the close parenthesis */
  401.         Token = GetNextToken(Scanner);
  402.         if (Token == NIL)
  403.             {
  404.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  405.                 return eCompileOutOfMemory;
  406.             }
  407.         if (GetTokenType(Token) != eTokenCloseParen)
  408.             {
  409.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  410.                 return eCompileExpectedCloseParen;
  411.             }
  412.  
  413.         /* swallow the colon */
  414.         Token = GetNextToken(Scanner);
  415.         if (Token == NIL)
  416.             {
  417.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  418.                 return eCompileOutOfMemory;
  419.             }
  420.         if (GetTokenType(Token) != eTokenColon)
  421.             {
  422.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  423.                 return eCompileExpectedColon;
  424.             }
  425.  
  426.         /* parse the return type of the function */
  427.         Error = ParseType(&ReturnType,Scanner,LineNumberOut);
  428.         if (Error != eCompileNoError)
  429.             {
  430.                 return Error;
  431.             }
  432.  
  433.         /* store the interesting information into the symbol table entry */
  434.         SymbolBecomeFunction(*FunctionSymbolTableEntryOut,FormalArgumentList,ReturnType);
  435.  
  436.         /* parse the body of the function */
  437.         Error = ParseExpr(FunctionBodyOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  438.         if (Error != eCompileNoError)
  439.             {
  440.                 return Error;
  441.             }
  442.  
  443.         /* pop lexical level */
  444.         DecrementSymbolTableLevel(SymbolTable);
  445.  
  446.         return eCompileNoError;
  447.     }
  448.  
  449.  
  450.  
  451.  
  452. /* this parses a prototype of a function and returns a symbol table entry in */
  453. /* the *PrototypeSymbolTableEntryOut place. */
  454. /*  21:   <prototype>        ::= proto <identifier> ( <formalparamstart> ) : */
  455. /*      <type> */
  456. /* FIRST SET: */
  457. /* <prototype>        : {proto} */
  458. /* FOLLOW SET: */
  459. /*  <prototype>        : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  460. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  461. static CompileErrors    ParsePrototype(SymbolRec** PrototypeSymbolTableEntryOut,
  462.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  463.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  464.     {
  465.         TokenRec*                        Token;
  466.         TokenRec*                        FunctionName;
  467.         long                                LineNumberOfIdentifier;
  468.         CompileErrors                Error;
  469.         SymbolListRec*            FormalArgumentList;
  470.         DataTypes                        ReturnType;
  471.  
  472.         /* swallow "proto" */
  473.         Token = GetNextToken(Scanner);
  474.         if (Token == NIL)
  475.             {
  476.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  477.                 return eCompileOutOfMemory;
  478.             }
  479.         if ((GetTokenType(Token) != eTokenKeyword)
  480.             || (GetTokenKeywordTag(Token) != eKeywordProto))
  481.             {
  482.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  483.                 return eCompileExpectedFunc;
  484.             }
  485.  
  486.         /* get the identifier */
  487.         FunctionName = GetNextToken(Scanner);
  488.         if (FunctionName == NIL)
  489.             {
  490.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  491.                 return eCompileOutOfMemory;
  492.             }
  493.         if (GetTokenType(FunctionName) != eTokenIdentifier)
  494.             {
  495.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  496.                 return eCompileExpectedIdentifier;
  497.             }
  498.         LineNumberOfIdentifier = GetCurrentLineNumber(Scanner);
  499.  
  500.         /* add the identifier to the symbol table */
  501.         *PrototypeSymbolTableEntryOut = NewSymbol(TrashTracker,
  502.             GetTokenIdentifierString(FunctionName),
  503.             PtrSize(GetTokenIdentifierString(FunctionName)));
  504.         if (*PrototypeSymbolTableEntryOut == NIL)
  505.             {
  506.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  507.                 return eCompileOutOfMemory;
  508.             }
  509.         switch (AddSymbolToTable(SymbolTable,*PrototypeSymbolTableEntryOut))
  510.             {
  511.                 case eAddSymbolNoErr:
  512.                     break;
  513.                 case eAddSymbolAlreadyExists:
  514.                     *LineNumberOut = LineNumberOfIdentifier;
  515.                     return eCompileMultiplyDefinedIdentifier;
  516.                 case eAddSymbolNoMemory:
  517.                     *LineNumberOut = LineNumberOfIdentifier;
  518.                     return eCompileOutOfMemory;
  519.                 default:
  520.                     EXECUTE(PRERR(ForceAbort,"ParsePrototype:  bad value from AddSymbolToTable"));
  521.                     break;
  522.             }
  523.  
  524.         /* create a new lexical level */
  525.         if (!IncrementSymbolTableLevel(SymbolTable))
  526.             {
  527.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  528.                 return eCompileOutOfMemory;
  529.             }
  530.  
  531.         /* swallow the open parenthesis */
  532.         Token = GetNextToken(Scanner);
  533.         if (Token == NIL)
  534.             {
  535.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  536.                 return eCompileOutOfMemory;
  537.             }
  538.         if (GetTokenType(Token) != eTokenOpenParen)
  539.             {
  540.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  541.                 return eCompileExpectedOpenParen;
  542.             }
  543.  
  544.         /* parse <formalparamstart> */
  545.         Error = ParseFormalParamStart(&FormalArgumentList,Scanner,SymbolTable,
  546.             TrashTracker,LineNumberOut);
  547.         if (Error != eCompileNoError)
  548.             {
  549.                 return Error;
  550.             }
  551.  
  552.         /* swallow the close parenthesis */
  553.         Token = GetNextToken(Scanner);
  554.         if (Token == NIL)
  555.             {
  556.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  557.                 return eCompileOutOfMemory;
  558.             }
  559.         if (GetTokenType(Token) != eTokenCloseParen)
  560.             {
  561.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  562.                 return eCompileExpectedCloseParen;
  563.             }
  564.  
  565.         /* swallow the colon */
  566.         Token = GetNextToken(Scanner);
  567.         if (Token == NIL)
  568.             {
  569.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  570.                 return eCompileOutOfMemory;
  571.             }
  572.         if (GetTokenType(Token) != eTokenColon)
  573.             {
  574.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  575.                 return eCompileExpectedColon;
  576.             }
  577.  
  578.         /* parse the return type of the function */
  579.         Error = ParseType(&ReturnType,Scanner,LineNumberOut);
  580.         if (Error != eCompileNoError)
  581.             {
  582.                 return Error;
  583.             }
  584.  
  585.         /* store the interesting information into the symbol table entry */
  586.         SymbolBecomeFunction(*PrototypeSymbolTableEntryOut,FormalArgumentList,ReturnType);
  587.  
  588.         /* pop lexical level */
  589.         DecrementSymbolTableLevel(SymbolTable);
  590.  
  591.         return eCompileNoError;
  592.     }
  593.  
  594.  
  595.  
  596.  
  597. /* this parses an argument list.  the argument list may be empty, in which case */
  598. /* the empty list (NIL) is returned in *FormalArgListOut. */
  599. /*  15:   <formalparamstart> ::= <formalparamlist> */
  600. /*  16:                      ::=  */
  601. /* FIRST SET: */
  602. /* <formalparamstart> : {<identifier>, <formalparamlist>, <formalarg>} */
  603. /* FOLLOW SET: */
  604. /* <formalparamstart> : {)} */
  605. static CompileErrors    ParseFormalParamStart(SymbolListRec** FormalArgListOut,
  606.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  607.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  608.     {
  609.         TokenRec*                        Token;
  610.  
  611.         /* get a token so we can lookahead */
  612.         Token = GetNextToken(Scanner);
  613.         if (Token == NIL)
  614.             {
  615.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  616.                 return eCompileOutOfMemory;
  617.             }
  618.  
  619.         /* if it's a paren, then we abort */
  620.         if (GetTokenType(Token) == eTokenCloseParen)
  621.             {
  622.                 /* stuff it back */
  623.                 UngetToken(Scanner,Token);
  624.  
  625.                 /* we want to return the empty list since argument list is empty */
  626.                 *FormalArgListOut = NIL;
  627.  
  628.                 return eCompileNoError;
  629.             }
  630.  
  631.         /* stuff it back */
  632.         UngetToken(Scanner,Token);
  633.  
  634.         /* it really is something, so parse it */
  635.         return ParseFormalParamList(FormalArgListOut,Scanner,SymbolTable,TrashTracker,
  636.             LineNumberOut);
  637.     }
  638.  
  639.  
  640.  
  641.  
  642. /* this function parses a type and returns the corresponding enumeration value */
  643. /* in *TypeOut. */
  644. /*   3:   <type>             ::= void */
  645. /*   4:                      ::= bool */
  646. /*   5:                      ::= int */
  647. /*   6:                      ::= single */
  648. /*   7:                      ::= double */
  649. /*   8:                      ::= fixed */
  650. /*   9:                      ::= boolarray */
  651. /*  10:                      ::= intarray */
  652. /*  11:                      ::= singlearray */
  653. /*  12:                      ::= doublearray */
  654. /*  13:                      ::= fixedarray */
  655. /* FIRST SET: */
  656. /* <type>             : {void, bool, int, single, double, fixed, boolarray, */
  657. /*      intarray, singlearray, doublearray, fixedarray} */
  658. /* FOLLOW SET: */
  659. /*  <type>             : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  660. /*       <string>, bool, int, single, double, fixed, proto, var, not, sin, cos, */
  661. /*       tan, asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, if, */
  662. /*       then, else, elseif, while, until, do, resize, to, error, true, */
  663. /*       false, set, (, ), CLOSEBRACKET, ,, :=, ;, -, EQ, <prototype>, <expr>, */
  664. /*       <formalargtail>, <vartail>, <expr2>, <expr3>, <expr4>, <expr5>, <expr6>, */
  665. /*       <unary_oper>, <expr7>, <expr8>, <actualtail>, <iftail>, <whileloop>, */
  666. /*       <loopwhileuntil>, <untilloop>, <exprlisttail>} */
  667. static CompileErrors    ParseType(DataTypes* TypeOut, ScannerRec* Scanner,
  668.                                                 long* LineNumberOut)
  669.     {
  670.         TokenRec*                        Token;
  671.  
  672.         /* get the word */
  673.         Token = GetNextToken(Scanner);
  674.         if (Token == NIL)
  675.             {
  676.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  677.                 return eCompileOutOfMemory;
  678.             }
  679.  
  680.         /* make sure it's a keyword */
  681.         if (GetTokenType(Token) != eTokenKeyword)
  682.             {
  683.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  684.                 return eCompileExpectedTypeSpecifier;
  685.             }
  686.  
  687.         /* do the decoding */
  688.         switch (GetTokenKeywordTag(Token))
  689.             {
  690.                 default:
  691.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  692.                     return eCompileExpectedTypeSpecifier;
  693.                 case eKeywordVoid:
  694.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  695.                     return eCompileVoidExpressionIsNotAllowed;
  696.                 case eKeywordBool:
  697.                     *TypeOut = eBoolean;
  698.                     break;
  699.                 case eKeywordInt:
  700.                     *TypeOut = eInteger;
  701.                     break;
  702.                 case eKeywordSingle:
  703.                     *TypeOut = eFloat;
  704.                     break;
  705.                 case eKeywordDouble:
  706.                     *TypeOut = eDouble;
  707.                     break;
  708.                 case eKeywordFixed:
  709.                     *TypeOut = eFixed;
  710.                     break;
  711.                 case eKeywordBoolarray:
  712.                     *TypeOut = eArrayOfBoolean;
  713.                     break;
  714.                 case eKeywordIntarray:
  715.                     *TypeOut = eArrayOfInteger;
  716.                     break;
  717.                 case eKeywordSinglearray:
  718.                     *TypeOut = eArrayOfFloat;
  719.                     break;
  720.                 case eKeywordDoublearray:
  721.                     *TypeOut = eArrayOfDouble;
  722.                     break;
  723.                 case eKeywordFixedarray:
  724.                     *TypeOut = eArrayOfFixed;
  725.                     break;
  726.             }
  727.  
  728.         return eCompileNoError;
  729.     }
  730.  
  731.  
  732.  
  733.  
  734. /*   26:   <expr>             ::= <expr2> */
  735. /*  109:   <expr>             ::= if <ifrest> */
  736. /*  114:   <expr>             ::= <whileloop> */
  737. /*  115:                      ::= do <expr> <loopwhileuntil> */
  738. /*  116:                      ::= <untilloop> */
  739. /*  121:   <expr>             ::= set <expr> := <expr> */
  740. /*  125:   <expr>             ::= resize <expr> to <expr> */
  741. /*  126:                      ::= error <string> resumable <expr> */
  742. /*  XXX:                      ::= getsampleleft <string> */
  743. /*  XXX:                      ::= getsampleright <string> */
  744. /*  XXX:                      ::= getsample <string> */
  745. /*  XXX:                      ::= getwavenumframes <string> */
  746. /*  XXX:                      ::= getwavenumtables <string> */
  747. /*  XXX:                      ::= getwavedata <string> */
  748. /* FIRST SET: */
  749. /*  <expr>             : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  750. /*       <string>, bool, int, single, double, fixed, proto, var, not, sin, cos, */
  751. /*       tan, asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, if, */
  752. /*       while, until, do, resize, error, true, false, set, (, -, */
  753. /*       <prototype>, <expr2>, <expr3>, <expr4>, <expr5>, <expr6>, <unary_oper>, */
  754. /*       <expr7>, <expr8>, <whileloop>, <untilloop>} */
  755. /* FOLLOW SET: */
  756. /*  <expr>             : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  757. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  758. CompileErrors                    ParseExpr(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  759.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  760.                                                 long* LineNumberOut)
  761.     {
  762.         TokenRec*                        Token;
  763.         long                                LineNumberForFirstToken;
  764.  
  765.         CheckPtrExistence(Scanner);
  766.         CheckPtrExistence(SymbolTable);
  767.         CheckPtrExistence(TrashTracker);
  768.  
  769.         /* get the first token to be gotten */
  770.         Token = GetNextToken(Scanner);
  771.         LineNumberForFirstToken = GetCurrentLineNumber(Scanner);
  772.         if (Token == NIL)
  773.             {
  774.                 *LineNumberOut = LineNumberForFirstToken;
  775.                 return eCompileOutOfMemory;
  776.             }
  777.  
  778.         /* see what action should be taken */
  779.         switch (GetTokenType(Token))
  780.             {
  781.                 default:
  782.                     UngetToken(Scanner,Token);
  783.                     return ParseExpr2(ExpressionOut,Scanner,SymbolTable,TrashTracker,
  784.                         LineNumberOut);
  785.  
  786.                 case eTokenKeyword:
  787.                     switch (GetTokenKeywordTag(Token))
  788.                         {
  789.                             default:
  790.                                 UngetToken(Scanner,Token);
  791.                                 return ParseExpr2(ExpressionOut,Scanner,SymbolTable,TrashTracker,
  792.                                     LineNumberOut);
  793.  
  794.                             /*  109:   <expr>             ::= if <ifrest> */
  795.                             case eKeywordIf:
  796.                                 return ParseIfRest(ExpressionOut,Scanner,SymbolTable,TrashTracker,
  797.                                     LineNumberOut);
  798.  
  799.                             /*  114:   <expr>             ::= <whileloop> */
  800.                             /* FIRST SET: */
  801.                             /*  <whileloop>        : {while} */
  802.                             case eKeywordWhile:
  803.                                 UngetToken(Scanner,Token);
  804.                                 return ParseWhileLoop(ExpressionOut,Scanner,SymbolTable,TrashTracker,
  805.                                     LineNumberOut);
  806.  
  807.                             /*  115:                      ::= do <expr> <loopwhileuntil> */
  808.                             case eKeywordDo:
  809.                                 {
  810.                                     ASTExpressionRec*        BodyExpression;
  811.                                     CompileErrors                Error;
  812.  
  813.                                     Error = ParseExpr(&BodyExpression,Scanner,SymbolTable,
  814.                                         TrashTracker,LineNumberOut);
  815.                                     if (Error != eCompileNoError)
  816.                                         {
  817.                                             return Error;
  818.                                         }
  819.  
  820.                                     /* parse the rest of it */
  821.                                     return ParseLoopWhileUntil(ExpressionOut,BodyExpression,Scanner,
  822.                                         SymbolTable,TrashTracker,LineNumberOut,LineNumberForFirstToken);
  823.                                 }
  824.  
  825.                             /*  116:                      ::= <untilloop> */
  826.                             /* FIRST SET */
  827.                             /*  <untilloop>        : {until} */
  828.                             case eKeywordUntil:
  829.                                 UngetToken(Scanner,Token);
  830.                                 return ParseUntilLoop(ExpressionOut,Scanner,SymbolTable,TrashTracker,
  831.                                     LineNumberOut);
  832.  
  833.                             /*  121:   <expr>             ::= set <expr> := <expr> */
  834.                             case eKeywordSet:
  835.                                 {
  836.                                     ASTExpressionRec*        LValue;
  837.                                     ASTExpressionRec*        RValue;
  838.                                     CompileErrors                Error;
  839.                                     ASTAssignRec*                TotalAssignment;
  840.  
  841.                                     Error = ParseExpr(&LValue,Scanner,SymbolTable,TrashTracker,
  842.                                         LineNumberOut);
  843.                                     if (Error != eCompileNoError)
  844.                                         {
  845.                                             return Error;
  846.                                         }
  847.  
  848.                                     /* swallow the colon-equals */
  849.                                     Token = GetNextToken(Scanner);
  850.                                     if (Token == NIL)
  851.                                         {
  852.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  853.                                             return eCompileOutOfMemory;
  854.                                         }
  855.                                     if (GetTokenType(Token) != eTokenColonEqual)
  856.                                         {
  857.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  858.                                             return eCompileExpectedColonEqual;
  859.                                         }
  860.  
  861.                                     Error = ParseExpr(&RValue,Scanner,SymbolTable,TrashTracker,
  862.                                         LineNumberOut);
  863.                                     if (Error != eCompileNoError)
  864.                                         {
  865.                                             return Error;
  866.                                         }
  867.  
  868.                                     TotalAssignment = NewAssignment(LValue,RValue,TrashTracker,
  869.                                         LineNumberForFirstToken);
  870.                                     if (TotalAssignment == NIL)
  871.                                         {
  872.                                             *LineNumberOut = LineNumberForFirstToken;
  873.                                             return eCompileOutOfMemory;
  874.                                         }
  875.  
  876.                                     *ExpressionOut = NewExprAssignment(TotalAssignment,TrashTracker,
  877.                                         LineNumberForFirstToken);
  878.                                     if (*ExpressionOut == NIL)
  879.                                         {
  880.                                             *LineNumberOut = LineNumberForFirstToken;
  881.                                             return eCompileOutOfMemory;
  882.                                         }
  883.  
  884.                                     return eCompileNoError;
  885.                                 }
  886.  
  887.                             /*  125:   <expr>             ::= resize <expr> to <expr> */
  888.                             case eKeywordResize:
  889.                                 {
  890.                                     ASTExpressionRec*        ArrayGenerator;
  891.                                     ASTExpressionRec*        NewSizeExpression;
  892.                                     CompileErrors                Error;
  893.                                     ASTBinaryOpRec*            BinaryOperator;
  894.  
  895.                                     Error = ParseExpr(&ArrayGenerator,Scanner,SymbolTable,TrashTracker,
  896.                                         LineNumberOut);
  897.                                     if (Error != eCompileNoError)
  898.                                         {
  899.                                             return Error;
  900.                                         }
  901.  
  902.                                     /* swallow the to */
  903.                                     Token = GetNextToken(Scanner);
  904.                                     if (Token == NIL)
  905.                                         {
  906.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  907.                                             return eCompileOutOfMemory;
  908.                                         }
  909.                                     if ((GetTokenType(Token) != eTokenKeyword)
  910.                                         || (GetTokenKeywordTag(Token) != eKeywordTo))
  911.                                         {
  912.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  913.                                             return eCompileExpectedTo;
  914.                                         }
  915.  
  916.                                     Error = ParseExpr(&NewSizeExpression,Scanner,SymbolTable,TrashTracker,
  917.                                         LineNumberOut);
  918.                                     if (Error != eCompileNoError)
  919.                                         {
  920.                                             return Error;
  921.                                         }
  922.  
  923.                                     BinaryOperator = NewBinaryOperator(eBinaryResizeArray,ArrayGenerator,
  924.                                         NewSizeExpression,TrashTracker,LineNumberForFirstToken);
  925.                                     if (BinaryOperator == NIL)
  926.                                         {
  927.                                             *LineNumberOut = LineNumberForFirstToken;
  928.                                             return eCompileOutOfMemory;
  929.                                         }
  930.  
  931.                                     *ExpressionOut = NewExprBinaryOperator(BinaryOperator,TrashTracker,
  932.                                         LineNumberForFirstToken);
  933.                                     if (*ExpressionOut == NIL)
  934.                                         {
  935.                                             *LineNumberOut = LineNumberForFirstToken;
  936.                                             return eCompileOutOfMemory;
  937.                                         }
  938.  
  939.                                     return eCompileNoError;
  940.                                 }
  941.  
  942.                             /*  126:                      ::= error <string> resumable <expr> */
  943.                             case eKeywordError:
  944.                                 {
  945.                                     TokenRec*                        MessageString;
  946.                                     ASTExpressionRec*        ResumableCondition;
  947.                                     CompileErrors                Error;
  948.                                     ASTErrorFormRec*        ErrorForm;
  949.  
  950.                                     MessageString = GetNextToken(Scanner);
  951.                                     if (MessageString == NIL)
  952.                                         {
  953.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  954.                                             return eCompileOutOfMemory;
  955.                                         }
  956.                                     if (GetTokenType(MessageString) != eTokenString)
  957.                                         {
  958.                                             *LineNumberOut = LineNumberForFirstToken;
  959.                                             return eCompileExpectedStringLiteral;
  960.                                         }
  961.  
  962.                                     /* swallow the resumable */
  963.                                     Token = GetNextToken(Scanner);
  964.                                     if (Token == NIL)
  965.                                         {
  966.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  967.                                             return eCompileOutOfMemory;
  968.                                         }
  969.                                     if ((GetTokenType(Token) != eTokenKeyword)
  970.                                         || (GetTokenKeywordTag(Token) != eKeywordResumable))
  971.                                         {
  972.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  973.                                             return eCompileExpectedResumable;
  974.                                         }
  975.  
  976.                                     Error = ParseExpr(&ResumableCondition,Scanner,SymbolTable,
  977.                                         TrashTracker,LineNumberOut);
  978.                                     if (Error != eCompileNoError)
  979.                                         {
  980.                                             return Error;
  981.                                         }
  982.  
  983.                                     ErrorForm = NewErrorForm(ResumableCondition,
  984.                                         GetTokenStringValue(MessageString),TrashTracker,
  985.                                         LineNumberForFirstToken);
  986.                                     if (ErrorForm == NIL)
  987.                                         {
  988.                                             *LineNumberOut = LineNumberForFirstToken;
  989.                                             return eCompileOutOfMemory;
  990.                                         }
  991.  
  992.                                     *ExpressionOut = NewExprErrorForm(ErrorForm,TrashTracker,
  993.                                         LineNumberForFirstToken);
  994.                                     if (*ExpressionOut == NIL)
  995.                                         {
  996.                                             *LineNumberOut = LineNumberForFirstToken;
  997.                                             return eCompileOutOfMemory;
  998.                                         }
  999.  
  1000.                                     return eCompileNoError;
  1001.                                 }
  1002.  
  1003.                             /*  XXX:                      ::= getsampleleft <string> */
  1004.                             case eKeywordGetsampleleft:
  1005.                                 {
  1006.                                     ASTWaveGetterRec*        WaveGetterThang;
  1007.  
  1008.                                     Token = GetNextToken(Scanner);
  1009.                                     if (Token == NIL)
  1010.                                         {
  1011.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1012.                                             return eCompileOutOfMemory;
  1013.                                         }
  1014.                                     if (GetTokenType(Token) != eTokenString)
  1015.                                         {
  1016.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1017.                                             return eCompileExpectedStringLiteral;
  1018.                                         }
  1019.  
  1020.                                     WaveGetterThang = NewWaveGetter(GetTokenStringValue(Token),
  1021.                                         eWaveGetterSampleLeft,TrashTracker,GetCurrentLineNumber(Scanner));
  1022.                                     if (WaveGetterThang == NIL)
  1023.                                         {
  1024.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1025.                                             return eCompileOutOfMemory;
  1026.                                         }
  1027.  
  1028.                                     *ExpressionOut = NewExprWaveGetter(WaveGetterThang,TrashTracker,
  1029.                                         GetCurrentLineNumber(Scanner));
  1030.                                     if (*ExpressionOut == NIL)
  1031.                                         {
  1032.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1033.                                             return eCompileOutOfMemory;
  1034.                                         }
  1035.  
  1036.                                     return eCompileNoError;
  1037.                                 }
  1038.  
  1039.                             /*  XXX:                      ::= getsampleright <string> */
  1040.                             case eKeywordGetsampleright:
  1041.                                 {
  1042.                                     ASTWaveGetterRec*        WaveGetterThang;
  1043.  
  1044.                                     Token = GetNextToken(Scanner);
  1045.                                     if (Token == NIL)
  1046.                                         {
  1047.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1048.                                             return eCompileOutOfMemory;
  1049.                                         }
  1050.                                     if (GetTokenType(Token) != eTokenString)
  1051.                                         {
  1052.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1053.                                             return eCompileExpectedStringLiteral;
  1054.                                         }
  1055.  
  1056.                                     WaveGetterThang = NewWaveGetter(GetTokenStringValue(Token),
  1057.                                         eWaveGetterSampleRight,TrashTracker,GetCurrentLineNumber(Scanner));
  1058.                                     if (WaveGetterThang == NIL)
  1059.                                         {
  1060.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1061.                                             return eCompileOutOfMemory;
  1062.                                         }
  1063.  
  1064.                                     *ExpressionOut = NewExprWaveGetter(WaveGetterThang,TrashTracker,
  1065.                                         GetCurrentLineNumber(Scanner));
  1066.                                     if (*ExpressionOut == NIL)
  1067.                                         {
  1068.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1069.                                             return eCompileOutOfMemory;
  1070.                                         }
  1071.  
  1072.                                     return eCompileNoError;
  1073.                                 }
  1074.  
  1075.                             /*  XXX:                      ::= getsample <string> */
  1076.                             case eKeywordGetsample:
  1077.                                 {
  1078.                                     ASTWaveGetterRec*        WaveGetterThang;
  1079.  
  1080.                                     Token = GetNextToken(Scanner);
  1081.                                     if (Token == NIL)
  1082.                                         {
  1083.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1084.                                             return eCompileOutOfMemory;
  1085.                                         }
  1086.                                     if (GetTokenType(Token) != eTokenString)
  1087.                                         {
  1088.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1089.                                             return eCompileExpectedStringLiteral;
  1090.                                         }
  1091.  
  1092.                                     WaveGetterThang = NewWaveGetter(GetTokenStringValue(Token),
  1093.                                         eWaveGetterSampleMono,TrashTracker,GetCurrentLineNumber(Scanner));
  1094.                                     if (WaveGetterThang == NIL)
  1095.                                         {
  1096.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1097.                                             return eCompileOutOfMemory;
  1098.                                         }
  1099.  
  1100.                                     *ExpressionOut = NewExprWaveGetter(WaveGetterThang,TrashTracker,
  1101.                                         GetCurrentLineNumber(Scanner));
  1102.                                     if (*ExpressionOut == NIL)
  1103.                                         {
  1104.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1105.                                             return eCompileOutOfMemory;
  1106.                                         }
  1107.  
  1108.                                     return eCompileNoError;
  1109.                                 }
  1110.  
  1111.                             /*  XXX:                      ::= getwavenumframes <string> */
  1112.                             case eKeywordGetwavenumframes:
  1113.                                 {
  1114.                                     ASTWaveGetterRec*        WaveGetterThang;
  1115.  
  1116.                                     Token = GetNextToken(Scanner);
  1117.                                     if (Token == NIL)
  1118.                                         {
  1119.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1120.                                             return eCompileOutOfMemory;
  1121.                                         }
  1122.                                     if (GetTokenType(Token) != eTokenString)
  1123.                                         {
  1124.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1125.                                             return eCompileExpectedStringLiteral;
  1126.                                         }
  1127.  
  1128.                                     WaveGetterThang = NewWaveGetter(GetTokenStringValue(Token),
  1129.                                         eWaveGetterWaveFrames,TrashTracker,GetCurrentLineNumber(Scanner));
  1130.                                     if (WaveGetterThang == NIL)
  1131.                                         {
  1132.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1133.                                             return eCompileOutOfMemory;
  1134.                                         }
  1135.  
  1136.                                     *ExpressionOut = NewExprWaveGetter(WaveGetterThang,TrashTracker,
  1137.                                         GetCurrentLineNumber(Scanner));
  1138.                                     if (*ExpressionOut == NIL)
  1139.                                         {
  1140.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1141.                                             return eCompileOutOfMemory;
  1142.                                         }
  1143.  
  1144.                                     return eCompileNoError;
  1145.                                 }
  1146.  
  1147.                             /*  XXX:                      ::= getwavenumtables <string> */
  1148.                             case eKeywordGetwavenumtables:
  1149.                                 {
  1150.                                     ASTWaveGetterRec*        WaveGetterThang;
  1151.  
  1152.                                     Token = GetNextToken(Scanner);
  1153.                                     if (Token == NIL)
  1154.                                         {
  1155.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1156.                                             return eCompileOutOfMemory;
  1157.                                         }
  1158.                                     if (GetTokenType(Token) != eTokenString)
  1159.                                         {
  1160.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1161.                                             return eCompileExpectedStringLiteral;
  1162.                                         }
  1163.  
  1164.                                     WaveGetterThang = NewWaveGetter(GetTokenStringValue(Token),
  1165.                                         eWaveGetterWaveTables,TrashTracker,GetCurrentLineNumber(Scanner));
  1166.                                     if (WaveGetterThang == NIL)
  1167.                                         {
  1168.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1169.                                             return eCompileOutOfMemory;
  1170.                                         }
  1171.  
  1172.                                     *ExpressionOut = NewExprWaveGetter(WaveGetterThang,TrashTracker,
  1173.                                         GetCurrentLineNumber(Scanner));
  1174.                                     if (*ExpressionOut == NIL)
  1175.                                         {
  1176.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1177.                                             return eCompileOutOfMemory;
  1178.                                         }
  1179.  
  1180.                                     return eCompileNoError;
  1181.                                 }
  1182.  
  1183.                             /*  XXX:                      ::= getwavedata <string> */
  1184.                             case eKeywordGetwavedata:
  1185.                                 {
  1186.                                     ASTWaveGetterRec*        WaveGetterThang;
  1187.  
  1188.                                     Token = GetNextToken(Scanner);
  1189.                                     if (Token == NIL)
  1190.                                         {
  1191.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1192.                                             return eCompileOutOfMemory;
  1193.                                         }
  1194.                                     if (GetTokenType(Token) != eTokenString)
  1195.                                         {
  1196.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1197.                                             return eCompileExpectedStringLiteral;
  1198.                                         }
  1199.  
  1200.                                     WaveGetterThang = NewWaveGetter(GetTokenStringValue(Token),
  1201.                                         eWaveGetterWaveArray,TrashTracker,GetCurrentLineNumber(Scanner));
  1202.                                     if (WaveGetterThang == NIL)
  1203.                                         {
  1204.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1205.                                             return eCompileOutOfMemory;
  1206.                                         }
  1207.  
  1208.                                     *ExpressionOut = NewExprWaveGetter(WaveGetterThang,TrashTracker,
  1209.                                         GetCurrentLineNumber(Scanner));
  1210.                                     if (*ExpressionOut == NIL)
  1211.                                         {
  1212.                                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1213.                                             return eCompileOutOfMemory;
  1214.                                         }
  1215.  
  1216.                                     return eCompileNoError;
  1217.                                 }
  1218.                         }
  1219.             }
  1220.         EXECUTE(PRERR(ForceAbort,"ParseExpr:  control reached end of function"));
  1221.     }
  1222.  
  1223.  
  1224.  
  1225.  
  1226. /*   17:   <formalparamlist>  ::= <formalarg> <formalargtail>  */
  1227. /* FIRST SET: */
  1228. /*  <formalparamlist>  : {<identifier>, <formalarg>} */
  1229. /* FOLLOW SET: */
  1230. /*  <formalparamlist>  : {)} */
  1231. static CompileErrors    ParseFormalParamList(SymbolListRec** FormalArgListOut,
  1232.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  1233.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  1234.     {
  1235.         CompileErrors                Error;
  1236.         SymbolRec*                    FormalArgOut;
  1237.         SymbolListRec*            ListTail;
  1238.  
  1239.         CheckPtrExistence(Scanner);
  1240.         CheckPtrExistence(SymbolTable);
  1241.         CheckPtrExistence(TrashTracker);
  1242.  
  1243.         Error = ParseFormalArg(&FormalArgOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1244.         if (Error != eCompileNoError)
  1245.             {
  1246.                 return Error;
  1247.             }
  1248.  
  1249.         Error = ParseFormalArgTail(&ListTail,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1250.         if (Error != eCompileNoError)
  1251.             {
  1252.                 return Error;
  1253.             }
  1254.  
  1255.         *FormalArgListOut = SymbolListCons(FormalArgOut,ListTail,TrashTracker);
  1256.         if (*FormalArgListOut == NIL)
  1257.             {
  1258.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1259.                 return eCompileOutOfMemory;
  1260.             }
  1261.  
  1262.         return eCompileNoError;
  1263.     }
  1264.  
  1265.  
  1266.  
  1267.  
  1268. /*  117:   <whileloop>        ::= while <expr> do <expr> */
  1269. /* FIRST SET: */
  1270. /*  <whileloop>        : {while} */
  1271. /* FOLLOW SET: */
  1272. /*  <whileloop>        : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  1273. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  1274. static CompileErrors    ParseWhileLoop(ASTExpressionRec** ExpressionOut,
  1275.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  1276.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  1277.     {
  1278.         TokenRec*                        Token;
  1279.         ASTExpressionRec*        ConditionalExpr;
  1280.         ASTExpressionRec*        BodyExpr;
  1281.         CompileErrors                Error;
  1282.         ASTLoopRec*                    WhileLoopThing;
  1283.         long                                LineNumberOfWholeForm;
  1284.  
  1285.         CheckPtrExistence(Scanner);
  1286.         CheckPtrExistence(SymbolTable);
  1287.         CheckPtrExistence(TrashTracker);
  1288.  
  1289.         LineNumberOfWholeForm = GetCurrentLineNumber(Scanner);
  1290.  
  1291.         /* munch while */
  1292.         Token = GetNextToken(Scanner);
  1293.         if (Token == NIL)
  1294.             {
  1295.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1296.                 return eCompileOutOfMemory;
  1297.             }
  1298.         if ((GetTokenType(Token) != eTokenKeyword)
  1299.             || (GetTokenKeywordTag(Token) != eKeywordWhile))
  1300.             {
  1301.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1302.                 return eCompileExpectedWhile;
  1303.             }
  1304.  
  1305.         Error = ParseExpr(&ConditionalExpr,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1306.         if (Error != eCompileNoError)
  1307.             {
  1308.                 return Error;
  1309.             }
  1310.  
  1311.         /* munch do */
  1312.         Token = GetNextToken(Scanner);
  1313.         if (Token == NIL)
  1314.             {
  1315.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1316.                 return eCompileOutOfMemory;
  1317.             }
  1318.         if ((GetTokenType(Token) != eTokenKeyword)
  1319.             || (GetTokenKeywordTag(Token) != eKeywordDo))
  1320.             {
  1321.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1322.                 return eCompileExpectedDo;
  1323.             }
  1324.  
  1325.         Error = ParseExpr(&BodyExpr,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1326.         if (Error != eCompileNoError)
  1327.             {
  1328.                 return Error;
  1329.             }
  1330.  
  1331.         WhileLoopThing = NewLoop(eLoopWhileDo,ConditionalExpr,BodyExpr,TrashTracker,
  1332.             LineNumberOfWholeForm);
  1333.         if (WhileLoopThing == NIL)
  1334.             {
  1335.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1336.                 return eCompileOutOfMemory;
  1337.             }
  1338.  
  1339.         *ExpressionOut = NewExprLoop(WhileLoopThing,TrashTracker,LineNumberOfWholeForm);
  1340.         if (*ExpressionOut == NIL)
  1341.             {
  1342.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1343.                 return eCompileOutOfMemory;
  1344.             }
  1345.  
  1346.         return eCompileNoError;
  1347.     }
  1348.  
  1349.  
  1350.  
  1351.  
  1352. /*  118:   <untilloop>        ::= until <expr> do <expr> */
  1353. /* FIRST SET: */
  1354. /*  <untilloop>        : {until} */
  1355. /* FOLLOW SET: */
  1356. /*  <untilloop>        : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  1357. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  1358. static CompileErrors    ParseUntilLoop(ASTExpressionRec** ExpressionOut,
  1359.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  1360.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  1361.     {
  1362.         TokenRec*                        Token;
  1363.         ASTExpressionRec*        ConditionalExpr;
  1364.         ASTExpressionRec*        BodyExpr;
  1365.         CompileErrors                Error;
  1366.         ASTLoopRec*                    UntilLoopThing;
  1367.         long                                LineNumberOfWholeForm;
  1368.  
  1369.         CheckPtrExistence(Scanner);
  1370.         CheckPtrExistence(SymbolTable);
  1371.         CheckPtrExistence(TrashTracker);
  1372.  
  1373.         LineNumberOfWholeForm = GetCurrentLineNumber(Scanner);
  1374.  
  1375.         /* munch until */
  1376.         Token = GetNextToken(Scanner);
  1377.         if (Token == NIL)
  1378.             {
  1379.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1380.                 return eCompileOutOfMemory;
  1381.             }
  1382.         if ((GetTokenType(Token) != eTokenKeyword)
  1383.             || (GetTokenKeywordTag(Token) != eKeywordUntil))
  1384.             {
  1385.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1386.                 return eCompileExpectedUntil;
  1387.             }
  1388.  
  1389.         Error = ParseExpr(&ConditionalExpr,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1390.         if (Error != eCompileNoError)
  1391.             {
  1392.                 return Error;
  1393.             }
  1394.  
  1395.         /* munch do */
  1396.         Token = GetNextToken(Scanner);
  1397.         if (Token == NIL)
  1398.             {
  1399.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1400.                 return eCompileOutOfMemory;
  1401.             }
  1402.         if ((GetTokenType(Token) != eTokenKeyword)
  1403.             || (GetTokenKeywordTag(Token) != eKeywordDo))
  1404.             {
  1405.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1406.                 return eCompileExpectedDo;
  1407.             }
  1408.  
  1409.         Error = ParseExpr(&BodyExpr,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1410.         if (Error != eCompileNoError)
  1411.             {
  1412.                 return Error;
  1413.             }
  1414.  
  1415.         UntilLoopThing = NewLoop(eLoopUntilDo,ConditionalExpr,BodyExpr,TrashTracker,
  1416.             LineNumberOfWholeForm);
  1417.         if (UntilLoopThing == NIL)
  1418.             {
  1419.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1420.                 return eCompileOutOfMemory;
  1421.             }
  1422.  
  1423.         *ExpressionOut = NewExprLoop(UntilLoopThing,TrashTracker,LineNumberOfWholeForm);
  1424.         if (*ExpressionOut == NIL)
  1425.             {
  1426.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1427.                 return eCompileOutOfMemory;
  1428.             }
  1429.  
  1430.         return eCompileNoError;
  1431.     }
  1432.  
  1433.  
  1434.  
  1435.  
  1436. /*   24:   <vartail>          ::= EQ <expr> */
  1437. /*   25:                      ::= ( <expr> ) */
  1438. /* FIRST SET: */
  1439. /*  <vartail>          : {(, EQ} */
  1440. /* FOLLOW SET: */
  1441. /*  <vartail>          : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  1442. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  1443. static CompileErrors    ParseVarTail(ASTExpressionRec** ExpressionOut,
  1444.                                                 TokenRec* VariableName, long VariableDeclLine,
  1445.                                                 DataTypes VariableType, ScannerRec* Scanner,
  1446.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  1447.                                                 long* LineNumberOut)
  1448.     {
  1449.         TokenRec*                        Token;
  1450.         SymbolRec*                    SymbolTableEntry;
  1451.  
  1452.         CheckPtrExistence(VariableName);
  1453.         CheckPtrExistence(Scanner);
  1454.         CheckPtrExistence(SymbolTable);
  1455.         CheckPtrExistence(TrashTracker);
  1456.  
  1457.         Token = GetNextToken(Scanner);
  1458.         if (Token == NIL)
  1459.             {
  1460.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1461.                 return eCompileOutOfMemory;
  1462.             }
  1463.  
  1464.         /* create symbol table entry */
  1465.         SymbolTableEntry = NewSymbol(TrashTracker,GetTokenIdentifierString(
  1466.             VariableName),PtrSize(GetTokenIdentifierString(VariableName)));
  1467.         if (SymbolTableEntry == NIL)
  1468.             {
  1469.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1470.                 return eCompileOutOfMemory;
  1471.             }
  1472.         SymbolBecomeVariable(SymbolTableEntry,VariableType);
  1473.  
  1474.         /* see what to do */
  1475.         switch (GetTokenType(Token))
  1476.             {
  1477.                 default:
  1478.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  1479.                     return eCompileExpectedOpenParenOrEqual;
  1480.  
  1481.                 /* array declaration */
  1482.                 case eTokenOpenParen:
  1483.                     {
  1484.                         ASTExpressionRec*            ArraySizeExpression;
  1485.                         CompileErrors                    Error;
  1486.                         ASTArrayDeclRec*            ArrayConstructor;
  1487.  
  1488.                         if ((VariableType != eArrayOfBoolean) && (VariableType != eArrayOfInteger)
  1489.                             && (VariableType != eArrayOfFloat) && (VariableType != eArrayOfDouble)
  1490.                             && (VariableType != eArrayOfFixed))
  1491.                             {
  1492.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1493.                                 return eCompileArrayConstructionOnScalarType;
  1494.                             }
  1495.  
  1496.                         Error = ParseExpr(&ArraySizeExpression,Scanner,SymbolTable,TrashTracker,
  1497.                             LineNumberOut);
  1498.                         if (Error != eCompileNoError)
  1499.                             {
  1500.                                 return Error;
  1501.                             }
  1502.  
  1503.                         /* swallow the close paren */
  1504.                         Token = GetNextToken(Scanner);
  1505.                         if (Token == NIL)
  1506.                             {
  1507.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1508.                                 return eCompileOutOfMemory;
  1509.                             }
  1510.                         if (GetTokenType(Token) != eTokenCloseParen)
  1511.                             {
  1512.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1513.                                 return eCompileExpectedCloseParen;
  1514.                             }
  1515.  
  1516.                         /* build the array constructor node */
  1517.                         ArrayConstructor = NewArrayConstruction(SymbolTableEntry,
  1518.                             ArraySizeExpression,TrashTracker,VariableDeclLine);
  1519.                         if (ArrayConstructor == NIL)
  1520.                             {
  1521.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1522.                                 return eCompileOutOfMemory;
  1523.                             }
  1524.  
  1525.                         /* build AST node */
  1526.                         *ExpressionOut = NewExprArrayDecl(ArrayConstructor,TrashTracker,
  1527.                             VariableDeclLine);
  1528.                         if (*ExpressionOut == NIL)
  1529.                             {
  1530.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1531.                                 return eCompileOutOfMemory;
  1532.                             }
  1533.                     }
  1534.                     break;
  1535.  
  1536.                 /* variable construction */
  1537.                 case eTokenEqual:
  1538.                     {
  1539.                         ASTExpressionRec*            Initializer;
  1540.                         CompileErrors                    Error;
  1541.                         ASTVarDeclRec*                VariableConstructor;
  1542.  
  1543.                         Error = ParseExpr(&Initializer,Scanner,SymbolTable,TrashTracker,
  1544.                             LineNumberOut);
  1545.                         if (Error != eCompileNoError)
  1546.                             {
  1547.                                 return Error;
  1548.                             }
  1549.  
  1550.                         /* build variable thing */
  1551.                         VariableConstructor = NewVariableDeclaration(SymbolTableEntry,
  1552.                             Initializer,TrashTracker,VariableDeclLine);
  1553.                         if (VariableConstructor == NIL)
  1554.                             {
  1555.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1556.                                 return eCompileOutOfMemory;
  1557.                             }
  1558.  
  1559.                         /* encapsulate */
  1560.                         *ExpressionOut = NewExprVariableDeclaration(VariableConstructor,TrashTracker,
  1561.                             VariableDeclLine);
  1562.                         if (*ExpressionOut == NIL)
  1563.                             {
  1564.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1565.                                 return eCompileOutOfMemory;
  1566.                             }
  1567.                     }
  1568.                     break;
  1569.             }
  1570.  
  1571.         /* add the identifier to the symbol table */
  1572.         switch (AddSymbolToTable(SymbolTable,SymbolTableEntry))
  1573.             {
  1574.                 case eAddSymbolNoErr:
  1575.                     break;
  1576.                 case eAddSymbolAlreadyExists:
  1577.                     *LineNumberOut = VariableDeclLine;
  1578.                     return eCompileMultiplyDefinedIdentifier;
  1579.                 case eAddSymbolNoMemory:
  1580.                     *LineNumberOut = VariableDeclLine;
  1581.                     return eCompileOutOfMemory;
  1582.                 default:
  1583.                     EXECUTE(PRERR(ForceAbort,"ParseVarTail:  bad value from AddSymbolToTable"));
  1584.                     break;
  1585.             }
  1586.  
  1587.         return eCompileNoError;
  1588.     }
  1589.  
  1590.  
  1591.  
  1592.  
  1593. /*  110:   <ifrest>           ::= <expr> then <expr> <iftail> */
  1594. /* FIRST SET: */
  1595. /*  <ifrest>           : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  1596. /*       <string>, bool, int, single, double, fixed, proto, var, not, sin, */
  1597. /*       cos, tan, asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, */
  1598. /*       if, while, until, do, resize, error, true, false, set, (, -, */
  1599. /*       <prototype>, <expr>, <expr2>, <expr3>, <expr4>, <expr5>, <expr6>, */
  1600. /*       <unary_oper>, <expr7>, <expr8>, <whileloop>, <untilloop>} */
  1601. /* FOLLOW SET: */
  1602. /*  <ifrest>           : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  1603. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  1604. static CompileErrors    ParseIfRest(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  1605.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  1606.                                                 long* LineNumberOut)
  1607.     {
  1608.         TokenRec*                        Token;
  1609.         CompileErrors                Error;
  1610.         ASTExpressionRec*        Predicate;
  1611.         ASTExpressionRec*        Consequent;
  1612.  
  1613.         CheckPtrExistence(Scanner);
  1614.         CheckPtrExistence(SymbolTable);
  1615.         CheckPtrExistence(TrashTracker);
  1616.  
  1617.         Error = ParseExpr(&Predicate,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1618.         if (Error != eCompileNoError)
  1619.             {
  1620.                 return Error;
  1621.             }
  1622.  
  1623.         /* eat the "then" */
  1624.         Token = GetNextToken(Scanner);
  1625.         if (Token == NIL)
  1626.             {
  1627.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1628.                 return eCompileOutOfMemory;
  1629.             }
  1630.         if ((GetTokenType(Token) != eTokenKeyword)
  1631.             || (GetTokenKeywordTag(Token) != eKeywordThen))
  1632.             {
  1633.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1634.                 return eCompileExpectedThen;
  1635.             }
  1636.  
  1637.         Error = ParseExpr(&Consequent,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1638.         if (Error != eCompileNoError)
  1639.             {
  1640.                 return Error;
  1641.             }
  1642.  
  1643.         return ParseIfTail(ExpressionOut,Predicate,Consequent,Scanner,SymbolTable,
  1644.             TrashTracker,LineNumberOut);
  1645.     }
  1646.  
  1647.  
  1648.  
  1649.  
  1650. /*  119:   <loopwhileuntil>   ::= while <expr> */
  1651. /*  120:                      ::= until <expr> */
  1652. /* FIRST SET: */
  1653. /*  <loopwhileuntil>   : {while, until} */
  1654. /* FOLLOW SET: */
  1655. /*  <loopwhileuntil>   : {then, else, elseif, while, until, do, to, */
  1656. /*       ), CLOSEBRACKET, ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, */
  1657. /*       <exprlisttail>} */
  1658. static CompileErrors    ParseLoopWhileUntil(ASTExpressionRec** ExpressionOut,
  1659.                                                 ASTExpressionRec* LoopBodyExpression, ScannerRec* Scanner,
  1660.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  1661.                                                 long* LineNumberOut, long LineNumberOfLoop)
  1662.     {
  1663.         TokenRec*                        Token;
  1664.         LoopTypes                        LoopKind;
  1665.         ASTExpressionRec*        ConditionalExpression;
  1666.         CompileErrors                Error;
  1667.         ASTLoopRec*                    LoopThang;
  1668.  
  1669.         CheckPtrExistence(Scanner);
  1670.         CheckPtrExistence(LoopBodyExpression);
  1671.         CheckPtrExistence(SymbolTable);
  1672.         CheckPtrExistence(TrashTracker);
  1673.  
  1674.         /* see what there is to do */
  1675.         Token = GetNextToken(Scanner);
  1676.         if (Token == NIL)
  1677.             {
  1678.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1679.                 return eCompileOutOfMemory;
  1680.             }
  1681.         if (GetTokenType(Token) != eTokenKeyword)
  1682.             {
  1683.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1684.                 return eCompileExpectedWhileOrUntil;
  1685.             }
  1686.  
  1687.         switch (GetTokenKeywordTag(Token))
  1688.             {
  1689.                 default:
  1690.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  1691.                     return eCompileExpectedWhileOrUntil;
  1692.  
  1693.                 case eKeywordWhile:
  1694.                     LoopKind = eLoopDoWhile;
  1695.                     break;
  1696.  
  1697.                 case eKeywordUntil:
  1698.                     LoopKind = eLoopDoUntil;
  1699.                     break;
  1700.             }
  1701.  
  1702.         Error = ParseExpr(&ConditionalExpression,Scanner,SymbolTable,TrashTracker,
  1703.             LineNumberOut);
  1704.         if (Error != eCompileNoError)
  1705.             {
  1706.                 return Error;
  1707.             }
  1708.  
  1709.         LoopThang = NewLoop(LoopKind,ConditionalExpression,LoopBodyExpression,
  1710.             TrashTracker,LineNumberOfLoop);
  1711.         if (LoopThang == NIL)
  1712.             {
  1713.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1714.                 return eCompileOutOfMemory;
  1715.             }
  1716.  
  1717.         *ExpressionOut = NewExprLoop(LoopThang,TrashTracker,LineNumberOfLoop);
  1718.         if (*ExpressionOut == NIL)
  1719.             {
  1720.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1721.                 return eCompileOutOfMemory;
  1722.             }
  1723.  
  1724.         return eCompileNoError;
  1725.     }
  1726.  
  1727.  
  1728.  
  1729.  
  1730. /*   27:   <expr2>            ::= <expr3> <expr2prime> */
  1731. /* FIRST SET: */
  1732. /*  <expr2>            : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  1733. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, asin, */
  1734. /*       acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, true, */
  1735. /*       false, (, -, <expr3>, <expr4>, <expr5>, <expr6>, <unary_oper>, <expr7>, */
  1736. /*       <expr8>} */
  1737. /* FOLLOW SET: */
  1738. /*  <expr2>            : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  1739. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  1740. static CompileErrors    ParseExpr2(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  1741.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  1742.                                                 long* LineNumberOut)
  1743.     {
  1744.         CompileErrors                Error;
  1745.         ASTExpressionRec*        LeftHandSide;
  1746.  
  1747.         CheckPtrExistence(Scanner);
  1748.         CheckPtrExistence(SymbolTable);
  1749.         CheckPtrExistence(TrashTracker);
  1750.  
  1751.         Error = ParseExpr3(&LeftHandSide,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  1752.         if (Error != eCompileNoError)
  1753.             {
  1754.                 return Error;
  1755.             }
  1756.  
  1757.         return ParseExpr2Prime(ExpressionOut,LeftHandSide,Scanner,SymbolTable,
  1758.             TrashTracker,LineNumberOut);
  1759.     }
  1760.  
  1761.  
  1762.  
  1763.  
  1764. /*   18:   <formalarg>        ::= <identifier> : <type> */
  1765. /* FIRST SET: */
  1766. /*  <formalarg>        : {<identifier>} */
  1767. /* FOLLOW SET: */
  1768. /*  <formalarg>        : {), ,, <formalargtail>} */
  1769. static CompileErrors    ParseFormalArg(SymbolRec** FormalArgOut, ScannerRec* Scanner,
  1770.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  1771.                                                 long* LineNumberOut)
  1772.     {
  1773.         TokenRec*                        IdentifierName;
  1774.         TokenRec*                        Token;
  1775.         DataTypes                        Type;
  1776.         CompileErrors                Error;
  1777.         long                                LineNumberOfIdentifier;
  1778.  
  1779.         CheckPtrExistence(Scanner);
  1780.         CheckPtrExistence(SymbolTable);
  1781.         CheckPtrExistence(TrashTracker);
  1782.  
  1783.         LineNumberOfIdentifier = GetCurrentLineNumber(Scanner);
  1784.  
  1785.         IdentifierName = GetNextToken(Scanner);
  1786.         if (IdentifierName == NIL)
  1787.             {
  1788.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1789.                 return eCompileOutOfMemory;
  1790.             }
  1791.         if (GetTokenType(IdentifierName) != eTokenIdentifier)
  1792.             {
  1793.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1794.                 return eCompileExpectedIdentifier;
  1795.             }
  1796.  
  1797.         /* swallow the colon */
  1798.         Token = GetNextToken(Scanner);
  1799.         if (Token == NIL)
  1800.             {
  1801.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1802.                 return eCompileOutOfMemory;
  1803.             }
  1804.         if (GetTokenType(Token) != eTokenColon)
  1805.             {
  1806.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1807.                 return eCompileExpectedColon;
  1808.             }
  1809.  
  1810.         Error = ParseType(&Type,Scanner,LineNumberOut);
  1811.         if (Error != eCompileNoError)
  1812.             {
  1813.                 return Error;
  1814.             }
  1815.  
  1816.         *FormalArgOut = NewSymbol(TrashTracker,GetTokenIdentifierString(IdentifierName),
  1817.             PtrSize(GetTokenIdentifierString(IdentifierName)));
  1818.         if (*FormalArgOut == NIL)
  1819.             {
  1820.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1821.                 return eCompileOutOfMemory;
  1822.             }
  1823.         SymbolBecomeVariable(*FormalArgOut,Type);
  1824.  
  1825.         switch (AddSymbolToTable(SymbolTable,*FormalArgOut))
  1826.             {
  1827.                 case eAddSymbolNoErr:
  1828.                     break;
  1829.                 case eAddSymbolAlreadyExists:
  1830.                     *LineNumberOut = LineNumberOfIdentifier;
  1831.                     return eCompileMultiplyDefinedIdentifier;
  1832.                 case eAddSymbolNoMemory:
  1833.                     *LineNumberOut = LineNumberOfIdentifier;
  1834.                     return eCompileOutOfMemory;
  1835.                 default:
  1836.                     EXECUTE(PRERR(ForceAbort,"ParseFormalArg:  bad value from AddSymbolToTable"));
  1837.                     break;
  1838.             }
  1839.  
  1840.         return eCompileNoError;
  1841.     }
  1842.  
  1843.  
  1844.  
  1845.  
  1846. /*   19:   <formalargtail>    ::= , <formalparamlist> */
  1847. /*   20:                      ::=  */
  1848. /* FIRST SET: */
  1849. /*  <formalargtail>    : {,} */
  1850. /* FOLLOW SET: */
  1851. /*  <formalargtail>    : {)} */
  1852. static CompileErrors    ParseFormalArgTail(SymbolListRec** ArgListTailOut,
  1853.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  1854.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  1855.     {
  1856.         TokenRec*                        Token;
  1857.  
  1858.         CheckPtrExistence(Scanner);
  1859.         CheckPtrExistence(SymbolTable);
  1860.         CheckPtrExistence(TrashTracker);
  1861.  
  1862.         Token = GetNextToken(Scanner);
  1863.         if (Token == NIL)
  1864.             {
  1865.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1866.                 return eCompileOutOfMemory;
  1867.             }
  1868.  
  1869.         switch (GetTokenType(Token))
  1870.             {
  1871.                 default:
  1872.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  1873.                     return eCompileExpectedCommaOrCloseParen;
  1874.  
  1875.                 case eTokenComma:
  1876.                     return ParseFormalParamList(ArgListTailOut,Scanner,SymbolTable,TrashTracker,
  1877.                         LineNumberOut);
  1878.  
  1879.                 case eTokenCloseParen:
  1880.                     UngetToken(Scanner,Token);
  1881.                     *ArgListTailOut = NIL; /* end of list */
  1882.                     return eCompileNoError;
  1883.             }
  1884.         EXECUTE(PRERR(ForceAbort,"ParseFormalArgTail:  control reaches end of function"));
  1885.     }
  1886.  
  1887.  
  1888.  
  1889.  
  1890. /*  111:   <iftail>           ::= else <expr> */
  1891. /*  112:                      ::= elseif <ifrest> */
  1892. /*  113:                      ::=  */
  1893. /* FIRST SET: */
  1894. /*  <iftail>           : {else, elseif} */
  1895. /* FOLLOW SET: */
  1896. /*  <iftail>           : {then, else, elseif, while, until, do, to, ), CLOSEBRACKET, */
  1897. /*       ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  1898. /* note that 'else' and 'elseif' are in both the first and follow set.  this is */
  1899. /* because if-then-else isn't LL(1).  we handle this by binding else to the deepest */
  1900. /* if statement. */
  1901. static CompileErrors    ParseIfTail(ASTExpressionRec** ExpressionOut,
  1902.                                                 ASTExpressionRec* Predicate, ASTExpressionRec* Consequent,
  1903.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  1904.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  1905.     {
  1906.         TokenRec*                        Token;
  1907.         ASTCondRec*                    Conditional;
  1908.         ASTExpressionRec*        Alternative;
  1909.         CompileErrors                Error;
  1910.  
  1911.         CheckPtrExistence(Scanner);
  1912.         CheckPtrExistence(SymbolTable);
  1913.         CheckPtrExistence(TrashTracker);
  1914.  
  1915.         /* see what the token is */
  1916.         Token = GetNextToken(Scanner);
  1917.         if (Token == NIL)
  1918.             {
  1919.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1920.                 return eCompileOutOfMemory;
  1921.             }
  1922.  
  1923.         /* do the operation */
  1924.         switch (GetTokenType(Token))
  1925.             {
  1926.                     /*  113:                      ::=  */
  1927.                 default:
  1928.                  NullificationPoint:
  1929.                     UngetToken(Scanner,Token);
  1930.                     Conditional = NewConditional(Predicate,Consequent,NIL,TrashTracker,
  1931.                         GetCurrentLineNumber(Scanner));
  1932.                     if (Conditional == NIL)
  1933.                         {
  1934.                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  1935.                             return eCompileOutOfMemory;
  1936.                         }
  1937.                     break;
  1938.  
  1939.                 case eTokenKeyword:
  1940.                     switch (GetTokenKeywordTag(Token))
  1941.                         {
  1942.                                 /*  113:                      ::=  */
  1943.                             default:
  1944.                                 goto NullificationPoint;
  1945.  
  1946.                                 /*  111:   <iftail>           ::= else <expr> */
  1947.                             case eKeywordElse:
  1948.                                 Error = ParseExpr(&Alternative,Scanner,SymbolTable,TrashTracker,
  1949.                                     LineNumberOut);
  1950.                                 if (Error != eCompileNoError)
  1951.                                     {
  1952.                                         return Error;
  1953.                                     }
  1954.                                 Conditional = NewConditional(Predicate,Consequent,Alternative,
  1955.                                     TrashTracker,GetCurrentLineNumber(Scanner));
  1956.                                 if (Conditional == NIL)
  1957.                                     {
  1958.                                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  1959.                                         return eCompileOutOfMemory;
  1960.                                     }
  1961.                                 break;
  1962.  
  1963.                                 /*  112:                      ::= elseif <ifrest> */
  1964.                             case eKeywordElseif:
  1965.                                 Error = ParseIfRest(&Alternative,Scanner,SymbolTable,TrashTracker,
  1966.                                     LineNumberOut);
  1967.                                 if (Error != eCompileNoError)
  1968.                                     {
  1969.                                         return Error;
  1970.                                     }
  1971.                                 Conditional = NewConditional(Predicate,Consequent,Alternative,
  1972.                                     TrashTracker,GetCurrentLineNumber(Scanner));
  1973.                                 if (Conditional == NIL)
  1974.                                     {
  1975.                                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  1976.                                         return eCompileOutOfMemory;
  1977.                                     }
  1978.                                 break;
  1979.                         }
  1980.                     break;
  1981.             }
  1982.  
  1983.         /* finish building expression node */
  1984.         *ExpressionOut = NewExprConditional(Conditional,TrashTracker,
  1985.             GetCurrentLineNumber(Scanner));
  1986.         if (*ExpressionOut == NIL)
  1987.             {
  1988.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  1989.                 return eCompileOutOfMemory;
  1990.             }
  1991.  
  1992.         return eCompileNoError;
  1993.     }
  1994.  
  1995.  
  1996.  
  1997.  
  1998. /*   33:   <expr3>            ::= <expr4> <expr3prime> */
  1999. /* FIRST SET: */
  2000. /*  <expr3>            : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2001. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, asin, */
  2002. /*       acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, true, */
  2003. /*       false, (, -, <expr4>, <expr5>, <expr6>, <unary_oper>, <expr7>, <expr8>} */
  2004. /* FOLLOW SET: */
  2005. /*  <expr3>            : {and, or, xor, then, else, elseif, while, until, do, */
  2006. /*       to, ), CLOSEBRACKET, ,, :=, ;, <expr2prime>, <conj_oper>, <actualtail>, */
  2007. /*       <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2008. static CompileErrors    ParseExpr3(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  2009.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2010.                                                 long* LineNumberOut)
  2011.     {
  2012.         CompileErrors                Error;
  2013.         ASTExpressionRec*        LeftHandSide;
  2014.  
  2015.         CheckPtrExistence(Scanner);
  2016.         CheckPtrExistence(SymbolTable);
  2017.         CheckPtrExistence(TrashTracker);
  2018.  
  2019.         Error = ParseExpr4(&LeftHandSide,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  2020.         if (Error != eCompileNoError)
  2021.             {
  2022.                 return Error;
  2023.             }
  2024.  
  2025.         return ParseExpr3Prime(ExpressionOut,LeftHandSide,Scanner,SymbolTable,
  2026.             TrashTracker,LineNumberOut);
  2027.     }
  2028.  
  2029.  
  2030.  
  2031.  
  2032. /*   28:   <expr2prime>       ::= <conj_oper> <expr3> <expr2prime> */
  2033. /*   29:                      ::=  */
  2034. /* FIRST SET: */
  2035. /*  <expr2prime>       : {and, or, xor, <conj_oper>} */
  2036. /* FOLLOW SET: */
  2037. /*  <expr2prime>       : {then, else, elseif, while, until, do, to, ), */
  2038. /*       CLOSEBRACKET, ,, :=, ;, <actualtail>, <iftail>, <loopwhileuntil>, */
  2039. /*       <exprlisttail>} */
  2040. static CompileErrors    ParseExpr2Prime(ASTExpressionRec** ExpressionOut,
  2041.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  2042.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2043.                                                 long* LineNumberOut)
  2044.     {
  2045.         TokenRec*                        Token;
  2046.         BinaryOpType                OperatorType;
  2047.         CompileErrors                Error;
  2048.         ASTExpressionRec*        RightHandSide;
  2049.         ASTBinaryOpRec*            WholeOperator;
  2050.         ASTExpressionRec*        ThisWholeNode;
  2051.  
  2052.         CheckPtrExistence(LeftHandSide);
  2053.         CheckPtrExistence(Scanner);
  2054.         CheckPtrExistence(SymbolTable);
  2055.         CheckPtrExistence(TrashTracker);
  2056.  
  2057.         Token = GetNextToken(Scanner);
  2058.         if (Token == NIL)
  2059.             {
  2060.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2061.                 return eCompileOutOfMemory;
  2062.             }
  2063.  
  2064.         switch (GetTokenType(Token))
  2065.             {
  2066.                 default:
  2067.                  NullifyPoint:
  2068.                     UngetToken(Scanner,Token);
  2069.                     *ExpressionOut = LeftHandSide;
  2070.                     return eCompileNoError;
  2071.  
  2072.                 case eTokenKeyword:
  2073.                     switch (GetTokenKeywordTag(Token))
  2074.                         {
  2075.                             default:
  2076.                                 goto NullifyPoint;
  2077.  
  2078.                             case eKeywordAnd:
  2079.                             case eKeywordOr:
  2080.                             case eKeywordXor:
  2081.                                 /* actually do the thing */
  2082.                                 UngetToken(Scanner,Token);
  2083.                                 Error = ParseConjOper(&OperatorType,Scanner,LineNumberOut);
  2084.                                 if (Error != eCompileNoError)
  2085.                                     {
  2086.                                         return Error;
  2087.                                     }
  2088.                                 Error = ParseExpr3(&RightHandSide,Scanner,SymbolTable,TrashTracker,
  2089.                                     LineNumberOut);
  2090.                                 if (Error != eCompileNoError)
  2091.                                     {
  2092.                                         return Error;
  2093.                                     }
  2094.                                 /* build the operator node */
  2095.                                 WholeOperator = NewBinaryOperator(OperatorType,LeftHandSide,
  2096.                                     RightHandSide,TrashTracker,GetCurrentLineNumber(Scanner));
  2097.                                 if (WholeOperator == NIL)
  2098.                                     {
  2099.                                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  2100.                                         return eCompileOutOfMemory;
  2101.                                     }
  2102.                                 ThisWholeNode = NewExprBinaryOperator(WholeOperator,TrashTracker,
  2103.                                     GetCurrentLineNumber(Scanner));
  2104.                                 if (ThisWholeNode == NIL)
  2105.                                     {
  2106.                                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  2107.                                         return eCompileOutOfMemory;
  2108.                                     }
  2109.                                 return ParseExpr2Prime(ExpressionOut,ThisWholeNode,Scanner,SymbolTable,
  2110.                                     TrashTracker,LineNumberOut);
  2111.                         }
  2112.                     break;
  2113.             }
  2114.         EXECUTE(PRERR(ForceAbort,"ParseExpr2Prime:  control reached end of function"));
  2115.     }
  2116.  
  2117.  
  2118.  
  2119.  
  2120. /*   42:   <expr4>            ::= <expr5> <expr4prime> */
  2121. /* FIRST SET: */
  2122. /*  <expr4>            : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2123. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, asin, */
  2124. /*       acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, true, */
  2125. /*       false, (, -, <expr5>, <expr6>, <unary_oper>, <expr7>, <expr8>} */
  2126. /* FOLLOW SET: */
  2127. /*  <expr4>            : {and, or, xor, then, else, elseif, while, until, do, */
  2128. /*       to, ), CLOSEBRACKET, ,, :=, ;, EQ, NEQ, LT, LTEQ, GR, GREQ, <expr2prime>, */
  2129. /*       <conj_oper>, <expr3prime>, <rel_oper>, <actualtail>, <iftail>, */
  2130. /*       <loopwhileuntil>, <exprlisttail>} */
  2131. static CompileErrors    ParseExpr4(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  2132.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2133.                                                 long* LineNumberOut)
  2134.     {
  2135.         CompileErrors                Error;
  2136.         ASTExpressionRec*        LeftHandSide;
  2137.  
  2138.         CheckPtrExistence(Scanner);
  2139.         CheckPtrExistence(SymbolTable);
  2140.         CheckPtrExistence(TrashTracker);
  2141.  
  2142.         Error = ParseExpr5(&LeftHandSide,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  2143.         if (Error != eCompileNoError)
  2144.             {
  2145.                 return Error;
  2146.             }
  2147.  
  2148.         return ParseExpr4Prime(ExpressionOut,LeftHandSide,Scanner,SymbolTable,
  2149.             TrashTracker,LineNumberOut);
  2150.     }
  2151.  
  2152.  
  2153.  
  2154.  
  2155. /*   34:   <expr3prime>       ::= <rel_oper> <expr4> <expr3prime> */
  2156. /*   35:                      ::=  */
  2157. /* FIRST SET: */
  2158. /*  <expr3prime>       : {EQ, NEQ, LT, LTEQ, GR, GREQ, <rel_oper>} */
  2159. /* FOLLOW SET: */
  2160. /*  <expr3prime>       : {and, or, xor, then, else, elseif, while, until, */
  2161. /*       do, to, ), CLOSEBRACKET, ,, :=, ;, <expr2prime>, <conj_oper>, */
  2162. /*       <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2163. static CompileErrors    ParseExpr3Prime(ASTExpressionRec** ExpressionOut,
  2164.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  2165.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2166.                                                 long* LineNumberOut)
  2167.     {
  2168.         TokenRec*                        Token;
  2169.         BinaryOpType                OperatorType;
  2170.         CompileErrors                Error;
  2171.         ASTExpressionRec*        RightHandSide;
  2172.         ASTBinaryOpRec*            WholeOperator;
  2173.         ASTExpressionRec*        ThisWholeNode;
  2174.  
  2175.         CheckPtrExistence(LeftHandSide);
  2176.         CheckPtrExistence(Scanner);
  2177.         CheckPtrExistence(SymbolTable);
  2178.         CheckPtrExistence(TrashTracker);
  2179.  
  2180.         Token = GetNextToken(Scanner);
  2181.         if (Token == NIL)
  2182.             {
  2183.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2184.                 return eCompileOutOfMemory;
  2185.             }
  2186.  
  2187.         switch (GetTokenType(Token))
  2188.             {
  2189.                 default:
  2190.                     UngetToken(Scanner,Token);
  2191.                     *ExpressionOut = LeftHandSide;
  2192.                     return eCompileNoError;
  2193.  
  2194.                 case eTokenLessThan:
  2195.                 case eTokenLessThanOrEqual:
  2196.                 case eTokenGreaterThan:
  2197.                 case eTokenGreaterThanOrEqual:
  2198.                 case eTokenEqual:
  2199.                 case eTokenNotEqual:
  2200.                     /* actually do the thing */
  2201.                     UngetToken(Scanner,Token);
  2202.                     Error = ParseRelOper(&OperatorType,Scanner,LineNumberOut);
  2203.                     if (Error != eCompileNoError)
  2204.                         {
  2205.                             return Error;
  2206.                         }
  2207.                     Error = ParseExpr4(&RightHandSide,Scanner,SymbolTable,TrashTracker,
  2208.                         LineNumberOut);
  2209.                     if (Error != eCompileNoError)
  2210.                         {
  2211.                             return Error;
  2212.                         }
  2213.                     /* build the operator node */
  2214.                     WholeOperator = NewBinaryOperator(OperatorType,LeftHandSide,
  2215.                         RightHandSide,TrashTracker,GetCurrentLineNumber(Scanner));
  2216.                     if (WholeOperator == NIL)
  2217.                         {
  2218.                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  2219.                             return eCompileOutOfMemory;
  2220.                         }
  2221.                     ThisWholeNode = NewExprBinaryOperator(WholeOperator,TrashTracker,
  2222.                         GetCurrentLineNumber(Scanner));
  2223.                     if (ThisWholeNode == NIL)
  2224.                         {
  2225.                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  2226.                             return eCompileOutOfMemory;
  2227.                         }
  2228.                     return ParseExpr3Prime(ExpressionOut,ThisWholeNode,Scanner,SymbolTable,
  2229.                         TrashTracker,LineNumberOut);
  2230.             }
  2231.  
  2232.         EXECUTE(PRERR(ForceAbort,"ParseExpr3Prime:  control reached end of function"));
  2233.     }
  2234.  
  2235.  
  2236.  
  2237.  
  2238. /*   30:   <conj_oper>        ::= and */
  2239. /*   31:                      ::= or */
  2240. /*   32:                      ::= xor */
  2241. /* FIRST SET: */
  2242. /*  <conj_oper>        : {and, or, xor} */
  2243. /* FOLLOW SET: */
  2244. /*  <conj_oper>        : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2245. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, */
  2246. /*       asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, */
  2247. /*       true, false, (, -, <expr3>, <expr4>, <expr5>, <expr6>, <unary_oper>, */
  2248. /*       <expr7>, <expr8>} */
  2249. static CompileErrors    ParseConjOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  2250.                                                 long* LineNumberOut)
  2251.     {
  2252.         TokenRec*                        Token;
  2253.  
  2254.         CheckPtrExistence(Scanner);
  2255.  
  2256.         Token = GetNextToken(Scanner);
  2257.         if (Token == NIL)
  2258.             {
  2259.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2260.                 return eCompileOutOfMemory;
  2261.             }
  2262.  
  2263.         switch (GetTokenType(Token))
  2264.             {
  2265.                 default:
  2266.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  2267.                     return eCompileExpectedOperatorOrStatement;
  2268.  
  2269.                 case eTokenKeyword:
  2270.                     switch (GetTokenKeywordTag(Token))
  2271.                         {
  2272.                             default:
  2273.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2274.                                 return eCompileExpectedOperatorOrStatement;
  2275.  
  2276.                             case eKeywordAnd:
  2277.                                 *OperatorOut = eBinaryAnd;
  2278.                                 return eCompileNoError;
  2279.  
  2280.                             case eKeywordOr:
  2281.                                 *OperatorOut = eBinaryOr;
  2282.                                 return eCompileNoError;
  2283.  
  2284.                             case eKeywordXor:
  2285.                                 *OperatorOut = eBinaryXor;
  2286.                                 return eCompileNoError;
  2287.                         }
  2288.                     break;
  2289.             }
  2290.         EXECUTE(PRERR(ForceAbort,"ParseConjOper:  control reached end of function"));
  2291.     }
  2292.  
  2293.  
  2294.  
  2295.  
  2296. /*   47:   <expr5>            ::= <expr6> <expr5prime> */
  2297. /* FIRST SET: */
  2298. /*  <expr5>            : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2299. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, asin, */
  2300. /*       acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, true, */
  2301. /*       false, (, -, <expr6>, <unary_oper>, <expr7>, <expr8>} */
  2302. /* FOLLOW SET: */
  2303. /*  <expr5>            : {and, or, xor, then, else, elseif, while, until, do, */
  2304. /*       to, ), CLOSEBRACKET, ,, :=, ;, +, -, EQ, NEQ, LT, LTEQ, GR, GREQ, */
  2305. /*       <expr2prime>, <conj_oper>, <expr3prime>, <rel_oper>, <expr4prime>, */
  2306. /*       <add_oper>, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2307. static CompileErrors    ParseExpr5(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  2308.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2309.                                                 long* LineNumberOut)
  2310.     {
  2311.         CompileErrors                Error;
  2312.         ASTExpressionRec*        LeftHandSide;
  2313.  
  2314.         CheckPtrExistence(Scanner);
  2315.         CheckPtrExistence(SymbolTable);
  2316.         CheckPtrExistence(TrashTracker);
  2317.  
  2318.         Error = ParseExpr6(&LeftHandSide,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  2319.         if (Error != eCompileNoError)
  2320.             {
  2321.                 return Error;
  2322.             }
  2323.  
  2324.         return ParseExpr5Prime(ExpressionOut,LeftHandSide,Scanner,SymbolTable,
  2325.             TrashTracker,LineNumberOut);
  2326.     }
  2327.  
  2328.  
  2329.  
  2330.  
  2331. /*   43:   <expr4prime>       ::= <add_oper> <expr5> <expr4prime> */
  2332. /*   44:                      ::=  */
  2333. /* FIRST SET: */
  2334. /*  <expr4prime>       : {+, -, <add_oper>} */
  2335. /* FOLLOW SET: */
  2336. /*  <expr4prime>       : {and, or, xor, then, else, elseif, while, until, */
  2337. /*       do, to, ), CLOSEBRACKET, ,, :=, ;, EQ, NEQ, LT, LTEQ, GR, GREQ, */
  2338. /*       <expr2prime>, <conj_oper>, <expr3prime>, <rel_oper>, <actualtail>, */
  2339. /*       <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2340. static CompileErrors    ParseExpr4Prime(ASTExpressionRec** ExpressionOut,
  2341.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  2342.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2343.                                                 long* LineNumberOut)
  2344.     {
  2345.         TokenRec*                        Token;
  2346.         BinaryOpType                OperatorType;
  2347.         CompileErrors                Error;
  2348.         ASTExpressionRec*        RightHandSide;
  2349.         ASTBinaryOpRec*            WholeOperator;
  2350.         ASTExpressionRec*        ThisWholeNode;
  2351.  
  2352.         CheckPtrExistence(LeftHandSide);
  2353.         CheckPtrExistence(Scanner);
  2354.         CheckPtrExistence(SymbolTable);
  2355.         CheckPtrExistence(TrashTracker);
  2356.  
  2357.         Token = GetNextToken(Scanner);
  2358.         if (Token == NIL)
  2359.             {
  2360.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2361.                 return eCompileOutOfMemory;
  2362.             }
  2363.  
  2364.         switch (GetTokenType(Token))
  2365.             {
  2366.                 default:
  2367.                     UngetToken(Scanner,Token);
  2368.                     *ExpressionOut = LeftHandSide;
  2369.                     return eCompileNoError;
  2370.  
  2371.                 case eTokenPlus:
  2372.                 case eTokenMinus:
  2373.                     UngetToken(Scanner,Token);
  2374.                     Error = ParseAddOper(&OperatorType,Scanner,LineNumberOut);
  2375.                     if (Error != eCompileNoError)
  2376.                         {
  2377.                             return Error;
  2378.                         }
  2379.                     Error = ParseExpr5(&RightHandSide,Scanner,SymbolTable,TrashTracker,
  2380.                         LineNumberOut);
  2381.                     if (Error != eCompileNoError)
  2382.                         {
  2383.                             return Error;
  2384.                         }
  2385.                     /* create the node */
  2386.                     WholeOperator = NewBinaryOperator(OperatorType,LeftHandSide,RightHandSide,
  2387.                         TrashTracker,GetCurrentLineNumber(Scanner));
  2388.                     if (WholeOperator == NIL)
  2389.                         {
  2390.                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  2391.                             return eCompileOutOfMemory;
  2392.                         }
  2393.                     ThisWholeNode = NewExprBinaryOperator(WholeOperator,TrashTracker,
  2394.                         GetCurrentLineNumber(Scanner));
  2395.                     if (ThisWholeNode == NIL)
  2396.                         {
  2397.                             *LineNumberOut = GetCurrentLineNumber(Scanner);
  2398.                             return eCompileOutOfMemory;
  2399.                         }
  2400.                     return ParseExpr4Prime(ExpressionOut,ThisWholeNode,Scanner,SymbolTable,
  2401.                         TrashTracker,LineNumberOut);
  2402.             }
  2403.         EXECUTE(PRERR(ForceAbort,"ParseConjOper:  control reached end of function"));
  2404.     }
  2405.  
  2406.  
  2407.  
  2408.  
  2409. /*   36:   <rel_oper>         ::= LT */
  2410. /*   37:                      ::= LTEQ */
  2411. /*   38:                      ::= GR */
  2412. /*   39:                      ::= GREQ */
  2413. /*   40:                      ::= EQ */
  2414. /*   41:                      ::= NEQ */
  2415. /* FIRST SET: */
  2416. /*  <rel_oper>         : {EQ, NEQ, LT, LTEQ, GR, GREQ} */
  2417. /* FOLLOW SET: */
  2418. /*  <rel_oper>         : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2419. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, */
  2420. /*       asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, */
  2421. /*       true, false, (, -, <expr4>, <expr5>, <expr6>, <unary_oper>, <expr7>, */
  2422. /*       <expr8>} */
  2423. static CompileErrors    ParseRelOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  2424.                                                 long* LineNumberOut)
  2425.     {
  2426.         TokenRec*                        Token;
  2427.  
  2428.         CheckPtrExistence(Scanner);
  2429.  
  2430.         Token = GetNextToken(Scanner);
  2431.         if (Token == NIL)
  2432.             {
  2433.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2434.                 return eCompileOutOfMemory;
  2435.             }
  2436.  
  2437.         switch (GetTokenType(Token))
  2438.             {
  2439.                 default:
  2440.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  2441.                     return eCompileExpectedOperatorOrStatement;
  2442.  
  2443.                 case eTokenEqual:
  2444.                     *OperatorOut = eBinaryEqual;
  2445.                     return eCompileNoError;
  2446.  
  2447.                 case eTokenNotEqual:
  2448.                     *OperatorOut = eBinaryNotEqual;
  2449.                     return eCompileNoError;
  2450.  
  2451.                 case eTokenLessThan:
  2452.                     *OperatorOut = eBinaryLessThan;
  2453.                     return eCompileNoError;
  2454.  
  2455.                 case eTokenLessThanOrEqual:
  2456.                     *OperatorOut = eBinaryLessThanOrEqual;
  2457.                     return eCompileNoError;
  2458.  
  2459.                 case eTokenGreaterThan:
  2460.                     *OperatorOut = eBinaryGreaterThan;
  2461.                     return eCompileNoError;
  2462.  
  2463.                 case eTokenGreaterThanOrEqual:
  2464.                     *OperatorOut = eBinaryGreaterThanOrEqual;
  2465.                     return eCompileNoError;
  2466.             }
  2467.         EXECUTE(PRERR(ForceAbort,"ParseRelOper:  control reached end of function"));
  2468.     }
  2469.  
  2470.  
  2471.  
  2472.  
  2473. /*   56:   <expr6>            ::= <unary_oper> <expr6> */
  2474. /*   57:                      ::= <expr7> */
  2475. /* FIRST SET: */
  2476. /*  <expr6>            : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2477. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, asin, */
  2478. /*       acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, true, */
  2479. /*       false, (, -, <unary_oper>, <expr7>, <expr8>} */
  2480. /* FOLLOW SET: */
  2481. /*  <expr6>            : {and, or, xor, div, mod, SHR, SHL, then, else, elseif, */
  2482. /*       while, until, do, to, ), CLOSEBRACKET, ,, :=, ;, *, /, +, -, EQ, NEQ, */
  2483. /*       LT, LTEQ, GR, GREQ, <expr2prime>, <conj_oper>, <expr3prime>, <rel_oper>, */
  2484. /*       <expr4prime>, <add_oper>, <expr5prime>, <mult_oper>, <actualtail>, */
  2485. /*       <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2486. static CompileErrors    ParseExpr6(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  2487.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2488.                                                 long* LineNumberOut)
  2489.     {
  2490.         TokenRec*                        Token;
  2491.         UnaryOpType                    UnaryOperatorThing;
  2492.         ASTExpressionRec*        UnaryArgument;
  2493.         CompileErrors                Error;
  2494.         ASTUnaryOpRec*            UnaryOpNode;
  2495.  
  2496.         CheckPtrExistence(Scanner);
  2497.         CheckPtrExistence(SymbolTable);
  2498.         CheckPtrExistence(TrashTracker);
  2499.  
  2500.         Token = GetNextToken(Scanner);
  2501.         if (Token == NIL)
  2502.             {
  2503.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2504.                 return eCompileOutOfMemory;
  2505.             }
  2506.  
  2507.         switch (GetTokenType(Token))
  2508.             {
  2509.                 default:
  2510.                  OtherPoint:
  2511.                     UngetToken(Scanner,Token);
  2512.                     return ParseExpr7(ExpressionOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  2513.  
  2514.                 case eTokenMinus:
  2515.                     UnaryOperatorThing = eUnaryNegation;
  2516.                     break;
  2517.  
  2518.                 case eTokenKeyword:
  2519.                     switch (GetTokenKeywordTag(Token))
  2520.                         {
  2521.                             default:
  2522.                                 goto OtherPoint;
  2523.  
  2524.                             case eKeywordNot:
  2525.                                 UnaryOperatorThing = eUnaryNot;
  2526.                                 break;
  2527.  
  2528.                             case eKeywordSin:
  2529.                                 UnaryOperatorThing = eUnarySine;
  2530.                                 break;
  2531.  
  2532.                             case eKeywordCos:
  2533.                                 UnaryOperatorThing = eUnaryCosine;
  2534.                                 break;
  2535.  
  2536.                             case eKeywordTan:
  2537.                                 UnaryOperatorThing = eUnaryTangent;
  2538.                                 break;
  2539.  
  2540.                             case eKeywordAsin:
  2541.                                 UnaryOperatorThing = eUnaryArcSine;
  2542.                                 break;
  2543.  
  2544.                             case eKeywordAcos:
  2545.                                 UnaryOperatorThing = eUnaryArcCosine;
  2546.                                 break;
  2547.  
  2548.                             case eKeywordAtan:
  2549.                                 UnaryOperatorThing = eUnaryArcTangent;
  2550.                                 break;
  2551.  
  2552.                             case eKeywordLn:
  2553.                                 UnaryOperatorThing = eUnaryLogarithm;
  2554.                                 break;
  2555.  
  2556.                             case eKeywordExp:
  2557.                                 UnaryOperatorThing = eUnaryExponentiation;
  2558.                                 break;
  2559.  
  2560.                             case eKeywordBool:
  2561.                                 UnaryOperatorThing = eUnaryCastToBoolean;
  2562.                                 break;
  2563.  
  2564.                             case eKeywordInt:
  2565.                                 UnaryOperatorThing = eUnaryCastToInteger;
  2566.                                 break;
  2567.  
  2568.                             case eKeywordSingle:
  2569.                                 UnaryOperatorThing = eUnaryCastToSingle;
  2570.                                 break;
  2571.  
  2572.                             case eKeywordDouble:
  2573.                                 UnaryOperatorThing = eUnaryCastToDouble;
  2574.                                 break;
  2575.  
  2576.                             case eKeywordFixed:
  2577.                                 UnaryOperatorThing = eUnaryCastToFixed;
  2578.                                 break;
  2579.  
  2580.                             case eKeywordSqr:
  2581.                                 UnaryOperatorThing = eUnarySquare;
  2582.                                 break;
  2583.  
  2584.                             case eKeywordSqrt:
  2585.                                 UnaryOperatorThing = eUnarySquareRoot;
  2586.                                 break;
  2587.  
  2588.                             case eKeywordAbs:
  2589.                                 UnaryOperatorThing = eUnaryAbsoluteValue;
  2590.                                 break;
  2591.  
  2592.                             case eKeywordNeg:
  2593.                                 UnaryOperatorThing = eUnaryTestNegative;
  2594.                                 break;
  2595.  
  2596.                             case eKeywordSign:
  2597.                                 UnaryOperatorThing = eUnaryGetSign;
  2598.                                 break;
  2599.  
  2600.                             case eKeywordLength:
  2601.                                 UnaryOperatorThing = eUnaryGetArrayLength;
  2602.                                 break;
  2603.                         }
  2604.                     break;
  2605.             }
  2606.  
  2607.         /* build argument */
  2608.         Error = ParseExpr6(&UnaryArgument,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  2609.         if (Error != eCompileNoError)
  2610.             {
  2611.                 return Error;
  2612.             }
  2613.  
  2614.         /* build node */
  2615.         UnaryOpNode = NewUnaryOperator(UnaryOperatorThing,UnaryArgument,TrashTracker,
  2616.             GetCurrentLineNumber(Scanner));
  2617.         if (UnaryOpNode == NIL)
  2618.             {
  2619.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2620.                 return eCompileOutOfMemory;
  2621.             }
  2622.  
  2623.         *ExpressionOut = NewExprUnaryOperator(UnaryOpNode,TrashTracker,
  2624.             GetCurrentLineNumber(Scanner));
  2625.         if (*ExpressionOut == NIL)
  2626.             {
  2627.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2628.                 return eCompileOutOfMemory;
  2629.             }
  2630.  
  2631.         return eCompileNoError;
  2632.     }
  2633.  
  2634.  
  2635.  
  2636.  
  2637. /*   48:   <expr5prime>       ::= <mult_oper> <expr6> <expr5prime> */
  2638. /*   49:                      ::=  */
  2639. /* FIRST SET: */
  2640. /*  <expr5prime>       : {div, mod, SHR, SHL, *, /, <mult_oper>} */
  2641. /* FOLLOW SET: */
  2642. /*  <expr5prime>       : {and, or, xor, then, else, elseif, while, until, */
  2643. /*       do, to, ), CLOSEBRACKET, ,, :=, ;, +, -, EQ, NEQ, LT, LTEQ, GR, */
  2644. /*       GREQ, <expr2prime>, <conj_oper>, <expr3prime>, <rel_oper>, <expr4prime>, */
  2645. /*       <add_oper>, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2646. static CompileErrors    ParseExpr5Prime(ASTExpressionRec** ExpressionOut,
  2647.                                                 ASTExpressionRec* LeftHandSide, ScannerRec* Scanner,
  2648.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2649.                                                 long* LineNumberOut)
  2650.     {
  2651.         TokenRec*                        Token;
  2652.         ASTExpressionRec*        RightHandSide;
  2653.         BinaryOpType                OperatorThing;
  2654.         CompileErrors                Error;
  2655.         ASTBinaryOpRec*            BinaryOperator;
  2656.         ASTExpressionRec*        WholeThingThing;
  2657.  
  2658.         CheckPtrExistence(LeftHandSide);
  2659.         CheckPtrExistence(Scanner);
  2660.         CheckPtrExistence(SymbolTable);
  2661.         CheckPtrExistence(TrashTracker);
  2662.  
  2663.         Token = GetNextToken(Scanner);
  2664.         if (Token == NIL)
  2665.             {
  2666.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2667.                 return eCompileOutOfMemory;
  2668.             }
  2669.  
  2670.         switch (GetTokenType(Token))
  2671.             {
  2672.                 default:
  2673.                  NullifyPoint:
  2674.                     *ExpressionOut = LeftHandSide;
  2675.                     UngetToken(Scanner,Token);
  2676.                     return eCompileNoError;
  2677.  
  2678.                 case eTokenKeyword:
  2679.                     switch (GetTokenKeywordTag(Token))
  2680.                         {
  2681.                             default:
  2682.                                 goto NullifyPoint;
  2683.  
  2684.                             case eKeywordDiv:
  2685.                             case eKeywordMod:
  2686.                              DoTheStuffPoint:
  2687.                                 UngetToken(Scanner,Token);
  2688.                                 Error = ParseMultOper(&OperatorThing,Scanner,LineNumberOut);
  2689.                                 if (Error != eCompileNoError)
  2690.                                     {
  2691.                                         return Error;
  2692.                                     }
  2693.                                 Error = ParseExpr6(&RightHandSide,Scanner,SymbolTable,TrashTracker,
  2694.                                     LineNumberOut);
  2695.                                 if (Error != eCompileNoError)
  2696.                                     {
  2697.                                         return Error;
  2698.                                     }
  2699.                                 /* create the node */
  2700.                                 BinaryOperator = NewBinaryOperator(OperatorThing,LeftHandSide,
  2701.                                     RightHandSide,TrashTracker,GetCurrentLineNumber(Scanner));
  2702.                                 if (BinaryOperator == NIL)
  2703.                                     {
  2704.                                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  2705.                                         return eCompileOutOfMemory;
  2706.                                     }
  2707.                                 WholeThingThing = NewExprBinaryOperator(BinaryOperator,TrashTracker,
  2708.                                     GetCurrentLineNumber(Scanner));
  2709.                                 if (WholeThingThing == NIL)
  2710.                                     {
  2711.                                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  2712.                                         return eCompileOutOfMemory;
  2713.                                     }
  2714.                                 return ParseExpr5Prime(ExpressionOut,WholeThingThing,Scanner,
  2715.                                     SymbolTable,TrashTracker,LineNumberOut);
  2716.                         }
  2717.                     break;
  2718.  
  2719.                 case eTokenShiftLeft:
  2720.                 case eTokenShiftRight:
  2721.                 case eTokenStar:
  2722.                 case eTokenSlash:
  2723.                     goto DoTheStuffPoint;
  2724.             }
  2725.         EXECUTE(PRERR(ForceAbort,"ParseExpr5Prime:  control reached end of function"));
  2726.     }
  2727.  
  2728.  
  2729.  
  2730.  
  2731. /*   45:   <add_oper>         ::= + */
  2732. /*   46:                      ::= - */
  2733. /*  <add_oper>         : {+, -} */
  2734. /*  <add_oper>         : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2735. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, */
  2736. /*       asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, */
  2737. /*       true, false, (, -, <expr5>, <expr6>, <unary_oper>, <expr7>, <expr8>} */
  2738. static CompileErrors    ParseAddOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  2739.                                                 long* LineNumberOut)
  2740.     {
  2741.         TokenRec*                        Token;
  2742.  
  2743.         CheckPtrExistence(Scanner);
  2744.  
  2745.         Token = GetNextToken(Scanner);
  2746.         if (Token == NIL)
  2747.             {
  2748.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2749.                 return eCompileOutOfMemory;
  2750.             }
  2751.  
  2752.         switch (GetTokenType(Token))
  2753.             {
  2754.                 default:
  2755.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  2756.                     return eCompileExpectedOperatorOrStatement;
  2757.  
  2758.                 case eTokenPlus:
  2759.                     *OperatorOut = eBinaryPlus;
  2760.                     return eCompileNoError;
  2761.  
  2762.                 case eTokenMinus:
  2763.                     *OperatorOut = eBinaryMinus;
  2764.                     return eCompileNoError;
  2765.             }
  2766.         EXECUTE(PRERR(ForceAbort,"ParseAddOper:  control reached end of function"));
  2767.     }
  2768.  
  2769.  
  2770.  
  2771.  
  2772. /*   79:   <expr7>            ::= <expr8> <expr7prime> */
  2773. /* FIRST SET: */
  2774. /*  <expr7>            : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2775. /*       <string>, true, false, (, <expr8>} */
  2776. /* FOLLOW SET: */
  2777. /*  <expr7>            : {and, or, xor, div, mod, SHR, SHL, then, else, elseif, */
  2778. /*       while, until, do, to, ), CLOSEBRACKET, ,, :=, ;, *, /, +, -, EQ, NEQ, */
  2779. /*       LT, LTEQ, GR, GREQ, <expr2prime>, <conj_oper>, <expr3prime>, <rel_oper>, */
  2780. /*       <expr4prime>, <add_oper>, <expr5prime>, <mult_oper>, <actualtail>, */
  2781. /*       <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2782. static CompileErrors    ParseExpr7(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  2783.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2784.                                                 long* LineNumberOut)
  2785.     {
  2786.         ASTExpressionRec*        ResultOfExpr8;
  2787.         CompileErrors                Error;
  2788.  
  2789.         CheckPtrExistence(Scanner);
  2790.         CheckPtrExistence(SymbolTable);
  2791.         CheckPtrExistence(TrashTracker);
  2792.  
  2793.         Error = ParseExpr8(&ResultOfExpr8,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  2794.         if (Error != eCompileNoError)
  2795.             {
  2796.                 return Error;
  2797.             }
  2798.  
  2799.         return ParseExpr7Prime(ExpressionOut,ResultOfExpr8,Scanner,SymbolTable,TrashTracker,
  2800.             LineNumberOut);
  2801.     }
  2802.  
  2803.  
  2804.  
  2805.  
  2806. /*   50:   <mult_oper>        ::= * */
  2807. /*   51:                      ::= / */
  2808. /*   52:                      ::= div */
  2809. /*   53:                      ::= mod */
  2810. /*   54:                      ::= SHL */
  2811. /*   55:                      ::= SHR */
  2812. /*  <mult_oper>        : {div, mod, SHR, SHL, *, /} */
  2813. /*  <mult_oper>        : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2814. /*       <string>, bool, int, single, double, fixed, not, sin, cos, tan, */
  2815. /*       asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, length, */
  2816. /*       true, false, (, -, <expr6>, <unary_oper>, <expr7>, <expr8>} */
  2817. static CompileErrors    ParseMultOper(BinaryOpType* OperatorOut, ScannerRec* Scanner,
  2818.                                                 long* LineNumberOut)
  2819.     {
  2820.         TokenRec*                        Token;
  2821.  
  2822.         CheckPtrExistence(Scanner);
  2823.  
  2824.         Token = GetNextToken(Scanner);
  2825.         if (Token == NIL)
  2826.             {
  2827.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2828.                 return eCompileOutOfMemory;
  2829.             }
  2830.  
  2831.         switch (GetTokenType(Token))
  2832.             {
  2833.                 default:
  2834.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  2835.                     return eCompileExpectedOperatorOrStatement;
  2836.  
  2837.                 case eTokenStar:
  2838.                     *OperatorOut = eBinaryMultiplication;
  2839.                     return eCompileNoError;
  2840.  
  2841.                 case eTokenSlash:
  2842.                     *OperatorOut = eBinaryImpreciseDivision;
  2843.                     return eCompileNoError;
  2844.  
  2845.                 case eTokenShiftLeft:
  2846.                     *OperatorOut = eBinaryShiftLeft;
  2847.                     return eCompileNoError;
  2848.  
  2849.                 case eTokenShiftRight:
  2850.                     *OperatorOut = eBinaryShiftRight;
  2851.                     return eCompileNoError;
  2852.  
  2853.                 case eTokenKeyword:
  2854.                     switch (GetTokenKeywordTag(Token))
  2855.                         {
  2856.                             default:
  2857.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2858.                                 return eCompileExpectedOperatorOrStatement;
  2859.  
  2860.                             case eKeywordDiv:
  2861.                                 *OperatorOut = eBinaryIntegerDivision;
  2862.                                 return eCompileNoError;
  2863.  
  2864.                             case eKeywordMod:
  2865.                                 *OperatorOut = eBinaryIntegerRemainder;
  2866.                                 return eCompileNoError;
  2867.                         }
  2868.                     break;
  2869.             }
  2870.         EXECUTE(PRERR(ForceAbort,"ParseMultOper:  control reached end of function"));
  2871.     }
  2872.  
  2873.  
  2874.  
  2875.  
  2876. /*   92:   <expr8>            ::= <identifier> */
  2877. /*   93:                      ::= <integer> */
  2878. /*   94:                      ::= <single> */
  2879. /*   95:                      ::= <double> */
  2880. /*   96:                      ::= <fixed> */
  2881. /*   97:                      ::= <string> */
  2882. /*   98:                      ::= true */
  2883. /*   99:                      ::= false */
  2884. /*  108:                      ::= ( <exprlist> ) */
  2885. /*  <expr8>            : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  2886. /*       <string>, true, false, (} */
  2887. /*  <expr8>            : {and, or, xor, div, mod, SHR, SHL, then, else, elseif, */
  2888. /*       while, until, do, to, (, ), OPENBRACKET, CLOSEBRACKET, ,, :=, ;, *, */
  2889. /*       /, +, -, ^, EQ, NEQ, LT, LTEQ, GR, GREQ, <expr2prime>, <conj_oper>, */
  2890. /*       <expr3prime>, <rel_oper>, <expr4prime>, <add_oper>, <expr5prime>, */
  2891. /*       <mult_oper>, <expr7prime>, <arraysubscript>, <funccall>, <exponentiation>, */
  2892. /*       <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  2893. static CompileErrors    ParseExpr8(ASTExpressionRec** ExpressionOut, ScannerRec* Scanner,
  2894.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  2895.                                                 long* LineNumberOut)
  2896.     {
  2897.         ASTOperandRec*            TheOperand;
  2898.         TokenRec*                        Token;
  2899.  
  2900.         CheckPtrExistence(Scanner);
  2901.         CheckPtrExistence(SymbolTable);
  2902.         CheckPtrExistence(TrashTracker);
  2903.  
  2904.         Token = GetNextToken(Scanner);
  2905.         if (Token == NIL)
  2906.             {
  2907.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2908.                 return eCompileOutOfMemory;
  2909.             }
  2910.  
  2911.         switch (GetTokenType(Token))
  2912.             {
  2913.                 default:
  2914.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  2915.                     return eCompileExpectedOperand;
  2916.  
  2917.                     /*   92:   <expr8>            ::= <identifier> */
  2918.                 case eTokenIdentifier:
  2919.                     {
  2920.                         SymbolRec*                TheSymbolTableEntry;
  2921.  
  2922.                         TheSymbolTableEntry = GetSymbolFromTable(SymbolTable,
  2923.                             GetTokenIdentifierString(Token),PtrSize(GetTokenIdentifierString(Token)));
  2924.                         if (TheSymbolTableEntry == NIL)
  2925.                             {
  2926.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2927.                                 return eCompileIdentifierNotDeclared;
  2928.                             }
  2929.                         TheOperand = NewSymbolReference(TrashTracker,TheSymbolTableEntry,
  2930.                             GetCurrentLineNumber(Scanner));
  2931.                     }
  2932.                     break;
  2933.  
  2934.                     /*   93:                      ::= <integer> */
  2935.                 case eTokenInteger:
  2936.                     TheOperand = NewIntegerLiteral(TrashTracker,GetTokenIntegerValue(Token),
  2937.                         GetCurrentLineNumber(Scanner));
  2938.                     break;
  2939.  
  2940.                     /*   94:                      ::= <single> */
  2941.                 case eTokenSingle:
  2942.                     TheOperand = NewSingleLiteral(TrashTracker,GetTokenSingleValue(Token),
  2943.                         GetCurrentLineNumber(Scanner));
  2944.                     break;
  2945.  
  2946.                     /*   95:                      ::= <double> */
  2947.                 case eTokenDouble:
  2948.                     TheOperand = NewDoubleLiteral(TrashTracker,GetTokenDoubleValue(Token),
  2949.                         GetCurrentLineNumber(Scanner));
  2950.                     break;
  2951.  
  2952.                     /*   96:                      ::= <fixed> */
  2953.                 case eTokenFixed:
  2954.                     TheOperand = NewFixedLiteral(TrashTracker,GetTokenFixedValue(Token),
  2955.                         GetCurrentLineNumber(Scanner));
  2956.                     break;
  2957.  
  2958.                     /*   97:                      ::= <string> */
  2959.                 case eTokenString:
  2960.                     /* this was here, but I took it out */
  2961.                     *LineNumberOut = GetCurrentLineNumber(Scanner);
  2962.                     return eCompileCantHaveStringLiteralThere;
  2963. #if 0
  2964.                     TheOperand = NewStringLiteral(TrashTracker,GetTokenStringValue(Token),
  2965.                         GetCurrentLineNumber(Scanner));
  2966. #endif
  2967.  
  2968.                     /*  108:                      ::= ( <exprlist> ) */
  2969.                 case eTokenOpenParen:
  2970.                     {
  2971.                         CompileErrors            Error;
  2972.                         ASTExprListRec*        ListOfExpressions;
  2973.  
  2974.                         /* open a new scope */
  2975.                         if (!IncrementSymbolTableLevel(SymbolTable))
  2976.                             {
  2977.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2978.                                 return eCompileOutOfMemory;
  2979.                             }
  2980.  
  2981.                         /* parse the expression sequence */
  2982.                         Error = ParseExprList(&ListOfExpressions,Scanner,SymbolTable,TrashTracker,
  2983.                             LineNumberOut);
  2984.                         if (Error != eCompileNoError)
  2985.                             {
  2986.                                 return Error;
  2987.                             }
  2988.  
  2989.                         /* dispose of the current scope */
  2990.                         DecrementSymbolTableLevel(SymbolTable);
  2991.  
  2992.                         /* build the thing */
  2993.                         *ExpressionOut = NewExprSequence(ListOfExpressions,TrashTracker,
  2994.                             GetCurrentLineNumber(Scanner));
  2995.                         if (*ExpressionOut == NIL)
  2996.                             {
  2997.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  2998.                                 return eCompileOutOfMemory;
  2999.                             }
  3000.  
  3001.                         /* clean up by getting rid of the close paren */
  3002.                         Token = GetNextToken(Scanner);
  3003.                         if (Token == NIL)
  3004.                             {
  3005.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3006.                                 return eCompileOutOfMemory;
  3007.                             }
  3008.                         if (GetTokenType(Token) != eTokenCloseParen)
  3009.                             {
  3010.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3011.                                 return eCompileExpectedCloseParen;
  3012.                             }
  3013.                     }
  3014.                     return eCompileNoError;
  3015.  
  3016.                 case eTokenKeyword:
  3017.                     switch (GetTokenKeywordTag(Token))
  3018.                         {
  3019.                             default:
  3020.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3021.                                 return eCompileExpectedOperand;
  3022.  
  3023.                                 /*   98:                      ::= true */
  3024.                             case eKeywordTrue:
  3025.                                 TheOperand = NewBooleanLiteral(TrashTracker,True,
  3026.                                     GetCurrentLineNumber(Scanner));
  3027.                                 break;
  3028.  
  3029.                                 /*   99:                      ::= false */
  3030.                             case eKeywordFalse:
  3031.                                 TheOperand = NewBooleanLiteral(TrashTracker,False,
  3032.                                     GetCurrentLineNumber(Scanner));
  3033.                                 break;
  3034.  
  3035.                                 /* this was added later. */
  3036.                             case eKeywordPi:
  3037.                                 TheOperand = NewDoubleLiteral(TrashTracker,DGETPI(),
  3038.                                     GetCurrentLineNumber(Scanner));
  3039.                                 break;
  3040.                         }
  3041.                     break;
  3042.             }
  3043.  
  3044.         if (TheOperand == NIL)
  3045.             {
  3046.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3047.                 return eCompileOutOfMemory;
  3048.             }
  3049.  
  3050.         *ExpressionOut = NewExprOperand(TheOperand,TrashTracker,
  3051.             GetCurrentLineNumber(Scanner));
  3052.         if (*ExpressionOut == NIL)
  3053.             {
  3054.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3055.                 return eCompileOutOfMemory;
  3056.             }
  3057.  
  3058.         return eCompileNoError;
  3059.     }
  3060.  
  3061.  
  3062.  
  3063.  
  3064. /*   80:   <expr7prime>       ::= <arraysubscript> */
  3065. /*   81:                      ::= <funccall> */
  3066. /*   82:                      ::= <exponentiation> */
  3067. /*   83:                      ::=  */
  3068. /*  <expr7prime>       : {(, OPENBRACKET, ^, <arraysubscript>, <funccall>, */
  3069. /*       <exponentiation>} */
  3070. /*  <expr7prime>       : {and, or, xor, div, mod, SHR, SHL, then, else, */
  3071. /*       elseif, while, until, do, to, ), CLOSEBRACKET, ,, :=, ;, *, /, */
  3072. /*       +, -, EQ, NEQ, LT, LTEQ, GR, GREQ, <expr2prime>, <conj_oper>, */
  3073. /*       <expr3prime>, <rel_oper>, <expr4prime>, <add_oper>, <expr5prime>, */
  3074. /*       <mult_oper>, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  3075. static CompileErrors    ParseExpr7Prime(ASTExpressionRec** ExpressionOut,
  3076.                                                 ASTExpressionRec* TheExpr8Thing, ScannerRec* Scanner,
  3077.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  3078.                                                 long* LineNumberOut)
  3079.     {
  3080.         TokenRec*                        Token;
  3081.  
  3082.         CheckPtrExistence(TheExpr8Thing);
  3083.         CheckPtrExistence(Scanner);
  3084.         CheckPtrExistence(SymbolTable);
  3085.         CheckPtrExistence(TrashTracker);
  3086.  
  3087.         Token = GetNextToken(Scanner);
  3088.         if (Token == NIL)
  3089.             {
  3090.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3091.                 return eCompileOutOfMemory;
  3092.             }
  3093.  
  3094.         switch (GetTokenType(Token))
  3095.             {
  3096.                 default:
  3097.                     UngetToken(Scanner,Token);
  3098.                     *ExpressionOut = TheExpr8Thing;
  3099.                     return eCompileNoError;
  3100.  
  3101.                     /*   81:                      ::= <funccall> */
  3102.                 case eTokenOpenParen:
  3103.                     UngetToken(Scanner,Token);
  3104.                     return ParseFuncCall(ExpressionOut,TheExpr8Thing,Scanner,SymbolTable,
  3105.                         TrashTracker,LineNumberOut);
  3106.  
  3107.                     /*   80:   <expr7prime>       ::= <arraysubscript> */
  3108.                 case eTokenOpenBracket:
  3109.                     UngetToken(Scanner,Token);
  3110.                     return ParseArraySubscript(ExpressionOut,TheExpr8Thing,Scanner,SymbolTable,
  3111.                         TrashTracker,LineNumberOut);
  3112.  
  3113.                     /*   82:                      ::= <exponentiation> */
  3114.                 case eTokenCircumflex:
  3115.                     {
  3116.                         ASTExpressionRec*            RightHandSide;
  3117.                         ASTBinaryOpRec*                TheOperator;
  3118.                         CompileErrors                    Error;
  3119.  
  3120.                         UngetToken(Scanner,Token);
  3121.                         Error = ParseExponentiation(&RightHandSide,Scanner,SymbolTable,
  3122.                             TrashTracker,LineNumberOut);
  3123.                         if (Error != eCompileNoError)
  3124.                             {
  3125.                                 return Error;
  3126.                             }
  3127.                         TheOperator = NewBinaryOperator(eBinaryExponentiation,TheExpr8Thing,
  3128.                             RightHandSide,TrashTracker,GetCurrentLineNumber(Scanner));
  3129.                         if (TheOperator == NIL)
  3130.                             {
  3131.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3132.                                 return eCompileOutOfMemory;
  3133.                             }
  3134.                         *ExpressionOut = NewExprBinaryOperator(TheOperator,TrashTracker,
  3135.                             GetCurrentLineNumber(Scanner));
  3136.                         if (*ExpressionOut == NIL)
  3137.                             {
  3138.                                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3139.                                 return eCompileOutOfMemory;
  3140.                             }
  3141.                         return eCompileNoError;
  3142.                     }
  3143.             }
  3144.         EXECUTE(PRERR(ForceAbort,"ParseExpr7Prime:  control reached end of function"));
  3145.     }
  3146.  
  3147.  
  3148.  
  3149.  
  3150. /*   85:   <funccall>         ::= ( <actualstart> ) */
  3151. /* FIRST SET: */
  3152. /*  <funccall>         : {(} */
  3153. /* FOLLOW SET: */
  3154. /*  <funccall>         : {and, or, xor, div, mod, SHR, SHL, then, else, elseif, */
  3155. /*       while, until, do, to, ), CLOSEBRACKET, ,, :=, ;, *, /, +, -, EQ, */
  3156. /*       NEQ, LT, LTEQ, GR, GREQ, <expr2prime>, <conj_oper>, <expr3prime>, */
  3157. /*       <rel_oper>, <expr4prime>, <add_oper>, <expr5prime>, <mult_oper>, */
  3158. /*       <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  3159. static CompileErrors    ParseFuncCall(ASTExpressionRec** ExpressionOut,
  3160.                                                 ASTExpressionRec* FunctionGenerator, ScannerRec* Scanner,
  3161.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  3162.                                                 long* LineNumberOut)
  3163.     {
  3164.         TokenRec*                        Token;
  3165.         ASTExprListRec*            ListOfParameters;
  3166.         CompileErrors                Error;
  3167.         ASTFuncCallRec*            TheFunctionCall;
  3168.  
  3169.         CheckPtrExistence(Scanner);
  3170.         CheckPtrExistence(SymbolTable);
  3171.         CheckPtrExistence(TrashTracker);
  3172.  
  3173.         /* swallow open parenthesis */
  3174.         Token = GetNextToken(Scanner);
  3175.         if (Token == NIL)
  3176.             {
  3177.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3178.                 return eCompileOutOfMemory;
  3179.             }
  3180.         if (GetTokenType(Token) != eTokenOpenParen)
  3181.             {
  3182.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3183.                 return eCompileExpectedOpenParen;
  3184.             }
  3185.  
  3186.         /* parse the argument list */
  3187.         Error = ParseActualStart(&ListOfParameters,Scanner,SymbolTable,TrashTracker,
  3188.             LineNumberOut);
  3189.         if (Error != eCompileNoError)
  3190.             {
  3191.                 return Error;
  3192.             }
  3193.  
  3194.         /* swallow close parenthesis */
  3195.         Token = GetNextToken(Scanner);
  3196.         if (Token == NIL)
  3197.             {
  3198.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3199.                 return eCompileOutOfMemory;
  3200.             }
  3201.         if (GetTokenType(Token) != eTokenCloseParen)
  3202.             {
  3203.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3204.                 return eCompileExpectedCommaOrCloseParen;
  3205.             }
  3206.  
  3207.         TheFunctionCall = NewFunctionCall(ListOfParameters,FunctionGenerator,
  3208.             TrashTracker,GetCurrentLineNumber(Scanner));
  3209.         if (TheFunctionCall == NIL)
  3210.             {
  3211.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3212.                 return eCompileOutOfMemory;
  3213.             }
  3214.  
  3215.         *ExpressionOut = NewExprFunctionCall(TheFunctionCall,TrashTracker,
  3216.             GetCurrentLineNumber(Scanner));
  3217.         if (*ExpressionOut == NIL)
  3218.             {
  3219.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3220.                 return eCompileOutOfMemory;
  3221.             }
  3222.  
  3223.         return eCompileNoError;
  3224.     }
  3225.  
  3226.  
  3227.  
  3228.  
  3229. /*   84:   <arraysubscript>   ::= OPENBRACKET <exprlist> CLOSEBRACKET */
  3230. /* FIRST SET: */
  3231. /*  <arraysubscript>   : {OPENBRACKET} */
  3232. /* FOLLOW SET: */
  3233. /*  <arraysubscript>   : {and, or, xor, div, mod, SHR, SHL, then, else, */
  3234. /*       elseif, while, until, do, to, ), CLOSEBRACKET, ,, :=, ;, *, */
  3235. /*       /, +, -, EQ, NEQ, LT, LTEQ, GR, GREQ, <expr2prime>, <conj_oper>, */
  3236. /*       <expr3prime>, <rel_oper>, <expr4prime>, <add_oper>, <expr5prime>, */
  3237. /*       <mult_oper>, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  3238. static CompileErrors    ParseArraySubscript(ASTExpressionRec** ExpressionOut,
  3239.                                                 ASTExpressionRec* ArrayGenerator, ScannerRec* Scanner,
  3240.                                                 SymbolTableRec* SymbolTable, TrashTrackRec* TrashTracker,
  3241.                                                 long* LineNumberOut)
  3242.     {
  3243.         TokenRec*                        Token;
  3244.         ASTExpressionRec*        Subscript;
  3245.         CompileErrors                Error;
  3246.         ASTBinaryOpRec*            ArraySubsOperation;
  3247.         ASTExprListRec*            SubscriptRaw;
  3248.  
  3249.         CheckPtrExistence(ArrayGenerator);
  3250.         CheckPtrExistence(Scanner);
  3251.         CheckPtrExistence(SymbolTable);
  3252.         CheckPtrExistence(TrashTracker);
  3253.  
  3254.         Token = GetNextToken(Scanner);
  3255.         if (Token == NIL)
  3256.             {
  3257.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3258.                 return eCompileOutOfMemory;
  3259.             }
  3260.         if (GetTokenType(Token) != eTokenOpenBracket)
  3261.             {
  3262.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3263.                 return eCompileExpectedOpenBracket;
  3264.             }
  3265.  
  3266.         Error = ParseExprList(&SubscriptRaw,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3267.         if (Error != eCompileNoError)
  3268.             {
  3269.                 return Error;
  3270.             }
  3271.         Subscript = NewExprSequence(SubscriptRaw,TrashTracker,GetCurrentLineNumber(Scanner));
  3272.         if (Subscript == NIL)
  3273.             {
  3274.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3275.                 return eCompileOutOfMemory;
  3276.             }
  3277.  
  3278.         Token = GetNextToken(Scanner);
  3279.         if (Token == NIL)
  3280.             {
  3281.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3282.                 return eCompileOutOfMemory;
  3283.             }
  3284.         if (GetTokenType(Token) != eTokenCloseBracket)
  3285.             {
  3286.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3287.                 return eCompileExpectedCloseBracket;
  3288.             }
  3289.  
  3290.         ArraySubsOperation = NewBinaryOperator(eBinaryArraySubscripting,ArrayGenerator,
  3291.             Subscript,TrashTracker,GetCurrentLineNumber(Scanner));
  3292.         if (ArraySubsOperation == NIL)
  3293.             {
  3294.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3295.                 return eCompileOutOfMemory;
  3296.             }
  3297.         *ExpressionOut = NewExprBinaryOperator(ArraySubsOperation,TrashTracker,
  3298.             GetCurrentLineNumber(Scanner));
  3299.         if (*ExpressionOut == NIL)
  3300.             {
  3301.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3302.                 return eCompileOutOfMemory;
  3303.             }
  3304.  
  3305.         return eCompileNoError;
  3306.     }
  3307.  
  3308.  
  3309.  
  3310.  
  3311. /*  124:   <exprlist>         ::= <exprlistelem> <exprlisttail> */
  3312. /* FIRST SET: */
  3313. /*  <exprlist>         : {<identifier>, <integer>, <single>, <double>, <fixed>, */
  3314. /*       <string>, bool, int, single, double, fixed, proto, var, not, sin, */
  3315. /*       cos, tan, asin, acos, atan, ln, exp, sqr, sqrt, abs, neg, sign, */
  3316. /*       length, if, while, until, do, resize, error, true, false, */
  3317. /*       set, (, -, <prototype>, <expr>, <expr2>, <expr3>, <expr4>, <expr5>, */
  3318. /*       <expr6>, <unary_oper>, <expr7>, <expr8>, <whileloop>, <untilloop>} */
  3319. /* FOLLOW SET: */
  3320. /*  <exprlist>         : {), CLOSEBRACKET, EOF} */
  3321. CompileErrors                    ParseExprList(ASTExprListRec** ExpressionOut,
  3322.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  3323.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  3324.     {
  3325.         CompileErrors                Error;
  3326.         ASTExpressionRec*        FirstExpression;
  3327.         TokenRec*                        Token;
  3328.         ASTExprListRec*            RestOfList;
  3329.  
  3330.         CheckPtrExistence(Scanner);
  3331.         CheckPtrExistence(SymbolTable);
  3332.         CheckPtrExistence(TrashTracker);
  3333.  
  3334.         Token = GetNextToken(Scanner);
  3335.         if (Token == NIL)
  3336.             {
  3337.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3338.                 return eCompileOutOfMemory;
  3339.             }
  3340.  
  3341.         if ((GetTokenType(Token) == eTokenCloseParen)
  3342.             || (GetTokenType(Token) == eTokenCloseBracket)
  3343.             || (GetTokenType(Token) == eTokenEndOfInput))
  3344.             {
  3345.                 UngetToken(Scanner,Token);
  3346.                 *ExpressionOut = NIL; /* empty list */
  3347.                 return eCompileNoError;
  3348.             }
  3349.  
  3350.         /* see if we should parse a non-existent element (prototype) which */
  3351.         /* generates no code */
  3352.         if ((GetTokenType(Token) == eTokenKeyword)
  3353.             && (GetTokenKeywordTag(Token) == eKeywordProto))
  3354.             {
  3355.                 SymbolRec*                    ProtoSymbolOut;
  3356.                 CompileErrors                Error;
  3357.  
  3358.                 UngetToken(Scanner,Token);
  3359.                 Error = ParsePrototype(&ProtoSymbolOut,Scanner,SymbolTable,
  3360.                     TrashTracker,LineNumberOut);
  3361.                 if (Error != eCompileNoError)
  3362.                     {
  3363.                         return Error;
  3364.                     }
  3365.                 /* this is declarative and generates no code */
  3366.                 /* as a hack to get this to work, we'll expect a semicolon and */
  3367.                 /* another expression list */
  3368.                 Token = GetNextToken(Scanner);
  3369.                 if (Token == NIL)
  3370.                     {
  3371.                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  3372.                         return eCompileOutOfMemory;
  3373.                     }
  3374.                 /* eat up the semicolon */
  3375.                 if (GetTokenType(Token) != eTokenSemicolon)
  3376.                     {
  3377.                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  3378.                         return eCompilePrototypeCantBeLastThingInExprList;
  3379.                     }
  3380.                 /* now just parse the rest of the expression list */
  3381.                 return ParseExprList(ExpressionOut,Scanner,SymbolTable,TrashTracker,
  3382.                     LineNumberOut);
  3383.             }
  3384.  
  3385.         /* get first part of list */
  3386.         UngetToken(Scanner,Token);
  3387.         Error = ParseExprListElem(&FirstExpression,Scanner,SymbolTable,TrashTracker,
  3388.             LineNumberOut);
  3389.         if (Error != eCompileNoError)
  3390.             {
  3391.                 return Error;
  3392.             }
  3393.  
  3394.         /* get the rest of the list */
  3395.         Error = ParseExprListTail(&RestOfList,Scanner,SymbolTable,TrashTracker,
  3396.             LineNumberOut);
  3397.         if (Error != eCompileNoError)
  3398.             {
  3399.                 return Error;
  3400.             }
  3401.  
  3402.         *ExpressionOut = ASTExprListCons(FirstExpression,RestOfList,TrashTracker);
  3403.         if (*ExpressionOut == NIL)
  3404.             {
  3405.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3406.                 return eCompileOutOfMemory;
  3407.             }
  3408.  
  3409.         return eCompileNoError;
  3410.     }
  3411.  
  3412.  
  3413.  
  3414.  
  3415. /*   91:   <exponentiation>   ::= ^ <expr7> */
  3416. /* FIRST SET: */
  3417. /*  <exponentiation>   : {^} */
  3418. /* FOLLOW SET: */
  3419. /*  <exponentiation>   : {and, or, xor, div, mod, SHR, SHL, then, else, */
  3420. /*       elseif, while, until, do, to, ), CLOSEBRACKET, ,, :=, ;, *, */
  3421. /*       /, +, -, EQ, NEQ, LT, LTEQ, GR, GREQ, <expr2prime>, <conj_oper>, */
  3422. /*       <expr3prime>, <rel_oper>, <expr4prime>, <add_oper>, <expr5prime>, */
  3423. /*       <mult_oper>, <actualtail>, <iftail>, <loopwhileuntil>, <exprlisttail>} */
  3424. static CompileErrors    ParseExponentiation(ASTExpressionRec** ExpressionOut,
  3425.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  3426.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  3427.     {
  3428.         TokenRec*                        Token;
  3429.  
  3430.         CheckPtrExistence(Scanner);
  3431.         CheckPtrExistence(SymbolTable);
  3432.         CheckPtrExistence(TrashTracker);
  3433.  
  3434.         Token = GetNextToken(Scanner);
  3435.         if (Token == NIL)
  3436.             {
  3437.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3438.                 return eCompileOutOfMemory;
  3439.             }
  3440.         if (GetTokenType(Token) != eTokenCircumflex)
  3441.             {
  3442.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3443.                 return eCompileExpectedRightAssociativeOperator;
  3444.             }
  3445.  
  3446.         return ParseExpr7(ExpressionOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3447.     }
  3448.  
  3449.  
  3450.  
  3451.  
  3452. /*   86:   <actualstart>      ::= <actuallist> */
  3453. /*   87:                      ::=  */
  3454. /* FIRST SET: */
  3455. /*  <actualstart>      : {<identifier>, <integer>, <single>, <double>, */
  3456. /*       <fixed>, <string>, bool, int, single, double, fixed, proto, var, */
  3457. /*       not, sin, cos, tan, asin, acos, atan, ln, exp, sqr, sqrt, abs, */
  3458. /*       neg, sign, length, if, while, until, do, resize, error, */
  3459. /*       true, false, set, (, -, <prototype>, <expr>, <expr2>, */
  3460. /*       <expr3>, <expr4>, <expr5>, <expr6>, <unary_oper>, <expr7>, <expr8>, */
  3461. /*       <actuallist>, <whileloop>, <untilloop>} */
  3462. /* FOLLOW SET: */
  3463. /*  <actualstart>      : {)} */
  3464. static CompileErrors    ParseActualStart(ASTExprListRec** ParamListOut,
  3465.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  3466.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  3467.     {
  3468.         TokenRec*                        Token;
  3469.  
  3470.         CheckPtrExistence(Scanner);
  3471.         CheckPtrExistence(SymbolTable);
  3472.         CheckPtrExistence(TrashTracker);
  3473.  
  3474.         Token = GetNextToken(Scanner);
  3475.         if (Token == NIL)
  3476.             {
  3477.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3478.                 return eCompileOutOfMemory;
  3479.             }
  3480.  
  3481.         /* handle the nullification */
  3482.         if (GetTokenType(Token) == eTokenCloseParen)
  3483.             {
  3484.                 UngetToken(Scanner,Token);
  3485.                 *ParamListOut = NIL; /* empty list is NIL */
  3486.                 return eCompileNoError;
  3487.             }
  3488.  
  3489.         UngetToken(Scanner,Token);
  3490.         return ParseActualList(ParamListOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3491.     }
  3492.  
  3493.  
  3494.  
  3495.  
  3496. /*   88:   <actuallist>       ::= <expr> <actualtail> */
  3497. /* FIRST SET: */
  3498. /*  <actuallist>       : {<identifier>, <integer>, <single>, <double>, */
  3499. /*       <fixed>, <string>, bool, int, single, double, fixed, proto, var, */
  3500. /*       not, sin, cos, tan, asin, acos, atan, ln, exp, sqr, sqrt, abs, */
  3501. /*       neg, sign, length, if, while, until, do, resize, error, */
  3502. /*       true, false, set, (, -, <prototype>, <expr>, <expr2>, */
  3503. /*       <expr3>, <expr4>, <expr5>, <expr6>, <unary_oper>, <expr7>, <expr8>, */
  3504. /*       <whileloop>, <untilloop>} */
  3505. /* FOLLOW SET: */
  3506. /*  <actuallist>       : {)} */
  3507. static CompileErrors    ParseActualList(ASTExprListRec** ParamListOut,
  3508.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  3509.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  3510.     {
  3511.         ASTExpressionRec*        FirstExpression;
  3512.         CompileErrors                Error;
  3513.         ASTExprListRec*            RestOfList;
  3514.  
  3515.         CheckPtrExistence(Scanner);
  3516.         CheckPtrExistence(SymbolTable);
  3517.         CheckPtrExistence(TrashTracker);
  3518.  
  3519.         Error = ParseExpr(&FirstExpression,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3520.         if (Error != eCompileNoError)
  3521.             {
  3522.                 return Error;
  3523.             }
  3524.  
  3525.         Error = ParseActualTail(&RestOfList,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3526.         if (Error != eCompileNoError)
  3527.             {
  3528.                 return Error;
  3529.             }
  3530.  
  3531.         *ParamListOut = ASTExprListCons(FirstExpression,RestOfList,TrashTracker);
  3532.         if (*ParamListOut == NIL)
  3533.             {
  3534.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3535.                 return eCompileOutOfMemory;
  3536.             }
  3537.  
  3538.         return eCompileNoError;
  3539.     }
  3540.  
  3541.  
  3542.  
  3543.  
  3544. /*   89:   <actualtail>       ::= , <actuallist> */
  3545. /*   90:                      ::=  */
  3546. /* FIRST SET: */
  3547. /*  <actualtail>       : {,} */
  3548. /* FOLLOW SET: */
  3549. /*  <actualtail>       : {)} */
  3550. static CompileErrors    ParseActualTail(ASTExprListRec** ParamListOut,
  3551.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  3552.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  3553.     {
  3554.         TokenRec*                        Token;
  3555.  
  3556.         CheckPtrExistence(Scanner);
  3557.         CheckPtrExistence(SymbolTable);
  3558.         CheckPtrExistence(TrashTracker);
  3559.  
  3560.         Token = GetNextToken(Scanner);
  3561.         if (Token == NIL)
  3562.             {
  3563.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3564.                 return eCompileOutOfMemory;
  3565.             }
  3566.         if ((GetTokenType(Token) != eTokenComma)
  3567.             && (GetTokenType(Token) != eTokenCloseParen))
  3568.             {
  3569.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3570.                 return eCompileExpectedCommaOrCloseParen;
  3571.             }
  3572.  
  3573.         /* handle nullification */
  3574.         if (GetTokenType(Token) == eTokenCloseParen)
  3575.             {
  3576.                 UngetToken(Scanner,Token);
  3577.                 *ParamListOut = NIL; /* empty list */
  3578.                 return eCompileNoError;
  3579.             }
  3580.  
  3581.         return ParseActualList(ParamListOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3582.     }
  3583.  
  3584.  
  3585.  
  3586.  
  3587. /*  125:   <exprlisttail>     ::= ; <exprlist> */
  3588. /*  126:                      ::=  */
  3589. /* FIRST SET: */
  3590. /*  <exprlisttail>     : {;} */
  3591. /* FOLLOW SET: */
  3592. /*  <exprlisttail>     : {), CLOSEBRACKET, EOF} */
  3593. static CompileErrors    ParseExprListTail(ASTExprListRec** ListOut,
  3594.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  3595.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  3596.     {
  3597.         TokenRec*                        Token;
  3598.         CompileErrors                Error;
  3599.  
  3600.         CheckPtrExistence(Scanner);
  3601.         CheckPtrExistence(SymbolTable);
  3602.         CheckPtrExistence(TrashTracker);
  3603.  
  3604.         Token = GetNextToken(Scanner);
  3605.         if (Token == NIL)
  3606.             {
  3607.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3608.                 return eCompileOutOfMemory;
  3609.             }
  3610.  
  3611.         /* find out if we should continue or not */
  3612.         if ((GetTokenType(Token) == eTokenCloseParen)
  3613.             || (GetTokenType(Token) == eTokenCloseBracket)
  3614.             || (GetTokenType(Token) == eTokenEndOfInput))
  3615.             {
  3616.                 UngetToken(Scanner,Token);
  3617.                 *ListOut = NIL; /* empty list */
  3618.                 return eCompileNoError;
  3619.             }
  3620.  
  3621.         if (GetTokenType(Token) != eTokenSemicolon)
  3622.             {
  3623.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3624.                 return eCompileExpectedSemicolon;
  3625.             }
  3626.  
  3627.         return ParseExprList(ListOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3628.     }
  3629.  
  3630.  
  3631.  
  3632.  
  3633. /*  124:   <exprlistelem>     ::= <expr> */
  3634. /*  125:                      ::= var <identifier> : <type> <vartail> */
  3635. /*   22:   <exprlistelem>     ::= <prototype> */
  3636. /* FIRST SET: */
  3637. /*  <exprlistelem>     : {<identifier>, <integer>, <single>, <double>, */
  3638. /*       <fixed>, <string>, bool, int, single, double, fixed, proto, */
  3639. /*       var, not, sin, cos, tan, asin, acos, atan, ln, exp, sqr, sqrt, */
  3640. /*       abs, neg, sign, length, if, while, until, do, resize, error, */
  3641. /*       true, false, set, (, -, <prototype>, <expr>, */
  3642. /*       <expr2>, <expr3>, <expr4>, <expr5>, <expr6>, <unary_oper>, <expr7>, */
  3643. /*       <expr8>, <whileloop>, <untilloop>} */
  3644. /* FOLLOW SET: */
  3645. /*  <exprlistelem>     : {), CLOSEBRACKET, ;, <exprlisttail>} */
  3646. static CompileErrors    ParseExprListElem(ASTExpressionRec** ExpressionOut,
  3647.                                                 ScannerRec* Scanner, SymbolTableRec* SymbolTable,
  3648.                                                 TrashTrackRec* TrashTracker, long* LineNumberOut)
  3649.     {
  3650.         TokenRec*                        Token;
  3651.  
  3652.         CheckPtrExistence(Scanner);
  3653.         CheckPtrExistence(SymbolTable);
  3654.         CheckPtrExistence(TrashTracker);
  3655.  
  3656.         /* lookahead to see what to do */
  3657.         Token = GetNextToken(Scanner);
  3658.         if (Token == NIL)
  3659.             {
  3660.                 *LineNumberOut = GetCurrentLineNumber(Scanner);
  3661.                 return eCompileOutOfMemory;
  3662.             }
  3663.  
  3664.         if ((GetTokenType(Token) == eTokenKeyword)
  3665.             && (GetTokenKeywordTag(Token) == eKeywordVar))
  3666.             {
  3667.                 TokenRec*                        VariableName;
  3668.                 DataTypes                        ReturnType;
  3669.                 CompileErrors                Error;
  3670.                 long                                LineNumberForFirstToken;
  3671.  
  3672.                 /* get the identifier */
  3673.                 VariableName = GetNextToken(Scanner);
  3674.                 if (VariableName == NIL)
  3675.                     {
  3676.                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  3677.                         return eCompileOutOfMemory;
  3678.                     }
  3679.                 if (GetTokenType(VariableName) != eTokenIdentifier)
  3680.                     {
  3681.                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  3682.                         return eCompileExpectedIdentifier;
  3683.                     }
  3684.                 LineNumberForFirstToken = GetCurrentLineNumber(Scanner);
  3685.  
  3686.                 /* get the colon */
  3687.                 Token = GetNextToken(Scanner);
  3688.                 if (Token == NIL)
  3689.                     {
  3690.                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  3691.                         return eCompileOutOfMemory;
  3692.                     }
  3693.                 if (GetTokenType(Token) != eTokenColon)
  3694.                     {
  3695.                         *LineNumberOut = GetCurrentLineNumber(Scanner);
  3696.                         return eCompileExpectedColon;
  3697.                     }
  3698.  
  3699.                 /* get the variable's type */
  3700.                 Error = ParseType(&ReturnType,Scanner,LineNumberOut);
  3701.                 if (Error != eCompileNoError)
  3702.                     {
  3703.                         return Error;
  3704.                     }
  3705.  
  3706.                 /* finish up the declaration of the variable */
  3707.                 return ParseVarTail(ExpressionOut,VariableName,LineNumberForFirstToken,
  3708.                     ReturnType,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3709.             }
  3710.         else
  3711.             {
  3712.                 /* do the other thing */
  3713.                 UngetToken(Scanner,Token);
  3714.                 return ParseExpr(ExpressionOut,Scanner,SymbolTable,TrashTracker,LineNumberOut);
  3715.             }
  3716.     }
  3717.