diff options
| -rw-r--r-- | src/expression.cpp | 10 | ||||
| -rw-r--r-- | src/expression.h | 16 | ||||
| -rw-r--r-- | src/main.cpp | 2 | ||||
| -rw-r--r-- | src/options.cpp | 9 | ||||
| -rw-r--r-- | src/parser.cpp | 65 | ||||
| -rw-r--r-- | src/parser.h | 9 | ||||
| -rw-r--r-- | src/scriptengine.cpp | 82 | ||||
| -rw-r--r-- | src/scriptengine.h | 33 | ||||
| -rw-r--r-- | src/unitparser.cpp | 2 |
9 files changed, 188 insertions, 40 deletions
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 @@ | |||
| 1 | #include "expression.h" | ||
| 2 | |||
| 3 | Expression::Expression() | ||
| 4 | { | ||
| 5 | } | ||
| 6 | |||
| 7 | Expression::~Expression() | ||
| 8 | { | ||
| 9 | } | ||
| 10 | |||
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 @@ | |||
| 1 | #ifndef EXPRESSION_H | ||
| 2 | #define EXPRESSION_H | ||
| 3 | |||
| 4 | #include <bu/list.h> | ||
| 5 | #include "token.h" | ||
| 6 | |||
| 7 | class Expression : public Bu::List<Token> | ||
| 8 | { | ||
| 9 | public: | ||
| 10 | Expression(); | ||
| 11 | virtual ~Expression(); | ||
| 12 | |||
| 13 | private: | ||
| 14 | }; | ||
| 15 | |||
| 16 | #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[] ) | |||
| 27 | Lexer lex( sioRaw ); | 27 | Lexer lex( sioRaw ); |
| 28 | lex.setScale( opt.getScale() ); | 28 | lex.setScale( opt.getScale() ); |
| 29 | lex.setRadix( opt.getRadix() ); | 29 | lex.setRadix( opt.getRadix() ); |
| 30 | Parser parser( lex, sioRaw ); | 30 | Parser parser( lex ); |
| 31 | parser.parse(); | 31 | parser.parse(); |
| 32 | } | 32 | } |
| 33 | catch( std::exception &e ) | 33 | 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 @@ | |||
| 7 | #include "number.h" | 7 | #include "number.h" |
| 8 | #include "lexer.h" | 8 | #include "lexer.h" |
| 9 | #include "parser.h" | 9 | #include "parser.h" |
| 10 | #include "scriptengine.h" | ||
| 10 | 11 | ||
| 11 | #include <bu/streamstack.h> | 12 | #include <bu/streamstack.h> |
| 12 | #include <bu/sio.h> | 13 | #include <bu/sio.h> |
| @@ -197,9 +198,11 @@ int Options::execute( Bu::StringArray aArgs ) | |||
| 197 | Lexer lex( mbIn ); | 198 | Lexer lex( mbIn ); |
| 198 | lex.setScale( iScale ); | 199 | lex.setScale( iScale ); |
| 199 | lex.setRadix( iRadix ); | 200 | lex.setRadix( iRadix ); |
| 200 | Parser parser( lex, mbOut ); | 201 | Parser parser( lex ); |
| 201 | parser.parse(); | 202 | Expression *pExp = parser.parse(); |
| 202 | Bu::print( mbOut.getString() ); | 203 | ScriptEngine se; |
| 204 | Number n = se.exec( pExp ); | ||
| 205 | Bu::println( n.toString() ); | ||
| 203 | exit( 0 ); | 206 | exit( 0 ); |
| 204 | return aArgs.getSize(); | 207 | return aArgs.getSize(); |
| 205 | } | 208 | } |
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 @@ | |||
| 3 | #include "lexer.h" | 3 | #include "lexer.h" |
| 4 | #include "number.h" | 4 | #include "number.h" |
| 5 | #include "datafiles.h" | 5 | #include "datafiles.h" |
| 6 | #include "expression.h" | ||
| 6 | 7 | ||
| 7 | #include <bu/sio.h> | 8 | #include <bu/sio.h> |
| 8 | #include <stdlib.h> | 9 | #include <stdlib.h> |
| 9 | 10 | ||
| 10 | 11 | Parser::Parser( Lexer &lex ) : | |
| 11 | Parser::Parser( Lexer &lex, Bu::Stream &rOut ) : | 12 | lex( lex ) |
| 12 | lex( lex ), | ||
| 13 | rOut( rOut ) | ||
| 14 | { | 13 | { |
| 15 | } | 14 | } |
| 16 | 15 | ||
| @@ -18,22 +17,19 @@ Parser::~Parser() | |||
| 18 | { | 17 | { |
| 19 | } | 18 | } |
| 20 | 19 | ||
| 21 | void Parser::parse() | 20 | Expression *Parser::parse() |
| 22 | { | 21 | { |
| 23 | for(;;) | 22 | pCurExp = new Expression(); |
| 24 | { | 23 | exprR(); |
| 25 | lex.nextToken(); | 24 | reduce(); |
| 26 | if( lex[0].eType == Token::tEndOfInput ) | ||
| 27 | break; | ||
| 28 | 25 | ||
| 29 | exprR(); | 26 | printState("Final"); |
| 30 | reduce(); | ||
| 31 | 27 | ||
| 32 | printState("Final"); | 28 | tsParse.clear(); |
| 33 | 29 | ||
| 34 | tsParse.clear(); | 30 | Expression *pTmp = pCurExp; |
| 35 | tsScript.clear(); | 31 | pCurExp = NULL; |
| 36 | } | 32 | return pTmp; |
| 37 | } | 33 | } |
| 38 | 34 | ||
| 39 | void Parser::exprR() | 35 | void Parser::exprR() |
| @@ -44,7 +40,7 @@ void Parser::exprR() | |||
| 44 | 40 | ||
| 45 | void Parser::expr() | 41 | void Parser::expr() |
| 46 | { | 42 | { |
| 47 | Bu::sio << "::expr " << lex[0] << Bu::sio.nl; | 43 | //Bu::sio << "::expr " << lex[0] << Bu::sio.nl; |
| 48 | if( lex[0].eType == Token::tEndOfInput ) | 44 | if( lex[0].eType == Token::tEndOfInput ) |
| 49 | return; | 45 | return; |
| 50 | 46 | ||
| @@ -61,7 +57,7 @@ void Parser::expr() | |||
| 61 | case Token::tModulus: | 57 | case Token::tModulus: |
| 62 | Token t = lex[0]; | 58 | Token t = lex[0]; |
| 63 | lex.nextToken(); | 59 | lex.nextToken(); |
| 64 | Bu::sio << "->expr " << t << " " << lex[0] << Bu::sio.nl; | 60 | //Bu::sio << "->expr " << t << " " << lex[0] << Bu::sio.nl; |
| 65 | if( lex[0].eType == Token::tOpenParen ) | 61 | if( lex[0].eType == Token::tOpenParen ) |
| 66 | { | 62 | { |
| 67 | exprP(); | 63 | exprP(); |
| @@ -74,10 +70,10 @@ void Parser::expr() | |||
| 74 | if( lex[0].eType == Token::tNumber || | 70 | if( lex[0].eType == Token::tNumber || |
| 75 | lex[0].eType == Token::tVariable ) | 71 | lex[0].eType == Token::tVariable ) |
| 76 | { | 72 | { |
| 77 | Bu::sio << "->expr " << t << | 73 | //Bu::sio << "->expr " << t << |
| 78 | " " << lex[0] << | 74 | // " " << lex[0] << |
| 79 | " " << lex[1] << | 75 | // " " << lex[1] << |
| 80 | Bu::sio.nl; | 76 | // Bu::sio.nl; |
| 81 | shift( lex[0] ); | 77 | shift( lex[0] ); |
| 82 | if( lex[1].eType&Token::mMetaOperator ) | 78 | if( lex[1].eType&Token::mMetaOperator ) |
| 83 | { | 79 | { |
| @@ -115,14 +111,14 @@ void Parser::expr() | |||
| 115 | else if( lex[0].eType == Token::tMinus ) | 111 | else if( lex[0].eType == Token::tMinus ) |
| 116 | { | 112 | { |
| 117 | // This is negation | 113 | // This is negation |
| 118 | Bu::sio << "next token: " << lex[0] << Bu::sio.nl; | 114 | //Bu::sio << "next token: " << lex[0] << Bu::sio.nl; |
| 119 | printState("inline-negate"); | 115 | printState("inline-negate"); |
| 120 | exprP(); | 116 | exprP(); |
| 121 | printState("inline-negate-post"); | 117 | printState("inline-negate-post"); |
| 122 | shift( t ); | 118 | shift( t ); |
| 123 | printState("inline-negate-post2"); | 119 | printState("inline-negate-post2"); |
| 124 | 120 | ||
| 125 | Bu::sio << "??? " << lex[0] << Bu::sio.nl; | 121 | //Bu::sio << "??? " << lex[0] << Bu::sio.nl; |
| 126 | } | 122 | } |
| 127 | } | 123 | } |
| 128 | break; | 124 | break; |
| @@ -161,7 +157,7 @@ void Parser::exprP() | |||
| 161 | exprR(); | 157 | exprR(); |
| 162 | if( lex[0].eType != Token::tCloseParen ) | 158 | if( lex[0].eType != Token::tCloseParen ) |
| 163 | { | 159 | { |
| 164 | Bu::sio << "::exprP " << lex[0] << Bu::sio.nl; | 160 | //Bu::sio << "::exprP " << lex[0] << Bu::sio.nl; |
| 165 | throw Bu::ExceptionBase("Expected close paren"); | 161 | throw Bu::ExceptionBase("Expected close paren"); |
| 166 | } | 162 | } |
| 167 | shift( lex[0] ); | 163 | shift( lex[0] ); |
| @@ -283,7 +279,7 @@ void Parser::reduce() | |||
| 283 | { | 279 | { |
| 284 | case Token::tNumber: | 280 | case Token::tNumber: |
| 285 | case Token::tVariable: | 281 | case Token::tVariable: |
| 286 | tsScript.append( tOp ); | 282 | output( tOp ); |
| 287 | tsParse.push( Token( Token::tComputedValue ) ); | 283 | tsParse.push( Token( Token::tComputedValue ) ); |
| 288 | break; | 284 | break; |
| 289 | 285 | ||
| @@ -303,14 +299,14 @@ void Parser::reduce() | |||
| 303 | if( t.eType == Token::tNumber || | 299 | if( t.eType == Token::tNumber || |
| 304 | t.eType == Token::tVariable ) | 300 | t.eType == Token::tVariable ) |
| 305 | { | 301 | { |
| 306 | tsScript.append( t ); | 302 | output( t ); |
| 307 | } | 303 | } |
| 308 | else if( t.eType == Token::tComputedValue ) | 304 | else if( t.eType == Token::tComputedValue ) |
| 309 | { | 305 | { |
| 310 | // Nope, we don't care | 306 | // Nope, we don't care |
| 311 | } | 307 | } |
| 312 | } | 308 | } |
| 313 | tsScript.append( tOp ); | 309 | output( tOp ); |
| 314 | shift( Token( Token::tComputedValue ) ); | 310 | shift( Token( Token::tComputedValue ) ); |
| 315 | break; | 311 | break; |
| 316 | 312 | ||
| @@ -318,8 +314,8 @@ void Parser::reduce() | |||
| 318 | { | 314 | { |
| 319 | Token t = tsParse.peekPop(); | 315 | Token t = tsParse.peekPop(); |
| 320 | if( t.eType != Token::tComputedValue ) | 316 | if( t.eType != Token::tComputedValue ) |
| 321 | tsScript.append( t ); | 317 | output( t ); |
| 322 | tsScript.append( tOp ); | 318 | output( tOp ); |
| 323 | shift( Token( Token::tComputedValue ) ); | 319 | shift( Token( Token::tComputedValue ) ); |
| 324 | } | 320 | } |
| 325 | break; | 321 | break; |
| @@ -345,6 +341,11 @@ void Parser::reduce() | |||
| 345 | } | 341 | } |
| 346 | } | 342 | } |
| 347 | 343 | ||
| 344 | void Parser::output( const Token &t ) | ||
| 345 | { | ||
| 346 | pCurExp->append( t ); | ||
| 347 | } | ||
| 348 | |||
| 348 | int Parser::reqTokens( Token::Type eType ) | 349 | int Parser::reqTokens( Token::Type eType ) |
| 349 | { | 350 | { |
| 350 | switch( eType ) | 351 | switch( eType ) |
| @@ -402,6 +403,7 @@ int Parser::getPriority( Token::Type eType ) | |||
| 402 | 403 | ||
| 403 | void Parser::printState( const Bu::String &sTag ) | 404 | void Parser::printState( const Bu::String &sTag ) |
| 404 | { | 405 | { |
| 406 | /* | ||
| 405 | Bu::sio << "----------------" << Bu::sio.nl; | 407 | Bu::sio << "----------------" << Bu::sio.nl; |
| 406 | Bu::sio << sTag << " stack:"; | 408 | Bu::sio << sTag << " stack:"; |
| 407 | for( TokenStack::iterator i = tsParse.begin(); i; i++ ) | 409 | for( TokenStack::iterator i = tsParse.begin(); i; i++ ) |
| @@ -410,11 +412,12 @@ void Parser::printState( const Bu::String &sTag ) | |||
| 410 | } | 412 | } |
| 411 | Bu::sio << Bu::sio.nl; | 413 | Bu::sio << Bu::sio.nl; |
| 412 | Bu::sio << sTag << " script:"; | 414 | Bu::sio << sTag << " script:"; |
| 413 | for( TokenStack::iterator i = tsScript.begin(); i; i++ ) | 415 | for( TokenStack::iterator i = pCurExp->begin(); i; i++ ) |
| 414 | { | 416 | { |
| 415 | Bu::sio << " " << (*i); | 417 | Bu::sio << " " << (*i); |
| 416 | } | 418 | } |
| 417 | Bu::sio << Bu::sio.nl; | 419 | Bu::sio << Bu::sio.nl; |
| 418 | Bu::sio << "----------------" << Bu::sio.nl; | 420 | Bu::sio << "----------------" << Bu::sio.nl; |
| 421 | */ | ||
| 419 | } | 422 | } |
| 420 | 423 | ||
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 | |||
| 12 | }; | 12 | }; |
| 13 | 13 | ||
| 14 | class Lexer; | 14 | class Lexer; |
| 15 | class Expression; | ||
| 15 | 16 | ||
| 16 | /** | 17 | /** |
| 17 | * | 18 | * |
| @@ -45,10 +46,10 @@ class Lexer; | |||
| 45 | class Parser | 46 | class Parser |
| 46 | { | 47 | { |
| 47 | public: | 48 | public: |
| 48 | Parser( Lexer &lex, Bu::Stream &rOut ); | 49 | Parser( Lexer &lex ); |
| 49 | virtual ~Parser(); | 50 | virtual ~Parser(); |
| 50 | 51 | ||
| 51 | void parse(); | 52 | Expression *parse(); |
| 52 | 53 | ||
| 53 | private: | 54 | private: |
| 54 | void expr(); | 55 | void expr(); |
| @@ -58,6 +59,7 @@ private: | |||
| 58 | private: | 59 | private: |
| 59 | void shift( const Token &t ); | 60 | void shift( const Token &t ); |
| 60 | void reduce(); | 61 | void reduce(); |
| 62 | void output( const Token &t ); | ||
| 61 | int reqTokens( Token::Type eType ); | 63 | int reqTokens( Token::Type eType ); |
| 62 | int getPriority( Token::Type eType ); | 64 | int getPriority( Token::Type eType ); |
| 63 | 65 | ||
| @@ -65,10 +67,9 @@ private: | |||
| 65 | 67 | ||
| 66 | private: | 68 | private: |
| 67 | Lexer &lex; | 69 | Lexer &lex; |
| 68 | Bu::Stream &rOut; | ||
| 69 | typedef Bu::List<Token> TokenStack; | 70 | typedef Bu::List<Token> TokenStack; |
| 70 | TokenStack tsParse; | 71 | TokenStack tsParse; |
| 71 | TokenStack tsScript; | 72 | Expression *pCurExp; |
| 72 | }; | 73 | }; |
| 73 | 74 | ||
| 74 | #endif | 75 | #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 @@ | |||
| 1 | #include "scriptengine.h" | ||
| 2 | #include "lexer.h" | ||
| 3 | #include "parser.h" | ||
| 4 | #include "expression.h" | ||
| 5 | |||
| 6 | #include <bu/staticmembuf.h> | ||
| 7 | #include <bu/exceptionbase.h> | ||
| 8 | |||
| 9 | ScriptEngine::ScriptEngine() | ||
| 10 | { | ||
| 11 | } | ||
| 12 | |||
| 13 | ScriptEngine::~ScriptEngine() | ||
| 14 | { | ||
| 15 | } | ||
| 16 | |||
| 17 | Number ScriptEngine::exec( const Bu::String &sExpr ) | ||
| 18 | { | ||
| 19 | Bu::StaticMemBuf mb( sExpr.getStr(), sExpr.getSize() ); | ||
| 20 | return exec( sExpr ); | ||
| 21 | } | ||
| 22 | |||
| 23 | Number ScriptEngine::exec( Bu::Stream &sInput ) | ||
| 24 | { | ||
| 25 | Lexer l( sInput ); | ||
| 26 | Parser p( l ); | ||
| 27 | Expression *pExp = p.parse(); | ||
| 28 | Number n = exec( pExp ); | ||
| 29 | delete pExp; | ||
| 30 | return n; | ||
| 31 | } | ||
| 32 | |||
| 33 | Number ScriptEngine::exec( Expression *pExpr ) | ||
| 34 | { | ||
| 35 | NumStack sNums; | ||
| 36 | |||
| 37 | for( Expression::iterator i = pExpr->begin(); i; i++ ) | ||
| 38 | { | ||
| 39 | switch( (*i).eType ) | ||
| 40 | { | ||
| 41 | case Token::tNumber: | ||
| 42 | sNums.push( *(*i).nVal ); | ||
| 43 | break; | ||
| 44 | |||
| 45 | case Token::tVariable: | ||
| 46 | if( hVarState.has( *(*i).sVal ) ) | ||
| 47 | { | ||
| 48 | sNums.push( hVarState[*(*i).sVal] ); | ||
| 49 | } | ||
| 50 | else | ||
| 51 | { | ||
| 52 | throw Bu::ExceptionBase( | ||
| 53 | Bu::String("No such variable: $%1").arg(*(*i).sVal).end().getStr() | ||
| 54 | ); | ||
| 55 | } | ||
| 56 | break; | ||
| 57 | |||
| 58 | case Token::tPlus: | ||
| 59 | sNums.push( sNums.peekPop() + sNums.peekPop() ); | ||
| 60 | break; | ||
| 61 | |||
| 62 | case Token::tMinus: | ||
| 63 | sNums.push( sNums.peekPop() - sNums.peekPop() ); | ||
| 64 | break; | ||
| 65 | |||
| 66 | case Token::tDivide: | ||
| 67 | sNums.push( sNums.peekPop() / sNums.peekPop() ); | ||
| 68 | break; | ||
| 69 | |||
| 70 | case Token::tMultiply: | ||
| 71 | sNums.push( sNums.peekPop() * sNums.peekPop() ); | ||
| 72 | break; | ||
| 73 | |||
| 74 | case Token::tNegate: | ||
| 75 | sNums.push( -sNums.peekPop() ); | ||
| 76 | break; | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | return sNums.peekPop(); | ||
| 81 | } | ||
| 82 | |||
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 @@ | |||
| 1 | #ifndef SCRIPT_ENGINE_H | ||
| 2 | #define SCRIPT_ENGINE_H | ||
| 3 | |||
| 4 | #include "number.h" | ||
| 5 | |||
| 6 | #include <bu/hash.h> | ||
| 7 | #include <bu/list.h> | ||
| 8 | #include <bu/string.h> | ||
| 9 | |||
| 10 | |||
| 11 | namespace Bu | ||
| 12 | { | ||
| 13 | class Stream; | ||
| 14 | } | ||
| 15 | class Expression; | ||
| 16 | |||
| 17 | class ScriptEngine | ||
| 18 | { | ||
| 19 | public: | ||
| 20 | ScriptEngine(); | ||
| 21 | virtual ~ScriptEngine(); | ||
| 22 | |||
| 23 | Number exec( const Bu::String &sExpr ); | ||
| 24 | Number exec( Bu::Stream &sInput ); | ||
| 25 | Number exec( Expression *pExpr ); | ||
| 26 | |||
| 27 | private: | ||
| 28 | typedef Bu::Hash<Bu::String, Number> VarHash; | ||
| 29 | typedef Bu::List<Number> NumStack; | ||
| 30 | VarHash hVarState; | ||
| 31 | }; | ||
| 32 | |||
| 33 | #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() | |||
| 53 | Bu::MemBuf mbOut; | 53 | Bu::MemBuf mbOut; |
| 54 | Lexer lex( mbIn ); | 54 | Lexer lex( mbIn ); |
| 55 | lex.setScale( 0 ); | 55 | lex.setScale( 0 ); |
| 56 | Parser parser( lex, mbOut ); | 56 | Parser parser( lex ); |
| 57 | parser.parse(); | 57 | parser.parse(); |
| 58 | // Bu::println("%1 == %2").arg( mbOut.getString().trimWhitespace() ) | 58 | // Bu::println("%1 == %2").arg( mbOut.getString().trimWhitespace() ) |
| 59 | // .arg( parser.getVariable("test") ); | 59 | // .arg( parser.getVariable("test") ); |
