aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/formula.cpp157
-rw-r--r--src/formula.h62
-rw-r--r--src/sbuffer.cpp5
-rw-r--r--src/sbuffer.h1
-rw-r--r--src/sfile.cpp5
-rw-r--r--src/sfile.h1
-rw-r--r--src/stream.cpp1
-rw-r--r--src/stream.h1
-rw-r--r--src/tests/formula.cpp13
9 files changed, 246 insertions, 0 deletions
diff --git a/src/formula.cpp b/src/formula.cpp
new file mode 100644
index 0000000..7cc1804
--- /dev/null
+++ b/src/formula.cpp
@@ -0,0 +1,157 @@
1#include "formula.h"
2
3subExceptionDef( ParseException );
4
5Formula::Formula()
6{
7}
8
9Formula::~Formula()
10{
11}
12
13double Formula::run( const char *sFormula )
14{
15 sBuf.write( sFormula, strlen( sFormula ) );
16 sBuf.setPos( 0 );
17
18 nState = 0;
19 for(;;)
20 {
21 tLook = nextToken();
22 if( tLook.nSym == symEOS )
23 break;
24 state();
25 }
26 printf("\n");
27 return 0.0;
28}
29
30void Formula::state()
31{
32 switch( nState )
33 {
34 case 0: // initial expr
35 switch( tLook.nSym )
36 {
37 case symNumber:
38 push();
39 nState = 1;
40 break;
41 }
42 break;
43
44 case 1: // binary operator
45 switch( tLook.nSym )
46 {
47 case symAdd:
48 case symSubtract:
49 push();
50 nState = 2;
51 break;
52
53 case symMultiply:
54 case symDivide:
55 push();
56 nState = 3;
57 break;
58 }
59 break;
60
61 case 2: // add/subtract
62 break;
63 }
64}
65
66void Formula::push()
67{
68 printToken( tLook );
69 sToken.push( tLook );
70}
71
72Formula::Token Formula::nextToken()
73{
74 char cbuf;
75 for(;;)
76 {
77 if( sBuf.isEOS() )
78 return Token( symEOS );
79
80 sBuf.read( &cbuf, 1 );
81 switch( cbuf )
82 {
83 case '+':
84 return Token( symAdd );
85
86 case '-':
87 return Token( symSubtract );
88
89 case '*':
90 return Token( symMultiply );
91
92 case '/':
93 return Token( symDivide );
94
95 case '(':
96 return Token( symOpenParen );
97
98 case ')':
99 return Token( symCloseParen );
100
101 case ' ':
102 case '\t':
103 case '\n':
104 case '\r':
105 break;
106
107 default:
108 if( cbuf == '.' || (cbuf >= '0' && cbuf <= '9') )
109 {
110 char num[50];
111 int nPos = 0;
112 bool bDot = false;
113
114 for(;;)
115 {
116 num[nPos++] = cbuf;
117 if( cbuf == '.' )
118 {
119 if( bDot == false )
120 bDot = true;
121 else
122 throw ParseException(
123 "Numbers cannot have more than one "
124 ". in them."
125 );
126 }
127 sBuf.read( &cbuf, 1 );
128 if( (cbuf != '.' && (cbuf < '0' || cbuf > '9')) ||
129 sBuf.isEOS() )
130 {
131 if( !sBuf.isEOS() ) sBuf.seek( -1 );
132 num[nPos] = '\0';
133 return Token( symNumber, strtod( num, NULL ) );
134 }
135 }
136 }
137 break;
138 }
139 }
140}
141
142void Formula::printToken( Token &tok )
143{
144 switch( tok.nSym )
145 {
146 case symEOS: printf("[EOS] "); break;
147 case symAdd: printf("+ "); break;
148 case symSubtract: printf("- "); break;
149 case symMultiply: printf("* "); break;
150 case symDivide: printf("/ "); break;
151 case symOpenParen: printf("( "); break;
152 case symCloseParen: printf(") "); break;
153 case symNumber: printf("%f ", tok.val.num ); break;
154 default: printf("??? "); break;
155 }
156}
157
diff --git a/src/formula.h b/src/formula.h
new file mode 100644
index 0000000..1eccd36
--- /dev/null
+++ b/src/formula.h
@@ -0,0 +1,62 @@
1#ifndef FORMULA_H
2#define FORMULA_H
3
4#include <stdint.h>
5
6#include <stack>
7#include "sbuffer.h"
8
9#include "exceptionbase.h"
10
11subExceptionDecl( ParseException );
12
13/**
14 *
15 */
16class Formula
17{
18public:
19 Formula();
20 virtual ~Formula();
21
22 double run( const char *sFormula );
23
24private:
25 enum
26 {
27 symEOS,
28 symAdd,
29 symSubtract,
30 symMultiply,
31 symDivide,
32 symOpenParen,
33 symCloseParen,
34 symNumber,
35 symVariable
36 };
37
38 typedef struct Token
39 {
40 Token() {}
41 Token( uint8_t nSym ) : nSym( nSym ) { }
42 Token( uint8_t nSym, double dNum ) : nSym( nSym ) { val.num = dNum; }
43 uint8_t nSym;
44 union
45 {
46 double num;
47 } val;
48 } Token;
49
50 std::stack<Token> sToken;
51 Token tLook;
52 int nState;
53 SBuffer sBuf;
54
55private:
56 void push();
57 void state();
58 Token nextToken();
59 void printToken( Token &tok );
60};
61
62#endif
diff --git a/src/sbuffer.cpp b/src/sbuffer.cpp
index 0ed0f47..f84f8a3 100644
--- a/src/sbuffer.cpp
+++ b/src/sbuffer.cpp
@@ -60,3 +60,8 @@ void SBuffer::setPosEnd( long pos )
60 nPos = fbData.getLength() - pos; 60 nPos = fbData.getLength() - pos;
61} 61}
62 62
63bool SBuffer::isEOS()
64{
65 return nPos == fbData.getLength();
66}
67
diff --git a/src/sbuffer.h b/src/sbuffer.h
index 5352bda..65feb71 100644
--- a/src/sbuffer.h
+++ b/src/sbuffer.h
@@ -24,6 +24,7 @@ public:
24 virtual void seek( long offset ); 24 virtual void seek( long offset );
25 virtual void setPos( long pos ); 25 virtual void setPos( long pos );
26 virtual void setPosEnd( long pos ); 26 virtual void setPosEnd( long pos );
27 virtual bool isEOS();
27 28
28 FlexBuf &getBuffer() 29 FlexBuf &getBuffer()
29 { 30 {
diff --git a/src/sfile.cpp b/src/sfile.cpp
index 3f5144d..f1de03c 100644
--- a/src/sfile.cpp
+++ b/src/sfile.cpp
@@ -67,3 +67,8 @@ void SFile::setPosEnd( long pos )
67 fseek( fh, pos, SEEK_END ); 67 fseek( fh, pos, SEEK_END );
68} 68}
69 69
70bool SFile::isEOS()
71{
72 return feof( fh );
73}
74
diff --git a/src/sfile.h b/src/sfile.h
index f276ad2..b51e5bc 100644
--- a/src/sfile.h
+++ b/src/sfile.h
@@ -19,6 +19,7 @@ public:
19 virtual void seek( long offset ); 19 virtual void seek( long offset );
20 virtual void setPos( long pos ); 20 virtual void setPos( long pos );
21 virtual void setPosEnd( long pos ); 21 virtual void setPosEnd( long pos );
22 virtual bool isEOS();
22 23
23private: 24private:
24 FILE *fh; 25 FILE *fh;
diff --git a/src/stream.cpp b/src/stream.cpp
index 99c25f2..856a58d 100644
--- a/src/stream.cpp
+++ b/src/stream.cpp
@@ -7,3 +7,4 @@ Stream::Stream()
7Stream::~Stream() 7Stream::~Stream()
8{ 8{
9} 9}
10
diff --git a/src/stream.h b/src/stream.h
index 32e5432..e086e28 100644
--- a/src/stream.h
+++ b/src/stream.h
@@ -18,6 +18,7 @@ public:
18 virtual void seek( long offset ) = 0; 18 virtual void seek( long offset ) = 0;
19 virtual void setPos( long pos ) = 0; 19 virtual void setPos( long pos ) = 0;
20 virtual void setPosEnd( long pos ) = 0; 20 virtual void setPosEnd( long pos ) = 0;
21 virtual bool isEOS() = 0;
21 22
22private: 23private:
23 24
diff --git a/src/tests/formula.cpp b/src/tests/formula.cpp
new file mode 100644
index 0000000..599a264
--- /dev/null
+++ b/src/tests/formula.cpp
@@ -0,0 +1,13 @@
1#include "formula.h"
2
3int main( int argc, char *argv[] )
4{
5 if( argc < 2 ) return 0;
6
7 Formula f;
8 double dOut = f.run( argv[1] );
9 printf("Final: %f\n", dOut );
10
11 return 0;
12}
13