C++ 条件句法分析

C++ 条件句法分析,c++,boost,boost-spirit,boost-spirit-qi,C++,Boost,Boost Spirit,Boost Spirit Qi,我需要匹配一些输入,构造一个复杂的对象,然后以两种方式匹配其余的输入,这取决于一些道具。构造对象的属性。 我试过qi::eps/condition/>>p1 | p2,但结果对我来说是显而易见的。 简化代码为$6 在代码段中,我从输入中匹配int_uu,如果值==0,则尝试匹配“a”或“b” 但我已获得“0b”输入的OK!我试着玩牙套,但运气不好。 以下是您的规则: qi::rule<char const*> r = qi::int_ [phoenix::ref(p) =

我需要匹配一些输入,构造一个复杂的对象,然后以两种方式匹配其余的输入,这取决于一些道具。构造对象的属性。 我试过qi::eps/condition/>>p1 | p2,但结果对我来说是显而易见的。 简化代码为$6

在代码段中,我从输入中匹配int_uu,如果值==0,则尝试匹配“a”或“b” 但我已获得“0b”输入的OK!我试着玩牙套,但运气不好。 以下是您的规则:

qi::rule<char const*> r =
    qi::int_ [phoenix::ref(p) = qi::_1]
    >> (qi::eps(phoenix::ref(p) == 0)
        >> qi::char_('a') | qi::char_('b'))
如果您更喜欢使用您在注释中添加的局部变量,那也没关系,但是使用对p的引用会减少代码的开销,只要您记住不要在语法中的任何其他地方设置p,并且您不会最终构建一个递归该规则的语法:

以下是您的规则:

qi::rule<char const*> r =
    qi::int_ [phoenix::ref(p) = qi::_1]
    >> (qi::eps(phoenix::ref(p) == 0)
        >> qi::char_('a') | qi::char_('b'))

如果您喜欢使用您在注释中添加的局部变量,那也没关系,但是使用对p的引用会减少代码的开销,只要您记住不要在语法中的任何其他地方设置p,并且您不会最终构建一个递归该规则的语法:

我个人不会轻易使用语义操作或phoenix。这并不是齐潘的精神

这是我的看法:

rule<char const*, char()> r = 
   (omit [ int_(0) ] >> char_('a')) |
   (omit [ int_(1) ] >> char_('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
}

我个人不会轻易地使用语义动作或phoenix。这并不是齐潘的精神

这是我的看法:

rule<char const*, char()> r = 
   (omit [ int_(0) ] >> char_('a')) |
   (omit [ int_(1) ] >> char_('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
}

通过qi的可能解决方法::lazy我已经添加了一个没有语义操作的答案@sehe:semantic actions是邪恶的:你的帖子中有一个很好的部分专门讨论了它们实际上是什么时候必要的:虽然这一点被采纳了,但我想问一下与解析器中上下文敏感度相关的问题,而不是让它成为一个实际的解析问题,这个例子只是一个简单的表达。我的2c。尽管如此,如果我们中的一个被接受,那将是一件好事…@Fatalflow:这是问题的标题,而不是我的答案:我的观点是,避免语义动作可以让你的语法保持简单和易于维护,编译时间和对例如Phoenix的依赖性都很低。我有耐心,我相信OP总有一天会通过qi::lazy重新审视这一可能的解决方法。我已经添加了一个没有语义操作的答案@sehe:semantic actions是邪恶的:你的帖子中有一个很好的部分是关于它们何时是真正必要的:虽然有点,但我想问一下与解析器中的上下文敏感度相关的问题,而不是把它变成一个实际的解析问题,这个例子只是一个简单的表达。我的2c。尽管如此,如果我们中的一个被接受,那将是一件好事…@Fatalflow:这是问题的标题,而不是我的答案:我的观点是,避免语义动作可以让你的语法保持简单和易于维护,编译时间和对例如Phoenix的依赖性都很低。我有耐心,我相信总有一天OP会重新考虑这个问题