From fc14c0f16e881607e55f04516934818091331bd3 Mon Sep 17 00:00:00 2001
From: Mike Buland <mike@xagasoft.com>
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(-)

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