office-gobmx/idlc/source/parser.y
Jens-Heiner Rechtien 35a3552dfb INTEGRATION: CWS sb10 (1.4.2); FILE MERGED
2003/12/10 09:12:20 sb 1.4.2.1: #114000# Adapted to multiple-inheritance interface types.
2004-02-03 11:00:25 +00:00

2889 lines
54 KiB
Text

/*************************************************************************
*
* $RCSfile: parser.y,v $
*
* $Revision: 1.5 $
*
* last change: $Author: hr $ $Date: 2004-02-03 12:00:25 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library 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 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (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.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
/*
* parser.yy - BISON grammar for IDLC 1.0
*/
%{
#include <hash_map>
#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 "rtl/strbuf.hxx"
#ifdef WNT
#include <stdarg.h>
namespace std {
int fprintf(FILE* stream, const char* format, ...)
{
va_list va_param;
va_start(va_param, format);
int res = ::vfprintf(stream, format, va_param);
va_end(va_param);
return res;
}
void* malloc( size_t size )
{
return ::malloc(size);
}
void free( void *memblock )
{
::free(memblock);
}
};
#endif
using namespace ::rtl;
#define YYDEBUG 1
#define YYERROR_VERBOSE 1
extern int yylex(void);
void yyerror(char *);
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());
}
}
typedef std::hash_map< rtl::OString, AstDeclaration *, rtl::OStringHash >
NameMap;
void checkNameClashes(AstInterface * pInterface, NameMap & map)
{
DeclList const & super = pInterface->getInheritedInterfaces();
{for (DeclList::const_iterator i(super.begin()); i != super.end(); ++i) {
checkNameClashes(static_cast< AstInterface * >(*i), map);
}}
{for (DeclList::iterator i(pInterface->getIteratorBegin());
i != pInterface->getIteratorEnd(); ++i) {
std::pair< NameMap::iterator, bool > res(
map.insert(NameMap::value_type((*i)->getLocalName(), *i)));
if (!res.second
&& res.first->second->getScopedName() != (*i)->getScopedName())
{
idlc()->error()->error2(EIDL_REDEF_SCOPE, *i, res.first->second);
}
}}
}
void checkNameClashes(AstInterface * pInterface)
{
NameMap map;
checkNameClashes(pInterface, map);
}
void addInheritedInterface(AstInterface * ifc, rtl::OString const & name)
{
AstDeclaration * decl = ifc->lookupByName(name);
if (decl != 0 && decl->getNodeType() == NT_interface) {
if (!static_cast< AstInterface * >(decl)->isDefined()) {
idlc()->error()->inheritanceError(
NT_interface, &ifc->getScopedName(), decl);
} else if (!ifc->addInheritedInterface(
static_cast< AstInterface * >(decl))) {
idlc()->error()->error1(EIDL_DOUBLE_INHERITANCE, decl);
}
} else {
idlc()->error()->lookupError(
EIDL_INTERFACEMEMBER_LOOKUP, name, scopeAsDecl(ifc));
}
}
%}
/*
* Declare the type of values in the grammar
*/
%union {
ExprType etval; /* Expression type */
AstDeclaration* dclval; /* Declaration */
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 */
sal_Char* strval; /* sal_Char* value */
sal_Char cval; /* sal_Char value */
sal_Bool bval; /* sal_Boolean* value */
sal_Int64 ival; /* sal_Int64 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 */
}
/*
* 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 <strval> IDL_LEFTSHIFT
%token <strval> IDL_RIGHTSHIFT
%token <strval> IDL_SCOPESEPARATOR
%token <ival> IDL_INTEGER_LITERAL
%token <sval> IDL_STRING_LITERAL
%token <dval> IDL_FLOATING_PT_LITERAL
%token <cval> IDL_CHARACTER_LITERAL
/*
* These are production names:
*/
%type <dclval> type_dcl const_dcl struct_type union_type enum_type
%type <dclval> constructed_type_spec type_spec simple_type_spec op_type_spec
%type <dclval> template_type_spec sequence_type_spec switch_type_spec
%type <dclval> array_declarator array_type
%type <sval> interface_decl
%type <sval> scoped_name inheritance_spec
%type <slval> scoped_names at_least_one_scoped_name opt_raises
%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
%%
/*
* Grammar start here
*/
start : definitions;
definitions :
definition definitions
| /* EMPTY */
;
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);
}
| module_dcl
{
idlc()->setParseState(PS_ModuleDeclSeen);
}
';'
{
idlc()->setParseState(PS_NoState);
}
| constants_dcl
{
idlc()->setParseState(PS_ConstantsDeclSeen);
}
';'
{
idlc()->setParseState(PS_NoState);
}
| error ';'
{
yyerror("definitions");
yyerrok;
}
;
module_dcl :
IDL_MODULE
{
idlc()->setParseState(PS_ModuleSeen);
}
IDL_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());
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);
}
IDL_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(), $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));
}
}
/*
* All OK, set full definition
*/
else
{
pForward->forwardDefined(*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->nInheritedInterfaces() == 0
&& ifc->getScopedName() != "com::sun::star::uno::XInterface")
{
addInheritedInterface(
ifc, rtl::OString("::com::sun::star::uno::XInterface"));
}
ifc->setDefined();
checkNameClashes(ifc);
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);
delete $2;
}
;
inheritance_spec :
':'
{
idlc()->setParseState(PS_InheritColonSeen);
}
scoped_name
{
$$ = $3;
}
| /* EMPTY */
{
$$ = NULL;
}
;
exports :
exports export
| /* EMPTY */
;
export :
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);
}
| 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);
}
at_least_one_declarator
{
idlc()->setParseState(PS_AttrCompleted);
AstScope* pScope = idlc()->scopes()->topNonNull();
AstAttribute* pAttr = NULL;
FeDeclList* pList = $4;
FeDeclarator* pDecl = NULL;
AstType* pType = NULL;
if ( !((AF_ATTRIBUTE == $1) ||
((AF_ATTRIBUTE | AF_READONLY) == $1)) )
{
idlc()->error()->flagError(EIDL_ATTRIBUTEREADONLYEXPECTED, $1);
}
/*
* Create nodes representing attributes and add them to the
* enclosing scope
*/
if ( pScope && $1 && $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($1, pType, pDecl->getName(), pScope);
pScope->addDeclaration(pAttr);
iter++;
delete pDecl;
}
delete pList;
}
}
;
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;
}
;
operation :
operation_head
op_type_spec
{
idlc()->setParseState(PS_OpTypeSeen);
}
IDL_IDENTIFIER
{
idlc()->setParseState(PS_OpIDSeen);
checkIdentifier($4);
AstScope* pScope = idlc()->scopes()->topNonNull();
AstOperation* pOp = NULL;
AstType* pType = 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);
pScope->addDeclaration(pOp);
}
}
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
{
idlc()->setParseState(PS_OpRaiseCompleted);
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 ( $12 && pOp )
pOp->addExceptions($12);
}
if ( $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);
}
declarator
{
idlc()->setParseState(PS_OpParDeclSeen);
AstScope* pScope = idlc()->scopes()->topNonNull();
AstParameter* pParam = NULL;
AstType* pType = NULL;
/*
* Create a node representing an argument to an operation
* Add it to the enclosing scope (the operation scope)
*/
if ( pScope && $5 && $7 )
{
AstType *pType = $7->compose($5);
if ( pType )
{
pParam = new AstParameter((Direction)$2, pType, $7->getName(), pScope);
if ( !$7->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_raises :
IDL_RAISES
{
idlc()->setParseState(PS_OpRaiseSeen);
}
'('
{
idlc()->setParseState(PS_OpRaiseSqSeen);
}
at_least_one_scoped_name
')'
{
idlc()->setParseState(PS_OpRaiseQsSeen);
$$ = $5;
}
| /* EMPTY */
{
$$ = NULL;
}
;
interface_inheritance_decl :
IDL_INTERFACE
{
idlc()->setParseState(PS_ServiceIFHeadSeen);
}
at_least_one_scoped_name
{
AstInterface * ifc = static_cast< AstInterface * >(
idlc()->scopes()->topNonNull());
if (ifc->usesSingleInheritance()) {
idlc()->error()->error0(EIDL_MIXED_INHERITANCE);
} else {
for (StringList::iterator i($3->begin()); i != $3->end(); ++i) {
addInheritedInterface(ifc, *i);
}
}
delete $3;
}
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);
}
IDL_IDENTIFIER
{
idlc()->setParseState(PS_ConstIDSeen);
checkIdentifier($5);
}
'='
{
idlc()->setParseState(PS_ConstAssignSeen);
}
expression
{
idlc()->setParseState(PS_ConstExprSeen);
AstScope* pScope = idlc()->scopes()->topNonNull();
AstConstant* pConstant = NULL;
AstDeclaration* pExists = 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);
}
IDL_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, sal_True);
}
| literal
| '(' const_expr ')'
{
$$ = $2;
}
;
literal :
IDL_INTEGER_LITERAL
{
$$ = new AstExpression($1);
}
| IDL_STRING_LITERAL
{
$$ = new AstExpression($1);
}
| IDL_CHARACTER_LITERAL
{
$$ = 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();
AstBaseType* pBaseType = NULL;
AstDeclaration* pDecl = NULL;
AstTypeDef* pTypeDef = NULL;
/*
* 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 ( pDecl->getNodeType() == NT_typedef )
{
pTypeDef = (AstTypeDef*)pDecl;
if ( !pTypeDef )
break;
pDecl = pTypeDef->getBaseType();
}
if ( !pDecl )
$$ = ET_any;
else
if (pDecl->getNodeType() == NT_predefined)
{
pBaseType = (AstBaseType*)pDecl;
if (pBaseType)
{
$$ = pBaseType->getExprType();
} else
{
$$ = ET_any;
}
} else
$$ = ET_any;
} else
$$ = ET_any;
}
;
exception_header :
IDL_EXCEPTION
{
idlc()->setParseState(PS_ExceptSeen);
}
IDL_IDENTIFIER
{
idlc()->setParseState(PS_ExceptIDSeen);
checkIdentifier($3);
}
inheritance_spec
{
idlc()->setParseState(PS_InheritSpecSeen);
$$ = new FeInheritanceHeader(NT_exception, $3, $5);
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* 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) )
{
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);
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);
}
IDL_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);
}
'{'
{
idlc()->setParseState(PS_ServiceSqSeen);
}
service_exports
{
idlc()->setParseState(PS_ServiceBodySeen);
}
'}'
{
idlc()->setParseState(PS_ServiceQsSeen);
/* this service is finished, pop its scope from the stack */
idlc()->scopes()->pop();
}
;
singleton_dcl :
IDL_SINGLETON
{
idlc()->setParseState(PS_SingletonSeen);
}
IDL_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);
}
'{'
{
idlc()->setParseState(PS_SingletonSqSeen);
}
service_exports
{
idlc()->setParseState(PS_SingletonBodySeen);
}
'}'
{
idlc()->setParseState(PS_SingletonQsSeen);
/* this singelton is finished, pop its scope from the stack */
idlc()->scopes()->pop();
}
;
type_dcl :
IDL_TYPEDEF
{
idlc()->setParseState(PS_TypedefSeen);
}
type_declarator {}
| struct_type {}
| union_type {}
| enum_type {}
;
type_declarator :
type_spec
{
idlc()->setParseState(PS_TypeSpecSeen);
}
at_least_one_declarator
{
idlc()->setParseState(PS_DeclaratorsSeen);
AstScope* pScope = idlc()->scopes()->topNonNull();
AstTypeDef* pTypeDef = NULL;
FeDeclList* pList = $3;
FeDeclarator* pDecl = NULL;
AstType* 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 :
IDL_IDENTIFIER
{
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 :
IDL_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 :
IDL_IDENTIFIER
{
idlc()->setParseState(PS_SN_IDSeen);
checkIdentifier($1);
$$ = $1;
}
| IDL_SCOPESEPARATOR
{
idlc()->setParseState(PS_ScopeDelimSeen);
}
IDL_IDENTIFIER
{
checkIdentifier($3);
OString* pName = new OString("::");
*pName += *$3;
delete $3;
$$ = pName;
}
| scoped_name
IDL_SCOPESEPARATOR
{
}
IDL_IDENTIFIER
{
checkIdentifier($4);
*$1 += ::rtl::OString("::");
*$1 += *$4;
delete $4;
$$ = $1;
}
;
type_spec :
simple_type_spec
| constructed_type_spec
;
simple_type_spec :
base_type_spec
{
$$ = idlc()->scopes()->bottom()->lookupPrimitiveType($1);
}
| template_type_spec
| scoped_name
{
AstScope* pScope = idlc()->scopes()->topNonNull();
AstDeclaration* pDecl = NULL;
if ( pScope )
pDecl = pScope->lookupByName(*$1);
if ( pDecl )
{
if ( !pDecl->isType() )
{
idlc()->error()->noTypeError(pDecl);
pDecl = NULL;
}
} else
{
idlc()->error()->lookupError(*$1);
}
delete $1;
$$ = pDecl;
}
;
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;
}
;
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(), 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);
}
IDL_IDENTIFIER
{
idlc()->setParseState(PS_StructIDSeen);
checkIdentifier($3);
}
inheritance_spec
{
idlc()->setParseState(PS_InheritSpecSeen);
$$ = new FeInheritanceHeader(NT_struct, $3, $5);
delete $5;
}
;
at_least_one_member : member members ;
members :
members member
| /* EMPTY */
;
member :
type_spec
{
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* 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;
}
;
enum_type :
IDL_ENUM
{
idlc()->setParseState(PS_EnumSeen);
}
IDL_IDENTIFIER
{
idlc()->setParseState(PS_EnumIDSeen);
checkIdentifier($3);
AstScope* pScope = idlc()->scopes()->topNonNull();
AstEnum* pEnum = NULL;
AstDeclaration* pDecl = 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 :
IDL_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;
}
| IDL_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);
}
IDL_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;
AstDeclaration* pDecl = 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* 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* pType = $3->compose($1);
if ( !pType )
$$ = NULL;
else
$$ = new AstMember(pType, $3->getName(), pScope);
} else
$$ = NULL;
if ( $3 ) delete $3;
}
| error
';'
{
$$ = NULL;
}
;
%%
/*
* Report an error situation discovered in a production
*/
void yyerror(char *errmsg)
{
idlc()->error()->syntaxError(idlc()->getParseState(), idlc()->getLineNumber(), errmsg);
idlc()->setParseState(PS_NoState);
}