1 using System;
  2 
  3 namespace Calculator
  4 {
  5     public Result<bool> Parse(const ustring& input)
  6     {
  7         Scanner scanner(input);
  8         auto nextTokenResult = scanner.NextToken();
  9         if (nextTokenResult.Error())
 10         {
 11             return nextTokenResult;
 12         }
 13         if (scanner.CurrentToken() is PrintToken*)
 14         {
 15             SymbolTable.Instance().Print();
 16             return Result<bool>(true);
 17         }
 18         else if (scanner.CurrentToken() is VariableNameToken*)
 19         {
 20             VariableNameToken* token = cast<VariableNameToken*>(scanner.CurrentToken());
 21             ustring variableName = token->VariableName();
 22             auto nextTokenResult = scanner.NextToken();
 23             if (nextTokenResult.Error())
 24             {
 25                 return nextTokenResult;
 26             }
 27             if (scanner.CurrentToken() is OperatorToken*)
 28             {
 29                 OperatorToken* token = cast<OperatorToken*>(scanner.CurrentToken());
 30                 if (token->Char() == '=')
 31                 {
 32                     auto nextTokenResult = scanner.NextToken();
 33                     if (nextTokenResult.Error())
 34                     {
 35                         return nextTokenResult;
 36                     }
 37                     auto expr = Expr(scanner);
 38                     if (expr.Error())
 39                     {
 40                         return Result<bool>(ErrorId(expr.GetErrorId()));
 41                     }
 42                     double value = expr.Value();
 43                     Token* token = scanner.CurrentToken();
 44                     if (token is EndToken*)
 45                     {
 46                         SymbolTable.Instance().SetVariable(variableNamevalue);
 47                         Console.Out() << variableName << " = " << value << endl();
 48                         return Result<bool>(true);
 49                     }
 50                     else
 51                     {
 52                         int errorId = AllocateError("invalid input");
 53                         return Result<bool>(ErrorId(errorId));
 54                     }
 55                 }
 56             }
 57         }
 58         scanner.Rewind();
 59         nextTokenResult = scanner.NextToken();
 60         if (nextTokenResult.Error())
 61         {
 62             return nextTokenResult;
 63         }
 64         auto expr = Expr(scanner);
 65         if (expr.Error())
 66         {
 67             return Result<bool>(ErrorId(expr.GetErrorId()));
 68         }
 69         Token* token = scanner.CurrentToken();
 70         if (token is EndToken*)
 71         {
 72             Console.Out() << "= " << expr.Value() << endl();
 73         }
 74         else
 75         {
 76             int errorId = AllocateError("invalid input");
 77             return Result<bool>(ErrorId(errorId));
 78         }
 79         return Result<bool>(true);
 80     }
 81 
 82     internal Result<double> Expr(Scanner& scanner)
 83     {
 84         auto term = Term(scanner);
 85         if (term.Error())
 86         {
 87             return Result<double>(ErrorId(term.GetErrorId()));
 88         }
 89         double value = term.Value();
 90         Token* token = scanner.CurrentToken();
 91         OperatorToken* op = token as OperatorToken*;
 92         while (op != null && op->IsAdditiveOperator())
 93         {
 94             uchar opChar = op->Char();
 95             auto nextTokenResult = scanner.NextToken();
 96             if (nextTokenResult.Error())
 97             {
 98                 return Result<double>(ErrorId(nextTokenResult.GetErrorId()));
 99             }
100             auto rightTerm = Term(scanner);
101             if (rightTerm.Error())
102             {
103                 return Result<double>(ErrorId(rightTerm.GetErrorId()));
104             }
105             double right = rightTerm.Value();
106             if (opChar == '+')
107             {
108                 value = value + right;
109             }
110             else if (opChar == '-')
111             {
112                 value = value - right;
113             }
114             else
115             {
116                 int errorId = AllocateError("logic error");
117                 return Result<double>(ErrorId(errorId));
118             }
119             token = scanner.CurrentToken();
120             op = token as OperatorToken*;
121         }
122         return value;
123     }
124 
125     internal Result<double> Term(Scanner& scanner)
126     {
127         auto factor = Factor(scanner);
128         if (factor.Error())
129         {
130             return factor;
131         }
132         double value = factor.Value();
133         Token* token = scanner.CurrentToken();
134         OperatorToken* op = token as OperatorToken*;
135         while (op != null && op->IsMultiplicativeOperator())
136         {
137             uchar opChar = op->Char();
138             auto nextTokenResult = scanner.NextToken();
139             if (nextTokenResult.Error())
140             {
141                 return Result<double>(ErrorId(nextTokenResult.GetErrorId()));;
142             }
143             auto rightFactor = Factor(scanner);
144             if (rightFactor.Error())
145             {
146                 return rightFactor;
147             }
148             double right = rightFactor.Value();
149             if (opChar == '*')
150             {
151                 value = value * right;
152             }
153             else if (opChar == '/')
154             {
155                 if (right == 0)
156                 {
157                     int errorId = AllocateError("division by zero");
158                     return Result<double>(ErrorId(errorId));
159                 }
160                 value = value / right;
161             }
162             else
163             {
164                 int errorId = AllocateError("logic error");
165                 return Result<double>(ErrorId(errorId));
166             }
167             token = scanner.CurrentToken();
168             op = token as OperatorToken*;
169         }
170         return value;
171     }
172 
173     internal Result<double> Factor(Scanner& scanner)
174     {
175         Token* token = scanner.CurrentToken();
176         OperatorToken* op = token as OperatorToken*;
177         bool neg = false;
178         if (op != null && op->IsAdditiveOperator())
179         {
180             if (op->Char() == '-')
181             {
182                 neg = true;
183             }
184             auto nextTokenResult = scanner.NextToken();
185             if (nextTokenResult.Error())
186             {
187                 return Result<double>(ErrorId(nextTokenResult.GetErrorId()));
188             }
189         }
190         auto primary = Primary(scanner);
191         if (primary.Error())
192         {
193             return primary;
194         }
195         double value = primary.Value();
196         if (neg)
197         {
198             return -value;
199         }
200         return Result<double>(value);
201     }
202 
203     internal Result<double> Primary(Scanner& scanner)
204     {
205         Token* token = scanner.CurrentToken();
206         if (token is NumberToken*)
207         {
208             NumberToken* number = cast<NumberToken*>(token);
209             double value = number->Value();
210             auto nextTokenResult = scanner.NextToken();
211             if (nextTokenResult.Error())
212             {
213                 return Result<double>(ErrorId(nextTokenResult.GetErrorId()));
214             }
215             return Result<double>(value);
216         }
217         else if (token is VariableNameToken*)
218         {
219             VariableNameToken* variableNameToken = cast<VariableNameToken*>(token);
220             auto variableResult = SymbolTable.Instance().GetVariableValue(variableNameToken->VariableName());
221             if (variableResult.Error())
222             {
223                 return variableResult;
224             }
225             double value = variableResult.Value();
226             auto nextTokenResult = scanner.NextToken();
227             if (nextTokenResult.Error())
228             {
229                 return Result<double>(ErrorId(nextTokenResult.GetErrorId()));
230             }
231             return Result<double>(value);
232         }
233         else if (token is OperatorToken*)
234         {
235             OperatorToken* op = cast<OperatorToken*>(token);
236             if (op->Char() == '(')
237             {
238                 auto nextTokenResult = scanner.NextToken();
239                 if (nextTokenResult.Error())
240                 {
241                     return Result<double>(ErrorId(nextTokenResult.GetErrorId()));
242                 }
243                 auto expr = Expr(scanner);
244                 if (expr.Error())
245                 {
246                     return expr;
247                 }
248                 double value = expr.Value();
249                 token = scanner.CurrentToken();
250                 if (token is OperatorToken*)
251                 {
252                     op = cast<OperatorToken*>(token);
253                     if (op->Char() == ')')
254                     {
255                         auto nextTokenResult = scanner.NextToken();
256                         if (nextTokenResult.Error())
257                         {
258                             return Result<double>(ErrorId(nextTokenResult.GetErrorId()));
259                         }
260                         return Result<double>(value);
261                     }
262                     else
263                     {
264                         int errorId = AllocateError("\')\' expected");
265                         return Result<double>(ErrorId(errorId));
266                     }
267                 }
268             }
269         }
270         int errorId = AllocateError("number, variable name or subexpression expected");
271         return Result<double>(ErrorId(errorId));
272     }