Re: Need to improve syntax error diagnostic message for Spirit grammar
"Mccall, Kurt E. \(MSFC-EV41\) via Spirit-general" <[email protected]> Fri, 25 Sep 2020 20:06:07 +0000
| Newsgroups | gmane.comp.parsers.spirit.general |
|---|---|
| Message-ID | <SA9PR09MB5808EDCA5E7FA7223CB168D8C6360@SA9PR09MB5808.namprd09.prod.outlook.com> |
Seth, My mistake, my error message below shows that it is working as desired. Spirit is taking the beginning quote of the third line as the end quote of the second, which makes sense. Thanks for your help! Kurt -----Original Message----- From: Mccall, Kurt E. (MSFC-EV41) <[email protected]> Sent: Thursday, September 24, 2020 1:31 PM To: Spirit General Mailing List <[email protected]> Cc: Mccall, Kurt E. (MSFC-EV41) <[email protected]> Subject: RE: [Spirit-general] Need to improve syntax error diagnostic message for Spirit grammar Seth, I tried to imitate your example, but my code is still not pointing to the missing double quote in my input string. The error message is: error: line 3 col 23: Missing ending semicolon liftoff2 = "time > 0.35"; ^-- here Parsing failed Here is the self-contained example, hopefully less of a jigsaw puzzle. ************************************ #include <iostream> #include <map> #include <string> #include <iomanip> #include "/opt/boost_pgc/include/boost/spirit/include/qi.hpp" #include "/opt/boost_pgc/include/boost/spirit/include/qi_expect.hpp" #include "/opt/boost_pgc/include/boost/spirit/home/support/iterators/line_pos_iterator.hpp" #include "/opt/boost_pgc/include/boost/locale.hpp" namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; namespace phoenix = boost::phoenix; using qi::eps; using qi::lexeme; using ascii::char_; using ascii::space; // for on_error using qi::on_error; using qi::fail; using phoenix::val; using std::cout; using std::cerr; using std::endl; using std::string; using Position_Itr_T = boost::spirit::line_pos_iterator<std::string::iterator>; template <typename Iterator, typename Skipper> class Grammar4 : boost::spirit::qi::grammar<Iterator, Skipper> { public: using rule_T = boost::spirit::qi::rule<Iterator>; using rule_nil_T = boost::spirit::qi::rule<Iterator, Skipper>; using rule_str_T = boost::spirit::qi::rule<Iterator, string()>; // thanks for this idea! using diagnostics = std::map<std::string, std::string>; struct error_handler_impl { template <typename, typename, typename, typename, typename> struct result { typedef void type; }; template <typename D, typename I> void operator()(D& _diagnostics, Iterator _begin, Iterator _end, Iterator _where, I const& _info) const { string const& tag(_info.tag); string const scratch = "Invalid syntax: expected " + tag; string const scratch2 = "Missing "; auto diagnostic(_diagnostics[tag]); if (diagnostic.empty()) diagnostic = scratch; else diagnostic = scratch2 + diagnostic; // raise_parsing_error(diagnostic, _begin, _end, _where); auto bol = get_line_start(_begin, _where); auto eol = get_line_end(_where, _end); auto line = get_line(_where); auto col = get_column(bol, _where); std::string subject(bol, eol); auto pos = std::distance(bol, _where); cerr << "error: line " << line << " col " << col << ": " << diagnostic << "\n"; cerr << subject << "\n"; cerr << std::setw(pos) << "" << "^-- here\n"; } }; diagnostics d0, d1, d2, d3; boost::phoenix::function<error_handler_impl> error_handler; rule_T comma, colon, semi, equals, keyword_events, dquote; rule_str_T ident, quoted_str; rule_nil_T start, event_list, event; Grammar4(void) : Grammar4::base_type{start} { comma = ','; comma.name(","); colon = ':'; colon.name(":"); semi = ';'; semi.name(";"); equals = '='; equals.name("="); dquote = '"'; dquote.name("\""); keyword_events = "events"; ident = lexeme [ qi::raw [ (qi::alpha | '_') >> *(qi::alnum | '_') ] ]; quoted_str = lexeme [ dquote > +(char_ - '"') > dquote ]; //d0 = { // { dquote.name(), "double quote" } //}; ident.name("ident"); quoted_str.name("quoted_str"); start.name("start"); keyword_events.name("keyword_events"); event_list.name("event_list"); event.name("event"); start = eps > keyword_events > colon > event_list > semi > qi::eoi ; d1 = { { keyword_events.name(), "events keyword" }, { colon.name(), "colon after events keyword" }, { event_list.name(), "event list", }, { semi.name(), "ending semicolon" } }; event_list = eps > event % comma ; d2 = { { event.name(), "event definition" }, { comma.name(), "comma" } }; event = eps > ident > equals > quoted_str ; d3 = { { ident.name(), "identifier" }, { equals.name(), "equals sign" }, { quoted_str.name(), "quoted C-expression string" } }; //auto handler_bind0 = error_handler(phoenix::ref(d0), qi::_1, qi::_2, qi::_3, qi::_4); auto handler_bind1 = error_handler(phoenix::ref(d1), qi::_1, qi::_2, qi::_3, qi::_4); auto handler_bind2 = error_handler(phoenix::ref(d2), qi::_1, qi::_2, qi::_3, qi::_4); auto handler_bind3 = error_handler(phoenix::ref(d3), qi::_1, qi::_2, qi::_3, qi::_4); //on_error<fail>(quoted_str, handler_bind0); on_error<fail>(start, handler_bind1); on_error<fail>(event_list, handler_bind2); on_error<fail>(event, handler_bind3); } ~Grammar4(void) { }; void parseInputFile(Iterator itr, Iterator itr_end) { try { bool r = phrase_parse(itr, itr_end, start, space); if (r) cout << "Parsing succeeded\n"; else cout << "Parsing failed\n"; } catch (qi::expectation_failure<Position_Itr_T> const& ef) { cout << "Parsing failed2\n"; //std::cout << "what 1: " << ef.what() << "\n"; //std::cout << "what 2: " << ef.what_ << "\n"; } } }; int main(int argc, char **argv) { boost::locale::generator gen; std::locale loc = gen("en_US.UTF-8"); cout.imbue(loc); Grammar4<Position_Itr_T, boost::spirit::ascii::space_type> g; // SYNTAX ERROR: missing closing double quote after time > 0.25 string input("events : \n \ liftoff = \"time > 0.25, \n \ liftoff2 = \"time > 0.35\";"); Position_Itr_T begin(input.begin()); Position_Itr_T end(input.end()); g.parseInputFile(begin, end); return 0; }; _______________________________________________ Spirit-general mailing list [email protected] https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.sourceforge.net_lists_listinfo_spirit-2Dgeneral&d=DwICAg&c=ApwzowJNAKKw3xye91w7BE1XMRKi2LN9kiMk5Csz9Zk&r=6cP1IfXu3IZOHSDh_vBqciYiIh4uuVgs1MSi5K7l5fQ&m=JQv3mClgVZPLRAmss85i3oF_jcnuGGJhiPqwdIMlHkk&s=_bKJ982Q1OiWqSD7sijWnuzIZN0HoBj2AinndrUuMLw&e= _______________________________________________ Spirit-general mailing list [email protected] https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.sourceforge.net_lists_listinfo_spirit-2Dgeneral&d=DwICAg&c=ApwzowJNAKKw3xye91w7BE1XMRKi2LN9kiMk5Csz9Zk&r=6cP1IfXu3IZOHSDh_vBqciYiIh4uuVgs1MSi5K7l5fQ&m=MRjyf7v_iV5tkJSmWgAboOnAQQlSXc9uj9tZ3UN_FSs&s=cJPsFURy9_ClYFBDfvHj68wgV1xrWH476-9iAI0We10&e=