该函数boost::spirit::qi::parse()
需要两个迭代器来定义输入范围。std::string
如果我尝试从or解析,这很好用std::istream
。现在我想为我的解析器实现一个更通用的接口。一种方法是用来boost::any_range
定义输入。这是我编译但抛出异常的测试代码"string iterator not dereferencable"
:
第二个问题。我怎样才能结合boost::any_range
在一起boost::spirit::classic::position_iterator
来检测可能的错误位置?
#include <boost/range/any_range.hpp>
#include <boost/spirit/include/classic_position_iterator.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_multi_pass.hpp>
namespace qi = boost::spirit::qi;
typedef boost::any_range<
char,
boost::forward_traversal_tag,
char,
std::ptrdiff_t
> input_type;
template < typename _Iterator >
struct decode
: qi::grammar< _Iterator >
{
decode( ) : decode::base_type( m_rule )
{
m_rule = qi::int_;
BOOST_SPIRIT_DEBUG_NODES( ( m_rule ) )
}
qi::rule< _Iterator > m_rule;
};
bool parse( const input_type& in, int& out )
{
// We use a stream iterator to access the given stream:
typedef boost::spirit::multi_pass<
input_type::const_iterator
> stream_iterator;
// Create begin iterator for given stream:
stream_iterator sBegin = boost::spirit::make_default_multi_pass( input_type::const_iterator( in.begin( ) ) );
stream_iterator sEnd = boost::spirit::make_default_multi_pass( input_type::const_iterator( ) );
// Create an instance of the used grammar:
decode<
stream_iterator
> gr;
// Try to decode the data stored within the stream according the grammar and store the result in the out variable:
bool r = boost::spirit::qi::parse( sBegin,
sEnd,
gr,
out );
return r && sBegin == sEnd;
}
void main( )
{
std::string in = "12345"; int out;
parse( in, out );
}
更新
1.) 我同意默认构造的sEnd
迭代器存在错误。因此我简化了我的例子,我想我误解了如何使用multi_pass
迭代器。在这种情况下c0
是false
(预期的)和c1
是true
(不是预期的)。那么使用multi_pass
迭代器的正确方法是什么?
#include <boost/range/any_range.hpp>
#include <boost/spirit/include/classic_position_iterator.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_multi_pass.hpp>
namespace qi = boost::spirit::qi;
typedef boost::any_range<
char,
boost::forward_traversal_tag,
char,
std::ptrdiff_t
> input_type;
bool parse( const input_type& in, int& out )
{
//for( input_type::iterator i = in.begin( ); i != in.end( ); ++i )
//{
// std::cout << *i;
//}
// We use a stream iterator to access the given stream:
typedef boost::spirit::multi_pass<
input_type::const_iterator,
boost::spirit::iterator_policies::default_policy< // Defaults:
boost::spirit::iterator_policies::ref_counted, // OwnershipPolicy: ref_counted
boost::spirit::iterator_policies::buf_id_check, // CheckingPolicy : buf_id_check
boost::spirit::iterator_policies::buffering_input_iterator, // InputPolicy : buffering_input_iterator
boost::spirit::iterator_policies::split_std_deque // StoragePolicy : split_std_deque
>
> stream_iterator;
bool c0 = in.begin( ) == in.end( );
// Create begin iterator for given stream:
stream_iterator sBegin( in.begin( ) );
stream_iterator sEnd( in.end( ) );
bool c1 = sBegin == sEnd;
//for( stream_iterator i = sBegin; i != sEnd; ++i )
//{
// std::cout << *i;
//}
return false;
}
void main( )
{
std::string in = "12345"; int out;
parse( in, out );
}
2.) 是的,我可以为每种类型的输入迭代器编译一个新的语法实例。我的想法是对用户隐藏实现细节(= boost::spirit
)并给他一个通用接口。因此,我想避免使用模板功能。
3.) 是的,我忘了公开属性。这只是一个快速而肮脏的例子。感谢您的提示。