From ce68e816bd82612c14f3492e8bc969da9bfab06c Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 9 May 2013 15:24:11 -0600 Subject: Added better filtering in Number::set, and cli options. The command line options let you set the initial radix/scale, and there's a function te test if any number is prime, that's fun. --- src/main.cpp | 2 ++ src/number.cpp | 22 ++++++++++++++++++---- src/options.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++++++- src/options.h | 7 +++++++ src/parser.cpp | 24 +++++++++++++++--------- 5 files changed, 88 insertions(+), 14 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 8e8c19d..c128dd8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -377,6 +377,8 @@ int main( int argc, char *argv[] ) // ordertest(); Lexer lex( sioRaw ); + lex.setScale( opt.getScale() ); + lex.setRadix( opt.getRadix() ); Parser parser( lex, sioRaw ); parser.parse(); diff --git a/src/number.cpp b/src/number.cpp index 062e368..eb4d01d 100644 --- a/src/number.cpp +++ b/src/number.cpp @@ -306,15 +306,22 @@ void Number::set( const Bu::String &sNum ) } for( ; iEnd < sNum.getSize() && sNum[iEnd] == '0'; iEnd++ ) { } + int iDigit; for( int j = iPt-1; j >= iEnd; j-- ) { // Bu::println(" -> '%1'").arg( sNum[j] ); if( sNum[j] == '.' ) break; if( sNum[j] >= '0' && sNum[j] <= '9' ) - aInt.append( sNum[j]-'0' ); + iDigit = sNum[j]-'0'; else - aInt.append( sNum[j]-'a'+10 ); + iDigit = sNum[j]-'a'+10; + if( iDigit < 0 || iDigit >= iRadix ) + throw Bu::ExceptionBase(Bu::String( + "Invalid character '%1' in Number::set").arg(sNum[j]). + end().getStr() + ); + aInt.append( iDigit ); } if( iScale > 0 ) @@ -324,9 +331,16 @@ void Number::set( const Bu::String &sNum ) { // Bu::println(" => '%1'").arg( sNum[j] ); if( sNum[j] >= '0' && sNum[j] <= '9' ) - aFrac.set( iFrac++, sNum[j]-'0' ); + iDigit = sNum[j]-'0'; else - aFrac.set( iFrac++, sNum[j]-'a'+10 ); + iDigit = sNum[j]-'a'+10; + + if( iDigit < 0 || iDigit >= iRadix ) + throw Bu::ExceptionBase(Bu::String( + "Invalid character '%1' in Number::set").arg(sNum[j]). + end().getStr() + ); + aFrac.set( iFrac++, iDigit ); if( iFrac >= iScale ) break; } diff --git a/src/options.cpp b/src/options.cpp index 7f66028..d9cd8f1 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -6,12 +6,20 @@ #include #include -Options::Options( int argc, char *argv[] ) +Options::Options( int argc, char *argv[] ) : + iScale( 0 ), + iRadix( 10 ) { + addOption( iRadix, 'r', "radix", + Bu::String("Set the radix (default: %1)").arg( iRadix ) ); + addOption( iScale, 's', "scale", + Bu::String("Set the scale (default: %1)").arg( iScale ) ); addOption( Bu::slot(this, &Options::selfTest), "self-test", "Run a series of tests to ensure everything is working correctly."); addOption( Bu::slot(this, &Options::textPrimes), "text-primes", "Generate primes in base 36 that only have digits > 9 in them."); + addOption( Bu::slot(this, &Options::isPrime), 'p', "is-prime", + "Test if the given number is prime. Set radix first."); addHelpOption('h', "help", "This help"); parse( argc, argv ); @@ -75,3 +83,40 @@ int Options::textPrimes( Bu::StringArray ) return 0; } +int Options::isPrime( Bu::StringArray aArgs ) +{ + Number tst( 0, iRadix ); + Number max( 0, iRadix ); + Number j( 0, iRadix ); + Number one( 0, iRadix ); + Number fact( 0, iRadix ); + one = "1"; + fact = "2"; + + Bu::println("Radix: %1").arg( iRadix ); + + for( Bu::StringArray::iterator i = aArgs.begin()+1; i; i++ ) + { + tst = *i; + Bu::println("%1").arg( tst ); + max = tst / fact; + bool bPrime = true; + for( j = "2"; j < max; j = j + one ) + { + if( (tst%j).isZero() ) + { + bPrime = false; + break; + } + } + + if( bPrime ) + { + Bu::println("%1").arg( tst ); + } + } + + exit( 0 ); + return aArgs.getSize(); +} + diff --git a/src/options.h b/src/options.h index 11bf896..1085e1e 100644 --- a/src/options.h +++ b/src/options.h @@ -9,9 +9,16 @@ public: Options( int argc, char *argv[] ); virtual ~Options(); + int getScale() const { return iScale; } + int getRadix() const { return iRadix; } + private: int selfTest( Bu::StringArray aArgs ); int textPrimes( Bu::StringArray aArgs ); + int isPrime( Bu::StringArray aArgs ); + + int iScale; + int iRadix; }; #endif diff --git a/src/parser.cpp b/src/parser.cpp index 57144c2..38988f5 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -152,22 +152,17 @@ void Parser::parse() default: if( tsNonTerminal.getSize() == 0 || - getPriority( tsNonTerminal.peek().eType ) < + getPriority( tsNonTerminal.peek().eType ) <= getPriority( t.eType ) ) { // Bu::println("Pushing non-terminal: %1").arg( t.eType ); tsNonTerminal.push( t ); - -// for( TokenStack::iterator i = tsTerminal.begin(); i; i++ ) Bu::print(" [%1]").arg( *(*i).nVal ); Bu::println(""); -// for( TokenStack::iterator i = tsNonTerminal.begin(); i; i++ ) Bu::print(" <%1>").arg( (*i).eType ); Bu::println(""); } else { // Bu::println("Unwinding stack before pushing: %1").arg( t.eType ); unwind(); tsNonTerminal.push( t ); -// for( TokenStack::iterator i = tsTerminal.begin(); i; i++ ) Bu::print(" [%1]").arg( *(*i).nVal ); Bu::println(""); -// for( TokenStack::iterator i = tsNonTerminal.begin(); i; i++ ) Bu::print(" <%1>").arg( (*i).eType ); Bu::println(""); } break; } @@ -178,8 +173,19 @@ void Parser::unwind() { for(;;) { -// for( TokenStack::iterator i = tsTerminal.begin(); i; i++ ) Bu::print(" [%1]").arg( *(*i).nVal ); Bu::println(""); -// for( TokenStack::iterator i = tsNonTerminal.begin(); i; i++ ) Bu::print(" <%1>").arg( (*i).eType ); Bu::println(""); +/* + for( TokenStack::iterator i = tsTerminal.begin(); i; i++ ) + { + if( (*i).eType == Token::tNumber ) + Bu::print(" [%1]").arg( *(*i).nVal ); + else + Bu::print(" [%1]").arg( *(*i).sVal ); + } + Bu::println(""); + for( TokenStack::iterator i = tsNonTerminal.begin(); i; i++ ) + Bu::print(" <%1>").arg( (*i).eType ); + Bu::println(""); +*/ if( tsNonTerminal.isEmpty() ) return; @@ -330,7 +336,6 @@ int Parser::getPriority( Token::Type eType ) case Token::tNumber: case Token::tVariable: case Token::tCommand: - case Token::tEquals: return 0; case Token::tPlus: @@ -348,6 +353,7 @@ int Parser::getPriority( Token::Type eType ) case Token::tEndOfLine: case Token::tEndOfInput: + case Token::tEquals: return -1; default: -- cgit v1.2.3