summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2016-12-01 09:31:45 -0700
committerMike Buland <eichlan@xagasoft.com>2016-12-01 09:31:45 -0700
commit3015ea4677201060777435cf76815e898d221f8c (patch)
tree8415fcef57ed5456ec03b2ea115ebd3789fd8c10
parent5b8df4e1ab3faffe5c010222ff3f8ce3a4ff810c (diff)
downloadclic-3015ea4677201060777435cf76815e898d221f8c.tar.gz
clic-3015ea4677201060777435cf76815e898d221f8c.tar.bz2
clic-3015ea4677201060777435cf76815e898d221f8c.tar.xz
clic-3015ea4677201060777435cf76815e898d221f8c.zip
The parser works.
There's still more to do, however. It doesn't do math anymore, it produces a script that can then be executed. Now we have to capture that script and execute it.
-rw-r--r--src/lexer.cpp24
-rw-r--r--src/parser.cpp213
-rw-r--r--src/parser.h4
-rw-r--r--src/token.cpp12
-rw-r--r--src/token.h4
5 files changed, 201 insertions, 56 deletions
diff --git a/src/lexer.cpp b/src/lexer.cpp
index 538e088..87d603a 100644
--- a/src/lexer.cpp
+++ b/src/lexer.cpp
@@ -6,7 +6,7 @@
6 6
7Lexer::Lexer( Bu::Stream &rIn ) : 7Lexer::Lexer( Bu::Stream &rIn ) :
8 rIn( rIn ), 8 rIn( rIn ),
9 iBufPos( 0 ), 9 iBufPos( -1 ),
10 iScale( 0 ), 10 iScale( 0 ),
11 iRadix( 10 ), 11 iRadix( 10 ),
12 numRangeTop('9'), 12 numRangeTop('9'),
@@ -55,28 +55,12 @@ void Lexer::fillToken()
55 default: 55 default:
56 throw Bu::ExceptionBase("Invalid mode."); 56 throw Bu::ExceptionBase("Invalid mode.");
57 } 57 }
58/*
59 Bu::sio << "read["
60 << ((iLookAheadUsed+iLookAheadStart)%iLookAheadSize)
61 << "]: "
62 << aLookAhead[(iLookAheadUsed+iLookAheadStart)%iLookAheadSize].eType;
63 if( aLookAhead[(iLookAheadUsed+iLookAheadStart)%iLookAheadSize].eType == Token::tNumber )
64 Bu::sio << "("
65 << aLookAhead[(iLookAheadUsed+iLookAheadStart)%iLookAheadSize].nVal->toString() << ")";
66 Bu::sio << Bu::sio.nl;
67*/
68} 58}
69 59
70Token Lexer::nextTokenNormal() 60Token Lexer::nextTokenNormal()
71{ 61{
72 for(;;) 62 for(;;)
73 { 63 {
74 if( iBufPos >= sBuf.getSize() )
75 {
76 iBufPos = -1;
77 return Token( Token::tEndOfLine );
78 }
79
80 if( iBufPos < 0 ) 64 if( iBufPos < 0 )
81 { 65 {
82 if( rIn.isEos() ) 66 if( rIn.isEos() )
@@ -90,8 +74,12 @@ Token Lexer::nextTokenNormal()
90 } 74 }
91 iBufPos = 0; 75 iBufPos = 0;
92 } 76 }
77 if( iBufPos >= sBuf.getSize() )
78 {
79 iBufPos = -1;
80 return Token( Token::tEndOfLine );
81 }
93 82
94 //Bu::println("Testing char '%1' at %2").arg( sBuf[iBufPos] ).arg( iBufPos );
95 switch( sBuf[iBufPos] ) 83 switch( sBuf[iBufPos] )
96 { 84 {
97 case ' ': 85 case ' ':
diff --git a/src/parser.cpp b/src/parser.cpp
index 510b471..f88ffe7 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -26,49 +26,34 @@ void Parser::parse()
26 if( lex[0].eType == Token::tEndOfInput ) 26 if( lex[0].eType == Token::tEndOfInput )
27 break; 27 break;
28 28
29 expr(); 29 exprR();
30 reduce();
30 31
31 Bu::sio << "Final stack:"; 32 printState("Final");
32 for( TokenStack::iterator i = tsParse.begin(); i; i++ ) 33
33 { 34 tsParse.clear();
34 Bu::sio << " " << (*i).eType; 35 tsScript.clear();
35 if( (*i).eType == Token::tNumber )
36 {
37 Bu::sio << "(" << (*i).nVal->toString() << ")";
38 }
39 }
40 Bu::sio << Bu::sio.nl;
41 Bu::sio << "Script:";
42 for( TokenStack::iterator i = tsScript.begin(); i; i++ )
43 {
44 Bu::sio << " " << (*i).eType;
45 if( (*i).eType == Token::tNumber )
46 {
47 Bu::sio << "(" << (*i).nVal->toString() << ")";
48 }
49 }
50 Bu::sio << Bu::sio.nl;
51 } 36 }
52} 37}
53 38
39void Parser::exprR()
40{
41 exprP();
42 expr();
43}
44
54void Parser::expr() 45void Parser::expr()
55{ 46{
47 Bu::sio << "::expr " << lex[0] << Bu::sio.nl;
56 if( lex[0].eType == Token::tEndOfInput ) 48 if( lex[0].eType == Token::tEndOfInput )
57 return; 49 return;
58 if( lex[0].eType == Token::tVariable &&
59 lex[1].eType == Token::tEquals )
60 {
61 Token t = lex[0];
62 lex.nextToken();
63 lex.nextToken();
64 expr();
65
66 return;
67 }
68 exprP();
69 50
70 switch( lex[0].eType ) 51 switch( lex[0].eType )
71 { 52 {
53 case Token::tEquals:
54 throw Bu::ExceptionBase("misplaced equals.");
55 break;
56
72 case Token::tPlus: 57 case Token::tPlus:
73 case Token::tMinus: 58 case Token::tMinus:
74 case Token::tMultiply: 59 case Token::tMultiply:
@@ -76,30 +61,111 @@ void Parser::expr()
76 case Token::tModulus: 61 case Token::tModulus:
77 Token t = lex[0]; 62 Token t = lex[0];
78 lex.nextToken(); 63 lex.nextToken();
79 expr(); 64 Bu::sio << "->expr " << t << " " << lex[0] << Bu::sio.nl;
80 shift( t ); 65 if( lex[0].eType == Token::tOpenParen )
66 {
67 exprP();
68 shift( t );
69 reduce();
70 expr();
71 }
72 else
73 {
74 if( lex[0].eType == Token::tNumber ||
75 lex[0].eType == Token::tVariable )
76 {
77 Bu::sio << "->expr " << t <<
78 " " << lex[0] <<
79 " " << lex[1] <<
80 Bu::sio.nl;
81 shift( lex[0] );
82 if( lex[1].eType == Token::tPlus ||
83 lex[1].eType == Token::tMinus ||
84 lex[1].eType == Token::tDivide ||
85 lex[1].eType == Token::tMultiply ||
86 lex[1].eType == Token::tModulus ||
87 lex[1].eType == Token::tEquals )
88 {
89 if( getPriority(lex[1].eType) <=
90 getPriority(t.eType) )
91 {
92 shift( t );
93 reduce();
94 printState("reduce");
95 lex.nextToken();
96 expr();
97 }
98 else
99 {
100 printState("no reduce");
101 lex.nextToken();
102 expr();
103 if( !tsParse.isEmpty() &&
104 tsParse.peek().eType != Token::tComputedValue )
105 {
106 reduce();
107 printState("no reduce reduce");
108 }
109 shift( t );
110 printState("post no reduce");
111 }
112 }
113 else
114 {
115 shift( t );
116 lex.nextToken();
117 printState("no next op");
118 }
119 }
120 else
121 {
122 Bu::println("???");
123 }
124 }
81 break; 125 break;
82 } 126 }
83} 127}
84 128
85void Parser::exprP() 129void Parser::exprP()
86{ 130{
131 if( lex[0].eType == Token::tVariable &&
132 lex[1].eType == Token::tEquals )
133 {
134 Token t = lex[0];
135 lex.nextToken( 2 );
136 exprR();
137 reduce();
138 printState("pre-equals");
139 shift( t );
140 shift( Token( Token::tEquals ) );
141 printState("post-equals");
142 reduce();
143 printState("post-equals-reduce");
144 return;
145 }
146
87 switch( lex[0].eType ) 147 switch( lex[0].eType )
88 { 148 {
89 case Token::tNumber: 149 case Token::tNumber:
90 case Token::tVariable: 150 case Token::tVariable:
91 shift( lex[0] ); 151 shift( lex[0] );
92 lex.nextToken(); 152 lex.nextToken();
93 break; 153 break;
94 154
95 case Token::tOpenParen: 155 case Token::tOpenParen:
156 shift( lex[0] );
96 lex.nextToken(); 157 lex.nextToken();
97 expr(); 158 exprR();
98 if( lex[0].eType != Token::tCloseParen ) 159 if( lex[0].eType != Token::tCloseParen )
99 { 160 {
161 Bu::sio << "::exprP " << lex[0] << Bu::sio.nl;
100 throw Bu::ExceptionBase("Expected close paren"); 162 throw Bu::ExceptionBase("Expected close paren");
101 } 163 }
164 shift( lex[0] );
165 printState("closeParen");
166 reduce();
102 lex.nextToken(); 167 lex.nextToken();
168 printState("post closeParen");
103 break; 169 break;
104 170
105 case Token::tMinus: 171 case Token::tMinus:
@@ -206,6 +272,63 @@ void Parser::shift( const Token &t )
206 272
207void Parser::reduce() 273void Parser::reduce()
208{ 274{
275 if( tsParse.isEmpty() || tsParse.peek().eType == Token::tOpenParen )
276 return;
277 Token tOp = tsParse.peekPop();
278 switch( tOp.eType )
279 {
280 case Token::tNumber:
281 case Token::tVariable:
282 tsScript.append( tOp );
283 tsParse.push( Token( Token::tComputedValue ) );
284 break;
285
286 case Token::tComputedValue:
287 tsParse.push( Token( Token::tComputedValue ) );
288 break;
289
290 case Token::tPlus:
291 case Token::tMinus:
292 case Token::tDivide:
293 case Token::tMultiply:
294 case Token::tModulus:
295 case Token::tEquals:
296 for(int j = 0; j < 2; j++ )
297 {
298 Token t = tsParse.peekPop();
299 if( t.eType == Token::tNumber ||
300 t.eType == Token::tVariable )
301 {
302 tsScript.append( t );
303 }
304 else if( t.eType == Token::tComputedValue )
305 {
306 // Nope, we don't care
307 }
308 }
309 tsScript.append( tOp );
310 shift( Token( Token::tComputedValue ) );
311 break;
312
313 case Token::tCloseParen:
314 if( tsParse.peek().eType != Token::tComputedValue )
315 {
316 printState("paren-innerReduce-pre");
317 reduce();
318 printState("paren-innerReduce-post");
319 }
320 tsParse.pop();
321 if( tsParse.peek().eType == Token::tOpenParen )
322 {
323 tsParse.pop();
324 shift( Token( Token::tComputedValue ) );
325 }
326 else
327 {
328 throw Bu::ExceptionBase("Error?");
329 }
330 break;
331 }
209} 332}
210 333
211int Parser::reqTokens( Token::Type eType ) 334int Parser::reqTokens( Token::Type eType )
@@ -263,3 +386,21 @@ int Parser::getPriority( Token::Type eType )
263 } 386 }
264} 387}
265 388
389void Parser::printState( const Bu::String &sTag )
390{
391 Bu::sio << "----------------" << Bu::sio.nl;
392 Bu::sio << sTag << " stack:";
393 for( TokenStack::iterator i = tsParse.begin(); i; i++ )
394 {
395 Bu::sio << " " << (*i);
396 }
397 Bu::sio << Bu::sio.nl;
398 Bu::sio << sTag << " script:";
399 for( TokenStack::iterator i = tsScript.begin(); i; i++ )
400 {
401 Bu::sio << " " << (*i);
402 }
403 Bu::sio << Bu::sio.nl;
404 Bu::sio << "----------------" << Bu::sio.nl;
405}
406
diff --git a/src/parser.h b/src/parser.h
index 1caa229..b0a1231 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -53,13 +53,15 @@ public:
53private: 53private:
54 void expr(); 54 void expr();
55 void exprP(); 55 void exprP();
56 void exprR();
56 57
57private: 58private:
58 void shift( const Token &t ); 59 void shift( const Token &t );
59 void reduce(); 60 void reduce();
60 int reqTokens( Token::Type eType ); 61 int reqTokens( Token::Type eType );
61 int getPriority( Token::Type eType ); 62 int getPriority( Token::Type eType );
62 Number &deref( Token &t ); 63
64 void printState( const Bu::String &sTag );
63 65
64private: 66private:
65 Lexer &lex; 67 Lexer &lex;
diff --git a/src/token.cpp b/src/token.cpp
index 1eaa92a..0c7bda1 100644
--- a/src/token.cpp
+++ b/src/token.cpp
@@ -100,8 +100,20 @@ Bu::Formatter &operator<<( Bu::Formatter &f, Token::Type eType )
100 case Token::tEndOfLine: return f << "eol"; 100 case Token::tEndOfLine: return f << "eol";
101 case Token::tEndOfInput: return f << "eoi"; 101 case Token::tEndOfInput: return f << "eoi";
102 case Token::tNegate: return f << "neg"; 102 case Token::tNegate: return f << "neg";
103 case Token::tUninitialized: return f << "<->";
104 case Token::tComputedValue: return f << "cmp";
103 105
104 default: return f << "???"; 106 default: return f << "???";
105 } 107 }
106} 108}
107 109
110Bu::Formatter &operator<<( Bu::Formatter &f, const Token &t )
111{
112 f << t.eType;
113 if( t.eType == Token::tNumber )
114 f << "(" << (t.nVal?t.nVal->toString():"<null>") << ")";
115 else if( t.eType == Token::tString || t.eType == Token::tVariable )
116 f << "(" << (t.sVal?*(t.sVal):"<null>") << ")";
117 return f;
118}
119
diff --git a/src/token.h b/src/token.h
index 8d7dc20..072a96b 100644
--- a/src/token.h
+++ b/src/token.h
@@ -31,7 +31,8 @@ public:
31 31
32 tEndOfInput, 32 tEndOfInput,
33 33
34 tUninitialized 34 tUninitialized,
35 tComputedValue
35 }; 36 };
36 37
37 Token(); 38 Token();
@@ -52,5 +53,6 @@ public:
52}; 53};
53 54
54Bu::Formatter &operator<<( Bu::Formatter &f, Token::Type eType ); 55Bu::Formatter &operator<<( Bu::Formatter &f, Token::Type eType );
56Bu::Formatter &operator<<( Bu::Formatter &f, const Token &t );
55 57
56#endif 58#endif