2013-09-05 4 views
3

Я довольно новичок в Boost Spirit. В идеале я хотел бы удостовериться, что две ценности в моей грамматике одинаковы с использованием Phoenix. Опущенная версия того, что я пытаюсь получить, будет кортежем, где оба ints равны.Используйте Boost Phoenix в Ци, чтобы ссылаться на предыдущий матч в грамматике

Я хотел бы, чтобы строка «14,14, test» была проанализирована, но «14,12, test» потерпела неудачу, так как 14 не равно 12. Мне нужен код ниже для печати:

Good: (14 14 test) 
Fail 

В настоящее время оба входа будут проходить с тех пор, как я разрешаю, и qi :: int_ для синтаксического анализа второго значения без каких-либо проверок.

#include <iostream> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 
#include <boost/fusion/include/vector.hpp> 
#include <boost/spirit/include/qi_matches.hpp> 

#include <string> 
#include <vector> 
#include <algorithm> 

namespace qi = boost::spirit::qi; 
namespace phx = boost::phoenix; 


int main(){ 


    std::vector<std::string> test_inputs = {"14,14,test","14,12,test"}; 

    std::for_each(test_inputs.begin(),test_inputs.end(),[](const std::string& input){ 
     boost::fusion::vector<int,int,std::string> result; 
     int i(0); 

     auto res = qi::parse(input.begin(),input.end(), 
      //works but also parses "14,12,test" 
      qi::int_[phx::ref(i) = qi::_1] >> qi::lit(",") >> qi::int_ >> qi::lit(",") >> +qi::char_, 
      //Fails to compile 
      //qi::int_[phx::ref(i) = qi::_1] >> qi::lit(",") >> qi::int_(phx::val(i)) >> qi::lit(",") >> +qi::char_, 
      //qi::int_[phx::ref(i) = qi::_1] >> qi::lit(",") >> qi::int_(phx::ref(i)) >> qi::lit(",") >> +qi::char_, 
      result); 
     if(res){ 
      std::cout << "Good: " << result << std::endl; 
     } 
     else{ 
      std::cout << "Fail" << std::endl; 
     } 
    });   
} 

Я могу использовать ФЕНИКС :: реф, чтобы захватить первое значение, но я не могу понять, чтобы проверить мой второй ци :: int_ анализатор для значения двутавровых. Я пробовал использовать phoenix :: val и phoenix :: ref без компиляции удачи. В идеале я хотел бы зафиксировать значение во втором int и подумал, что парсер int_ возьмет ленивый литерал из Phoenix.

Спасибо за любую помощь по этому вопросу.

+1

Альтернатива, использующая 'phx :: ref' дважды, которую вы отметили как не скомпилированные работы, если вы определяете' BOOST_SPIRIT_USE_PHOENIX_V3' при использовании g ++ 4.8.1 и boost 1.54. Я бы рекомендовал использовать это определение всегда, оно решает множество проблем. – llonesmiz

+1

Я имел в виду определение перед включением заголовков. Вы можете увидеть это [здесь] (http://coliru.stacked-crooked.com/a/01cbe1ce2b361a3d). В любом случае я думаю, что должны быть альтернативные решения, поэтому, надеюсь, вы получите информативный ответ. – llonesmiz

+0

Определяет код для компиляции для меня как в gcc 4.7, так и в Clang. Благодаря! – Joel

ответ

4

Самое простое исправление, чтобы поставить значение i подобран с первого ци :: int_ ко второй, т.е .:

qi::int_[phx::ref(i) = qi::_1] >> qi::lit(",") >> qi::int_(phx::ref(i)) >> qi::lit(",") >> +qi::char_, 

ци :: _ INT с параметром ожидает, что указанное значение.

Другой альтернативой рассмотрению является использование локальной локальной переменной. Вы можете сделать это:

typedef boost::fusion::vector<int,int,std::string> result_t; 
result_t result; 
qi::rule<std::string::const_iterator, result_t(), 
    boost::spirit::qi::locals<int> > r; 
r %= qi::int_[qi::_a = qi::_1] >> qi::lit(",") >> qi::int_(qi::_a) >> qi::lit(",") >> +qi::char_; 

Затем используйте вместо «r» вместо «r». Хотя я полагаю, что если вы просто намереваетесь запустить правило напрямую, используя qi :: parse, это не имеет смысла.

+0

Я думаю, что ваше первое решение - именно то, что я прокомментировал. Для этого нужно было определить BOOST_SPIRIT_USE_PHOENIX_V3. Это было предложено в комментарии @cv_and_he. Когда я это делаю, он работает. – Joel

+0

Следует также отметить, что фрагмент qi :: rule оценен. Проблема заключается в более крупном проекте, который использовал парсер подкласса из qi :: grammar и определенных правил. Я просто пытался создать простой пример кода, который показал проблему. Первоначально я хотел использовать местных жителей, но я не мог заставить это работать хорошо (потому что я уезжал с qi :: locals, без сомнения). Благодаря! – Joel

+0

Ах, по какой-то причине мне не нужен BOOST_SPIRIT_USE_PHOENIX_V3 для этого ... Boost 1.54 с -std = C++ 0x –