bru*_*ery 5 c++ boost boost-spirit boost-spirit-qi
我使用Boost :: Spirit这个非常简单的解析器:
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;
Run Code Online (Sandbox Code Playgroud)
当我尝试解析时
std::string o{"1"};
std::string s;
parse(o.begin(), o.end(), zeroTo255, s);
std::cout << o << ": " << s << std::endl;
Run Code Online (Sandbox Code Playgroud)
我有输出
1: 111
Run Code Online (Sandbox Code Playgroud)
我显然做错了什么,但是什么?
qi::hold 正如@Andrzej所正确提到的那样是一种解决方法
我想我有一些可能有帮助的观察,以及更好的解决方案.
重点是Spirit不会因设计而需要"临时"存储属性.事实上,它不能真正假设该属性首先是可复制的.这就是这里的原因(想象一下将所有内容解析为单个std :: vector <>并为每个解析器步骤进行复制?).
在一个更重要的水平,在我看来,如果它不是属性的处理是倒退这里,但解析器表达式本身:它没有说明意图,并造成处理多次交涉各种复杂的时...真的不应该.
我对它的看法是
rule<std::string::iterator, std::string()> zeroTo255, alternatively;
alternatively %= raw [ uint_ [ _pass = (_1 <= 255) ] ];
Run Code Online (Sandbox Code Playgroud)
你看:你让Spirit解析一个数字,而且确实只是验证了范围,这就是你想要做的事情.
作为一个典型的第二件事是,规则暴露了一个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
];
Run Code Online (Sandbox Code Playgroud)
这与使用的代码具有大致相同的效果,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;
}
}
Run Code Online (Sandbox Code Playgroud)
产量
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
Run Code Online (Sandbox Code Playgroud)
我曾经遇到过类似的问题.这是Spirit中另类运算符的特定方式.如果您使用其他指令"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;
Run Code Online (Sandbox Code Playgroud)
有关此行为的详细信息,请参阅此主题.
| 归档时间: |
|
| 查看次数: |
645 次 |
| 最近记录: |