掛け算、割り算もできるようにする

足し算、引き算ができるようになったのですから、次は掛け算、割り算ができるようにしてみましょう

仕組み

掛け算と割り算も使えるようにしたパーサが処理すべき式は必ず次のような形式になっています


完結式 ::= 部分式_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-9​a-f​A-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();
}