2013-08-12 4 views
4

У меня есть следующий обработчик ошибок в нижней части моего синтаксического анализа грамматики:Ошибка отчетности в Boost Духа

qi::on_error<qi::fail>(
    launch, 
    std::cerr << phoenix::val("Paring error in ") << spirit::_4 << std::endl 
       << phoenix::construct<std::string>(spirit::_3, spirit::_2) 
       << std::endl 
    ); 

Проблема заключается в том, что вход парсера не разбитым на новые линии заранее, так что в результате ошибка будет все строк в исходном коде от точки ошибки до конца. Существует ли простая альтернатива

phoenix::construct<std::string>(spirit::_3, spirit::_2) 

только для печати одной строки, на которой происходит ошибка? Семантика Phoenix дает мне проблемы, если я попытаюсь просто найти '\n'.

ответ

7

Нам нужно создать функцию Phoenix, которая может принимать параметры Spirit.

// lazy function for error reporting 
struct ReportError { 
    // the result type must be explicit for Phoenix 
    template<typename, typename, typename, typename> 
    struct result { typedef void type; }; 

    // contract the string to the surrounding new-line characters 
    template<typename Iter> 
    void operator()(Iter first_iter, Iter last_iter, 
        Iter error_iter, const qi::info& what) const { 
    std::string first(first_iter, error_iter); 
    std::string last(error_iter, last_iter); 
    auto first_pos = first.rfind('\n'); 
    auto last_pos = last.find('\n'); 
    auto error_line = ((first_pos == std::string::npos) ? first 
         : std::string(first, first_pos + 1)) 
         + std::string(last, 0, last_pos); 
    auto error_pos = (error_iter - first_iter) + 1; 
    if (first_pos != std::string::npos) { 
     error_pos -= (first_pos + 1); 
    } 
    std::cerr << "Parsing error in " << what << std::endl 
       << error_line << std::endl 
       << std::setw(error_pos) << '^' 
       << std::endl; 
    } 
}; 

const phoenix::function<ReportError> report_error = ReportError(); 

Затем мы просто вызываем эту функцию в обработчике ошибок.

qi::on_error<qi::fail>(
    launch, 
    report_error(spirit::_1, spirit::_2, spirit::_3, spirit::_4) 
    ); 
Смежные вопросы