#include "config.h" #include "parser.h" #include "lexer.h" #include "number.h" #include "datafiles.h" #include #include Parser::Parser( Lexer &lex, Bu::Stream &rOut ) : lex( lex ), rOut( rOut ) { } Parser::~Parser() { } void Parser::parse() { for(;;) { lex.nextToken(); if( lex[0].eType == Token::tEndOfInput ) break; expr(); Bu::sio << "Final stack:"; for( TokenStack::iterator i = tsParse.begin(); i; i++ ) { Bu::sio << " " << (*i).eType; if( (*i).eType == Token::tNumber ) { Bu::sio << "(" << (*i).nVal->toString() << ")"; } } Bu::sio << Bu::sio.nl; Bu::sio << "Script:"; for( TokenStack::iterator i = tsScript.begin(); i; i++ ) { Bu::sio << " " << (*i).eType; if( (*i).eType == Token::tNumber ) { Bu::sio << "(" << (*i).nVal->toString() << ")"; } } Bu::sio << Bu::sio.nl; } } void Parser::expr() { if( lex[0].eType == Token::tEndOfInput ) return; if( lex[0].eType == Token::tVariable && lex[1].eType == Token::tEquals ) { Token t = lex[0]; lex.nextToken(); lex.nextToken(); expr(); return; } exprP(); switch( lex[0].eType ) { case Token::tPlus: case Token::tMinus: case Token::tMultiply: case Token::tDivide: case Token::tModulus: Token t = lex[0]; lex.nextToken(); expr(); shift( t ); break; } } void Parser::exprP() { switch( lex[0].eType ) { case Token::tNumber: case Token::tVariable: shift( lex[0] ); lex.nextToken(); break; case Token::tOpenParen: lex.nextToken(); expr(); if( lex[0].eType != Token::tCloseParen ) { throw Bu::ExceptionBase("Expected close paren"); } lex.nextToken(); break; case Token::tMinus: lex.nextToken(); exprP(); shift( Token( Token::tNegate ) ); break; } } /* case Token::tCommand: lex.setMode( Lexer::modeCommand ); if( *t.sVal == "exit" || *t.sVal == "quit" ) return; else if( *t.sVal == "scale" ) { Token t2 = lex.nextToken(); if( t2.eType == Token::tEndOfLine ) { Bu::println( rOut, "Current scale: %1"). arg( lex.getScale() ); } else if( t2.eType == Token::tString ) { int32_t i = strtol( t2.sVal->getStr(), 0, 10 ); lex.setScale( i ); if( i < 0 ) { Bu::println( rOut, "ERROR: You must provide a " "positive integer or zero as the parameter " "to scale."); } else { Bu::println( rOut, "Scale changed to: %1"). arg( lex.getScale() ); for( VarHash::iterator i = hVars.begin(); i; i++ ) (*i).setScale( lex.getScale() ); nZero = Number( lex.getScale(), lex.getRadix() ); } } else { Bu::println( rOut, "ERROR: You must provide a number " "as the parameter to scale."); } } else if( *t.sVal == "radix" ) { Token t2 = lex.nextToken(); if( t2.eType == Token::tEndOfLine ) { Bu::println( rOut, "Current radix: %1"). arg( lex.getRadix() ); } else if( t2.eType == Token::tString ) { int32_t i = strtol( t2.sVal->getStr(), 0, 10 ); if( i < 2 || i > 36 ) Bu::println( rOut, "ERROR: Radix must be between " "2 and 36 inclusive"); else { lex.setRadix( i ); Bu::println( rOut, "Radix changed to: %1"). arg( lex.getRadix() ); hVars.clear(); nZero = Number( lex.getScale(), lex.getRadix() ); } } else { Bu::println( rOut, "You must provide a number as " "the parameter to radix."); } } else if( *t.sVal == "vars" ) { Bu::println( rOut, "Declared variables:"); for( VarHash::iterator i = hVars.begin(); i; i++ ) { Bu::println( rOut, " - %1 = %2"). arg( i.getKey() ).arg( *i ); } Bu::println( rOut, ""); } else if( *t.sVal == "help" || *t.sVal == "h" || *t.sVal == "?" ) { Bu::println( rOut, Datafiles::getString("parserhelp.txt") ); } else { Bu::println( rOut, "ERROR: Unknown command '%1'"). arg( *t.sVal ); } lex.setMode( Lexer::modeNormal ); break; */ void Parser::shift( const Token &t ) { tsParse.push( t ); } void Parser::reduce() { } int Parser::reqTokens( Token::Type eType ) { switch( eType ) { case Token::tPlus: case Token::tMinus: case Token::tDivide: case Token::tMultiply: case Token::tModulus: case Token::tEquals: return 2; case Token::tOpenParen: return 0; case Token::tCloseParen: return 1; default: return 0; } } int Parser::getPriority( Token::Type eType ) { switch( eType ) { case Token::tNumber: case Token::tVariable: case Token::tCommand: return 0; case Token::tPlus: case Token::tMinus: return 1; case Token::tDivide: case Token::tMultiply: case Token::tModulus: return 2; case Token::tOpenParen: case Token::tCloseParen: return 3; case Token::tEndOfLine: case Token::tEndOfInput: case Token::tEquals: return -1; default: throw Bu::ExceptionBase("Invalid type in getPriority"); } }