summaryrefslogtreecommitdiff
path: root/src/parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/parser.cpp114
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
344Number &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