summaryrefslogtreecommitdiff
path: root/src/experimental/parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/experimental/parser.cpp')
-rw-r--r--src/experimental/parser.cpp311
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"
12using namespace Bu;
13
14Bu::Parser::Parser()
15{
16}
17
18Bu::Parser::~Parser()
19{
20}
21
22void Bu::Parser::pushLexer( Lexer *pLex )
23{
24 sLexer.push( pLex );
25}
26
27void Bu::Parser::popLexer()
28{
29 delete sLexer.peekPop();
30}
31
32Lexer::Token *Bu::Parser::popToken()
33{
34 return sToken.peekPop();
35}
36
37void Bu::Parser::pushToken( Lexer::Token *pTok )
38{
39 sToken.push( pTok );
40}
41
42void 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
108bool 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
160void 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
177void Bu::Parser::setRootNonTerminal( int iRoot )
178{
179 iRootNonTerminal = iRoot;
180}
181
182void Bu::Parser::setRootNonTerminal( const Bu::String &sRoot )
183{
184 setRootNonTerminal( hNonTerminalName.get( sRoot ) );
185}
186
187int 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
196int 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
205void Bu::Parser::setNonTerminal( const Bu::String &sName, NonTerminal &nt )
206{
207 aNonTerminal[hNonTerminalName.get(sName)] = nt;
208}
209
210int Bu::Parser::getNonTerminalId( const Bu::String &sName )
211{
212 return hNonTerminalName.get( sName );
213}
214
215bool Bu::Parser::hasNonTerminal( const Bu::String &sName )
216{
217 return hNonTerminalName.has( sName );
218}
219
220int 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
228int 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
236void Bu::Parser::setReduction( const Bu::String &sName, const Reduction &r )
237{
238 aReduction[hReductionName.get(sName)] = r;
239}
240
241int Bu::Parser::getReductionId( const Bu::String &sName )
242{
243 return hReductionName.get( sName );
244}
245
246bool Bu::Parser::hasReduction( const Bu::String &sName )
247{
248 return hReductionName.has( sName );
249}
250
251//
252// Bu::Parser::State
253//
254
255Bu::Parser::State::State( Bu::Parser::State::Type eType, int iIndex ) :
256 eType( eType ),
257 iIndex( iIndex )
258{
259}
260
261Bu::Parser::State::~State()
262{
263}
264
265//
266// Bu::Parser::NonTerminal
267//
268
269Bu::Parser::NonTerminal::NonTerminal() :
270 bCanSkip( false )
271{
272}
273
274Bu::Parser::NonTerminal::~NonTerminal()
275{
276}
277
278void Bu::Parser::NonTerminal::addProduction( Production p )
279{
280 lProduction.append( p );
281}
282
283void Bu::Parser::NonTerminal::setCanSkip()
284{
285 bCanSkip = true;
286}
287
288Bu::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
307Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Parser::State &s )
308{
309 return f << "{" << s.eType << ": " << s.iIndex << "}";
310}
311