【发布时间】:2010-09-23 12:20:23
【问题描述】:
对于我自己的小解析器框架,我正在尝试定义(类似于)以下函数:
template <class T>
// with operator>>( std::istream&, T& )
void tryParse( std::istream& is, T& tgt )
{
is >> tgt /* , *BUT* store every character that is consumed by this operation
in some string. If afterwards, is.fail() (which should indicate a parsing
error for now), put all the characters read back into the 'is' stream so that
we can try a different parser. */
}
然后我可以这样写:(也许不是最好的例子)
/* grammar: MyData = <IntTriple> | <DoublePair>
DoublePair = <double> <double>
IntTriple = <int> <int> <int> */
class MyData
{ public:
union { DoublePair dp; IntTriple it; } data;
bool isDoublePair;
};
istream& operator>>( istream& is, MyData& md )
{
/* If I used just "is >> md.data.it" here instead, the
operator>>( ..., IntTriple ) might consume two ints, then hit an
unexpected character, and fail, making it impossible to read these two
numbers as doubles in the "else" branch below. */
tryParse( is, md.data.it );
if ( !is.fail() )
md.isDoublePair = false;
else
{
md.isDoublePair = true;
is.clear();
is >> md.data.dp;
}
return is;
}
非常感谢任何帮助。
【问题讨论】:
-
流不是合适的工具,因为它们缺乏适当的回退。当设计像这样的简单内联解析器时(否则,试试
boost::spirit),解析函数应该真的需要一对迭代器。回滚变得很容易(只需在回溯解析器之前保存迭代器值)。