我需要匹配一些输入,构造一个复杂的对象,然后以两种方式匹配其余的输入,具体取决于一些道具。构造对象。 我试过qi :: eps(/ 条件 /)>> p1 | p2但结果对我来说很明显。 简化代码http://liveworkspace.org/code/1NzThA $ 6
在代码片段中,我匹配来自输入的int_,如果值== 0,请尝试匹配'a' - 'b' 但我对'0b'的输入感到满意!我试过用括号玩,但没有运气。
答案 0 :(得分:3)
我个人不会轻易使用语义动作(或凤凰)。这不是齐的“精神”(双关语意思)。
这是我的看法:
rule<char const*, char()> r =
(omit [ int_(0) ] >> char_('a')) |
(omit [ int_(1) ] >> char_('b'))
;
请参阅?更清洁。另外:自动属性传播。在http://liveworkspace.org/code/1T9h5
上查看输出:
ok: a
fail
fail
ok: b
完整的示例代码:
//#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
template <typename P>
inline
void test_parser(char const* input, P const& p, bool full_match = true)
{
char const* f(input);
char const* l(f + strlen(f));
char result;
if (qi::parse(f, l, p, result) && (!full_match || (f == l)))
std::cout << "ok: " << result << std::endl;
else
std::cout << "fail" << std::endl;
}
int main()
{
int p;
using namespace qi;
rule<char const*, char()> r =
(omit [ int_(0) ] >> char_('a')) |
(omit [ int_(1) ] >> char_('b'))
;
BOOST_SPIRIT_DEBUG_NODE(r);
test_parser("0a", r); //should match
test_parser("0b", r); //should not match
test_parser("1a", r); //should not match
test_parser("1b", r); //should match
}
答案 1 :(得分:1)
这是你的规则:
qi::rule<char const*> r =
qi::int_ [phoenix::ref(p) = qi::_1]
>> (qi::eps(phoenix::ref(p) == 0)
>> qi::char_('a') | qi::char_('b'))
对我说:接受'0a'或以'b'结尾的任何内容。这与您在代码段中获得的结果相符。
我承认我并不完全理解你的问题,但是如果你试图让某种“独占或”事情发生(如你的代码片段中的注释所示),那么这条规则就不完整了。你在评论中提出的解决方法(实际上更像是“修复”而不是“解决方法”)是一种解决方案,尽管你不需要qi::lazy
,因为基于凤凰的齐本地人已经很懒,但是你走在正确的轨道上。这是另一个(更具可读性的)解决方案。
qi::rule<char const*> r =
qi::int_ [phoenix::ref(p) = qi::_1]
>> ((qi::eps(phoenix::ref(p) == 0) >> qi::char_('a')) |
(qi::eps(phoenix::ref(p) == 1) >> qi::char_('b')))
;
如果您更喜欢使用本地人&lt;&gt;你在评论中添加了,也没关系,但使用p
的引用会增加代码的开销,只要你记得不要在你的语法中的任何其他地方设置p
,并且你不要最终建立一个递归该规则的语法:)