/************************************************************************* * * $RCSfile: parser.y,v $ * * $Revision: 1.3 $ * * last change: $Author: hr $ $Date: 2003-03-26 12:11:09 $ * * 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 #ifndef _IDLC_IDLC_HXX_ #include #endif #ifndef _IDLC_ERRORHANDLER_HXX_ #include #endif #ifndef _IDLC_FEHELPER_HXX_ #include #endif #ifndef _IDLC_EXPRESSION_HXX_ #include #endif #ifndef _IDLC_ASTCONSTANTS_HXX_ #include #endif #ifndef _IDLC_ASTCONSTANT_HXX_ #include #endif #ifndef _IDLC_ASTARRAY_HXX_ #include #endif #ifndef _IDLC_ASTBASETYPE_HXX_ #include #endif #ifndef _IDLC_ASTTYPEDEF_HXX_ #include #endif #ifndef _IDLC_ASTEXCEPTION_HXX_ #include #endif #ifndef _IDLC_ASTMEMBER_HXX_ #include #endif #ifndef _IDLC_ASTENUM_HXX_ #include #endif #ifndef _IDLC_ASTSEQUENCE_HXX_ #include #endif #ifndef _IDLC_ASTATTRIBUTE_HXX_ #include #endif #ifndef _IDLC_ASTOPERATION_HXX_ #include #endif #ifndef _IDLC_ASTPARAMETER_HXX_ #include #endif #ifndef _IDLC_ASTINTERFACEMEMBER_HXX_ #include #endif #ifndef _IDLC_ASTSERVICEMEMBER_HXX_ #include #endif #ifndef _IDLC_ASTOBSERVES_HXX_ #include #endif #ifndef _IDLC_ASTNEEDS_HXX_ #include #endif #ifndef _IDLC_ASTUNION_HXX_ #include #endif #ifdef WNT #include 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 IDL_IDENTIFIER %token IDL_ATTRIBUTE %token IDL_BOUND %token IDL_CASE %token IDL_CONST %token IDL_CONSTANTS %token IDL_CONSTRAINED %token IDL_DEFAULT %token IDL_ENUM %token IDL_EXCEPTION %token IDL_INTERFACE %token IDL_MAYBEAMBIGUOUS %token IDL_MAYBEDEFAULT %token IDL_MAYBEVOID %token IDL_MODULE %token IDL_NEEDS %token IDL_OBSERVES %token IDL_OPTIONAL %token IDL_PROPERTY %token IDL_RAISES %token IDL_READONLY %token IDL_REMOVEABLE %token IDL_SERVICE %token IDL_SEQUENCE %token IDL_SINGLETON %token IDL_STRUCT %token IDL_SWITCH %token IDL_TYPEDEF %token IDL_TRANSIENT %token IDL_UNION %token IDL_ANY %token IDL_CHAR %token IDL_BOOLEAN %token IDL_BYTE %token IDL_DOUBLE %token IDL_FLOAT %token IDL_HYPER %token IDL_LONG %token IDL_SHORT %token IDL_VOID %token IDL_STRING %token IDL_TYPE %token IDL_UNSIGNED %token IDL_TRUE %token IDL_FALSE %token IDL_IN %token IDL_OUT %token IDL_INOUT %token IDL_ONEWAY %token IDL_LEFTSHIFT %token IDL_RIGHTSHIFT %token IDL_SCOPESEPARATOR %token IDL_INTEGER_LITERAL %token IDL_STRING_LITERAL %token IDL_FLOATING_PT_LITERAL %token IDL_CHARACTER_LITERAL /* * These are production names: */ %type type_dcl const_dcl struct_type union_type enum_type %type constructed_type_spec type_spec simple_type_spec op_type_spec %type template_type_spec sequence_type_spec switch_type_spec %type array_declarator array_type %type interface_decl %type scoped_name %type scoped_names at_least_one_scoped_name inheritance_spec opt_raises %type const_type integer_type char_type boolean_type %type floating_pt_type any_type signed_int string_type %type unsigned_int base_type_spec byte_type type_type %type expression const_expr or_expr xor_expr and_expr %type add_expr mult_expr unary_expr primary_expr shift_expr %type literal positive_int_expr array_dim %type at_least_one_array_dim array_dims %type declarator simple_declarator complex_declarator %type declarators at_least_one_declarator %type exception_header structure_header %type interfaceheader %type flag_header opt_attrflags opt_attrflag operation_head %type direction service_interface_header service_service_header %type case_labels at_least_one_case_label %type case_label %type 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 { if ( $1->getInherits() ) 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; } | error ']' { yyerror("unknown property|attribute flag"); yyerrok; } ; 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); }