我想实现输入字符串的颜色突出显示,该输入字符串被馈送到给定的精神语法。是否有一种简单(或任何一种,如果不是很简单的方法)将给定字符从输入映射到匹配的规则/ ast类型?最好以规则/ ast类型的数组/ vector 的形式表示,其中index是输入字符串的字符的索引。也许更好-迭代器对ast类型大肆宣传。

最佳答案

当然有这个站点上的几个答案说明了类似的事情。您必须决定如何对待子规则。

使用 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_viewstring_ref代替iterator_range。而且,该“折叠”相邻范围会导致更多可用范围。

其他相关示例:
  • Cross-platform way to get line number of an INI file where given option was found
  • boost spirit parse with the source
  • 09-26 04:47