blob: 09794104528221834b959702a5fd93e67abe37f2 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the 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);
}