summaryrefslogtreecommitdiff
path: root/idlc
diff options
context:
space:
mode:
authorHans-Joachim Lankenau <hjs@openoffice.org>2002-07-10 08:43:18 +0000
committerHans-Joachim Lankenau <hjs@openoffice.org>2002-07-10 08:43:18 +0000
commitc697bf077d05a3a171258dfdc31bd29596b85196 (patch)
tree90f055f8a681263cca94b992499e85d2ef69ddc8 /idlc
parent8f2f4960f98c2e1d5963939f69b74d5ba1b4cf0f (diff)
#100157# yacc files must have the extension .y
Diffstat (limited to 'idlc')
-rw-r--r--idlc/source/parser.y2776
1 files changed, 2776 insertions, 0 deletions
diff --git a/idlc/source/parser.y b/idlc/source/parser.y
new file mode 100644
index 000000000000..3ad168eacb97
--- /dev/null
+++ b/idlc/source/parser.y
@@ -0,0 +1,2776 @@
+/*************************************************************************
+ *
+ * $RCSfile: parser.y,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: hjs $ $Date: 2002-07-10 09:43:18 $
+ *
+ * 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 <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
+
+#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 *);
+
+%}
+/*
+ * 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 */
+ FeInterfaceHeader* ifval; /* interface 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
+%type <slval> scoped_names at_least_one_scoped_name inheritance_spec 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
+%type <ifval> 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);
+
+ 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);
+ $$ = $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, sal_False, 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(), sal_True, 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->setInheritedInterfaces(*$1->getInherits());
+
+ pForward->setImported(pInterface->isImported());
+ pForward->setInMainfile(pInterface->isInMainfile());
+ pForward->setLineNumber(pInterface->getLineNumber());
+ pForward->setFileName(pInterface->getFileName());
+
+ pForward->setDocumentation(pInterface->getDocumentation());
+ pForward->setDefined(sal_True);
+
+ 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
+ {
+ 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);
+
+ FeInterfaceHeader* ih = new FeInterfaceHeader(NT_interface,$1, $2);
+ delete $2;
+ $$ = ih;
+ }
+ ;
+
+inheritance_spec :
+ ':'
+ {
+ idlc()->setParseState(PS_InheritColonSeen);
+ }
+ at_least_one_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);
+ }
+ ;
+
+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;
+ }
+ ;
+
+operation :
+ operation_head
+ op_type_spec
+ {
+ idlc()->setParseState(PS_OpTypeSeen);
+ }
+ IDL_IDENTIFIER
+ {
+ idlc()->setParseState(PS_OpIDSeen);
+
+ 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;
+ }
+ ;
+
+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);
+ }
+ '='
+ {
+ 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);
+ }
+ '{'
+ {
+ 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);
+ }
+ 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 = NULL;
+ if ( $1->nInherits() )
+ pBase = (AstException*)$1->getInherits()->front();
+
+ pExcept = new AstException(*$1->getName(), pBase, pScope);
+
+ if ( $1->nInherits() > 1 )
+ idlc()->error()->error1(EIDL_MULTIBLE_INHERITANCE, pExcept);
+
+ 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);
+
+ 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);
+
+ 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
+ {
+ $$ = 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);
+ }
+ 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);
+ $$ = $1;
+ }
+ | IDL_SCOPESEPARATOR
+ {
+ idlc()->setParseState(PS_ScopeDelimSeen);
+ }
+ IDL_IDENTIFIER
+ {
+ OString* pName = new OString("::");
+ *pName += *$3;
+ delete $3;
+ $$ = pName;
+ }
+ | scoped_name
+ IDL_SCOPESEPARATOR
+ {
+ }
+ IDL_IDENTIFIER
+ {
+ *$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= NULL;
+ if ( $1->nInherits() )
+ pBase = (AstStruct*)$1->getInherits()->front();
+
+ pStruct = new AstStruct(*$1->getName(), pBase, pScope);
+
+ if ( $1->nInherits() > 1 )
+ idlc()->error()->error1(EIDL_MULTIBLE_INHERITANCE, pStruct);
+
+ 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);
+ }
+ 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);
+
+ 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
+ {
+ 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
+ {
+ 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);
+ }
+ 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);
+}