#include "lexer.h" #include "token.h" #include "number.h" #include Lexer::Lexer( Bu::Stream &rIn ) : rIn( rIn ), iBufPos( 0 ), iScale( 0 ), iRadix( 10 ), numRangeTop('9'), ascRangeTop('a'-1), eMode( modeNormal ) { } Lexer::~Lexer() { } Token Lexer::nextToken() { switch( eMode ) { case modeNormal: return nextTokenNormal(); case modeCommand: return nextTokenCommand(); default: throw Bu::ExceptionBase("Invalid mode."); } } Token Lexer::nextTokenNormal() { for(;;) { if( iBufPos >= sBuf.getSize() ) { iBufPos = -1; return Token( Token::tEndOfLine ); } if( iBufPos < 0 ) { if( rIn.isEos() ) return Token( Token::tEndOfInput ); sBuf = rIn.readLine(); if( sBuf.getSize() == 0 ) { iBufPos = -1; continue; } iBufPos = 0; } //Bu::println("Testing char '%1' at %2").arg( sBuf[iBufPos] ).arg( iBufPos ); switch( sBuf[iBufPos] ) { case ' ': case '\t': iBufPos++; break; case '\\': { Bu::String *sTmp = new Bu::String(); for( iBufPos++; iBufPos < sBuf.getSize() && sBuf[iBufPos] != ' ' && sBuf[iBufPos] != '\t'; iBufPos++ ) { sTmp->append( sBuf[iBufPos] ); } return Token( Token::tCommand, sTmp ); } break; case '$': { Bu::String *sTmp = new Bu::String(); for( iBufPos++; iBufPos < sBuf.getSize() && sBuf[iBufPos] != ' ' && sBuf[iBufPos] != '\t' && sBuf[iBufPos] != '+' && sBuf[iBufPos] != '-' && sBuf[iBufPos] != '*' && sBuf[iBufPos] != '/' && sBuf[iBufPos] != '%' && sBuf[iBufPos] != '=' && sBuf[iBufPos] != '(' && sBuf[iBufPos] != ')'; iBufPos++ ) { sTmp->append( sBuf[iBufPos] ); } return Token( Token::tVariable, sTmp ); } break; case '=': iBufPos++; return Token( Token::tEquals ); case '+': iBufPos++; return Token( Token::tPlus ); case '-': iBufPos++; return Token( Token::tMinus ); case '*': iBufPos++; return Token( Token::tMultiply ); case '/': iBufPos++; return Token( Token::tDivide ); case '%': iBufPos++; return Token( Token::tModulus ); case '(': iBufPos++; return Token( Token::tOpenParen ); case ')': iBufPos++; return Token( Token::tCloseParen ); default: { Bu::String *sTmp = new Bu::String(); if( (sBuf[iBufPos] >= '0' && sBuf[iBufPos] <= numRangeTop) || (sBuf[iBufPos] >= 'a' && sBuf[iBufPos] <= ascRangeTop) || sBuf[iBufPos] == '.' ) { for( ; iBufPos < sBuf.getSize() ; iBufPos++ ) { if( (sBuf[iBufPos] >= '0' && sBuf[iBufPos] <= numRangeTop) || (sBuf[iBufPos] >= 'a' && sBuf[iBufPos] <= ascRangeTop) || sBuf[iBufPos] == '.' ) { sTmp->append( sBuf[iBufPos] ); } else { break; } } Number *n = new Number( *sTmp, iScale, iRadix ); delete sTmp; return Token( Token::tNumber, n ); } else { sBuf.clear(); throw Bu::ExceptionBase( "Invalid character discovered!"); } } break; } } } Token Lexer::nextTokenCommand() { for(;;) { if( iBufPos >= sBuf.getSize() ) { iBufPos = -1; return Token( Token::tEndOfLine ); } if( iBufPos < 0 ) { if( rIn.isEos() ) return Token( Token::tEndOfInput ); sBuf = rIn.readLine(); if( sBuf.getSize() == 0 ) { iBufPos = -1; continue; } iBufPos = 0; } //Bu::println("Testing char '%1' at %2").arg( sBuf[iBufPos] ).arg( iBufPos ); switch( sBuf[iBufPos] ) { case ' ': case '\t': iBufPos++; break; default: { Bu::String *sTmp = new Bu::String(); for( ; iBufPos < sBuf.getSize() ; iBufPos++ ) { if( sBuf[iBufPos] == ' ' || sBuf[iBufPos] == '\t' ) break; sTmp->append( sBuf[iBufPos] ); } return Token( Token::tString, sTmp ); } break; } } } void Lexer::setRadix( int i ) { iRadix = i; if( iRadix <= 10 ) { numRangeTop = '0'+iRadix-1; ascRangeTop = 'a'-1; } else { numRangeTop = '9'; ascRangeTop = 'a'+iRadix-11; } }