Trong Boost :: Spirit, làm thế nào tôi có thể kích hoạt một expectation_failure
từ một chức năng ràng buộc với Boost::Bind
?Làm thế nào để ném một expectation_failure từ một chức năng trong Tăng Thần?
Thông tin cơ bản: Tôi phân tích cú pháp tệp lớn chứa các mục nhập phức tạp. Khi một mục nhập không phù hợp với mục nhập trước tôi muốn thất bại và ném một số expectation_failure
(chứa thông tin vị trí phân tích thích hợp). Khi tôi phân tích cú pháp một mục, tôi ràng buộc một hàm quyết định xem mục nhập có không phù hợp với một cái gì đó đã thấy trước đây không.
Tôi đã tạo ra một ví dụ về đồ chơi nhỏ thể hiện quan điểm. Ở đây tôi chỉ đơn giản là muốn ném một expectation_failure
khi int
là không chia hết cho 10:
#include <iostream>
#include <iomanip>
#include <boost/spirit/include/qi.hpp>
#include <boost/bind.hpp>
#include <boost/spirit/include/classic_position_iterator.hpp>
namespace qi = boost::spirit::qi;
namespace classic = boost::spirit::classic;
void checkNum(int const& i) {
if (i % 10 != 0) // >> How to throw proper expectation_failure? <<
std::cerr << "ERROR: Number check failed" << std::endl;
}
template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, int(), Skipper> {
MyGrammar() : MyGrammar::base_type(start) {
start %= qi::eps > qi::int_[boost::bind(&checkNum, _1)];
}
qi::rule<Iterator, int(), Skipper> start;
};
template<class PosIter>
std::string errorMsg(PosIter const& iter) {
const classic::file_position_base<std::string>& pos = iter.get_position();
std::stringstream msg;
msg << "parse error at file " << pos.file
<< " line " << pos.line << " column " << pos.column << std::endl
<< "'" << iter.get_currentline() << "'" << std::endl
<< std::setw(pos.column) << " " << "^- here";
return msg.str();
}
int main() {
std::string in = "11";
typedef std::string::const_iterator Iter;
typedef classic::position_iterator2<Iter> PosIter;
MyGrammar<PosIter, qi::space_type> grm;
int i;
PosIter it(in.begin(), in.end(), "<string>");
PosIter end;
try {
qi::phrase_parse(it, end, grm, qi::space, i);
if (it != end)
throw std::runtime_error(errorMsg(it));
} catch(const qi::expectation_failure<PosIter>& e) {
throw std::runtime_error(errorMsg(e.first));
}
return 0;
}
Ném một expectation_failure
sẽ có nghĩa là tôi nhận được một thông báo lỗi như thế này trên một int mà không chia hết cho 10:
parse error at file <string> line 1 column 2
'11'
^- here
Bạn có thể tạo quy tắc khác thay vì int_, mã này chỉ khớp với số nguyên khi điều kiện của bạn được thỏa mãn không? Tôi không biết rõ về Thần Khí, nhưng tôi cho rằng có một quy tắc tương tự như r_bool trong AX, kết thúc tốt đẹp một vị ngữ, đó là tình huống khá phổ biến. –
Tôi nghĩ tôi sẽ cần một cái gì đó như thế này, thật không may: http://boost-spirit.com/home/articles/qi-example/creating-your-own-parser-component-for-spirit-qi/ – Frank
Xin lỗi thấy rằng, nó rất thân thiện với người dùng. Đó là lý do tại sao bạn cần AX :-) –