В настоящее время я изучаю, как использовать x3. Как говорится в заголовке, мне удалось создать грамматику с несколькими простыми правилами, но при объединении двух из этих правил в одно код больше не компилируется. Вот код для части AST:
namespace x3 = boost::spirit::x3;
struct Expression;
struct FunctionExpression {
std::string functionName;
std::vector<x3::forward_ast<Expression>> inputs;
};
struct Expression: x3::variant<int, double, bool, FunctionExpression> {
using base_type::base_type;
using base_type::operator=;
};
Правила, которые я создал для синтаксического анализа, отформатированы как {rangeMin, rangeMax}
:
rule<struct basic_exp_class, ast::Expression> const
basic_exp = "basic_exp";
rule<struct exp_pair_class, std::vector<ast::Expression>> const
exp_pair = "exp_pair";
rule<struct range_class, ast::FunctionExpression> const
range = "range";
auto const basic_exp_def = double_ | int_ | bool_;
auto const exp_pair_def = basic_expr >> ',' >> basic_expr;
auto const range_def = attr("computeRange") >> '{' >> exp_pair >> '}';
BOOST_SPIRIT_DEFINE(basic_expr, exp_pair_def, range_def);
Этот код компилируется нормально. Однако, если я попытаюсь встроить правило exp_pair
в правило range_def
, вот так:
rule<struct basic_exp_class, ast::Expression> const
basic_exp = "basic_exp";
rule<struct range_class, ast::FunctionExpression> const
range = "range";
auto const basic_exp_def = double_ | int_ | bool_;
auto const range_def = attr("computeRange") >> '{' >> (
basic_exp >> ',' >> basic_exp
) >> '}';
BOOST_SPIRIT_DEFINE(basic_expr, range_def);
Код не компилируется с очень длинной ошибкой шаблона, заканчивающейся строкой:
spirit/include/boost/spirit/home/x3/operator/detail/sequence.hpp:149:9: error: static assertion failed: Size of the passed attribute is less than expected.
static_assert(
^~~~~~~~~~~~~
Файл заголовка также включает этот комментарий над static_assert
:
// If you got an error here, then you are trying to pass
// a fusion sequence with the wrong number of elements
// as that expected by the (sequence) parser.
Но я не понимаю, почему код должен дать сбой. Согласно составному , встроенная часть в скобках должна иметь атрибут типа vector<ast::Expression>
, чтобы общее правило имело тип tuple<string, vector<ast::Expression>
, чтобы оно было совместимо с ast::FunctionExpression
. Та же логика применяется к более подробной версии с тремя правилами, с той лишь разницей, что я специально объявил правило для внутренней части и специально указал, что его атрибут должен иметь тип vector<ast::Expression>
.
as
, чтобы вы могли указать тип. stackoverflow.com/questions/49932608/ не могу попробовать сейчас, поэтому не знаю, работает ли он. - person Bob Bills   schedule 22.11.2018as
, я могу изменить правило наauto const range_def = attr("computeRange") >> '{' >> as<std::vector<ast::Expression>>(basic_exp >> ',' >> basic_exp) >> '}';
, и оно успешно скомпилируется. Не могли бы вы изложить свое предложение в виде полного ответа, чтобы я мог его принять? - person CompileYourCake   schedule 22.11.2018FunctionExpression
) анализатору последовательности (... >> ...
), Spirit не будет творить никакой магии (не будет пытаться свернуть последовательность). - person Nikita Kniazev   schedule 23.11.2018