Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  sourceprovider-parser.y   Sprache: unbekannt

 
/* -*- 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: check Exception, RuntimeException, XInterface defns */

%locations
%pure-parser

%{

#include <sal/config.h>

#include <o3tl/unreachable.hxx>
#include <o3tl/string_view.hxx>
#include <rtl/ustrbuf.hxx>
#include <unoidl/unoidl.hxx>

#include <algorithm>
#include <cassert>
#include <cerrno>
#include <cstddef>
#include <cstdlib>
#include <limits>
#include <new>
#include <utility>
#include <vector>

#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 <osl/file.h>
#include <osl/thread.h>
#include <sal/log.hxx>

#include "sourceprovider-scanner.hxx"

#define YYLLOC_DEFAULT(Current, Rhs, N) \
    do { (Current) = YYRHSLOC((Rhs), (N) ? 1 : 0); } while (0)

static void yyerror(YYLTYPE * locp, yyscan_t yyscanner, char const * msg) {
    assert(locp != nullptr);
    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 u"attribute"_ustr;
    case unoidl::detail::FLAG_BOUND:
        return u"bound"_ustr;
    case unoidl::detail::FLAG_CONSTRAINED:
        return u"constrained"_ustr;
    case unoidl::detail::FLAG_MAYBEAMBIGUOUS:
        return u"maybeambiguous"_ustr;
    case unoidl::detail::FLAG_MAYBEDEFAULT:
        return u"maybedefault"_ustr;
    case unoidl::detail::FLAG_MAYBEVOID:
        return u"maybevoid"_ustr;
    case unoidl::detail::FLAG_OPTIONAL:
        return u"optional"_ustr;
    case unoidl::detail::FLAG_PROPERTY:
        return u"property"_ustr;
    case unoidl::detail::FLAG_READONLY:
        return u"readonly"_ustr;
    case unoidl::detail::FLAG_REMOVABLE:
        return u"removable"_ustr;
    case unoidl::detail::FLAG_TRANSIENT:
        return u"transient"_ustr;
    default:
        assert(false && "this cannot happen"); for (;;) { std::abort(); }
    }
}

OUString convertName(OString const * name) {
    assert(name != nullptr);
    OUString s(OStringToOUString(*name, RTL_TEXTENCODING_ASCII_US));
    delete name;
    return s;
}

OUString convertToFullName(
    unoidl::detail::SourceProviderScannerData const * data,
    OString const * identifier)
{
    assert(data != nullptr);
    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 != nullptr);
    assert(data->currentName.isEmpty());
    data->currentName = convertToFullName(data, identifier);
    assert(!data->currentName.isEmpty());
}

void clearCurrentState(unoidl::detail::SourceProviderScannerData * data) {
    assert(data != nullptr);
    data->currentName.clear();
    data->publishedContext = false;
}

