将输入映射到提升精神的 ast 类型

Map input to ast types in boost spirit

本文关键字:ast 类型 输入 映射      更新时间:2023-10-16

我想实现输入字符串的颜色突出显示,该输入字符串正在馈送到给定的精神语法。有没有一种简单(或任何,如果不是简单的话(的方法将给定字符从输入映射到它匹配的规则/ast 类型?优选规则/ast类型的数组/向量形式,其中索引是输入字符串字符的索引。或者也许更好 - 迭代器对 ast 类型肆虐。

当然有。这个网站上的几个答案展示了类似的事情。您必须决定如何处理子规则。

使用on_success的随机示例:

住在科里鲁

//#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 failedn";
}
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});

你得到:住在科里鲁

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)

更多

一个更时髦的例子是 如何为用户提供给定的 boost::spirit 语法的自动完成建议? - 使用string_viewstring_ref而不是iterator_range的地方。此外,这会"折叠"相邻范围以产生更多可用范围。

其他相关示例:

  • 获取 INI 文件行号的跨平台方式,其中找到了给定的选项
  • 使用源头增强精神解析