diff options
author | Mike Buland <eichlan@xagasoft.com> | 2016-12-01 11:54:52 -0700 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2016-12-01 11:54:52 -0700 |
commit | 17a39c19e5bff97c3b3d2bc888a3bb5ded7c1b96 (patch) | |
tree | 77ed32bfbcfc84ae5ebf2da468d6cca47796dc55 /src | |
parent | 32b48aeb75db4ad40fe0173614e585f9bee72257 (diff) | |
download | clic-17a39c19e5bff97c3b3d2bc888a3bb5ded7c1b96.tar.gz clic-17a39c19e5bff97c3b3d2bc888a3bb5ded7c1b96.tar.bz2 clic-17a39c19e5bff97c3b3d2bc888a3bb5ded7c1b96.tar.xz clic-17a39c19e5bff97c3b3d2bc888a3bb5ded7c1b96.zip |
Terrible parsing issues are behind us now.
At least...those issues are behind us. We'll see what happens next.
Also, added some macros to make debugging easily optional.
Diffstat (limited to 'src')
-rw-r--r-- | src/parser.cpp | 110 | ||||
-rw-r--r-- | src/parser.h | 3 | ||||
-rw-r--r-- | src/scriptengine.cpp | 8 |
3 files changed, 74 insertions, 47 deletions
diff --git a/src/parser.cpp b/src/parser.cpp index 701c4bd..e9388c8 100644 --- a/src/parser.cpp +++ b/src/parser.cpp | |||
@@ -8,6 +8,13 @@ | |||
8 | #include <bu/sio.h> | 8 | #include <bu/sio.h> |
9 | #include <stdlib.h> | 9 | #include <stdlib.h> |
10 | 10 | ||
11 | // #define DEBUG_MODE 1 | ||
12 | #ifdef DEBUG_MODE | ||
13 | #define DBG( x ) { x; } (void)0 | ||
14 | #else | ||
15 | #define DBG( x ) (void)0 | ||
16 | #endif | ||
17 | |||
11 | Parser::Parser( Lexer &lex ) : | 18 | Parser::Parser( Lexer &lex ) : |
12 | lex( lex ) | 19 | lex( lex ) |
13 | { | 20 | { |
@@ -21,10 +28,15 @@ Expression *Parser::parse() | |||
21 | { | 28 | { |
22 | pCurExp = new Expression(); | 29 | pCurExp = new Expression(); |
23 | statement(); | 30 | statement(); |
31 | while( !tsTerminal.isEmpty() ) | ||
32 | { | ||
33 | reduce(); | ||
34 | } | ||
24 | 35 | ||
25 | printState("Final"); | 36 | printState("Final"); |
26 | 37 | ||
27 | tsParse.clear(); | 38 | tsTerminal.clear(); |
39 | tsNonTerminal.clear(); | ||
28 | 40 | ||
29 | Expression *pTmp = pCurExp; | 41 | Expression *pTmp = pCurExp; |
30 | pCurExp = NULL; | 42 | pCurExp = NULL; |
@@ -34,12 +46,17 @@ Expression *Parser::parse() | |||
34 | void Parser::exprR() | 46 | void Parser::exprR() |
35 | { | 47 | { |
36 | exprP(); | 48 | exprP(); |
37 | expr(); | 49 | for(;;) |
50 | { | ||
51 | expr(); | ||
52 | if( !(lex[0].eType & Token::mMetaOperator) ) | ||
53 | break; | ||
54 | } | ||
38 | } | 55 | } |
39 | 56 | ||
40 | void Parser::expr() | 57 | void Parser::expr() |
41 | { | 58 | { |
42 | Bu::sio << "::expr " << lex[0] << Bu::sio.nl; | 59 | DBG( Bu::sio << "::expr " << lex[0] << Bu::sio.nl ); |
43 | if( lex[0].eType == Token::tEndOfInput ) | 60 | if( lex[0].eType == Token::tEndOfInput ) |
44 | return; | 61 | return; |
45 | 62 | ||
@@ -56,7 +73,7 @@ void Parser::expr() | |||
56 | case Token::tModulus: | 73 | case Token::tModulus: |
57 | Token t = lex[0]; | 74 | Token t = lex[0]; |
58 | lex.nextToken(); | 75 | lex.nextToken(); |
59 | Bu::sio << "->expr " << t << " " << lex[0] << Bu::sio.nl; | 76 | DBG( Bu::sio << "->expr " << t << " " << lex[0] << Bu::sio.nl ); |
60 | if( lex[0].eType == Token::tOpenParen ) | 77 | if( lex[0].eType == Token::tOpenParen ) |
61 | { | 78 | { |
62 | exprP(); | 79 | exprP(); |
@@ -69,40 +86,42 @@ void Parser::expr() | |||
69 | if( lex[0].eType == Token::tNumber || | 86 | if( lex[0].eType == Token::tNumber || |
70 | lex[0].eType == Token::tVariable ) | 87 | lex[0].eType == Token::tVariable ) |
71 | { | 88 | { |
72 | Bu::sio << "->expr " << t << | 89 | DBG( Bu::sio << "->expr " << t << |
73 | " " << lex[0] << | 90 | " " << lex[0] << |
74 | " " << lex[1] << | 91 | " " << lex[1] << |
75 | Bu::sio.nl; | 92 | Bu::sio.nl ); |
76 | shift( lex[0] ); | 93 | shift( lex[0] ); |
94 | shift( t ); | ||
77 | if( lex[1].eType&Token::mMetaOperator ) | 95 | if( lex[1].eType&Token::mMetaOperator ) |
78 | { | 96 | { |
79 | if( getPriority(lex[1].eType) <= | 97 | if( getPriority(lex[1].eType) < |
80 | getPriority(t.eType) ) | 98 | getPriority(t.eType) ) |
81 | { | 99 | { |
82 | shift( t ); | 100 | while( !tsTerminal.isEmpty() ) |
83 | reduce(); | 101 | { |
102 | reduce(); | ||
103 | } | ||
84 | printState("reduce"); | 104 | printState("reduce"); |
85 | lex.nextToken(); | 105 | lex.nextToken(); |
86 | expr(); | 106 | // expr(); |
87 | } | 107 | } |
88 | else | 108 | else |
89 | { | 109 | { |
90 | printState("no reduce"); | 110 | printState("no reduce"); |
91 | lex.nextToken(); | 111 | lex.nextToken(); |
92 | expr(); | 112 | // expr(); |
93 | if( !tsParse.isEmpty() && | 113 | /* |
114 | if( !tsNonTerminal.isEmpty() && | ||
94 | tsParse.peek().eType != Token::tComputedValue ) | 115 | tsParse.peek().eType != Token::tComputedValue ) |
95 | { | 116 | { |
96 | reduce(); | 117 | //reduce(); |
97 | printState("no reduce reduce"); | 118 | //printState("no reduce reduce"); |
98 | } | 119 | }*/ |
99 | shift( t ); | ||
100 | printState("post no reduce"); | 120 | printState("post no reduce"); |
101 | } | 121 | } |
102 | } | 122 | } |
103 | else | 123 | else |
104 | { | 124 | { |
105 | shift( t ); | ||
106 | lex.nextToken(); | 125 | lex.nextToken(); |
107 | printState("no next op"); | 126 | printState("no next op"); |
108 | } | 127 | } |
@@ -110,14 +129,14 @@ void Parser::expr() | |||
110 | else if( lex[0].eType == Token::tMinus ) | 129 | else if( lex[0].eType == Token::tMinus ) |
111 | { | 130 | { |
112 | // This is negation | 131 | // This is negation |
113 | Bu::sio << "next token: " << lex[0] << Bu::sio.nl; | 132 | DBG( Bu::sio << "next token: " << lex[0] << Bu::sio.nl ); |
114 | printState("inline-negate"); | 133 | printState("inline-negate"); |
115 | exprP(); | 134 | exprP(); |
116 | printState("inline-negate-post"); | 135 | printState("inline-negate-post"); |
117 | shift( t ); | 136 | shift( t ); |
118 | printState("inline-negate-post2"); | 137 | printState("inline-negate-post2"); |
119 | 138 | ||
120 | Bu::sio << "??? " << lex[0] << Bu::sio.nl; | 139 | DBG( Bu::sio << "??? " << lex[0] << Bu::sio.nl ); |
121 | } | 140 | } |
122 | } | 141 | } |
123 | break; | 142 | break; |
@@ -156,7 +175,7 @@ void Parser::exprP() | |||
156 | exprR(); | 175 | exprR(); |
157 | if( lex[0].eType != Token::tCloseParen ) | 176 | if( lex[0].eType != Token::tCloseParen ) |
158 | { | 177 | { |
159 | Bu::sio << "::exprP " << lex[0] << Bu::sio.nl; | 178 | DBG( Bu::sio << "::exprP " << lex[0] << Bu::sio.nl ); |
160 | throw Bu::ExceptionBase("Expected close paren"); | 179 | throw Bu::ExceptionBase("Expected close paren"); |
161 | } | 180 | } |
162 | shift( lex[0] ); | 181 | shift( lex[0] ); |
@@ -281,16 +300,20 @@ case Token::tCommand: | |||
281 | 300 | ||
282 | void Parser::shift( const Token &t ) | 301 | void Parser::shift( const Token &t ) |
283 | { | 302 | { |
284 | tsParse.push( t ); | 303 | if( (t.eType&(Token::mMetaOperator)) || t.eType==Token::tCloseParen ) |
304 | tsTerminal.push( t ); | ||
305 | else | ||
306 | tsNonTerminal.push( t ); | ||
285 | } | 307 | } |
286 | 308 | ||
287 | void Parser::reduce() | 309 | void Parser::reduce() |
288 | { | 310 | { |
289 | if( tsParse.isEmpty() || tsParse.peek().eType == Token::tOpenParen ) | 311 | if( tsTerminal.isEmpty() || tsNonTerminal.peek().eType == Token::tOpenParen ) |
290 | return; | 312 | return; |
291 | Token tOp = tsParse.peekPop(); | 313 | Token tOp = tsTerminal.peekPop(); |
292 | switch( tOp.eType ) | 314 | switch( tOp.eType ) |
293 | { | 315 | { |
316 | /* | ||
294 | case Token::tNumber: | 317 | case Token::tNumber: |
295 | case Token::tVariable: | 318 | case Token::tVariable: |
296 | output( tOp ); | 319 | output( tOp ); |
@@ -300,25 +323,18 @@ void Parser::reduce() | |||
300 | case Token::tComputedValue: | 323 | case Token::tComputedValue: |
301 | tsParse.push( Token( Token::tComputedValue ) ); | 324 | tsParse.push( Token( Token::tComputedValue ) ); |
302 | break; | 325 | break; |
303 | 326 | */ | |
304 | case Token::tPlus: | 327 | case Token::tPlus: |
305 | case Token::tMinus: | 328 | case Token::tMinus: |
306 | case Token::tDivide: | 329 | case Token::tDivide: |
307 | case Token::tMultiply: | 330 | case Token::tMultiply: |
308 | case Token::tModulus: | 331 | case Token::tModulus: |
309 | case Token::tEquals: | 332 | case Token::tEquals: |
310 | for(int j = 0; j < 2; j++ ) | ||
311 | { | 333 | { |
312 | Token t = tsParse.peekPop(); | 334 | Token a = tsNonTerminal.peekPop(); |
313 | if( t.eType == Token::tNumber || | 335 | Token b = tsNonTerminal.peekPop(); |
314 | t.eType == Token::tVariable ) | 336 | output( b ); |
315 | { | 337 | output( a ); |
316 | output( t ); | ||
317 | } | ||
318 | else if( t.eType == Token::tComputedValue ) | ||
319 | { | ||
320 | // Nope, we don't care | ||
321 | } | ||
322 | } | 338 | } |
323 | output( tOp ); | 339 | output( tOp ); |
324 | shift( Token( Token::tComputedValue ) ); | 340 | shift( Token( Token::tComputedValue ) ); |
@@ -326,7 +342,7 @@ void Parser::reduce() | |||
326 | 342 | ||
327 | case Token::tNegate: | 343 | case Token::tNegate: |
328 | { | 344 | { |
329 | Token t = tsParse.peekPop(); | 345 | Token t = tsNonTerminal.peekPop(); |
330 | if( t.eType != Token::tComputedValue ) | 346 | if( t.eType != Token::tComputedValue ) |
331 | output( t ); | 347 | output( t ); |
332 | output( tOp ); | 348 | output( tOp ); |
@@ -335,16 +351,16 @@ void Parser::reduce() | |||
335 | break; | 351 | break; |
336 | 352 | ||
337 | case Token::tCloseParen: | 353 | case Token::tCloseParen: |
338 | if( tsParse.peek().eType != Token::tComputedValue ) | 354 | if( tsNonTerminal.peek().eType != Token::tComputedValue ) |
339 | { | 355 | { |
340 | printState("paren-innerReduce-pre"); | 356 | printState("paren-innerReduce-pre"); |
341 | reduce(); | 357 | reduce(); |
342 | printState("paren-innerReduce-post"); | 358 | printState("paren-innerReduce-post"); |
343 | } | 359 | } |
344 | tsParse.pop(); | 360 | tsNonTerminal.pop(); |
345 | if( tsParse.peek().eType == Token::tOpenParen ) | 361 | if( tsNonTerminal.peek().eType == Token::tOpenParen ) |
346 | { | 362 | { |
347 | tsParse.pop(); | 363 | tsNonTerminal.pop(); |
348 | shift( Token( Token::tComputedValue ) ); | 364 | shift( Token( Token::tComputedValue ) ); |
349 | } | 365 | } |
350 | else | 366 | else |
@@ -357,6 +373,8 @@ void Parser::reduce() | |||
357 | 373 | ||
358 | void Parser::output( const Token &t ) | 374 | void Parser::output( const Token &t ) |
359 | { | 375 | { |
376 | if( t.eType == Token::tComputedValue ) | ||
377 | return; | ||
360 | pCurExp->append( t ); | 378 | pCurExp->append( t ); |
361 | } | 379 | } |
362 | 380 | ||
@@ -417,9 +435,16 @@ int Parser::getPriority( Token::Type eType ) | |||
417 | 435 | ||
418 | void Parser::printState( const Bu::String &sTag ) | 436 | void Parser::printState( const Bu::String &sTag ) |
419 | { | 437 | { |
438 | #ifdef DEBUG_MODE | ||
420 | Bu::sio << "----------------" << Bu::sio.nl; | 439 | Bu::sio << "----------------" << Bu::sio.nl; |
421 | Bu::sio << sTag << " stack:"; | 440 | Bu::sio << sTag << " non-terminals:"; |
422 | for( TokenStack::iterator i = tsParse.begin(); i; i++ ) | 441 | for( TokenStack::iterator i = tsNonTerminal.begin(); i; i++ ) |
442 | { | ||
443 | Bu::sio << " " << (*i); | ||
444 | } | ||
445 | Bu::sio << Bu::sio.nl; | ||
446 | Bu::sio << sTag << " terminal:"; | ||
447 | for( TokenStack::iterator i = tsTerminal.begin(); i; i++ ) | ||
423 | { | 448 | { |
424 | Bu::sio << " " << (*i); | 449 | Bu::sio << " " << (*i); |
425 | } | 450 | } |
@@ -431,5 +456,6 @@ void Parser::printState( const Bu::String &sTag ) | |||
431 | } | 456 | } |
432 | Bu::sio << Bu::sio.nl; | 457 | Bu::sio << Bu::sio.nl; |
433 | Bu::sio << "----------------" << Bu::sio.nl; | 458 | Bu::sio << "----------------" << Bu::sio.nl; |
459 | #endif | ||
434 | } | 460 | } |
435 | 461 | ||
diff --git a/src/parser.h b/src/parser.h index 60dd8e1..cc97222 100644 --- a/src/parser.h +++ b/src/parser.h | |||
@@ -69,7 +69,8 @@ private: | |||
69 | private: | 69 | private: |
70 | Lexer &lex; | 70 | Lexer &lex; |
71 | typedef Bu::List<Token> TokenStack; | 71 | typedef Bu::List<Token> TokenStack; |
72 | TokenStack tsParse; | 72 | TokenStack tsTerminal; |
73 | TokenStack tsNonTerminal; | ||
73 | Expression *pCurExp; | 74 | Expression *pCurExp; |
74 | }; | 75 | }; |
75 | 76 | ||
diff --git a/src/scriptengine.cpp b/src/scriptengine.cpp index b828409..65b6ec2 100644 --- a/src/scriptengine.cpp +++ b/src/scriptengine.cpp | |||
@@ -57,32 +57,32 @@ Number ScriptEngine::exec( Expression *pExpr ) | |||
57 | 57 | ||
58 | case Token::tPlus: | 58 | case Token::tPlus: |
59 | { | 59 | { |
60 | Number a = sNums.peekPop(); | ||
61 | Number b = sNums.peekPop(); | 60 | Number b = sNums.peekPop(); |
61 | Number a = sNums.peekPop(); | ||
62 | sNums.push( a + b ); | 62 | sNums.push( a + b ); |
63 | } | 63 | } |
64 | break; | 64 | break; |
65 | 65 | ||
66 | case Token::tMinus: | 66 | case Token::tMinus: |
67 | { | 67 | { |
68 | Number a = sNums.peekPop(); | ||
69 | Number b = sNums.peekPop(); | 68 | Number b = sNums.peekPop(); |
69 | Number a = sNums.peekPop(); | ||
70 | sNums.push( a - b ); | 70 | sNums.push( a - b ); |
71 | } | 71 | } |
72 | break; | 72 | break; |
73 | 73 | ||
74 | case Token::tDivide: | 74 | case Token::tDivide: |
75 | { | 75 | { |
76 | Number a = sNums.peekPop(); | ||
77 | Number b = sNums.peekPop(); | 76 | Number b = sNums.peekPop(); |
77 | Number a = sNums.peekPop(); | ||
78 | sNums.push( a / b ); | 78 | sNums.push( a / b ); |
79 | } | 79 | } |
80 | break; | 80 | break; |
81 | 81 | ||
82 | case Token::tMultiply: | 82 | case Token::tMultiply: |
83 | { | 83 | { |
84 | Number a = sNums.peekPop(); | ||
85 | Number b = sNums.peekPop(); | 84 | Number b = sNums.peekPop(); |
85 | Number a = sNums.peekPop(); | ||
86 | sNums.push( a * b ); | 86 | sNums.push( a * b ); |
87 | } | 87 | } |
88 | break; | 88 | break; |