【问题标题】:how to access elements of a tuple in a semantic action如何在语义动作中访问元组的元素
【发布时间】:2017-01-16 00:33:51
【问题描述】:

我的语法有各种以通用名称开头的条目。 在确定类型后,我想使用期望运算符来创建解析错误。

rule1=name >> (type1 > something);
rule2=name >> (type2 > something);

我已经知道我不能混合使用 > 和 >> 这两个运算符——这就是括号的原因。我的猜测是括号会导致创建一个元组。 如何在语义操作中访问元组的元素? 以下肯定是错误的,但应该澄清我想要完成的事情。

rule1=(name >> (type1 > something))[qi::_val = boost::phoenix::bind(
    create,
    qi::_1,
    std::get<0>(qi::_2), 
    std::get<1>(qi::_2))];

谢谢

【问题讨论】:

    标签: c++ boost-spirit boost-spirit-qi boost-fusion boost-phoenix


    【解决方案1】:

    直接解决问题:

    using px::at_c;
    rule1 = (name >> (type1 > something)) [_val = px::bind(create, _1, at_c<0>(_2), at_c<1>(_2))];
    

    但是,我会在 qi::eps 中使用这个小技巧来避免复杂性:

    rule2 = (name >> type1 >> (eps > something)) [_val = px::bind(create, _1, _2, _3)];
    

    最后看看boost::phoenix::function&lt;&gt;

    px::function<decltype(&create)> create_(create); // or just decltype(create) if it's a function object
    rule3 = (name >> type1 >> (eps > something)) [_val = create_(_1, _2, _3)];
    

    这样你甚至可以拥有可读的代码!

    演示

    只是为了证明所有三个都有相同的行为¹

    Live On Coliru

    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    #include <boost/fusion/include/at_c.hpp>
    
    namespace qi = boost::spirit::qi;
    namespace px = boost::phoenix;
    
    static int create(char n, char t, char s) {
        assert(n=='n' && t=='t' && s=='s');
        return 42;
    }
    
    int main() {
        using It = std::string::const_iterator;
    
        // fake rules just for demo
        qi::rule<It, char()>
            name = qi::char_("n"),
            type1 = qi::char_("t"),
            something = qi::char_("s");
    
        //using boost::fusion::at_c;
        qi::rule<It, int(), qi::space_type> rule1, rule2, rule3;
    
        {
            using namespace qi;
            using px::at_c;
    
            rule1 = (name >> (type1 > something))        [_val = px::bind(create, _1, at_c<0>(_2), at_c<1>(_2))];
            rule2 = (name >> type1 >> (eps > something)) [_val = px::bind(create, _1, _2, _3)];
    
            px::function<decltype(&create)> create_(create); // or just decltype(create) if it's a function object
            rule3 = (name >> type1 >> (eps > something)) [_val = create_(_1, _2, _3)];
        }
    
        for(auto& parser : { rule1, rule2, rule3 }) {
            for(std::string const input : { "n t s", "n t !" }) {
                std::cout << "Input: '" << input << "'\n";
                auto f = input.begin(), l = input.end();
                int data;
    
                try {
                    bool ok = qi::phrase_parse(f, l, parser, qi::space, data);
                    if (ok) {
                        std::cout << "Parsing result: " << data << '\n';
                    } else {
                        std::cout << "Parsing failed\n";
                    }
                } catch(qi::expectation_failure<It> const& e) {
                    std::cout << "Expectation failure: " << e.what() << " at '" << std::string(e.first, e.last) << "'\n";
                }
    
                if (f!=l) {
                    std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
                }
    
                std::cout << "-------------------------------------------\n";
            }
        }
    }
    

    打印 3 倍相同的输出:

    Input: 'n t s'
    Parsing result: 42
    -------------------------------------------
    Input: 'n t !'
    Expectation failure: boost::spirit::qi::expectation_failure at '!'
    Remaining unparsed: 'n t !'
    -------------------------------------------
    Input: 'n t s'
    Parsing result: 42
    -------------------------------------------
    Input: 'n t !'
    Expectation failure: boost::spirit::qi::expectation_failure at '!'
    Remaining unparsed: 'n t !'
    -------------------------------------------
    Input: 'n t s'
    Parsing result: 42
    -------------------------------------------
    Input: 'n t !'
    Expectation failure: boost::spirit::qi::expectation_failure at '!'
    Remaining unparsed: 'n t !'
    -------------------------------------------
    

    ¹ PS 让这作为如何在您的问题中创建 SSCCE 代码示例的示例

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-17
      • 1970-01-01
      • 1970-01-01
      • 2020-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多