diff options
Diffstat (limited to 'src/parser.cpp')
| -rw-r--r-- | src/parser.cpp | 110 |
1 files changed, 68 insertions, 42 deletions
diff --git a/src/parser.cpp b/src/parser.cpp index 701c4bd..e9388c8 100644 --- a/src/parser.cpp +++ b/src/parser.cpp | |||
| @@ -8,6 +8,13 @@ | |||
| 8 | #include <bu/sio.h> | 8 | #include <bu/sio.h> |
| 9 | #include <stdlib.h> | 9 | #include <stdlib.h> |
| 10 | 10 | ||
| 11 | // #define DEBUG_MODE 1 | ||
| 12 | #ifdef DEBUG_MODE | ||
| 13 | #define DBG( x ) { x; } (void)0 | ||
| 14 | #else | ||
| 15 | #define DBG( x ) (void)0 | ||
| 16 | #endif | ||
| 17 | |||
| 11 | Parser::Parser( Lexer &lex ) : | 18 | Parser::Parser( Lexer &lex ) : |
| 12 | lex( lex ) | 19 | lex( lex ) |
| 13 | { | 20 | { |
| @@ -21,10 +28,15 @@ Expression *Parser::parse() | |||
| 21 | { | 28 | { |
| 22 | pCurExp = new Expression(); | 29 | pCurExp = new Expression(); |
| 23 | statement(); | 30 | statement(); |
| 31 | while( !tsTerminal.isEmpty() ) | ||
| 32 | { | ||
| 33 | reduce(); | ||
| 34 | } | ||
| 24 | 35 | ||
| 25 | printState("Final"); | 36 | printState("Final"); |
| 26 | 37 | ||
| 27 | tsParse.clear(); | 38 | tsTerminal.clear(); |
| 39 | tsNonTerminal.clear(); | ||
| 28 | 40 | ||
| 29 | Expression *pTmp = pCurExp; | 41 | Expression *pTmp = pCurExp; |
| 30 | pCurExp = NULL; | 42 | pCurExp = NULL; |
| @@ -34,12 +46,17 @@ Expression *Parser::parse() | |||
| 34 | void Parser::exprR() | 46 | void Parser::exprR() |
| 35 | { | 47 | { |
| 36 | exprP(); | 48 | exprP(); |
| 37 | expr(); | 49 | for(;;) |
| 50 | { | ||
| 51 | expr(); | ||
| 52 | if( !(lex[0].eType & Token::mMetaOperator) ) | ||
| 53 | break; | ||
| 54 | } | ||
| 38 | } | 55 | } |
| 39 | 56 | ||
| 40 | void Parser::expr() | 57 | void Parser::expr() |
| 41 | { | 58 | { |
| 42 | Bu::sio << "::expr " << lex[0] << Bu::sio.nl; | 59 | DBG( Bu::sio << "::expr " << lex[0] << Bu::sio.nl ); |
| 43 | if( lex[0].eType == Token::tEndOfInput ) | 60 | if( lex[0].eType == Token::tEndOfInput ) |
| 44 | return; | 61 | return; |
| 45 | 62 | ||
| @@ -56,7 +73,7 @@ void Parser::expr() | |||
| 56 | case Token::tModulus: | 73 | case Token::tModulus: |
| 57 | Token t = lex[0]; | 74 | Token t = lex[0]; |
| 58 | lex.nextToken(); | 75 | lex.nextToken(); |
| 59 | Bu::sio << "->expr " << t << " " << lex[0] << Bu::sio.nl; | 76 | DBG( Bu::sio << "->expr " << t << " " << lex[0] << Bu::sio.nl ); |
| 60 | if( lex[0].eType == Token::tOpenParen ) | 77 | if( lex[0].eType == Token::tOpenParen ) |
| 61 | { | 78 | { |
| 62 | exprP(); | 79 | exprP(); |
| @@ -69,40 +86,42 @@ void Parser::expr() | |||
| 69 | if( lex[0].eType == Token::tNumber || | 86 | if( lex[0].eType == Token::tNumber || |
| 70 | lex[0].eType == Token::tVariable ) | 87 | lex[0].eType == Token::tVariable ) |
| 71 | { | 88 | { |
| 72 | Bu::sio << "->expr " << t << | 89 | DBG( Bu::sio << "->expr " << t << |
| 73 | " " << lex[0] << | 90 | " " << lex[0] << |
| 74 | " " << lex[1] << | 91 | " " << lex[1] << |
| 75 | Bu::sio.nl; | 92 | Bu::sio.nl ); |
| 76 | shift( lex[0] ); | 93 | shift( lex[0] ); |
| 94 | shift( t ); | ||
| 77 | if( lex[1].eType&Token::mMetaOperator ) | 95 | if( lex[1].eType&Token::mMetaOperator ) |
| 78 | { | 96 | { |
| 79 | if( getPriority(lex[1].eType) <= | 97 | if( getPriority(lex[1].eType) < |
| 80 | getPriority(t.eType) ) | 98 | getPriority(t.eType) ) |
| 81 | { | 99 | { |
| 82 | shift( t ); | 100 | while( !tsTerminal.isEmpty() ) |
| 83 | reduce(); | 101 | { |
| 102 | reduce(); | ||
| 103 | } | ||
| 84 | printState("reduce"); | 104 | printState("reduce"); |
| 85 | lex.nextToken(); | 105 | lex.nextToken(); |
| 86 | expr(); | 106 | // expr(); |
| 87 | } | 107 | } |
| 88 | else | 108 | else |
| 89 | { | 109 | { |
| 90 | printState("no reduce"); | 110 | printState("no reduce"); |
| 91 | lex.nextToken(); | 111 | lex.nextToken(); |
| 92 | expr(); | 112 | // expr(); |
| 93 | if( !tsParse.isEmpty() && | 113 | /* |
| 114 | if( !tsNonTerminal.isEmpty() && | ||
| 94 | tsParse.peek().eType != Token::tComputedValue ) | 115 | tsParse.peek().eType != Token::tComputedValue ) |
| 95 | { | 116 | { |
| 96 | reduce(); | 117 | //reduce(); |
| 97 | printState("no reduce reduce"); | 118 | //printState("no reduce reduce"); |
| 98 | } | 119 | }*/ |
| 99 | shift( t ); | ||
| 100 | printState("post no reduce"); | 120 | printState("post no reduce"); |
| 101 | } | 121 | } |
| 102 | } | 122 | } |
| 103 | else | 123 | else |
| 104 | { | 124 | { |
| 105 | shift( t ); | ||
| 106 | lex.nextToken(); | 125 | lex.nextToken(); |
| 107 | printState("no next op"); | 126 | printState("no next op"); |
| 108 | } | 127 | } |
| @@ -110,14 +129,14 @@ void Parser::expr() | |||
| 110 | else if( lex[0].eType == Token::tMinus ) | 129 | else if( lex[0].eType == Token::tMinus ) |
| 111 | { | 130 | { |
| 112 | // This is negation | 131 | // This is negation |
| 113 | Bu::sio << "next token: " << lex[0] << Bu::sio.nl; | 132 | DBG( Bu::sio << "next token: " << lex[0] << Bu::sio.nl ); |
| 114 | printState("inline-negate"); | 133 | printState("inline-negate"); |
| 115 | exprP(); | 134 | exprP(); |
| 116 | printState("inline-negate-post"); | 135 | printState("inline-negate-post"); |
| 117 | shift( t ); | 136 | shift( t ); |
| 118 | printState("inline-negate-post2"); | 137 | printState("inline-negate-post2"); |
| 119 | 138 | ||
| 120 | Bu::sio << "??? " << lex[0] << Bu::sio.nl; | 139 | DBG( Bu::sio << "??? " << lex[0] << Bu::sio.nl ); |
| 121 | } | 140 | } |
| 122 | } | 141 | } |
| 123 | break; | 142 | break; |
| @@ -156,7 +175,7 @@ void Parser::exprP() | |||
| 156 | exprR(); | 175 | exprR(); |
| 157 | if( lex[0].eType != Token::tCloseParen ) | 176 | if( lex[0].eType != Token::tCloseParen ) |
| 158 | { | 177 | { |
| 159 | Bu::sio << "::exprP " << lex[0] << Bu::sio.nl; | 178 | DBG( Bu::sio << "::exprP " << lex[0] << Bu::sio.nl ); |
| 160 | throw Bu::ExceptionBase("Expected close paren"); | 179 | throw Bu::ExceptionBase("Expected close paren"); |
| 161 | } | 180 | } |
| 162 | shift( lex[0] ); | 181 | shift( lex[0] ); |
| @@ -281,16 +300,20 @@ case Token::tCommand: | |||
| 281 | 300 | ||
| 282 | void Parser::shift( const Token &t ) | 301 | void Parser::shift( const Token &t ) |
| 283 | { | 302 | { |
| 284 | tsParse.push( t ); | 303 | if( (t.eType&(Token::mMetaOperator)) || t.eType==Token::tCloseParen ) |
| 304 | tsTerminal.push( t ); | ||
| 305 | else | ||
| 306 | tsNonTerminal.push( t ); | ||
| 285 | } | 307 | } |
| 286 | 308 | ||
| 287 | void Parser::reduce() | 309 | void Parser::reduce() |
| 288 | { | 310 | { |
| 289 | if( tsParse.isEmpty() || tsParse.peek().eType == Token::tOpenParen ) | 311 | if( tsTerminal.isEmpty() || tsNonTerminal.peek().eType == Token::tOpenParen ) |
| 290 | return; | 312 | return; |
| 291 | Token tOp = tsParse.peekPop(); | 313 | Token tOp = tsTerminal.peekPop(); |
| 292 | switch( tOp.eType ) | 314 | switch( tOp.eType ) |
| 293 | { | 315 | { |
| 316 | /* | ||
| 294 | case Token::tNumber: | 317 | case Token::tNumber: |
| 295 | case Token::tVariable: | 318 | case Token::tVariable: |
| 296 | output( tOp ); | 319 | output( tOp ); |
| @@ -300,25 +323,18 @@ void Parser::reduce() | |||
| 300 | case Token::tComputedValue: | 323 | case Token::tComputedValue: |
| 301 | tsParse.push( Token( Token::tComputedValue ) ); | 324 | tsParse.push( Token( Token::tComputedValue ) ); |
| 302 | break; | 325 | break; |
| 303 | 326 | */ | |
| 304 | case Token::tPlus: | 327 | case Token::tPlus: |
| 305 | case Token::tMinus: | 328 | case Token::tMinus: |
| 306 | case Token::tDivide: | 329 | case Token::tDivide: |
| 307 | case Token::tMultiply: | 330 | case Token::tMultiply: |
| 308 | case Token::tModulus: | 331 | case Token::tModulus: |
| 309 | case Token::tEquals: | 332 | case Token::tEquals: |
| 310 | for(int j = 0; j < 2; j++ ) | ||
| 311 | { | 333 | { |
| 312 | Token t = tsParse.peekPop(); | 334 | Token a = tsNonTerminal.peekPop(); |
| 313 | if( t.eType == Token::tNumber || | 335 | Token b = tsNonTerminal.peekPop(); |
| 314 | t.eType == Token::tVariable ) | 336 | output( b ); |
| 315 | { | 337 | output( a ); |
| 316 | output( t ); | ||
| 317 | } | ||
| 318 | else if( t.eType == Token::tComputedValue ) | ||
| 319 | { | ||
| 320 | // Nope, we don't care | ||
| 321 | } | ||
| 322 | } | 338 | } |
| 323 | output( tOp ); | 339 | output( tOp ); |
| 324 | shift( Token( Token::tComputedValue ) ); | 340 | shift( Token( Token::tComputedValue ) ); |
| @@ -326,7 +342,7 @@ void Parser::reduce() | |||
| 326 | 342 | ||
| 327 | case Token::tNegate: | 343 | case Token::tNegate: |
| 328 | { | 344 | { |
| 329 | Token t = tsParse.peekPop(); | 345 | Token t = tsNonTerminal.peekPop(); |
| 330 | if( t.eType != Token::tComputedValue ) | 346 | if( t.eType != Token::tComputedValue ) |
| 331 | output( t ); | 347 | output( t ); |
| 332 | output( tOp ); | 348 | output( tOp ); |
| @@ -335,16 +351,16 @@ void Parser::reduce() | |||
| 335 | break; | 351 | break; |
| 336 | 352 | ||
| 337 | case Token::tCloseParen: | 353 | case Token::tCloseParen: |
| 338 | if( tsParse.peek().eType != Token::tComputedValue ) | 354 | if( tsNonTerminal.peek().eType != Token::tComputedValue ) |
| 339 | { | 355 | { |
| 340 | printState("paren-innerReduce-pre"); | 356 | printState("paren-innerReduce-pre"); |
| 341 | reduce(); | 357 | reduce(); |
| 342 | printState("paren-innerReduce-post"); | 358 | printState("paren-innerReduce-post"); |
| 343 | } | 359 | } |
| 344 | tsParse.pop(); | 360 | tsNonTerminal.pop(); |
| 345 | if( tsParse.peek().eType == Token::tOpenParen ) | 361 | if( tsNonTerminal.peek().eType == Token::tOpenParen ) |
| 346 | { | 362 | { |
| 347 | tsParse.pop(); | 363 | tsNonTerminal.pop(); |
| 348 | shift( Token( Token::tComputedValue ) ); | 364 | shift( Token( Token::tComputedValue ) ); |
| 349 | } | 365 | } |
| 350 | else | 366 | else |
| @@ -357,6 +373,8 @@ void Parser::reduce() | |||
| 357 | 373 | ||
| 358 | void Parser::output( const Token &t ) | 374 | void Parser::output( const Token &t ) |
| 359 | { | 375 | { |
| 376 | if( t.eType == Token::tComputedValue ) | ||
| 377 | return; | ||
| 360 | pCurExp->append( t ); | 378 | pCurExp->append( t ); |
| 361 | } | 379 | } |
| 362 | 380 | ||
| @@ -417,9 +435,16 @@ int Parser::getPriority( Token::Type eType ) | |||
| 417 | 435 | ||
| 418 | void Parser::printState( const Bu::String &sTag ) | 436 | void Parser::printState( const Bu::String &sTag ) |
| 419 | { | 437 | { |
| 438 | #ifdef DEBUG_MODE | ||
| 420 | Bu::sio << "----------------" << Bu::sio.nl; | 439 | Bu::sio << "----------------" << Bu::sio.nl; |
| 421 | Bu::sio << sTag << " stack:"; | 440 | Bu::sio << sTag << " non-terminals:"; |
| 422 | for( TokenStack::iterator i = tsParse.begin(); i; i++ ) | 441 | for( TokenStack::iterator i = tsNonTerminal.begin(); i; i++ ) |
| 442 | { | ||
| 443 | Bu::sio << " " << (*i); | ||
| 444 | } | ||
| 445 | Bu::sio << Bu::sio.nl; | ||
| 446 | Bu::sio << sTag << " terminal:"; | ||
| 447 | for( TokenStack::iterator i = tsTerminal.begin(); i; i++ ) | ||
| 423 | { | 448 | { |
| 424 | Bu::sio << " " << (*i); | 449 | Bu::sio << " " << (*i); |
| 425 | } | 450 | } |
| @@ -431,5 +456,6 @@ void Parser::printState( const Bu::String &sTag ) | |||
| 431 | } | 456 | } |
| 432 | Bu::sio << Bu::sio.nl; | 457 | Bu::sio << Bu::sio.nl; |
| 433 | Bu::sio << "----------------" << Bu::sio.nl; | 458 | Bu::sio << "----------------" << Bu::sio.nl; |
| 459 | #endif | ||
| 434 | } | 460 | } |
| 435 | 461 | ||
