diff options
Diffstat (limited to '')
-rw-r--r-- | src/tests/parser.cpp | 576 |
1 files changed, 288 insertions, 288 deletions
diff --git a/src/tests/parser.cpp b/src/tests/parser.cpp index af53bc8..6ad722f 100644 --- a/src/tests/parser.cpp +++ b/src/tests/parser.cpp | |||
@@ -16,185 +16,185 @@ using namespace Bu; | |||
16 | 16 | ||
17 | enum Tok | 17 | enum Tok |
18 | { | 18 | { |
19 | tokNumber, | 19 | tokNumber, |
20 | tokPlus, | 20 | tokPlus, |
21 | tokMinus, | 21 | tokMinus, |
22 | tokDivide, | 22 | tokDivide, |
23 | tokMultiply, | 23 | tokMultiply, |
24 | tokOpenParen, | 24 | tokOpenParen, |
25 | tokCloseParen, | 25 | tokCloseParen, |
26 | tokCompute, | 26 | tokCompute, |
27 | tokEndOfInput=-1 | 27 | tokEndOfInput=-1 |
28 | }; | 28 | }; |
29 | 29 | ||
30 | Bu::Formatter &operator<<( Bu::Formatter &f, Tok e ) | 30 | Bu::Formatter &operator<<( Bu::Formatter &f, Tok e ) |
31 | { | 31 | { |
32 | switch( e ) | 32 | switch( e ) |
33 | { | 33 | { |
34 | case tokNumber: return f << "tokNumber"; | 34 | case tokNumber: return f << "tokNumber"; |
35 | case tokPlus: return f << "tokPlus"; | 35 | case tokPlus: return f << "tokPlus"; |
36 | case tokMinus: return f << "tokMinus"; | 36 | case tokMinus: return f << "tokMinus"; |
37 | case tokDivide: return f << "tokDivide"; | 37 | case tokDivide: return f << "tokDivide"; |
38 | case tokMultiply: return f << "tokMultiply"; | 38 | case tokMultiply: return f << "tokMultiply"; |
39 | case tokOpenParen: return f << "tokOpenParen"; | 39 | case tokOpenParen: return f << "tokOpenParen"; |
40 | case tokCloseParen: return f << "tokCloseParen"; | 40 | case tokCloseParen: return f << "tokCloseParen"; |
41 | case tokCompute: return f << "tokCompute"; | 41 | case tokCompute: return f << "tokCompute"; |
42 | case tokEndOfInput: return f << "tokEndOfInput"; | 42 | case tokEndOfInput: return f << "tokEndOfInput"; |
43 | } | 43 | } |
44 | 44 | ||
45 | return f << "***error***"; | 45 | return f << "***error***"; |
46 | } | 46 | } |
47 | 47 | ||
48 | class MathLexer : public Lexer | 48 | class MathLexer : public Lexer |
49 | { | 49 | { |
50 | public: | 50 | public: |
51 | MathLexer( Bu::Stream &rSrc ) : | 51 | MathLexer( Bu::Stream &rSrc ) : |
52 | rSrc( rSrc ) | 52 | rSrc( rSrc ) |
53 | { | 53 | { |
54 | } | 54 | } |
55 | 55 | ||
56 | virtual ~MathLexer() | 56 | virtual ~MathLexer() |
57 | { | 57 | { |
58 | } | 58 | } |
59 | 59 | ||
60 | enum TokenTypes | 60 | enum TokenTypes |
61 | { | 61 | { |
62 | tokStuff | 62 | tokStuff |
63 | }; | 63 | }; |
64 | 64 | ||
65 | virtual Token *nextToken() | 65 | virtual Token *nextToken() |
66 | { | 66 | { |
67 | for(;;) | 67 | for(;;) |
68 | { | 68 | { |
69 | if( qbIn.getSize() == 0 ) | 69 | if( qbIn.getSize() == 0 ) |
70 | { | 70 | { |
71 | char buf[4096]; | 71 | char buf[4096]; |
72 | qbIn.write( buf, rSrc.read( buf, 4096 ) ); | 72 | qbIn.write( buf, rSrc.read( buf, 4096 ) ); |
73 | 73 | ||
74 | if( rSrc.isEos() && qbIn.getSize() == 0 ) | 74 | if( rSrc.isEos() && qbIn.getSize() == 0 ) |
75 | return new Token( tokEndOfInput ); | 75 | return new Token( tokEndOfInput ); |
76 | } | 76 | } |
77 | 77 | ||
78 | char b; | 78 | char b; |
79 | qbIn.peek( &b, 1 ); | 79 | qbIn.peek( &b, 1 ); |
80 | switch( b ) | 80 | switch( b ) |
81 | { | 81 | { |
82 | case '+': | 82 | case '+': |
83 | qbIn.seek( 1 ); | 83 | qbIn.seek( 1 ); |
84 | return new Token( tokPlus ); | 84 | return new Token( tokPlus ); |
85 | 85 | ||
86 | case '-': | 86 | case '-': |
87 | qbIn.seek( 1 ); | 87 | qbIn.seek( 1 ); |
88 | return new Token( tokMinus ); | 88 | return new Token( tokMinus ); |
89 | 89 | ||
90 | case '/': | 90 | case '/': |
91 | qbIn.seek( 1 ); | 91 | qbIn.seek( 1 ); |
92 | return new Token( tokDivide ); | 92 | return new Token( tokDivide ); |
93 | 93 | ||
94 | case '*': | 94 | case '*': |
95 | qbIn.seek( 1 ); | 95 | qbIn.seek( 1 ); |
96 | return new Token( tokMultiply ); | 96 | return new Token( tokMultiply ); |
97 | 97 | ||
98 | case ' ': | 98 | case ' ': |
99 | case '\t': | 99 | case '\t': |
100 | case '\n': | 100 | case '\n': |
101 | qbIn.seek( 1 ); | 101 | qbIn.seek( 1 ); |
102 | break; | 102 | break; |
103 | 103 | ||
104 | case '=': | 104 | case '=': |
105 | qbIn.seek( 1 ); | 105 | qbIn.seek( 1 ); |
106 | return new Token( tokCompute ); | 106 | return new Token( tokCompute ); |
107 | 107 | ||
108 | case '(': | 108 | case '(': |
109 | qbIn.seek( 1 ); | 109 | qbIn.seek( 1 ); |
110 | return new Token( tokOpenParen ); | 110 | return new Token( tokOpenParen ); |
111 | 111 | ||
112 | case ')': | 112 | case ')': |
113 | qbIn.seek( 1 ); | 113 | qbIn.seek( 1 ); |
114 | return new Token( tokCloseParen ); | 114 | return new Token( tokCloseParen ); |
115 | 115 | ||
116 | case '.': | 116 | case '.': |
117 | case '0': | 117 | case '0': |
118 | case '1': | 118 | case '1': |
119 | case '2': | 119 | case '2': |
120 | case '3': | 120 | case '3': |
121 | case '4': | 121 | case '4': |
122 | case '5': | 122 | case '5': |
123 | case '6': | 123 | case '6': |
124 | case '7': | 124 | case '7': |
125 | case '8': | 125 | case '8': |
126 | case '9': | 126 | case '9': |
127 | { | 127 | { |
128 | Bu::String sTmp; | 128 | Bu::String sTmp; |
129 | sTmp += b; | 129 | sTmp += b; |
130 | qbIn.seek( 1 ); | 130 | qbIn.seek( 1 ); |
131 | for(;;) | 131 | for(;;) |
132 | { | 132 | { |
133 | qbIn.peek( &b, 1 ); | 133 | qbIn.peek( &b, 1 ); |
134 | if( b != '.' && (b < '0' || b > '9') ) | 134 | if( b != '.' && (b < '0' || b > '9') ) |
135 | { | 135 | { |
136 | sio << "!! Convert '" << sTmp << "' to " | 136 | sio << "!! Convert '" << sTmp << "' to " |
137 | << strtod( sTmp.getStr(), NULL ) << sio.nl; | 137 | << strtod( sTmp.getStr(), NULL ) << sio.nl; |
138 | return new Token( | 138 | return new Token( |
139 | tokNumber, strtod( sTmp.getStr(), NULL ) | 139 | tokNumber, strtod( sTmp.getStr(), NULL ) |
140 | ); | 140 | ); |
141 | } | 141 | } |
142 | qbIn.seek( 1 ); | 142 | qbIn.seek( 1 ); |
143 | sTmp += b; | 143 | sTmp += b; |
144 | } | 144 | } |
145 | } | 145 | } |
146 | break; | 146 | break; |
147 | 147 | ||
148 | default: | 148 | default: |
149 | throw Bu::ExceptionBase("Unexpected character '%c'.", b ); | 149 | throw Bu::ExceptionBase("Unexpected character '%c'.", b ); |
150 | } | 150 | } |
151 | } | 151 | } |
152 | } | 152 | } |
153 | 153 | ||
154 | private: | 154 | private: |
155 | Bu::Stream &rSrc; | 155 | Bu::Stream &rSrc; |
156 | QueueBuf qbIn; | 156 | QueueBuf qbIn; |
157 | }; | 157 | }; |
158 | 158 | ||
159 | void redAdd( Bu::Parser &p ) | 159 | void redAdd( Bu::Parser &p ) |
160 | { | 160 | { |
161 | Lexer::Token *a = p.popToken(); | 161 | Lexer::Token *a = p.popToken(); |
162 | Lexer::Token *b = p.popToken(); | 162 | Lexer::Token *b = p.popToken(); |
163 | 163 | ||
164 | sio << "Add! " << b->vExtra.get<double>() << " + " | 164 | sio << "Add! " << b->vExtra.get<double>() << " + " |
165 | << a->vExtra.get<double>() << sio.nl; | 165 | << a->vExtra.get<double>() << sio.nl; |
166 | 166 | ||
167 | Lexer::Token *c = new Lexer::Token( tokNumber, | 167 | Lexer::Token *c = new Lexer::Token( tokNumber, |
168 | b->vExtra.get<double>() + a->vExtra.get<double>() | 168 | b->vExtra.get<double>() + a->vExtra.get<double>() |
169 | ); | 169 | ); |
170 | p.pushToken( c ); | 170 | p.pushToken( c ); |
171 | 171 | ||
172 | delete a; | 172 | delete a; |
173 | delete b; | 173 | delete b; |
174 | } | 174 | } |
175 | 175 | ||
176 | void redSubtract( Bu::Parser &p ) | 176 | void redSubtract( Bu::Parser &p ) |
177 | { | 177 | { |
178 | Lexer::Token *a = p.popToken(); | 178 | Lexer::Token *a = p.popToken(); |
179 | Lexer::Token *b = p.popToken(); | 179 | Lexer::Token *b = p.popToken(); |
180 | 180 | ||
181 | sio << "Subtract! " << b->vExtra.get<double>() << " - " | 181 | sio << "Subtract! " << b->vExtra.get<double>() << " - " |
182 | << a->vExtra.get<double>() << sio.nl; | 182 | << a->vExtra.get<double>() << sio.nl; |
183 | 183 | ||
184 | Lexer::Token *c = new Lexer::Token( tokNumber, | 184 | Lexer::Token *c = new Lexer::Token( tokNumber, |
185 | b->vExtra.get<double>() - a->vExtra.get<double>() | 185 | b->vExtra.get<double>() - a->vExtra.get<double>() |
186 | ); | 186 | ); |
187 | p.pushToken( c ); | 187 | p.pushToken( c ); |
188 | 188 | ||
189 | delete a; | 189 | delete a; |
190 | delete b; | 190 | delete b; |
191 | } | 191 | } |
192 | 192 | ||
193 | void redPrint( Bu::Parser &p ) | 193 | void redPrint( Bu::Parser &p ) |
194 | { | 194 | { |
195 | Lexer::Token *a = p.popToken(); | 195 | Lexer::Token *a = p.popToken(); |
196 | sio << "Print! = " << a->vExtra.get<double>() << sio.nl; | 196 | sio << "Print! = " << a->vExtra.get<double>() << sio.nl; |
197 | delete a; | 197 | delete a; |
198 | } | 198 | } |
199 | 199 | ||
200 | /* Basic grammer example: | 200 | /* Basic grammer example: |
@@ -227,143 +227,143 @@ void redPrint( Bu::Parser &p ) | |||
227 | 227 | ||
228 | int main( int argc, char *argv[] ) | 228 | int main( int argc, char *argv[] ) |
229 | { | 229 | { |
230 | if( argc < 2 ) | 230 | if( argc < 2 ) |
231 | { | 231 | { |
232 | println("Provide an input filename as the first parameter."); | 232 | println("Provide an input filename as the first parameter."); |
233 | return 0; | 233 | return 0; |
234 | } | 234 | } |
235 | File fIn( argv[1], File::Read ); | 235 | File fIn( argv[1], File::Read ); |
236 | 236 | ||
237 | Parser p; | 237 | Parser p; |
238 | 238 | ||
239 | p.addNonTerminal("expr"); | 239 | p.addNonTerminal("expr"); |
240 | p.addNonTerminal("expr-sub1"); | 240 | p.addNonTerminal("expr-sub1"); |
241 | p.addNonTerminal("expr-sub2"); | 241 | p.addNonTerminal("expr-sub2"); |
242 | { | 242 | { |
243 | Parser::NonTerminal nt; | 243 | Parser::NonTerminal nt; |
244 | nt.addProduction( | 244 | nt.addProduction( |
245 | Parser::Production( | 245 | Parser::Production( |
246 | Parser::State( | 246 | Parser::State( |
247 | Parser::State::typeTerminal, | 247 | Parser::State::typeTerminal, |
248 | tokPlus | 248 | tokPlus |
249 | ) | 249 | ) |
250 | ).append( | 250 | ).append( |
251 | Parser::State( | 251 | Parser::State( |
252 | Parser::State::typeNonTerminal, | 252 | Parser::State::typeNonTerminal, |
253 | p.getNonTerminalId("expr") | 253 | p.getNonTerminalId("expr") |
254 | ) | 254 | ) |
255 | ).append( | 255 | ).append( |
256 | Parser::State( | 256 | Parser::State( |
257 | Parser::State::typeReduction, | 257 | Parser::State::typeReduction, |
258 | p.addReduction("add") | 258 | p.addReduction("add") |
259 | ) | 259 | ) |
260 | ) | 260 | ) |
261 | ); | 261 | ); |
262 | nt.addProduction( | 262 | nt.addProduction( |
263 | Parser::Production( | 263 | Parser::Production( |
264 | Parser::State( | 264 | Parser::State( |
265 | Parser::State::typeTerminal, | 265 | Parser::State::typeTerminal, |
266 | tokMinus | 266 | tokMinus |
267 | ) | 267 | ) |
268 | ).append( | 268 | ).append( |
269 | Parser::State( | 269 | Parser::State( |
270 | Parser::State::typeNonTerminal, | 270 | Parser::State::typeNonTerminal, |
271 | p.getNonTerminalId("expr") | 271 | p.getNonTerminalId("expr") |
272 | ) | 272 | ) |
273 | ).append( | 273 | ).append( |
274 | Parser::State( | 274 | Parser::State( |
275 | Parser::State::typeReduction, | 275 | Parser::State::typeReduction, |
276 | p.addReduction("subtract") | 276 | p.addReduction("subtract") |
277 | ) | 277 | ) |
278 | ) | 278 | ) |
279 | ); | 279 | ); |
280 | nt.addProduction( | 280 | nt.addProduction( |
281 | Parser::Production( | 281 | Parser::Production( |
282 | ) | 282 | ) |
283 | ); | 283 | ); |
284 | nt.setCanSkip(); | 284 | nt.setCanSkip(); |
285 | p.setNonTerminal("expr-sub2", nt ); | 285 | p.setNonTerminal("expr-sub2", nt ); |
286 | } | 286 | } |
287 | { | 287 | { |
288 | Parser::NonTerminal nt; | 288 | Parser::NonTerminal nt; |
289 | nt.addProduction( | 289 | nt.addProduction( |
290 | Parser::Production( | 290 | Parser::Production( |
291 | Parser::State( | 291 | Parser::State( |
292 | Parser::State::typeTerminalPush, | 292 | Parser::State::typeTerminalPush, |
293 | tokNumber | 293 | tokNumber |
294 | ) | 294 | ) |
295 | ) | 295 | ) |
296 | ); | 296 | ); |
297 | nt.addProduction( | 297 | nt.addProduction( |
298 | Parser::Production( | 298 | Parser::Production( |
299 | Parser::State( | 299 | Parser::State( |
300 | Parser::State::typeTerminal, | 300 | Parser::State::typeTerminal, |
301 | tokOpenParen | 301 | tokOpenParen |
302 | ) | 302 | ) |
303 | ).append( | 303 | ).append( |
304 | Parser::State( | 304 | Parser::State( |
305 | Parser::State::typeNonTerminal, | 305 | Parser::State::typeNonTerminal, |
306 | p.getNonTerminalId("expr") | 306 | p.getNonTerminalId("expr") |
307 | ) | 307 | ) |
308 | ).append( | 308 | ).append( |
309 | Parser::State( | 309 | Parser::State( |
310 | Parser::State::typeTerminal, | 310 | Parser::State::typeTerminal, |
311 | tokCloseParen | 311 | tokCloseParen |
312 | ) | 312 | ) |
313 | ) | 313 | ) |
314 | ); | 314 | ); |
315 | p.setNonTerminal("expr-sub1", nt ); | 315 | p.setNonTerminal("expr-sub1", nt ); |
316 | } | 316 | } |
317 | { | 317 | { |
318 | Parser::NonTerminal nt; | 318 | Parser::NonTerminal nt; |
319 | nt.addProduction( | 319 | nt.addProduction( |
320 | Parser::Production( | 320 | Parser::Production( |
321 | Parser::State( | 321 | Parser::State( |
322 | Parser::State::typeNonTerminal, | 322 | Parser::State::typeNonTerminal, |
323 | p.getNonTerminalId("expr-sub1") | 323 | p.getNonTerminalId("expr-sub1") |
324 | ) | 324 | ) |
325 | ).append( | 325 | ).append( |
326 | Parser::State( | 326 | Parser::State( |
327 | Parser::State::typeNonTerminal, | 327 | Parser::State::typeNonTerminal, |
328 | p.getNonTerminalId("expr-sub2") | 328 | p.getNonTerminalId("expr-sub2") |
329 | ) | 329 | ) |
330 | ) | 330 | ) |
331 | ); | 331 | ); |
332 | p.setNonTerminal("expr", nt ); | 332 | p.setNonTerminal("expr", nt ); |
333 | } | 333 | } |
334 | { | 334 | { |
335 | Parser::NonTerminal nt; | 335 | Parser::NonTerminal nt; |
336 | nt.addProduction( | 336 | nt.addProduction( |
337 | Parser::Production( | 337 | Parser::Production( |
338 | Parser::State( | 338 | Parser::State( |
339 | Parser::State::typeNonTerminal, | 339 | Parser::State::typeNonTerminal, |
340 | p.getNonTerminalId("expr") | 340 | p.getNonTerminalId("expr") |
341 | ) | 341 | ) |
342 | ).append( | 342 | ).append( |
343 | Parser::State( | 343 | Parser::State( |
344 | Parser::State::typeTerminal, | 344 | Parser::State::typeTerminal, |
345 | tokCompute | 345 | tokCompute |
346 | ) | 346 | ) |
347 | ).append( | 347 | ).append( |
348 | Parser::State( | 348 | Parser::State( |
349 | Parser::State::typeReduction, | 349 | Parser::State::typeReduction, |
350 | p.addReduction("print") | 350 | p.addReduction("print") |
351 | ) | 351 | ) |
352 | ) | 352 | ) |
353 | ); | 353 | ); |
354 | p.addNonTerminal("input", nt ); | 354 | p.addNonTerminal("input", nt ); |
355 | } | 355 | } |
356 | 356 | ||
357 | p.setRootNonTerminal("input"); | 357 | p.setRootNonTerminal("input"); |
358 | 358 | ||
359 | p.setReduction("add", Bu::slot( &redAdd ) ); | 359 | p.setReduction("add", Bu::slot( &redAdd ) ); |
360 | p.setReduction("subtract", Bu::slot( &redSubtract ) ); | 360 | p.setReduction("subtract", Bu::slot( &redSubtract ) ); |
361 | p.setReduction("print", Bu::slot( &redPrint ) ); | 361 | p.setReduction("print", Bu::slot( &redPrint ) ); |
362 | 362 | ||
363 | p.pushLexer( new MathLexer( fIn ) ); | 363 | p.pushLexer( new MathLexer( fIn ) ); |
364 | 364 | ||
365 | p.parse(); | 365 | p.parse(); |
366 | 366 | ||
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
369 | 369 | ||