summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2016-12-01 15:51:52 -0700
committerMike Buland <eichlan@xagasoft.com>2016-12-01 15:51:52 -0700
commit5d59aa3e9dffe2912215335ce0b76c67ebbe5a4e (patch)
treefa4f7b73f912b0b5ff87280c0bc4dc118a82392d
parent17a39c19e5bff97c3b3d2bc888a3bb5ded7c1b96 (diff)
downloadclic-5d59aa3e9dffe2912215335ce0b76c67ebbe5a4e.tar.gz
clic-5d59aa3e9dffe2912215335ce0b76c67ebbe5a4e.tar.bz2
clic-5d59aa3e9dffe2912215335ce0b76c67ebbe5a4e.tar.xz
clic-5d59aa3e9dffe2912215335ce0b76c67ebbe5a4e.zip
Signals solve many problems.
The command structures will be changed, I think. I want the lexer to actually lex the command names into tokens, then the parser and the engine can both use them to update their state when necesarry. It will be less ambiguous and easier for both sides to stay synchronized.
-rw-r--r--src/options.cpp15
-rw-r--r--src/options.h4
-rw-r--r--src/parser.cpp9
-rw-r--r--src/scriptengine.cpp75
-rw-r--r--src/scriptengine.h26
5 files changed, 110 insertions, 19 deletions
diff --git a/src/options.cpp b/src/options.cpp
index 672858a..3ed2336 100644
--- a/src/options.cpp
+++ b/src/options.cpp
@@ -201,8 +201,9 @@ int Options::execute( Bu::StringArray aArgs )
201 Parser parser( lex ); 201 Parser parser( lex );
202 Expression *pExp = parser.parse(); 202 Expression *pExp = parser.parse();
203 ScriptEngine se; 203 ScriptEngine se;
204 Number n = se.exec( pExp ); 204 se.sigError = Bu::slot( this, &Options::printError );
205 Bu::println( n.toString() ); 205 se.sigNumResult = Bu::slot( this, &Options::printNumber );
206 se.exec( pExp );
206 exit( 0 ); 207 exit( 0 );
207 return aArgs.getSize(); 208 return aArgs.getSize();
208} 209}
@@ -328,3 +329,13 @@ int Options::grind( Bu::StringArray aArgs )
328 return 0; 329 return 0;
329} 330}
330 331
332void Options::printError( const Bu::String &sMsg )
333{
334 Bu::println("ERROR: %1").arg( sMsg );
335}
336
337void Options::printNumber( const class Number &rNum )
338{
339 Bu::println("%1").arg( rNum );
340}
341
diff --git a/src/options.h b/src/options.h
index a7453ab..dc28190 100644
--- a/src/options.h
+++ b/src/options.h
@@ -24,6 +24,10 @@ private:
24 24
25 int iScale; 25 int iScale;
26 int iRadix; 26 int iRadix;
27
28private:
29 void printError( const Bu::String &sMsg );
30 void printNumber( const class Number &rNum );
27}; 31};
28 32
29#endif 33#endif
diff --git a/src/parser.cpp b/src/parser.cpp
index e9388c8..982c342 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -199,6 +199,15 @@ void Parser::statement()
199 if( lex[0].eType == Token::tCommand ) 199 if( lex[0].eType == Token::tCommand )
200 { 200 {
201 lex.setMode( Lexer::modeCommand ); 201 lex.setMode( Lexer::modeCommand );
202 output( lex[0] );
203 for(;;)
204 {
205 lex.nextToken();
206 if( lex[0].eType == Token::tEndOfLine ||
207 lex[0].eType == Token::tEndOfInput )
208 break;
209 output( lex[0] );
210 }
202 lex.setMode( Lexer::modeNormal ); 211 lex.setMode( Lexer::modeNormal );
203 } 212 }
204 else 213 else
diff --git a/src/scriptengine.cpp b/src/scriptengine.cpp
index 65b6ec2..b65db70 100644
--- a/src/scriptengine.cpp
+++ b/src/scriptengine.cpp
@@ -5,8 +5,12 @@
5 5
6#include <bu/staticmembuf.h> 6#include <bu/staticmembuf.h>
7#include <bu/exceptionbase.h> 7#include <bu/exceptionbase.h>
8#include <bu/sio.h>
8 9
9ScriptEngine::ScriptEngine() 10#include <stdlib.h>
11
12ScriptEngine::ScriptEngine() :
13 bRunning( true )
10{ 14{
11} 15}
12 16
@@ -14,23 +18,22 @@ ScriptEngine::~ScriptEngine()
14{ 18{
15} 19}
16 20
17Number ScriptEngine::exec( const Bu::String &sExpr ) 21void ScriptEngine::exec( const Bu::String &sExpr )
18{ 22{
19 Bu::StaticMemBuf mb( sExpr.getStr(), sExpr.getSize() ); 23 Bu::StaticMemBuf mb( sExpr.getStr(), sExpr.getSize() );
20 return exec( sExpr ); 24 exec( sExpr );
21} 25}
22 26
23Number ScriptEngine::exec( Bu::Stream &sInput ) 27void ScriptEngine::exec( Bu::Stream &sInput )
24{ 28{
25 Lexer l( sInput ); 29 Lexer l( sInput );
26 Parser p( l ); 30 Parser p( l );
27 Expression *pExp = p.parse(); 31 Expression *pExp = p.parse();
28 Number n = exec( pExp ); 32 exec( pExp );
29 delete pExp; 33 delete pExp;
30 return n;
31} 34}
32 35
33Number ScriptEngine::exec( Expression *pExpr ) 36void ScriptEngine::exec( Expression *pExpr )
34{ 37{
35 NumStack sNums; 38 NumStack sNums;
36 39
@@ -49,9 +52,12 @@ Number ScriptEngine::exec( Expression *pExpr )
49 } 52 }
50 else 53 else
51 { 54 {
52 throw Bu::ExceptionBase( 55 if( sigError.isSet() )
53 Bu::String("No such variable: $%1").arg(*(*i).sVal).end().getStr() 56 sigError(
54 ); 57 Bu::String("No such variable: $%1").
58 arg(*(*i).sVal)
59 );
60 return;
55 } 61 }
56 break; 62 break;
57 63
@@ -90,9 +96,56 @@ Number ScriptEngine::exec( Expression *pExpr )
90 case Token::tNegate: 96 case Token::tNegate:
91 sNums.push( -sNums.peekPop() ); 97 sNums.push( -sNums.peekPop() );
92 break; 98 break;
99
100 case Token::tCommand:
101 command( i );
102 return;
93 } 103 }
94 } 104 }
95 105
96 return sNums.peekPop(); 106 if( sigNumResult.isSet() )
107 sigNumResult( sNums.peekPop() );
108}
109
110void ScriptEngine::command( Expression::iterator &i )
111{
112 Bu::String sCmd = *(*i).sVal;
113 if( sCmd == "exit" || sCmd == "quit" )
114 {
115 bRunning = false;
116 return;
117 }
118 else if( sCmd == "scale" )
119 {
120 if( !(++i) )
121 {
122 if( sigError.isSet() )
123 sigError("You must provide a positive integer.");
124 return;
125 }
126 int32_t iScale = strtol( (*i).sVal->getStr(), 0, 10 );
127 if( iScale < 0 )
128 {
129 if( sigError.isSet() )
130 sigError("You must provide a positive integer.");
131 return;
132 }
133 if( sigMessage.isSet() )
134 sigMessage(Bu::String("Changed scale to: %1").arg( iScale ));
135 for( VarHash::iterator i = hVarState.begin(); i; i++ )
136 (*i).setScale( iScale );
137 }
138 else if( sCmd == "radix" )
139 {
140 }
141 else if( sCmd == "vars" )
142 {
143 }
144 else if( sCmd == "help" || sCmd == "?" )
145 {
146 }
147 else
148 {
149 }
97} 150}
98 151
diff --git a/src/scriptengine.h b/src/scriptengine.h
index 74924d6..b25c651 100644
--- a/src/scriptengine.h
+++ b/src/scriptengine.h
@@ -2,11 +2,12 @@
2#define SCRIPT_ENGINE_H 2#define SCRIPT_ENGINE_H
3 3
4#include "number.h" 4#include "number.h"
5#include "expression.h"
5 6
6#include <bu/hash.h> 7#include <bu/hash.h>
7#include <bu/list.h> 8#include <bu/list.h>
8#include <bu/string.h> 9#include <bu/string.h>
9 10#include <bu/signals.h>
10 11
11namespace Bu 12namespace Bu
12{ 13{
@@ -16,18 +17,31 @@ class Expression;
16 17
17class ScriptEngine 18class ScriptEngine
18{ 19{
20private:
21 typedef Bu::Hash<Bu::String, Number> VarHash;
22 typedef Bu::List<Number> NumStack;
23
19public: 24public:
20 ScriptEngine(); 25 ScriptEngine();
21 virtual ~ScriptEngine(); 26 virtual ~ScriptEngine();
22 27
23 Number exec( const Bu::String &sExpr ); 28 void exec( const Bu::String &sExpr );
24 Number exec( Bu::Stream &sInput ); 29 void exec( Bu::Stream &sInput );
25 Number exec( Expression *pExpr ); 30 void exec( Expression *pExpr );
31
32 bool isRunning() const { return bRunning; }
33
34public:
35 Bu::Signal1<void, const class Number &> sigNumResult;
36 Bu::Signal1<void, const Bu::String &> sigError;
37 Bu::Signal1<void, const Bu::String &> sigMessage;
38
39private:
40 void command( Expression::iterator &i );
26 41
27private: 42private:
28 typedef Bu::Hash<Bu::String, Number> VarHash;
29 typedef Bu::List<Number> NumStack;
30 VarHash hVarState; 43 VarHash hVarState;
44 bool bRunning;
31}; 45};
32 46
33#endif 47#endif