エラーメッセージに行番号を加える

これまでのエラーメッセージでは起きたエラーが何かということは判りましたが、それがどこで起きたのかということは判りませんでした
そこでエラーメッセージに行番号を加えてどこで発生したエラーなのかも判るようにしてみましょう

仕組み

解析器で改行を数えます
改行文字は必ず空白なので skipspace に手を加えます

ノードのメンバには行番号を追加しましょう

ノードの実装

class node {
	size_t	m_lineno;
	.
	.
	.
public:
	size_t	get_lineno() const {
		return	m_lineno;
	}
	.
	.
	.
	void	clear(){
		m_lineno = ( size_t )-1;
		m_operator.clear();
		m_operands.clear();
		m_value.clear();
	}
	void	assign( size_t	lineno, const std::string&	operator_new, const node&	operand1 ){
		clear();
		m_lineno = lineno;
		m_operator = operator_new;
		m_operands.push_back( operand1 );
	}
	void	assign( size_t	lineno, const std::string&	operator_new, const node&	operand1, const node&	operand2 ){
		clear();
		m_lineno = lineno;
		m_operator = operator_new;
		m_operands.push_back( operand1 );
		m_operands.push_back( operand2 );
	}
	void	assign( size_t	lineno, const std::string&	operator_new, const std::list<node>&	operands ){
		clear();
		m_lineno = lineno;
		m_operator = operator_new;
		m_operands = operands;
	}
	void	assign( size_t	lineno, const std::string&	name, const std::string&	value ){
		clear();
		m_lineno = lineno;
		m_value.assign( name, value );
	}
	
	node&	operator=( const node&	rhs ){
		if( this != &rhs ){
			m_lineno = rhs.m_lineno;
			m_operator = rhs.m_operator;
			m_operands = rhs.m_operands;
			m_value = rhs.m_value;
		}
		return	*this;
	}
	node( size_t	lineno = ( size_t )-1 ):
	m_lineno(lineno),
	m_operator(),
	m_operands(),
	m_value()
	{
	}
	node( const node&	rhs ):
	m_lineno(rhs.m_lineno),
	m_operator(rhs.m_operator),
	m_operands(rhs.m_operands),
	m_value(rhs.m_value)
	{
	}
	node( size_t	lineno, const std::string&	operator_new, const node&	operand1 ):
	m_lineno(( size_t )-1),
	m_operator(),
	m_operands(),
	m_value()
	{
		assign( lineno, operator_new, operand1 );
	}
	node( size_t	lineno, const std::string&	operator_new, const node&	operand1, const node&	operand2 ):
	m_lineno(( size_t )-1),
	m_operator(),
	m_operands(),
	m_value()
	{
		assign( lineno, operator_new, operand1, operand2 );
	}
	node( size_t	lineno, const std::string&	operator_new, std::list<node>	operands ):
	m_lineno(( size_t )-1),
	m_operator(),
	m_operands(),
	m_value()
	{
		assign( lineno, operator_new, operands );
	}
	node( size_t	lineno, const std::string&	name, const std::string&	value ):
	m_lineno(( size_t )-1),
	m_operator(),
	m_operands(),
	m_value()
	{
		assign( lineno, name, value );
	}
};

解析器の実装

class parser : protected istringstream<char> {
	parser_callback*	m_callback;
	std::vector<size_type>	m_lines;
	
	size_type	get_lineno( size_type	offset );
	...
};
parser::parser( parser_callback*	callback ):
istringstream<char>(),
m_callback(callback),
m_lines()
{
}
parser::size_type	parser::get_lineno( size_type	offset ){
	std::vector<size_type>::iterator	p = std::lower_bound( m_lines.begin(), m_lines.end(), offset );
	return	size_type( std::distance( m_lines.begin(), p ) + 1 );
}
bool	parser::skipspace(){
	char	comment = 0;
	while( !eof()){
		.
		.
		.
		if( c == '\n' ){
			m_lines.push_back( m_offset );
		}
	}
	return	!eof();
}

エラー処理の実装

class string_calc : private parser_callback, private evaluator_callback {
	void	error_illegal_character( size_t	lineno, char	c );
	void	error_unexpected_eof( size_t	lineno );
	void	error_unbalanced_parenthesis( size_t	lineno );
	void	runtime_error_devide_by_zero( size_t	lineno );
	...
};
void	string_calc::runtime_error_devide_by_zero( size_t	lineno ){
	// 0 除算
	OutputDebugString( stringprintf( " line#%d: ", lineno ));
	OutputDebugString( "runtime error: devide by zero.\n" );
}
void	string_calc::error_illegal_character( size_t	lineno, char	c ){
	// 変な文字だからお終い
	OutputDebugString( stringprintf( " line#%d: ", lineno ));
	OutputDebugString( stringprintf( "error: illegal caracter '%c'.\n", c ));
}
void	string_calc::error_unexpected_eof( size_t	lineno ){
	// 予期せぬ EOF
	OutputDebugString( stringprintf( " line#%d: ", lineno ));
	OutputDebugString( "error: unexpected EOF.\n" );
}
void	string_calc::error_unbalanced_parenthesis( size_t	lineno ){
	// 対応する () が見つからないから終わり
	OutputDebugString( stringprintf( " line#%d: ", lineno ));
	OutputDebugString( "error: unbalanced parenthesis.\n" );
}