diff options
Diffstat (limited to 'src/experimental/parser.cpp')
-rw-r--r-- | src/experimental/parser.cpp | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/src/experimental/parser.cpp b/src/experimental/parser.cpp new file mode 100644 index 0000000..4d9f793 --- /dev/null +++ b/src/experimental/parser.cpp | |||
@@ -0,0 +1,311 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2011 Xagasoft, All rights reserved. | ||
3 | * | ||
4 | * This file is part of the libbu++ library and is released under the | ||
5 | * terms of the license contained in the file LICENSE. | ||
6 | */ | ||
7 | |||
8 | #include "bu/parser.h" | ||
9 | #include "bu/lexer.h" | ||
10 | |||
11 | #include "bu/sio.h" | ||
12 | using namespace Bu; | ||
13 | |||
14 | Bu::Parser::Parser() | ||
15 | { | ||
16 | } | ||
17 | |||
18 | Bu::Parser::~Parser() | ||
19 | { | ||
20 | } | ||
21 | |||
22 | void Bu::Parser::pushLexer( Lexer *pLex ) | ||
23 | { | ||
24 | sLexer.push( pLex ); | ||
25 | } | ||
26 | |||
27 | void Bu::Parser::popLexer() | ||
28 | { | ||
29 | delete sLexer.peekPop(); | ||
30 | } | ||
31 | |||
32 | Lexer::Token *Bu::Parser::popToken() | ||
33 | { | ||
34 | return sToken.peekPop(); | ||
35 | } | ||
36 | |||
37 | void Bu::Parser::pushToken( Lexer::Token *pTok ) | ||
38 | { | ||
39 | sToken.push( pTok ); | ||
40 | } | ||
41 | |||
42 | void Bu::Parser::parse() | ||
43 | { | ||
44 | int iCurNt = iRootNonTerminal; | ||
45 | Lexer::Token *ptCur = sLexer.peek()->nextToken(); | ||
46 | sio << "Token(a): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; | ||
47 | selectProduction( iCurNt, ptCur ); | ||
48 | |||
49 | while( !sState.isEmpty() ) | ||
50 | { | ||
51 | switch( (*sState.peek()).eType ) | ||
52 | { | ||
53 | case State::typeTerminal: | ||
54 | sio << "terminal: " << ptCur->iToken << " == " | ||
55 | << (*sState.peek()).iIndex << sio.nl; | ||
56 | if( ptCur->iToken == (*sState.peek()).iIndex ) | ||
57 | { | ||
58 | advanceState(); | ||
59 | delete ptCur; | ||
60 | ptCur = sLexer.peek()->nextToken(); | ||
61 | sio << "Token(b): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; | ||
62 | } | ||
63 | else | ||
64 | { | ||
65 | throw Bu::ExceptionBase("Error parsing code."); | ||
66 | } | ||
67 | break; | ||
68 | |||
69 | case State::typeTerminalPush: | ||
70 | sio << "terminalpush: " << ptCur->iToken << " == " | ||
71 | << (*sState.peek()).iIndex << sio.nl; | ||
72 | if( ptCur->iToken == (*sState.peek()).iIndex ) | ||
73 | { | ||
74 | advanceState(); | ||
75 | sToken.push( ptCur ); | ||
76 | |||
77 | ptCur = sLexer.peek()->nextToken(); | ||
78 | sio << "Token(c): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; | ||
79 | } | ||
80 | else | ||
81 | { | ||
82 | throw Bu::ExceptionBase("Error parsing code."); | ||
83 | } | ||
84 | break; | ||
85 | |||
86 | case State::typeNonTerminal: | ||
87 | sio << "nonterminal: " << ptCur->iToken << " --> " | ||
88 | << (*sState.peek()).iIndex << sio.nl; | ||
89 | { | ||
90 | int iNt = (*sState.peek()).iIndex; | ||
91 | sio << "Current state: " << *sState.peek() << sio.nl; | ||
92 | if( !selectProduction( iNt, ptCur ) ) | ||
93 | { | ||
94 | throw Bu::ExceptionBase("Error parsing code."); | ||
95 | } | ||
96 | } | ||
97 | break; | ||
98 | |||
99 | case State::typeReduction: | ||
100 | sio << "reduction" << sio.nl; | ||
101 | aReduction[(*sState.peek()).iIndex]( *this ); | ||
102 | advanceState(); | ||
103 | break; | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | |||
108 | bool Bu::Parser::selectProduction( int iNt, Lexer::Token *ptCur ) | ||
109 | { | ||
110 | NonTerminal &nt = aNonTerminal[iNt]; | ||
111 | int j = 0; | ||
112 | for( NonTerminal::ProductionList::iterator i = nt.lProduction.begin(); | ||
113 | i; i++,j++ ) | ||
114 | { | ||
115 | if( (*i).isEmpty() ) | ||
116 | continue; | ||
117 | sio << "-->(Attempting production " << iNt << ":" << j << ": " | ||
118 | << (*i).first() << ")" << sio.nl; | ||
119 | if( (*i).first().eType == State::typeTerminal || | ||
120 | (*i).first().eType == State::typeTerminalPush ) | ||
121 | { | ||
122 | if( (*i).first().iIndex == ptCur->iToken ) | ||
123 | { | ||
124 | sState.push( (*i).begin() ); | ||
125 | sio.incIndent(); | ||
126 | sio << "Pushing production " << j << " from nt " << iNt | ||
127 | << sio.nl; | ||
128 | return true; | ||
129 | } | ||
130 | } | ||
131 | else if( (*i).first().eType == State::typeNonTerminal ) | ||
132 | { | ||
133 | sState.push( (*i).begin() ); | ||
134 | sio.incIndent(); | ||
135 | sio << "Pushing production " << j << " from nt " << iNt | ||
136 | << " as test." << sio.nl; | ||
137 | if( !selectProduction( (*i).first().iIndex, ptCur ) ) | ||
138 | { | ||
139 | sio.decIndent(); | ||
140 | sState.pop(); | ||
141 | sio << "Production " << j << " from nt " << iNt | ||
142 | << " didn't work out." << sio.nl; | ||
143 | } | ||
144 | else | ||
145 | { | ||
146 | return true; | ||
147 | } | ||
148 | } | ||
149 | } | ||
150 | if( nt.bCanSkip ) | ||
151 | { | ||
152 | sio << "Nothing matches, skipping non-terminal." << sio.nl; | ||
153 | advanceState(); | ||
154 | return true; | ||
155 | } | ||
156 | sio << "-->(Found nothing)" << sio.nl; | ||
157 | return false; | ||
158 | } | ||
159 | |||
160 | void Bu::Parser::advanceState() | ||
161 | { | ||
162 | if( sState.isEmpty() ) | ||
163 | return; | ||
164 | |||
165 | sState.peek()++; | ||
166 | if( !sState.peek() ) | ||
167 | { | ||
168 | sio.decIndent(); | ||
169 | sState.pop(); | ||
170 | sio << "State advanced, End of production." << sio.nl; | ||
171 | advanceState(); | ||
172 | return; | ||
173 | } | ||
174 | sio << "State advanced, now: " << *(sState.peek()) << sio.nl; | ||
175 | } | ||
176 | |||
177 | void Bu::Parser::setRootNonTerminal( int iRoot ) | ||
178 | { | ||
179 | iRootNonTerminal = iRoot; | ||
180 | } | ||
181 | |||
182 | void Bu::Parser::setRootNonTerminal( const Bu::String &sRoot ) | ||
183 | { | ||
184 | setRootNonTerminal( hNonTerminalName.get( sRoot ) ); | ||
185 | } | ||
186 | |||
187 | int Bu::Parser::addNonTerminal( const Bu::String &sName, NonTerminal &nt ) | ||
188 | { | ||
189 | int iId = aNonTerminal.getSize(); | ||
190 | aNonTerminal.append( nt ); | ||
191 | hNonTerminalName.insert( sName, iId ); | ||
192 | sio << "nt '" << sName << "' = " << iId << sio.nl; | ||
193 | return iId; | ||
194 | } | ||
195 | |||
196 | int Bu::Parser::addNonTerminal( const Bu::String &sName ) | ||
197 | { | ||
198 | int iId = aNonTerminal.getSize(); | ||
199 | aNonTerminal.append( NonTerminal() ); | ||
200 | hNonTerminalName.insert( sName, iId ); | ||
201 | sio << "nt '" << sName << "' = " << iId << sio.nl; | ||
202 | return iId; | ||
203 | } | ||
204 | |||
205 | void Bu::Parser::setNonTerminal( const Bu::String &sName, NonTerminal &nt ) | ||
206 | { | ||
207 | aNonTerminal[hNonTerminalName.get(sName)] = nt; | ||
208 | } | ||
209 | |||
210 | int Bu::Parser::getNonTerminalId( const Bu::String &sName ) | ||
211 | { | ||
212 | return hNonTerminalName.get( sName ); | ||
213 | } | ||
214 | |||
215 | bool Bu::Parser::hasNonTerminal( const Bu::String &sName ) | ||
216 | { | ||
217 | return hNonTerminalName.has( sName ); | ||
218 | } | ||
219 | |||
220 | int Bu::Parser::addReduction( const Bu::String &sName, const Reduction &r ) | ||
221 | { | ||
222 | int iId = aReduction.getSize(); | ||
223 | aReduction.append( r ); | ||
224 | hReductionName.insert( sName, iId ); | ||
225 | return iId; | ||
226 | } | ||
227 | |||
228 | int Bu::Parser::addReduction( const Bu::String &sName ) | ||
229 | { | ||
230 | int iId = aReduction.getSize(); | ||
231 | aReduction.append( Reduction() ); | ||
232 | hReductionName.insert( sName, iId ); | ||
233 | return iId; | ||
234 | } | ||
235 | |||
236 | void Bu::Parser::setReduction( const Bu::String &sName, const Reduction &r ) | ||
237 | { | ||
238 | aReduction[hReductionName.get(sName)] = r; | ||
239 | } | ||
240 | |||
241 | int Bu::Parser::getReductionId( const Bu::String &sName ) | ||
242 | { | ||
243 | return hReductionName.get( sName ); | ||
244 | } | ||
245 | |||
246 | bool Bu::Parser::hasReduction( const Bu::String &sName ) | ||
247 | { | ||
248 | return hReductionName.has( sName ); | ||
249 | } | ||
250 | |||
251 | // | ||
252 | // Bu::Parser::State | ||
253 | // | ||
254 | |||
255 | Bu::Parser::State::State( Bu::Parser::State::Type eType, int iIndex ) : | ||
256 | eType( eType ), | ||
257 | iIndex( iIndex ) | ||
258 | { | ||
259 | } | ||
260 | |||
261 | Bu::Parser::State::~State() | ||
262 | { | ||
263 | } | ||
264 | |||
265 | // | ||
266 | // Bu::Parser::NonTerminal | ||
267 | // | ||
268 | |||
269 | Bu::Parser::NonTerminal::NonTerminal() : | ||
270 | bCanSkip( false ) | ||
271 | { | ||
272 | } | ||
273 | |||
274 | Bu::Parser::NonTerminal::~NonTerminal() | ||
275 | { | ||
276 | } | ||
277 | |||
278 | void Bu::Parser::NonTerminal::addProduction( Production p ) | ||
279 | { | ||
280 | lProduction.append( p ); | ||
281 | } | ||
282 | |||
283 | void Bu::Parser::NonTerminal::setCanSkip() | ||
284 | { | ||
285 | bCanSkip = true; | ||
286 | } | ||
287 | |||
288 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, Bu::Parser::State::Type t ) | ||
289 | { | ||
290 | switch( t ) | ||
291 | { | ||
292 | case Bu::Parser::State::typeTerminal: | ||
293 | return f << "typeTerminal"; | ||
294 | |||
295 | case Bu::Parser::State::typeTerminalPush: | ||
296 | return f << "typeTerminalPush"; | ||
297 | |||
298 | case Bu::Parser::State::typeNonTerminal: | ||
299 | return f << "typeNonTerminal"; | ||
300 | |||
301 | case Bu::Parser::State::typeReduction: | ||
302 | return f << "typeReduction"; | ||
303 | } | ||
304 | return f << "***error***"; | ||
305 | } | ||
306 | |||
307 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Parser::State &s ) | ||
308 | { | ||
309 | return f << "{" << s.eType << ": " << s.iIndex << "}"; | ||
310 | } | ||
311 | |||