From 00ecd458ced768b3b8752cdd421a22244b7adc01 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sun, 17 Oct 2010 05:50:57 +0000 Subject: Hey! The parser parses now! It's actually a little stupid, I didn't implement lookahead or precedence, but I should be able to do that easily with the next version. I'm treating this more as a proof of concept than a real working model. Although it can handle +, -, (), and = :) --- src/parser.cpp | 24 +++++++++++--- src/parser.h | 3 ++ src/tools/parser.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 102 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/parser.cpp b/src/parser.cpp index e4e8ae5..3ce73b6 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -22,16 +22,25 @@ 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: " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; + sio << "Token(a): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; selectProduction( iCurNt, ptCur ); while( !sState.isEmpty() ) { - sio << "Currently: " << *sState.peek() << sio.nl; switch( (*sState.peek()).eType ) { case State::typeTerminal: @@ -42,7 +51,7 @@ void Bu::Parser::parse() advanceState(); delete ptCur; ptCur = sLexer.peek()->nextToken(); - sio << "Token: " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; + sio << "Token(b): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; } else { @@ -59,7 +68,7 @@ void Bu::Parser::parse() sToken.push( ptCur ); ptCur = sLexer.peek()->nextToken(); - sio << "Token: " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; + sio << "Token(c): " << sLexer.peek()->tokenToString( *ptCur ) << sio.nl; } else { @@ -72,7 +81,7 @@ void Bu::Parser::parse() << (*sState.peek()).iIndex << sio.nl; { int iNt = (*sState.peek()).iIndex; - advanceState(); + sio << "Current state: " << *sState.peek() << sio.nl; if( !selectProduction( iNt, ptCur ) ) { throw Bu::ExceptionBase("Error parsing code."); @@ -132,7 +141,11 @@ bool Bu::Parser::selectProduction( int iNt, Lexer::Token *ptCur ) } } if( nt.bCanSkip ) + { + sio << "Nothing matches, skipping non-terminal." << sio.nl; + advanceState(); return true; + } sio << "-->(Found nothing)" << sio.nl; return false; } @@ -148,6 +161,7 @@ void Bu::Parser::advanceState() sio.decIndent(); sState.pop(); sio << "State advanced, End of production." << sio.nl; + advanceState(); return; } sio << "State advanced, now: " << *(sState.peek()) << sio.nl; diff --git a/src/parser.h b/src/parser.h index 5b5d4a8..1679c7f 100644 --- a/src/parser.h +++ b/src/parser.h @@ -34,6 +34,9 @@ namespace Bu */ void popLexer(); + Lexer::Token *popToken(); + void pushToken( Lexer::Token *pTok ); + /** * Execute a parse. */ diff --git a/src/tools/parser.cpp b/src/tools/parser.cpp index 76d4a72..7933f31 100644 --- a/src/tools/parser.cpp +++ b/src/tools/parser.cpp @@ -151,10 +151,43 @@ private: void redAdd( Bu::Parser &p ) { + Lexer::Token *a = p.popToken(); + Lexer::Token *b = p.popToken(); + + sio << "Add! " << b->vExtra.get() << " + " + << a->vExtra.get() << sio.nl; + + Lexer::Token *c = new Lexer::Token( tokNumber, + b->vExtra.get() + a->vExtra.get() + ); + p.pushToken( c ); + + delete a; + delete b; +} + +void redSubtract( Bu::Parser &p ) +{ + Lexer::Token *a = p.popToken(); + Lexer::Token *b = p.popToken(); + + sio << "Subtract! " << b->vExtra.get() << " - " + << a->vExtra.get() << sio.nl; + + Lexer::Token *c = new Lexer::Token( tokNumber, + b->vExtra.get() - a->vExtra.get() + ); + p.pushToken( c ); + + delete a; + delete b; } void redPrint( Bu::Parser &p ) { + Lexer::Token *a = p.popToken(); + sio << "Print! = " << a->vExtra.get() << sio.nl; + delete a; } /* Basic grammer example: @@ -170,14 +203,15 @@ void redPrint( Bu::Parser &p ) * The problem is, that we can't actually make something left hand recursive, * so we break it into two exprs: * - * expr': '(' expr ')' + * expr-sub1: '(' expr ')' * | NUMBER * ; * - * expr: expr' expr'' + * expr: expr-sub1 expr-sub2 * ; * - * expr'': '+' expr + * expr-sub2: '+' expr + * | '-' expr * | * ; * @@ -191,8 +225,8 @@ int main( int argc, char *argv[] ) Parser p; p.addNonTerminal("expr"); - p.addNonTerminal("expr'"); - p.addNonTerminal("expr''"); + p.addNonTerminal("expr-sub1"); + p.addNonTerminal("expr-sub2"); { Parser::NonTerminal nt; nt.addProduction( @@ -213,12 +247,30 @@ int main( int argc, char *argv[] ) ) ) ); + nt.addProduction( + Parser::Production( + Parser::State( + Parser::State::typeTerminal, + tokMinus + ) + ).append( + Parser::State( + Parser::State::typeNonTerminal, + p.getNonTerminalId("expr") + ) + ).append( + Parser::State( + Parser::State::typeReduction, + p.addReduction("subtract") + ) + ) + ); nt.addProduction( Parser::Production( ) ); nt.setCanSkip(); - p.setNonTerminal("expr''", nt ); + p.setNonTerminal("expr-sub2", nt ); } { Parser::NonTerminal nt; @@ -230,7 +282,25 @@ int main( int argc, char *argv[] ) ) ) ); - p.setNonTerminal("expr'", nt ); + nt.addProduction( + Parser::Production( + Parser::State( + Parser::State::typeTerminal, + tokOpenParen + ) + ).append( + Parser::State( + Parser::State::typeNonTerminal, + p.getNonTerminalId("expr") + ) + ).append( + Parser::State( + Parser::State::typeTerminal, + tokCloseParen + ) + ) + ); + p.setNonTerminal("expr-sub1", nt ); } { Parser::NonTerminal nt; @@ -238,12 +308,12 @@ int main( int argc, char *argv[] ) Parser::Production( Parser::State( Parser::State::typeNonTerminal, - p.getNonTerminalId("expr'") + p.getNonTerminalId("expr-sub1") ) ).append( Parser::State( Parser::State::typeNonTerminal, - p.getNonTerminalId("expr''") + p.getNonTerminalId("expr-sub2") ) ) ); @@ -275,6 +345,7 @@ int main( int argc, char *argv[] ) p.setRootNonTerminal("input"); p.setReduction("add", Bu::slot( &redAdd ) ); + p.setReduction("subtract", Bu::slot( &redSubtract ) ); p.setReduction("print", Bu::slot( &redPrint ) ); p.pushLexer( new MathLexer( fIn ) ); -- cgit v1.2.3