From 3015ea4677201060777435cf76815e898d221f8c Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 1 Dec 2016 09:31:45 -0700 Subject: The parser works. There's still more to do, however. It doesn't do math anymore, it produces a script that can then be executed. Now we have to capture that script and execute it. --- src/parser.cpp | 213 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 177 insertions(+), 36 deletions(-) (limited to 'src/parser.cpp') diff --git a/src/parser.cpp b/src/parser.cpp index 510b471..f88ffe7 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -26,49 +26,34 @@ void Parser::parse() if( lex[0].eType == Token::tEndOfInput ) break; - expr(); + exprR(); + reduce(); - Bu::sio << "Final stack:"; - for( TokenStack::iterator i = tsParse.begin(); i; i++ ) - { - Bu::sio << " " << (*i).eType; - if( (*i).eType == Token::tNumber ) - { - Bu::sio << "(" << (*i).nVal->toString() << ")"; - } - } - Bu::sio << Bu::sio.nl; - Bu::sio << "Script:"; - for( TokenStack::iterator i = tsScript.begin(); i; i++ ) - { - Bu::sio << " " << (*i).eType; - if( (*i).eType == Token::tNumber ) - { - Bu::sio << "(" << (*i).nVal->toString() << ")"; - } - } - Bu::sio << Bu::sio.nl; + printState("Final"); + + tsParse.clear(); + tsScript.clear(); } } +void Parser::exprR() +{ + exprP(); + expr(); +} + void Parser::expr() { + Bu::sio << "::expr " << lex[0] << Bu::sio.nl; if( lex[0].eType == Token::tEndOfInput ) return; - if( lex[0].eType == Token::tVariable && - lex[1].eType == Token::tEquals ) - { - Token t = lex[0]; - lex.nextToken(); - lex.nextToken(); - expr(); - - return; - } - exprP(); switch( lex[0].eType ) { + case Token::tEquals: + throw Bu::ExceptionBase("misplaced equals."); + break; + case Token::tPlus: case Token::tMinus: case Token::tMultiply: @@ -76,30 +61,111 @@ void Parser::expr() case Token::tModulus: Token t = lex[0]; lex.nextToken(); - expr(); - shift( t ); + Bu::sio << "->expr " << t << " " << lex[0] << Bu::sio.nl; + if( lex[0].eType == Token::tOpenParen ) + { + exprP(); + shift( t ); + reduce(); + expr(); + } + else + { + if( lex[0].eType == Token::tNumber || + lex[0].eType == Token::tVariable ) + { + Bu::sio << "->expr " << t << + " " << lex[0] << + " " << lex[1] << + Bu::sio.nl; + shift( lex[0] ); + if( lex[1].eType == Token::tPlus || + lex[1].eType == Token::tMinus || + lex[1].eType == Token::tDivide || + lex[1].eType == Token::tMultiply || + lex[1].eType == Token::tModulus || + lex[1].eType == Token::tEquals ) + { + if( getPriority(lex[1].eType) <= + getPriority(t.eType) ) + { + shift( t ); + reduce(); + printState("reduce"); + lex.nextToken(); + expr(); + } + else + { + printState("no reduce"); + lex.nextToken(); + expr(); + if( !tsParse.isEmpty() && + tsParse.peek().eType != Token::tComputedValue ) + { + reduce(); + printState("no reduce reduce"); + } + shift( t ); + printState("post no reduce"); + } + } + else + { + shift( t ); + lex.nextToken(); + printState("no next op"); + } + } + else + { + Bu::println("???"); + } + } break; } } void Parser::exprP() { + if( lex[0].eType == Token::tVariable && + lex[1].eType == Token::tEquals ) + { + Token t = lex[0]; + lex.nextToken( 2 ); + exprR(); + reduce(); + printState("pre-equals"); + shift( t ); + shift( Token( Token::tEquals ) ); + printState("post-equals"); + reduce(); + printState("post-equals-reduce"); + return; + } + switch( lex[0].eType ) { case Token::tNumber: case Token::tVariable: - shift( lex[0] ); + shift( lex[0] ); lex.nextToken(); break; case Token::tOpenParen: + shift( lex[0] ); lex.nextToken(); - expr(); + exprR(); if( lex[0].eType != Token::tCloseParen ) { + Bu::sio << "::exprP " << lex[0] << Bu::sio.nl; throw Bu::ExceptionBase("Expected close paren"); } + shift( lex[0] ); + printState("closeParen"); + reduce(); lex.nextToken(); + printState("post closeParen"); break; case Token::tMinus: @@ -206,6 +272,63 @@ void Parser::shift( const Token &t ) void Parser::reduce() { + if( tsParse.isEmpty() || tsParse.peek().eType == Token::tOpenParen ) + return; + Token tOp = tsParse.peekPop(); + switch( tOp.eType ) + { + case Token::tNumber: + case Token::tVariable: + tsScript.append( tOp ); + tsParse.push( Token( Token::tComputedValue ) ); + break; + + case Token::tComputedValue: + tsParse.push( Token( Token::tComputedValue ) ); + break; + + case Token::tPlus: + case Token::tMinus: + case Token::tDivide: + case Token::tMultiply: + case Token::tModulus: + case Token::tEquals: + for(int j = 0; j < 2; j++ ) + { + Token t = tsParse.peekPop(); + if( t.eType == Token::tNumber || + t.eType == Token::tVariable ) + { + tsScript.append( t ); + } + else if( t.eType == Token::tComputedValue ) + { + // Nope, we don't care + } + } + tsScript.append( tOp ); + shift( Token( Token::tComputedValue ) ); + break; + + case Token::tCloseParen: + if( tsParse.peek().eType != Token::tComputedValue ) + { + printState("paren-innerReduce-pre"); + reduce(); + printState("paren-innerReduce-post"); + } + tsParse.pop(); + if( tsParse.peek().eType == Token::tOpenParen ) + { + tsParse.pop(); + shift( Token( Token::tComputedValue ) ); + } + else + { + throw Bu::ExceptionBase("Error?"); + } + break; + } } int Parser::reqTokens( Token::Type eType ) @@ -263,3 +386,21 @@ int Parser::getPriority( Token::Type eType ) } } +void Parser::printState( const Bu::String &sTag ) +{ + Bu::sio << "----------------" << Bu::sio.nl; + Bu::sio << sTag << " stack:"; + for( TokenStack::iterator i = tsParse.begin(); i; i++ ) + { + Bu::sio << " " << (*i); + } + Bu::sio << Bu::sio.nl; + Bu::sio << sTag << " script:"; + for( TokenStack::iterator i = tsScript.begin(); i; i++ ) + { + Bu::sio << " " << (*i); + } + Bu::sio << Bu::sio.nl; + Bu::sio << "----------------" << Bu::sio.nl; +} + -- cgit v1.2.3