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/lexer.cpp | 24 ++----- src/parser.cpp | 213 +++++++++++++++++++++++++++++++++++++++++++++++---------- src/parser.h | 4 +- src/token.cpp | 12 ++++ src/token.h | 4 +- 5 files changed, 201 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/lexer.cpp b/src/lexer.cpp index 538e088..87d603a 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -6,7 +6,7 @@ Lexer::Lexer( Bu::Stream &rIn ) : rIn( rIn ), - iBufPos( 0 ), + iBufPos( -1 ), iScale( 0 ), iRadix( 10 ), numRangeTop('9'), @@ -55,28 +55,12 @@ void Lexer::fillToken() default: throw Bu::ExceptionBase("Invalid mode."); } -/* - Bu::sio << "read[" - << ((iLookAheadUsed+iLookAheadStart)%iLookAheadSize) - << "]: " - << aLookAhead[(iLookAheadUsed+iLookAheadStart)%iLookAheadSize].eType; - if( aLookAhead[(iLookAheadUsed+iLookAheadStart)%iLookAheadSize].eType == Token::tNumber ) - Bu::sio << "(" - << aLookAhead[(iLookAheadUsed+iLookAheadStart)%iLookAheadSize].nVal->toString() << ")"; - Bu::sio << Bu::sio.nl; -*/ } Token Lexer::nextTokenNormal() { for(;;) { - if( iBufPos >= sBuf.getSize() ) - { - iBufPos = -1; - return Token( Token::tEndOfLine ); - } - if( iBufPos < 0 ) { if( rIn.isEos() ) @@ -90,8 +74,12 @@ Token Lexer::nextTokenNormal() } iBufPos = 0; } + if( iBufPos >= sBuf.getSize() ) + { + iBufPos = -1; + return Token( Token::tEndOfLine ); + } - //Bu::println("Testing char '%1' at %2").arg( sBuf[iBufPos] ).arg( iBufPos ); switch( sBuf[iBufPos] ) { case ' ': 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; +} + diff --git a/src/parser.h b/src/parser.h index 1caa229..b0a1231 100644 --- a/src/parser.h +++ b/src/parser.h @@ -53,13 +53,15 @@ public: private: void expr(); void exprP(); + void exprR(); private: void shift( const Token &t ); void reduce(); int reqTokens( Token::Type eType ); int getPriority( Token::Type eType ); - Number &deref( Token &t ); + + void printState( const Bu::String &sTag ); private: Lexer &lex; diff --git a/src/token.cpp b/src/token.cpp index 1eaa92a..0c7bda1 100644 --- a/src/token.cpp +++ b/src/token.cpp @@ -100,8 +100,20 @@ Bu::Formatter &operator<<( Bu::Formatter &f, Token::Type eType ) case Token::tEndOfLine: return f << "eol"; case Token::tEndOfInput: return f << "eoi"; case Token::tNegate: return f << "neg"; + case Token::tUninitialized: return f << "<->"; + case Token::tComputedValue: return f << "cmp"; default: return f << "???"; } } +Bu::Formatter &operator<<( Bu::Formatter &f, const Token &t ) +{ + f << t.eType; + if( t.eType == Token::tNumber ) + f << "(" << (t.nVal?t.nVal->toString():"") << ")"; + else if( t.eType == Token::tString || t.eType == Token::tVariable ) + f << "(" << (t.sVal?*(t.sVal):"") << ")"; + return f; +} + diff --git a/src/token.h b/src/token.h index 8d7dc20..072a96b 100644 --- a/src/token.h +++ b/src/token.h @@ -31,7 +31,8 @@ public: tEndOfInput, - tUninitialized + tUninitialized, + tComputedValue }; Token(); @@ -52,5 +53,6 @@ public: }; Bu::Formatter &operator<<( Bu::Formatter &f, Token::Type eType ); +Bu::Formatter &operator<<( Bu::Formatter &f, const Token &t ); #endif -- cgit v1.2.3