代码之家  ›  专栏  ›  技术社区  ›  PiotrK

将输入映射到boost spirit中的ast类型

  •  1
  • PiotrK  · 技术社区  · 7 年前

    我想实现输入字符串的颜色突出显示,该字符串被输入到给定的spirit语法中。有没有一种简单的(或者任何的,如果不简单的话)方法可以将给定的字符从输入映射到它匹配的rule/ast类型?最好采用rule/ast类型的数组/向量形式,其中index是输入字符串字符的索引。或者更好的方法是-迭代器对ast类型使用rage。

    1 回复  |  直到 7 年前
        1
  •  1
  •   sehe    7 年前

    当然有。这个网站上的几个答案也说明了类似的问题。你必须决定如何处理子规则。

    一个随机的例子 on_success 以下内容:

    Live On Coliru

    //#define BOOST_SPIRIT_DEBUG
    #include <boost/spirit/include/qi.hpp>
    #include <iomanip>
    namespace qi = boost::spirit::qi;
    
    using It     = std::string::const_iterator;
    using R      = boost::iterator_range<It>;
    using RuleId = void const*;
    
    struct token {
        R what;
        RuleId r_id;
    }; 
    
    struct assocociate_f {
        std::vector<token>& into;
        RuleId r_id = nullptr;
    
        template <typename Ctx>
        void operator()(qi::unused_type, Ctx& ctx) const {
            using boost::fusion::at_c;
            into.push_back({at_c<0>(ctx.attributes), r_id});
        }
    };
    
    int main() {
        qi::rule<It, R()> numlit, ident, oper;
        qi::rule<It, R(), qi::space_type> simple, expr;
    
        numlit = qi::raw[qi::double_];
        ident  = qi::raw[qi::lexeme[qi::alpha >> *qi::alnum]];
        simple = qi::raw[(numlit | ident | '(' >> expr >> ')')];
        oper   = qi::raw[qi::char_("-+*/%")];
        expr   = qi::raw[simple >> *(oper >> expr)];
    
        std::vector<token> collect;
        qi::on_success(numlit, assocociate_f{collect, &numlit});
        qi::on_success(ident,  assocociate_f{collect, &ident});
        qi::on_success(oper,   assocociate_f{collect, &oper});
        //qi::on_success(simple, assocociate_f{collect, &simple});
        //qi::on_success(expr,   assocociate_f{collect, &expr});
    
        BOOST_SPIRIT_DEBUG_NODES((numlit)(ident)(simple)(expr));
    
        auto idof = [&](token const& tok) -> std::string {
            auto match = [&](auto const& x) { return tok.r_id == static_cast<void const*>(&x); };
            if (match(numlit)) return "numeric literal";
            if (match(ident))  return "identifier";
            if (match(simple)) return "simple expression";
            if (match(expr))   return "expression";
            if (match(oper))   return "operator";
            return "other";
        };
    
        for (std::string const input : { "3 * pi + (13/47 - 5)" }) {
            std::cout << std::setw(20) << "input: " << input << "\n";
            It f = input.begin(), l = input.end();
    
            if (qi::phrase_parse(f, l, expr, qi::space)) {
                for (auto& tok : collect) {
                    std::cout 
                        << std::setw(20) << idof(tok) + ": "
                        << std::setw(tok.what.begin() - input.begin() + 1) << tok.what
                        << "\n";
                }
            } else {
                std::cout << "Parse failed\n";
            }
    
            if (f!=l) {
                std::cout << "Remaining: '" << std::string(f,l) << "'\n";
            }
        }
    }
    

    打印

                 input: 3 * pi + (13/47 - 5)
       numeric literal: 3
              operator:   *
            identifier:     pi
              operator:        +
       numeric literal:           13
              operator:             /
       numeric literal:              47
              operator:                 -
       numeric literal:                   5
    

    取消附加注释

    //qi::on_success(simple, assocociate_f{collect, &simple});
    //qi::on_success(expr,   assocociate_f{collect, &expr});
    

    你得到: Live On Coliru

                 input: 3 * pi + (13/47 - 5)
       numeric literal: 3
     simple expression: 3
              operator:   *
            identifier:     pi
     simple expression:     pi
              operator:        +
       numeric literal:           13
     simple expression:           13
              operator:             /
       numeric literal:              47
     simple expression:              47
              operator:                 -
       numeric literal:                   5
     simple expression:                   5
            expression:                   5
            expression:              47 - 5
            expression:           13/47 - 5
     simple expression:          (13/47 - 5)
            expression:          (13/47 - 5)
            expression:     pi + (13/47 - 5)
            expression: 3 * pi + (13/47 - 5)
    

    更多

    一个更有趣的例子是 How to provider user with autocomplete suggestions for given boost::spirit grammar? -其中 string_view string_ref 正在使用而不是 iterator_range 是的。此外,这会“折叠”相邻的范围,从而产生更多可用的范围。

    其他相关例子: