掛け算、割り算もできるようにする
足し算、引き算ができるようになったのですから、次は掛け算、割り算ができるようにしてみましょう
仕組み
掛け算と割り算も使えるようにしたパーサが処理すべき式は必ず次のような形式になっています
完結式 ::= 部分式_add_sub
部分式_add_sub ::= 部分式_mul_div_mod 部分式_add_sub_
部分式_add_sub_ ::= 演算子_add_sub 部分式_mul_div_mod 部分式_add_sub_
演算子_add_sub ::= + あるいは −
部分式_mul_div_mod ::= 数値 部分式_mul_div_mod_
部分式_mul_div_mod_ ::= 演算子_mul_div_mod 数値 部分式_mul_div_mod_
演算子_mul_div_mod ::= * あるいは / あるいは %
数値 ::= 16進数 あるいは 8進数 あるいは 10進数
16進数 ::= 0x[0-9a-fA-F]+
8進数 ::= 0[0-7]*
10進数 ::= [1-9][0-9]*
今追加しようとしている「掛け算・割り算」は既に実装してある「足し算・引き算」よりも優先順位が高いので「足し算・引き算」の処理と「数値」の評価との間に「掛け算・割り算」の処理を割り込ませます
要するに operator_add_sub と operator_add_sub_ で呼んでいた constant を operator_mul_div_mod に変えるだけのことです
簡単ですね
では実装してみましょう
実装
次のメソッドを追加しましょう
class string_calc : protected istringstream<char> { . . . bool operator_mul_div_mod_( any_value_t* presult ); bool operator_mul_div_mod( any_value_t* presult ); void error_devide_by_zero(); . . . }; void string_calc::error_devide_by_zero(){ // 0 除算 OutputDebugString( "error: devide by zero.\n" ); } bool string_calc::operator_mul_div_mod_( any_value_t* presult ){ bool success = true; if( skipspace()){ char c = at( 0, SEEK_CUR ); if( c == '*' ){ seek( 1, SEEK_CUR ); any_value_t rhs; success = constant( &rhs ); if( success && presult ){ presult->operator_assign_mul( rhs ); } if( success ){ success = operator_mul_div_mod_( presult ); } } else if( c == '/' ){ seek( 1, SEEK_CUR ); any_value_t rhs; success = constant( &rhs ); if( success && presult ){ if( rhs ){ presult->operator_assign_div( rhs ); } else{ error_devide_by_zero(); success = false; } } if( success ){ success = operator_mul_div_mod_( presult ); } } else if( c == '%' ){ seek( 1, SEEK_CUR ); any_value_t rhs; success = constant( &rhs ); if( success && presult ){ if( rhs ){ presult->operator_assign_mod( rhs ); } else{ error_devide_by_zero(); success = false; } } if( success ){ success = operator_mul_div_mod_( presult ); } } } return success; } bool string_calc::operator_mul_div_mod( any_value_t* presult ){ bool success = constant( presult ); if( success ){ success = operator_mul_div_mod_( presult ); } return success; }
any_value_t クラスに次のメソッドを追加しましょう
any_value_t& operator_assign_mul( const any_value_t& rhs ){ long l = operator_typecast_to_long(); long r = rhs.operator_typecast_to_long(); l *= r; return assign( TYPEOF_INTEGER, stringprintf( "%d", l )); } any_value_t& operator_assign_div( const any_value_t& rhs ){ long l = operator_typecast_to_long(); long r = rhs.operator_typecast_to_long(); l /= r; return assign( TYPEOF_INTEGER, stringprintf( "%d", l )); } any_value_t& operator_assign_mod( const any_value_t& rhs ){ long l = operator_typecast_to_long(); long r = rhs.operator_typecast_to_long(); l %= r; return assign( TYPEOF_INTEGER, stringprintf( "%d", l )); } any_value_t operator_mul( const any_value_t& rhs ) const { any_value_t result = *this; return result.operator_assign_mul( rhs ); } any_value_t operator_div( const any_value_t& rhs ) const { any_value_t result = *this; return result.operator_assign_div( rhs ); } any_value_t operator_mod( const any_value_t& rhs ) const { any_value_t result = *this; return result.operator_assign_mod( rhs ); } bool operator_typecast_to_bool() const { return !!operator_typecast_to_long(); } operator bool() const { return operator_typecast_to_bool(); }