home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / Arashi 1.1 / Game Source / GameCompiler (jam) / Parser.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-14  |  20.5 KB  |  1,003 lines  |  [TEXT/KAHL]

  1. /*/
  2.      Project Arashi: Parser.c
  3.      Major release: Version 1.1, 7/22/92
  4.  
  5.      Last modification: Sunday, March 14, 1993, 21:21
  6.      Created: Thursday, February 11, 1993, 7:18
  7.  
  8.      Copyright © 1993, Juri Munkki
  9. /*/
  10.  
  11. #include "Numbers.h"
  12. #include "Parser.h"
  13. #include "RAMFiles.h"
  14. #include "CStringDictionary.h"
  15. #include "CTagBase.h"
  16. #include <math.h>
  17. #include "InternalVars.h"
  18.  
  19.  
  20. #ifdef    DEBUGPARSER
  21. #include "stdio.h"
  22. #define    DEBUGPAR(a)    {    a    }
  23. #else
  24. #define    DEBUGPAR(a)    {        }
  25. #endif
  26.  
  27. ParserVariables    parserVar;
  28. long            lastKeyword;
  29. long            lastVariable;
  30.  
  31. typedef    struct
  32. {
  33.     double    value;
  34.     short    calcLevel;
  35. } variableValue;
  36.  
  37. Handle                theScript;
  38. double                *stackP;
  39. CStringDictionary    *symTable;
  40. CTagBase            *variableBase;
  41. CTagBase            *programBase;
  42. short                currentLevel = 0;
  43. short                fromLevel = 32000;
  44. short                upToLevel = -1;
  45.  
  46. void    InitSymbols()
  47. {
  48.     symTable = new CStringDictionary;
  49.     symTable->IStringDictionary();
  50.     
  51.     symTable->AddDictEntry("\pmin",-1);
  52.     symTable->AddDictEntry("\pmax",-1);
  53.     symTable->AddDictEntry("\prandom",-1);
  54.     symTable->AddDictEntry("\psin",-1);
  55.     symTable->AddDictEntry("\pcos",-1);
  56.     symTable->AddDictEntry("\pint",-1);
  57.     symTable->AddDictEntry("\pround",-1);
  58.     lastKeyword = symTable->AddDictEntry("\plevel",-1);
  59.     lastVariable = lastKeyword;
  60.     
  61.     variableBase = new CTagBase;
  62.     variableBase->ITagBase();
  63.     
  64.     programBase = new CTagBase;
  65.     programBase->ITagBase();
  66. }
  67.  
  68. void    ResetVariables()
  69. {
  70.     variableBase->Dispose();
  71.     programBase->Dispose();
  72.     InitSymbols();
  73. }
  74. void    CreateVariable(
  75.     long    token)
  76. {
  77.     variableValue    zeroValue;
  78.     
  79.     zeroValue.value = 0;
  80.     zeroValue.calcLevel = -1;
  81.     variableBase->WriteEntry(token, sizeof(variableValue), &zeroValue);
  82. }
  83.  
  84. void    VariableToKeyword(
  85.     LexSymbol    *theSymbol)
  86. {
  87.     switch(theSymbol->value.token)
  88.     {
  89.         case kMinKey:
  90.             theSymbol->kind = kLexMin;
  91.             break;
  92.         case kMaxKey:
  93.             theSymbol->kind = kLexMax;
  94.             break;
  95.         case kRandomKey:
  96.             theSymbol->kind = kLexFun0;
  97.             break;
  98.         case kSinKey:
  99.         case kCosKey:
  100.         case kIntKey:
  101.         case kRoundKey:
  102.             theSymbol->kind = kLexFun1;
  103.             break;
  104.         case kLevelKey:
  105.             theSymbol->kind = kLexLevel;
  106.             break;
  107.     }
  108. }
  109.  
  110. short    MatchVariable(
  111.     StringPtr    theString)
  112. {
  113.     unsigned    char theChar;
  114.     short    matchCount = 0;
  115.     short    state = TRUE;
  116.     
  117.     theChar = theString[0];
  118.     
  119.     if(    (theChar >= 'a' && theChar <= 'z') ||
  120.         (theChar >= 'A' && theChar <= 'Z'))
  121.     {    
  122.         matchCount++;
  123.         
  124.         do
  125.         {
  126.             theChar = theString[matchCount];
  127.             
  128.             if(    (theChar >= 'a' && theChar <= '}') || theChar == '_' ||
  129.                 (theChar >= 'A' && theChar <= ']') || theChar == '.' ||
  130.                 (theChar >= '0' && theChar <= '9'))
  131.             {
  132.                 matchCount++;
  133.             }
  134.             else
  135.             {
  136.                 state = FALSE;
  137.             }
  138.         } while(state);
  139.     }
  140.     
  141.     return matchCount;
  142. }
  143. /*
  144. **    Match the exponent part of a floating point number.
  145. **    The input is a null-terminated string. The output
  146. **    tells how many characters could belong to the exponent
  147. **    of a floating point number.
  148. */
  149. short    MatchExponent(
  150.     StringPtr    theString)
  151. {
  152.     enum    {    initialState,
  153.                 integerState,
  154.                 endState    };
  155.  
  156.     short    matchCount = 0;
  157.     char    theChar;
  158.     short    state = initialState;
  159.  
  160.     while(state != endState)
  161.     {    theChar = theString[matchCount];
  162.         
  163.         if(theChar == 0)
  164.             state = endState;    //    String ends with null
  165.  
  166.         switch(state)
  167.         {    case initialState:
  168.                 if(    theChar == '+'    ||    theChar == '-'    ||
  169.                     (theChar >= '0' && theChar <= '9'))
  170.                 {        matchCount++;
  171.                         state = integerState;
  172.                 }
  173.                 else    state = endState;
  174.                 break;
  175.             case integerState:
  176.                 if(theChar >= '0' && theChar <= '9')
  177.                 {    matchCount++;
  178.                 }
  179.                 else    state = endState;
  180.                 break;                
  181.         }
  182.     }
  183.  
  184.     return matchCount;
  185. }
  186.  
  187. /*
  188. **    Match the number part of a row index.
  189. **    The input is a null-terminated string. The output
  190. **    tells how many characters could belong to the row
  191. **    index of a row specifier. Row specifiers are of the
  192. **    format @n, where n is an integer. (@1, @2, @3, ...)
  193. */
  194. short    MatchRowIndex(
  195.     StringPtr    theString)
  196. {
  197.     short    matchCount = 0;
  198.     char    theChar;
  199.  
  200.     theChar = *theString++;
  201.  
  202.     while(theChar >= '0' && theChar <= '9')
  203.     {    matchCount++;
  204.         theChar = *theString++;
  205.     }
  206.  
  207.     return matchCount;
  208. }
  209.  
  210. /*
  211. **    Match a floating point number.
  212. **    The input is a null-terminated string. The output
  213. **    tells how many characters could belong to a floating
  214. **    point number.
  215. */
  216. short    MatchFloat(
  217.     StringPtr    theString)
  218. {
  219.     enum    {    initialState,
  220.                 integerPartState,
  221.                 decimalPartState,
  222.                 exponentMatchState,
  223.                 endState    };
  224.  
  225.     short    matchCount = 0;
  226.     char    theChar;
  227.     short    state = initialState;
  228.  
  229.     while(state != endState)
  230.     {    theChar = theString[matchCount];
  231.         
  232.         if(theChar == 0)
  233.             state = endState;    //    String ends with null
  234.  
  235.         switch(state)
  236.         {    case initialState:
  237.                 if(    theChar == '+'    ||    theChar == '-'    ||
  238.                     (theChar >= '0' && theChar <= '9'))
  239.                 {        matchCount++;
  240.                         state = integerPartState; 
  241.                 }
  242. #ifdef ALLOWSHORTHAND        //    Are numbers like . and .0 and .e1 and .0e1 valid?
  243.                 else if(theChar == '.')
  244.                 {    matchCount++;
  245.                     state = decimalPartState;
  246.                 }
  247. #endif
  248.                 else    state = endState;
  249.                 break;
  250.  
  251.             case integerPartState:
  252.                 if(theChar >= '0' && theChar <= '9')
  253.                 {    matchCount++;
  254.                 }
  255.                 else if(theChar == 'e' || theChar == 'E')
  256.                 {    state = exponentMatchState;
  257.                 }
  258.                 else if(theChar == '.')
  259.                 {    matchCount++;
  260.                     state = decimalPartState;
  261.                 }
  262.                 else    state = endState;
  263.                 break;
  264.  
  265.             case decimalPartState:
  266.                 if(theChar >= '0' && theChar <= '9')
  267.                 {    matchCount++;
  268.                 }
  269.                 else if(theChar == 'e' || theChar == 'E')
  270.                 {    state = exponentMatchState;
  271.                 }
  272.                 else    state = endState;
  273.                 break;                
  274.  
  275.             case exponentMatchState:
  276.                 {
  277.                     short    expLength = MatchExponent(theString+matchCount+1);
  278.                 
  279.                     if(expLength > 0)
  280.                     {    matchCount += expLength+1;
  281.                     }
  282.                     state = endState;
  283.                 }
  284.                 break;
  285.         }
  286.     }
  287.     
  288.     return matchCount;
  289. }
  290.  
  291.  
  292. void    EmitInstruction(
  293.     LexSymbol    *theOperation,
  294.     short        stackChange)
  295. {
  296.     long    writeOffset = parserVar.logicalSize;
  297.  
  298.     parserVar.stackDepth += stackChange;
  299.     if(parserVar.stackDepth > parserVar.stackMax)
  300.         parserVar.stackMax = parserVar.stackDepth;
  301.  
  302.     if(    IncreaseByClump(    parserVar.output,
  303.                             &parserVar.realSize,
  304.                             &parserVar.logicalSize,
  305.                             sizeof(LexSymbol),
  306.                             sizeof(LexSymbol)*10) == noErr)
  307.     {    *(LexSymbol *)(*parserVar.output+writeOffset) = *theOperation;
  308.     }
  309. }
  310.  
  311. void    SkipComment()
  312. {
  313.     parserVar.input+= 2;
  314.     if(parserVar.input[0] != 0)
  315.     {    while(    (parserVar.input[0] != 0) &&
  316.                 !(parserVar.input[0] == '*' && parserVar.input[1] == '/'))
  317.         {    parserVar.input++;
  318.         }
  319.         
  320.         if(parserVar.input[0] != 0)
  321.         {    parserVar.input += 2;
  322.         }
  323.     }
  324. }
  325. void    SkipOneLineComment()
  326. {
  327.     parserVar.input+= 2;
  328.     if(parserVar.input[0] != 0)
  329.     {    while(    (parserVar.input[0] != 0) &&
  330.                 !(parserVar.input[0] == 13))
  331.         {    parserVar.input++;
  332.         }
  333.         
  334.         if(parserVar.input[0] != 0)
  335.         {    parserVar.input += 1;
  336.         }
  337.     }
  338. }
  339.  
  340. void    LexRead(
  341.     LexSymbol    *theSymbol)
  342. {
  343.     unsigned char    theChar;
  344.     short            matchCount;
  345.  
  346.     //    First, skip any whitespace like returns, tabs, spaces and control characters.
  347.     
  348.     theChar = *parserVar.input;
  349.     
  350.     while(theChar <= 32 && theChar > 0)
  351.     {    theChar = *(++parserVar.input);
  352.     }
  353.     
  354.     switch(theChar)
  355.     {
  356.         case '+':
  357.             theSymbol->kind = kLexPlus;
  358.             parserVar.input++;
  359.             break;
  360.         case '-':
  361.             theSymbol->kind = kLexMinus;
  362.             parserVar.input++;
  363.             break;
  364.         case '|':
  365.             theSymbol->kind = kLexAbs;
  366.             parserVar.input++;
  367.             break;
  368.         case '*':
  369.             theSymbol->kind = kLexMultiply;
  370.             parserVar.input++;
  371.             break;
  372.         case '/':
  373.             if(parserVar.input[1] == '*')
  374.             {    SkipComment();
  375.                 LexRead(theSymbol);
  376.             }
  377.             else if(parserVar.input[1] == '/')
  378.             {    SkipOneLineComment();
  379.                 LexRead(theSymbol);
  380.             }
  381.             else
  382.             {    theSymbol->kind = kLexDivide;
  383.                 parserVar.input++;
  384.             }
  385.             break;
  386.         case '%':
  387.             theSymbol->kind = kLexModulo;
  388.             parserVar.input++;
  389.             break;
  390.         case '^':
  391.             theSymbol->kind = kLexPower;
  392.             parserVar.input++;
  393.             break;
  394.         case '>':
  395.             theSymbol->kind = kLexGt;
  396.             parserVar.input++;
  397.             break;
  398.         case '<':
  399.             theSymbol->kind = kLexLt;
  400.             parserVar.input++;
  401.             break;
  402.         case '=':
  403.             theSymbol->kind = kLexEq;
  404.             parserVar.input++;
  405.             break;
  406. #ifdef TESTMINMAX
  407.         case ']':
  408.             theSymbol->kind = kLexMin;
  409.             parserVar.input++;
  410.             break;
  411.         case '[':
  412.             theSymbol->kind = kLexMax;
  413.             parserVar.input++;
  414.             break;
  415. #endif
  416.         case '(':
  417.             theSymbol->kind = kLexOpenParen;
  418.             parserVar.input++;
  419.             break;
  420.         case ')':
  421.             theSymbol->kind = kLexCloseParen;
  422.             parserVar.input++;
  423.             break;
  424.         case 0:
  425.             theSymbol->kind = kLexEof;
  426.             break;
  427.         default:
  428.             matchCount = MatchVariable(parserVar.input);
  429.             if(matchCount > 0)
  430.             {    theSymbol->value.token = symTable->FindEntry(parserVar.input - 1, matchCount);
  431.                 if(theSymbol->value.token > lastVariable)
  432.                 {    lastVariable = theSymbol->value.token;
  433.                     CreateVariable(lastVariable);
  434.                 }
  435.                 theSymbol->kind = kLexVariable;
  436.                 if(theSymbol->value.token <= lastKeyword)
  437.                 {    VariableToKeyword(theSymbol);
  438.                 }
  439.                 parserVar.input += matchCount;
  440.             }
  441.             else
  442.             {    matchCount = MatchFloat(parserVar.input);
  443.                 if(matchCount > 0)
  444.                 {    char    temp;
  445.                 
  446.                     temp = parserVar.input[-1];
  447.                     parserVar.input[-1] = matchCount;
  448.                     theSymbol->kind = kLexConstant;
  449.                     theSymbol->value.floating = StringToLongDouble(parserVar.input-1);
  450.                     parserVar.input[-1] = temp;
  451.                     parserVar.input += matchCount;
  452.                 }
  453.             }
  454.             
  455.             if(matchCount == 0)
  456.             {    theSymbol->kind = kParseError;
  457.             }
  458.             break;
  459.     }
  460. }
  461.  
  462. void    LexMatch(
  463.     short kind)
  464. {
  465.     if(parserVar.lookahead.kind == kind)
  466.         LexRead(&parserVar.lookahead);
  467.     else
  468.         parserVar.lookahead.kind = kParseError;
  469. }
  470.  
  471.  
  472. void    ParseFactor()
  473. {
  474.     LexSymbol    savedSymbol;
  475.     
  476.     switch(parserVar.lookahead.kind)
  477.     {    
  478.         case kLexFun0:
  479.             EmitInstruction(&parserVar.lookahead,1);
  480.             DEBUGPAR(printf("function0 ");)
  481.             LexMatch(parserVar.lookahead.kind);
  482.             break;
  483.             
  484.         case kLexFun1:
  485.             savedSymbol = parserVar.lookahead;
  486.             LexMatch(parserVar.lookahead.kind);
  487.             ParseFactor();
  488.             EmitInstruction(&savedSymbol, 0);
  489.             DEBUGPAR(printf("function1 ");)
  490.             break;
  491.  
  492.         case kLexConstant:
  493.             EmitInstruction(&parserVar.lookahead,1);
  494.             DEBUGPAR(printf("%3.2f ", parserVar.lookahead.value.floating);)
  495.             LexMatch(parserVar.lookahead.kind);
  496.             break;
  497.             
  498.         case kLexVariable:
  499.             EmitInstruction(&parserVar.lookahead,1);
  500.             DEBUGPAR(printf("Variable #%ld ", parserVar.lookahead.value.token);)
  501.             LexMatch(parserVar.lookahead.kind);
  502.             break;
  503.             
  504.         case kLexRowOffset:
  505.             EmitInstruction(&parserVar.lookahead,1);
  506.             DEBUGPAR(printf("@(%ld) ", parserVar.lookahead.value.offset);)
  507.             LexMatch(parserVar.lookahead.kind);
  508.             break;
  509.         
  510.         case kLexMinus:
  511.             LexMatch(parserVar.lookahead.kind);
  512.             ParseFactor();
  513.             
  514.             savedSymbol.kind = kUnaryMinus;
  515.             EmitInstruction(&savedSymbol,0);
  516.             DEBUGPAR(printf("neg ");)
  517.             break;
  518.  
  519.         case kLexAbs:
  520.             LexMatch(parserVar.lookahead.kind);
  521.             ParseFactor();
  522.  
  523.             savedSymbol.kind = kLexAbs;
  524.             EmitInstruction(&savedSymbol,0);
  525.             DEBUGPAR(printf("abs ");)
  526.             break;
  527.  
  528.         case kLexPlus:    //    This is a no-op.
  529.             LexMatch(parserVar.lookahead.kind);
  530.             ParseFactor();
  531.             break;
  532.         
  533.         case kLexOpenParen:
  534.             LexMatch(parserVar.lookahead.kind);
  535.             ParseCompare();
  536.             if(parserVar.lookahead.kind == kLexCloseParen)
  537.             {    LexMatch(parserVar.lookahead.kind);
  538.             }
  539.             else
  540.             {    parserVar.lookahead.kind = kParseError;
  541.             }
  542.             break;
  543.  
  544.         default:
  545.             parserVar.lookahead.kind = kParseError;
  546.             break;
  547.     }
  548. }
  549. void    ParsePower()
  550. {
  551.     LexSymbol    mySymbol;
  552.     
  553.     ParseFactor();
  554.     
  555.     while(1)
  556.     {    if(    parserVar.lookahead.kind == kLexPower)
  557.         {    mySymbol.kind = parserVar.lookahead.kind;
  558.  
  559.             LexMatch(parserVar.lookahead.kind);
  560.             ParseFactor();
  561.         
  562.             EmitInstruction(&mySymbol,-1);
  563.  
  564.             DEBUGPAR(printf("^ ");)
  565.         }
  566.         else
  567.         {    if(parserVar.lookahead.kind != kLexEof)
  568.                 parserVar.lookahead.kind == kParseError;
  569.                 
  570.             break;
  571.         }
  572.     }
  573. }
  574. void    ParseTerm()
  575. {
  576.     LexSymbol    mySymbol;
  577.     
  578.     ParsePower();
  579.     
  580.     while(1)
  581.     {    if(    parserVar.lookahead.kind == kLexMultiply ||
  582.             parserVar.lookahead.kind == kLexDivide ||
  583.             parserVar.lookahead.kind == kLexModulo)
  584.         {    mySymbol.kind = parserVar.lookahead.kind;
  585.  
  586.             LexMatch(parserVar.lookahead.kind);
  587.             ParsePower();
  588.         
  589.             EmitInstruction(&mySymbol,-1);
  590.  
  591. #ifdef DEBUGPARSER
  592.             if(mySymbol.kind == kLexMultiply)    printf("* ");
  593.             else
  594.             if(mySymbol.kind == kLexModulo)     printf("% ");
  595.             else                                printf("/ ");
  596. #endif
  597.         }
  598.         else
  599.         {    if(parserVar.lookahead.kind != kLexEof)
  600.                 parserVar.lookahead.kind == kParseError;
  601.                 
  602.             break;
  603.         }
  604.     }
  605. }
  606.  
  607. void    ParseExpr()
  608. {
  609.     LexSymbol    mySymbol;
  610.     
  611.     ParseTerm();
  612.     
  613.     while(1)
  614.     {    if(    parserVar.lookahead.kind == kLexPlus ||
  615.             parserVar.lookahead.kind == kLexMinus)
  616.         {    mySymbol.kind = parserVar.lookahead.kind;
  617.  
  618.             LexMatch(parserVar.lookahead.kind);
  619.             ParseTerm();
  620.             EmitInstruction(&mySymbol,-1);
  621.  
  622. #ifdef DEBUGPARSER
  623.             if(mySymbol.kind == kLexPlus)    printf("+ ");
  624.             else                            printf("- ");
  625. #endif
  626.         }
  627.         else
  628.         {    if(parserVar.lookahead.kind != kLexEof)
  629.                 parserVar.lookahead.kind == kParseError;
  630.             
  631.             break;
  632.         }
  633.     }
  634. }
  635. void    ParseMinMax()
  636. {
  637.     LexSymbol    mySymbol;
  638.     
  639.     ParseExpr();
  640.     
  641.     while(1)
  642.     {    if(    parserVar.lookahead.kind == kLexMin ||
  643.             parserVar.lookahead.kind == kLexMax)
  644.         {    mySymbol.kind = parserVar.lookahead.kind;
  645.  
  646.             LexMatch(parserVar.lookahead.kind);
  647.             ParseExpr();
  648.             EmitInstruction(&mySymbol,-1);
  649.  
  650. #ifdef DEBUGPARSER
  651.             if(mySymbol.kind == kLexMin)    printf("min ");
  652.             else                            printf("max ");
  653. #endif
  654.         }
  655.         else
  656.         {    if(parserVar.lookahead.kind != kLexEof)
  657.                 parserVar.lookahead.kind == kParseError;
  658.             
  659.             break;
  660.         }
  661.     }
  662. }
  663.  
  664.  
  665. void    ParseCompare()
  666. {
  667.     LexSymbol    mySymbol;
  668.     
  669.     ParseMinMax();
  670.     
  671.     while(1)
  672.     {    if(    parserVar.lookahead.kind == kLexGt ||
  673.             parserVar.lookahead.kind == kLexEq ||
  674.             parserVar.lookahead.kind == kLexLt)
  675.         {    mySymbol.kind = parserVar.lookahead.kind;
  676.  
  677.             LexMatch(parserVar.lookahead.kind);
  678.             ParseMinMax();
  679.             EmitInstruction(&mySymbol,-1);
  680.  
  681. #ifdef DEBUGOUTPUT
  682.             if(mySymbol.kind == kLexGt    )        printf("> ");
  683.             else if(mySymbol.kind == kLexLt)    printf("< ");
  684.             else                                printf("= ");
  685. #endif
  686.         }
  687.         else
  688.         {    if(parserVar.lookahead.kind != kLexEof)
  689.                 parserVar.lookahead.kind == kParseError;
  690.             
  691.             break;
  692.         }
  693.     }
  694. }
  695.  
  696. void    ParseStatement(
  697.     LexSymbol    *statement)
  698. {
  699.     if(parserVar.lookahead.kind == kLexVariable)
  700.     {    *statement = parserVar.lookahead;
  701.         
  702.         LexMatch(parserVar.lookahead.kind);
  703.         if(parserVar.lookahead.kind == kLexEq)
  704.         {
  705.             LexMatch(parserVar.lookahead.kind);
  706.  
  707.             if(statement->value.token > lastVariable)
  708.             {    lastVariable = statement->value.token;
  709.                 CreateVariable(lastVariable);
  710.             }
  711.             
  712.             ParseCompare();
  713.             statement->kind = kAssignment;
  714.             EmitInstruction(statement, -1);
  715.             DEBUGPAR(printf("Store to var #%ld ", statement->value.token);)
  716.         }
  717.         else
  718.         {    parserVar.lookahead.kind = kParseError;
  719.         }
  720.     }
  721.     else
  722.     if(parserVar.lookahead.kind == kLexLevel)
  723.     {    *statement = parserVar.lookahead;
  724.         
  725.         LexMatch(parserVar.lookahead.kind);
  726.         if(parserVar.lookahead.kind == kLexConstant)
  727.         {    statement->value.level = parserVar.lookahead.value.floating;
  728.             DEBUGPAR(printf("Start of level info for level #%3.0lf ", parserVar.lookahead.value.floating);)
  729.             LexMatch(parserVar.lookahead.kind);
  730.         }
  731.         else
  732.         {    parserVar.lookahead.kind = kParseError;
  733.         }
  734.     }
  735.     else    parserVar.lookahead.kind = kParseError;
  736. }
  737.  
  738. void    SetupCompiler(
  739.     StringPtr theInput)
  740. {
  741.     parserVar.input = theInput;
  742.     parserVar.output = NewHandle(0);
  743.     parserVar.realSize = 0;
  744.     parserVar.logicalSize = 0;
  745.     parserVar.stackDepth = 0;
  746.     parserVar.stackMax = 0;
  747.  
  748. }
  749.  
  750. void    WriteVariable(
  751.     long    token,
  752.     double    value)
  753. {
  754.     variableValue    *theVar;
  755.     double            temp;
  756.     
  757.     theVar = variableBase->GetEntryPointer(token);
  758.     if(theVar)
  759.     {    theVar->calcLevel = currentLevel;
  760.         theVar->value = value;
  761.     }
  762.  
  763. }
  764. double    EvalVariable(
  765.     long    token)
  766. {
  767.     variableValue    *theVar;
  768.     double            temp;
  769.     
  770.     theVar = variableBase->GetEntryPointer(token);
  771.     if(theVar->calcLevel != currentLevel)
  772.     {    LexSymbol    *theProgram;
  773.     
  774.         theVar->calcLevel = currentLevel;
  775.         theProgram = programBase->GetEntryPointer(token);
  776.         if(theProgram)
  777.         {    while(theProgram->kind != kAssignment)
  778.             {    switch(theProgram->kind)
  779.                 {    case kLexConstant:
  780.                         *(++stackP) = theProgram->value.floating;
  781.                         break;
  782.                     case kLexVariable:
  783.                         temp = EvalVariable(theProgram->value.token);
  784.                         *(++stackP) = temp;
  785.                         break;
  786.                     case kLexPlus:        stackP[-1] += stackP[0];    stackP--;    break;
  787.                     case kLexMinus:        stackP[-1] -= stackP[0];    stackP--;    break;
  788.                     case kLexMultiply:    stackP[-1] *= stackP[0];    stackP--;    break;
  789.                     case kLexDivide:    stackP[-1] /= stackP[0];    stackP--;    break;
  790.  
  791.                     case kLexGt:        stackP[-1] = stackP[-1] > stackP[0];    stackP--;    break;
  792.                     case kLexLt:        stackP[-1] = stackP[-1] < stackP[0];    stackP--;    break;
  793.                     case kLexEq:        stackP[-1] = stackP[-1] == stackP[0];    stackP--;    break;
  794.                     
  795.                     case kLexPower:        stackP[-1] = pow(stackP[-1], stackP[0]);stackP--;    break;
  796.                     
  797.                     case kLexMin:
  798.                             if(stackP[-1] < stackP[0])    stackP[-1] = stackP[0];
  799.                             stackP--;
  800.                             break;
  801.                     case kLexMax:
  802.                             if(stackP[-1] > stackP[0])    stackP[-1] = stackP[0];
  803.                             stackP--;
  804.                             break;
  805.  
  806.                     case kLexModulo:
  807.                         stackP[-1] = fmod(stackP[-1], stackP[0]);
  808.                         stackP--;
  809.                         break;
  810.                     case kUnaryMinus:    stackP[0] = -stackP[0];        break;
  811.                     case kLexAbs:
  812.                         if(stackP[0] < 0)
  813.                             stackP[0] = -stackP[0];
  814.                         break;
  815.                     case kLexFun0:
  816.                         *(++stackP) = ((unsigned int)Random()) /65536.0;
  817.                         break;
  818.                     case kLexFun1:
  819.                         switch(theProgram->value.token)
  820.                         {    
  821.                             case kSinKey:    *stackP = sin(*stackP);                break;
  822.                             case kCosKey:    *stackP = cos(*stackP);                break;
  823.                             case kRoundKey:    *stackP = floor(*stackP+0.5);        break;
  824.                             case kIntKey:    *stackP = floor(*stackP);            break;
  825.                         }
  826.                         break;
  827.  
  828.                 }
  829.                 theProgram++;
  830.             }
  831.             theVar->value = *(stackP--);
  832.         }
  833.     }
  834.     
  835.     return    theVar->value;
  836. }
  837.  
  838. void    LoadProgram()
  839. {
  840.     OSErr    err;
  841.     short    ref;
  842.     long    preSize, postSize, wholeSize;
  843.     
  844.     theScript = GetResource('TEXT',2128);
  845.     DetachResource(theScript);
  846.     
  847.     preSize = GetHandleSize(theScript);
  848.     
  849.     err = FSOpen("\pArashi Script", 0, &ref);
  850.  
  851.     if(err != noErr)
  852.     {    Handle    postScript;
  853.     
  854.         postScript = GetResource('TEXT',2129);
  855.         postSize = GetHandleSize(postScript);
  856.         wholeSize = postSize + preSize;
  857.         HandAndHand(postScript, theScript);
  858.         ReleaseResource(postScript);
  859.     }
  860.     else
  861.     {    
  862.     
  863.         GetEOF(ref, &postSize);
  864.         wholeSize = postSize + GetHandleSize(theScript);
  865.         SetHandleSize(theScript,wholeSize);
  866.         HLock(theScript);
  867.         if(GetHandleSize(theScript) == wholeSize)
  868.         {    FSRead(ref, &postSize, *theScript+wholeSize-postSize);
  869.         }
  870.         FSClose(ref);
  871.     }
  872.     HUnlock(theScript);
  873.     SetHandleSize(theScript, wholeSize+1);
  874.     HLock(theScript);
  875.     (*theScript)[wholeSize] = 0;    //    Append a NULL to terminate the script.
  876. }
  877.  
  878. void    LoadLevel(
  879.     short    whichLevel)
  880. {
  881.     LexSymbol    statement;
  882.  
  883.     currentLevel = whichLevel;
  884.     
  885.     if(fromLevel > currentLevel)
  886.     {    ResetVariables();
  887.         SetupCompiler((StringPtr)*theScript);
  888.         LexRead(&parserVar.lookahead);
  889.         fromLevel = -1;
  890.         upToLevel = -1;
  891.     }
  892.     
  893.     while(whichLevel >= upToLevel)
  894.     {    ParseStatement(&statement);
  895.         SetHandleSize(parserVar.output, parserVar.logicalSize);
  896.  
  897.         if(parserVar.lookahead.kind == kParseError)
  898.         {
  899.             DEBUGPAR(printf(" ** Parse Error **\n");)
  900.             upToLevel = 32000;
  901.         }
  902.         else
  903.         {    DEBUGPAR(printf("\n");)
  904.             if(statement.kind == kAssignment)
  905.             {    programBase->WriteHandle(statement.value.token, parserVar.output);
  906.             }
  907.             else
  908.             if(statement.kind == kLexLevel)
  909.             {    fromLevel = upToLevel;
  910.                 upToLevel = statement.value.level;
  911.             }
  912.         }
  913.         DisposHandle(parserVar.output);
  914.         SetupCompiler(parserVar.input);
  915.         
  916.         if(parserVar.lookahead.kind == kLexEof)
  917.         {    upToLevel = 32000;
  918.         }
  919.     }
  920.     
  921.     WriteVariable(    kVarLevelNumber, (double) currentLevel);
  922. }
  923. void    RunThis(
  924.     StringPtr    script)
  925. {
  926.     LexSymbol    statement;
  927.  
  928.     parserVar.input = script;
  929.     
  930.     SetupCompiler(parserVar.input);
  931.     LexRead(&parserVar.lookahead);
  932.  
  933.     do
  934.     {    ParseStatement(&statement);
  935.         SetHandleSize(parserVar.output, parserVar.logicalSize);
  936.  
  937.         if(parserVar.lookahead.kind == kParseError)
  938.         {    DEBUGPAR(printf(" ** Parse Error **\n");)
  939.         }
  940.         else
  941.         {    if(statement.kind == kAssignment)
  942.             {    programBase->WriteHandle(statement.value.token, parserVar.output);
  943.                 programBase->Lock();
  944.                 currentLevel++;
  945.                 DEBUGPAR(printf(" ==> %lf\n", EvalVariable(statement.value.token));)
  946.                 programBase->Unlock();
  947.             }
  948.             else
  949.             if(statement.kind == kLexLevel)
  950.             {    fromLevel = upToLevel;
  951.                 upToLevel = statement.value.level;
  952.                 DEBUGPAR(printf("\n");)
  953.             }
  954.         }
  955.         DisposHandle(parserVar.output);
  956.         SetupCompiler(parserVar.input);
  957.         
  958.     } while(!(    parserVar.lookahead.kind == kLexEof ||
  959.                 parserVar.lookahead.kind == kParseError));
  960.  
  961. }
  962.  
  963. void    AllocParser()
  964. {
  965.     InitSymbols();
  966.     stackP = (double *)NewPtr(sizeof(double) * 256);
  967.  
  968.     LoadProgram();
  969.  
  970. }
  971.  
  972. #ifdef DEBUGPARSER
  973. void    main()
  974. {
  975.     unsigned    char    dummystring[128];
  976.     unsigned    char    *ditto;
  977.     int                    numChars;
  978.     short                i;
  979.     short                j;
  980.  
  981.     printf("Enter expressions and see if I can parse them.\n");
  982.  
  983.     InitSymbols();
  984.     stackP = (double *)NewPtr(sizeof(double) * 256);
  985.     
  986.     LoadProgram();
  987.     
  988.     for(i=1;i<15;i++)
  989.     {    LoadLevel(i);
  990.         programBase->Lock();
  991.         
  992.         printf("Level %4d   Flippercount: %d\n", currentLevel, (int)EvalVariable(kVarFlipperCount));
  993.         programBase->Unlock();
  994.     }
  995.  
  996.  
  997.     do
  998.     {    ditto=(void *)fgets((char *)dummystring,127,stdin);
  999.         RunThis(dummystring);
  1000.  
  1001.     } while(ditto);
  1002. }
  1003. #endif