unoidl::detail::SourceProviderEntity * getCurrentEntity(
    unoidl::detail::SourceProviderScannerData * data)
{
    assert(data != nullptr);
    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(std::u16string_view name, std::u16string_view identifier)
{
    std::u16string_view::size_type pos = name.rfind('.');
    size_t i = (pos != std::u16string_view::npos) ? pos + 1 : 0;
    return identifier.size() == name.size() - i
        && o3tl::starts_with(name.substr(i), identifier);
}

bool coerce(
    YYLTYPE location, yyscan_t yyscanner,
    unoidl::detail::SourceProviderExpr * lhs,
    unoidl::detail::SourceProviderExpr * rhs)
{
    assert(lhs != nullptr);
    assert(rhs != nullptr);
    bool ok = bool(); // avoid warnings
    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:
            {
                auto tmp = lhs->ival;
                lhs->fval = tmp;
                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:
            {
                auto nTmp = lhs->uval;
                lhs->fval = nTmp;
                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:
            {
                auto tmp = rhs->ival;
                rhs->fval = tmp;
                ok = true;
            }
            break;
        case unoidl::detail::SourceProviderExpr::TYPE_UINT:
            {
                auto tmp = rhs->uval;
                rhs->fval = tmp;
                ok = true;
            }
            break;
        case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
            ok = true;
            break;
        }
        break;
    }
    if (!ok) {
        error(location, yyscanner, u"cannot coerce binary expression arguments"_ustr);
    }
    return ok;
}

unoidl::detail::SourceProviderEntity * findEntity_(
    unoidl::detail::SourceProviderScannerData * data, OUString * name)
{
    assert(data != nullptr);
    assert(name != nullptr);
    OUString n;
    if (!name->startsWith(".", &n)) {
        for (auto 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.emplace(
                              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.emplace(
                      n,
                      unoidl::detail::SourceProviderEntity(
                          unoidl::detail::SourceProviderEntity::KIND_EXTERNAL,
                          ent)).
              first);
        *name = n;
        return &j->second;
    }
    return nullptr;
}

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, bool * typedefed,
    unoidl::detail::SourceProviderType * typedefedType)
{
    //TODO: avoid recursion
    assert(data != nullptr);
    assert(name != nullptr);
    assert(entity != nullptr);
    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 != nullptr) {
            switch (e->kind) {
            case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
                if (e->pad.is()) {
                    break;
                }
                assert(e->entity.is());
                [[fallthrough]];
            case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
                if (e->entity->getSort() == unoidl::Entity::SORT_TYPEDEF) {
                    if (typedefed != nullptr) {
                        *typedefed = true;
                    }
                    if (data->publishedContext
                        && !static_cast<unoidl::TypedefEntity *>(
                            e->entity.get())->isPublished())
                    {
                        error(
                            location, yyscanner,
                            ("type " + *name + " based on unpublished typedef "
                             + n + " used in published context"));
                        return FOUND_ERROR;
                    }
                    OUString t(
                        static_cast<unoidl::TypedefEntity *>(e->entity.get())
                        ->getType());
                    typeNucleus = t;
                    while (typeNucleus.startsWith("[]", &typeNucleus)) {
                        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;
                    }
                    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;
                        }
                        std::u16string_view tmpl(typeNucleus.subView(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, nullptr, &argType))
                                {
                                case FOUND_ERROR:
                                    return FOUND_ERROR;
                                case FOUND_TYPE:
                                    break;
                                case FOUND_ENTITY:
                                    if (argEnt == nullptr) {
                                        error(
                                            location, yyscanner,
                                            (("inconsistent type manager: bad"
                                              " instantiated polymorphic struct"
                                              " type template type argument ")
                                             + argName));
                                        return FOUND_ERROR;
                                    } else {
                                        unoidl::detail::SourceProviderType::Type
                                            argT
                                            = unoidl::detail::SourceProviderType::Type();
                                            // avoid warnings
                                        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());
                                            [[fallthrough]];
                                        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:
                                        case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
                                            argT = unoidl::detail::SourceProviderType::TYPE_INTERFACE;
                                            break;
                                        case unoidl::detail::SourceProviderEntity::KIND_MODULE:
                                            assert(false && "this cannot happen");
                                        }
                                        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.clear();
                    e = findEntity_(data, &n);
                    continue;
                }
                break;
            case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
            case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_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 = std::move(ent);
                }
                break;
            case unoidl::detail::SourceProviderEntity::KIND_MODULE:
                error(
                    location, yyscanner,
                    *name + " is based on module entity " + n);
                return FOUND_ERROR;
            }
        }
        if (!typeNucleus.isEmpty() || rank != 0 || !args.empty()) {
            if (typeNucleus.isEmpty() && e == nullptr) {
                // Found a type name based on an unknown entity:
                *entity = nullptr;
                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 == "unsigned 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 != nullptr);
                    switch (e->kind) {
                    case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
                        if (e->pad.is()) {
                            if (dynamic_cast<unoidl::detail::SourceProviderEnumTypeEntityPad *>(
                                    e->pad.get())
                                != nullptr)
                            {
                                t = unoidl::detail::SourceProviderType(
                                    unoidl::detail::SourceProviderType::TYPE_ENUM,
                                    n, e);
                            } else if (dynamic_cast<unoidl::detail::SourceProviderPlainStructTypeEntityPad *>(
                                           e->pad.get())
                                       != nullptr)
                            {
                                t = unoidl::detail::SourceProviderType(
                                    unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT,
                                    n, e);
                            } else if (dynamic_cast<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
                                           e->pad.get())
                                       != nullptr)
                            {
                                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())
                                       != nullptr)
                            {
                                t = unoidl::detail::SourceProviderType(
                                    unoidl::detail::SourceProviderType::TYPE_EXCEPTION,
                                    n, e);
                            } else if (dynamic_cast<unoidl::detail::SourceProviderInterfaceTypeEntityPad *>(
                                           e->pad.get())
                                       != nullptr)
                            {
                                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());
                        [[fallthrough]];
                    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:
                    case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
                        t = unoidl::detail::SourceProviderType(
                            unoidl::detail::SourceProviderType::TYPE_INTERFACE,
                            n, e);
                        break;
                    case unoidl::detail::SourceProviderEntity::KIND_MODULE:
                        assert(false && "this cannot happen");
                    }
                }
            } else {
                assert(typeNucleus.isEmpty());
                assert(e != nullptr);
                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());
                    [[fallthrough]];
                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 parameters"));
                            return FOUND_ERROR;
                        }
                        t = unoidl::detail::SourceProviderType(n, e, std::move(args));
                        break;
                    }
                    [[fallthrough]];
                case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
                case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_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;
                case unoidl::detail::SourceProviderEntity::KIND_MODULE:
                    assert(false && "this cannot happen");
                }
            }
            if (typedefedType != nullptr) {
                for (std::size_t i = 0; i != rank; ++i) {
                    t = unoidl::detail::SourceProviderType(&t);
                }
                *typedefedType = std::move(t);
                typedefedType->typedefName = *name;
            }
            *entity = nullptr;
            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,
            u"bad instantiated polymorphic struct type argument"_ustr);
        return false;
    case unoidl::detail::SourceProviderType::TYPE_SEQUENCE:
        return checkTypeArgument(location, yyscanner, type.subtypes.front());
    default:
        return true;
    }
}

