diff options
Diffstat (limited to '')
-rw-r--r-- | src/parser.cpp | 114 |
1 files changed, 107 insertions, 7 deletions
diff --git a/src/parser.cpp b/src/parser.cpp index 21ccc11..5bb0aa6 100644 --- a/src/parser.cpp +++ b/src/parser.cpp | |||
@@ -28,7 +28,7 @@ void Parser::parse() | |||
28 | unwind(); | 28 | unwind(); |
29 | if( !tsTerminal.isEmpty() ) | 29 | if( !tsTerminal.isEmpty() ) |
30 | { | 30 | { |
31 | Bu::println( rOut, "%1").arg( *tsTerminal.peek().nVal ); | 31 | Bu::println( rOut, "%1").arg( deref( tsTerminal.peek() ) ); |
32 | } | 32 | } |
33 | tsTerminal.clear(); | 33 | tsTerminal.clear(); |
34 | break; | 34 | break; |
@@ -58,6 +58,9 @@ void Parser::parse() | |||
58 | { | 58 | { |
59 | Bu::println( rOut, "Scale changed to: %1"). | 59 | Bu::println( rOut, "Scale changed to: %1"). |
60 | arg( lex.getScale() ); | 60 | arg( lex.getScale() ); |
61 | for( VarHash::iterator i = hVars.begin(); i; i++ ) | ||
62 | (*i).setScale( lex.getScale() ); | ||
63 | nZero = Number( lex.getScale(), lex.getRadix() ); | ||
61 | } | 64 | } |
62 | } | 65 | } |
63 | else | 66 | else |
@@ -85,6 +88,8 @@ void Parser::parse() | |||
85 | lex.setRadix( i ); | 88 | lex.setRadix( i ); |
86 | Bu::println( rOut, "Radix changed to: %1"). | 89 | Bu::println( rOut, "Radix changed to: %1"). |
87 | arg( lex.getRadix() ); | 90 | arg( lex.getRadix() ); |
91 | hVars.clear(); | ||
92 | nZero = Number( lex.getScale(), lex.getRadix() ); | ||
88 | } | 93 | } |
89 | } | 94 | } |
90 | else | 95 | else |
@@ -93,6 +98,47 @@ void Parser::parse() | |||
93 | "the parameter to radix."); | 98 | "the parameter to radix."); |
94 | } | 99 | } |
95 | } | 100 | } |
101 | else if( *t.sVal == "vars" ) | ||
102 | { | ||
103 | Bu::println( rOut, "Declared variables:"); | ||
104 | for( VarHash::iterator i = hVars.begin(); i; i++ ) | ||
105 | { | ||
106 | Bu::println( rOut, " - %1 = %2"). | ||
107 | arg( i.getKey() ).arg( *i ); | ||
108 | } | ||
109 | Bu::println( rOut, ""); | ||
110 | } | ||
111 | else if( *t.sVal == "help" || *t.sVal == "h" || *t.sVal == "?" ) | ||
112 | { | ||
113 | Bu::println( rOut, | ||
114 | "All commands start with a '\\'. The following commands are defined:\n" | ||
115 | " \\help, \\h, \\? - This help\n" | ||
116 | " \\exit, \\quit - Exit the program\n" | ||
117 | " \\radix - Display the current radix (base)\n" | ||
118 | " \\radix <num> - Set the radix to anything between 2 and 36 (inclusive)\n" | ||
119 | " \\scale - Display the current scale\n" | ||
120 | " \\scale <num> - Set the current scale\n" | ||
121 | " \\vars - List all defined variables\n" | ||
122 | "\n" | ||
123 | "All variables must prefixed with a $ but otherwise can be used anywhere a\n" | ||
124 | "number can be used. To assign a variable use =, i.e.:\n" | ||
125 | " $amnt = $rate * 144000.09\n" | ||
126 | "\n" | ||
127 | "When using a radix greater than 10 all extended digits are lowercase letters\n" | ||
128 | "starting with 'a'. Upper case is not currently supported.\n" | ||
129 | "\n" | ||
130 | "All numbers are interpreted in the current radix, this means that you need to\n" | ||
131 | "set the radix using the current radix, even though the current value is aways\n" | ||
132 | "displayed in decimal. That is, to go to base 8 and back to base 10 you would:\n" | ||
133 | " \\radix 8\n" | ||
134 | " Radix changed to: 8\n" | ||
135 | " \\radix 12\n" | ||
136 | " Radix changed to: 10\n" | ||
137 | "\n" | ||
138 | "Changing the radix always clears all variables.\n" | ||
139 | ); | ||
140 | |||
141 | } | ||
96 | else | 142 | else |
97 | { | 143 | { |
98 | Bu::println( rOut, "ERROR: Unknown command '%1'"). | 144 | Bu::println( rOut, "ERROR: Unknown command '%1'"). |
@@ -101,6 +147,7 @@ void Parser::parse() | |||
101 | break; | 147 | break; |
102 | 148 | ||
103 | case Token::tNumber: | 149 | case Token::tNumber: |
150 | case Token::tVariable: | ||
104 | tsTerminal.push( t ); | 151 | tsTerminal.push( t ); |
105 | break; | 152 | break; |
106 | 153 | ||
@@ -150,7 +197,9 @@ void Parser::unwind() | |||
150 | Token b = tsTerminal.peekPop(); | 197 | Token b = tsTerminal.peekPop(); |
151 | Token a = tsTerminal.peekPop(); | 198 | Token a = tsTerminal.peekPop(); |
152 | tsTerminal.push( | 199 | tsTerminal.push( |
153 | Token( Token::tNumber, new Number( *a.nVal + *b.nVal ) ) | 200 | Token( Token::tNumber, |
201 | new Number( deref(a) + deref(b) ) | ||
202 | ) | ||
154 | ); | 203 | ); |
155 | } | 204 | } |
156 | break; | 205 | break; |
@@ -160,7 +209,9 @@ void Parser::unwind() | |||
160 | Token b = tsTerminal.peekPop(); | 209 | Token b = tsTerminal.peekPop(); |
161 | Token a = tsTerminal.peekPop(); | 210 | Token a = tsTerminal.peekPop(); |
162 | tsTerminal.push( | 211 | tsTerminal.push( |
163 | Token( Token::tNumber, new Number( *a.nVal - *b.nVal ) ) | 212 | Token( Token::tNumber, |
213 | new Number( deref(a) - deref(b) ) | ||
214 | ) | ||
164 | ); | 215 | ); |
165 | } | 216 | } |
166 | break; | 217 | break; |
@@ -170,7 +221,9 @@ void Parser::unwind() | |||
170 | Token b = tsTerminal.peekPop(); | 221 | Token b = tsTerminal.peekPop(); |
171 | Token a = tsTerminal.peekPop(); | 222 | Token a = tsTerminal.peekPop(); |
172 | tsTerminal.push( | 223 | tsTerminal.push( |
173 | Token( Token::tNumber, new Number( *a.nVal * *b.nVal ) ) | 224 | Token( Token::tNumber, |
225 | new Number( deref(a) * deref(b) ) | ||
226 | ) | ||
174 | ); | 227 | ); |
175 | } | 228 | } |
176 | break; | 229 | break; |
@@ -180,7 +233,9 @@ void Parser::unwind() | |||
180 | Token b = tsTerminal.peekPop(); | 233 | Token b = tsTerminal.peekPop(); |
181 | Token a = tsTerminal.peekPop(); | 234 | Token a = tsTerminal.peekPop(); |
182 | tsTerminal.push( | 235 | tsTerminal.push( |
183 | Token( Token::tNumber, new Number( *a.nVal / *b.nVal ) ) | 236 | Token( Token::tNumber, |
237 | new Number( deref(a) / deref(b) ) | ||
238 | ) | ||
184 | ); | 239 | ); |
185 | } | 240 | } |
186 | break; | 241 | break; |
@@ -202,8 +257,28 @@ void Parser::unwind() | |||
202 | } | 257 | } |
203 | break; | 258 | break; |
204 | 259 | ||
260 | case Token::tEquals: | ||
261 | { | ||
262 | Token b = tsTerminal.peekPop(); | ||
263 | Token a = tsTerminal.peekPop(); | ||
264 | if( a.eType != Token::tVariable ) | ||
265 | { | ||
266 | Bu::println("The left hand side of a = must be a variable."); | ||
267 | tsTerminal.clear(); | ||
268 | tsNonTerminal.clear(); | ||
269 | return; | ||
270 | } | ||
271 | hVars.insert( *a.sVal, deref( b ) ); | ||
272 | tsTerminal.push( | ||
273 | Token( Token::tNumber, | ||
274 | new Number( deref( b ) ) | ||
275 | ) | ||
276 | ); | ||
277 | } | ||
278 | break; | ||
279 | |||
205 | case Token::tNumber: | 280 | case Token::tNumber: |
206 | case Token::tString: | 281 | case Token::tVariable: |
207 | case Token::tCommand: | 282 | case Token::tCommand: |
208 | case Token::tEndOfLine: | 283 | case Token::tEndOfLine: |
209 | case Token::tEndOfInput: | 284 | case Token::tEndOfInput: |
@@ -221,6 +296,7 @@ int Parser::reqTokens( Token::Type eType ) | |||
221 | case Token::tMinus: | 296 | case Token::tMinus: |
222 | case Token::tDivide: | 297 | case Token::tDivide: |
223 | case Token::tMultiply: | 298 | case Token::tMultiply: |
299 | case Token::tEquals: | ||
224 | return 2; | 300 | return 2; |
225 | 301 | ||
226 | case Token::tOpenParen: | 302 | case Token::tOpenParen: |
@@ -239,8 +315,9 @@ int Parser::getPriority( Token::Type eType ) | |||
239 | switch( eType ) | 315 | switch( eType ) |
240 | { | 316 | { |
241 | case Token::tNumber: | 317 | case Token::tNumber: |
242 | case Token::tString: | 318 | case Token::tVariable: |
243 | case Token::tCommand: | 319 | case Token::tCommand: |
320 | case Token::tEquals: | ||
244 | return 0; | 321 | return 0; |
245 | 322 | ||
246 | case Token::tPlus: | 323 | case Token::tPlus: |
@@ -264,3 +341,26 @@ int Parser::getPriority( Token::Type eType ) | |||
264 | } | 341 | } |
265 | } | 342 | } |
266 | 343 | ||
344 | Number &Parser::deref( Token &t ) | ||
345 | { | ||
346 | if( t.eType == Token::tNumber ) | ||
347 | { | ||
348 | return *t.nVal; | ||
349 | } | ||
350 | else if( t.eType == Token::tVariable ) | ||
351 | { | ||
352 | try | ||
353 | { | ||
354 | return hVars.get( *t.sVal ); | ||
355 | } | ||
356 | catch(...) | ||
357 | { | ||
358 | return nZero; | ||
359 | } | ||
360 | } | ||
361 | else | ||
362 | { | ||
363 | throw Bu::ExceptionBase("Element was not a number or variable."); | ||
364 | } | ||
365 | } | ||
366 | |||