c++ - trigger warning from boost spirit parser -
how can add warnings in boost spirit parser.
edit: ... report issue position
for example if have integer parser:
('0' >> oct) | int_
i able this:
('0' >> oct) | "-0" --> trigger warning("negative octal values not supported, interpreted negative decimal value , leading 0 ignored") | int_
q. can create own callback? how?
a. sure. way you'd in c++ (or @ boost signal2 and/or boost log)
parser(std::function<bool(std::string const& s)> callback) : parser::base_type(start), callback(callback) { using namespace qi; start %= as_string[+graph] [ _pass = phx::bind(callback, _1) ] % +space ; boost_spirit_debug_nodes((start)); }
as can see, can make handler decide whether warning should ignored or cause match fail.
update #1 i've extended sample show of unrelated challenges mentioned in comments (position, duplicate checking). hope helps
here's simple demonstration: see live on coliru (word
)
update #2 i've made (a) store source information instead of iterators, (b) made "work" floats (or other exposed attribute type, really).
note how uncannily similar is, s/word/number/
, basically: live on coliru (number
)
#define boost_result_of_use_decltype // needed gcc 4.7, not clang++ #define boost_spirit_use_phoenix_v3 #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> #include <boost/spirit/include/phoenix_stl.hpp> #include <functional> namespace qi = boost::spirit::qi; namespace phx = boost::phoenix; // okay, want position reporting (actually unrelated): #include <boost/spirit/include/support_line_pos_iterator.hpp> using = boost::spirit::line_pos_iterator<std::string::const_iterator>; // ast type represents number 'token' (with source , location // information) struct number { double value; size_t line_pos; std::string source; explicit number(double value = 0.0, boost::iterator_range<it> const& range = {}) : value(value), line_pos(get_line(range.begin())), source(range.begin(), range.end()) {} bool operator< (const number& other) const { return (other.value - value) > 0.0001; } }; // exposed attribute parser: using words = std::set<number>; // callback signature our warning; make more // `on_error` takes iterators directly, again, i'm doing // simple thing dmeo using callback = std::function<bool(number const& s)>; template <typename it> struct parser : qi::grammar<it, words()> { parser(callback warning) : parser::base_type(start), warning(warning) { using namespace qi; auto check_unique = phx::end(_val) == phx::find(_val, _1); word = raw [ double_ [ _a = _1 ] ] [ _val = phx::construct<number>(_a, _1) ] ; start %= - word [ _pass = check_unique || phx::bind(warning, _1) ] % +space >> eoi ; } private: callback warning; qi::rule<it, number(), qi::locals<double> > word; qi::rule<it, words()> start; }; int main(int argc, const char *argv[]) { // parse command line arguments const auto flags = std::set<std::string> { argv+1, argv+argc }; const bool fatal_warnings = end(flags) != flags.find("-werror"); // test input const std::string input("2.4 2.7 \n\n\n-inf \n\nnan 88 -2.40001 \n3.14 240001e-5\n\ninf"); // warning handler auto warning_handler = [&](number const& w) { std::cerr << (fatal_warnings?"error":"warning") << ": near-identical entry '" << w.source << "' @ l:" << w.line_pos << "\n"; return !fatal_warnings; }; // parse f(begin(input)), l(end(input)); bool ok = qi::parse(f, l, parser<it>(warning_handler)); // report results if (ok) std::cout << "parse success\n"; else std::cerr << "parse failed\n"; if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n"; // exit code return ok? 0 : 255; }
prints:
warning: near-identical entry 'nan' @ l:6 warning: near-identical entry '240001e-5' @ l:7 parse success
Comments
Post a Comment