[Libreoffice-commits] core.git: 2 commits - codemaker/source include/codemaker include/unoidl unodevtools/source unoidl/Library_unoidl.mk unoidl/source

Stephan Bergmann sbergman at redhat.com
Thu Sep 12 08:45:39 PDT 2013


 codemaker/source/codemaker/typemanager.cxx         |    8 
 codemaker/source/cppumaker/cppumaker.cxx           |    6 
 codemaker/source/cppumaker/cppuoptions.cxx         |   25 
 codemaker/source/javamaker/javamaker.cxx           |    4 
 include/codemaker/typemanager.hxx                  |    2 
 include/unoidl/sourceprovider.hxx                  |   48 
 unodevtools/source/skeletonmaker/skeletonmaker.cxx |    2 
 unoidl/Library_unoidl.mk                           |   14 
 unoidl/source/sourceprovider-parser-requires.hxx   |  136 
 unoidl/source/sourceprovider-parser.y              | 3631 +++++++++++++++++++++
 unoidl/source/sourceprovider-scanner.hxx           |  247 +
 unoidl/source/sourceprovider-scanner.l             |  253 +
 unoidl/source/sourceprovider.cxx                   |  206 +
 13 files changed, 4572 insertions(+), 10 deletions(-)

New commits:
commit c4113906d7f15f8aa0eb385a4caf474b3505ede1
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Thu Sep 12 17:44:55 2013 +0200

    WIP: add cppumaker -U to directly read from .idl files
    
    Change-Id: I420847515b6b691ae81a249a8820cf9a3d132372

diff --git a/codemaker/source/codemaker/typemanager.cxx b/codemaker/source/codemaker/typemanager.cxx
index ff0e6f9..13da4d3 100644
--- a/codemaker/source/codemaker/typemanager.cxx
+++ b/codemaker/source/codemaker/typemanager.cxx
@@ -27,15 +27,19 @@
 #include "codemaker/typemanager.hxx"
 #include "rtl/ref.hxx"
 #include "rtl/ustring.hxx"
+#include "unoidl/sourceprovider.hxx"
 #include "unoidl/unoidl.hxx"
 
 TypeManager::TypeManager(): manager_(new unoidl::Manager) {}
 
 TypeManager::~TypeManager() {}
 
-void TypeManager::loadProvider(OUString const & uri, bool primary) {
+void TypeManager::loadProvider(OUString const & uri, bool source, bool primary)
+{
     rtl::Reference< unoidl::Provider > prov(
-        unoidl::loadProvider(manager_, uri));
+        source
+        ? new unoidl::SourceProvider(manager_, uri)
+        : unoidl::loadProvider(manager_, uri));
     manager_->addProvider(prov);
     if (primary) {
         primaryProviders_.push_back(prov);
diff --git a/codemaker/source/cppumaker/cppumaker.cxx b/codemaker/source/cppumaker/cppumaker.cxx
index 2a698f4..733eb85 100644
--- a/codemaker/source/cppumaker/cppumaker.cxx
+++ b/codemaker/source/cppumaker/cppumaker.cxx
@@ -52,13 +52,15 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
                  options.getExtraInputFiles().begin());
              i != options.getExtraInputFiles().end(); ++i)
         {
-            typeMgr->loadProvider(convertToFileUrl(*i), false);
+            typeMgr->loadProvider(
+                convertToFileUrl(*i), options.isValid("-U"), false);
         }
         for (std::vector< OString >::const_iterator i(
                  options.getInputFiles().begin());
              i != options.getInputFiles().end(); ++i)
         {
-            typeMgr->loadProvider(convertToFileUrl(*i), true);
+            typeMgr->loadProvider(
+                convertToFileUrl(*i), options.isValid("-U"), true);
         }
         codemaker::GeneratedTypeSet generated;
         if (options.isValid("-T")) {
diff --git a/codemaker/source/cppumaker/cppuoptions.cxx b/codemaker/source/cppumaker/cppuoptions.cxx
index 3e70b68..3643954 100644
--- a/codemaker/source/cppumaker/cppuoptions.cxx
+++ b/codemaker/source/cppumaker/cppuoptions.cxx
@@ -139,6 +139,19 @@ sal_Bool CppuOptions::initOptions(int ac, char* av[], sal_Bool bCmdFile)
                         m_options["-T"] = OString(s);
                     }
                     break;
