aboutsummaryrefslogtreecommitdiff
path: root/src/tools/parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/parser.cpp')
-rw-r--r--src/tools/parser.cpp164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/tools/parser.cpp b/src/tools/parser.cpp
new file mode 100644
index 0000000..a70dfa4
--- /dev/null
+++ b/src/tools/parser.cpp
@@ -0,0 +1,164 @@
1#include <bu/parser.h>
2#include <bu/lexer.h>
3#include <bu/file.h>
4#include <bu/sio.h>
5#include <bu/queuebuf.h>
6#include <stdlib.h>
7
8using namespace Bu;
9
10enum Tok
11{
12 tokNumber,
13 tokPlus,
14 tokMinus,
15 tokDivide,
16 tokMultiply,
17 tokOpenParen,
18 tokCloseParen,
19 tokCompute,
20 tokEndOfInput=-1
21};
22
23Bu::Formatter &operator<<( Bu::Formatter &f, Tok e )
24{
25 switch( e )
26 {
27 case tokNumber: return f << "tokNumber";
28 case tokPlus: return f << "tokPlus";
29 case tokMinus: return f << "tokMinus";
30 case tokDivide: return f << "tokDivide";
31 case tokMultiply: return f << "tokMultiply";
32 case tokOpenParen: return f << "tokOpenParen";
33 case tokCloseParen: return f << "tokCloseParen";
34 case tokCompute: return f << "tokCompute";
35 case tokEndOfInput: return f << "tokEndOfInput";
36 }
37
38 return f << "***error***";
39}
40
41class MathLexer : public Lexer
42{
43public:
44 MathLexer( Bu::Stream &rSrc ) :
45 rSrc( rSrc )
46 {
47 }
48
49 virtual ~MathLexer()
50 {
51 }
52
53 enum TokenTypes
54 {
55 tokStuff
56 };
57
58 virtual Token *nextToken()
59 {
60 for(;;)
61 {
62 if( qbIn.getSize() == 0 )
63 {
64 char buf[4096];
65 qbIn.write( buf, rSrc.read( buf, 4096 ) );
66
67 if( rSrc.isEos() && qbIn.getSize() == 0 )
68 return new Token( tokEndOfInput );
69 }
70
71 char b;
72 qbIn.peek( &b, 1 );
73 switch( b )
74 {
75 case '+':
76 qbIn.seek( 1 );
77 return new Token( tokPlus );
78
79 case '-':
80 qbIn.seek( 1 );
81 return new Token( tokMinus );
82
83 case '/':
84 qbIn.seek( 1 );
85 return new Token( tokDivide );
86
87 case '*':
88 qbIn.seek( 1 );
89 return new Token( tokMultiply );
90
91 case ' ':
92 case '\t':
93 case '\n':
94 qbIn.seek( 1 );
95 break;
96
97 case '=':
98 qbIn.seek( 1 );
99 return new Token( tokCompute );
100
101 case '(':
102 qbIn.seek( 1 );
103 return new Token( tokOpenParen );
104
105 case ')':
106 qbIn.seek( 1 );
107 return new Token( tokCloseParen );
108
109 case '.':
110 case '0':
111 case '1':
112 case '2':
113 case '3':
114 case '4':
115 case '5':
116 case '6':
117 case '7':
118 case '8':
119 case '9':
120 {
121 Bu::FString sTmp;
122 sTmp += b;
123 qbIn.seek( 1 );
124 for(;;)
125 {
126 qbIn.peek( &b, 1 );
127 if( b != '.' && (b < '0' || b > '9') )
128 {
129 sio << "!! Convert '" << sTmp << "' to "
130 << strtod( sTmp.getStr(), NULL ) << sio.nl;
131 return new Token(
132 tokNumber, strtod( sTmp.getStr(), NULL )
133 );
134 }
135 qbIn.seek( 1 );
136 sTmp += b;
137 }
138 }
139 break;
140
141 default:
142 throw Bu::ExceptionBase("Unexpected character '%c'.", b );
143 }
144 }
145 }
146
147private:
148 Bu::Stream &rSrc;
149 QueueBuf qbIn;
150};
151
152int main( int argc, char *argv[] )
153{
154 File fIn( argv[1], File::Read );
155
156 Parser p;
157
158 p.pushLexer( new MathLexer( fIn ) );
159
160 p.parse();
161
162 return 0;
163}
164