summaryrefslogtreecommitdiff
path: root/idlc/source/parser.y
diff options
context:
space:
mode:
Diffstat (limited to 'idlc/source/parser.y')
-rw-r--r--idlc/source/parser.y3292
1 files changed, 3292 insertions, 0 deletions
diff --git a/idlc/source/parser.y b/idlc/source/parser.y
new file mode 100644
index 000000000000..8da9c7ad63b5
--- /dev/null
+++ b/idlc/source/parser.y
@@ -0,0 +1,3292 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+/*
+ * parser.yy - BISON grammar for IDLC 1.0
+ */
+
+%{
+#include <string.h>
+
+#ifndef _IDLC_IDLC_HXX_
+#include <idlc/idlc.hxx>
+#endif
+#ifndef _IDLC_ERRORHANDLER_HXX_
+#include <idlc/errorhandler.hxx>
+#endif
+#ifndef _IDLC_FEHELPER_HXX_
+#include <idlc/fehelper.hxx>
+#endif
+#ifndef _IDLC_EXPRESSION_HXX_
+#include <idlc/astexpression.hxx>
+#endif
+#ifndef _IDLC_ASTCONSTANTS_HXX_
+#include <idlc/astconstants.hxx>
+#endif
+#ifndef _IDLC_ASTCONSTANT_HXX_
+#include <idlc/astconstant.hxx>
+#endif
+#ifndef _IDLC_ASTARRAY_HXX_
+#include <idlc/astarray.hxx>
+#endif
+#ifndef _IDLC_ASTBASETYPE_HXX_
+#include <idlc/astbasetype.hxx>
+#endif
+#ifndef _IDLC_ASTTYPEDEF_HXX_
+#include <idlc/asttypedef.hxx>
+#endif
+#ifndef _IDLC_ASTEXCEPTION_HXX_
+#include <idlc/astexception.hxx>
+#endif
+#ifndef _IDLC_ASTMEMBER_HXX_
+#include <idlc/astmember.hxx>
+#endif
+#ifndef _IDLC_ASTENUM_HXX_
+#include <idlc/astenum.hxx>
+#endif
+#ifndef _IDLC_ASTSEQUENCE_HXX_
+#include <idlc/astsequence.hxx>
+#endif
+#ifndef _IDLC_ASTATTRIBUTE_HXX_
+#include <idlc/astattribute.hxx>
+#endif
+#ifndef _IDLC_ASTOPERATION_HXX_
+#include <idlc/astoperation.hxx>
+#endif
+#ifndef _IDLC_ASTPARAMETER_HXX_
+#include <idlc/astparameter.hxx>
+#endif
+#ifndef _IDLC_ASTINTERFACEMEMBER_HXX_
+#include <idlc/astinterfacemember.hxx>
+#endif
+#ifndef _IDLC_ASTSERVICEMEMBER_HXX_
+#include <idlc/astservicemember.hxx>
+#endif
+#ifndef _IDLC_ASTOBSERVES_HXX_
+#include <idlc/astobserves.hxx>
+#endif
+#ifndef _IDLC_ASTNEEDS_HXX_
+#include <idlc/astneeds.hxx>
+#endif
+#ifndef _IDLC_ASTUNION_HXX_
+#include <idlc/astunion.hxx>
+#endif
+#include "idlc/aststructinstance.hxx"
+
+#include "attributeexceptions.hxx"
+
+#include "rtl/strbuf.hxx"
+
+#include <algorithm>
+#include <vector>
+
+using namespace ::rtl;
+
+#define YYDEBUG 1
+#define YYERROR_VERBOSE 1
+
+extern int yylex(void);
+void yyerror(char const *);
+
+void checkIdentifier(::rtl::OString* id)
+{
+ static short check = 0;
+ if (check == 0) {
+ if (idlc()->getOptions()->isValid("-cid"))
+ check = 1;
+ else
+ check = 2;
+ }
+
+ if ( id->indexOf('_') >= 0 )
+ if ( (id->pData->buffer[0] >= 97 && id->pData->buffer[0] <= 122)
+ || id->pData->buffer[0] == '_') {
+ if (check == 1) {
+ ::rtl::OStringBuffer msg(25 + id->getLength());
+ msg.append("mismatched identifier '");
+ msg.append(*id);
+ msg.append("'");
+ idlc()->error()->syntaxError(idlc()->getParseState(),
+ idlc()->getLineNumber(),
+ msg.getStr());
+ }
+ else
+ idlc()->error()->warning0(WIDL_WRONG_NAMING_CONV, id->getStr());
+ }
+}
+
+void reportDoubleMemberDeclarations(
+ AstInterface::DoubleMemberDeclarations const & doubleMembers)
+{
+ for (AstInterface::DoubleMemberDeclarations::const_iterator i(
+ doubleMembers.begin());
+ i != doubleMembers.end(); ++i)
+ {
+ idlc()->error()->error2(EIDL_DOUBLE_MEMBER, i->first, i->second);
+ }
+}
+
+void addInheritedInterface(
+ AstInterface * ifc, rtl::OString const & name, bool optional,
+ rtl::OUString const & documentation)
+{
+ AstDeclaration * decl = ifc->lookupByName(name);
+ AstDeclaration const * resolved = resolveTypedefs(decl);
+ if (resolved != 0 && resolved->getNodeType() == NT_interface) {
+ if (idlc()->error()->checkPublished(decl)) {
+ if (!static_cast< AstInterface const * >(resolved)->isDefined()) {
+ idlc()->error()->inheritanceError(
+ NT_interface, &ifc->getScopedName(), decl);
+ } else {
+ AstInterface::DoubleDeclarations doubleDecls(
+ ifc->checkInheritedInterfaceClashes(
+ static_cast< AstInterface const * >(resolved),
+ optional));
+ if (doubleDecls.interfaces.empty()
+ && doubleDecls.members.empty())
+ {
+ ifc->addInheritedInterface(
+ static_cast< AstType * >(decl), optional,
+ documentation);
+ } else {
+ for (AstInterface::DoubleInterfaceDeclarations::iterator i(
+ doubleDecls.interfaces.begin());
+ i != doubleDecls.interfaces.end(); ++i)
+ {
+ idlc()->error()->error1(
+ EIDL_DOUBLE_INHERITANCE, *i);
+ }
+ reportDoubleMemberDeclarations(doubleDecls.members);
+ }
+ }
+ }
+ } else {
+ idlc()->error()->lookupError(
+ EIDL_INTERFACEMEMBER_LOOKUP, name, scopeAsDecl(ifc));
+ }
+}
+
+AstDeclaration const * createNamedType(
+ rtl::OString const * scopedName, DeclList const * typeArgs)
+{
+ AstDeclaration * decl = idlc()->scopes()->topNonNull()->lookupByName(
+ *scopedName);
+ AstDeclaration const * resolved = resolveTypedefs(decl);
+ if (decl == 0) {
+ idlc()->error()->lookupError(*scopedName);
+ } else if (!idlc()->error()->checkPublished(decl)) {
+ decl = 0;
+ } else if (resolved->getNodeType() == NT_struct) {
+ if (static_cast< AstStruct const * >(resolved)->getTypeParameterCount()
+ != (typeArgs == 0 ? 0 : typeArgs->size()))
+ {
+ idlc()->error()->error0(EIDL_WRONG_NUMBER_OF_TYPE_ARGUMENTS);
+ decl = 0;
+ } else if (typeArgs != 0) {
+ AstScope * global = idlc()->scopes()->bottom();
+ AstDeclaration * inst = new AstStructInstance(
+ static_cast< AstType * >(decl), typeArgs, global);
+ decl = global->addDeclaration(inst);
+ if (decl != inst) {
+ delete inst;
+ }
+ }
+ } else if (decl->isType()) {
+ if (typeArgs != 0) {
+ idlc()->error()->error0(EIDL_WRONG_NUMBER_OF_TYPE_ARGUMENTS);
+ decl = 0;
+ }
+ } else {
+ idlc()->error()->noTypeError(decl);
+ decl = 0;
+ }
+ delete scopedName;
+ delete typeArgs;
+ return decl;
+}
+
+bool includes(AstDeclaration const * type1, AstDeclaration const * type2) {
+ OSL_ASSERT(type2 != 0);
+ if (type1 != 0) {
+ if (type1->getNodeType() == NT_instantiated_struct) {
+ AstStructInstance const * inst
+ = static_cast< AstStructInstance const * >(type1);
+ if (inst->getTypeTemplate() == type2) {
+ return true;
+ }
+ for (DeclList::const_iterator i(inst->getTypeArgumentsBegin());
+ i != inst->getTypeArgumentsEnd(); ++i)
+ {
+ if (includes(*i, type2)) {
+ return true;
+ }
+ }
+ } else if (type1 == type2) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Suppress any warnings from generated code:
+#if defined __GNUC__
+#pragma GCC system_header
+#elif defined __SUNPRO_CC
+#pragma disable_warn
+#elif defined _MSC_VER
+#pragma warning(push, 1)
+#pragma warning(disable: 4273 4701 4706)
+#endif
+%}
+/*
+ * Declare the type of values in the grammar
+ */
+%union {
+ ExprType etval; /* Expression type */
+ AstDeclaration* dclval; /* Declaration */
+ AstDeclaration const * cdclval;
+ DeclList * dclsval;
+ AstExpression* exval; /* expression value */
+ ExprList* exlval; /* expression list value */
+ FeDeclarator* fdval; /* declarator value */
+ FeDeclList* dlval; /* declarator list value */
+ FeInheritanceHeader* ihval; /* inheritance header value */
+ ::rtl::OString* sval; /* OString value */
+ std::vector< rtl::OString > * svals;
+ sal_Char* strval; /* sal_Char* value */
+ sal_Bool bval; /* sal_Boolean* value */
+ sal_Int64 ival; /* sal_Int64 value */
+ sal_uInt64 uval; /* sal_uInt64 value */
+ sal_uInt32 ulval; /* sal_uInt32 value */
+ double dval; /* double value */
+ float fval; /* float value */
+ StringList* slval; /* StringList value */
+ LabelList* llval; /* LabelList value */
+ AstUnionLabel* lbval; /* union label value */
+ AstMember* mval; /* member value */
+ AttributeExceptions::Part attexcpval;
+ AttributeExceptions attexcval;
+}
+
+/*
+ * Token types: These are returned by the lexer
+ */
+
+%token <sval> IDL_IDENTIFIER
+%token IDL_ATTRIBUTE
+%token IDL_BOUND
+%token IDL_CASE
+%token IDL_CONST
+%token IDL_CONSTANTS
+%token IDL_CONSTRAINED
+%token IDL_DEFAULT
+%token IDL_ENUM
+%token IDL_EXCEPTION
+%token IDL_INTERFACE
+%token IDL_MAYBEAMBIGUOUS
+%token IDL_MAYBEDEFAULT
+%token IDL_MAYBEVOID
+%token IDL_MODULE
+%token IDL_NEEDS
+%token IDL_OBSERVES
+%token IDL_OPTIONAL
+%token IDL_PROPERTY
+%token IDL_RAISES
+%token IDL_READONLY
+%token IDL_REMOVEABLE
+%token IDL_SERVICE
+%token IDL_SEQUENCE
+%token IDL_SINGLETON
+%token IDL_STRUCT
+%token IDL_SWITCH
+%token IDL_TYPEDEF
+%token IDL_TRANSIENT
+%token IDL_UNION
+
+%token IDL_ANY
+%token IDL_CHAR
+%token IDL_BOOLEAN
+%token IDL_BYTE
+%token IDL_DOUBLE
+%token IDL_FLOAT
+%token IDL_HYPER
+%token IDL_LONG
+%token IDL_SHORT
+%token IDL_VOID
+%token IDL_STRING
+%token IDL_TYPE
+%token IDL_UNSIGNED
+
+%token IDL_TRUE
+%token IDL_FALSE
+
+%token IDL_IN
+%token IDL_OUT
+%token IDL_INOUT
+%token IDL_ONEWAY
+
+%token IDL_GET
+%token IDL_SET
+
+%token IDL_PUBLISHED
+
+%token IDL_ELLIPSIS
+
+%token <strval> IDL_LEFTSHIFT
+%token <strval> IDL_RIGHTSHIFT
+%token <strval> IDL_SCOPESEPARATOR
+
+%token <ival> IDL_INTEGER_LITERAL
+%token <uval> IDL_INTEGER_ULITERAL
+%token <dval> IDL_FLOATING_PT_LITERAL
+
+/*
+ * These are production names:
+ */
+%type <dclval> type_dcl const_dcl
+%type <dclval> array_declarator
+%type <dclval> exception_name
+%type <cdclval> array_type constructed_type_spec enum_type op_type_spec
+%type <cdclval> sequence_type_spec simple_type_spec struct_type switch_type_spec
+%type <cdclval> template_type_spec type_spec union_type
+%type <cdclval> fundamental_type type_arg type_or_parameter
+%type <dclsval> opt_raises raises exception_list
+%type <attexcpval> opt_attribute_get_raises attribute_get_raises
+%type <attexcpval> opt_attribute_set_raises attribute_set_raises
+%type <dclsval> opt_type_args type_args
+
+%type <sval> identifier
+%type <sval> interface_decl
+%type <sval> scoped_name inheritance_spec
+%type <slval> scoped_names at_least_one_scoped_name
+
+%type <etval> const_type integer_type char_type boolean_type
+%type <etval> floating_pt_type any_type signed_int string_type
+%type <etval> unsigned_int base_type_spec byte_type type_type
+
+%type <exval> expression const_expr or_expr xor_expr and_expr
+%type <exval> add_expr mult_expr unary_expr primary_expr shift_expr
+%type <exval> literal positive_int_expr array_dim
+
+%type <exlval> at_least_one_array_dim array_dims
+
+%type <fdval> declarator simple_declarator complex_declarator
+%type <dlval> declarators at_least_one_declarator
+
+%type <ihval> exception_header structure_header interfaceheader
+
+%type <ulval> flag_header opt_attrflags opt_attrflag operation_head
+%type <ulval> direction service_interface_header service_service_header
+
+%type <llval> case_labels at_least_one_case_label
+%type <lbval> case_label
+%type <mval> element_spec
+
+%type <bval> optional_inherited_interface opt_rest opt_service_body
+
+%type <attexcval> opt_attribute_block attribute_block_rest opt_attribute_raises
+
+%type <svals> opt_type_params type_params
+
+%%
+/*
+ * Grammar start here
+ */
+start : definitions;
+
+definitions :
+ definition definitions
+ | /* EMPTY */
+ ;
+
+definition :
+ opt_published publishable_definition
+ | module_dcl
+ {
+ idlc()->setParseState(PS_ModuleDeclSeen);
+ }
+ ';'
+ {
+ idlc()->setParseState(PS_NoState);
+ }
+ | error ';'
+ {
+ yyerror("definitions");
+ yyerrok;
+ }
+ ;
+
+opt_published:
+ IDL_PUBLISHED { idlc()->setPublished(true); }
+ | /* empty */ { idlc()->setPublished(false); }
+ ;
+
+publishable_definition:
+ type_dcl
+ {
+ idlc()->setParseState(PS_TypeDeclSeen);
+ }
+ ';'
+ {
+ idlc()->setParseState(PS_NoState);
+ }
+ | const_dcl
+ {
+ idlc()->setParseState(PS_ConstantDeclSeen);
+ }
+ ';'
+ {
+ idlc()->setParseState(PS_NoState);
+ }
+ | exception_dcl
+ {
+ idlc()->setParseState(PS_ExceptionDeclSeen);
+ }
+ ';'
+ {
+ idlc()->setParseState(PS_NoState);
+ }
+ | interface
+ {
+ idlc()->setParseState(PS_InterfaceDeclSeen);
+ }
+ ';'
+ {
+ idlc()->setParseState(PS_NoState);
+ }
+ | service_dcl
+ {
+ idlc()->setParseState(PS_ServiceDeclSeen);
+ }
+ ';'
+ {
+ idlc()->setParseState(PS_NoState);
+ }
+ | singleton_dcl
+ {
+ idlc()->setParseState(PS_SingletonDeclSeen);
+ }
+ ';'
+ {
+ idlc()->setParseState(PS_NoState);
+ }
+ | constants_dcl
+ {
+ idlc()->setParseState(PS_ConstantsDeclSeen);
+ }
+ ';'
+ {
+ idlc()->setParseState(PS_NoState);
+ }
+ ;
+
+module_dcl :
+ IDL_MODULE
+ {
+ idlc()->setParseState(PS_ModuleSeen);
+ idlc()->setPublished(false);
+ }
+ identifier
+ {
+ idlc()->setParseState(PS_ModuleIDSeen);
+ checkIdentifier($3);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstModule* pModule = NULL;
+ AstDeclaration* pExists = NULL;
+
+ if ( pScope )
+ {
+ pModule = new AstModule(*$3, pScope);
+ if( (pExists = pScope->lookupForAdd(pModule)) )
+ {
+ pExists->setInMainfile(idlc()->isInMainFile());
+ pExists->setFileName(pModule->getFileName());
+ if (pExists->isPredefined())
+ {
+ pExists->setPredefined(false);
+ if (pExists->getDocumentation().getLength() == 0 &&
+ pModule->getDocumentation().getLength() > 0)
+ {
+ pExists->setDocumentation(pModule->getDocumentation());
+ }
+ }
+ delete(pModule);
+ pModule = (AstModule*)pExists;
+ } else
+ {
+ pScope->addDeclaration(pModule);
+ }
+ idlc()->scopes()->push(pModule);
+ }
+ delete $3;
+ }
+ '{'
+ {
+ idlc()->setParseState(PS_ModuleSqSeen);
+ }
+ definitions
+ {
+ idlc()->setParseState(PS_ModuleBodySeen);
+ }
+ '}'
+ {
+ idlc()->setParseState(PS_ModuleQsSeen);
+ /*
+ * Finished with this module - pop it from the scope stack
+ */
+ idlc()->scopes()->pop();
+ }
+ ;
+
+interface :
+ interface_dcl
+ | forward_dcl
+ ;
+
+interface_decl :
+ IDL_INTERFACE
+ {
+ idlc()->setParseState(PS_InterfaceSeen);
+ }
+ identifier
+ {
+ idlc()->setParseState(PS_InterfaceIDSeen);
+ checkIdentifier($3);
+ $$ = $3;
+ }
+ ;
+
+forward_dcl :
+ interface_decl
+ {
+ idlc()->setParseState(PS_ForwardDeclSeen);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstInterface* pForward = NULL;
+ AstDeclaration* pDecl = NULL;
+
+ /*
+ * Make a new forward interface node and add it to its enclosing scope
+ */
+ if ( pScope && $1 )
+ {
+ pForward = new AstInterface(*$1, NULL, pScope);
+
+ if ( pDecl = pScope->lookupByName(pForward->getScopedName()) )
+ {
+ if ( (pDecl != pForward) &&
+ (pDecl->getNodeType() == NT_interface) )
+ {
+ delete pForward;
+ } else
+ {
+ idlc()->error()->error2(EIDL_REDEF_SCOPE, scopeAsDecl(pScope), pDecl);
+ }
+ } else
+ {
+ /*
+ * Add the interface to its definition scope
+ */
+ pScope->addDeclaration(pForward);
+ }
+ }
+ delete $1;
+ }
+ ;
+
+interface_dcl :
+ interfaceheader
+ {
+ idlc()->setParseState(PS_InterfaceHeadSeen);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstInterface* pInterface = NULL;
+ AstInterface* pForward = NULL;
+ AstDeclaration* pDecl = NULL;
+
+ /*
+ * Make a new interface node and add it to its enclosing scope
+ */
+ if ( pScope && $1 )
+ {
+ pInterface = new AstInterface(
+ *$1->getName(),
+ static_cast< AstInterface * >($1->getInherits()), pScope);
+ if ( pInterface &&
+ (pDecl = pScope->lookupByName(pInterface->getScopedName())) )
+ {
+ /*
+ * See if we're defining a forward declared interface.
+ */
+ if (pDecl->getNodeType() == NT_interface)
+ {
+ pForward = (AstInterface*)pDecl;
+ if ( !pForward->isDefined() )
+ {
+ /*
+ * Check if redefining in same scope
+ */
+ if ( pForward->getScope() != pScope )
+ {
+ if ( pForward->getScopedName() != pInterface->getScopedName() )
+ {
+ idlc()->error()->error3(EIDL_SCOPE_CONFLICT,
+ pInterface, pForward, scopeAsDecl(pScope));
+ }
+ }
+ else if ( !pInterface->isPublished()
+ && pForward->isPublished() )
+ {
+ idlc()->error()->error0(EIDL_PUBLISHED_FORWARD);
+ }
+ /*
+ * All OK, set full definition
+ */
+ else
+ {
+ pForward->forwardDefined(*pInterface);
+ delete pInterface;
+ pInterface = pForward;
+ }
+ } else {
+ // special handling for XInterface because it is predefined
+ if ( pForward->isPredefined() &&
+ pForward->getScopedName() == "com::sun::star::uno::XInterface")
+ {
+ /* replace the predefined XInterface */
+ *pForward = *pInterface;
+ delete pInterface;
+ pInterface = pForward;
+ }
+
+ }
+ }
+ } else
+ {
+ /*
+ * Add the interface to its definition scope
+ */
+ pScope->addDeclaration(pInterface);
+ }
+ }
+ /*
+ * Push it on the scope stack
+ */
+ idlc()->scopes()->push(pInterface);
+ delete($1);
+ }
+ '{'
+ {
+ idlc()->setParseState(PS_InterfaceSqSeen);
+ }
+ exports
+ {
+ AstInterface * ifc = static_cast< AstInterface * >(
+ idlc()->scopes()->topNonNull());
+ if (!ifc->hasMandatoryInheritedInterfaces()
+ && ifc->getScopedName() != "com::sun::star::uno::XInterface")
+ {
+ addInheritedInterface(
+ ifc, rtl::OString("::com::sun::star::uno::XInterface"), false,
+ rtl::OUString());
+ }
+ ifc->setDefined();
+ idlc()->setParseState(PS_InterfaceBodySeen);
+ }
+ '}'
+ {
+ idlc()->setParseState(PS_InterfaceQsSeen);
+ /*
+ * Done with this interface - pop it off the scopes stack
+ */
+ idlc()->scopes()->pop();
+ }
+ | error '}'
+ {
+ yyerror("interface definition");
+ yyerrok;
+ }
+ ;
+
+interfaceheader :
+ interface_decl inheritance_spec
+ {
+ idlc()->setParseState(PS_InheritSpecSeen);
+
+ $$ = new FeInheritanceHeader(NT_interface, $1, $2, 0);
+ delete $2;
+ }
+ ;
+
+inheritance_spec :
+ ':'
+ {
+ idlc()->setParseState(PS_InheritColonSeen);
+ }
+ scoped_name
+ {
+ $$ = $3;
+ }
+ | /* EMPTY */
+ {
+ $$ = NULL;
+ }
+ ;
+
+exports :
+ exports export
+ | /* EMPTY */
+ ;
+
+export :
+ attribute
+ {
+ idlc()->setParseState(PS_AttributeDeclSeen);
+ }
+ ';'
+ {
+ idlc()->setParseState(PS_NoState);
+ }
+ | operation
+ {
+ idlc()->setParseState(PS_OperationDeclSeen);
+ }
+ ';'
+ {
+ idlc()->setParseState(PS_NoState);
+ }
+ | interface_inheritance_decl
+ {
+ idlc()->setParseState(PS_InterfaceInheritanceDeclSeen);
+ }
+ ';'
+ {
+ idlc()->setParseState(PS_NoState);
+ }
+ ;
+
+attribute :
+ flag_header
+ simple_type_spec
+ {
+ idlc()->setParseState(PS_AttrTypeSeen);
+ }
+ simple_declarator
+ {
+ idlc()->setParseState(PS_AttrCompleted);
+ if (($1 & ~(AF_BOUND | AF_READONLY)) != AF_ATTRIBUTE) {
+ idlc()->error()->flagError(EIDL_BAD_ATTRIBUTE_FLAGS, $1);
+ }
+ AstInterface * scope = static_cast< AstInterface * >(
+ idlc()->scopes()->top());
+ AstAttribute * attr = new AstAttribute(
+ $1, $4->compose($2), $4->getName(), scope);
+ delete $4;
+ AstInterface::DoubleMemberDeclarations doubleMembers(
+ scope->checkMemberClashes(attr));
+ if (doubleMembers.empty()) {
+ scope->addMember(attr);
+ } else {
+ reportDoubleMemberDeclarations(doubleMembers);
+ }
+ idlc()->scopes()->push(attr);
+ }
+ opt_attribute_block
+ {
+ static_cast< AstAttribute * >(idlc()->scopes()->top())->setExceptions(
+ $6.get.documentation, $6.get.exceptions, $6.set.documentation,
+ $6.set.exceptions);
+ delete $6.get.documentation;
+ delete $6.get.exceptions;
+ delete $6.set.documentation;
+ delete $6.set.exceptions;
+ idlc()->scopes()->pop();
+ }
+ ;
+
+flag_header :
+ '[' opt_attrflags ']'
+ {
+ idlc()->setParseState(PS_FlagHeaderSeen);
+ $$ = $2;
+ }
+ ;
+
+opt_attrflags :
+ opt_attrflags ',' opt_attrflag
+ {
+ if ( ($1 & $3) == $3 )
+ idlc()->error()->flagError(EIDL_DEFINED_ATTRIBUTEFLAG, $3);
+
+ $$ = $1 | $3;
+ }
+ | opt_attrflag
+ {
+ $$ = $1;
+ }
+ ;
+
+opt_attrflag :
+ IDL_ATTRIBUTE
+ {
+ idlc()->setParseState(PS_AttrSeen);
+ $$ = AF_ATTRIBUTE;
+ }
+ | IDL_PROPERTY
+ {
+ idlc()->setParseState(PS_PropertySeen);
+ $$ = AF_PROPERTY;
+ }
+ | IDL_READONLY
+ {
+ idlc()->setParseState(PS_ReadOnlySeen);
+ $$ = AF_READONLY;
+ }
+ | IDL_OPTIONAL
+ {
+ idlc()->setParseState(PS_OptionalSeen);
+ $$ = AF_OPTIONAL;
+ }
+ | IDL_MAYBEVOID
+ {
+ idlc()->setParseState(PS_MayBeVoidSeen);
+ $$ = AF_MAYBEVOID;
+ }
+ | IDL_BOUND
+ {
+ idlc()->setParseState(PS_BoundSeen);
+ $$ = AF_BOUND;
+ }
+ | IDL_CONSTRAINED
+ {
+ idlc()->setParseState(PS_ConstrainedSeen);
+ $$ = AF_CONSTRAINED;
+ }
+ | IDL_TRANSIENT
+ {
+ idlc()->setParseState(PS_TransientSeen);
+ $$ = AF_TRANSIENT;
+ }
+ | IDL_MAYBEAMBIGUOUS
+ {
+ idlc()->setParseState(PS_MayBeAmbigiousSeen);
+ $$ = AF_MAYBEAMBIGUOUS;
+ }
+ | IDL_MAYBEDEFAULT
+ {
+ idlc()->setParseState(PS_MayBeDefaultSeen);
+ $$ = AF_MAYBEDEFAULT;
+ }
+ | IDL_REMOVEABLE
+ {
+ idlc()->setParseState(PS_RemoveableSeen);
+ $$ = AF_REMOVEABLE;
+ }
+ | error ']'
+ {
+ yyerror("unknown property|attribute flag");
+ yyerrok;
+ }
+ ;
+
+opt_attribute_block:
+ '{' attribute_block_rest { $$ = $2; }
+ | /* empty */
+ {
+ $$.get.documentation = 0;
+ $$.get.exceptions = 0;
+ $$.set.documentation = 0;
+ $$.set.exceptions = 0;
+ }
+ ;
+
+attribute_block_rest:
+ opt_attribute_raises '}'
+ | error '}'
+ {
+ yyerror("bad attribute raises block");
+ yyerrok;
+ $$.get.documentation = 0;
+ $$.get.exceptions = 0;
+ $$.set.documentation = 0;
+ $$.set.exceptions = 0;
+ }
+ ;
+
+opt_attribute_raises:
+ attribute_get_raises
+ opt_attribute_set_raises
+ {
+ $$.get = $1;
+ $$.set = $2;
+ }
+ | attribute_set_raises
+ opt_attribute_get_raises
+ {
+ $$.get = $2;
+ $$.set = $1;
+ }
+ | /* empty */
+ {
+ $$.get.documentation = 0;
+ $$.get.exceptions = 0;
+ $$.set.documentation = 0;
+ $$.set.exceptions = 0;
+ }
+ ;
+
+opt_attribute_get_raises:
+ attribute_get_raises
+ | /* empty */ { $$.documentation = 0; $$.exceptions = 0; }
+ ;
+
+attribute_get_raises:
+ IDL_GET raises ';'
+ {
+ $$.documentation = new rtl::OUString(
+ rtl::OStringToOUString(
+ idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8));
+ $$.exceptions = $2;
+ }
+ ;
+
+opt_attribute_set_raises:
+ attribute_set_raises
+ | /* empty */ { $$.documentation = 0; $$.exceptions = 0; }
+ ;
+
+attribute_set_raises:
+ IDL_SET
+ {
+ if (static_cast< AstAttribute * >(idlc()->scopes()->top())->
+ isReadonly())
+ {
+ idlc()->error()->error0(EIDL_READONLY_ATTRIBUTE_SET_EXCEPTIONS);
+ }
+ }
+ raises ';'
+ {
+ $$.documentation = new rtl::OUString(
+ rtl::OStringToOUString(
+ idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8));
+ $$.exceptions = $3;
+ }
+ ;
+
+operation :
+ operation_head
+ op_type_spec
+ {
+ idlc()->setParseState(PS_OpTypeSeen);
+ }
+ identifier
+ {
+ idlc()->setParseState(PS_OpIDSeen);
+ checkIdentifier($4);
+
+ AstInterface * pScope = static_cast< AstInterface * >(
+ idlc()->scopes()->top());
+ AstOperation* pOp = NULL;
+
+ /*
+ * Create a node representing an operation on an interface
+ * and add it to its enclosing scope
+ */
+ if ( pScope && $2 )
+ {
+ AstType *pType = (AstType*)$2;
+ if ( !pType || (pType->getNodeType() == NT_exception) )
+ {
+ // type ERROR
+ } else
+ {
+ pOp = new AstOperation($1, pType, *$4, pScope);
+
+ AstInterface::DoubleMemberDeclarations doubleMembers(
+ pScope->checkMemberClashes(pOp));
+ if (doubleMembers.empty()) {
+ pScope->addMember(pOp);
+ } else {
+ reportDoubleMemberDeclarations(doubleMembers);
+ }
+ }
+ }
+ delete $4;
+ /*
+ * Push the operation scope onto the scopes stack
+ */
+ idlc()->scopes()->push(pOp);
+ }
+ '('
+ {
+ idlc()->setParseState(PS_OpSqSeen);
+ }
+ parameters
+ {
+ idlc()->setParseState(PS_OpParsCompleted);
+ }
+ ')'
+ {
+ idlc()->setParseState(PS_OpQsSeen);
+ }
+ opt_raises
+ {
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstOperation* pOp = NULL;
+ /*
+ * Add exceptions and context to the operation
+ */
+ if ( pScope && pScope->getScopeNodeType() == NT_operation)
+ {
+ pOp = (AstOperation*)pScope;
+
+ if ( pOp )
+ pOp->setExceptions($12);
+ }
+ delete $12;
+ /*
+ * Done with this operation. Pop its scope from the scopes stack
+ */
+ idlc()->scopes()->pop();
+ }
+ ;
+
+operation_head :
+ '['
+ IDL_ONEWAY
+ {
+ idlc()->setParseState(PS_OpOnewaySeen);
+ }
+ ']'
+ {
+ idlc()->setParseState(PS_OpHeadSeen);
+ $$ = OP_ONEWAY;
+ }
+ | /* EMPTY */
+ {
+ $$ = OP_NONE;
+ }
+ ;
+
+op_type_spec :
+ simple_type_spec
+ | IDL_VOID
+ {
+ $$ = idlc()->scopes()->bottom()->lookupPrimitiveType(ET_void);
+ }
+ ;
+
+parameters :
+ parameter
+ | parameters
+ ','
+ {
+ idlc()->setParseState(PS_OpParCommaSeen);
+ }
+ parameter
+ | /* EMPTY */
+ | error ','
+ {
+ yyerror("parameter definition");
+ yyerrok;
+ }
+ ;
+
+parameter :
+ '['
+ direction
+ ']'
+ {
+ idlc()->setParseState(PS_OpParDirSeen);
+ }
+ simple_type_spec
+ {
+ idlc()->setParseState(PS_OpParTypeSeen);
+ }
+ opt_rest
+ declarator
+ {
+ idlc()->setParseState(PS_OpParDeclSeen);
+
+ AstOperation * pScope = static_cast< AstOperation * >(
+ idlc()->scopes()->top());
+ AstParameter* pParam = NULL;
+
+ /*
+ * Create a node representing an argument to an operation
+ * Add it to the enclosing scope (the operation scope)
+ */
+ if ( pScope && $5 && $8 )
+ {
+ AstType const * pType = $8->compose($5);
+ if ( pType )
+ {
+ if (pScope->isConstructor() && $2 != DIR_IN) {
+ idlc()->error()->error0(EIDL_CONSTRUCTOR_PARAMETER_NOT_IN);
+ }
+ if (pScope->isVariadic()) {
+ idlc()->error()->error0(EIDL_REST_PARAMETER_NOT_LAST);
+ }
+ if ($7) {
+ AstDeclaration const * type = resolveTypedefs(pType);
+ if (type->getNodeType() != NT_predefined
+ || (static_cast< AstBaseType const * >(type)->
+ getExprType() != ET_any))
+ {
+ idlc()->error()->error0(EIDL_REST_PARAMETER_NOT_ANY);
+ }
+ if (pScope->isConstructor()) {
+ if (pScope->getIteratorBegin()
+ != pScope->getIteratorEnd())
+ {
+ idlc()->error()->error0(
+ EIDL_CONSTRUCTOR_REST_PARAMETER_NOT_FIRST);
+ }
+ } else {
+ idlc()->error()->error0(EIDL_METHOD_HAS_REST_PARAMETER);
+ }
+ }
+
+ pParam = new AstParameter(
+ static_cast< Direction >($2), $7, pType, $8->getName(),
+ pScope);
+
+ if ( !$8->checkType($5) )
+ {
+ // WARNING
+ }
+
+ pScope->addDeclaration(pParam);
+ }
+ }
+ }
+ | error
+ simple_type_spec
+ {
+ idlc()->setParseState(PS_NoState);
+ yyerrok;
+ }
+ ;
+
+direction :
+ IDL_IN
+ {
+ $$ = DIR_IN;
+ }
+ | IDL_OUT
+ {
+ $$ = DIR_OUT;
+ }
+ | IDL_INOUT
+ {
+ $$ = DIR_INOUT;
+ }
+ ;
+
+opt_rest:
+ IDL_ELLIPSIS
+ {
+ $$ = true;
+ }
+ | /* empty */
+ {
+ $$ = false;
+ }
+ ;
+
+opt_raises:
+ raises
+ | /* empty */
+ {
+ $$ = 0;
+ }
+ ;
+
+raises:
+ IDL_RAISES
+ {
+ idlc()->setParseState(PS_RaiseSeen);
+ }
+ '('
+ {
+ idlc()->setParseState(PS_RaiseSqSeen);
+ }
+ exception_list
+ ')'
+ {
+ idlc()->setParseState(PS_RaiseQsSeen);
+ $$ = $5;
+ }
+ ;
+
+exception_list:
+ exception_name
+ {
+ $$ = new DeclList;
+ $$->push_back($1);
+ }
+ | exception_list ',' exception_name
+ {
+ $1->push_back($3);
+ $$ = $1;
+ }
+ ;
+
+exception_name:
+ scoped_name
+ {
+ // The topmost scope is either an AstOperation (for interface methods
+ // and service constructors) or an AstAttribute (for interface
+ // attributes), so look up exception names in the next-to-topmost scope:
+ AstDeclaration * decl = idlc()->scopes()->nextToTop()->lookupByName(
+ *$1);
+ if (decl == 0) {
+ idlc()->error()->lookupError(*$1);
+ } else if (!idlc()->error()->checkPublished(decl)) {
+ decl = 0;
+ } else if (decl->getNodeType() != NT_exception) {
+ idlc()->error()->error1(EIDL_ILLEGAL_RAISES, decl);
+ decl = 0;
+ }
+ delete $1;
+ $$ = decl;
+ }
+ ;
+
+interface_inheritance_decl:
+ optional_inherited_interface
+ IDL_INTERFACE
+ {
+ idlc()->setParseState(PS_ServiceIFHeadSeen);
+ }
+ scoped_name
+ {
+ AstInterface * ifc = static_cast< AstInterface * >(
+ idlc()->scopes()->top());
+ if (ifc->usesSingleInheritance()) {
+ idlc()->error()->error0(EIDL_MIXED_INHERITANCE);
+ } else {
+ addInheritedInterface(
+ ifc, *$4, $1,
+ rtl::OStringToOUString(
+ idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8));
+ }
+ delete $4;
+ }
+ ;
+
+optional_inherited_interface:
+ '[' IDL_OPTIONAL ']' { $$ = true; }
+ | /* EMPTY */ { $$ = false; }
+ ;
+
+constants_exports :
+ constants_export constants_exports
+ | /* EMPTY */
+ ;
+
+constants_export :
+ const_dcl
+ {
+ idlc()->setParseState(PS_ConstantDeclSeen);
+ }
+ ';' {};
+
+const_dcl :
+ IDL_CONST
+ {
+ idlc()->setParseState(PS_ConstSeen);
+ }
+ const_type
+ {
+ idlc()->setParseState(PS_ConstTypeSeen);
+ }
+ identifier
+ {
+ idlc()->setParseState(PS_ConstIDSeen);
+ checkIdentifier($5);
+ }
+ '='
+ {
+ idlc()->setParseState(PS_ConstAssignSeen);
+ }
+ expression
+ {
+ idlc()->setParseState(PS_ConstExprSeen);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstConstant* pConstant = NULL;
+
+ if ( $9 && pScope )
+ {
+ if ( !$9->coerce($3) )
+ {
+ idlc()->error()->coercionError($9, $3);
+ } else
+ {
+ pConstant = new AstConstant($3, $9, *$5, pScope);
+ pScope->addDeclaration(pConstant);
+ }
+ }
+ delete $5;
+ }
+ ;
+
+constants_dcl :
+ IDL_CONSTANTS
+ {
+ idlc()->setParseState(PS_ConstantsSeen);
+ }
+ identifier
+ {
+ idlc()->setParseState(PS_ConstantsIDSeen);
+ checkIdentifier($3);
+ }
+ '{'
+ {
+ idlc()->setParseState(PS_ConstantsSqSeen);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstConstants* pConstants = NULL;
+ AstDeclaration* pExists = NULL;
+
+ if ( pScope )
+ {
+ pConstants = new AstConstants(*$3, pScope);
+ if( (pExists = pScope->lookupForAdd(pConstants)) )
+ {
+ pExists->setInMainfile(idlc()->isInMainFile());
+ delete(pConstants);
+ pConstants = (AstConstants*)pExists;
+ } else
+ {
+ pScope->addDeclaration(pConstants);
+ }
+ idlc()->scopes()->push(pConstants);
+ }
+ delete $3;
+ }
+ constants_exports
+ {
+ idlc()->setParseState(PS_ConstantsBodySeen);
+ }
+ '}'
+ {
+ idlc()->setParseState(PS_ConstantsQsSeen);
+ /*
+ * Finished with this constants - pop it from the scope stack
+ */
+ idlc()->scopes()->pop();
+ }
+ ;
+
+expression : const_expr ;
+
+const_expr : or_expr ;
+
+or_expr :
+ xor_expr
+ | or_expr '|' xor_expr
+ {
+ $$ = new AstExpression(EC_or, $1, $3);
+ }
+ ;
+
+xor_expr :
+ and_expr
+ | xor_expr '^' and_expr
+ {
+ $$ = new AstExpression(EC_xor, $1, $3);
+ }
+ ;
+
+and_expr :
+ shift_expr
+ | and_expr '&' shift_expr
+ {
+ $$ = new AstExpression(EC_and, $1, $3);
+ }
+ ;
+
+shift_expr :
+ add_expr
+ | shift_expr IDL_LEFTSHIFT add_expr
+ {
+ $$ = new AstExpression(EC_left, $1, $3);
+ }
+ | shift_expr IDL_RIGHTSHIFT add_expr
+ {
+ $$ = new AstExpression(EC_right, $1, $3);
+ }
+ ;
+
+add_expr :
+ mult_expr
+ | add_expr '+' mult_expr
+ {
+ $$ = new AstExpression(EC_add, $1, $3);
+ }
+ | add_expr '-' mult_expr
+ {
+ $$ = new AstExpression(EC_minus, $1, $3);
+ }
+ ;
+
+mult_expr :
+ unary_expr
+ | mult_expr '*' unary_expr
+ {
+ $$ = new AstExpression(EC_mul, $1, $3);
+ }
+ | mult_expr '/' unary_expr
+ {
+ $$ = new AstExpression(EC_div, $1, $3);
+ }
+ | mult_expr '%' unary_expr
+ {
+ $$ = new AstExpression(EC_mod, $1, $3);
+ }
+ ;
+
+unary_expr :
+ primary_expr
+ | '+' primary_expr
+ {
+ $$ = new AstExpression(EC_u_plus, $2, NULL);
+ }
+ | '-' primary_expr
+ {
+ $$ = new AstExpression(EC_u_minus, $2, NULL);
+ }
+ | '~' primary_expr
+ {
+ }
+ ;
+
+primary_expr :
+ scoped_name
+ {
+ /*
+ * An expression which is a scoped name is not resolved now,
+ * but only when it is evaluated (such as when it is assigned
+ * as a constant value)
+ */
+ $$ = new AstExpression($1);
+ }
+ | literal
+ | '(' const_expr ')'
+ {
+ $$ = $2;
+ }
+ ;
+
+literal :
+ IDL_INTEGER_LITERAL
+ {
+ $$ = new AstExpression($1);
+ }
+ | IDL_INTEGER_ULITERAL
+ {
+ $$ = new AstExpression($1);
+ }
+ | IDL_FLOATING_PT_LITERAL
+ {
+ $$ = new AstExpression($1);
+ }
+ | IDL_TRUE
+ {
+ $$ = new AstExpression((sal_Int32)1, ET_boolean);
+ }
+ | IDL_FALSE
+ {
+ $$ = new AstExpression((sal_Int32)0, ET_boolean);
+ }
+ ;
+
+positive_int_expr :
+ const_expr
+ {
+ $1->evaluate(EK_const);
+ if ( !$1->coerce(ET_ulong) )
+ {
+ idlc()->error()->coercionError($1, ET_ulong);
+ delete $1;
+ $$ = NULL;
+ }
+ }
+ ;
+
+const_type :
+ integer_type
+ | char_type
+ | byte_type
+ | boolean_type
+ | floating_pt_type
+ | scoped_name
+ {
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstDeclaration const * type = 0;
+
+ /*
+ * If the constant's type is a scoped name, it must resolve
+ * to a scalar constant type
+ */
+ if ( pScope && (type = pScope->lookupByName(*$1)) ) {
+ if (!idlc()->error()->checkPublished(type))
+ {
+ type = 0;
+ }
+ else
+ {
+ type = resolveTypedefs(type);
+ if (type->getNodeType() == NT_predefined)
+ {
+ $$ = static_cast< AstBaseType const * >(type)->
+ getExprType();
+ } else
+ $$ = ET_any;
+ }
+ } else
+ $$ = ET_any;
+ }
+ ;
+
+exception_header :
+ IDL_EXCEPTION
+ {
+ idlc()->setParseState(PS_ExceptSeen);
+ }
+ identifier
+ {
+ idlc()->setParseState(PS_ExceptIDSeen);
+ checkIdentifier($3);
+ }
+ inheritance_spec
+ {
+ idlc()->setParseState(PS_InheritSpecSeen);
+
+ $$ = new FeInheritanceHeader(NT_exception, $3, $5, 0);
+ delete $5;
+ }
+ ;
+
+exception_dcl :
+ exception_header
+ {
+ idlc()->setParseState(PS_ExceptHeaderSeen);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstException* pExcept = NULL;
+
+ if ( pScope )
+ {
+ AstException* pBase = static_cast< AstException* >(
+ $1->getInherits());
+ pExcept = new AstException(*$1->getName(), pBase, pScope);
+ pScope->addDeclaration(pExcept);
+ }
+ /*
+ * Push the scope of the exception on the scopes stack
+ */
+ idlc()->scopes()->push(pExcept);
+ delete $1;
+ }
+ '{'
+ {
+ idlc()->setParseState(PS_ExceptSqSeen);
+ }
+ members
+ {
+ idlc()->setParseState(PS_ExceptBodySeen);
+ }
+ '}'
+ {
+ idlc()->setParseState(PS_ExceptQsSeen);
+ /* this exception is finished, pop its scope from the stack */
+ idlc()->scopes()->pop();
+ }
+ ;
+
+property :
+ flag_header
+ simple_type_spec
+ {
+ idlc()->setParseState(PS_PropertyTypeSeen);
+ }
+ at_least_one_declarator
+ {
+ idlc()->setParseState(PS_PropertyCompleted);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstAttribute* pAttr = NULL;
+ FeDeclList* pList = $4;
+ FeDeclarator* pDecl = NULL;
+ AstType const * pType = NULL;
+
+ if ( pScope->getScopeNodeType() == NT_singleton )
+ {
+ idlc()->error()->error0(EIDL_ILLEGAL_ADD);
+ } else
+ {
+ if ( ($1 & AF_ATTRIBUTE) == AF_ATTRIBUTE )
+ idlc()->error()->flagError(EIDL_WRONGATTRIBUTEKEYWORD, AF_ATTRIBUTE);
+
+ if ( ($1 & AF_PROPERTY) != AF_PROPERTY )
+ idlc()->error()->flagError(EIDL_MISSINGATTRIBUTEKEYWORD, AF_PROPERTY);
+
+ /*
+ * Create nodes representing attributes and add them to the
+ * enclosing scope
+ */
+ if ( pScope && $2 && pList )
+ {
+ FeDeclList::iterator iter = pList->begin();
+ FeDeclList::iterator end = pList->end();
+
+ while (iter != end)
+ {
+ pDecl = (*iter);
+ if ( !pDecl )
+ {
+ iter++;
+ continue;
+ }
+
+ pType = pDecl->compose($2);
+
+ if ( !pType )
+ {
+ iter++;
+ continue;
+ }
+
+ pAttr = new AstAttribute(NT_property, $1, pType, pDecl->getName(), pScope);
+
+ pScope->addDeclaration(pAttr);
+ iter++;
+ delete pDecl;
+ }
+ }
+ }
+
+ if ( pList )
+ delete pList;
+ }
+ | error ';'
+ {
+ yyerror("property");
+ yyerrok;
+ }
+ ;
+
+service_exports :
+ service_exports service_export
+ | /* EMPTY */
+ ;
+
+service_export :
+ service_interface_header
+ at_least_one_scoped_name
+ ';'
+ {
+ idlc()->setParseState(PS_ServiceMemberSeen);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstDeclaration* pDecl = NULL;
+ AstInterfaceMember* pIMember = NULL;
+
+ if ( pScope->getScopeNodeType() == NT_singleton )
+ {
+ idlc()->error()->error0(EIDL_ILLEGAL_ADD);
+ } else
+ {
+ /*
+ * Create a node representing a class member.
+ * Store it in the enclosing scope
+ */
+ if ( pScope && $2 )
+ {
+ StringList::iterator iter = $2->begin();
+ StringList::iterator end = $2->end();
+
+ while ( iter != end )
+ {
+ pDecl = pScope->lookupByName(*iter);
+ if ( pDecl && (pDecl->getNodeType() == NT_interface) )
+ {
+ /* we relax the strict published check and allow to add new
+ * interfaces if they are optional
+ */
+ bool bOptional = (($1 & AF_OPTIONAL) == AF_OPTIONAL);
+ if ( idlc()->error()->checkPublished(pDecl, bOptional) )
+ {
+ pIMember = new AstInterfaceMember(
+ $1, (AstInterface*)pDecl, *iter, pScope);
+ pScope->addDeclaration(pIMember);
+ }
+ } else
+ {
+ idlc()->error()->
+ lookupError(EIDL_INTERFACEMEMBER_LOOKUP, *iter, scopeAsDecl(pScope));
+ }
+ iter++;
+ }
+ }
+ }
+ delete $2;
+ }
+ | service_service_header
+ at_least_one_scoped_name
+ ';'
+ {
+ idlc()->setParseState(PS_ServiceMemberSeen);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstDeclaration* pDecl = NULL;
+ AstServiceMember* pSMember = NULL;
+
+ /*
+ * Create a node representing a class member.
+ * Store it in the enclosing scope
+ */
+ if ( pScope && $2 )
+ {
+ StringList::iterator iter = $2->begin();
+ StringList::iterator end = $2->end();
+
+ while ( iter != end )
+ {
+ pDecl = pScope->lookupByName(*iter);
+ if ( pDecl && (pDecl->getNodeType() == NT_service) )
+ {
+ if ( pScope->getScopeNodeType() == NT_singleton && pScope->nMembers() > 0 )
+ idlc()->error()->error0(EIDL_ILLEGAL_ADD);
+ else if ( idlc()->error()->checkPublished(pDecl) )
+ {
+ pSMember = new AstServiceMember(
+ $1, (AstService*)pDecl, *iter, pScope);
+ pScope->addDeclaration(pSMember);
+ }
+ } else
+ {
+ idlc()->error()->
+ lookupError(EIDL_SERVICEMEMBER_LOOKUP, *iter, scopeAsDecl(pScope));
+ }
+ iter++;
+ }
+ }
+ delete $2;
+ }
+ | IDL_OBSERVES
+ at_least_one_scoped_name
+ ';'
+ {
+ idlc()->setParseState(PS_ServiceMemberSeen);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstDeclaration* pDecl = NULL;
+ AstObserves* pObserves = NULL;
+
+ if ( pScope->getScopeNodeType() == NT_singleton )
+ {
+ idlc()->error()->error0(EIDL_ILLEGAL_ADD);
+ } else
+ {
+ /*
+ * Create a node representing a class member.
+ * Store it in the enclosing scope
+ */
+ if ( pScope && $2 )
+ {
+ StringList::iterator iter = $2->begin();
+ StringList::iterator end = $2->end();
+
+ while ( iter != end )
+ {
+ pDecl = pScope->lookupByName(*iter);
+ if ( pDecl && (pDecl->getNodeType() == NT_interface) )
+ {
+ pObserves = new AstObserves((AstInterface*)pDecl, *iter, pScope);
+ pScope->addDeclaration(pObserves);
+ } else
+ {
+ idlc()->error()->
+ lookupError(EIDL_INTERFACEMEMBER_LOOKUP, *iter, scopeAsDecl(pScope));
+ }
+ iter++;
+ }
+ }
+ }
+ delete $2;
+ }
+ | IDL_NEEDS
+ at_least_one_scoped_name
+ ';'
+ {
+ idlc()->setParseState(PS_ServiceMemberSeen);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstDeclaration* pDecl = NULL;
+ AstNeeds* pNeeds = NULL;
+
+ if ( pScope->getScopeNodeType() == NT_singleton )
+ {
+ idlc()->error()->error0(EIDL_ILLEGAL_ADD);
+ } else
+ {
+ /*
+ * Create a node representing a class member.
+ * Store it in the enclosing scope
+ */
+ if ( pScope && $2 )
+ {
+ StringList::iterator iter = $2->begin();
+ StringList::iterator end = $2->end();
+
+ while ( iter != end )
+ {
+ pDecl = pScope->lookupByName(*iter);
+ if ( pDecl && (pDecl->getNodeType() == NT_service) )
+ {
+ pNeeds = new AstNeeds((AstService*)pDecl, *iter, pScope);
+ pScope->addDeclaration(pNeeds);
+ } else
+ {
+ idlc()->error()->
+ lookupError(EIDL_SERVICEMEMBER_LOOKUP, *iter, scopeAsDecl(pScope));
+ }
+ iter++;
+ }
+ }
+ }
+ delete $2;
+ }
+ | property
+ ';'
+ {
+ idlc()->setParseState(PS_PropertyDeclSeen);
+ }
+ ;
+
+service_interface_header :
+ IDL_INTERFACE
+ {
+ idlc()->setParseState(PS_ServiceIFHeadSeen);
+ $$ = AF_INVALID;
+ }
+ | flag_header
+ IDL_INTERFACE
+ {
+ idlc()->setParseState(PS_ServiceIFHeadSeen);
+ if ( (AF_OPTIONAL != $1) && ( AF_INVALID != $1) )
+ idlc()->error()->flagError(EIDL_OPTIONALEXPECTED, $1);
+ $$ = $1;
+ }
+ ;
+
+service_service_header :
+ IDL_SERVICE
+ {
+ idlc()->setParseState(PS_ServiceSHeadSeen);
+ $$ = AF_INVALID;
+ }
+ | flag_header
+ IDL_SERVICE
+ {
+ idlc()->setParseState(PS_ServiceSHeadSeen);
+ if ( (AF_OPTIONAL != $1) && ( AF_INVALID != $1) )
+ idlc()->error()->flagError(EIDL_OPTIONALEXPECTED, $1);
+ $$ = $1;
+ }
+ ;
+
+service_dcl :
+ IDL_SERVICE
+ {
+ idlc()->setParseState(PS_ServiceSeen);
+ }
+ identifier
+ {
+ idlc()->setParseState(PS_ServiceIDSeen);
+ checkIdentifier($3);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstService* pService = NULL;
+
+ /*
+ * Make a new service and add it to the enclosing scope
+ */
+ if (pScope != NULL)
+ {
+ pService = new AstService(*$3, pScope);
+ pScope->addDeclaration(pService);
+ }
+ delete $3;
+ /*
+ * Push it on the stack
+ */
+ idlc()->scopes()->push(pService);
+ }
+ service_dfn
+ {
+ /* this service is finished, pop its scope from the stack */
+ idlc()->scopes()->pop();
+ }
+ ;
+
+service_dfn:
+ service_interface_dfn
+ | service_obsolete_dfn
+ ;
+
+service_interface_dfn:
+ ':' scoped_name
+ {
+ AstScope * scope = idlc()->scopes()->nextToTop();
+ // skip the scope pushed by service_dcl
+ AstDeclaration * decl = scope->lookupByName(*$2);
+ if (decl != 0 && resolveTypedefs(decl)->getNodeType() == NT_interface) {
+ if (idlc()->error()->checkPublished(decl)) {
+ idlc()->scopes()->top()->addDeclaration(decl);
+ }
+ } else {
+ idlc()->error()->lookupError(
+ EIDL_INTERFACEMEMBER_LOOKUP, *$2, scopeAsDecl(scope));
+ }
+ delete $2;
+ }
+ opt_service_body
+ {
+ AstService * s = static_cast< AstService * >(idlc()->scopes()->top());
+ if (s != 0) {
+ s->setDefaultConstructor(!$4);
+ }
+ }
+ ;
+
+opt_service_body:
+ service_body { $$ = true; }
+ | /* empty */ { $$ = false; }
+ ;
+
+service_body:
+ '{'
+ constructors
+ '}'
+ ;
+
+constructors:
+ constructors constructor
+ | /* empty */
+ ;
+
+constructor:
+ identifier
+ {
+ checkIdentifier($1);
+ AstScope * scope = idlc()->scopes()->top();
+ AstOperation * ctor = new AstOperation(OP_NONE, 0, *$1, scope);
+ delete $1;
+ scope->addDeclaration(ctor);
+ idlc()->scopes()->push(ctor);
+ }
+ '('
+ parameters
+ ')'
+ opt_raises
+ {
+ static_cast< AstOperation * >(idlc()->scopes()->top())->setExceptions(
+ $6);
+ delete $6;
+ idlc()->scopes()->pop();
+ if (static_cast< AstService * >(idlc()->scopes()->top())->
+ checkLastConstructor())
+ {
+ idlc()->error()->error0(EIDL_SIMILAR_CONSTRUCTORS);
+ }
+ }
+ ';'
+ ;
+
+singleton_dcl :
+ IDL_SINGLETON
+ {
+ idlc()->setParseState(PS_SingletonSeen);
+ }
+ identifier
+ {
+ idlc()->setParseState(PS_SingletonIDSeen);
+ checkIdentifier($3);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstService* pService = NULL;
+
+ /*
+ * Make a new service and add it to the enclosing scope
+ */
+ if (pScope != NULL)
+ {
+ pService = new AstService(NT_singleton, *$3, pScope);
+ pScope->addDeclaration(pService);
+ }
+ delete $3;
+ /*
+ * Push it on the stack
+ */
+ idlc()->scopes()->push(pService);
+ }
+ singleton_dfn
+ {
+ /* this singelton is finished, pop its scope from the stack */
+ idlc()->scopes()->pop();
+ }
+ ;
+
+singleton_dfn:
+ singleton_interface_dfn
+ | service_obsolete_dfn
+ ;
+
+singleton_interface_dfn:
+ ':' scoped_name
+ {
+ AstScope * scope = idlc()->scopes()->nextToTop();
+ // skip the scope (needlessly) pushed by singleton_dcl
+ AstDeclaration * decl = scope->lookupByName(*$2);
+ if (decl != 0 && resolveTypedefs(decl)->getNodeType() == NT_interface) {
+ if (idlc()->error()->checkPublished(decl)) {
+ idlc()->scopes()->top()->addDeclaration(decl);
+ }
+ } else {
+ idlc()->error()->lookupError(
+ EIDL_INTERFACEMEMBER_LOOKUP, *$2, scopeAsDecl(scope));
+ }
+ delete $2;
+ }
+ ;
+
+service_obsolete_dfn:
+ '{'
+ {
+ idlc()->setParseState(
+ idlc()->scopes()->top()->getScopeNodeType() == NT_service
+ ? PS_ServiceSqSeen : PS_SingletonSqSeen);
+ }
+ service_exports
+ {
+ idlc()->setParseState(
+ idlc()->scopes()->top()->getScopeNodeType() == NT_service
+ ? PS_ServiceBodySeen : PS_SingletonBodySeen);
+ }
+ '}'
+ {
+ idlc()->setParseState(
+ idlc()->scopes()->top()->getScopeNodeType() == NT_service
+ ? PS_ServiceQsSeen : PS_SingletonQsSeen);
+ }
+ ;
+
+type_dcl :
+ IDL_TYPEDEF
+ {
+ idlc()->setParseState(PS_TypedefSeen);
+ }
+ type_declarator {}
+ | struct_type {}
+ | union_type {}
+ | enum_type {}
+ ;
+
+type_declarator :
+ type_spec
+ {
+ idlc()->setParseState(PS_TypeSpecSeen);
+ if ($1 != 0 && $1->getNodeType() == NT_instantiated_struct) {
+ idlc()->error()->error0(EIDL_INSTANTIATED_STRUCT_TYPE_TYPEDEF);
+ }
+ }
+ at_least_one_declarator
+ {
+ idlc()->setParseState(PS_DeclaratorsSeen);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstTypeDef* pTypeDef = NULL;
+ FeDeclList* pList = $3;
+ FeDeclarator* pDecl = NULL;
+ AstType const * pType = NULL;
+
+ /*
+ * Create nodes representing typedefs and add them to the
+ * enclosing scope
+ */
+ if ( pScope && $1 && pList )
+ {
+ FeDeclList::iterator iter = pList->begin();
+ FeDeclList::iterator end = pList->end();
+
+ while (iter != end)
+ {
+ pDecl = (*iter);
+ if ( !pDecl )
+ {
+ iter++;
+ continue;
+ }
+
+ pType = pDecl->compose($1);
+
+ if ( !pType )
+ {
+ iter++;
+ continue;
+ }
+
+ pTypeDef = new AstTypeDef(pType, pDecl->getName(), pScope);
+
+ pScope->addDeclaration(pTypeDef);
+ iter++;
+ delete pDecl;
+ }
+ delete pList;
+ }
+ }
+ ;
+
+at_least_one_declarator :
+ declarator declarators
+ {
+ if ( $2 )
+ {
+ $2->push_back($1);
+ $$ = $2;
+ } else
+ {
+ FeDeclList* pList = new FeDeclList();
+ pList->push_back($1);
+ $$ = pList;
+ }
+ }
+ ;
+
+declarators :
+ declarators
+ ','
+ {
+ idlc()->setParseState(PS_DeclsCommaSeen);
+ }
+ declarator
+ {
+ idlc()->setParseState(PS_DeclsDeclSeen);
+ if ( $1 )
+ {
+ $1->push_back($4);
+ $$ = $1;
+ } else
+ {
+ FeDeclList* pList = new FeDeclList();
+ pList->push_back($4);
+ $$ = pList;
+ }
+ }
+ | /* EMPTY */
+ {
+ $$ = NULL;
+ }
+ ;
+
+declarator :
+ simple_declarator
+ | complex_declarator
+ ;
+
+simple_declarator :
+ identifier
+ {
+ // For historic reasons, the struct com.sun.star.uno.Uik contains
+ // members with illegal names (of the form "m_DataN"); avoid useless
+ // warnings about them:
+ AstScope * scope = idlc()->scopes()->top();
+ if (scope == 0 || scope->getScopeNodeType() != NT_struct
+ || (scopeAsDecl(scope)->getScopedName()
+ != "com::sun::star::uno::Uik"))
+ {
+ checkIdentifier($1);
+ }
+
+ $$ = new FeDeclarator(*$1, FeDeclarator::FD_simple, NULL);
+ delete $1;
+ }
+ ;
+
+complex_declarator :
+ array_declarator
+ {
+ $$ = new FeDeclarator($1->getLocalName(), FeDeclarator::FD_complex, $1);
+ }
+ ;
+
+array_declarator :
+ identifier
+ {
+ idlc()->setParseState(PS_ArrayIDSeen);
+ checkIdentifier($1);
+ }
+ at_least_one_array_dim
+ {
+ idlc()->setParseState(PS_ArrayCompleted);
+ $$ = new AstArray(*$1, NULL, *$3, idlc()->scopes()->bottom());
+ delete $1;
+ }
+ ;
+
+at_least_one_array_dim :
+ array_dim array_dims
+ {
+ if( $2 )
+ {
+ $2->push_front($1);
+ $$ = $2;
+ } else
+ {
+ ExprList* pList = new ExprList();
+ pList->push_back($1);
+ $$ = pList;
+ }
+ }
+ ;
+
+array_dims :
+ array_dims array_dim
+ {
+ if( $1 )
+ {
+ $1->push_back($2);
+ $$ = $1;
+ } else
+ {
+ ExprList* pList = new ExprList();
+ pList->push_back($2);
+ $$ = pList;
+ }
+ }
+ | /* EMPTY */
+ {
+ $$ = NULL;
+ }
+ ;
+
+array_dim :
+ '['
+ {
+ idlc()->setParseState(PS_DimSqSeen);
+ }
+ positive_int_expr
+ {
+ idlc()->setParseState(PS_DimExprSeen);
+ }
+ ']'
+ {
+ idlc()->setParseState(PS_DimQsSeen);
+ /*
+ * Array dimensions are expressions which must be coerced to
+ * positive integers
+ */
+ if ( !$3 || !$3->coerce(ET_uhyper) )
+ {
+ idlc()->error()->coercionError($3, ET_uhyper);
+ $$ = NULL;
+ } else
+ $$ = $3;
+ }
+ ;
+
+at_least_one_scoped_name :
+ scoped_name scoped_names
+ {
+ if ($2)
+ {
+ $2->push_front(*$1);
+ $$ = $2;
+ } else
+ {
+ StringList* pNames = new StringList();
+ pNames->push_back(*$1);
+ $$ = pNames;
+ }
+ delete($1);
+ }
+ ;
+
+scoped_names :
+ scoped_names
+ ','
+ {
+ idlc()->setParseState(PS_SNListCommaSeen);
+ }
+ scoped_name
+ {
+ idlc()->setParseState(PS_ScopedNameSeen);
+ if ($1)
+ {
+ $1->push_back(*$4);
+ $$ = $1;
+ } else
+ {
+ StringList* pNames = new StringList();
+ pNames->push_back(*$4);
+ $$ = pNames;
+ }
+ delete($4);
+ }
+ | /* EMPTY */
+ {
+ $$ = NULL;
+ }
+ ;
+
+scoped_name :
+ identifier
+ {
+ idlc()->setParseState(PS_SN_IDSeen);
+ checkIdentifier($1);
+ $$ = $1;
+ }
+ | IDL_SCOPESEPARATOR
+ {
+ idlc()->setParseState(PS_ScopeDelimSeen);
+ }
+ identifier
+ {
+ checkIdentifier($3);
+ OString* pName = new OString("::");
+ *pName += *$3;
+ delete $3;
+ $$ = pName;
+ }
+ | scoped_name
+ IDL_SCOPESEPARATOR
+ {
+ }
+ identifier
+ {
+ checkIdentifier($4);
+ *$1 += ::rtl::OString("::");
+ *$1 += *$4;
+ delete $4;
+ $$ = $1;
+ }
+ ;
+
+type_spec :
+ simple_type_spec
+ | constructed_type_spec
+ ;
+
+simple_type_spec :
+ fundamental_type
+ | scoped_name opt_type_args
+ {
+ $$ = createNamedType($1, $2);
+ }
+ ;
+
+fundamental_type:
+ base_type_spec
+ {
+ $$ = idlc()->scopes()->bottom()->lookupPrimitiveType($1);
+ }
+ | template_type_spec
+ ;
+
+opt_type_args:
+ '<' type_args '>' { $$ = $2; }
+ | /* empty */ { $$ = 0; }
+ ;
+
+type_args:
+ type_arg
+ {
+ $$ = new DeclList;
+ $$->push_back(const_cast< AstDeclaration * >($1)); //TODO: const_cast
+ }
+ | type_args ',' type_arg
+ {
+ $1->push_back(const_cast< AstDeclaration * >($3)); //TODO: const_cast
+ $$ = $1;
+ }
+ ;
+
+type_arg:
+ simple_type_spec
+ {
+ if ($1 != 0 && static_cast< AstType const * >($1)->isUnsigned()) {
+ idlc()->error()->error0(EIDL_UNSIGNED_TYPE_ARGUMENT);
+ }
+ $$ = $1;
+ }
+ ;
+
+base_type_spec :
+ integer_type
+ | floating_pt_type
+ | char_type
+ | boolean_type
+ | byte_type
+ | any_type
+ | type_type
+ | string_type
+ ;
+
+integer_type :
+ signed_int
+ | unsigned_int
+ ;
+
+signed_int :
+ IDL_LONG
+ {
+ $$ = ET_long;
+ }
+ | IDL_HYPER
+ {
+ $$ = ET_hyper;
+ }
+ | IDL_SHORT
+ {
+ $$ = ET_short;
+ }
+ ;
+
+unsigned_int :
+ IDL_UNSIGNED IDL_LONG
+ {
+ $$ = ET_ulong;
+ }
+ | IDL_UNSIGNED IDL_HYPER
+ {
+ $$ = ET_uhyper;
+ }
+ | IDL_UNSIGNED IDL_SHORT
+ {
+ $$ = ET_ushort;
+ }
+ ;
+
+floating_pt_type :
+ IDL_DOUBLE
+ {
+ $$ = ET_double;
+ }
+ | IDL_FLOAT
+ {
+ $$ = ET_float;
+ }
+ ;
+
+char_type :
+ IDL_CHAR
+ {
+ $$ = ET_char;
+ }
+ ;
+
+byte_type :
+ IDL_BYTE
+ {
+ $$ = ET_byte;
+ }
+ ;
+
+boolean_type :
+ IDL_BOOLEAN
+ {
+ $$ = ET_boolean;
+ }
+ ;
+
+any_type :
+ IDL_ANY
+ {
+ $$ = ET_any;
+ }
+ ;
+
+type_type :
+ IDL_TYPE
+ {
+ $$ = ET_type;
+ }
+ ;
+
+string_type :
+ IDL_STRING
+ {
+ $$ = ET_string;
+ }
+ ;
+
+template_type_spec :
+ sequence_type_spec
+ | array_type
+ ;
+
+constructed_type_spec :
+ struct_type
+ | union_type
+ | enum_type
+ ;
+
+array_type :
+ simple_type_spec
+ {
+ idlc()->setParseState(PS_ArrayTypeSeen);
+ }
+ at_least_one_array_dim
+ {
+ idlc()->setParseState(PS_ArrayCompleted);
+
+ AstScope* pScope = idlc()->scopes()->bottom();
+ AstDeclaration* pDecl = NULL;
+ AstDeclaration* pArray = NULL;
+
+ if ( $1 )
+ {
+ pArray = new AstArray((AstType*)$1, *$3, idlc()->scopes()->bottom());
+ if ( pScope )
+ {
+ pDecl = pScope->addDeclaration(pArray);
+ if ( pArray != pDecl )
+ {
+ // if array type already defined then use it
+ delete pArray;
+ pArray = pDecl;
+ }
+ }
+ }
+ $$ = pArray;
+ }
+ ;
+
+sequence_type_spec :
+ IDL_SEQUENCE
+ {
+ idlc()->setParseState(PS_SequenceSeen);
+ /*
+ * Push a sequence marker on scopes stack
+ */
+ idlc()->scopes()->push(NULL);
+ }
+ '<'
+ {
+ idlc()->setParseState(PS_SequenceSqSeen);
+ }
+ simple_type_spec
+ {
+ idlc()->setParseState(PS_SequenceTypeSeen);
+ }
+ '>'
+ {
+ idlc()->setParseState(PS_SequenceQsSeen);
+ /*
+ * Remove sequence marker from scopes stack
+ */
+ if (idlc()->scopes()->top() == NULL)
+ idlc()->scopes()->pop();
+ /*
+ * Create a node representing a sequence
+ */
+ AstScope* pScope = idlc()->scopes()->bottom();
+ AstDeclaration* pDecl = NULL;
+ AstDeclaration* pSeq = NULL;
+
+ if ( $5 )
+ {
+ AstType *pType = (AstType*)$5;
+ if ( pType )
+ {
+ pSeq = new AstSequence(pType, pScope);
+ /*
+ * Add this AstSequence to the types defined in the global scope
+ */
+ pDecl = pScope->addDeclaration(pSeq);
+ if ( pSeq != pDecl )
+ {
+ // if sequence type already defined then use it
+ delete pSeq;
+ pSeq = pDecl;
+ }
+ }
+ }
+ $$ = pSeq;
+ }
+ | error '>'
+ {
+ yyerror("sequence declaration");
+ yyerrok;
+ $$ = 0;
+ }
+ ;
+
+struct_type :
+ structure_header
+ {
+ idlc()->setParseState(PS_StructHeaderSeen);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstStruct* pStruct = NULL;
+
+ if ( pScope )
+ {
+ AstStruct* pBase= static_cast< AstStruct* >($1->getInherits());
+ pStruct = new AstStruct(
+ *$1->getName(), $1->getTypeParameters(), pBase, pScope);
+ pScope->addDeclaration(pStruct);
+ }
+ /*
+ * Push the scope of the struct on the scopes stack
+ */
+ idlc()->scopes()->push(pStruct);
+ delete $1;
+ }
+ '{'
+ {
+ idlc()->setParseState(PS_StructSqSeen);
+ }
+ at_least_one_member
+ {
+ idlc()->setParseState(PS_StructBodySeen);
+ }
+ '}'
+ {
+ idlc()->setParseState(PS_StructQsSeen);
+ /* this exception is finished, pop its scope from the stack */
+ idlc()->scopes()->pop();
+ }
+ ;
+
+structure_header :
+ IDL_STRUCT
+ {
+ idlc()->setParseState(PS_StructSeen);
+ }
+ identifier
+ {
+ idlc()->setParseState(PS_StructIDSeen);
+ checkIdentifier($3);
+ }
+ opt_type_params
+ inheritance_spec
+ {
+ idlc()->setParseState(PS_InheritSpecSeen);
+
+ // Polymorphic struct type templates with base types would cause various
+ // problems in language bindings, so forbid them here. For example,
+ // GCC prior to version 3.4 fails with code like
+ //
+ // struct Base { ... };
+ // template< typename typeparam_T > struct Derived: public Base {
+ // int member1 CPPU_GCC3_ALIGN(Base);
+ // ... };
+ //
+ // (Note that plain struct types with instantiated polymorphic struct
+ // type bases, which might also cause problems in language bindings, are
+ // already rejected on a syntactic level.)
+ if ($5 != 0 && $6 != 0) {
+ idlc()->error()->error0(EIDL_STRUCT_TYPE_TEMPLATE_WITH_BASE);
+ }
+
+ $$ = new FeInheritanceHeader(NT_struct, $3, $6, $5);
+ delete $5;
+ delete $6;
+ }
+ ;
+
+opt_type_params:
+ '<' type_params '>' { $$ = $2; }
+ | /* empty */ { $$ = 0; }
+ ;
+
+type_params:
+ identifier
+ {
+ $$ = new std::vector< rtl::OString >;
+ $$->push_back(*$1);
+ delete $1;
+ }
+ | type_params ',' identifier
+ {
+ if (std::find($1->begin(), $1->end(), *$3) != $1->end()) {
+ idlc()->error()->error0(EIDL_IDENTICAL_TYPE_PARAMETERS);
+ }
+ $1->push_back(*$3);
+ delete $3;
+ $$ = $1;
+ }
+ ;
+
+at_least_one_member : member members ;
+
+members :
+ members member
+ | /* EMPTY */
+ ;
+
+member :
+ type_or_parameter
+ {
+ idlc()->setParseState(PS_MemberTypeSeen);
+ }
+ at_least_one_declarator
+ {
+ idlc()->setParseState(PS_MemberDeclsSeen);
+ }
+ ';'
+ {
+ idlc()->setParseState(PS_MemberDeclsCompleted);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstMember* pMember = NULL;
+ FeDeclList* pList = $3;
+ FeDeclarator* pDecl = NULL;
+ AstType const * pType = NULL;
+
+ // !!! check recursive type
+
+ if ( pScope && pList && $1 )
+ {
+ FeDeclList::iterator iter = pList->begin();
+ FeDeclList::iterator end = pList->end();
+ while (iter != end)
+ {
+ pDecl = (*iter);
+ if ( !pDecl )
+ {
+ iter++;
+ continue;
+ }
+
+ pType = pDecl->compose($1);
+
+ if ( !pType )
+ {
+ iter++;
+ continue;
+ }
+
+ pMember = new AstMember(pType, pDecl->getName(), pScope);
+
+ if ( !pDecl->checkType($1) )
+ {
+ // WARNING
+ }
+
+ pScope->addDeclaration(pMember);
+ iter++;
+ delete pDecl;
+ }
+ delete pList;
+ }
+ }
+ | error ';'
+ {
+ yyerror("member definition");
+ yyerrok;
+ }
+ ;
+
+type_or_parameter:
+ fundamental_type
+ | scoped_name opt_type_args
+ {
+ AstDeclaration const * decl = 0;
+ AstStruct * scope = static_cast< AstStruct * >(idlc()->scopes()->top());
+ if (scope != 0 && $2 == 0) {
+ decl = scope->findTypeParameter(*$1);
+ }
+ if (decl != 0) {
+ delete $1;
+ delete $2;
+ } else {
+ decl = createNamedType($1, $2);
+ if (scope != 0 && includes(decl, scopeAsDecl(scope))) {
+ idlc()->error()->error1(
+ EIDL_RECURSIVE_TYPE, scopeAsDecl(scope));
+ decl = 0;
+ }
+ }
+ $$ = decl;
+ }
+ ;
+
+enum_type :
+ IDL_ENUM
+ {
+ idlc()->setParseState(PS_EnumSeen);
+ }
+ identifier
+ {
+ idlc()->setParseState(PS_EnumIDSeen);
+ checkIdentifier($3);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstEnum* pEnum = NULL;
+
+ /*
+ * Create a node representing an enum and add it to its
+ * enclosing scope
+ */
+ if (pScope != NULL)
+ {
+ pEnum = new AstEnum(*$3, pScope);
+ /*
+ * Add it to its defining scope
+ */
+ pScope->addDeclaration(pEnum);
+ }
+ delete $3;
+ /*
+ * Push the enum scope on the scopes stack
+ */
+ idlc()->scopes()->push(pEnum);
+
+ }
+ '{'
+ {
+ idlc()->setParseState(PS_EnumSqSeen);
+ }
+ at_least_one_enumerator
+ {
+ idlc()->setParseState(PS_EnumBodySeen);
+ }
+ '}'
+ {
+ idlc()->setParseState(PS_EnumQsSeen);
+ /*
+ * Done with this enum. Pop its scope from the scopes stack
+ */
+ if (idlc()->scopes()->top() == NULL)
+ $$ = NULL;
+ else
+ {
+ $$ = (AstEnum*)idlc()->scopes()->topNonNull();
+ idlc()->scopes()->pop();
+ }
+ }
+ ;
+
+at_least_one_enumerator : enumerator enumerators ;
+
+enumerators :
+ enumerators
+ ','
+ {
+ idlc()->setParseState(PS_EnumCommaSeen);
+ }
+ enumerator
+ | /* EMPTY */
+ | error ','
+ {
+ yyerror("enumerator definition");
+ yyerrok;
+ }
+ ;
+
+enumerator :
+ identifier
+ {
+ checkIdentifier($1);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstEnum* pEnum = NULL;
+ AstConstant* pEnumVal = NULL;
+
+ if ( pScope && pScope->getScopeNodeType() == NT_enum)
+ {
+ pEnum = (AstEnum*)pScope;
+ if (pEnum && $1)
+ {
+ AstExpression* pExpr = new AstExpression(pEnum->getEnumValueCount());
+ pEnumVal = new AstConstant(ET_long , NT_enum_val,
+ pExpr, *$1, pScope);
+ }
+ if ( pEnum->checkValue(pEnumVal->getConstValue()) )
+ idlc()->error()->error1(EIDL_EVAL_ERROR, pEnum);
+
+ pScope->addDeclaration(pEnumVal);
+ }
+ delete $1;
+ }
+ | identifier
+ '='
+ const_expr
+ {
+ checkIdentifier($1);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstEnum* pEnum = NULL;
+ AstConstant* pEnumVal = NULL;
+
+ if ( $3 && pScope && pScope->getScopeNodeType() == NT_enum)
+ {
+ $3->evaluate(EK_const);
+ if ( $3->coerce(ET_long) )
+ {
+ pEnum = (AstEnum*)pScope;
+ if (pEnum)
+ {
+ pEnumVal = new AstConstant(ET_long , NT_enum_val,
+ $3, *$1, pScope);
+ }
+ if ( pEnum->checkValue(pEnumVal->getConstValue()) )
+ idlc()->error()->error1(EIDL_EVAL_ERROR, pEnum);
+
+ pScope->addDeclaration(pEnumVal);
+ } else
+ {
+ idlc()->error()->coercionError($3, ET_long);
+ delete $3;
+ }
+ }
+ delete $1;
+ }
+ ;
+
+union_type :
+ IDL_UNION
+ {
+ idlc()->setParseState(PS_UnionSeen);
+ }
+ identifier
+ {
+ idlc()->setParseState(PS_UnionIDSeen);
+ checkIdentifier($3);
+ }
+ IDL_SWITCH
+ {
+ idlc()->setParseState(PS_SwitchSeen);
+ }
+ '('
+ {
+ idlc()->setParseState(PS_SwitchOpenParSeen);
+ }
+ switch_type_spec
+ {
+ idlc()->setParseState(PS_SwitchTypeSeen);
+ }
+ ')'
+ {
+ idlc()->setParseState(PS_SwitchCloseParSeen);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstUnion* pUnion = NULL;
+
+ /*
+ * Create a node representing a union. Add it to its enclosing
+ * scope
+ */
+ if ( $9 && pScope )
+ {
+ AstType* pType = (AstType*)$9;
+ if ( !pType)
+ {
+ idlc()->error()->noTypeError($9);
+ } else
+ {
+ pUnion = new AstUnion(*$3, pType, pScope);
+ pScope->addDeclaration(pUnion);
+ }
+ }
+ delete $3;
+ /*
+ * Push the scope of the union on the scopes stack
+ */
+ idlc()->scopes()->push(pUnion);
+ }
+ '{'
+ {
+ idlc()->setParseState(PS_UnionSqSeen);
+ }
+ at_least_one_case_branch
+ {
+ idlc()->setParseState(PS_UnionBodySeen);
+ }
+ '}'
+ {
+ idlc()->setParseState(PS_UnionQsSeen);
+ /* this union is finished, pop its scope from the stack */
+ idlc()->scopes()->pop();
+ }
+ ;
+
+switch_type_spec :
+ integer_type
+ {
+ $$ = idlc()->scopes()->bottom()->lookupPrimitiveType($1);
+ }
+ | char_type
+ {
+ $$ = idlc()->scopes()->bottom()->lookupPrimitiveType($1);
+ }
+ | boolean_type
+ {
+ $$ = idlc()->scopes()->bottom()->lookupPrimitiveType($1);
+ }
+ | enum_type
+ | scoped_name
+ {
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstBaseType* pBaseType = NULL;
+ AstDeclaration const * pDecl = NULL;
+ AstTypeDef* pTypeDef = NULL;
+ sal_Bool bFound = sal_False;
+ /*
+ * If the constant's type is a scoped name, it must resolve
+ * to a scalar constant type
+ */
+ if ( pScope && (pDecl = pScope->lookupByName(*$1)) )
+ {
+ /*
+ * Look through typedefs
+ */
+ while ( !bFound )
+ {
+ switch (pDecl->getNodeType())
+ {
+ case NT_enum:
+ $$ = pDecl;
+ bFound = sal_True;
+ break;
+ case NT_predefined:
+ pBaseType = (AstBaseType*)pDecl;
+ if ( pBaseType )
+ {
+ switch (pBaseType->getExprType())
+ {
+ case ET_short:
+ case ET_ushort:
+ case ET_long:
+ case ET_ulong:
+ case ET_hyper:
+ case ET_uhyper:
+ case ET_char:
+ case ET_byte:
+ case ET_boolean:
+ $$ = pBaseType;
+ bFound = sal_True;
+ break;
+ default:
+ $$ = NULL;
+ bFound = sal_True;
+ break;
+ }
+ }
+ break;
+ case NT_typedef:
+ pTypeDef = (AstTypeDef*)pDecl;
+ if ( pTypeDef )
+ pDecl = pTypeDef->getBaseType();
+ break;
+ default:
+ $$ = NULL;
+ bFound = sal_True;
+ break;
+ }
+ }
+ } else
+ $$ = NULL;
+
+ if ($$ == NULL)
+ idlc()->error()->lookupError(*$1);
+ }
+ ;
+
+at_least_one_case_branch : case_branch case_branches ;
+
+case_branches :
+ case_branches case_branch
+ | /* EMPTY */
+ ;
+
+case_branch :
+ at_least_one_case_label
+ {
+ idlc()->setParseState(PS_UnionLabelSeen);
+ }
+ element_spec
+ {
+ idlc()->setParseState(PS_UnionElemSeen);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ AstUnionLabel* pLabel = NULL;
+ AstUnionBranch* pBranch = NULL;
+ AstMember* pMember = $3;
+
+ /*
+ * Create several nodes representing branches of a union.
+ * Add them to the enclosing scope (the union scope)
+ */
+ if ( pScope && $1 && $3 )
+ {
+ LabelList::iterator iter = $1->begin();
+ LabelList::iterator end = $1->end();
+ for (;iter != end; iter++)
+ {
+ pLabel = *iter;
+ if ( !pLabel )
+ {
+ iter++;
+ continue;
+ }
+ pBranch = new AstUnionBranch(pLabel, pMember->getType(),
+ pMember->getLocalName(), pScope);
+ pScope->addDeclaration(pBranch);
+ }
+ }
+ if ( $1 ) delete($1);
+ }
+ ;
+
+at_least_one_case_label :
+ case_label case_labels
+ {
+ if ( $2 )
+ {
+ $2->push_front($1);
+ $$ = $2;
+ } else
+ {
+ LabelList* pLabels = new LabelList();
+ pLabels->push_back($1);
+ $$ = pLabels;
+ }
+ }
+ ;
+
+case_labels :
+ case_labels case_label
+ {
+ if ( $1 )
+ {
+ $1->push_back($2);
+ $$ = $1;
+ } else
+ {
+ LabelList* pLabels = new LabelList();
+ pLabels->push_back($2);
+ $$ = pLabels;
+ }
+ }
+ | /* EMPTY */
+ {
+ $$ = NULL;
+ }
+ ;
+
+case_label :
+ IDL_DEFAULT
+ {
+ idlc()->setParseState(PS_DefaultSeen);
+ }
+ ':'
+ {
+ idlc()->setParseState(PS_LabelColonSeen);
+ $$ = new AstUnionLabel(UL_default, NULL);
+ }
+ | IDL_CASE
+ {
+ idlc()->setParseState(PS_CaseSeen);
+ }
+ const_expr
+ {
+ idlc()->setParseState(PS_LabelExprSeen);
+ }
+ ':'
+ {
+ idlc()->setParseState(PS_LabelColonSeen);
+ $$ = new AstUnionLabel(UL_label, $3);
+ }
+ ;
+
+element_spec :
+ type_spec
+ {
+ idlc()->setParseState(PS_UnionElemTypeSeen);
+ }
+ declarator
+ {
+ idlc()->setParseState(PS_UnionElemDeclSeen);
+ }
+ ';'
+ {
+ idlc()->setParseState(PS_UnionElemCompleted);
+
+ AstScope* pScope = idlc()->scopes()->topNonNull();
+ /*
+ * Check for illegal recursive use of type
+ */
+// if ( $1 && AST_illegal_recursive_type($1))
+// idlc()->error()->error1(EIDL_RECURSIVE_TYPE, $1);
+ /*
+ * Create a field in a union branch
+ */
+ if ( $1 && $3 )
+ {
+ AstType const * pType = $3->compose($1);
+ if ( !pType )
+ $$ = NULL;
+ else
+ $$ = new AstMember(pType, $3->getName(), pScope);
+ } else
+ $$ = NULL;
+
+ if ( $3 ) delete $3;
+ }
+ | error
+ ';'
+ {
+ $$ = NULL;
+ }
+ ;
+
+identifier:
+ IDL_IDENTIFIER
+ | IDL_GET { $$ = new OString("get"); }
+ | IDL_SET { $$ = new OString("set"); }
+ | IDL_PUBLISHED { $$ = new OString("published"); }
+ ;
+
+%%
+
+/*
+ * Report an error situation discovered in a production
+ */
+void yyerror(char const *errmsg)
+{
+ idlc()->error()->syntaxError(idlc()->getParseState(), idlc()->getLineNumber(), errmsg);
+ idlc()->setParseState(PS_NoState);
+}