Я хотел создать правило в boost :: spirit :: qi, которое выполняет восходящий анализ .
У меня есть такая структура данных:
struct Bnop;
typedef boost::variant<int,boost::recursive_wrapper<Bnop> > Expr;
struct Bnop { char op; Expr left, right; };
BOOST_FUSION_ADAPT_STRUCT ( Bnop, (Expr, left) (char, op) (Expr, right))
И сэти правила:
qi::rule<Iter,Expr(),ns::space_type> ex;
qi::rule<Iter,Bnop(),ns::space_type> bin;
ex = bin | qi::int_;
bin = qi::int_ >> ns::char_ >> ex;
Строка «1 + 2 + 3 + 4 + 5» разбирается в структуру, которая «похожа» (1+ (2+ (3+ (4 + 5))))
По сути, я хотел достичь ((((1 + 2) +3) +4) +5)
После некоторой борьбы я действительно принял рабочее решение.Правила таковы:
qi::rule<Iter,Expr(),qi::locals<int>,ns::space_type> expr;
qi::rule<Iter,Expr(Expr),qi::locals<char,int>,ns::space_type> rhs;
expr = omit[ int_[_a=_1]] >> rhs(_a);
rhs = omit[char_[_a=_1]] >>
omit[ int_[_b=_1]] >>
rhs(construct<Bnop>(_r1,_a,_b))
| attr(_r1);
Однако меня по-прежнему беспокоят две вещи:
- Это выглядит немного сложным и загроможденным.Может быть, есть более компактный / элегантный способ сделать это?
- Также меня беспокоит эффективность этого подхода.Влияет ли использование унаследованных атрибутов, локальных и особенно phoenix :: construct на производительность духа?
Полный код здесь