From 469bbcf0701e1eb8a6670c23145b0da87357e178 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sun, 25 Mar 2012 20:00:08 +0000 Subject: Code is all reorganized. We're about ready to release. I should write up a little explenation of the arrangement. --- src/experimental/parser.cpp | 311 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 311 insertions(+) create mode 100644 src/experimental/parser.cpp (limited to 'src/experimental/parser.cpp') 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 @@ +/* + * Copyright (C) 2007-2011 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#include "bu/parser.h" +#include "bu/lexer.h" + +#include "bu/sio.h" +using namespace Bu; + +Bu::Parser::Parser() +{ +} + +Bu::Parser::~Parser() +{ +} + +void Bu::Parser::pushLexer( Lexer *pLex ) +{ + sLexer.push( pLex ); +} + +void Bu::Parser::popLexer() +{ + delete sLexer.peekPop(); +} + +Lexer::Token *Bu::Parser::popToken() +{ + return sToken.peekPop(); +} + +void Bu::Parser::pushToken( Lexer::Token *pTok ) +{ + sToken.push( pTok ); +} + +void Bu::Parser::parse() +{ + int iCurNt = iRootNonTerminal; + Lexer::Token *ptCur = sLexer.peek()->nextToken(); + sio << "Token(a): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; + selectProduction( iCurNt, ptCur ); + + while( !sState.isEmpty() ) + { + switch( (*sState.peek()).eType ) + { + case State::typeTerminal: + sio << "terminal: " << ptCur->iToken << " == " + << (*sState.peek()).iIndex << sio.nl; + if( ptCur->iToken == (*sState.peek()).iIndex ) + { + advanceState(); + delete ptCur; + ptCur = sLexer.peek()->nextToken(); + sio << "Token(b): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; + } + else + { + throw Bu::ExceptionBase("Error parsing code."); + } + break; + + case State::typeTerminalPush: + sio << "terminalpush: " << ptCur->iToken << " == " + << (*sState.peek()).iIndex << sio.nl; + if( ptCur->iToken == (*sState.peek()).iIndex ) + { + advanceState(); + sToken.push( ptCur ); + + ptCur = sLexer.peek()->nextToken(); + sio << "Token(c): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; + } + else + { + throw Bu::ExceptionBase("Error parsing code."); + } + break; + + case State::typeNonTerminal: + sio << "nonterminal: " << ptCur->iToken << " --> " + << (*sState.peek()).iIndex << sio.nl; + { + int iNt = (*sState.peek()).iIndex; + sio << "Current state: " << *sState.peek() << sio.nl; + if( !selectProduction( iNt, ptCur ) ) + { + throw Bu::ExceptionBase("Error parsing code."); + } + } + break; + + case State::typeReduction: + sio << "reduction" << sio.nl; + aReduction[(*sState.peek()).iIndex]( *this ); + advanceState(); + break; + } + } +} + +bool Bu::Parser::selectProduction( int iNt, Lexer::Token *ptCur ) +{ + NonTerminal &nt = aNonTerminal[iNt]; + int j = 0; + for( NonTerminal::ProductionList::iterator i = nt.lProduction.begin(); + i; i++,j++ ) + { + if( (*i).isEmpty() ) + continue; + sio << "-->(Attempting production " << iNt << ":" << j << ": " + << (*i).first() << ")" << sio.nl; + if( (*i).first().eType == State::typeTerminal || + (*i).first().eType == State::typeTerminalPush ) + { + if( (*i).first().iIndex == ptCur->iToken ) + { + sState.push( (*i).begin() ); + sio.incIndent(); + sio << "Pushing production " << j << " from nt " << iNt + << sio.nl; + return true; + } + } + else if( (*i).first().eType == State::typeNonTerminal ) + { + sState.push( (*i).begin() ); + sio.incIndent(); + sio << "Pushing production " << j << " from nt " << iNt + << " as test." << sio.nl; + if( !selectProduction( (*i).first().iIndex, ptCur ) ) + { + sio.decIndent(); + sState.pop(); + sio << "Production " << j << " from nt " << iNt + << " didn't work out." << sio.nl; + } + else + { + return true; + } + } + } + if( nt.bCanSkip ) + { + sio << "Nothing matches, skipping non-terminal." << sio.nl; + advanceState(); + return true; + } + sio << "-->(Found nothing)" << sio.nl; + return false; +} + +void Bu::Parser::advanceState() +{ + if( sState.isEmpty() ) + return; + + sState.peek()++; + if( !sState.peek() ) + { + sio.decIndent(); + sState.pop(); + sio << "State advanced, End of production." << sio.nl; + advanceState(); + return; + } + sio << "State advanced, now: " << *(sState.peek()) << sio.nl; +} + +void Bu::Parser::setRootNonTerminal( int iRoot ) +{ + iRootNonTerminal = iRoot; +} + +void Bu::Parser::setRootNonTerminal( const Bu::String &sRoot ) +{ + setRootNonTerminal( hNonTerminalName.get( sRoot ) ); +} + +int Bu::Parser::addNonTerminal( const Bu::String &sName, NonTerminal &nt ) +{ + int iId = aNonTerminal.getSize(); + aNonTerminal.append( nt ); + hNonTerminalName.insert( sName, iId ); + sio << "nt '" << sName << "' = " << iId << sio.nl; + return iId; +} + +int Bu::Parser::addNonTerminal( const Bu::String &sName ) +{ + int iId = aNonTerminal.getSize(); + aNonTerminal.append( NonTerminal() ); + hNonTerminalName.insert( sName, iId ); + sio << "nt '" << sName << "' = " << iId << sio.nl; + return iId; +} + +void Bu::Parser::setNonTerminal( const Bu::String &sName, NonTerminal &nt ) +{ + aNonTerminal[hNonTerminalName.get(sName)] = nt; +} + +int Bu::Parser::getNonTerminalId( const Bu::String &sName ) +{ + return hNonTerminalName.get( sName ); +} + +bool Bu::Parser::hasNonTerminal( const Bu::String &sName ) +{ + return hNonTerminalName.has( sName ); +} + +int Bu::Parser::addReduction( const Bu::String &sName, const Reduction &r ) +{ + int iId = aReduction.getSize(); + aReduction.append( r ); + hReductionName.insert( sName, iId ); + return iId; +} + +int Bu::Parser::addReduction( const Bu::String &sName ) +{ + int iId = aReduction.getSize(); + aReduction.append( Reduction() ); + hReductionName.insert( sName, iId ); + return iId; +} + +void Bu::Parser::setReduction( const Bu::String &sName, const Reduction &r ) +{ + aReduction[hReductionName.get(sName)] = r; +} + +int Bu::Parser::getReductionId( const Bu::String &sName ) +{ + return hReductionName.get( sName ); +} + +bool Bu::Parser::hasReduction( const Bu::String &sName ) +{ + return hReductionName.has( sName ); +} + +// +// Bu::Parser::State +// + +Bu::Parser::State::State( Bu::Parser::State::Type eType, int iIndex ) : + eType( eType ), + iIndex( iIndex ) +{ +} + +Bu::Parser::State::~State() +{ +} + +// +// Bu::Parser::NonTerminal +// + +Bu::Parser::NonTerminal::NonTerminal() : + bCanSkip( false ) +{ +} + +Bu::Parser::NonTerminal::~NonTerminal() +{ +} + +void Bu::Parser::NonTerminal::addProduction( Production p ) +{ + lProduction.append( p ); +} + +void Bu::Parser::NonTerminal::setCanSkip() +{ + bCanSkip = true; +} + +Bu::Formatter &Bu::operator<<( Bu::Formatter &f, Bu::Parser::State::Type t ) +{ + switch( t ) + { + case Bu::Parser::State::typeTerminal: + return f << "typeTerminal"; + + case Bu::Parser::State::typeTerminalPush: + return f << "typeTerminalPush"; + + case Bu::Parser::State::typeNonTerminal: + return f << "typeNonTerminal"; + + case Bu::Parser::State::typeReduction: + return f << "typeReduction"; + } + return f << "***error***"; +} + +Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Parser::State &s ) +{ + return f << "{" << s.eType << ": " << s.iIndex << "}"; +} + -- cgit v1.2.3