From 5e527213a2430bb3018e5eebd909aef294edf9b5 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 18 Dec 2020 18:48:46 +0300 Subject: Switch to build2 --- xsd/xsd/type-map/lexer.cxx | 131 ++++++++++++++++++++ xsd/xsd/type-map/lexer.hxx | 74 +++++++++++ xsd/xsd/type-map/parser.cxx | 279 ++++++++++++++++++++++++++++++++++++++++++ xsd/xsd/type-map/parser.hxx | 41 +++++++ xsd/xsd/type-map/type-map.hxx | 178 +++++++++++++++++++++++++++ 5 files changed, 703 insertions(+) create mode 100644 xsd/xsd/type-map/lexer.cxx create mode 100644 xsd/xsd/type-map/lexer.hxx create mode 100644 xsd/xsd/type-map/parser.cxx create mode 100644 xsd/xsd/type-map/parser.hxx create mode 100644 xsd/xsd/type-map/type-map.hxx (limited to 'xsd/xsd/type-map') diff --git a/xsd/xsd/type-map/lexer.cxx b/xsd/xsd/type-map/lexer.cxx new file mode 100644 index 0000000..ae318d1 --- /dev/null +++ b/xsd/xsd/type-map/lexer.cxx @@ -0,0 +1,131 @@ +// file : xsd/type-map/lexer.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +using std::wcerr; +using std::endl; + +namespace TypeMap +{ + Lexer::Lexer (std::istream& is, String const& path) + : locale_ ("C"), is_ (is), path_ (path), line_ (1), comment_ (false) + { + is_.exceptions (std::ios_base::badbit); + } + + Lexer::Token Lexer:: + next () + { + if (held_lexeme_) + { + Token t (Token::punct, held_lexeme_, line_); + held_lexeme_.clear (); + return t; + } + + typedef std::char_traits Traits; + typedef Traits::char_type CharType; + typedef Traits::int_type IntType; + + IntType i; + CharType c ('\0'); + NarrowString lexeme; + + // Skip all whitespaces including comments. + // + while (!is_.eof ()) + { + i = is_.get (); + + if (i == Traits::eof ()) + break; + + c = Traits::to_char_type (i); + + if (comment_) + { + if (c == '\n') + comment_ = false; + } + else + { + if (!(std::isspace (c, locale_) || c == '#')) + break; + + if (c == '#') + comment_ = true; + } + + if (c == '\n') + ++line_; + } + + if (is_.eof ()) + return Token (Token::eos, L"", line_); + + bool quote (c == '"'); + + if (!quote) + lexeme += c; + + if (c != ';' && c != '{' && c != '}') + { + // Accumulate non-whitespace character sequence. + // + + while (!is_.eof ()) + { + i = is_.get (); + + if (i == Traits::eof ()) + break; + + c = Traits::to_char_type (i); + + if (!quote && c == '#') + { + comment_ = true; + break; + } + + if (std::isspace (c, locale_)) + { + if (c == '\n') + ++line_; + + if (!quote) + break; + } + + if (!quote && (c == ';' || c == '{' || c == '}')) + { + held_lexeme_ += c; + break; + } + + if (quote && c == '"') + break; + + lexeme += c; + } + + if (quote && c != '"') + { + wcerr << path_ << ":" << line_ << ": error: closing '\"' expected" + << endl; + + throw Failed (); + } + } + + if (!quote && (lexeme == ";" || lexeme == "{" || lexeme == "}")) + { + return Token (Token::punct, lexeme, line_); + } + else + return Token (Token::token, lexeme, line_); + } +} diff --git a/xsd/xsd/type-map/lexer.hxx b/xsd/xsd/type-map/lexer.hxx new file mode 100644 index 0000000..a0e1e44 --- /dev/null +++ b/xsd/xsd/type-map/lexer.hxx @@ -0,0 +1,74 @@ +// file : xsd/type-map/lexer.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_TYPE_MAP_LEXER_HXX +#define XSD_TYPE_MAP_LEXER_HXX + +#include +#include + +#include + +namespace TypeMap +{ + class Lexer + { + public: + class Token + { + public: + enum Type + { + token, + punct, + eos + }; + + Token (Type type, String const& lexeme, size_t line) + : type_ (type), lexeme_ (lexeme), line_ (line) + { + } + + Type + type () const + { + return type_; + } + + String const& + lexeme () const + { + return lexeme_; + } + + size_t + line () const + { + return line_; + } + + private: + Type type_; + String lexeme_; + size_t line_; + }; + + Lexer (std::istream&, String const& path); + + struct Failed {}; + + Token + next (); + + private: + std::locale locale_; + std::istream& is_; + String path_; + size_t line_; + String held_lexeme_; + bool comment_; + }; + +} + +#endif // XSD_TYPE_MAP_LEXER_HXX diff --git a/xsd/xsd/type-map/parser.cxx b/xsd/xsd/type-map/parser.cxx new file mode 100644 index 0000000..f11fac3 --- /dev/null +++ b/xsd/xsd/type-map/parser.cxx @@ -0,0 +1,279 @@ +// file : xsd/type-map/parser.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include + +using std::endl; + +namespace TypeMap +{ + typedef Lexer::Token Token; + typedef cutl::re::wformat Format; + + Parser::Parser (Lexer& lex, String const& path) + : lex_ (lex), path_ (path), e (std::wcerr) + { + } + + bool Parser:: + parse (Namespaces& ns) + { + try + { + Namespace* global = 0; + + for (Token t (lex_.next ()); t.type () != Token::eos; t = lex_.next ()) + { + String l (t.lexeme ()); + + if (l == L"namespace") + { + global = 0; + + if (!namespace_ (ns)) + return false; + } + else if (l == L"include") + { + if (global == 0) + { + ns.push_back (Namespace (Pattern ())); + global = &(*ns.rbegin ()); + } + + if (!include (*global)) + return false; + } + else if (l == L"type" || t.type () == Token::token) + { + // Type mapping can have 'type' specifier omitted. + // + if (l == L"type") + t = lex_.next (); + + if (global == 0) + { + ns.push_back (Namespace (Pattern ())); + global = &(*ns.rbegin ()); + } + + if (!type (t, *global)) + return false; + } + else + { + e << path_ << ":" << t.line () << ": unexpected '" << l << "'" + << endl; + + return false; + } + } + } + catch (Lexer::Failed const&) + { + return false; + } + + return true; + } + + bool Parser:: + namespace_ (Namespaces& ns) + { + // First get XML namespace. + // + Token t (lex_.next ()); + + Pattern xsd_name; + + try + { + xsd_name = t.lexeme (); + } + catch (Format const& ex) + { + e << path_ << ":" << t.line () << ": invalid namespace pattern: " + << ex.description ().c_str () << endl; + return false; + } + + if (t.type () != Token::token) + { + e << path_ << ":" << t.line () << ": expected XML namespace " + << "instead of '" << xsd_name << "'" << endl; + return false; + } + + + // See if we've got optional C++ mapping. + // + t = lex_.next (); + + bool has_cxx_name (false); + String cxx_name; + + if (t.type () != Token::token) + { + if (t.lexeme () != L"{") + { + e << path_ << ":" << t.line () << ": expected C++ namespace or '{' " + << "instead of '" << t.lexeme () << "'" << endl; + return false; + } + } + else + { + has_cxx_name = true; + cxx_name = t.lexeme (); + } + + // Swallow '{' if needed. + // + if (has_cxx_name) + { + t = lex_.next (); + + if (t.type () != Token::punct || t.lexeme () != L"{") + { + e << path_ << ":" << t.line () << ": expected '{' instead of '" + << t.lexeme () << "'" << endl; + return false; + } + } + + Namespace n (xsd_name, has_cxx_name, cxx_name); + + // Parse namespace body. + // + for (t = lex_.next ();; t = lex_.next ()) + { + String l (t.lexeme ()); + + if (l == L"include") + { + if (!include (n)) + return false; + } + else if (l == L"type" || t.type () == Token::token) + { + // Type mapping can have 'type' specifier omitted. + // + if (l == L"type") + t = lex_.next (); + + if (!type (t, n)) + return false; + } + else if (t.type () == Token::punct && l == L"}") + { + break; + } + else + { + e << path_ << ":" << t.line () << ": unexpected '" << l << "'" + << endl; + return false; + } + } + + if (cxx_name || n.types_begin () != n.types_end () || + n.includes_begin () != n.includes_end ()) + { + ns.push_back (n); + } + + return true; + } + + bool Parser:: + include (Namespace& n) + { + Token t (lex_.next ()); + + String path (t.lexeme ()); + + if (t.type () != Token::token) + { + e << path_ << ":" << t.line () << ": expected include path " + << "instead of '" << path << "'" << endl; + return false; + } + + if (path && path[0] == L'<') + n.includes_push_back (path); + else + n.includes_push_back (L'"' + path + L'"'); + + t = lex_.next (); + + if (t.type () != Token::punct || t.lexeme () != L";") + { + e << path_ << ":" << t.line () << ": expected ';' after '" + << path << "'" << endl; + return false; + } + + return true; + } + + bool Parser:: + type (Token t, Namespace& n) + { + Pattern xsd_name; + + try + { + xsd_name = t.lexeme (); + } + catch (Format const& ex) + { + e << path_ << ":" << t.line () << ": invalid namespace pattern: " + << ex.description ().c_str () << endl; + return false; + } + + if (t.type () != Token::token) + { + e << path_ << ":" << t.line () << ": expected XML Schema type name " + << "instead of '" << xsd_name << "'" << endl; + return false; + } + + t = lex_.next (); + String cxx_ret_name (t.lexeme ()); + + if (t.type () != Token::token) + { + e << path_ << ":" << t.line () << ": expected C++ type name " + << "instead of '" << cxx_ret_name << "'" << endl; + return false; + } + + t = lex_.next (); + + String cxx_arg_name; + + // See if we've got optional argument type. + // + if (t.type () == Token::token) + { + cxx_arg_name = t.lexeme (); + t = lex_.next (); + } + + if (t.type () != Token::punct || t.lexeme () != L";") + { + e << path_ << ":" << t.line () << ": expected ';' after '" + << cxx_arg_name << "'" << endl; + return false; + } + + n.types_push_back (xsd_name, cxx_ret_name, cxx_arg_name); + + return true; + } +} diff --git a/xsd/xsd/type-map/parser.hxx b/xsd/xsd/type-map/parser.hxx new file mode 100644 index 0000000..ec9ea49 --- /dev/null +++ b/xsd/xsd/type-map/parser.hxx @@ -0,0 +1,41 @@ +// file : xsd/type-map/parser.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_TYPE_MAP_PARSER_HXX +#define XSD_TYPE_MAP_PARSER_HXX + +#include + +#include +#include + +namespace TypeMap +{ + class Parser + { + public: + Parser (Lexer&, String const& path); + + // Merge parsed namespaces. + // + bool + parse (Namespaces&); + + private: + bool + namespace_ (Namespaces&); + + bool + include (Namespace&); + + bool + type (Lexer::Token, Namespace&); + + private: + Lexer& lex_; + String path_; + std::wostream& e; + }; +} + +#endif // XSD_TYPE_MAP_PARSER_HXX diff --git a/xsd/xsd/type-map/type-map.hxx b/xsd/xsd/type-map/type-map.hxx new file mode 100644 index 0000000..dd2ec2c --- /dev/null +++ b/xsd/xsd/type-map/type-map.hxx @@ -0,0 +1,178 @@ +// file : xsd/type-map/type-map.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_XSD_TYPE_MAP_TYPE_MAP_HXX +#define XSD_XSD_TYPE_MAP_TYPE_MAP_HXX + +#include + +#include + +#include + +namespace TypeMap +{ + typedef cutl::re::wregex Pattern; + + class Type + { + public: + Type (String const& xsd_name, + String const& cxx_ret_name, + String const& cxx_arg_name) + : xsd_name_ (xsd_name), + cxx_ret_name_ (cxx_ret_name), + cxx_arg_name_ (cxx_arg_name) + { + } + + Type (Pattern const& xsd_name, + String const& cxx_ret_name, + String const& cxx_arg_name) + : xsd_name_ (xsd_name), + cxx_ret_name_ (cxx_ret_name), + cxx_arg_name_ (cxx_arg_name) + { + } + + Pattern const& + xsd_name () const + { + return xsd_name_; + } + + String const& + cxx_ret_name () const + { + return cxx_ret_name_; + } + + String const& + cxx_arg_name () const + { + return cxx_arg_name_; + } + + private: + Pattern xsd_name_; + String cxx_ret_name_; + String cxx_arg_name_; + }; + + class Namespace + { + public: + Namespace (String const& xsd_name) + : xsd_name_ (xsd_name), has_cxx_name_ (false) + { + } + + Namespace (Pattern const& xsd_name) + : xsd_name_ (xsd_name), has_cxx_name_ (false) + { + } + + Namespace (Pattern const& xsd_name, String const& cxx_name) + : xsd_name_ (xsd_name), has_cxx_name_ (true), cxx_name_ (cxx_name) + { + } + + Namespace (Pattern const& xsd_name, + bool has_cxx_name, + String const& cxx_name) + : xsd_name_ (xsd_name), + has_cxx_name_ (has_cxx_name), + cxx_name_ (cxx_name) + { + } + + // + // + typedef std::vector Includes; + typedef Includes::const_iterator IncludesIterator; + + IncludesIterator + includes_begin () const + { + return includes_.begin (); + } + + IncludesIterator + includes_end () const + { + return includes_.end (); + } + + void + includes_push_back (String const& i) + { + includes_.push_back (i); + } + + // + // + typedef std::vector Types; + typedef Types::const_iterator TypesIterator; + + TypesIterator + types_begin () const + { + return types_.begin (); + } + + TypesIterator + types_end () const + { + return types_.end (); + } + + void + types_push_back (String const& xsd_type, + String const& cxx_ret_type, + String const& cxx_arg_type = L"") + { + types_.push_back (Type (xsd_type, cxx_ret_type, cxx_arg_type)); + } + + void + types_push_back (Pattern const& xsd_type, + String const& cxx_ret_type, + String const& cxx_arg_type = L"") + { + types_.push_back (Type (xsd_type, cxx_ret_type, cxx_arg_type)); + } + + // + // + Pattern const& + xsd_name () const + { + return xsd_name_; + } + + // + // + bool + has_cxx_name () const + { + return has_cxx_name_; + } + + String const& + cxx_name () const + { + return cxx_name_; + } + + private: + Includes includes_; + Types types_; + Pattern xsd_name_; + bool has_cxx_name_; + String cxx_name_; + }; + + typedef std::vector Namespaces; +} + +#endif // XSD_XSD_TYPE_MAP_TYPE_MAP_HXX -- cgit v1.1