Семантические действия духа после устранения левой рекурсии

Следуя образцу в классическом FAQ по устранению левой рекурсии, я не могу определить правильные заполнители для семантических действий Phoenix. Моя нерабочая грамматика показана ниже:

template <typename It, typename Skipper = qi::space_type>
struct parser : qi::grammar<It, expr(), Skipper>
{
    parser() : parser::base_type(expression)
    {
        using namespace qi;

        expression =
                term                        [_val = _1]
                >> *( (char_('+') >> term)  [_val = phx::construct<binop<op_add>>(_1, _2)]
                    | (char_('-') >> term)  [_val = phx::construct<binop<op_sub>>(_1, _2)]
                    ) ;
        term =
            factor                          [_val = _1]
                >> *( (char_('*') >> factor)    [_val = phx::construct<binop<op_mul>>(_1, _2)]
                    | (char_('/') >> factor)    [_val = phx::construct<binop<op_div>>(_1, _2)]
                   );

        factor =
                uint_                           [_val = _1]
            | var_                          [_val = _1]
            | ('(' >> expression >> ')')    [_val = _1]
            | (char_('-') > factor)         [_val = phx::construct<unop<op_uminus>>(_1)]
            | (char_('+') > factor)         [_val = _1]
            ;


        var_ = qi::lexeme[ +alpha ];

        BOOST_SPIRIT_DEBUG_NODE(expression);
        BOOST_SPIRIT_DEBUG_NODE(term);
        BOOST_SPIRIT_DEBUG_NODE(factor);
        BOOST_SPIRIT_DEBUG_NODE(var_);
    }
  private:
    qi::rule<It, var() , Skipper> var_;
    qi::rule<It, expr(), Skipper> expression, term, factor;
};

Любая помощь в правильном способе обработки атрибутов будет принята с благодарностью.

Спасибо.


person KentH    schedule 24.04.2014    source источник
comment
Чтобы упростить поиск вашего вопроса, вам, вероятно, следует добавить больше тегов (например, boost и/или boost-spirit). Также, если вы добавите c++, ваш код будет иметь подсветку синтаксиса.   -  person llonesmiz    schedule 24.04.2014


Ответы (1)


Я полагаю, вы на самом деле не хотите

>> *( (char_('+') >> term)  [_val = phx::construct<binop<op_add>>(_1, _2)]
    | (char_('-') >> term)  [_val = phx::construct<binop<op_sub>>(_1, _2)]

Передайте '+' в качестве первого параметра конструктора, потому что тип binop<op_add> уже отражает тип оператора. Таким образом, вы, вероятно, захотите, чтобы левый операнд был первым аргументом.

Это аргумент, который вы сейчас разбираете здесь:

term                        [_val = _1]

Вероятно, это должно подсказать вам: вы только что назначили его... _val! Итак, есть ваше решение:

>> *( (char_('+') >> term)  [_val = phx::construct<binop<op_add>>(_val, _2)]
    | (char_('-') >> term)  [_val = phx::construct<binop<op_sub>>(_val, _2)]

Однако, поскольку открытый атрибут из char_(...) не используется, вы можете заменить его:

>> *( (lit('+') >> term)  [_val = phx::construct<binop<op_add>>(_val, _1)]
    | (lit('-') >> term)  [_val = phx::construct<binop<op_sub>>(_val, _1

)]

person sehe    schedule 26.04.2014
comment
Спасибо за вашу помощь. Ответ имеет смысл — использование phx только усложняет задачу! - person KentH; 27.04.2014