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(variableName, value);
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 }