+                case 'U':
+                    if (av[i][2] != '\0')
+                    {
+                        OString tmp("'-U', please check");
+                        if (i <= ac - 1)
+                        {
+                            tmp += " your input '" + OString(av[i]) + "'";
+                        }
+
+                        throw IllegalArgument(tmp);
+                    }
+                    m_options["-U"] = "";
+                    break;
                 case 'L':
                     if (av[i][2] != '\0')
                     {
@@ -321,9 +334,17 @@ OString CppuOptions::prepareHelp()
     help += "    -O<path>   = path describes the root directory for the generated output.\n";
     help += "                 The output directory tree is generated under this directory.\n";
     help += "    -T<name>   = name specifies a type or a list of types. The output for this\n";
-    help += "      [t1;...]   type is generated. If no '-T' option is specified,\n";
-    help += "                 then output for all types is generated.\n";
+    help += "      [t1;...]   type and all dependent types are generated. If no '-T' option is\n";
+    help += "                 specified, then output for all types is generated.\n";
     help += "                 Example: 'com.sun.star.uno.XInterface' is a valid type.\n";
+    help += "    -U         = instead of interpreting file_1 ... file_n as type rdb files,\n";
+    help += "                 interpret them as (directories of) UNOIDL source files.  If no\n";
+    help += "                 '-T' option is given, each file_i must denote a UNOIDL file, and\n";
+    help += "                 headers are generated for all entities defined in those files.";
+    help += "                 Otherwise, each file_i must denote a directory, and an entity\n";
+    help += "                 com.sun.star.uno.XInterface specified with '-T' would be searched\n";
+    help += "                 for as com/sun/star/uno/XInterface.idl under each of those\n";
+    help += "                 directories in turn.";
     help += "    -L         = UNO type functions are generated lightweight, that means only\n";
     help += "                 the name and typeclass are given and everything else is retrieved\n";
     help += "                 from the type library dynamically. The default is that UNO type\n";
diff --git a/codemaker/source/javamaker/javamaker.cxx b/codemaker/source/javamaker/javamaker.cxx
index d74aafa..4f5730c 100644
--- a/codemaker/source/javamaker/javamaker.cxx
+++ b/codemaker/source/javamaker/javamaker.cxx
@@ -52,13 +52,13 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
                  options.getExtraInputFiles().begin());
              i != options.getExtraInputFiles().end(); ++i)
         {
-            typeMgr->loadProvider(convertToFileUrl(*i), false);
+            typeMgr->loadProvider(convertToFileUrl(*i), false, false);
         }
         for (std::vector< rtl::OString >::const_iterator i(
                  options.getInputFiles().begin());
              i != options.getInputFiles().end(); ++i)
         {
-            typeMgr->loadProvider(convertToFileUrl(*i), true);
+            typeMgr->loadProvider(convertToFileUrl(*i), false, true);
         }
         codemaker::GeneratedTypeSet generated;
         if (options.isValid("-T")) {
diff --git a/include/codemaker/typemanager.hxx b/include/codemaker/typemanager.hxx
index fc6aba6..a268b11 100644
--- a/include/codemaker/typemanager.hxx
+++ b/include/codemaker/typemanager.hxx
@@ -42,7 +42,7 @@ class TypeManager: public salhelper::SimpleReferenceObject {
 public:
     TypeManager();
 
-    void loadProvider(OUString const & uri, bool primary);
+    void loadProvider(OUString const & uri, bool source, bool primary);
 
     bool foundAtPrimaryProvider(OUString const & name) const;
 
diff --git a/unodevtools/source/skeletonmaker/skeletonmaker.cxx b/unodevtools/source/skeletonmaker/skeletonmaker.cxx
index b2d5461..f884f88 100644
--- a/unodevtools/source/skeletonmaker/skeletonmaker.cxx
+++ b/unodevtools/source/skeletonmaker/skeletonmaker.cxx
@@ -268,7 +268,7 @@ SAL_IMPLEMENT_MAIN()
     for (std::vector< OString >::const_iterator i(registries.begin());
          i != registries.end(); ++i)
     {
-        manager->loadProvider(convertToFileUrl(*i), true);
+        manager->loadProvider(convertToFileUrl(*i), false, true);
     }
 
     if ( options.dump ) {
commit 5c2ba4aad61ce2c7c661202ae7ed26e1859c5216
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Thu Sep 12 17:39:48 2013 +0200

    WIP: additional unoidl::Provider that directly reads from .idl files
    
    Change-Id: I30fa6400724f4ca6f0e1986c741500f05710b840

diff --git a/include/unoidl/sourceprovider.hxx b/include/unoidl/sourceprovider.hxx
new file mode 100644
index 0000000..e596711
--- /dev/null
+++ b/include/unoidl/sourceprovider.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_UNOIDL_SOURCEPROVIDER_HXX
+#define INCLUDED_UNOIDL_SOURCEPROVIDER_HXX
+
+#include "sal/config.h"
+
+#include <map>
+
+#include "rtl/ref.hxx"
+#include "sal/types.h"
+#include "unoidl/detail/dllapi.hxx"
+#include "unoidl/unoidl.hxx"
+
+namespace unoidl {
+
+class LO_DLLPUBLIC_UNOIDL SourceProvider: public Provider {
+public:
+    // throws FileFormatException, NoSuchFileException:
+    SourceProvider(
+        rtl::Reference<Manager> const & manager, OUString const & uri);
+
+    // throws FileFormatException:
+    virtual rtl::Reference<MapCursor> createRootCursor() const;
+
+    // throws FileFormatException:
+    virtual rtl::Reference<Entity> findEntity(OUString const & name) const;
+
+private:
+    virtual SAL_DLLPRIVATE ~SourceProvider() throw ();
+
+    rtl::Reference<Manager> manager_;
+    OUString uri_;
+    mutable std::map< OUString, rtl::Reference<Entity> > cache_; //TODO: at manager
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/unoidl/Library_unoidl.mk b/unoidl/Library_unoidl.mk
index 46534c7..5cffa49 100644
--- a/unoidl/Library_unoidl.mk
+++ b/unoidl/Library_unoidl.mk
@@ -13,10 +13,24 @@ $(eval $(call gb_Library_add_defs,unoidl,-DLO_DLLIMPLEMENTATION_UNOIDL))
 
 $(eval $(call gb_Library_add_exception_objects,unoidl, \
     unoidl/source/legacyprovider \
+    unoidl/source/sourceprovider \
     unoidl/source/unoidl \
     unoidl/source/unoidlprovider \
 ))
 
+$(eval $(call gb_Library_add_grammars,unoidl, \
+    unoidl/source/sourceprovider-parser \
+))
+
+$(eval $(call gb_Library_add_scanners,unoidl, \
+    unoidl/source/sourceprovider-scanner \
+))
+
+$(eval $(call gb_Library_set_include,unoidl, \
+    $$(INCLUDE) \
+    -I$(SRCDIR)/unoidl/source \
+))
+
 $(eval $(call gb_Library_use_libraries,unoidl, \
     reg \
     sal \
diff --git a/unoidl/source/sourceprovider-parser-requires.hxx b/unoidl/source/sourceprovider-parser-requires.hxx
new file mode 100644
index 0000000..0c52b3d
--- /dev/null
+++ b/unoidl/source/sourceprovider-parser-requires.hxx
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_UNOIDL_SOURCE_SOURCEPROVIDER_PARSER_REQUIRES_HXX
+#define INCLUDED_UNOIDL_SOURCE_SOURCEPROVIDER_PARSER_REQUIRES_HXX
+
+#include "sal/config.h"
+
+#include <vector>
+
+#include "rtl/string.hxx"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "unoidl/unoidl.hxx"
+
+#define YYLTYPE int
+
+typedef void * yyscan_t;
+
+int yyparse(yyscan_t yyscanner);
+
+namespace unoidl { namespace detail {
+
+struct SourceProviderEntity;
+
+enum SourceProviderAccessDecls { ACCESS_DECL_GET = 0x1, ACCESS_DECL_SET = 0x2 };
+
+enum SourceProviderFlags {
+    FLAG_ATTRIBUTE = 0x001, FLAG_BOUND = 0x002, FLAG_CONSTRAINED = 0x004,
+    FLAG_MAYBEAMBIGUOUS = 0x008, FLAG_MAYBEDEFAULT = 0x010,
+    FLAG_MAYBEVOID = 0x020, FLAG_OPTIONAL = 0x040, FLAG_PROPERTY = 0x080,
+    FLAG_READONLY = 0x100, FLAG_REMOVABLE = 0x200, FLAG_TRANSIENT = 0x400
+};
+
+struct SourceProviderExpr {
+    static SourceProviderExpr Bool(bool v) {
+        SourceProviderExpr e;
+        e.type = TYPE_BOOL;
+        e.bval = v;
+        return e;
+    }
+
+    static SourceProviderExpr Int(sal_Int64 v) {
+        SourceProviderExpr e;
+        e.type = TYPE_INT;
+        e.ival = v;
+        return e;
+    }
+
+    static SourceProviderExpr Uint(sal_uInt64 v) {
+        SourceProviderExpr e;
+        e.type = TYPE_UINT;
+        e.uval = v;
+        return e;
+    }
+
+    static SourceProviderExpr Float(double v) {
+        SourceProviderExpr e;
+        e.type = TYPE_FLOAT;
+        e.fval = v;
+        return e;
+    }
+
+    enum Type { TYPE_BOOL, TYPE_INT, TYPE_UINT, TYPE_FLOAT };
+
+    Type type;
+    union {
+        bool bval;
+        sal_Int64 ival;
+        sal_uInt64 uval;
+        double fval;
+    };
+};
+
+struct SourceProviderType {
+    enum Type {
+        TYPE_VOID, TYPE_BOOLEAN, TYPE_BYTE, TYPE_SHORT, TYPE_UNSIGNED_SHORT,
+        TYPE_LONG, TYPE_UNSIGNED_LONG, TYPE_HYPER, TYPE_UNSIGNED_HYPER,
+        TYPE_FLOAT, TYPE_DOUBLE, TYPE_CHAR, TYPE_STRING, TYPE_TYPE, TYPE_ANY,
+        TYPE_SEQUENCE, TYPE_ENUM, TYPE_PLAIN_STRUCT, TYPE_EXCEPTION,
+        TYPE_INTERFACE, TYPE_INSTANTIATED_POLYMORPHIC_STRUCT, TYPE_PARAMETER
+    };
+
+    SourceProviderType() {}
+
+    explicit SourceProviderType(Type theType): type(theType)
+    { assert(theType <= TYPE_ANY); }
+
+    explicit SourceProviderType(SourceProviderType const * componentType):
+        type(TYPE_SEQUENCE)
+    { assert(componentType != 0); subtypes.push_back(*componentType); }
+
+    SourceProviderType(
+        Type theType, OUString const & theName,
+        SourceProviderEntity const * theEntity):
+        type(theType), name(theName), entity(theEntity)
+    {
+        assert(theType >= TYPE_ENUM && theType <= TYPE_INTERFACE);
+        assert(theEntity != 0);
+    }
+
+    SourceProviderType(
+        OUString const & polymorphicStructTypeTemplateName,
+        SourceProviderEntity const * theEntity,
+        std::vector<SourceProviderType> const & typeArguments):
+        type(TYPE_INSTANTIATED_POLYMORPHIC_STRUCT),
+        name(polymorphicStructTypeTemplateName), entity(theEntity),
+        subtypes(typeArguments)
+    { assert(theEntity != 0); }
+
+    explicit SourceProviderType(OUString const & identifier):
+        type(TYPE_PARAMETER), name(identifier)
+    {}
+
+    OUString getName() const;
+
+    Type type;
+    OUString name; // TYPE_ENUM ... TYPE_PARAMETER
+    SourceProviderEntity const * entity;
+        // TYPE_ENUM ... TYPE_INSTANTIATED_POLYMOPRHIC_STRUCT
+    std::vector<SourceProviderType> subtypes;
+        // TYPE_SEQUENCE, TYPE_INSTANTIATED_POLYMOPRHIC_STRUCT
+    OUString typedefName;
+};
+
+} }
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/unoidl/source/sourceprovider-parser.y b/unoidl/source/sourceprovider-parser.y
new file mode 100644
index 0000000..6029151
--- /dev/null
+++ b/unoidl/source/sourceprovider-parser.y
@@ -0,0 +1,3631 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/*TODO: @deprecated annotations */
+/*TODO: check Exception, RuntimeException, XInterface defns */
+
+%locations
+%pure-parser
+
+%{
+
+#include "sal/config.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdlib>
+#include <limits>
+#include <utility>
+
+#include <sourceprovider-parser-requires.hxx>
+
+%}
+
+%union {
+    sal_uInt64 ival;
+    double fval;
+    OString * sval;
+
+    bool bval;
+    std::vector<OUString> * excns;
+    unoidl::detail::SourceProviderAccessDecls decls;
+    unoidl::InterfaceTypeEntity::Method::Parameter::Direction dir;
+    unoidl::detail::SourceProviderFlags flags;
+    unoidl::detail::SourceProviderExpr expr;
+    unoidl::detail::SourceProviderType * type;
+    std::vector<unoidl::detail::SourceProviderType> * types;
+}
+
+/* TODO: %destructor { delete $$; } <sval> <excns> <type> <types> */
+
+%lex-param {yyscan_t yyscanner}
+%parse-param {yyscan_t yyscanner}
+
+%{
+
+#include "sourceprovider-scanner.hxx"
+
+#define YYLLOC_DEFAULT(Current, Rhs, N) \
+    do { (Current) = YYRHSLOC((Rhs), YYID((N)) ? 1 : 0); } while (YYID(0))
+
+void yyerror(YYLTYPE * locp, yyscan_t yyscanner, char const * msg) {
+    assert(locp != 0);
+    unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+    data->errorLine = *locp;
+    data->parserError = OString(msg);
+}
+
+namespace {
+
+void error(YYLTYPE location, yyscan_t yyscanner, OUString const & message) {
+    unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+    data->errorLine = location;
+    data->errorMessage = message;
+}
+
+OUString flagName(unoidl::detail::SourceProviderFlags flag) {
+    switch (flag) {
+    case unoidl::detail::FLAG_ATTRIBUTE:
+        return OUString("attribute");
+    case unoidl::detail::FLAG_BOUND:
+        return OUString("bound");
+    case unoidl::detail::FLAG_CONSTRAINED:
+        return OUString("constrained");
+    case unoidl::detail::FLAG_MAYBEAMBIGUOUS:
+        return OUString("maybeambiguous");
+    case unoidl::detail::FLAG_MAYBEDEFAULT:
+        return OUString("maybedefault");
+    case unoidl::detail::FLAG_MAYBEVOID:
+        return OUString("maybevoid");
+    case unoidl::detail::FLAG_OPTIONAL:
+        return OUString("optional");
+    case unoidl::detail::FLAG_PROPERTY:
+        return OUString("property");
+    case unoidl::detail::FLAG_READONLY:
+        return OUString("readonly");
+    case unoidl::detail::FLAG_REMOVABLE:
+        return OUString("removable");
+    case unoidl::detail::FLAG_TRANSIENT:
+        return OUString("transient");
+    default:
+        assert(false); for (;;) { std::abort(); } // this cannot happen
+    }
+}
+
+OUString convertName(OString const * name) {
+    assert(name != 0);
+    OUString s(OStringToOUString(*name, RTL_TEXTENCODING_ASCII_US));
+    delete name;
+    return s;
+}
+
+OUString convertToFullName(
+    unoidl::detail::SourceProviderScannerData const * data,
+    OString const * identifier)
+{
+    assert(data != 0);
+    OUString pref;
+    if (!data->modules.empty()) {
+        pref = data->modules.back() + ".";
+    }
+    return pref + convertName(identifier);
+}
+
+void convertToCurrentName(
+    unoidl::detail::SourceProviderScannerData * data,
+    OString const * identifier)
+{
+    assert(data != 0);
+    assert(data->currentName.isEmpty());
+    data->currentName = convertToFullName(data, identifier);
+    assert(!data->currentName.isEmpty());
+}
+
+void clearCurrentName(unoidl::detail::SourceProviderScannerData * data) {
+    assert(data != 0);
+    assert(!data->currentName.isEmpty());
+    data->currentName = "";
+}
+
+unoidl::detail::SourceProviderEntity * getCurrentEntity(
+    unoidl::detail::SourceProviderScannerData * data)
+{
+    assert(data != 0);
+    assert(!data->currentName.isEmpty());
+    std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator i(
+        data->entities.find(data->currentName));
+    assert(i != data->entities.end());
+    assert(i->second.kind == unoidl::detail::SourceProviderEntity::KIND_LOCAL);
+    assert(i->second.pad.is());
+    return &i->second;
+}
+
+template<typename T> rtl::Reference<T> getCurrentPad(
+    unoidl::detail::SourceProviderScannerData * data)
+{
+    rtl::Reference<T> pad(dynamic_cast<T *>(getCurrentEntity(data)->pad.get()));
+    assert(pad.is());
+    return pad;
+}
+
+bool nameHasSameIdentifierAs(OUString const & name, OUString const & identifier)
+{
+    sal_Int32 i = name.lastIndexOf('.') + 1;
+    return identifier.getLength() == name.getLength() - i
+        && name.match(identifier, i);
+}
+
+bool coerce(
+    YYLTYPE location, yyscan_t yyscanner,
+    unoidl::detail::SourceProviderExpr * lhs,
+    unoidl::detail::SourceProviderExpr * rhs)
+{
+    assert(lhs != 0);
+    assert(rhs != 0);
+    bool ok;
+    switch (lhs->type) {
+    case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
+        ok = rhs->type != unoidl::detail::SourceProviderExpr::TYPE_BOOL;
+        break;
+    case unoidl::detail::SourceProviderExpr::TYPE_INT:
+        switch (rhs->type) {
+        case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
+            ok = false;
+            break;
+        case unoidl::detail::SourceProviderExpr::TYPE_INT:
+            ok = true;
+            break;
+        case unoidl::detail::SourceProviderExpr::TYPE_UINT:
+            if (lhs->ival >= 0) {
+                lhs->type = unoidl::detail::SourceProviderExpr::TYPE_UINT;
+                ok = true;
+            } else if (rhs->uval <= SAL_MAX_INT64) {
+                rhs->type = unoidl::detail::SourceProviderExpr::TYPE_INT;
+                ok = true;
+            } else {
+                ok = false;
+            }
+            break;
+        case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
+            lhs->fval = lhs->ival;
+            ok = true;
+            break;
+        }
+        break;
+    case unoidl::detail::SourceProviderExpr::TYPE_UINT:
+        switch (rhs->type) {
+        case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
+            ok = false;
+            break;
+        case unoidl::detail::SourceProviderExpr::TYPE_INT:
+            if (rhs->ival >= 0) {
+                rhs->type = unoidl::detail::SourceProviderExpr::TYPE_UINT;
+                ok = true;
+            } else if (lhs->uval <= SAL_MAX_INT64) {
+                lhs->type = unoidl::detail::SourceProviderExpr::TYPE_INT;
+                ok = true;
+            } else {
+                ok = false;
+            }
+            break;
+        case unoidl::detail::SourceProviderExpr::TYPE_UINT:
+            ok = true;
+            break;
+        case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
+            lhs->fval = lhs->uval;
+            ok = true;
+            break;
+        }
+        break;
+    case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
+        switch (rhs->type) {
+        case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
+            ok = false;
+            break;
+        case unoidl::detail::SourceProviderExpr::TYPE_INT:
+            rhs->fval = rhs->ival;
+            ok = true;
+            break;
+        case unoidl::detail::SourceProviderExpr::TYPE_UINT:
+            rhs->fval = rhs->uval;
+            ok = true;
+            break;
+        case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
+            ok = true;
+            break;
+        }
+        break;
+    }
+    if (!ok) {
+        error(location, yyscanner, "cannot coerce binary expression arguments");
+    }
+    return ok;
+}
+
+unoidl::detail::SourceProviderEntity * findEntity_(
+    unoidl::detail::SourceProviderScannerData * data, OUString * name)
+{
+    assert(data != 0);
+    assert(name != 0);
+    OUString n;
+    if (name->startsWith(".")) {
+        n = name->copy(1);
+    } else {
+        for (std::vector<OUString>::const_reverse_iterator i(data->modules.rbegin());
+             i != data->modules.rend(); ++i)
+        {
+            n = *i + "." + *name;
+            std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator j(
+                data->entities.find(n));
+            if (j != data->entities.end()) {
+                *name = n;
+                return &j->second;
+            }
+            rtl::Reference<unoidl::Entity> ent(data->manager->findEntity(n));
+            if (ent.is()) {
+                std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator
+                    k(data->entities.insert(
+                          std::map<OUString, unoidl::detail::SourceProviderEntity>::value_type(
+                              n,
+                              unoidl::detail::SourceProviderEntity(
+                                  unoidl::detail::SourceProviderEntity::KIND_EXTERNAL,
+                                  ent))).
+                      first);
+                *name = n;
+                return &k->second;
+            }
+        }
+        n = *name;
+    }
+    std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator i(
+        data->entities.find(n));
+    if (i != data->entities.end()) {
+        *name = n;
+        return &i->second;
+    }
+    rtl::Reference<unoidl::Entity> ent(data->manager->findEntity(n));
+    if (ent.is()) {
+        std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator
+            j(data->entities.insert(
+                  std::map<OUString, unoidl::detail::SourceProviderEntity>::value_type(
+                      n,
+                      unoidl::detail::SourceProviderEntity(
+                          unoidl::detail::SourceProviderEntity::KIND_EXTERNAL,
+                          ent))).
+              first);
+        *name = n;
+        return &j->second;
+    }
+    return 0;
+}
+
+enum Found { FOUND_ERROR, FOUND_TYPE, FOUND_ENTITY };
+
+Found findEntity(
+    YYLTYPE location, yyscan_t yyscanner,
+    unoidl::detail::SourceProviderScannerData * data,
+    bool resolveInterfaceDefinitions, OUString * name,
+    unoidl::detail::SourceProviderEntity const ** entity,
+    unoidl::detail::SourceProviderType * typedefedType)
+{
+    //TODO: avoid recursion
+    assert(data != 0);
+    assert(name != 0);
+    assert(entity != 0);
+    unoidl::detail::SourceProviderEntity * e = findEntity_(data, name);
+    OUString n(*name);
+    OUString typeNucleus;
+    std::size_t rank = 0;
+    std::vector<unoidl::detail::SourceProviderType> args;
+    for (;;) {
+        if (e != 0) {
+            switch (e->kind) {
+            case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
+                if (e->pad.is()) {
+                    break;
+                }
+                assert(e->entity.is());
+                // fall through
+            case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
+                if (e->entity->getSort() == unoidl::Entity::SORT_TYPEDEF) {
+                    OUString t(
+                        static_cast<unoidl::TypedefEntity *>(e->entity.get())
+                        ->getType());
+                    typeNucleus = t;
+                    while (typeNucleus.startsWith("[]")) {
+                        if (!args.empty()) {
+                            error(
+                                location, yyscanner,
+                                ("inconsistent type manager: bad type " + *name
+                                 + (" based on instantiated polymorphic struct"
+                                    " type based on sequence type named ")
+                                 + t));
+                            return FOUND_ERROR;
+                        }
+                        if (rank == std::numeric_limits<std::size_t>::max()) {
+                            error(
+                                location, yyscanner,
+                                ("bad type " + *name
+                                 + " based on sequence type of too high rank"));
+                            return FOUND_ERROR;
+                        }
+                        ++rank;
+                        typeNucleus = typeNucleus.copy(2);
+                    }
+                    sal_Int32 i = typeNucleus.indexOf('<');
+                    if (i != -1) {
+                        if (!args.empty()) {
+                            error(
+                                location, yyscanner,
+                                ("inconsistent type manager: bad type " + *name
+                                 + (" based on instantiated polymorphic struct"
+                                    " type based on instantiated polymorphic"
+                                    " struct type named ")
+                                 + t));
+                            return FOUND_ERROR;
+                        }
+                        OUString tmpl(typeNucleus.copy(0, i));
+                        do {
+                            ++i; // skip '<' or ','
+                            sal_Int32 j = i;
+                            for (sal_Int32 level = 0;
+                                 j != typeNucleus.getLength(); ++j)
+                            {
+                                sal_Unicode c = typeNucleus[j];
+                                if (c == ',') {
+                                    if (level == 0) {
+                                        break;
+                                    }
+                                } else if (c == '<') {
+                                    ++level;
+                                } else if (c == '>') {
+                                    if (level == 0) {
+                                        break;
+                                    }
+                                    --level;
+                                }
+                            }
+                            if (j != typeNucleus.getLength()) {
+                                OUString argName(typeNucleus.copy(i, j - i));
+                                unoidl::detail::SourceProviderEntity const *
+                                    argEnt;
+                                unoidl::detail::SourceProviderType argType;
+                                switch (
+                                    findEntity(
+                                        location, yyscanner, data, false,
+                                        &argName, &argEnt, &argType))
+                                {
+                                case FOUND_ERROR:
+                                    return FOUND_ERROR;
+                                case FOUND_TYPE:
+                                    break;
+                                case FOUND_ENTITY:
+                                    if (argEnt == 0) {
+                                        error(
+                                            location, yyscanner,
+                                            (("inconsistent type manager: bad"
+                                              " instantiated polymorphic struct"
+                                              " type template type argument ")
+                                             + argName));
+                                        return FOUND_ERROR;
+                                    } else {
+                                        unoidl::detail::SourceProviderType::Type argT;
+                                        switch (argEnt->kind) {
+                                        case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
+                                            if (e->pad.is()) {
+                                                error(
+                                                    location, yyscanner,
+                                                    (("inconsistent type"
+                                                      " manager: bad"
+                                                      " instantiated"
+                                                      " polymorphic struct type"
+                                                      " template type"
+                                                      " argument ")
+                                                     + argName));
+                                                return FOUND_ERROR;
+                                            }
+                                            assert(e->entity.is());
+                                            // fall through
+                                        case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
+                                            switch (e->entity->getSort()) {
+                                            case unoidl::Entity::SORT_ENUM_TYPE:
+                                                argT = unoidl::detail::SourceProviderType::TYPE_ENUM;
+                                                break;
+                                            case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
+                                                argT = unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT;
+                                                break;
+                                            case unoidl::Entity::SORT_INTERFACE_TYPE:
+                                                argT = unoidl::detail::SourceProviderType::TYPE_INTERFACE;
+                                                break;
+                                            default:
+                                                error(
+                                                    location, yyscanner,
+                                                    (("inconsistent type"
+                                                      "manager: bad"
+                                                      " instantiated"
+                                                      " polymorphic struct type"
+                                                      " template type"
+                                                      " argument ")
+                                                     + argName));
+                                                return FOUND_ERROR;
+                                            }
+                                            break;
+                                        case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
+                                            argT = unoidl::detail::SourceProviderType::TYPE_INTERFACE;
+                                            break;
+                                        }
+                                        argType
+                                            = unoidl::detail::SourceProviderType(
+                                                argT, argName, argEnt);
+                                    }
+                                    break;
+                                }
+                                args.push_back(argType);
+                            }
+                            i = j;
+                        } while (i != typeNucleus.getLength()
+                                 && typeNucleus[i] != '>');
+                        if (i != typeNucleus.getLength() - 1
+                            || typeNucleus[i] != '>')
+                        {
+                            error(
+                                location, yyscanner,
+                                ("inconsistent type manager: bad type name \""
+                                 + t + "\""));
+                            return FOUND_ERROR;
+                        }
+                        assert(!args.empty());
+                        typeNucleus = tmpl;
+                    }
+                    if (typeNucleus.isEmpty()) {
+                        error(
+                            location, yyscanner,
+                            ("inconsistent type manager: bad type name \"" + t
+                             + "\""));
+                        return FOUND_ERROR;
+                    }
+                    if (typeNucleus == "void") {
+                        error(
+                            location, yyscanner,
+                            ("inconsistent type manager: bad type " + *name
+                             + " based on void"));
+                        return FOUND_ERROR;
+                    }
+                    if (typeNucleus == "boolean" || typeNucleus == "byte"
+                        || typeNucleus == "short"
+                        || typeNucleus == "unsigned short"
+                        || typeNucleus == "long"
+                        || typeNucleus == "unsigned long"
+                        || typeNucleus == "hyper"
+                        || typeNucleus == "unsigned hyper"
+                        || typeNucleus == "float" || typeNucleus == "double"
+                        || typeNucleus == "char" || typeNucleus == "string"
+                        || typeNucleus == "type" || typeNucleus == "any")
+                    {
+                        if (!args.empty()) {
+                            error(
+                                location, yyscanner,
+                                ("inconsistent type manager: bad type " + *name
+                                 + (" based on instantiated polymorphic struct"
+                                    " type based on ")
+                                 + typeNucleus));
+                            return FOUND_ERROR;
+                        }
+                        break;
+                    }
+                    n = "." + typeNucleus;
+                    typeNucleus = "",
+                    e = findEntity_(data, &n);
+                    continue;
+                }
+                break;
+            case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
+                if (resolveInterfaceDefinitions) {
+                    rtl::Reference<unoidl::Entity> ent(
+                        data->manager->findEntity(n));
+                    // Do not allow ent to be of SORT_TYPEDEF:
+                    if (!ent.is()
+                        || (ent->getSort()
+                            != unoidl::Entity::SORT_INTERFACE_TYPE))
+                    {
+                        error(
+                            location, yyscanner,
+                            (*name + " is based on interface declaration " + n
+                             + " that is not an interface type entity"));
+                        return FOUND_ERROR;
+                    }
+                    e->kind
+                        = unoidl::detail::SourceProviderEntity::KIND_EXTERNAL;
+                    e->entity = ent;
+                }
+                break;
+            }
+        }
+        if (!typeNucleus.isEmpty() || rank != 0 || !args.empty()) {
+            if (typeNucleus.isEmpty() && e == 0) {
+                // Found a type name based on an unknown entity:
+                *entity = 0;
+                return FOUND_ENTITY;
+            }
+            unoidl::detail::SourceProviderType t;
+            if (args.empty()) {
+                if (typeNucleus == "boolean") {
+                    t = unoidl::detail::SourceProviderType(
+                        unoidl::detail::SourceProviderType::TYPE_BOOLEAN);
+                } else if (typeNucleus == "byte") {
+                    t = unoidl::detail::SourceProviderType(
+                        unoidl::detail::SourceProviderType::TYPE_BYTE);
+                } else if (typeNucleus == "short") {
+                    t = unoidl::detail::SourceProviderType(
+                        unoidl::detail::SourceProviderType::TYPE_SHORT);
+                } else if (typeNucleus == "unsigned short") {
+                    t = unoidl::detail::SourceProviderType(
+                        unoidl::detail::SourceProviderType::TYPE_UNSIGNED_SHORT);
+                } else if (typeNucleus == "long") {
+                    t = unoidl::detail::SourceProviderType(
+                        unoidl::detail::SourceProviderType::TYPE_LONG);
+                } else if (typeNucleus == "unsigned long") {
+                    t = unoidl::detail::SourceProviderType(
+                        unoidl::detail::SourceProviderType::TYPE_UNSIGNED_LONG);
+                } else if (typeNucleus == "hyper") {
+                    t = unoidl::detail::SourceProviderType(
+                        unoidl::detail::SourceProviderType::TYPE_HYPER);
+                } else if (typeNucleus == "usigned hyper") {
+                    t = unoidl::detail::SourceProviderType(
+                        unoidl::detail::SourceProviderType::TYPE_UNSIGNED_HYPER);
+                } else if (typeNucleus == "float") {
+                    t = unoidl::detail::SourceProviderType(
+                        unoidl::detail::SourceProviderType::TYPE_FLOAT);
+                } else if (typeNucleus == "double") {
+                    t = unoidl::detail::SourceProviderType(
+                        unoidl::detail::SourceProviderType::TYPE_DOUBLE);
+                } else if (typeNucleus == "char") {
+                    t = unoidl::detail::SourceProviderType(
+                        unoidl::detail::SourceProviderType::TYPE_CHAR);
+                } else if (typeNucleus == "string") {
+                    t = unoidl::detail::SourceProviderType(
+                        unoidl::detail::SourceProviderType::TYPE_STRING);
+                } else if (typeNucleus == "type") {
+                    t = unoidl::detail::SourceProviderType(
+                        unoidl::detail::SourceProviderType::TYPE_TYPE);
+                } else if (typeNucleus == "any") {
+                    t = unoidl::detail::SourceProviderType(
+                        unoidl::detail::SourceProviderType::TYPE_ANY);
+                } else {
+                    assert(typeNucleus.isEmpty());
+                    assert(e != 0);
+                    switch (e->kind) {
+                    case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
+                        if (e->pad.is()) {
+                            if (dynamic_cast<unoidl::detail::SourceProviderEnumTypeEntityPad *>(
+                                    e->pad.get())
+                                != 0)
+                            {
+                                t = unoidl::detail::SourceProviderType(
+                                    unoidl::detail::SourceProviderType::TYPE_ENUM,
+                                    n, e);
+                            } else if (dynamic_cast<unoidl::detail::SourceProviderPlainStructTypeEntityPad *>(
+                                           e->pad.get())
+                                       != 0)
+                            {
+                                t = unoidl::detail::SourceProviderType(
+                                    unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT,
+                                    n, e);
+                            } else if (dynamic_cast<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
+                                           e->pad.get())
+                                       != 0)
+                            {
+                                error(
+                                    location, yyscanner,
+                                    ("bad type " + *name
+                                     + (" based on recursive reference to"
+                                        " polymorphic struct type template ")
+                                     + n));
+                                return FOUND_ERROR;
+                            } else if (dynamic_cast<unoidl::detail::SourceProviderExceptionTypeEntityPad *>(
+                                           e->pad.get())
+                                       != 0)
+                            {
+                                t = unoidl::detail::SourceProviderType(
+                                    unoidl::detail::SourceProviderType::TYPE_EXCEPTION,
+                                    n, e);
+                            } else if (dynamic_cast<unoidl::detail::SourceProviderInterfaceTypeEntityPad *>(
+                                           e->pad.get())
+                                       != 0)
+                            {
+                                t = unoidl::detail::SourceProviderType(
+                                    unoidl::detail::SourceProviderType::TYPE_INTERFACE,
+                                    n, e);
+                            } else {
+                                error(
+                                    location, yyscanner,
+                                    ("bad type " + *name
+                                     + " based on non-type entity " + n));
+                                return FOUND_ERROR;
+                            }
+                            break;
+                        }
+                        assert(e->entity.is());
+                        // fall through
+                    case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
+                        switch (e->entity->getSort()) {
+                        case unoidl::Entity::SORT_ENUM_TYPE:
+                            t = unoidl::detail::SourceProviderType(
+                                unoidl::detail::SourceProviderType::TYPE_ENUM,
+                                n, e);
+                            break;
+                        case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
+                            t = unoidl::detail::SourceProviderType(
+                                unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT,
+                                n, e);
+                            break;
+                        case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
+                            error(
+                                location, yyscanner,
+                                ("bad type " + *name
+                                 + " based on polymorphic struct type template "
+                                 + n + " without type arguments"));
+                            return FOUND_ERROR;
+                        case unoidl::Entity::SORT_EXCEPTION_TYPE:
+                            t = unoidl::detail::SourceProviderType(
+                                unoidl::detail::SourceProviderType::TYPE_EXCEPTION,
+                                n, e);
+                            break;
+                        case unoidl::Entity::SORT_INTERFACE_TYPE:
+                            t = unoidl::detail::SourceProviderType(
+                                unoidl::detail::SourceProviderType::TYPE_INTERFACE,
+                                n, e);
+                            break;
+                        default:
+                            error(
+                                location, yyscanner,
+                                ("bad type " + *name
+                                 + " based on non-type entity " + n));
+                            return FOUND_ERROR;
+                        }
+                        break;
+                    case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
+                        t = unoidl::detail::SourceProviderType(
+                            unoidl::detail::SourceProviderType::TYPE_INTERFACE,
+                            n, e);
+                        break;
+                    }
+                }
+            } else {
+                assert(typeNucleus.isEmpty());
+                assert(e != 0);
+                switch (e->kind) {
+                case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
+                    if (e->pad.is()) {
+                        error(
+                            location, yyscanner,
+                            ("bad type " + *name
+                             + (" based on instantiated polymorphic struct type"
+                                " based on ")
+                             + n
+                             + (" that is either not a polymorphic struct type"
+                                " template or a recursive reference to a"
+                                " polymorphic struct type template")));
+                        return FOUND_ERROR;
+                    }
+                    assert(e->entity.is());
+                    // fall through
+                case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
+                    if (e->entity->getSort()
+                        == unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE)
+                    {
+                        if (args.size()
+                            != (static_cast<
+                                    unoidl::PolymorphicStructTypeTemplateEntity *>(
+                                        e->entity.get())
+                                ->getTypeParameters().size()))
+                        {
+                            error(
+                                location, yyscanner,
+                                ("bad type " + *name
+                                 + (" based on instantiated polymorphic struct"
+                                    " type with ")
+                                 + OUString::number(args.size())
+                                 + (" type arguments based on polymorphic"
+                                    " struct type template ")
+                                 + n + " with "
+                                 + OUString::number(
+                                     static_cast<
+                                         unoidl::PolymorphicStructTypeTemplateEntity *>(
+                                             e->entity.get())
+                                     ->getTypeParameters().size())
+                                 + " type paramters"));
+                            return FOUND_ERROR;
+                        }
+                        t = unoidl::detail::SourceProviderType(n, e, args);
+                        break;
+                    }
+                    // fall through
+                case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
+                    error(
+                        location, yyscanner,
+                        ("bad type " + *name
+                         + (" based on instantiated polymorphic struct type"
+                            " based on ")
+                         + n
+                         + " that is not a polymorphic struct type template"));
+                    return FOUND_ERROR;
+                }
+            }
+            if (typedefedType != 0) {
+                for (std::size_t i = 0; i != rank; ++i) {
+                    t = unoidl::detail::SourceProviderType(&t);
+                }
+                *typedefedType = t;
+                typedefedType->typedefName = *name;
+            }
+            *entity = 0;
+            return FOUND_TYPE;
+        }
+        *entity = e;
+        return FOUND_ENTITY;
+    }
+}
+
+bool checkTypeArgument(
+    YYLTYPE location, yyscan_t yyscanner,
+    unoidl::detail::SourceProviderType const & type)
+{
+    switch (type.type) {
+    case unoidl::detail::SourceProviderType::TYPE_VOID:
+    case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_SHORT:
+    case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_LONG:
+    case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_HYPER:
+    case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
+    case unoidl::detail::SourceProviderType::TYPE_PARAMETER: //TODO?
+        error(
+            location, yyscanner,
+            "bad instantiated polymorphic struct type argument");
+        return false;
+    default:
+        return true;
+    }
+}
+
+std::vector<OUString> annotations(bool deprecated) {
+    std::vector<OUString> ann;
+    if (deprecated) {
+        ann.push_back("deprecated");
+    }
+    return ann;
+}
+
+}
+
+%}
+
+%token TOK_ELLIPSIS
+%token TOK_COLONS
+%token TOK_LEFTSHIFT
+%token TOK_RIGHTSHIFT
+
+%token TOK_FALSE
+%token TOK_TRUE
+%token TOK_ANY
+%token TOK_ATTRIBUTE
+%token TOK_BOOLEAN
+%token TOK_BOUND
+%token TOK_BYTE
+%token TOK_CHAR
+%token TOK_CONST
+%token TOK_CONSTANTS
+%token TOK_CONSTRAINED
+%token TOK_DOUBLE
+%token TOK_ENUM
+%token TOK_EXCEPTION
+%token TOK_FLOAT
+%token TOK_GET
+%token TOK_HYPER
+%token TOK_IN
+%token TOK_INOUT
+%token TOK_INTERFACE
+%token TOK_LONG
+%token TOK_MAYBEAMBIGUOUS
+%token TOK_MAYBEDEFAULT
+%token TOK_MAYBEVOID
+%token TOK_MODULE
+%token TOK_OPTIONAL
+%token TOK_OUT
+%token TOK_PROPERTY
+%token TOK_PUBLISHED
+%token TOK_RAISES
+%token TOK_READONLY
+%token TOK_REMOVABLE
+%token TOK_SEQUENCE
+%token TOK_SERVICE
+%token TOK_SET
+%token TOK_SHORT
+%token TOK_SINGLETON
+%token TOK_STRING
+%token TOK_STRUCT
+%token TOK_TRANSIENT
+%token TOK_TYPE
+%token TOK_TYPEDEF
+%token TOK_UNSIGNED
+%token TOK_VOID
+
+%token<sval> TOK_IDENTIFIER
+%token<ival> TOK_INTEGER
+%token<fval> TOK_FLOATING
+
+%token TOK_DEPRECATED
+
+%token TOK_ERROR
+
+%type<sval> identifier name singleInheritance singleInheritance_opt
+%type<bval> ctors_opt deprecated_opt ellipsis_opt published_opt
+%type<decls> attributeAccessDecl attributeAccessDecls
+%type<dir> direction
+%type<excns> exceptionSpec exceptionSpec_opt exceptions
+%type<flags> flag flagSection flagSection_opt flags
+%type<expr> addExpr andExpr expr multExpr orExpr primaryExpr shiftExpr unaryExpr
+  xorExpr
+%type<type> type
+%type<types> typeArguments
+
+%initial-action { yylloc = 1; }
+
+%%
+
+definitions:
+  definitions definition
+| /* empty */
+;
+
+definition:
+  moduleDecl
+| enumDefn
+| plainStructDefn
+| polymorphicStructTemplateDefn
+| exceptionDefn
+| interfaceDefn
+| typedefDefn
+| constantGroupDefn
+| singleInterfaceBasedServiceDefn
+| accumulationBasedServiceDefn
+| interfaceBasedSingletonDefn
+| serviceBasedSingletonDefn
+| interfaceDecl
+;
+
+moduleDecl:
+  TOK_MODULE identifier
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      data->modules.push_back(convertToFullName(data, $2));
+  }
+  '{' definitions '}' ';' { yyget_extra(yyscanner)->modules.pop_back(); }
+;
+
+enumDefn:
+  deprecated_opt published_opt TOK_ENUM identifier
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      convertToCurrentName(data, $4);
+      if (!data->entities.insert(
+              std::map<OUString, unoidl::detail::SourceProviderEntity>::value_type(
+                  data->currentName,
+                  unoidl::detail::SourceProviderEntity(
+                      new unoidl::detail::SourceProviderEnumTypeEntityPad(
+                          $2)))).
+          second)
+      {
+          error(@4, yyscanner, "multiple entities named " + data->currentName);
+          YYERROR;
+      }
+  }
+  '{' enumMembers '}' ';'
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
+      unoidl::detail::SourceProviderEnumTypeEntityPad * pad =
+          dynamic_cast<unoidl::detail::SourceProviderEnumTypeEntityPad *>(
+              ent->pad.get());
+      assert(pad != 0);
+      ent->entity = new unoidl::EnumTypeEntity(
+          pad->isPublished(), pad->members, annotations($1));
+      ent->pad.clear();
+      clearCurrentName(data);
+  }
+;
+
+enumMembers:
+| enumMembers ',' enumMember
+| enumMember
+;
+
+enumMember:
+  deprecated_opt identifier
+  {
+      OUString id(convertName($2));
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      rtl::Reference<unoidl::detail::SourceProviderEnumTypeEntityPad> pad(
+          getCurrentPad<unoidl::detail::SourceProviderEnumTypeEntityPad>(data));
+      sal_Int32 v;
+      if (pad->members.empty()) {
+          v = 0;
+      } else {
+          v = pad->members.back().value;
+          if (v == SAL_MAX_INT32) {
+              error(
+                  @2, yyscanner,
+                  ("enum " + data->currentName + " member " + id
+                   + " would have out-of-range value 2^31"));
+              YYERROR;
+          }
+          ++v;
+      }
+      pad->members.push_back(
+          unoidl::EnumTypeEntity::Member(id, v, annotations($1)));
+  }
+| deprecated_opt identifier '=' expr
+  {
+      OUString id(convertName($2));
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      rtl::Reference<unoidl::detail::SourceProviderEnumTypeEntityPad> pad(
+          getCurrentPad<unoidl::detail::SourceProviderEnumTypeEntityPad>(data));
+      sal_Int32 v;
+      switch ($4.type) {
+      case unoidl::detail::SourceProviderExpr::TYPE_INT:
+          if ($4.ival < SAL_MIN_INT32 || $4.ival > SAL_MAX_INT32) {
+              error(
+                  @4, yyscanner,
+                  ("out-of-range enum " + data->currentName + " member " + id
+                   + " value " + OUString::number($4.ival)));
+              YYERROR;
+          }
+          v = static_cast<sal_Int32>($4.ival);
+          break;
+      case unoidl::detail::SourceProviderExpr::TYPE_UINT:
+          if ($4.uval > SAL_MAX_INT32) {
+              error(
+                  @4, yyscanner,
+                  ("out-of-range enum " + data->currentName + " member " + id
+                   + " value " + OUString::number($4.uval)));
+              YYERROR;
+          }
+          v = static_cast<sal_Int32>($4.uval);
+          break;
+      default:
+          error(
+              @4, yyscanner,
+              ("non-integer enum " + data->currentName + " member " + id
+               + " value"));
+          YYERROR;
+          break;
+      }
+      pad->members.push_back(
+          unoidl::EnumTypeEntity::Member(id, v, annotations($1)));
+  }
+;
+
+plainStructDefn:
+  deprecated_opt published_opt TOK_STRUCT identifier singleInheritance_opt
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      convertToCurrentName(data, $4);
+      OUString baseName;
+      rtl::Reference<unoidl::PlainStructTypeEntity> baseEnt;
+      if ($5 != 0) {
+          baseName = convertName($5);
+          unoidl::detail::SourceProviderEntity const * p;
+          if (findEntity(@5, yyscanner, data, false, &baseName, &p, 0)
+              == FOUND_ERROR)
+          {
+              YYERROR;
+          }
+          if (p == 0 || !p->entity.is()
+              || p->entity->getSort() != unoidl::Entity::SORT_PLAIN_STRUCT_TYPE)
+          {
+              error(
+                  @5, yyscanner,
+                  ("plain struct type " + data->currentName + " base "
+                   + baseName
+                   + " does not resolve to an existing plain struct type"));
+              YYERROR;
+          }
+          baseEnt = static_cast<unoidl::PlainStructTypeEntity *>(
+              p->entity.get());
+      }
+      if (!data->entities.insert(
+              std::map<OUString, unoidl::detail::SourceProviderEntity>::value_type(
+                  data->currentName,
+                  unoidl::detail::SourceProviderEntity(
+                      new unoidl::detail::SourceProviderPlainStructTypeEntityPad(
+                          $2, baseName, baseEnt)))).
+          second)
+      {
+          error(@4, yyscanner, "multiple entities named " + data->currentName);
+          YYERROR;
+      }
+  }
+  '{' structMembers '}' ';'
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
+      unoidl::detail::SourceProviderPlainStructTypeEntityPad * pad =
+          dynamic_cast<
+              unoidl::detail::SourceProviderPlainStructTypeEntityPad *>(
+                  ent->pad.get());
+      assert(pad != 0);
+      ent->entity = new unoidl::PlainStructTypeEntity(
+          pad->isPublished(), pad->baseName, pad->members, annotations($1));
+      ent->pad.clear();
+      clearCurrentName(data);
+  }
+;
+
+polymorphicStructTemplateDefn:
+  deprecated_opt published_opt TOK_STRUCT identifier '<'
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      convertToCurrentName(data, $4);
+      if (!data->entities.insert(
+              std::map<OUString, unoidl::detail::SourceProviderEntity>::value_type(
+                  data->currentName,
+                  unoidl::detail::SourceProviderEntity(
+                      new unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad(
+                          $2)))).
+          second)
+      {
+          error(@4, yyscanner, "multiple entities named " + data->currentName);
+          YYERROR;
+      }
+  }
+  typeParameters '>' '{' structMembers '}' ';'
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
+      unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *
+          pad = dynamic_cast<
+              unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
+                  ent->pad.get());
+      assert(pad != 0);
+      ent->entity = new unoidl::PolymorphicStructTypeTemplateEntity(
+          pad->isPublished(), pad->typeParameters, pad->members,
+          annotations($1));
+      ent->pad.clear();
+      clearCurrentName(data);
+  }
+;
+
+typeParameters:
+  typeParameters ',' identifier
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      rtl::Reference<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad>
+          pad(getCurrentPad<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad>(
+                  data));
+      OUString id(convertName($3));
+      if (nameHasSameIdentifierAs(data->currentName, id)) {
+          error(
+              @3, yyscanner,
+              ("polymorphic struct type template " + data->currentName
+               + " type parameter " + id
+               + " has same unqualified identifer as the type itself"));
+          YYERROR;
+      }
+      if (std::find(
+              pad->typeParameters.begin(), pad->typeParameters.end(),  id)
+          != pad->typeParameters.end())
+      {
+          error(
+              @3, yyscanner,
+              ("polymorphic struct type template " + data->currentName
+               + " type parameter " + id
+               + " has same identifier as another type parameter"));
+          YYERROR;
+      }
+      pad->typeParameters.push_back(id);
+  }
+| identifier
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      rtl::Reference<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad>
+          pad(getCurrentPad<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad>(
+                  data));
+      OUString id(convertName($1));
+      if (nameHasSameIdentifierAs(data->currentName, id)) {
+          error(
+              @1, yyscanner,
+              ("polymorphic struct type template " + data->currentName
+               + " type parameter " + id
+               + " has same unqualified identifer as the type itself"));
+          YYERROR;
+      }
+      assert(pad->typeParameters.empty());
+      pad->typeParameters.push_back(id);
+  }
+;
+
+exceptionDefn:
+  deprecated_opt published_opt TOK_EXCEPTION identifier singleInheritance_opt
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      convertToCurrentName(data, $4);
+      OUString baseName;
+      rtl::Reference<unoidl::ExceptionTypeEntity> baseEnt;
+      if ($5 != 0) {
+          baseName = convertName($5);
+          unoidl::detail::SourceProviderEntity const * p;
+          if (findEntity(@5, yyscanner, data, false, &baseName, &p, 0)
+              == FOUND_ERROR)
+          {
+              YYERROR;
+          }
+          if (p == 0 || !p->entity.is()
+              || p->entity->getSort() != unoidl::Entity::SORT_EXCEPTION_TYPE)
+          {
+              error(
+                  @5, yyscanner,
+                  ("exception type " + data->currentName + " base " + baseName
+                   + " does not resolve to an existing exception type"));
+              YYERROR;
+          }
+          baseEnt = static_cast<unoidl::ExceptionTypeEntity *>(
+              p->entity.get());
+      }
+      if (!data->entities.insert(
+              std::map<OUString, unoidl::detail::SourceProviderEntity>::value_type(
+                  data->currentName,
+                  unoidl::detail::SourceProviderEntity(
+                      new unoidl::detail::SourceProviderExceptionTypeEntityPad(
+                          $2, baseName, baseEnt)))).
+          second)
+      {
+          error(@4, yyscanner, "multiple entities named " + data->currentName);
+          YYERROR;
+      }
+  }
+ '{' structMembers '}' ';'
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
+      unoidl::detail::SourceProviderExceptionTypeEntityPad * pad =
+          dynamic_cast<unoidl::detail::SourceProviderExceptionTypeEntityPad *>(
+              ent->pad.get());
+      assert(pad != 0);
+      ent->entity = new unoidl::ExceptionTypeEntity(
+          pad->isPublished(), pad->baseName, pad->members, annotations($1));
+      ent->pad.clear();
+      clearCurrentName(data);
+  }
+;
+
+structMembers:
+  structMembers structMember
+| /* empty */
+;
+
+structMember:
+  deprecated_opt type identifier ';'
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      unoidl::detail::SourceProviderType t(*$2);
+      delete $2;
+      OUString id(convertName($3));
+      switch (t.type) {
+      case unoidl::detail::SourceProviderType::TYPE_VOID:
+      case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
+          error(
+              @2, yyscanner,
+              ("illegal struct/exception type " + data->currentName
+               + " direct member " + id + " type"));
+          YYERROR;
+          break;
+      default:
+          break;
+      }
+      if (nameHasSameIdentifierAs(data->currentName, id)) {
+          error(
+              @2, yyscanner,
+              ("struct/exception type " + data->currentName + " direct member "
+               + id + " has same unqualified identifer as the type itself"));
+          YYERROR;
+      }
+      unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
+      unoidl::detail::SourceProviderPlainStructTypeEntityPad * p1 =
+          dynamic_cast<unoidl::detail::SourceProviderPlainStructTypeEntityPad *>(
+              ent->pad.get());
+      if (p1 != 0) {
+          for (std::vector<unoidl::PlainStructTypeEntity::Member>::iterator i(
+                   p1->members.begin());
+               i != p1->members.end(); ++i)
+          {
+              if (id == i->name) {
+                  error(
+                      @3, yyscanner,
+                      ("plain struct type " + data->currentName
+                       + " direct member " + id
+                       + " has same identifier as another direct member"));
+                  YYERROR;
+              }
+          }
+          if (p1->baseEntity.is()) {
+              OUString baseName(p1->baseName);
+              for (rtl::Reference<unoidl::PlainStructTypeEntity> baseEnt(
+                       p1->baseEntity);;)
+              {
+                  if (nameHasSameIdentifierAs(baseName, id)) {
+                      error(
+                          @3, yyscanner,
+                          ("plain struct type " + data->currentName
+                           + " direct member " + id
+                           + " has same unqalified identifier as base "
+                           + baseName));
+                      YYERROR;
+                  }
+                  for (std::vector<unoidl::PlainStructTypeEntity::Member>::const_iterator i(
+                           baseEnt->getDirectMembers().begin());
+                       i != baseEnt->getDirectMembers().end(); ++i)
+                  {
+                      if (id == i->name) {
+                          error(
+                              @3, yyscanner,
+                              ("plain struct type " + data->currentName
+                               + " direct member " + id
+                               + " has same identifier as a member of base "
+                               + baseName));
+                          YYERROR;
+                      }
+                  }
+                  baseName = baseEnt->getDirectBase();
+                  if (baseName.isEmpty()) {
+                      break;
+                  }
+                  unoidl::detail::SourceProviderEntity const * p;
+                  if (findEntity(@2, yyscanner, data, false, &baseName, &p, 0)
+                      == FOUND_ERROR)
+                  {
+                      YYERROR;
+                  }
+                  if (p == 0 || !p->entity.is()
+                      || (p->entity->getSort()
+                          != unoidl::Entity::SORT_PLAIN_STRUCT_TYPE))
+                  {
+                      error(
+                          @2, yyscanner,
+                          ("inconsistent type manager: plain struct type "
+                           + data->currentName + " base " + baseName
+                           + (" does not resolve to an existing plain struct"
+                              " type")));
+                      YYERROR;
+                  }
+                  baseEnt = static_cast<unoidl::PlainStructTypeEntity *>(
+                      p->entity.get());
+              }
+          }
+          p1->members.push_back(
+              unoidl::PlainStructTypeEntity::Member(
+                  id, t.getName(), annotations($1)));
+      } else {
+          unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *
+              p2 = dynamic_cast<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
+                  ent->pad.get());
+          if (p2 != 0) {
+              if (std::find(
+                      p2->typeParameters.begin(), p2->typeParameters.end(),  id)
+                  != p2->typeParameters.end())
+              {
+                  error(
+                      @3, yyscanner,
+                      ("polymorphic struct type template " + data->currentName
+                       + " direct member " + id
+                       + " has same identifier as a type parameter"));
+                  YYERROR;
+              }
+              for (std::vector<unoidl::PolymorphicStructTypeTemplateEntity::Member>::iterator i(
+                       p2->members.begin());
+                   i != p2->members.end(); ++i)
+              {
+                  if (id == i->name) {
+                      error(
+                          @3, yyscanner,
+                          ("polymorphic struct type template "
+                           + data->currentName + " direct member " + id
+                           + " has same identifier as another direct member"));
+                      YYERROR;
+                  }
+              }
+              p2->members.push_back(
+                  unoidl::PolymorphicStructTypeTemplateEntity::Member(
+                      id, t.getName(),
+                      (t.type
+                       == unoidl::detail::SourceProviderType::TYPE_PARAMETER),
+                      annotations($1)));
+          } else {
+              unoidl::detail::SourceProviderExceptionTypeEntityPad * p3
+                  = dynamic_cast<unoidl::detail::SourceProviderExceptionTypeEntityPad *>(
+                      ent->pad.get());
+              assert(p3 != 0);
+              for (std::vector<unoidl::ExceptionTypeEntity::Member>::iterator i(
+                       p3->members.begin());
+                   i != p3->members.end(); ++i)
+              {
+                  if (id == i->name) {
+                      error(
+                          @3, yyscanner,
+                          ("exception type " + data->currentName
+                           + " direct member " + id
+                           + " has same identifier as another direct member"));
+                      YYERROR;
+                  }
+              }
+              if (p3->baseEntity.is()) {
+                  OUString baseName(p3->baseName);
+                  for (rtl::Reference<unoidl::ExceptionTypeEntity> baseEnt(
+                           p3->baseEntity);;)
+                  {
+                      if (nameHasSameIdentifierAs(baseName, id)) {
+                          error(
+                              @3, yyscanner,
+                              ("exception type " + data->currentName
+                               + " direct member " + id
+                               + " has same unqalified identifier as base "
+                               + baseName));
+                          YYERROR;
+                      }
+                      for (std::vector<unoidl::ExceptionTypeEntity::Member>::const_iterator i(
+                               baseEnt->getDirectMembers().begin());
+                           i != baseEnt->getDirectMembers().end(); ++i)
+                      {
+                          if (id == i->name) {
+                              error(
+                                  @3, yyscanner,
+                                  ("exception type " + data->currentName
+                                   + " direct member " + id
+                                   + " has same identifier as a member of base "
+                                   + baseName));
+                              YYERROR;
+                          }
+                      }
+                      baseName = baseEnt->getDirectBase();
+                      if (baseName.isEmpty()) {
+                          break;
+                      }
+                      unoidl::detail::SourceProviderEntity const * p;
+                      if (findEntity(
+                              @2, yyscanner, data, false, &baseName, &p, 0)
+                          == FOUND_ERROR)
+                      {
+                          YYERROR;
+                      }
+                      if (p == 0 || !p->entity.is()
+                          || (p->entity->getSort()
+                              != unoidl::Entity::SORT_EXCEPTION_TYPE))
+                      {
+                          error(
+                              @2, yyscanner,
+                              ("inconsistent type manager: exception type "
+                               + data->currentName + " base " + baseName
+                               + (" does not resolve to an existing exception"
+                                  " type")));
+                          YYERROR;
+                      }
+                      baseEnt = static_cast<unoidl::ExceptionTypeEntity *>(
+                          p->entity.get());
+                  }
+              }
+              p3->members.push_back(
+                  unoidl::ExceptionTypeEntity::Member(
+                      id, t.getName(), annotations($1)));
+          }
+      }
+  }
+;
+
+interfaceDefn:
+  deprecated_opt published_opt TOK_INTERFACE identifier singleInheritance_opt
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      convertToCurrentName(data, $4);
+      OUString baseName;
+      rtl::Reference<unoidl::InterfaceTypeEntity> baseEnt;
+      if ($5 != 0) {
+          baseName = convertName($5);
+          unoidl::detail::SourceProviderEntity const * p;
+          if (findEntity(@5, yyscanner, data, true, &baseName, &p, 0)
+              == FOUND_ERROR)
+          {
+              YYERROR;
+          }
+          if (p == 0 || !p->entity.is()
+              || p->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
+          {
+              error(
+                  @5, yyscanner,
+                  ("interface type " + data->currentName + " direct base "
+                   + baseName
+                   + " does not resolve to an existing interface type"));
+              YYERROR;
+          }
+          baseEnt = static_cast<unoidl::InterfaceTypeEntity *>(p->entity.get());
+      }
+      std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator i(
+          data->entities.find(data->currentName));
+      if (i != data->entities.end()
+          && (i->second.kind
+              != unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL))
+      {
+          error(@4, yyscanner, "multiple entities named " + data->currentName);
+          YYERROR;
+      }
+      data->entities[data->currentName] = unoidl::detail::SourceProviderEntity(
+          new unoidl::detail::SourceProviderInterfaceTypeEntityPad(
+              $2, baseName, baseEnt));
+  }
+  '{' interfaceMembers '}' ';'
+  {
+      //TODO: check direct member uniqueness
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
+      unoidl::detail::SourceProviderInterfaceTypeEntityPad * pad =
+          dynamic_cast<unoidl::detail::SourceProviderInterfaceTypeEntityPad *>(
+              ent->pad.get());
+      assert(pad != 0);
+      if (pad->mandatoryBases.empty()
+          && data->currentName != "com.sun.star.uno.XInterface")
+      {
+          OUString base(".com.sun.star.uno.XInterface");
+          unoidl::detail::SourceProviderEntity const * p;
+          if (findEntity(@4, yyscanner, data, true, &base, &p, 0)
+              == FOUND_ERROR)
+          {
+              YYERROR;
+          }
+          if (p == 0 || !p->entity.is()
+              || p->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
+          {
+              error(
+                  @3, yyscanner,
+                  ("interface type " + data->currentName
+                   + " implicit direct base " + base
+                   + " does not resolve to an existing interface type"));
+              YYERROR;
+          }
+          pad->mandatoryBases.push_back(
+              unoidl::detail::SourceProviderInterfaceTypeEntityPad::Base(
+                  base,
+                  static_cast<unoidl::InterfaceTypeEntity *>(p->entity.get()),
+                  std::vector<OUString>()));
+      }
+      std::vector<unoidl::AnnotatedReference> mbases;
+      for (std::vector<unoidl::detail::SourceProviderInterfaceTypeEntityPad::Base>::const_iterator
+               i(pad->mandatoryBases.begin());
+           i != pad->mandatoryBases.end(); ++i)
+      {
+          mbases.push_back(unoidl::AnnotatedReference(i->name, i->annotations));
+      }
+      std::vector<unoidl::AnnotatedReference> obases;
+      for (std::vector<unoidl::detail::SourceProviderInterfaceTypeEntityPad::Base>::const_iterator
+               i(pad->optionalBases.begin());
+           i != pad->optionalBases.end(); ++i)
+      {
+          obases.push_back(unoidl::AnnotatedReference(i->name, i->annotations));
+      }
+      ent->entity = new unoidl::InterfaceTypeEntity(
+          pad->isPublished(), mbases, obases, pad->attributes, pad->methods,
+          annotations($1));
+      ent->pad.clear();
+      clearCurrentName(data);
+  }
+;
+
+interfaceMembers:
+ interfaceMembers interfaceMember
+| /* empty */
+;
+
+interfaceMember:
+  interfaceBase
+| interfaceAttribute
+| interfaceMethod
+;
+
+interfaceBase:
+  deprecated_opt flagSection_opt TOK_INTERFACE name ';'
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      OUString name(convertName($4));
+      rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad> pad(
+          getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
+              data));
+      if (pad->singleBase) {
+          error(
+              @3, yyscanner,
+              "single-inheritance interface cannot have additional bases");
+          YYERROR;
+      }
+      if (($2 & ~unoidl::detail::FLAG_OPTIONAL) != 0) {
+          error(
+              @2, yyscanner,
+              "interface base can only be flagged as [optional]");
+          YYERROR;
+      }
+      bool opt = ($2 & unoidl::detail::FLAG_OPTIONAL) != 0;
+      unoidl::detail::SourceProviderEntity const * p;
+      if (findEntity(@4, yyscanner, data, true, &name, &p, 0) == FOUND_ERROR) {
+          YYERROR;
+      }
+      if (p == 0 || !p->entity.is()
+          || p->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
+      {
+          error(
+              @4, yyscanner,
+              ("interface type " + data->currentName + " direct base " + name
+               + " does not resolve to an existing interface type"));
+          YYERROR;
+      }
+      //TODO: check uniqueness (incl. that opt base != XInterface)
+      (opt ? pad->optionalBases : pad->mandatoryBases).push_back(
+          unoidl::detail::SourceProviderInterfaceTypeEntityPad::Base(
+              name,
+              static_cast<unoidl::InterfaceTypeEntity *>(p->entity.get()),
+              annotations($1)));
+  }
+;
+
+interfaceAttribute:
+  deprecated_opt flagSection type identifier
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      unoidl::detail::SourceProviderType t(*$3);
+      delete $3;
+      OUString id(convertName($4));
+      if (($2 & unoidl::detail::FLAG_ATTRIBUTE) == 0) {
+          error(
+              @2, yyscanner,
+              "interface attribute must be flagged as [attribute]");
+          YYERROR;
+      }
+      if (($2
+           & ~(unoidl::detail::FLAG_ATTRIBUTE | unoidl::detail::FLAG_BOUND
+               | unoidl::detail::FLAG_READONLY))
+          != 0)
+      {
+          error(
+              @2, yyscanner,
+              ("interface attribute can only be flagged as [attribute,"
+               " optional]"));
+          YYERROR;
+      }
+      switch (t.type) {
+      case unoidl::detail::SourceProviderType::TYPE_VOID:
+      case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
+          error(
+              @3, yyscanner,
+              ("illegal interface type " + data->currentName
+               + " direct attribute " + id + " type"));
+          YYERROR;
+          break;
+      default:
+          break;
+      }
+      rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad> pad(
+          getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
+              data));
+      pad->attributes.push_back(
+          unoidl::InterfaceTypeEntity::Attribute(
+              id, t.getName(), ($2 & unoidl::detail::FLAG_BOUND) != 0,
+              ($2 & unoidl::detail::FLAG_READONLY) != 0,
+              std::vector<OUString>(), std::vector<OUString>(),
+              annotations($1)));
+  }
+  attributeAccessDecls_opt ';'
+;
+
+attributeAccessDecls_opt:
+  '{' attributeAccessDecls '}'
+| /* empty */
+;
+
+attributeAccessDecls:
+  attributeAccessDecls attributeAccessDecl
+  {
+      if (($1 & $2) != 0) {
+          error(
+              @2, yyscanner, "duplicate get/set attribute access declaration");
+          YYERROR;
+      }
+      $$ = unoidl::detail::SourceProviderAccessDecls($1 | $2);
+  }
+| /* empty */ { $$ = unoidl::detail::SourceProviderAccessDecls(0); }
+;
+
+attributeAccessDecl:
+  TOK_GET exceptionSpec ';'
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
+          pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
+              data));
+      assert(!pad->attributes.empty());
+      pad->attributes.back().getExceptions = *$2;
+      delete $2;
+      $$ = unoidl::detail::SourceProviderAccessDecls::ACCESS_DECL_GET;
+  }
+| TOK_SET exceptionSpec ';'
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
+          pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
+              data));
+      assert(!pad->attributes.empty());
+      pad->attributes.back().setExceptions = *$2;
+      delete $2;
+      if (pad->attributes.back().readOnly) {
+          error(
+              @1, yyscanner,
+              ("interface type " + data->currentName
+               + " direct read-only attribute " + pad->attributes.back().name
+               + " cannot have set access declaration"));
+          YYERROR;
+      }
+      $$ = unoidl::detail::SourceProviderAccessDecls::ACCESS_DECL_SET;
+  }
+;
+
+interfaceMethod:
+  deprecated_opt type identifier
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      unoidl::detail::SourceProviderType t(*$2);
+      delete $2;
+      OUString id(convertName($3));
+      if (t.type == unoidl::detail::SourceProviderType::TYPE_EXCEPTION) {
+          error(
+              @3, yyscanner,
+              ("illegal interface type " + data->currentName
+               + " direct method " + id + " return type"));
+          YYERROR;
+      }
+      rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad> pad(
+          getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
+              data));
+      pad->methods.push_back(
+          unoidl::InterfaceTypeEntity::Method(
+              id, t.getName(),
+              std::vector<unoidl::InterfaceTypeEntity::Method::Parameter>(),
+              std::vector<OUString>(), annotations($1)));
+  }
+  '(' methodParams_opt ')' exceptionSpec_opt ';'
+  {
+      if ($8 != 0) {
+          unoidl::detail::SourceProviderScannerData * data
+              = yyget_extra(yyscanner);
+          rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
+              pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
+                  data));
+          assert(!pad->methods.empty());
+          pad->methods.back().exceptions = *$8;
+          delete $8;
+      }
+  }
+;
+
+methodParams_opt:
+  methodParams
+| /* empty */
+;
+
+methodParams:
+  methodParams ',' methodParam
+| methodParam
+;
+
+methodParam:
+  '[' direction ']' type identifier
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      unoidl::detail::SourceProviderType t(*$4);
+      delete $4;
+      OUString id(convertName($5));
+      rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
+          pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
+              data));
+      assert(!pad->methods.empty());
+      switch (t.type) {
+      case unoidl::detail::SourceProviderType::TYPE_VOID:
+      case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
+          error(
+              @4, yyscanner,
+              ("illegal interface type " + data->currentName
+               + " direct method " + pad->methods.back().name + " parameter "
+               + id + " type"));
+          YYERROR;
+          break;
+      default:
+          break;
+      }
+      for (std::vector<unoidl::InterfaceTypeEntity::Method::Parameter>::iterator
+               i(pad->methods.back().parameters.begin());
+           i != pad->methods.back().parameters.end(); ++i)
+      {
+          if (id == i->name) {
+              error(
+                  @5, yyscanner,
+                  ("interface type " + data->currentName + " direct method "
+                   + pad->methods.back().name + " parameter " + id
+                   + " has same identifier as another parameter"));
+              YYERROR;
+          }
+      }
+      pad->methods.back().parameters.push_back(
+          unoidl::InterfaceTypeEntity::Method::Parameter(id, t.getName(), $2));
+  }
+;
+
+direction:
+  TOK_IN { $$ = unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN; }
+| TOK_OUT
+  { $$ = unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT; }
+| TOK_INOUT
+  { $$ = unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT; }
+;
+
+typedefDefn:
+  deprecated_opt published_opt TOK_TYPEDEF type identifier ';'
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      unoidl::detail::SourceProviderType t(*$4); //TODO: service/singleton typedefs?
+      delete $4;
+      OUString name(convertToFullName(data, $5));
+      if (!data->entities.insert(
+              std::map<OUString, unoidl::detail::SourceProviderEntity>::value_type(
+                  name,
+                  unoidl::detail::SourceProviderEntity(
+                      unoidl::detail::SourceProviderEntity::KIND_LOCAL,
+                      new unoidl::TypedefEntity(
+                          $2, t.getName(), annotations($1))))).
+          second)
+      {
+          error(@5, yyscanner, "multiple entities named " + name);
+          YYERROR;
+      }
+  }
+;
+
+constantGroupDefn:
+  deprecated_opt published_opt TOK_CONSTANTS identifier
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      convertToCurrentName(data, $4);
+      if (!data->entities.insert(
+              std::map<OUString, unoidl::detail::SourceProviderEntity>::value_type(
+                  data->currentName,
+                  unoidl::detail::SourceProviderEntity(
+                      new unoidl::detail::SourceProviderConstantGroupEntityPad(
+                          $2)))).
+          second)
+      {
+          error(@4, yyscanner, "multiple entities named " + data->currentName);
+          YYERROR;
+      }
+  }
+  '{' constants '}' ';'
+  {
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
+      unoidl::detail::SourceProviderConstantGroupEntityPad * pad =
+          dynamic_cast<unoidl::detail::SourceProviderConstantGroupEntityPad *>(
+              ent->pad.get());
+      assert(pad != 0);
+      ent->entity = new unoidl::ConstantGroupEntity(
+          pad->isPublished(), pad->members, annotations($1));
+      ent->pad.clear();
+      clearCurrentName(data);
+  }
+;
+
+constants:
+  constants constant
+| /* empty */
+;
+
+constant:
+  deprecated_opt TOK_CONST type identifier '=' expr ';'
+  {
+      OUString id(convertName($4));
+      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
+      rtl::Reference<unoidl::detail::SourceProviderConstantGroupEntityPad> pad(
+          getCurrentPad<unoidl::detail::SourceProviderConstantGroupEntityPad>(
+              data));
+      unoidl::detail::SourceProviderType t(*$3);
+      delete $3;
+      unoidl::ConstantValue v(false); // dummy value
+      switch (t.type) {
+      case unoidl::detail::SourceProviderType::TYPE_BOOLEAN:
+          if ($6.type != unoidl::detail::SourceProviderExpr::TYPE_BOOL) {
+              error(
+                  @6, yyscanner,
+                  ("bad value of boolean-typed constant " + data->currentName
+                   + "." + id));
+              YYERROR;
+          }
+          v = unoidl::ConstantValue($6.bval);
+          break;
+      case unoidl::detail::SourceProviderType::TYPE_BYTE:
+          switch ($6.type) {
+          case unoidl::detail::SourceProviderExpr::TYPE_INT:
+              if ($6.ival < SAL_MIN_INT8 || $6.ival > SAL_MAX_INT8) {
+                  error(
+                      @6, yyscanner,
+                      ("out-of-range byte-typed constant " + data->currentName
+                       + "." + id + " value " + OUString::number($6.ival)));
+                  YYERROR;
+              }
+              v = unoidl::ConstantValue(static_cast<sal_Int8>($6.ival));
+              break;
+          case unoidl::detail::SourceProviderExpr::TYPE_UINT:
+              if ($6.uval > SAL_MAX_INT8) {
+                  error(
+                      @6, yyscanner,
+                      ("out-of-range byte-typed constant " + data->currentName
+                       + "." + id + " value " + OUString::number($6.uval)));
+                  YYERROR;
+              }
+              v = unoidl::ConstantValue(static_cast<sal_Int8>($6.uval));
+              break;
+          default:
+              error(
+                  @6, yyscanner,
+                  ("bad value of byte-typed constant " + data->currentName + "."
+                   + id));
+              YYERROR;
+              break;
+          }
+          break;
+      case unoidl::detail::SourceProviderType::TYPE_SHORT:
+          switch ($6.type) {
+          case unoidl::detail::SourceProviderExpr::TYPE_INT:
+              if ($6.ival < SAL_MIN_INT16 || $6.ival > SAL_MAX_INT16) {
+                  error(
+                      @6, yyscanner,
+                      ("out-of-range short-typed constant " + data->currentName
+                       + "." + id + " value " + OUString::number($6.ival)));
+                  YYERROR;
+              }
+              v = unoidl::ConstantValue(static_cast<sal_Int16>($6.ival));
+              break;
+          case unoidl::detail::SourceProviderExpr::TYPE_UINT:
+              if ($6.uval > SAL_MAX_INT16) {
+                  error(
+                      @6, yyscanner,
+                      ("out-of-range short-typed constant " + data->currentName
+                       + "." + id + " value " + OUString::number($6.uval)));
+                  YYERROR;
+              }
+              v = unoidl::ConstantValue(static_cast<sal_Int16>($6.uval));
+              break;
+          default:
+              error(
+                  @6, yyscanner,
+                  ("bad value of short-typed constant " + data->currentName
+                   + "." + id));
+              YYERROR;
+              break;
+          }
+          break;
+      case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_SHORT:
+          switch ($6.type) {
+          case unoidl::detail::SourceProviderExpr::TYPE_INT:
+              if ($6.ival < 0 || $6.ival > SAL_MAX_UINT16) {
+                  error(
+                      @6, yyscanner,
+                      ("out-of-range unsigned-short-typed constant "
+                       + data->currentName + "." + id + " value "
+                       + OUString::number($6.ival)));
+                  YYERROR;
+              }
+              v = unoidl::ConstantValue(static_cast<sal_uInt16>($6.ival));
+              break;
+          case unoidl::detail::SourceProviderExpr::TYPE_UINT:
+              if ($6.uval > SAL_MAX_UINT16) {
+                  error(
+                      @6, yyscanner,
+                      ("out-of-range unsigned-short-typed constant "
+                       + data->currentName + "." + id + " value "
+                       + OUString::number($6.uval)));
+                  YYERROR;
+              }
+              v = unoidl::ConstantValue(static_cast<sal_uInt16>($6.uval));
+              break;
+          default:
+              error(
+                  @6, yyscanner,
+                  ("bad value of unsigned-short-typed constant "
+                   + data->currentName + "." + id));
+              YYERROR;
+              break;
+          }
+          break;
+      case unoidl::detail::SourceProviderType::TYPE_LONG:
+          switch ($6.type) {
+          case unoidl::detail::SourceProviderExpr::TYPE_INT:
+              if ($6.ival < SAL_MIN_INT32 || $6.ival > SAL_MAX_INT32) {
+                  error(
+                      @6, yyscanner,
+                      ("out-of-range long-typed constant " + data->currentName
+                       + "." + id + " value " + OUString::number($6.ival)));
+                  YYERROR;
+              }
+              v = unoidl::ConstantValue(static_cast<sal_Int32>($6.ival));
+              break;
+          case unoidl::detail::SourceProviderExpr::TYPE_UINT:
+              if ($6.uval > SAL_MAX_INT32) {
+                  error(
+                      @6, yyscanner,
+                      ("out-of-range long-typed constant " + data->currentName
+                       + "." + id + " value " + OUString::number($6.uval)));
+                  YYERROR;
+              }
+              v = unoidl::ConstantValue(static_cast<sal_Int32>($6.uval));
+              break;
+          default:
+              error(
+                  @6, yyscanner,
+                  ("bad value of long-typed constant " + data->currentName
+                   + "." + id));
+              YYERROR;
+              break;
+          }
+          break;
+      case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_LONG:
+          switch ($6.type) {
+          case unoidl::detail::SourceProviderExpr::TYPE_INT:
+              if ($6.ival < 0 || $6.ival > SAL_MAX_UINT32) {
+                  error(
+                      @6, yyscanner,
+                      ("out-of-range unsigned-long-typed constant "
+                       + data->currentName + "." + id + " value "
+                       + OUString::number($6.ival)));
+                  YYERROR;
+              }
+              v = unoidl::ConstantValue(static_cast<sal_uInt32>($6.ival));
+              break;
+          case unoidl::detail::SourceProviderExpr::TYPE_UINT:
+              if ($6.uval > SAL_MAX_UINT32) {
+                  error(
+                      @6, yyscanner,
+                      ("out-of-range unsigned-long-typed constant "
+                       + data->currentName + "." + id + " value "
+                       + OUString::number($6.uval)));
+                  YYERROR;
+              }
+              v = unoidl::ConstantValue(static_cast<sal_uInt32>($6.uval));
+              break;
+          default:
+              error(
+                  @6, yyscanner,
+                  ("bad value of unsigned-long-typed constant "
+                   + data->currentName + "." + id));
+              YYERROR;
+              break;
+          }
+          break;
+      case unoidl::detail::SourceProviderType::TYPE_HYPER:
+          switch ($6.type) {
+          case unoidl::detail::SourceProviderExpr::TYPE_INT:
+              v = unoidl::ConstantValue($6.ival);
+              break;
+          case unoidl::detail::SourceProviderExpr::TYPE_UINT:
+              if ($6.uval > SAL_MAX_INT64) {
+                  error(
+                      @6, yyscanner,
+                      ("out-of-range hyper-typed constant " + data->currentName
+                       + "." + id + " value " + OUString::number($6.uval)));
+                  YYERROR;
+              }
+              v = unoidl::ConstantValue(static_cast<sal_Int64>($6.uval));
+              break;
+          default:
+              error(
+                  @6, yyscanner,
+                  ("bad value of hyper-typed constant " + data->currentName
+                   + "." + id));
+              YYERROR;
+              break;
+          }
+          break;
+      case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_HYPER:
+          switch ($6.type) {
+          case unoidl::detail::SourceProviderExpr::TYPE_INT:
+              if ($6.ival < 0) {
+                  error(
+                      @6, yyscanner,
+                      ("out-of-range unsigned-hyper-typed constant "
+                       + data->currentName + "." + id + " value "
+                       + OUString::number($6.ival)));
+                  YYERROR;
+              }
+              v = unoidl::ConstantValue(static_cast<sal_uInt64>($6.ival));
+              break;
+          case unoidl::detail::SourceProviderExpr::TYPE_UINT:
+              v = unoidl::ConstantValue($6.uval);
+              break;
+          default:
+              error(
+                  @6, yyscanner,
+                  ("bad value of unsigned-hyper-typed constant "
+                   + data->currentName + "." + id));
+              YYERROR;
+              break;
+          }
+          break;
+      case unoidl::detail::SourceProviderType::TYPE_FLOAT:
+          switch ($6.type) {
+          case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
+              error(
+                  @6, yyscanner,
+                  ("bad boolean value of float-typed constant "
+                   + data->currentName + "." + id));
+              YYERROR;
+              break;
+          case unoidl::detail::SourceProviderExpr::TYPE_INT:
+              v = unoidl::ConstantValue(static_cast<float>($6.ival));
+              break;
+          case unoidl::detail::SourceProviderExpr::TYPE_UINT:
+              v = unoidl::ConstantValue(static_cast<float>($6.uval));
+              break;
+          case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
+              v = unoidl::ConstantValue(static_cast<float>($6.fval));
+              break;
+          }
+          break;
+      case unoidl::detail::SourceProviderType::TYPE_DOUBLE:
+          switch ($6.type) {
+          case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
+              error(
+                  @6, yyscanner,
+                  ("bad boolean value of double-typed constant "
+                   + data->currentName + "." + id));
+              YYERROR;
+              break;

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list