From f0510d2f90467de8e8f260b47d79a9baaf9bef17 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 17 Sep 2009 07:15:29 +0200 Subject: Start tracking XSD with git --- xsd/type-map/lexer.cxx | 133 ++++++++++++++++++++++ xsd/type-map/lexer.hxx | 80 +++++++++++++ xsd/type-map/parser.cxx | 281 ++++++++++++++++++++++++++++++++++++++++++++++ xsd/type-map/parser.hxx | 46 ++++++++ xsd/type-map/type-map.hxx | 160 ++++++++++++++++++++++++++ 5 files changed, 700 insertions(+) create mode 100644 xsd/type-map/lexer.cxx create mode 100644 xsd/type-map/lexer.hxx create mode 100644 xsd/type-map/parser.cxx create mode 100644 xsd/type-map/parser.hxx create mode 100644 xsd/type-map/type-map.hxx (limited to 'xsd/type-map') diff --git a/xsd/type-map/lexer.cxx b/xsd/type-map/lexer.cxx new file mode 100644 index 0000000..4376730 --- /dev/null +++ b/xsd/type-map/lexer.cxx @@ -0,0 +1,133 @@ +// file : xsd/type-map/lexer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2007-2009 Code Synthesis Tools CC +// 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_); + + Boolean 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/type-map/lexer.hxx b/xsd/type-map/lexer.hxx new file mode 100644 index 0000000..2969e5d --- /dev/null +++ b/xsd/type-map/lexer.hxx @@ -0,0 +1,80 @@ +// file : xsd/type-map/lexer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2007-2009 Code Synthesis Tools CC +// 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 +{ + using namespace Cult::Types; + typedef WideString String; + + class Lexer + { + public: + class Token + { + public: + enum Type + { + token, + punct, + eos + }; + + Token (Type type, String const& lexeme, UnsignedLong line) + : type_ (type), lexeme_ (lexeme), line_ (line) + { + } + + Type + type () const + { + return type_; + } + + String const& + lexeme () const + { + return lexeme_; + } + + UnsignedLong + line () const + { + return line_; + } + + private: + Type type_; + String lexeme_; + UnsignedLong line_; + }; + + Lexer (std::istream&, String const& path); + + struct Failed {}; + + Token + next (); + + private: + std::locale locale_; + std::istream& is_; + String path_; + UnsignedLong line_; + String held_lexeme_; + Boolean comment_; + }; + +} + +#endif // XSD_TYPE_MAP_LEXER_HXX + diff --git a/xsd/type-map/parser.cxx b/xsd/type-map/parser.cxx new file mode 100644 index 0000000..9bf1576 --- /dev/null +++ b/xsd/type-map/parser.cxx @@ -0,0 +1,281 @@ +// file : xsd/type-map/parser.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2007-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include + +using std::endl; + +namespace TypeMap +{ + typedef Lexer::Token Token; + typedef BackendElements::Regex::Format Format; + + Parser::Parser (Lexer& lex, String const& path) + : lex_ (lex), path_ (path), e (std::wcerr) + { + } + + Boolean 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; + } + + Boolean 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 () << 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 (); + + Boolean 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; + } + + Boolean 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; + } + + Boolean 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 () << 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/type-map/parser.hxx b/xsd/type-map/parser.hxx new file mode 100644 index 0000000..514ad86 --- /dev/null +++ b/xsd/type-map/parser.hxx @@ -0,0 +1,46 @@ +// file : xsd/type-map/parser.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2007-2009 Code Synthesis Tools CC +// 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 +{ + using namespace Cult::Types; + typedef WideString String; + + class Parser + { + public: + Parser (Lexer&, String const& path); + + // Merge parsed namespaces. + // + Boolean + parse (Namespaces&); + + private: + Boolean + namespace_ (Namespaces&); + + Boolean + include (Namespace&); + + Boolean + type (Lexer::Token, Namespace&); + + private: + Lexer& lex_; + String path_; + std::wostream& e; + }; +} + +#endif // XSD_TYPE_MAP_PARSER_HXX diff --git a/xsd/type-map/type-map.hxx b/xsd/type-map/type-map.hxx new file mode 100644 index 0000000..b9b0d5c --- /dev/null +++ b/xsd/type-map/type-map.hxx @@ -0,0 +1,160 @@ +// file : xsd/type-map/type-map.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2007-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_TYPE_MAP_TYPE_MAP_HXX +#define XSD_TYPE_MAP_TYPE_MAP_HXX + +#include +#include + +#include + +namespace TypeMap +{ + using namespace Cult::Types; + typedef WideString String; + typedef BackendElements::Regex::Pattern Pattern; + + class Type + { + public: + 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 (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, + Boolean has_cxx_name, + String const& cxx_name) + : xsd_name_ (xsd_name), + has_cxx_name_ (has_cxx_name), + cxx_name_ (cxx_name) + { + } + + // + // + typedef Cult::Containers::Vector Includes; + typedef Includes::ConstIterator 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 Cult::Containers::Vector Types; + typedef Types::ConstIterator TypesIterator; + + TypesIterator + types_begin () const + { + return types_.begin (); + } + + TypesIterator + types_end () const + { + return types_.end (); + } + + 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_; + } + + // + // + Boolean + has_cxx_name () const + { + return has_cxx_name_; + } + + String const& + cxx_name () const + { + return cxx_name_; + } + + private: + Includes includes_; + Types types_; + Pattern xsd_name_; + Boolean has_cxx_name_; + String cxx_name_; + }; + + typedef Cult::Containers::Vector Namespaces; +} + +#endif // XSD_TYPE_MAP_TYPE_MAP_HXX + -- cgit v1.1