From fc14c0f16e881607e55f04516934818091331bd3 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Wed, 8 May 2013 13:36:09 -0600 Subject: Command parameters are taken as strings & decimal. You no longer need to set the radix in the current radix. --- src/lexer.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/lexer.h | 14 ++++++++++++ src/parser.cpp | 22 +++++++++---------- src/token.cpp | 2 ++ src/token.h | 1 + 5 files changed, 95 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/lexer.cpp b/src/lexer.cpp index 2521b40..97ceb1b 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -10,7 +10,8 @@ Lexer::Lexer( Bu::Stream &rIn ) : iScale( 0 ), iRadix( 10 ), numRangeTop('9'), - ascRangeTop('a'-1) + ascRangeTop('a'-1), + eMode( modeNormal ) { } @@ -19,6 +20,21 @@ 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(;;) { @@ -151,6 +167,56 @@ Token Lexer::nextToken() } } +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; diff --git a/src/lexer.h b/src/lexer.h index 4e6d73d..57b2865 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -11,6 +11,15 @@ public: Lexer( Bu::Stream &rIn ); virtual ~Lexer(); + enum Mode + { + modeNormal, + modeCommand, + }; + + void setMode( Mode e ) { eMode = e; } + Mode getMode() const { return eMode; } + Token nextToken(); int getScale() const { return iScale; } @@ -19,6 +28,10 @@ public: int getRadix() const { return iRadix; } void setRadix( int i ); +private: + Token nextTokenNormal(); + Token nextTokenCommand(); + private: Bu::Stream &rIn; Bu::String sBuf; @@ -27,6 +40,7 @@ private: int iRadix; char numRangeTop; char ascRangeTop; + Mode eMode; }; #endif diff --git a/src/parser.cpp b/src/parser.cpp index 804e595..57144c2 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -31,9 +31,11 @@ void Parser::parse() Bu::println( rOut, "%1").arg( deref( tsTerminal.peek() ) ); } tsTerminal.clear(); + lex.setMode( Lexer::modeNormal ); break; case Token::tCommand: + lex.setMode( Lexer::modeCommand ); if( *t.sVal == "exit" || *t.sVal == "quit" ) return; else if( *t.sVal == "scale" ) @@ -44,9 +46,9 @@ void Parser::parse() Bu::println( rOut, "Current scale: %1"). arg( lex.getScale() ); } - else if( t2.eType == Token::tNumber ) + else if( t2.eType == Token::tString ) { - int32_t i = t2.nVal->toInt32(); + int32_t i = strtol( t2.sVal->getStr(), 0, 10 ); lex.setScale( i ); if( i < 0 ) { @@ -77,9 +79,9 @@ void Parser::parse() Bu::println( rOut, "Current radix: %1"). arg( lex.getRadix() ); } - else if( t2.eType == Token::tNumber ) + else if( t2.eType == Token::tString ) { - int32_t i = t2.nVal->toInt32(); + 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"); @@ -127,13 +129,9 @@ void Parser::parse() "When using a radix greater than 10 all extended digits are lowercase letters\n" "starting with 'a'. Upper case is not currently supported.\n" "\n" - "All numbers are interpreted in the current radix, this means that you need to\n" - "set the radix using the current radix, even though the current value is aways\n" - "displayed in decimal. That is, to go to base 8 and back to base 10 you would:\n" - " \\radix 8\n" - " Radix changed to: 8\n" - " \\radix 12\n" - " Radix changed to: 10\n" + "All numeric command parameters (i.e. \\scale, \\radix) are in base 10 no\n" + "matter what radix is currently set. These are also displayed in base 10\n" + "at all times.\n" "\n" "Changing the radix always clears all variables.\n" ); @@ -144,6 +142,7 @@ void Parser::parse() Bu::println( rOut, "ERROR: Unknown command '%1'"). arg( *t.sVal ); } + lex.setMode( Lexer::modeNormal ); break; case Token::tNumber: @@ -292,6 +291,7 @@ void Parser::unwind() case Token::tNumber: case Token::tVariable: case Token::tCommand: + case Token::tString: case Token::tEndOfLine: case Token::tEndOfInput: // These should never show up at all diff --git a/src/token.cpp b/src/token.cpp index 5b0e6fe..a03c821 100644 --- a/src/token.cpp +++ b/src/token.cpp @@ -40,6 +40,7 @@ Token::~Token() case tVariable: case tCommand: + case tString: delete sVal; break; @@ -63,6 +64,7 @@ Bu::Formatter &operator<<( Bu::Formatter &f, Token::Type eType ) case Token::tOpenParen: return f << "("; case Token::tCloseParen: return f << ")"; case Token::tEquals: return f << "="; + case Token::tString: return f << "str"; case Token::tEndOfLine: return f << "eol"; case Token::tEndOfInput: return f << "eoi"; diff --git a/src/token.h b/src/token.h index 1cc6516..92a7bcc 100644 --- a/src/token.h +++ b/src/token.h @@ -24,6 +24,7 @@ public: tOpenParen, tCloseParen, tEquals, + tString, tEndOfLine, -- cgit v1.2.3