summaryrefslogtreecommitdiff
path: root/src/parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/parser.cpp406
1 files changed, 97 insertions, 309 deletions
diff --git a/src/parser.cpp b/src/parser.cpp
index 0131ba3..510b471 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -29,7 +29,17 @@ void Parser::parse()
29 expr(); 29 expr();
30 30
31 Bu::sio << "Final stack:"; 31 Bu::sio << "Final stack:";
32 for( TokenStack::iterator i = tsStack.begin(); i; i++ ) 32 for( TokenStack::iterator i = tsParse.begin(); i; i++ )
33 {
34 Bu::sio << " " << (*i).eType;
35 if( (*i).eType == Token::tNumber )
36 {
37 Bu::sio << "(" << (*i).nVal->toString() << ")";
38 }
39 }
40 Bu::sio << Bu::sio.nl;
41 Bu::sio << "Script:";
42 for( TokenStack::iterator i = tsScript.begin(); i; i++ )
33 { 43 {
34 Bu::sio << " " << (*i).eType; 44 Bu::sio << " " << (*i).eType;
35 if( (*i).eType == Token::tNumber ) 45 if( (*i).eType == Token::tNumber )
@@ -67,7 +77,7 @@ void Parser::expr()
67 Token t = lex[0]; 77 Token t = lex[0];
68 lex.nextToken(); 78 lex.nextToken();
69 expr(); 79 expr();
70 tsStack.push( t ); 80 shift( t );
71 break; 81 break;
72 } 82 }
73} 83}
@@ -78,7 +88,7 @@ void Parser::exprP()
78 { 88 {
79 case Token::tNumber: 89 case Token::tNumber:
80 case Token::tVariable: 90 case Token::tVariable:
81 tsStack.push( lex[0] ); 91 shift( lex[0] );
82 lex.nextToken(); 92 lex.nextToken();
83 break; 93 break;
84 94
@@ -95,306 +105,107 @@ void Parser::exprP()
95 case Token::tMinus: 105 case Token::tMinus:
96 lex.nextToken(); 106 lex.nextToken();
97 exprP(); 107 exprP();
98 tsStack.push( Token( Token::tNegate ) ); 108 shift( Token( Token::tNegate ) );
99 break; 109 break;
100 } 110 }
101} 111}
102/* 112/*
103 for(;;) 113case Token::tCommand:
114 lex.setMode( Lexer::modeCommand );
115 if( *t.sVal == "exit" || *t.sVal == "quit" )
116 return;
117 else if( *t.sVal == "scale" )
104 { 118 {
105 Token t = lex.nextToken(); 119 Token t2 = lex.nextToken();
106 switch( t.eType ) 120 if( t2.eType == Token::tEndOfLine )
107 { 121 {
108 case Token::tEndOfInput: 122 Bu::println( rOut, "Current scale: %1").
109 while( !tsNonTerminal.isEmpty() ) 123 arg( lex.getScale() );
110 unwind(); 124 }
111 return; 125 else if( t2.eType == Token::tString )
112 126 {
113 case Token::tEndOfLine: 127 int32_t i = strtol( t2.sVal->getStr(), 0, 10 );
114 while( !tsNonTerminal.isEmpty() ) 128 lex.setScale( i );
115 unwind(); 129 if( i < 0 )
116 if( !tsTerminal.isEmpty() ) 130 {
117 { 131 Bu::println( rOut, "ERROR: You must provide a "
118 Bu::println( rOut, "%1").arg( deref( tsTerminal.peek() ) ); 132 "positive integer or zero as the parameter "
119 hVars.insert("ans", deref( tsTerminal.peek() ) ); 133 "to scale.");
120 } 134 }
121 tsTerminal.clear(); 135 else
122 lex.setMode( Lexer::modeNormal ); 136 {
123 break; 137 Bu::println( rOut, "Scale changed to: %1").
124 138 arg( lex.getScale() );
125 case Token::tCommand: 139 for( VarHash::iterator i = hVars.begin(); i; i++ )
126 lex.setMode( Lexer::modeCommand ); 140 (*i).setScale( lex.getScale() );
127 if( *t.sVal == "exit" || *t.sVal == "quit" ) 141 nZero = Number( lex.getScale(), lex.getRadix() );
128 return; 142 }
129 else if( *t.sVal == "scale" ) 143 }
130 { 144 else
131 Token t2 = lex.nextToken(); 145 {
132 if( t2.eType == Token::tEndOfLine ) 146 Bu::println( rOut, "ERROR: You must provide a number "
133 { 147 "as the parameter to scale.");
134 Bu::println( rOut, "Current scale: %1").
135 arg( lex.getScale() );
136 }
137 else if( t2.eType == Token::tString )
138 {
139 int32_t i = strtol( t2.sVal->getStr(), 0, 10 );
140 lex.setScale( i );
141 if( i < 0 )
142 {
143 Bu::println( rOut, "ERROR: You must provide a "
144 "positive integer or zero as the parameter "
145 "to scale.");
146 }
147 else
148 {
149 Bu::println( rOut, "Scale changed to: %1").
150 arg( lex.getScale() );
151 for( VarHash::iterator i = hVars.begin(); i; i++ )
152 (*i).setScale( lex.getScale() );
153 nZero = Number( lex.getScale(), lex.getRadix() );
154 }
155 }
156 else
157 {
158 Bu::println( rOut, "ERROR: You must provide a number "
159 "as the parameter to scale.");
160 }
161 }
162 else if( *t.sVal == "radix" )
163 {
164 Token t2 = lex.nextToken();
165 if( t2.eType == Token::tEndOfLine )
166 {
167 Bu::println( rOut, "Current radix: %1").
168 arg( lex.getRadix() );
169 }
170 else if( t2.eType == Token::tString )
171 {
172 int32_t i = strtol( t2.sVal->getStr(), 0, 10 );
173 if( i < 2 || i > 36 )
174 Bu::println( rOut, "ERROR: Radix must be between "
175 "2 and 36 inclusive");
176 else
177 {
178 lex.setRadix( i );
179 Bu::println( rOut, "Radix changed to: %1").
180 arg( lex.getRadix() );
181 hVars.clear();
182 nZero = Number( lex.getScale(), lex.getRadix() );
183 }
184 }
185 else
186 {
187 Bu::println( rOut, "You must provide a number as "
188 "the parameter to radix.");
189 }
190 }
191 else if( *t.sVal == "vars" )
192 {
193 Bu::println( rOut, "Declared variables:");
194 for( VarHash::iterator i = hVars.begin(); i; i++ )
195 {
196 Bu::println( rOut, " - %1 = %2").
197 arg( i.getKey() ).arg( *i );
198 }
199 Bu::println( rOut, "");
200 }
201 else if( *t.sVal == "help" || *t.sVal == "h" || *t.sVal == "?" )
202 {
203 Bu::println( rOut, Datafiles::getString("parserhelp.txt") );
204 }
205 else
206 {
207 Bu::println( rOut, "ERROR: Unknown command '%1'").
208 arg( *t.sVal );
209 }
210 lex.setMode( Lexer::modeNormal );
211 break;
212
213 case Token::tNumber:
214 case Token::tVariable:
215 tsTerminal.push( t );
216 break;
217
218 default:
219 if( tsNonTerminal.getSize() == 0 ||
220 getPriority( tsNonTerminal.peek().eType ) <
221 getPriority( t.eType ) )
222 {
223 DBS( PARSE,
224 Bu::println("Pushing non-terminal: %1").arg( t.eType )
225 );
226 tsNonTerminal.push( t );
227 }
228 else
229 {
230 DBS( PARSE,
231 Bu::println("Unwinding stack before pushing: %1")
232 .arg( t.eType )
233 );
234 unwind();
235 tsNonTerminal.push( t );
236 }
237 break;
238 } 148 }
239 } 149 }
240} 150 else if( *t.sVal == "radix" )
241*/
242
243Number Parser::getVariable( const Bu::String &sName )
244{
245 return hVars.get( sName );
246}
247
248void Parser::setVariable( const Bu::String &sName, const Number &rValue )
249{
250 hVars.insert( sName, rValue );
251}
252
253void Parser::reduce()
254{
255 /*
256 for(;;)
257 { 151 {
258 DBS_START( PARSE ); 152 Token t2 = lex.nextToken();
259 for( TokenStack::iterator i = tsTerminal.begin(); i; i++ ) 153 if( t2.eType == Token::tEndOfLine )
260 { 154 {
261 if( (*i).eType == Token::tNumber ) 155 Bu::println( rOut, "Current radix: %1").
262 Bu::print(" [%1]").arg( *(*i).nVal ); 156 arg( lex.getRadix() );
157 }
158 else if( t2.eType == Token::tString )
159 {
160 int32_t i = strtol( t2.sVal->getStr(), 0, 10 );
161 if( i < 2 || i > 36 )
162 Bu::println( rOut, "ERROR: Radix must be between "
163 "2 and 36 inclusive");
263 else 164 else
264 Bu::print(" [%1]").arg( *(*i).sVal ); 165 {
166 lex.setRadix( i );
167 Bu::println( rOut, "Radix changed to: %1").
168 arg( lex.getRadix() );
169 hVars.clear();
170 nZero = Number( lex.getScale(), lex.getRadix() );
171 }
265 } 172 }
266 Bu::println(""); 173 else
267 for( TokenStack::iterator i = tsNonTerminal.begin(); i; i++ )
268 Bu::print(" <%1>").arg( (*i).eType );
269 Bu::println("");
270 DBS_END();
271
272 if( tsNonTerminal.isEmpty() )
273 return;
274
275 if( tsTerminal.getSize() < reqTokens( tsNonTerminal.peek().eType ) )
276 { 174 {
277 return; 175 Bu::println( rOut, "You must provide a number as "
176 "the parameter to radix.");
278 } 177 }
279 178 }
280 Token t = tsNonTerminal.peekPop(); 179 else if( *t.sVal == "vars" )
281 switch( t.eType ) 180 {
181 Bu::println( rOut, "Declared variables:");
182 for( VarHash::iterator i = hVars.begin(); i; i++ )
282 { 183 {
283 case Token::tPlus: 184 Bu::println( rOut, " - %1 = %2").
284 { 185 arg( i.getKey() ).arg( *i );
285 Token b = tsTerminal.peekPop();
286 Token a = tsTerminal.peekPop();
287 tsTerminal.push(
288 Token( Token::tNumber,
289 new Number( deref(a) + deref(b) )
290 )
291 );
292 }
293 break;
294
295 case Token::tMinus:
296 {
297 Token b = tsTerminal.peekPop();
298 Token a = tsTerminal.peekPop();
299 tsTerminal.push(
300 Token( Token::tNumber,
301 new Number( deref(a) - deref(b) )
302 )
303 );
304 }
305 break;
306
307 case Token::tMultiply:
308 {
309 Token b = tsTerminal.peekPop();
310 Token a = tsTerminal.peekPop();
311 Number *pProduct = new Number( deref(a) * deref(b) );
312 pProduct->setScale( lex.getScale() );
313 tsTerminal.push(
314 Token( Token::tNumber,
315 pProduct
316 )
317 );
318 }
319 break;
320
321 case Token::tDivide:
322 {
323 Token b = tsTerminal.peekPop();
324 Token a = tsTerminal.peekPop();
325 tsTerminal.push(
326 Token( Token::tNumber,
327 new Number( deref(a) / deref(b) )
328 )
329 );
330 }
331 break;
332
333 case Token::tModulus:
334 {
335 Token b = tsTerminal.peekPop();
336 Token a = tsTerminal.peekPop();
337 tsTerminal.push(
338 Token( Token::tNumber,
339 new Number( deref(a) % deref(b) )
340 )
341 );
342 }
343 break;
344
345 case Token::tOpenParen:
346 tsNonTerminal.push( t );
347 return;
348
349 case Token::tCloseParen:
350 unwind();
351 if( tsNonTerminal.peek().eType == Token::tOpenParen )
352 {
353
354 tsNonTerminal.pop();
355 unwind();
356 }
357 else
358 {
359 throw Bu::ExceptionBase("Close paren found without open paren.");
360 }
361 break;
362
363 case Token::tEquals:
364 {
365 Token b = tsTerminal.peekPop();
366 Token a = tsTerminal.peekPop();
367 if( a.eType != Token::tVariable )
368 {
369 Bu::println("The left hand side of a = must be a variable.");
370 tsTerminal.clear();
371 tsNonTerminal.clear();
372 return;
373 }
374 hVars.insert( *a.sVal, deref( b ) );
375 tsTerminal.push(
376 Token( Token::tNumber,
377 new Number( deref( b ) )
378 )
379 );
380 }
381 break;
382
383 case Token::tNumber:
384 case Token::tVariable:
385 case Token::tCommand:
386 case Token::tString:
387 case Token::tEndOfLine:
388 case Token::tEndOfInput:
389 // These should never show up at all
390 break;
391 } 186 }
392 if( !tsNonTerminal.isEmpty() && 187 Bu::println( rOut, "");
393 getPriority( tsNonTerminal.peek().eType ) < 188 }
394 getPriority( t.eType ) ) 189 else if( *t.sVal == "help" || *t.sVal == "h" || *t.sVal == "?" )
395 return; 190 {
191 Bu::println( rOut, Datafiles::getString("parserhelp.txt") );
396 } 192 }
397 */ 193 else
194 {
195 Bu::println( rOut, "ERROR: Unknown command '%1'").
196 arg( *t.sVal );
197 }
198 lex.setMode( Lexer::modeNormal );
199 break;
200*/
201
202void Parser::shift( const Token &t )
203{
204 tsParse.push( t );
205}
206
207void Parser::reduce()
208{
398} 209}
399 210
400int Parser::reqTokens( Token::Type eType ) 211int Parser::reqTokens( Token::Type eType )
@@ -452,26 +263,3 @@ int Parser::getPriority( Token::Type eType )
452 } 263 }
453} 264}
454 265
455Number &Parser::deref( Token &t )
456{
457 if( t.eType == Token::tNumber )
458 {
459 return *t.nVal;
460 }
461 else if( t.eType == Token::tVariable )
462 {
463 try
464 {
465 return hVars.get( *t.sVal );
466 }
467 catch(...)
468 {
469 return nZero;
470 }
471 }
472 else
473 {
474 throw Bu::ExceptionBase("Element was not a number or variable.");
475 }
476}
477