diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/formula.cpp | 157 | ||||
| -rw-r--r-- | src/formula.h | 62 | ||||
| -rw-r--r-- | src/sbuffer.cpp | 5 | ||||
| -rw-r--r-- | src/sbuffer.h | 1 | ||||
| -rw-r--r-- | src/sfile.cpp | 5 | ||||
| -rw-r--r-- | src/sfile.h | 1 | ||||
| -rw-r--r-- | src/stream.cpp | 1 | ||||
| -rw-r--r-- | src/stream.h | 1 | ||||
| -rw-r--r-- | src/tests/formula.cpp | 13 |
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 | |||
| 3 | subExceptionDef( ParseException ); | ||
| 4 | |||
| 5 | Formula::Formula() | ||
| 6 | { | ||
| 7 | } | ||
| 8 | |||
| 9 | Formula::~Formula() | ||
| 10 | { | ||
| 11 | } | ||
| 12 | |||
| 13 | double 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 | |||
| 30 | void 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 | |||
| 66 | void Formula::push() | ||
| 67 | { | ||
| 68 | printToken( tLook ); | ||
| 69 | sToken.push( tLook ); | ||
| 70 | } | ||
| 71 | |||
| 72 | Formula::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 | |||
| 142 | void 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 | |||
| 11 | subExceptionDecl( ParseException ); | ||
| 12 | |||
| 13 | /** | ||
| 14 | * | ||
| 15 | */ | ||
| 16 | class Formula | ||
| 17 | { | ||
| 18 | public: | ||
| 19 | Formula(); | ||
| 20 | virtual ~Formula(); | ||
| 21 | |||
| 22 | double run( const char *sFormula ); | ||
| 23 | |||
| 24 | private: | ||
| 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 | |||
| 55 | private: | ||
| 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 | ||
| 63 | bool 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 | ||
| 70 | bool 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 | ||
| 23 | private: | 24 | private: |
| 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() | |||
| 7 | Stream::~Stream() | 7 | Stream::~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 | ||
| 22 | private: | 23 | private: |
| 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 | |||
| 3 | int 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 | |||
