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 | |
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')
-rw-r--r-- | src/lexer.cpp | 24 | ||||
-rw-r--r-- | src/parser.cpp | 213 | ||||
-rw-r--r-- | src/parser.h | 4 | ||||
-rw-r--r-- | src/token.cpp | 12 | ||||
-rw-r--r-- | src/token.h | 4 |
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 | ||
7 | Lexer::Lexer( Bu::Stream &rIn ) : | 7 | Lexer::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 | ||
70 | Token Lexer::nextTokenNormal() | 60 | Token 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 | ||
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 | |||
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: | |||
53 | private: | 53 | private: |
54 | void expr(); | 54 | void expr(); |
55 | void exprP(); | 55 | void exprP(); |
56 | void exprR(); | ||
56 | 57 | ||
57 | private: | 58 | private: |
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 | ||
64 | private: | 66 | private: |
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 | ||
110 | Bu::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 | ||
54 | Bu::Formatter &operator<<( Bu::Formatter &f, Token::Type eType ); | 55 | Bu::Formatter &operator<<( Bu::Formatter &f, Token::Type eType ); |
56 | Bu::Formatter &operator<<( Bu::Formatter &f, const Token &t ); | ||
55 | 57 | ||
56 | #endif | 58 | #endif |