将输入映射为Boost类型的ast类型 [英] Map input to ast types in boost spirit

查看:68
本文介绍了将输入映射为Boost类型的ast类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to implement color highlighting of input string that is being fed to given spirit grammar. Is there an easy (or any, if not easy) way to map given character from input into rule/ast type that it matches? Preferable in form of array/vector of rule/ast types where index is index of character of input string. Or maybe better - iterator rages to ast types.

推荐答案

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

Of course there is. Several answers on this site demonstrate similar things. You'll have to decide how you want to treat subrules.

使用 在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});

您得到: 在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)

更多

一个更时髦的示例是

More

A more funky example would be How to provider user with autocomplete suggestions for given boost::spirit grammar? - where string_view or string_ref is being used instead of iterator_range. Also, that "collapses" adjacent ranges to result in more usable ranges.

其他相关示例:

  • Cross-platform way to get line number of an INI file where given option was found
  • boost spirit parse with the source

这篇关于将输入映射为Boost类型的ast类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