diff options
author | Mike Buland <eichlan@xagasoft.com> | 2016-12-01 09:31:45 -0700 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2016-12-01 09:31:45 -0700 |
commit | 3015ea4677201060777435cf76815e898d221f8c (patch) | |
tree | 8415fcef57ed5456ec03b2ea115ebd3789fd8c10 /src/parser.cpp | |
parent | 5b8df4e1ab3faffe5c010222ff3f8ce3a4ff810c (diff) | |
download | clic-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.
Diffstat (limited to 'src/parser.cpp')
-rw-r--r-- | src/parser.cpp | 213 |
1 files changed, 177 insertions, 36 deletions
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 | ||
39 | void Parser::exprR() | ||
40 | { | ||
41 | exprP(); | ||
42 | expr(); | ||
43 | } | ||
44 | |||
54 | void Parser::expr() | 45 | void 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 | ||
85 | void Parser::exprP() | 129 | void 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 | ||
207 | void Parser::reduce() | 273 | void 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 | ||
211 | int Parser::reqTokens( Token::Type eType ) | 334 | int Parser::reqTokens( Token::Type eType ) |
@@ -263,3 +386,21 @@ int Parser::getPriority( Token::Type eType ) | |||
263 | } | 386 | } |
264 | } | 387 | } |
265 | 388 | ||
389 | void 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 | |||