From cf469aa28804418338c79a5f9c68608ea2f2807a Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 19 Jun 2015 17:24:11 +0200 Subject: Parse C++ type mapping --- odb/pragma.cxx | 150 ++++++++++++++++++++++++++++++++------------- odb/relational/context.hxx | 20 ++++++ 2 files changed, 126 insertions(+), 44 deletions(-) diff --git a/odb/pragma.cxx b/odb/pragma.cxx index fec7014..01c31d2 100644 --- a/odb/pragma.cxx +++ b/odb/pragma.cxx @@ -842,10 +842,10 @@ handle_pragma (cxx_lexer& l, } else if (qualifier == "map") { - // type("") - // as("") - // to("") - // from("") + // type("") | type() + // as("") | as() + // to("") | to() + // from("") | from() // if (p != "type" && @@ -857,12 +857,9 @@ handle_pragma (cxx_lexer& l, return; } - using relational::custom_db_type; - // Make sure we've got the correct declaration type. // assert (decl == global_namespace); - custom_db_type& ct (qualifier_value.value ()); if (l.next (tl, &tn) != CPP_OPEN_PAREN) { @@ -872,59 +869,119 @@ handle_pragma (cxx_lexer& l, tt = l.next (tl, &tn); - if (p == "type") + using relational::custom_db_type; + using relational::custom_cxx_type; + + if (qualifier_value.type_info () == typeid (custom_db_type)) { - if (tt != CPP_STRING) + // Database type mapping. + // + custom_db_type& ct (qualifier_value.value ()); + + if (p == "type") { - error (l) << "type name regex expected in db pragma " << p << endl; - return; - } + if (tt != CPP_STRING) + { + error (l) << "type name regex expected in db pragma " << p << endl; + return; + } - try + try + { + // Make it case-insensitive. + // + ct.type.assign (tl, true); + } + catch (regex_format const& e) + { + error (l) << "invalid regex: '" << e.regex () << "' in db pragma " + << p << ": " << e.description () << endl; + return; + } + } + else if (p == "as") { - // Make it case-insensitive. - // - ct.type.assign (tl, true); + if (tt != CPP_STRING) + { + error (l) << "type name expected in db pragma " << p << endl; + return; + } + + ct.as = tl; } - catch (regex_format const& e) + else if (p == "to") { - error (l) << "invalid regex: '" << e.regex () << "' in db pragma " - << p << ": " << e.description () << endl; - return; + if (tt != CPP_STRING) + { + error (l) << "expression expected in db pragma " << p << endl; + return; + } + + ct.to = tl; } - } - else if (p == "as") - { - if (tt != CPP_STRING) + else if (p == "from") { - error (l) << "type name expected in db pragma " << p << endl; - return; + if (tt != CPP_STRING) + { + error (l) << "expression expected in db pragma " << p << endl; + return; + } + + ct.from = tl; } - ct.as = tl; + tt = l.next (tl, &tn); } - else if (p == "to") + else { - if (tt != CPP_STRING) + // C++ type mapping. + // + custom_cxx_type& ct (qualifier_value.value ()); + + if (p == "type" || p == "as") { - error (l) << "expression expected in db pragma " << p << endl; - return; - } + // Can be built-in type (e.g., bool). + // + if (tt == CPP_NAME || tt == CPP_KEYWORD || tt == CPP_SCOPE) + { + string name; + tree type ( + resolve_scoped_name ( + l, tt, tl, tn, current_scope (), name, true, p)); - ct.to = tl; - } - else if (p == "from") - { - if (tt != CPP_STRING) + if (type == 0) + return; // Diagnostics has already been issued. + + if (TREE_CODE (type) != TYPE_DECL) + { + error (loc) << "name '" << name << "' in db pragma " + << p << " does not refer to a type" << endl; + return; + } + + type = TREE_TYPE (type); + + (p == "type" ? ct.type_node : ct.as_node) = type; + (p == "type" ? ct.type_name : ct.as_name) = name; + } + else + { + error (l) << "type name expected in db pragma " << p << endl; + return; + } + } + else if (p == "to" || p == "from") { - error (l) << "expression expected in db pragma " << p << endl; - return; + if (tt != CPP_CLOSE_PAREN) // Empty expression is ok. + { + if (!parse_expression ( + l, tt, tl, tn, (p == "to" ? ct.to : ct.from), p)) + return; // Diagnostics has already been issued. + } } - - ct.from = tl; } - if (l.next (tl, &tn) != CPP_CLOSE_PAREN) + if (tt != CPP_CLOSE_PAREN) { error (l) << "')' expected at the end of db pragma " << p << endl; return; @@ -3061,8 +3118,13 @@ handle_pragma_qualifier (cxx_lexer& l, string p) } else { - error (loc) << "custom C++ type!" << endl; - return; + using relational::custom_cxx_type; + + custom_cxx_type ct; + ct.loc = loc; + val = ct; + name = "custom-cxx-types"; + adder = &accumulate; } } else if (p == "index") diff --git a/odb/relational/context.hxx b/odb/relational/context.hxx index 45dbba6..956f6c4 100644 --- a/odb/relational/context.hxx +++ b/odb/relational/context.hxx @@ -71,6 +71,26 @@ namespace relational typedef std::vector custom_db_types; + // Custom C++ type mapping. + // + struct custom_cxx_type + { + tree type_node; + std::string type_name; + + tree as_node; + std::string as_name; + + // Empty expression means the values are implicitly convertible. + // + cxx_tokens to; + cxx_tokens from; + + location_t loc; + }; + + typedef std::vector custom_cxx_types; + class context: public virtual ::context { public: -- cgit v1.1