summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2016-12-01 11:54:52 -0700
committerMike Buland <eichlan@xagasoft.com>2016-12-01 11:54:52 -0700
commit17a39c19e5bff97c3b3d2bc888a3bb5ded7c1b96 (patch)
tree77ed32bfbcfc84ae5ebf2da468d6cca47796dc55
parent32b48aeb75db4ad40fe0173614e585f9bee72257 (diff)
downloadclic-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.
-rw-r--r--src/parser.cpp110
-rw-r--r--src/parser.h3
-rw-r--r--src/scriptengine.cpp8
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
11Parser::Parser( Lexer &lex ) : 18Parser::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()
34void Parser::exprR() 46void 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
40void Parser::expr() 57void 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
282void Parser::shift( const Token &t ) 301void 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
287void Parser::reduce() 309void 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
358void Parser::output( const Token &t ) 374void 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
418void Parser::printState( const Bu::String &sTag ) 436void 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:
69private: 69private:
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;