diff options
author | Mike Buland <eichlan@xagasoft.com> | 2016-12-01 10:40:43 -0700 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2016-12-01 10:40:43 -0700 |
commit | b96daa4e9849ac9caf5c0dfcea8daac28267ea19 (patch) | |
tree | 9be42c8cfe8b875f396b5887742bb936bd081c65 /src | |
parent | 4efeaef41e57b25d6004e7f91828f7d5b5cd0b20 (diff) | |
download | clic-b96daa4e9849ac9caf5c0dfcea8daac28267ea19.tar.gz clic-b96daa4e9849ac9caf5c0dfcea8daac28267ea19.tar.bz2 clic-b96daa4e9849ac9caf5c0dfcea8daac28267ea19.tar.xz clic-b96daa4e9849ac9caf5c0dfcea8daac28267ea19.zip |
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.
Diffstat (limited to 'src')
-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") ); |