bool checkInstantiatedPolymorphicStructTypeArgument(
    unoidl::detail::SourceProviderType const & type, OUString const & name)
{
    if (type.type
        == unoidl::detail::SourceProviderType::TYPE_INSTANTIATED_POLYMORPHIC_STRUCT)
    {
        for (auto & i: type.subtypes) {
            if (checkInstantiatedPolymorphicStructTypeArgument(i, name)
                || i.getName() == name) // no need to worry about typedef
            {
                return true;
            }
        }
    }
    return false;
}

std::vector<OUString> annotations(bool deprecated) {
    std::vector<OUString> ann;
    if (deprecated) {
        ann.push_back(u"deprecated"_ustr);
    }
    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);
      OUString name(convertToFullName(data, $2));
      data->modules.push_back(name);
      std::pair<std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator, bool> p(
          data->entities.emplace(
                  name,
                  unoidl::detail::SourceProviderEntity(
                      unoidl::detail::SourceProviderEntity::KIND_MODULE)));
      if (!p.second
          && (p.first->second.kind
              != unoidl::detail::SourceProviderEntity::KIND_MODULE))
      {
          error(@2, yyscanner, "multiple entities named " + name);
          YYERROR;
      }
  }
  '{' definitions '}' ';' { yyget_extra(yyscanner)->modules.pop_back(); }
;

