From dac3640ed08cf18eaa6eb26605a27e6c7387b2c2 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 14 Mar 2013 11:08:13 +0200 Subject: Add next_expect() functions to XML parser --- cutl/xml/parser.cxx | 74 +++++++++++++++++++++++++++++++-------------- cutl/xml/parser.hxx | 17 +++++++++++ cutl/xml/parser.ixx | 21 +++++++++++++ tests/xml/parser/driver.cxx | 33 ++++++++++++++++++++ 4 files changed, 123 insertions(+), 22 deletions(-) create mode 100644 cutl/xml/parser.ixx diff --git a/cutl/xml/parser.cxx b/cutl/xml/parser.cxx index ca20edd..08f08ff 100644 --- a/cutl/xml/parser.cxx +++ b/cutl/xml/parser.cxx @@ -58,6 +58,26 @@ namespace cutl return what_.c_str (); } + // parser::event_type + // + static const char* parser_event_str[] = + { + "start element", + "end element", + "start attribute", + "end attribute", + "characters", + "start namespace declaration", + "end namespace declaration", + "end of file" + }; + + ostream& + operator<< (ostream& os, parser::event_type e) + { + return os << parser_event_str[e]; + } + // parser // parser:: @@ -117,9 +137,9 @@ namespace cutl switch (content ()) { case empty: - throw parsing (iname_, line_, column_, "character in empty content"); + throw parsing (*this, "character in empty content"); case complex: - throw parsing (iname_, line_, column_, "character in complex content"); + throw parsing (*this, "character in complex content"); default: assert (false); } @@ -171,6 +191,34 @@ namespace cutl istream::iostate old_state_; }; + void parser:: + next_expect (event_type e) + { + if (next () != e) + throw parsing (*this, parser_event_str[e] + string (" expected")); + } + + void parser:: + next_expect (event_type e, const string& ns, const string& n) + { + if (next () != e || namespace_ () != ns || name () != n) + { + string m (parser_event_str[e]); + m += " '"; + + if (!ns.empty ()) + { + m += ns; + m += '#'; + } + + m += n; + m += "' expected"; + + throw parsing (*this, m); + } + } + parser::event_type parser:: next_ () { @@ -190,9 +238,9 @@ namespace cutl switch (content ()) { case empty: - throw parsing (iname_, line_, column_, "element in empty content"); + throw parsing (*this, "element in empty content"); case simple: - throw parsing (iname_, line_, column_, "element in simple content"); + throw parsing (*this, "element in simple content"); default: break; } @@ -630,23 +678,5 @@ namespace cutl p.end_ns_.push_back (qname_type ()); p.end_ns_.back ().prefix () = (prefix != 0 ? prefix : ""); } - - static const char* parser_event_str[] = - { - "start element", - "end element", - "start attribute", - "end attribute", - "characters", - "start namespace declaration", - "end namespace declaration", - "end of file" - }; - - ostream& - operator<< (ostream& os, parser::event_type e) - { - return os << parser_event_str[e]; - } } } diff --git a/cutl/xml/parser.hxx b/cutl/xml/parser.hxx index d7011af..5d1e9e5 100644 --- a/cutl/xml/parser.hxx +++ b/cutl/xml/parser.hxx @@ -131,6 +131,21 @@ namespace cutl } } + // Get the next event and make sure that it's what's expected. If it + // is not, then throw an appropriate parsing exception. + // + void + next_expect (event_type); + + void + next_expect (event_type, const qname_type& qname); + + void + next_expect (event_type, const std::string& name); + + void + next_expect (event_type, const std::string& ns, const std::string& name); + event_type peek () { @@ -283,4 +298,6 @@ namespace cutl } } +#include + #endif // CUTL_XML_PARSER_HXX diff --git a/cutl/xml/parser.ixx b/cutl/xml/parser.ixx new file mode 100644 index 0000000..61bb05b --- /dev/null +++ b/cutl/xml/parser.ixx @@ -0,0 +1,21 @@ +// file : cutl/xml/parser.ixx +// copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +namespace cutl +{ + namespace xml + { + inline void parser:: + next_expect (event_type e, const qname_type& qn) + { + return next_expect (e, qn.namespace_ (), qn.name ()); + } + + inline void parser:: + next_expect (event_type e, const std::string& n) + { + return next_expect (e, std::string (), n); + } + } +} diff --git a/tests/xml/parser/driver.cxx b/tests/xml/parser/driver.cxx index 31d1e97..787da50 100644 --- a/tests/xml/parser/driver.cxx +++ b/tests/xml/parser/driver.cxx @@ -48,6 +48,39 @@ main () { } + // Test the next_expect() functionality. + // + { + istringstream is (""); + parser p (is, "test"); + p.next_expect (parser::start_element, "root"); + p.next_expect (parser::end_element); + } + + try + { + istringstream is (""); + parser p (is, "test"); + p.next_expect (parser::end_element); + assert (false); + } + catch (const xml::exception& e) + { + // cerr << e.what () << endl; + } + + try + { + istringstream is (""); + parser p (is, "test"); + p.next_expect (parser::start_element, "root1"); + assert (false); + } + catch (const xml::exception& e) + { + // cerr << e.what () << endl; + } + // Test peeking and getting the current event. // { -- cgit v1.1