From b96daa4e9849ac9caf5c0dfcea8daac28267ea19 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 1 Dec 2016 10:40:43 -0700 Subject: Scripts are executable now! The main interactive interface doesn't work, and there's a lot left to do with the unit tests, other command line options, etc. but it's pretty exciting. I also still have to figure out how commands will work. I'm thinking they'll be stored in an Expression and executed by the engine as normal. --- src/expression.cpp | 10 +++++++ src/expression.h | 16 ++++++++++ src/main.cpp | 2 +- src/options.cpp | 9 ++++-- src/parser.cpp | 65 +++++++++++++++++++++-------------------- src/parser.h | 9 +++--- src/scriptengine.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/scriptengine.h | 33 +++++++++++++++++++++ src/unitparser.cpp | 2 +- 9 files changed, 188 insertions(+), 40 deletions(-) create mode 100644 src/expression.cpp create mode 100644 src/expression.h create mode 100644 src/scriptengine.cpp create mode 100644 src/scriptengine.h (limited to 'src') diff --git a/src/expression.cpp b/src/expression.cpp new file mode 100644 index 0000000..e167ee7 --- /dev/null +++ b/src/expression.cpp @@ -0,0 +1,10 @@ +#include "expression.h" + +Expression::Expression() +{ +} + +Expression::~Expression() +{ +} + diff --git a/src/expression.h b/src/expression.h new file mode 100644 index 0000000..e78b54b --- /dev/null +++ b/src/expression.h @@ -0,0 +1,16 @@ +#ifndef EXPRESSION_H +#define EXPRESSION_H + +#include +#include "token.h" + +class Expression : public Bu::List +{ +public: + Expression(); + virtual ~Expression(); + +private: +}; + +#endif diff --git a/src/main.cpp b/src/main.cpp index 1a4ab38..667d19a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,7 +27,7 @@ int main( int argc, char *argv[] ) Lexer lex( sioRaw ); lex.setScale( opt.getScale() ); lex.setRadix( opt.getRadix() ); - Parser parser( lex, sioRaw ); + Parser parser( lex ); parser.parse(); } catch( std::exception &e ) diff --git a/src/options.cpp b/src/options.cpp index 3c016a6..672858a 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -7,6 +7,7 @@ #include "number.h" #include "lexer.h" #include "parser.h" +#include "scriptengine.h" #include #include @@ -197,9 +198,11 @@ int Options::execute( Bu::StringArray aArgs ) Lexer lex( mbIn ); lex.setScale( iScale ); lex.setRadix( iRadix ); - Parser parser( lex, mbOut ); - parser.parse(); - Bu::print( mbOut.getString() ); + Parser parser( lex ); + Expression *pExp = parser.parse(); + ScriptEngine se; + Number n = se.exec( pExp ); + Bu::println( n.toString() ); exit( 0 ); return aArgs.getSize(); } diff --git a/src/parser.cpp b/src/parser.cpp index 04a81ce..c7cf994 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3,14 +3,13 @@ #include "lexer.h" #include "number.h" #include "datafiles.h" +#include "expression.h" #include #include - -Parser::Parser( Lexer &lex, Bu::Stream &rOut ) : - lex( lex ), - rOut( rOut ) +Parser::Parser( Lexer &lex ) : + lex( lex ) { } @@ -18,22 +17,19 @@ Parser::~Parser() { } -void Parser::parse() +Expression *Parser::parse() { - for(;;) - { - lex.nextToken(); - if( lex[0].eType == Token::tEndOfInput ) - break; + pCurExp = new Expression(); + exprR(); + reduce(); - exprR(); - reduce(); + printState("Final"); - printState("Final"); + tsParse.clear(); - tsParse.clear(); - tsScript.clear(); - } + Expression *pTmp = pCurExp; + pCurExp = NULL; + return pTmp; } void Parser::exprR() @@ -44,7 +40,7 @@ void Parser::exprR() void Parser::expr() { - Bu::sio << "::expr " << lex[0] << Bu::sio.nl; + //Bu::sio << "::expr " << lex[0] << Bu::sio.nl; if( lex[0].eType == Token::tEndOfInput ) return; @@ -61,7 +57,7 @@ void Parser::expr() case Token::tModulus: Token t = lex[0]; lex.nextToken(); - Bu::sio << "->expr " << t << " " << lex[0] << Bu::sio.nl; + //Bu::sio << "->expr " << t << " " << lex[0] << Bu::sio.nl; if( lex[0].eType == Token::tOpenParen ) { exprP(); @@ -74,10 +70,10 @@ void Parser::expr() if( lex[0].eType == Token::tNumber || lex[0].eType == Token::tVariable ) { - Bu::sio << "->expr " << t << - " " << lex[0] << - " " << lex[1] << - Bu::sio.nl; + //Bu::sio << "->expr " << t << + // " " << lex[0] << + // " " << lex[1] << + // Bu::sio.nl; shift( lex[0] ); if( lex[1].eType&Token::mMetaOperator ) { @@ -115,14 +111,14 @@ void Parser::expr() else if( lex[0].eType == Token::tMinus ) { // This is negation - Bu::sio << "next token: " << lex[0] << Bu::sio.nl; + //Bu::sio << "next token: " << lex[0] << Bu::sio.nl; printState("inline-negate"); exprP(); printState("inline-negate-post"); shift( t ); printState("inline-negate-post2"); - Bu::sio << "??? " << lex[0] << Bu::sio.nl; + //Bu::sio << "??? " << lex[0] << Bu::sio.nl; } } break; @@ -161,7 +157,7 @@ void Parser::exprP() exprR(); if( lex[0].eType != Token::tCloseParen ) { - Bu::sio << "::exprP " << lex[0] << Bu::sio.nl; + //Bu::sio << "::exprP " << lex[0] << Bu::sio.nl; throw Bu::ExceptionBase("Expected close paren"); } shift( lex[0] ); @@ -283,7 +279,7 @@ void Parser::reduce() { case Token::tNumber: case Token::tVariable: - tsScript.append( tOp ); + output( tOp ); tsParse.push( Token( Token::tComputedValue ) ); break; @@ -303,14 +299,14 @@ void Parser::reduce() if( t.eType == Token::tNumber || t.eType == Token::tVariable ) { - tsScript.append( t ); + output( t ); } else if( t.eType == Token::tComputedValue ) { // Nope, we don't care } } - tsScript.append( tOp ); + output( tOp ); shift( Token( Token::tComputedValue ) ); break; @@ -318,8 +314,8 @@ void Parser::reduce() { Token t = tsParse.peekPop(); if( t.eType != Token::tComputedValue ) - tsScript.append( t ); - tsScript.append( tOp ); + output( t ); + output( tOp ); shift( Token( Token::tComputedValue ) ); } break; @@ -345,6 +341,11 @@ void Parser::reduce() } } +void Parser::output( const Token &t ) +{ + pCurExp->append( t ); +} + int Parser::reqTokens( Token::Type eType ) { switch( eType ) @@ -402,6 +403,7 @@ 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++ ) @@ -410,11 +412,12 @@ void Parser::printState( const Bu::String &sTag ) } Bu::sio << Bu::sio.nl; Bu::sio << sTag << " script:"; - for( TokenStack::iterator i = tsScript.begin(); i; i++ ) + for( TokenStack::iterator i = pCurExp->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 b0a1231..1e0d1c4 100644 --- a/src/parser.h +++ b/src/parser.h @@ -12,6 +12,7 @@ namespace Bu }; class Lexer; +class Expression; /** * @@ -45,10 +46,10 @@ class Lexer; class Parser { public: - Parser( Lexer &lex, Bu::Stream &rOut ); + Parser( Lexer &lex ); virtual ~Parser(); - void parse(); + Expression *parse(); private: void expr(); @@ -58,6 +59,7 @@ private: private: void shift( const Token &t ); void reduce(); + void output( const Token &t ); int reqTokens( Token::Type eType ); int getPriority( Token::Type eType ); @@ -65,10 +67,9 @@ private: private: Lexer &lex; - Bu::Stream &rOut; typedef Bu::List TokenStack; TokenStack tsParse; - TokenStack tsScript; + Expression *pCurExp; }; #endif diff --git a/src/scriptengine.cpp b/src/scriptengine.cpp new file mode 100644 index 0000000..7b5df03 --- /dev/null +++ b/src/scriptengine.cpp @@ -0,0 +1,82 @@ +#include "scriptengine.h" +#include "lexer.h" +#include "parser.h" +#include "expression.h" + +#include +#include + +ScriptEngine::ScriptEngine() +{ +} + +ScriptEngine::~ScriptEngine() +{ +} + +Number ScriptEngine::exec( const Bu::String &sExpr ) +{ + Bu::StaticMemBuf mb( sExpr.getStr(), sExpr.getSize() ); + return exec( sExpr ); +} + +Number ScriptEngine::exec( Bu::Stream &sInput ) +{ + Lexer l( sInput ); + Parser p( l ); + Expression *pExp = p.parse(); + Number n = exec( pExp ); + delete pExp; + return n; +} + +Number ScriptEngine::exec( Expression *pExpr ) +{ + NumStack sNums; + + for( Expression::iterator i = pExpr->begin(); i; i++ ) + { + switch( (*i).eType ) + { + case Token::tNumber: + sNums.push( *(*i).nVal ); + break; + + case Token::tVariable: + if( hVarState.has( *(*i).sVal ) ) + { + sNums.push( hVarState[*(*i).sVal] ); + } + else + { + throw Bu::ExceptionBase( + Bu::String("No such variable: $%1").arg(*(*i).sVal).end().getStr() + ); + } + break; + + case Token::tPlus: + sNums.push( sNums.peekPop() + sNums.peekPop() ); + break; + + case Token::tMinus: + sNums.push( sNums.peekPop() - sNums.peekPop() ); + break; + + case Token::tDivide: + sNums.push( sNums.peekPop() / sNums.peekPop() ); + break; + + case Token::tMultiply: + sNums.push( sNums.peekPop() * sNums.peekPop() ); + break; + + case Token::tNegate: + sNums.push( -sNums.peekPop() ); + break; + } + } + + return sNums.peekPop(); +} + diff --git a/src/scriptengine.h b/src/scriptengine.h new file mode 100644 index 0000000..74924d6 --- /dev/null +++ b/src/scriptengine.h @@ -0,0 +1,33 @@ +#ifndef SCRIPT_ENGINE_H +#define SCRIPT_ENGINE_H + +#include "number.h" + +#include +#include +#include + + +namespace Bu +{ + class Stream; +} +class Expression; + +class ScriptEngine +{ +public: + ScriptEngine(); + virtual ~ScriptEngine(); + + Number exec( const Bu::String &sExpr ); + Number exec( Bu::Stream &sInput ); + Number exec( Expression *pExpr ); + +private: + typedef Bu::Hash VarHash; + typedef Bu::List NumStack; + VarHash hVarState; +}; + +#endif diff --git a/src/unitparser.cpp b/src/unitparser.cpp index a894647..01a4f80 100644 --- a/src/unitparser.cpp +++ b/src/unitparser.cpp @@ -53,7 +53,7 @@ void UnitParser::assignment() Bu::MemBuf mbOut; Lexer lex( mbIn ); lex.setScale( 0 ); - Parser parser( lex, mbOut ); + Parser parser( lex ); parser.parse(); // Bu::println("%1 == %2").arg( mbOut.getString().trimWhitespace() ) // .arg( parser.getVariable("test") ); -- cgit v1.2.3