我使用boost ::精神这个非常简单的解析器:
rule<std::string::iterator, std::string()> zeroTo255 = (string("25") >> char_('0', '5'))
| (char_('2') >> char_('0', '4') >> digit)
| (char_('1') >> repeat[2](digit))
| (char_('1', '9') >> digit) | digit;
当我尝试解析
std::string o{"1"};
std::string s;
parse(o.begin(), o.end(), zeroTo255, s);
std::cout << o << ": " << s << std::endl;
我作为输出
1: 111
我明明做错事,但什么?
qi::hold
大约是它的一种方式,如正确地@Andrzej提到
我想我有几点看法,可能会帮助,以及更好的解决方案。
问题的关键是,灵将不需要通过设计属性“临时”存储。 事实上,它不能真正承担属性是摆在首位可复制。 这是原因这里(想象解析一切成一个单一的std ::矢量<>和复制为每个解析器步骤?)。
在一个更重要的水平,在我看来,如果它不是属性的处理是倒退这里,但解析器表达式本身: 它没有说明意图,并造成处理多次交涉时, 各种复杂的 ...真不应该。
我就带它会
rule<std::string::iterator, std::string()> zeroTo255, alternatively;
alternatively %= raw [ uint_ [ _pass = (_1 <= 255) ] ];
你看:你让精神分析的数字,而事实上只是验证的范围,这是你想在第一时间做什么。
这在我看来是一个非典型的第二件事,是一个事实,即规则暴露出std::string
,而不是属性, unsigned char
如这是为什么?
假设这是一个有意识的设计决策,就可以通过明智地使用有它自己的方式
- 负前瞻(
!parser
) -这不影响属性 - 正向前查找(
&parser
) -这不影响属性 - 想结识
qi::as_string
, qi::raw
, qi::lexeme
和qi::no_skip
- 语义动作(不依赖于自动规则 )
这里就是你原来的规则变化最小会工作:
zeroTo255 = raw [
("25" >> char_("0-5"))
| ('2' >> char_("0-4") >> digit)
| ('1' >> digit >> digit)
| (char_("1-9") >> digit)
| digit
];
这有大致为使用的代码相同的效果qi::hold
但不_hold_ing属性值的性能缺陷。
希望这可以帮助。
全样本:住在http://liveworkspace.org/code/4v4CQW$0 :
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
int main()
{
using namespace qi;
rule<std::string::iterator, std::string()> zeroTo255, alternatively;
zeroTo255 = raw [
("25" >> char_("0-5"))
| ('2' >> char_("0-4") >> digit)
| ('1' >> digit >> digit)
| (char_("1-9") >> digit)
| digit
];
alternatively %= raw [ uint_ [ _pass = (_1 <= 255) ] ];
for (auto& input : std::vector<std::string> { "255", "249", "178", "30", "4" })
{
std::string output;
std::cout << "zeroTo255:\t" << std::boolalpha
<< parse(std::begin(input), std::end(input), zeroTo255, output)
<< ": " << output << std::endl;
output.clear();
std::cout << "alternatively:\t" << std::boolalpha
<< parse(std::begin(input), std::end(input), alternatively, output)
<< ": " << output << std::endl;
}
}
产量
zeroTo255: true: 255
alternatively: true: 255
zeroTo255: true: 249
alternatively: true: 249
zeroTo255: true: 178
alternatively: true: 178
zeroTo255: true: 30
alternatively: true: 30
zeroTo255: true: 4
alternatively: true: 4
我遇到了类似的问题一次。 这是特别的方式在精神的替代操作符。 如果你使用其他指令“HOLD”你的榜样应该工作。
rule<std::string::iterator, std::string()> zeroTo255
= hold[string("25") >> char_('0', '5')]
| hold[char_('2') >> char_('0', '4') >> digit]
| hold[char_('1') >> repeat[2](digit)]
| hold[char_('1', '9') >> digit] | digit;
有关此行为的详细信息请参阅此线程 。