enumDefn:
  deprecated_opt published_opt TOK_ENUM identifier
  {
      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
      data->publishedContext = $2;
      convertToCurrentName(data, $4);
      if (!data->entities.emplace(
                  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 != nullptr);
      ent->entity = new unoidl::EnumTypeEntity(
          pad->isPublished(), std::move(pad->members), annotations($1));
      ent->pad.clear();
      clearCurrentState(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.emplace_back(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.emplace_back(id, v, annotations($1));
  }
;

plainStructDefn:
  deprecated_opt published_opt TOK_STRUCT identifier singleInheritance_opt
  {
      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
      data->publishedContext = $2;
      convertToCurrentName(data, $4);
      OUString baseName;
      rtl::Reference<unoidl::PlainStructTypeEntity> baseEnt;
      if ($5 != nullptr) {
          baseName = convertName($5);
          unoidl::detail::SourceProviderEntity const * p;
          if (findEntity(
                  @5, yyscanner, data, false, &baseName, &p, nullptr, nullptr)
              == FOUND_ERROR)
          {
              YYERROR;
          }
          if (p == nullptr || !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 ($2 && !baseEnt->isPublished()) {
              error(
                  @5, yyscanner,
                  ("published plain struct type " + data->currentName + " base "
                   + baseName + " is unpublished"));
              YYERROR;
          }
      }
      if (!data->entities.emplace(
                  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 != nullptr);
      ent->entity = new unoidl::PlainStructTypeEntity(
          pad->isPublished(), pad->baseName, std::move(pad->members), annotations($1));
      ent->pad.clear();
      clearCurrentState(data);
  }
;

polymorphicStructTemplateDefn:
  deprecated_opt published_opt TOK_STRUCT identifier '<'
  {
      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
      data->publishedContext = $2;
      convertToCurrentName(data, $4);
      if (!data->entities.emplace(
                  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 != nullptr);
      ent->entity = new unoidl::PolymorphicStructTypeTemplateEntity(
          pad->isPublished(), std::move(pad->typeParameters), std::move(pad->members),
          annotations($1));
      ent->pad.clear();
      clearCurrentState(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 (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));
      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);
      data->publishedContext = $2;
      convertToCurrentName(data, $4);
      OUString baseName;
      rtl::Reference<unoidl::ExceptionTypeEntity> baseEnt;
      if ($5 != nullptr) {
          baseName = convertName($5);
          unoidl::detail::SourceProviderEntity const * p;
          if (findEntity(
                  @5, yyscanner, data, false, &baseName, &p, nullptr, nullptr)
              == FOUND_ERROR)
          {
              YYERROR;
          }
          if (p == nullptr || !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 ($2 && !baseEnt->isPublished()) {
              error(
                  @5, yyscanner,
                  ("published exception type " + data->currentName + " base "
                   + baseName + " is unpublished"));
              YYERROR;
          }
      }
      if (!data->entities.emplace(
                  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 != nullptr);
      ent->entity = new unoidl::ExceptionTypeEntity(
          pad->isPublished(), pad->baseName, std::move(pad->members), annotations($1));
      ent->pad.clear();
      clearCurrentState(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 (t.type != unoidl::detail::SourceProviderType::TYPE_PARAMETER
          && t.getName() == data->currentName) // no need to worry about typedef
      {
          error(
              @2, yyscanner,
              ("struct/exception type " + data->currentName + " direct member "
               + id + " has same type as the type itself"));
          YYERROR;
      }
      if (checkInstantiatedPolymorphicStructTypeArgument(t, data->currentName))
      {
          error(
              @2, yyscanner,
              ("struct/exception type " + data->currentName + " direct member "
               + id
               + (" has instantiated polymorphic struct type that uses the type"
                  " itself as an argument")));
          YYERROR;
      }
      if (nameHasSameIdentifierAs(data->currentName, id)) {
          error(
              @3, yyscanner,
              ("struct/exception type " + data->currentName + " direct member "
               + id + " has same unqualified identifier 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 != nullptr) {
          for (const auto & i: p1->members) {
              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 (auto 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 (auto & i: baseEnt->getDirectMembers()) {
                      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, nullptr,
                          nullptr)
                      == FOUND_ERROR)
                  {
                      YYERROR;
                  }
                  if (p == nullptr || !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.emplace_back(id, t.getName(), annotations($1));
      } else {
          unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *
              p2 = dynamic_cast<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
                  ent->pad.get());
          if (p2 != nullptr) {
              for (const auto & i: p2->members) {
                  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.emplace_back(
                  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 != nullptr);
              for (const auto & i: p3->members) {
                  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 (auto 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 (auto & i: baseEnt->getDirectMembers()) {
                          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,
                              nullptr, nullptr)
                          == FOUND_ERROR)
                      {
                          YYERROR;
                      }
                      if (p == nullptr || !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.emplace_back(id, t.getName(), annotations($1));
          }
      }
  }
;

interfaceDefn:
  deprecated_opt published_opt TOK_INTERFACE identifier singleInheritance_opt
  {
      unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
      data->publishedContext = $2;
      convertToCurrentName(data, $4);
      OUString baseName;
      rtl::Reference<unoidl::InterfaceTypeEntity> baseEnt;
      if ($5 != nullptr) {
          baseName = convertName($5);
          unoidl::detail::SourceProviderEntity const * p;
          if (findEntity(
                  @5, yyscanner, data, true, &baseName, &p, nullptr, nullptr)
              == FOUND_ERROR)
          {
              YYERROR;
          }
          if (p == nullptr || !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());
          if ($2 && !baseEnt->isPublished()) {
              error(
                  @5, yyscanner,
                  ("published interface type " + data->currentName
                   + " direct base " + baseName + " is unpublished"));
              YYERROR;
          }
      }
      std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator i(
          data->entities.find(data->currentName));
      if (i != data->entities.end()) {
          switch (i->second.kind) {
          case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
              break;
          case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
              if (!$2) {
                  error(
                      @4, yyscanner,
                      ("unpublished interface type " + data->currentName
                       + " has been declared published"));
                  YYERROR;
              }
              break;
          default:
              error(
                  @4, yyscanner,
                  "multiple entities named " + data->currentName);
              YYERROR;
              break;
          }
      }
      rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad> pad(
          new unoidl::detail::SourceProviderInterfaceTypeEntityPad(
              $2, baseEnt.is()));
      if (baseEnt.is()
          && !pad->addDirectBase(
              @4, yyscanner, data,
              unoidl::detail::SourceProviderInterfaceTypeEntityPad::DirectBase(
                  baseName, baseEnt, std::vector<OUString>()),
              false))
      {
          YYERROR;
      }
      data->entities[data->currentName] = unoidl::detail::SourceProviderEntity(
          pad);
  }
  '{' interfaceMembers '}' ';'
  {
      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 != nullptr);
      if (pad->directMandatoryBases.empty()
          && data->currentName != "com.sun.star.uno.XInterface")
      {
          OUString base(u".com.sun.star.uno.XInterface"_ustr);
          unoidl::detail::SourceProviderEntity const * p;
          if (findEntity(@4, yyscanner, data, true, &base, &p, nullptr, nullptr)
              == FOUND_ERROR)
          {
              YYERROR;
          }
          if (p == nullptr || !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;
          }
          if (!pad->addDirectBase(
                  @3, yyscanner, data,
                  unoidl::detail::SourceProviderInterfaceTypeEntityPad::DirectBase(
                      base,
                      static_cast<unoidl::InterfaceTypeEntity *>(
                          p->entity.get()),
                      std::vector<OUString>()),
                  false))
          {
              YYERROR;
          }
      }
      std::vector<unoidl::AnnotatedReference> mbases;
      for (auto & i: pad->directMandatoryBases) {
          mbases.emplace_back(i.name, std::move(i.annotations));
      }
      std::vector<unoidl::AnnotatedReference> obases;
--> --------------------

--> maximum size reached

--> --------------------

[ Verzeichnis aufwärts0.28unsichere Verbindung  Übersetzung europäischer Sprachen durch Browser  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge