カンマ演算子も使えるようにする

実はカンマ(,)も演算子です
このカンマ演算子を使えるようにしてみましょう

仕組み

カンマ演算子も使えるようにしたパーサが処理すべき式は必ず次のような形式になっています


完結式 ::= 部分式_comma
部分式_comma ::= 部分式_add_sub 部分式_comma_
部分式_comma_ ::= 演算子_comma 部分式_add_sub 部分式_comma_
演算子_comma ::= ,
部分式_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 ::= * あるいは / あるいは %
定数式 ::= 数値 あるいは ( 部分式_comma )
数値  ::= 16進数 あるいは 8進数 あるいは 10進数
16進数 ::= 0x[0-9​a-f​A-F]+
8進数 ::= 0[0-7]*
10進数 ::= [1-9][0-9]*

今追加しようとしている「カンマ演算子」は既に実装してある「足し算・引き算」よりも優先順位が低いので「完結式」と「足し算・引き算」との評価との間に「カンマ」の処理を割り込ませます

つまり full_expression と constant から呼び出していた operator_add_sub の代わりに operator_comma を呼ぶようにするだけです
簡単ですね
では実装してみましょう

実装

次のメソッドを追加しましょう

class string_calc : protected istringstream<char> {
.
.
.
	bool	operator_comma( any_value_t*	presult );
.
.
.
};

bool	string_calc::constant( any_value_t*	presult ){
	bool	success = true;
	if( !skipspace()){
		error_unexpected_eof();
		success = false;
	}
	else{
		char	c = at( 0, SEEK_CUR );
		if( c == '(' ){
			size_type	offset_prev = tell();
			seek( 1, SEEK_CUR );
			success = operator_comma( presult );
			if( success ){
				skipspace();
				if( getch() != ')' ){
					seek( offset_prev, SEEK_SET );
					error_unbalanced_parenthesis();
					success = false;
				}
			}
		}
		else if( isdigit( c )){
			success = operator_new_number( presult );
		}
		else{
			error_illegal_character( c );
			success = false;
		}
	}
	return	success;
}
bool	string_calc::operator_comma( any_value_t*	presult ){
	bool	success = true;
	while( skipspace()){
		success = operator_add_sub( presult );
		if( !success ){
			break;
		}
		skipspace();
		char	c = getch();
		if( c != ',' ){
			ungetch( c );
			break;
		}
	}
	return	success;
}
bool	string_calc::full_expression( any_value_t*	presult ){
	return	operator_comma( presult );
}