Разбор снизу вверх с повышением духа - PullRequest
2 голосов
/ 05 января 2012

Я хотел создать правило в 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);

Однако меня по-прежнему беспокоят две вещи:

  1. Это выглядит немного сложным и загроможденным.Может быть, есть более компактный / элегантный способ сделать это?
  2. Также меня беспокоит эффективность этого подхода.Влияет ли использование унаследованных атрибутов, локальных и особенно phoenix :: construct на производительность духа?

Полный код здесь

...