1 using System;
  2 
  3 namespace Calculator
  4 {
  5     public void Parse(const ustring& input)
  6     {
  7         Scanner scanner(input);
  8         scanner.NextToken();
  9         if (scanner.CurrentToken() is PrintToken*)
 10         {
 11             SymbolTable.Instance().Print();
 12             return;
 13         }
 14         else if (scanner.CurrentToken() is VariableNameToken*)
 15         {
 16             VariableNameToken* token = cast<VariableNameToken*>(scanner.CurrentToken());
 17             ustring variableName = token->VariableName();
 18             scanner.NextToken();
 19             if (scanner.CurrentToken() is OperatorToken*)
 20             {
 21                 OperatorToken* token = cast<OperatorToken*>(scanner.CurrentToken());
 22                 if (token->Char() == '=')
 23                 {
 24                     scanner.NextToken();
 25                     double value = Expr(scanner);
 26                     Token* token = scanner.CurrentToken();
 27                     if (token is EndToken*)
 28                     {
 29                         SymbolTable.Instance().SetVariable(variableNamevalue);
 30                         Console.Out() << variableName << " = " << value << endl();
 31                         return;
 32                     }
 33                     else
 34                     {
 35                         throw ParsingException("invalid input");
 36                     }
 37                 }
 38             }
 39         }
 40         scanner.Rewind();
 41         scanner.NextToken();
 42         double value = Expr(scanner);
 43         Token* token = scanner.CurrentToken();
 44         if (token is EndToken*)
 45         {
 46             Console.Out() << "= " << value << endl();
 47         }
 48         else
 49         {
 50             throw ParsingException("invalid input");
 51         }
 52     }
 53 
 54     internal double Expr(Scanner& scanner)
 55     {
 56         double value = Term(scanner);
 57         Token* token = scanner.CurrentToken();
 58         OperatorToken* op = token as OperatorToken*;
 59         while (op != null && op->IsAdditiveOperator())
 60         {
 61             uchar opChar = op->Char();
 62             scanner.NextToken();
 63             double right = Term(scanner);
 64             if (opChar == '+')
 65             {
 66                 value = value + right;
 67             }
 68             else if (opChar == '-')
 69             {
 70                 value = value - right;
 71             }
 72             else
 73             {
 74                 throw LogicErrorException("logic error");
 75             }
 76             token = scanner.CurrentToken();
 77             op = token as OperatorToken*;
 78         }
 79         return value;
 80     }
 81 
 82     internal double Term(Scanner& scanner)
 83     {
 84         double value = Factor(scanner);
 85         Token* token = scanner.CurrentToken();
 86         OperatorToken* op = token as OperatorToken*;
 87         while (op != null && op->IsMultiplicativeOperator())
 88         {
 89             uchar opChar = op->Char();
 90             scanner.NextToken();
 91             double right = Factor(scanner);
 92             if (opChar == '*')
 93             {
 94                 value = value * right;
 95             }
 96             else if (opChar == '/')
 97             {
 98                 if (right == 0)
 99                 {
100                     throw DivisionByZeroException("division by zero");
101                 }
102                 value = value / right;
103             }
104             else
105             {
106                 throw LogicErrorException("logic error");
107             }
108             token = scanner.CurrentToken();
109             op = token as OperatorToken*;
110         }
111         return value;
112     }
113 
114     internal double Factor(Scanner& scanner)
115     {
116         Token* token = scanner.CurrentToken();
117         OperatorToken* op = token as OperatorToken*;
118         bool neg = false;
119         if (op != null && op->IsAdditiveOperator())
120         {
121             if (op->Char() == '-')
122             {
123                 neg = true;
124             }
125             scanner.NextToken();
126         }
127         double value = Primary(scanner);
128         if (neg)
129         {
130             return -value;
131         }
132         return value;
133     }
134 
135     internal double Primary(Scanner& scanner)
136     {
137         Token* token = scanner.CurrentToken();
138         if (token is NumberToken*)
139         {
140             NumberToken* number = cast<NumberToken*>(token);
141             double value = number->Value();
142             scanner.NextToken();
143             return value;
144         }
145         else if (token is VariableNameToken*)
146         {
147             VariableNameToken* variableNameToken = cast<VariableNameToken*>(token);
148             double value = SymbolTable.Instance().GetVariableValue(variableNameToken->VariableName());
149             scanner.NextToken();
150             return value;
151         }
152         else if (token is OperatorToken*)
153         {
154             OperatorToken* op = cast<OperatorToken*>(token);
155             if (op->Char() == '(')
156             {
157                 scanner.NextToken();
158                 double value = Expr(scanner);
159                 token = scanner.CurrentToken();
160                 if (token is OperatorToken*)
161                 {
162                     op = cast<OperatorToken*>(token);
163                     if (op->Char() == ')')
164                     {
165                         scanner.NextToken();
166                         return value;
167                     }
168                     else
169                     {
170                         throw ParsingException("')' expected");
171                     }
172                 }
173             }
174         }
175         throw ParsingException("number, variable name or subexpression expected");
176     }
177 }