From 50c6956d99b4ee2cf3d003e5918e84b9d1a08f1b Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 1 Dec 2016 07:22:35 -0700 Subject: New layout for the parser, it doesn't parse yet. --- src/lexer.cpp | 8 +- src/lexer.h | 2 +- src/parser.cpp | 406 ++++++++++++++------------------------------------------- src/parser.h | 10 +- src/token.cpp | 1 + 5 files changed, 106 insertions(+), 321 deletions(-) (limited to 'src') diff --git a/src/lexer.cpp b/src/lexer.cpp index 55d155d..538e088 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -24,17 +24,17 @@ Lexer::~Lexer() { } -void Lexer::nextToken() +void Lexer::nextToken( int iCount ) { - if( iLookAheadUsed <= 1 ) + if( iLookAheadUsed-iCount <= 0 ) { iLookAheadUsed = 0; iLookAheadStart = 0; } else { - iLookAheadStart = (iLookAheadStart+1)%iLookAheadSize; - iLookAheadUsed--; + iLookAheadStart = (iLookAheadStart+iCount)%iLookAheadSize; + iLookAheadUsed -= iCount; } } diff --git a/src/lexer.h b/src/lexer.h index 193a22b..1d6ddcb 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -20,7 +20,7 @@ public: void setMode( Mode e ) { eMode = e; } Mode getMode() const { return eMode; } - void nextToken(); + void nextToken( int iCount=1 ); int getScale() const { return iScale; } void setScale( int i ) { iScale = i; } 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() expr(); Bu::sio << "Final stack:"; - for( TokenStack::iterator i = tsStack.begin(); i; i++ ) + 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 ) @@ -67,7 +77,7 @@ void Parser::expr() Token t = lex[0]; lex.nextToken(); expr(); - tsStack.push( t ); + shift( t ); break; } } @@ -78,7 +88,7 @@ void Parser::exprP() { case Token::tNumber: case Token::tVariable: - tsStack.push( lex[0] ); + shift( lex[0] ); lex.nextToken(); break; @@ -95,306 +105,107 @@ void Parser::exprP() case Token::tMinus: lex.nextToken(); exprP(); - tsStack.push( Token( Token::tNegate ) ); + shift( Token( Token::tNegate ) ); break; } } /* - for(;;) +case Token::tCommand: + lex.setMode( Lexer::modeCommand ); + if( *t.sVal == "exit" || *t.sVal == "quit" ) + return; + else if( *t.sVal == "scale" ) { - Token t = lex.nextToken(); - switch( t.eType ) + Token t2 = lex.nextToken(); + if( t2.eType == Token::tEndOfLine ) { - case Token::tEndOfInput: - while( !tsNonTerminal.isEmpty() ) - unwind(); - return; - - case Token::tEndOfLine: - while( !tsNonTerminal.isEmpty() ) - unwind(); - if( !tsTerminal.isEmpty() ) - { - Bu::println( rOut, "%1").arg( deref( tsTerminal.peek() ) ); - hVars.insert("ans", deref( tsTerminal.peek() ) ); - } - tsTerminal.clear(); - lex.setMode( Lexer::modeNormal ); - break; - - case Token::tCommand: - lex.setMode( Lexer::modeCommand ); - if( *t.sVal == "exit" || *t.sVal == "quit" ) - return; - else if( *t.sVal == "scale" ) - { - Token t2 = lex.nextToken(); - if( t2.eType == Token::tEndOfLine ) - { - Bu::println( rOut, "Current scale: %1"). - arg( lex.getScale() ); - } - else if( t2.eType == Token::tString ) - { - int32_t i = strtol( t2.sVal->getStr(), 0, 10 ); - lex.setScale( i ); - if( i < 0 ) - { - Bu::println( rOut, "ERROR: You must provide a " - "positive integer or zero as the parameter " - "to scale."); - } - else - { - Bu::println( rOut, "Scale changed to: %1"). - arg( lex.getScale() ); - for( VarHash::iterator i = hVars.begin(); i; i++ ) - (*i).setScale( lex.getScale() ); - nZero = Number( lex.getScale(), lex.getRadix() ); - } - } - else - { - Bu::println( rOut, "ERROR: You must provide a number " - "as the parameter to scale."); - } - } - else if( *t.sVal == "radix" ) - { - Token t2 = lex.nextToken(); - if( t2.eType == Token::tEndOfLine ) - { - Bu::println( rOut, "Current radix: %1"). - arg( lex.getRadix() ); - } - else if( t2.eType == Token::tString ) - { - int32_t i = strtol( t2.sVal->getStr(), 0, 10 ); - if( i < 2 || i > 36 ) - Bu::println( rOut, "ERROR: Radix must be between " - "2 and 36 inclusive"); - else - { - lex.setRadix( i ); - Bu::println( rOut, "Radix changed to: %1"). - arg( lex.getRadix() ); - hVars.clear(); - nZero = Number( lex.getScale(), lex.getRadix() ); - } - } - else - { - Bu::println( rOut, "You must provide a number as " - "the parameter to radix."); - } - } - else if( *t.sVal == "vars" ) - { - Bu::println( rOut, "Declared variables:"); - for( VarHash::iterator i = hVars.begin(); i; i++ ) - { - Bu::println( rOut, " - %1 = %2"). - arg( i.getKey() ).arg( *i ); - } - Bu::println( rOut, ""); - } - else if( *t.sVal == "help" || *t.sVal == "h" || *t.sVal == "?" ) - { - Bu::println( rOut, Datafiles::getString("parserhelp.txt") ); - } - else - { - Bu::println( rOut, "ERROR: Unknown command '%1'"). - arg( *t.sVal ); - } - lex.setMode( Lexer::modeNormal ); - break; - - case Token::tNumber: - case Token::tVariable: - tsTerminal.push( t ); - break; - - default: - if( tsNonTerminal.getSize() == 0 || - getPriority( tsNonTerminal.peek().eType ) < - getPriority( t.eType ) ) - { - DBS( PARSE, - Bu::println("Pushing non-terminal: %1").arg( t.eType ) - ); - tsNonTerminal.push( t ); - } - else - { - DBS( PARSE, - Bu::println("Unwinding stack before pushing: %1") - .arg( t.eType ) - ); - unwind(); - tsNonTerminal.push( t ); - } - break; + Bu::println( rOut, "Current scale: %1"). + arg( lex.getScale() ); + } + else if( t2.eType == Token::tString ) + { + int32_t i = strtol( t2.sVal->getStr(), 0, 10 ); + lex.setScale( i ); + if( i < 0 ) + { + Bu::println( rOut, "ERROR: You must provide a " + "positive integer or zero as the parameter " + "to scale."); + } + else + { + Bu::println( rOut, "Scale changed to: %1"). + arg( lex.getScale() ); + for( VarHash::iterator i = hVars.begin(); i; i++ ) + (*i).setScale( lex.getScale() ); + nZero = Number( lex.getScale(), lex.getRadix() ); + } + } + else + { + Bu::println( rOut, "ERROR: You must provide a number " + "as the parameter to scale."); } } -} -*/ - -Number Parser::getVariable( const Bu::String &sName ) -{ - return hVars.get( sName ); -} - -void Parser::setVariable( const Bu::String &sName, const Number &rValue ) -{ - hVars.insert( sName, rValue ); -} - -void Parser::reduce() -{ - /* - for(;;) + else if( *t.sVal == "radix" ) { - DBS_START( PARSE ); - for( TokenStack::iterator i = tsTerminal.begin(); i; i++ ) + Token t2 = lex.nextToken(); + if( t2.eType == Token::tEndOfLine ) { - if( (*i).eType == Token::tNumber ) - Bu::print(" [%1]").arg( *(*i).nVal ); + Bu::println( rOut, "Current radix: %1"). + arg( lex.getRadix() ); + } + else if( t2.eType == Token::tString ) + { + int32_t i = strtol( t2.sVal->getStr(), 0, 10 ); + if( i < 2 || i > 36 ) + Bu::println( rOut, "ERROR: Radix must be between " + "2 and 36 inclusive"); else - Bu::print(" [%1]").arg( *(*i).sVal ); + { + lex.setRadix( i ); + Bu::println( rOut, "Radix changed to: %1"). + arg( lex.getRadix() ); + hVars.clear(); + nZero = Number( lex.getScale(), lex.getRadix() ); + } } - Bu::println(""); - for( TokenStack::iterator i = tsNonTerminal.begin(); i; i++ ) - Bu::print(" <%1>").arg( (*i).eType ); - Bu::println(""); - DBS_END(); - - if( tsNonTerminal.isEmpty() ) - return; - - if( tsTerminal.getSize() < reqTokens( tsNonTerminal.peek().eType ) ) + else { - return; + Bu::println( rOut, "You must provide a number as " + "the parameter to radix."); } - - Token t = tsNonTerminal.peekPop(); - switch( t.eType ) + } + else if( *t.sVal == "vars" ) + { + Bu::println( rOut, "Declared variables:"); + for( VarHash::iterator i = hVars.begin(); i; i++ ) { - case Token::tPlus: - { - Token b = tsTerminal.peekPop(); - Token a = tsTerminal.peekPop(); - tsTerminal.push( - Token( Token::tNumber, - new Number( deref(a) + deref(b) ) - ) - ); - } - break; - - case Token::tMinus: - { - Token b = tsTerminal.peekPop(); - Token a = tsTerminal.peekPop(); - tsTerminal.push( - Token( Token::tNumber, - new Number( deref(a) - deref(b) ) - ) - ); - } - break; - - case Token::tMultiply: - { - Token b = tsTerminal.peekPop(); - Token a = tsTerminal.peekPop(); - Number *pProduct = new Number( deref(a) * deref(b) ); - pProduct->setScale( lex.getScale() ); - tsTerminal.push( - Token( Token::tNumber, - pProduct - ) - ); - } - break; - - case Token::tDivide: - { - Token b = tsTerminal.peekPop(); - Token a = tsTerminal.peekPop(); - tsTerminal.push( - Token( Token::tNumber, - new Number( deref(a) / deref(b) ) - ) - ); - } - break; - - case Token::tModulus: - { - Token b = tsTerminal.peekPop(); - Token a = tsTerminal.peekPop(); - tsTerminal.push( - Token( Token::tNumber, - new Number( deref(a) % deref(b) ) - ) - ); - } - break; - - case Token::tOpenParen: - tsNonTerminal.push( t ); - return; - - case Token::tCloseParen: - unwind(); - if( tsNonTerminal.peek().eType == Token::tOpenParen ) - { - - tsNonTerminal.pop(); - unwind(); - } - else - { - throw Bu::ExceptionBase("Close paren found without open paren."); - } - break; - - case Token::tEquals: - { - Token b = tsTerminal.peekPop(); - Token a = tsTerminal.peekPop(); - if( a.eType != Token::tVariable ) - { - Bu::println("The left hand side of a = must be a variable."); - tsTerminal.clear(); - tsNonTerminal.clear(); - return; - } - hVars.insert( *a.sVal, deref( b ) ); - tsTerminal.push( - Token( Token::tNumber, - new Number( deref( b ) ) - ) - ); - } - break; - - case Token::tNumber: - case Token::tVariable: - case Token::tCommand: - case Token::tString: - case Token::tEndOfLine: - case Token::tEndOfInput: - // These should never show up at all - break; + Bu::println( rOut, " - %1 = %2"). + arg( i.getKey() ).arg( *i ); } - if( !tsNonTerminal.isEmpty() && - getPriority( tsNonTerminal.peek().eType ) < - getPriority( t.eType ) ) - return; + Bu::println( rOut, ""); + } + else if( *t.sVal == "help" || *t.sVal == "h" || *t.sVal == "?" ) + { + Bu::println( rOut, Datafiles::getString("parserhelp.txt") ); } - */ + else + { + Bu::println( rOut, "ERROR: Unknown command '%1'"). + arg( *t.sVal ); + } + lex.setMode( Lexer::modeNormal ); + break; +*/ + +void Parser::shift( const Token &t ) +{ + tsParse.push( t ); +} + +void Parser::reduce() +{ } int Parser::reqTokens( Token::Type eType ) @@ -452,26 +263,3 @@ int Parser::getPriority( Token::Type eType ) } } -Number &Parser::deref( Token &t ) -{ - if( t.eType == Token::tNumber ) - { - return *t.nVal; - } - else if( t.eType == Token::tVariable ) - { - try - { - return hVars.get( *t.sVal ); - } - catch(...) - { - return nZero; - } - } - else - { - throw Bu::ExceptionBase("Element was not a number or variable."); - } -} - diff --git a/src/parser.h b/src/parser.h index 05fab0b..1caa229 100644 --- a/src/parser.h +++ b/src/parser.h @@ -49,14 +49,13 @@ public: virtual ~Parser(); void parse(); - Number getVariable( const Bu::String &sName ); - void setVariable( const Bu::String &sName, const Number &rValue ); private: void expr(); void exprP(); private: + void shift( const Token &t ); void reduce(); int reqTokens( Token::Type eType ); int getPriority( Token::Type eType ); @@ -66,11 +65,8 @@ private: Lexer &lex; Bu::Stream &rOut; typedef Bu::List TokenStack; - typedef Bu::Hash VarHash; - TokenStack tsStack; -// TokenStack tsNonTerminal; - Number nZero; - VarHash hVars; + TokenStack tsParse; + TokenStack tsScript; }; #endif diff --git a/src/token.cpp b/src/token.cpp index c591e6a..1eaa92a 100644 --- a/src/token.cpp +++ b/src/token.cpp @@ -99,6 +99,7 @@ Bu::Formatter &operator<<( Bu::Formatter &f, Token::Type eType ) case Token::tString: return f << "str"; case Token::tEndOfLine: return f << "eol"; case Token::tEndOfInput: return f << "eoi"; + case Token::tNegate: return f << "neg"; default: return f << "???"; } -- cgit v1.2.3