<commit_before>/*************************************************************************
 *
 *  $RCSfile: parser.y,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2004-03-30 16:48:22 $
 *
 *  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

#include "attributeexceptions.hxx"

#include "rtl/strbuf.hxx"
    
#ifdef WNT
#include <stdarg.h>
namespace std {
int fprintf(FILE* stream, const char* format, ...)
{
    va_list va_param;

    va_start(va_param, format);
	int res = ::vfprintf(stream, format, va_param);
    va_end(va_param);

    return res;
}

void* malloc( size_t size )
{
    return ::malloc(size);
}

void free( void *memblock )
{
    ::free(memblock);
}
    
};
#endif

using namespace ::rtl;

#define YYDEBUG 1
#define YYERROR_VERBOSE 1

extern int yylex(void);
void yyerror(char *);

void checkIdentifier(::rtl::OString* id)
{
    static short check = 0;
    if (check == 0) {
        if (idlc()->getOptions()->isValid("-cid"))
            check = 1;
        else
            check = 2;
    }

    if ( id->indexOf('_') >= 0 )
        if ( (id->pData->buffer[0] >= 97 && id->pData->buffer[0] <= 122)
             || id->pData->buffer[0] == '_') {
            if (check == 1) {
                ::rtl::OStringBuffer msg(25 + id->getLength());
                msg.append("mismatched identifier '");
                msg.append(*id);
                msg.append("'");
                idlc()->error()->syntaxError(idlc()->getParseState(),
                                         idlc()->getLineNumber(),
                                         msg.getStr());
            }
            else
                idlc()->error()->warning0(WIDL_WRONG_NAMING_CONV, id->getStr());
        }
}

void reportDoubleMemberDeclarations(
    AstInterface::DoubleMemberDeclarations const & doubleMembers)
{
    for (AstInterface::DoubleMemberDeclarations::const_iterator i(
             doubleMembers.begin());
         i != doubleMembers.end(); ++i)
    {
        idlc()->error()->error2(EIDL_DOUBLE_MEMBER, i->first, i->second);
    }
}

void addInheritedInterface(
    AstInterface * ifc, rtl::OString const & name, bool optional,
    rtl::OUString const & documentation)
{
    AstDeclaration * decl = ifc->lookupByName(name);
    if (decl != 0 && decl->getNodeType() == NT_interface) {
        if (!static_cast< AstInterface * >(decl)->isDefined()) {
            idlc()->error()->inheritanceError(
                NT_interface, &ifc->getScopedName(), decl);
        } else {
            AstInterface::DoubleDeclarations doubleDecls(
                ifc->checkInheritedInterfaceClashes(
                    static_cast< AstInterface * >(decl), optional));
            if (doubleDecls.interfaces.empty() && doubleDecls.members.empty()) {
                ifc->addInheritedInterface(
                    static_cast< AstInterface * >(decl), optional,
                    documentation);
            } else {
                for (AstInterface::DoubleInterfaceDeclarations::iterator i(
                         doubleDecls.interfaces.begin());
                     i != doubleDecls.interfaces.end(); ++i)
                {
                    idlc()->error()->error1(
                        EIDL_DOUBLE_INHERITANCE, *i);
                }
                reportDoubleMemberDeclarations(doubleDecls.members);
            }
        }
    } else {
        idlc()->error()->lookupError(
            EIDL_INTERFACEMEMBER_LOOKUP, name, scopeAsDecl(ifc));
    }
}

%}
/*
 * Declare the type of values in the grammar
 */
%union {
	ExprType				etval;     /* Expression type */
	AstDeclaration*		dclval;    /* Declaration */
    AstDeclaration const * cdclval;
    DeclList * dclsval;
	AstExpression*		exval;		/* expression value */
	ExprList*				exlval;	/* expression list value */
	FeDeclarator*			fdval;		/* declarator value */
	FeDeclList*			dlval;		/* declarator list value */
	FeInheritanceHeader*	ihval;		/* inheritance header value */
	::rtl::OString*		sval;		/* OString value */
	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 */
    AttributeExceptions attexcval;
}

/*
 * Token types: These are returned by the lexer
 */

%token <sval>		IDL_IDENTIFIER
%token 			IDL_ATTRIBUTE
%token				IDL_BOUND
%token 			IDL_CASE
%token 			IDL_CONST
%token 			IDL_CONSTANTS
%token				IDL_CONSTRAINED
%token 			IDL_DEFAULT
%token 			IDL_ENUM
%token 			IDL_EXCEPTION
%token 			IDL_INTERFACE
%token 			IDL_MAYBEAMBIGUOUS
%token 			IDL_MAYBEDEFAULT
%token 			IDL_MAYBEVOID
%token 			IDL_MODULE
%token 			IDL_NEEDS
%token 			IDL_OBSERVES
%token 			IDL_OPTIONAL
%token 			IDL_PROPERTY
%token 			IDL_RAISES
%token 			IDL_READONLY
%token 			IDL_REMOVEABLE
%token 			IDL_SERVICE
%token 			IDL_SEQUENCE
%token 			IDL_SINGLETON
%token 			IDL_STRUCT
%token 			IDL_SWITCH
%token 			IDL_TYPEDEF
%token				IDL_TRANSIENT
%token 			IDL_UNION

%token 			IDL_ANY
%token 			IDL_CHAR
%token 			IDL_BOOLEAN
%token 			IDL_BYTE
%token 			IDL_DOUBLE
%token 			IDL_FLOAT
%token 			IDL_HYPER
%token 			IDL_LONG
%token 			IDL_SHORT
%token 			IDL_VOID
%token 			IDL_STRING
%token 			IDL_TYPE
%token 			IDL_UNSIGNED

%token 			IDL_TRUE
%token 			IDL_FALSE

%token 			IDL_IN
%token 			IDL_OUT
%token 			IDL_INOUT
%token 			IDL_ONEWAY

%token IDL_GET
%token IDL_SET

%token IDL_ELLIPSIS

%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
%type <dclval>	array_declarator
%type <dclval>  exception_name
%type <cdclval> array_type constructed_type_spec enum_type op_type_spec
%type <cdclval> sequence_type_spec simple_type_spec struct_type switch_type_spec
%type <cdclval> template_type_spec type_spec union_type
%type <dclsval> opt_raises raises exception_list exception_list_tail
%type <dclsval> opt_attribute_get_raises attribute_get_raises
%type <dclsval> opt_attribute_set_raises attribute_set_raises

%type <sval>    identifier
%type <sval>	interface_decl 
%type <sval>	scoped_name inheritance_spec
%type <slval>  	scoped_names at_least_one_scoped_name

%type <etval>	const_type integer_type char_type boolean_type
%type <etval>	floating_pt_type any_type signed_int string_type
%type <etval>	unsigned_int base_type_spec byte_type type_type 

%type <exval>	expression const_expr or_expr xor_expr and_expr
%type <exval>	add_expr mult_expr unary_expr primary_expr shift_expr
%type <exval>	literal positive_int_expr array_dim

%type <exlval> 	at_least_one_array_dim array_dims

%type <fdval> 	declarator simple_declarator complex_declarator
%type <dlval> 	declarators at_least_one_declarator

%type <ihval>	exception_header structure_header interfaceheader

%type <ulval> 	flag_header opt_attrflags opt_attrflag operation_head
%type <ulval>	direction service_interface_header service_service_header

%type <llval>	case_labels at_least_one_case_label
%type <lbval>	case_label
%type <mval>	element_spec

%type <bval>    optional_inherited_interface opt_rest

%type <attexcval> opt_attribute_block attribute_block_rest opt_attribute_raises

%%
/*
 * 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);
	}
	identifier
	{
        idlc()->setParseState(PS_ModuleIDSeen);
        checkIdentifier($3);

        AstScope* 		pScope = idlc()->scopes()->topNonNull();
        AstModule* 		pModule = NULL;
        AstDeclaration*	pExists = NULL;

        if ( pScope )
        {
        	pModule = new AstModule(*$3, pScope);
			if( (pExists = pScope->lookupForAdd(pModule)) )
			{
				pExists->setInMainfile(idlc()->isInMainFile());
				pExists->setFileName(pModule->getFileName());
				delete(pModule);
				pModule = (AstModule*)pExists;
			} else
			{
				pScope->addDeclaration(pModule);
			}
			idlc()->scopes()->push(pModule);
        }
        delete $3;
    }
    '{'
    {
        idlc()->setParseState(PS_ModuleSqSeen);
    }
	definitions
	{
		idlc()->setParseState(PS_ModuleBodySeen);
	}
	'}'
	{
		idlc()->setParseState(PS_ModuleQsSeen);
		/*
		 * Finished with this module - pop it from the scope stack
		 */
		idlc()->scopes()->pop();
	}
	;

interface :
	interface_dcl
	| forward_dcl
	; 

interface_decl :
	IDL_INTERFACE
	{
		idlc()->setParseState(PS_InterfaceSeen);
	}
	identifier
	{
		idlc()->setParseState(PS_InterfaceIDSeen);
       checkIdentifier($3);
		$$ = $3;
	}
	;

forward_dcl :
	interface_decl
	{
		idlc()->setParseState(PS_ForwardDeclSeen);

		AstScope* 		pScope = idlc()->scopes()->topNonNull();
		AstInterface*	pForward = NULL;
		AstDeclaration*	pDecl = NULL;

        /*
		 * Make a new forward interface node and add it to its enclosing scope
		 */
		if ( pScope && $1 ) 
		{
			pForward = new AstInterface(*$1, NULL, pScope);
			
			if ( pDecl = pScope->lookupByName(pForward->getScopedName()) ) 
			{
				if ( (pDecl != pForward) && 
					 (pDecl->getNodeType() == NT_interface) )
				{
					delete pForward;
				} else
				{
					idlc()->error()->error2(EIDL_REDEF_SCOPE, scopeAsDecl(pScope), pDecl);
				}
			} else
			{
				/*
				 * Add the interface to its definition scope
				 */
				pScope->addDeclaration(pForward);
			}
		}
		delete $1;
	}
	;

interface_dcl :
	interfaceheader
	{
		idlc()->setParseState(PS_InterfaceHeadSeen);

		AstScope* 		pScope = idlc()->scopes()->topNonNull();
		AstInterface*	pInterface = NULL;
		AstInterface*	pForward = NULL;
		AstDeclaration*	pDecl = NULL;

        /*
		 * Make a new interface node and add it to its enclosing scope
		 */
		if ( pScope && $1 ) 
		{
			pInterface = new AstInterface(
                *$1->getName(),
                static_cast< AstInterface * >($1->getInherits()), pScope);
			if ( pInterface &&
				(pDecl = pScope->lookupByName(pInterface->getScopedName())) ) 
			{
				/*
				 * See if we're defining a forward declared interface.
				 */
				if (pDecl->getNodeType() == NT_interface) 
				{
					pForward = (AstInterface*)pDecl;
					if ( !pForward->isDefined() ) 
					{
						/*
						 * Check if redefining in same scope
						 */
						if ( pForward->getScope() != pScope ) 
						{
							if ( pForward->getScopedName() != pInterface->getScopedName() )
							{
								idlc()->error()->error3(EIDL_SCOPE_CONFLICT,
										 pInterface, pForward, scopeAsDecl(pScope));
							}
						}
						/*
						 * All OK, set full definition
						 */
						else 
						{
                            pForward->forwardDefined(*pInterface);
							delete pInterface;
							pInterface = pForward;
						}
					}
				}
			} else
			{
				/*
				 * Add the interface to its definition scope
				 */
				pScope->addDeclaration(pInterface);
			}
		}
		/*
		 * Push it on the scope stack
		 */
		idlc()->scopes()->push(pInterface);
		delete($1);
	}
	'{'
	{
		idlc()->setParseState(PS_InterfaceSqSeen);
	}
	exports
	{
        AstInterface * ifc = static_cast< AstInterface * >(
            idlc()->scopes()->topNonNull());
        if (!ifc->hasMandatoryInheritedInterfaces()
            && ifc->getScopedName() != "com::sun::star::uno::XInterface")
        {
            addInheritedInterface(
                ifc, rtl::OString("::com::sun::star::uno::XInterface"), false,
                rtl::OUString());
        }
        ifc->setDefined();
		idlc()->setParseState(PS_InterfaceBodySeen);
	}
	'}'
	{
		idlc()->setParseState(PS_InterfaceQsSeen);
		/*
		 * Done with this interface - pop it off the scopes stack
		 */
		idlc()->scopes()->pop();
	}
	| error '}' 
	{
		yyerror("interface definition");
		yyerrok;
	}
	;

interfaceheader :
	interface_decl inheritance_spec
	{
		idlc()->setParseState(PS_InheritSpecSeen);

		$$ = new FeInheritanceHeader(NT_interface, $1, $2);
		delete $2;
	}
	;   

inheritance_spec :
	':'
	{
		idlc()->setParseState(PS_InheritColonSeen);
	}
	scoped_name
	{
        $$ = $3;
	}
	| /* EMPTY */
	{
		$$ = NULL;
	}
	;

exports :
	exports export
	| /* EMPTY */
	;

export :
    attribute
	{
		idlc()->setParseState(PS_AttributeDeclSeen);
	}
	';'
	{
		idlc()->setParseState(PS_NoState);
	}
	| operation
	{
		idlc()->setParseState(PS_OperationDeclSeen);
	}
	';'
	{
		idlc()->setParseState(PS_NoState);
	}
    | interface_inheritance_decl
    {
		idlc()->setParseState(PS_InterfaceInheritanceDeclSeen);
    }
    ';'
	{
		idlc()->setParseState(PS_NoState);
	}
    ;

attribute :
	flag_header
	simple_type_spec
	{
		idlc()->setParseState(PS_AttrTypeSeen);
	}
    simple_declarator
	{
		idlc()->setParseState(PS_AttrCompleted);
        if (($1 & ~(AF_BOUND | AF_READONLY)) != AF_ATTRIBUTE) {
            idlc()->error()->flagError(EIDL_BAD_ATTRIBUTE_FLAGS, $1);
        }
        AstInterface * scope = static_cast< AstInterface * >(
            idlc()->scopes()->top());
        AstAttribute * attr = new AstAttribute(
            $1, $4->compose($2), $4->getName(), scope);
        delete $4;
        AstInterface::DoubleMemberDeclarations doubleMembers(
            scope->checkMemberClashes(attr));
        if (doubleMembers.empty()) {
            scope->addMember(attr);
        } else {
            reportDoubleMemberDeclarations(doubleMembers);
        }
        idlc()->scopes()->push(attr);
    }
    opt_attribute_block
    {
        static_cast< AstAttribute * >(idlc()->scopes()->top())->setExceptions(
            $6.getExceptions, $6.setExceptions);
        delete $6.getExceptions;
        delete $6.setExceptions;
        idlc()->scopes()->pop();
    }
	;

flag_header :
	'[' opt_attrflags ']'
	{
		idlc()->setParseState(PS_FlagHeaderSeen);
		$$ = $2;
	}
	;

opt_attrflags :
	opt_attrflags ',' opt_attrflag 
	{
		if ( ($1 & $3) == $3 )
 			idlc()->error()->flagError(EIDL_DEFINED_ATTRIBUTEFLAG, $3);
 
 		$$ = $1 | $3;
	}
	| opt_attrflag
	{
		$$ = $1;
	}
	;

opt_attrflag :
	IDL_ATTRIBUTE
	{
		idlc()->setParseState(PS_AttrSeen);
		$$ = AF_ATTRIBUTE;
	}
	| IDL_PROPERTY
	{
		idlc()->setParseState(PS_PropertySeen);
		$$ = AF_PROPERTY;
	}
	| IDL_READONLY
	{
		idlc()->setParseState(PS_ReadOnlySeen);
		$$ = AF_READONLY;
	}
	| IDL_OPTIONAL
	{
		idlc()->setParseState(PS_OptionalSeen);
		$$ = AF_OPTIONAL;
	}
	| IDL_MAYBEVOID
	{
		idlc()->setParseState(PS_MayBeVoidSeen);
		$$ = AF_MAYBEVOID;
	}
	| IDL_BOUND
	{
		idlc()->setParseState(PS_BoundSeen);
		$$ = AF_BOUND;
	}
	| IDL_CONSTRAINED
	{
		idlc()->setParseState(PS_ConstrainedSeen);
		$$ = AF_CONSTRAINED;
	}
	| IDL_TRANSIENT
	{
		idlc()->setParseState(PS_TransientSeen);
		$$ = AF_TRANSIENT;
	}
	| IDL_MAYBEAMBIGUOUS
	{
		idlc()->setParseState(PS_MayBeAmbigiousSeen);
		$$ = AF_MAYBEAMBIGUOUS;
	}
	| IDL_MAYBEDEFAULT
	{
		idlc()->setParseState(PS_MayBeDefaultSeen);
		$$ = AF_MAYBEDEFAULT;
	}
	| IDL_REMOVEABLE
	{
		idlc()->setParseState(PS_RemoveableSeen);
		$$ = AF_REMOVEABLE;
	}
	| error ']' 
	{
       yyerror("unknown property|attribute flag");
		yyerrok;
	}
	;

opt_attribute_block:
    '{' attribute_block_rest { $$ = $2; }
    | /* empty */
    {
        $$.getExceptions = 0;
        $$.setExceptions = 0;
    }
    ;

attribute_block_rest:
    opt_attribute_raises '}'
    | error '}'
    {
        yyerror("bad attribute raises block");
        yyerrok;
        $$.getExceptions = 0;
        $$.setExceptions = 0;
    }
    ;

opt_attribute_raises:
    attribute_get_raises
    opt_attribute_set_raises
    {
        $$.getExceptions = $1;
        $$.setExceptions = $2;
    }
    | attribute_set_raises
    opt_attribute_get_raises
    {
        $$.getExceptions = $2;
        $$.setExceptions = $1;
    }
    | /* empty */
    {
        $$.getExceptions = 0;
        $$.setExceptions = 0;
    }
    ;

opt_attribute_get_raises:
    attribute_get_raises
    | /* empty */ { $$ = 0; }
    ;

attribute_get_raises:
    IDL_GET raises ';' { $$ = $2; }
    ;

opt_attribute_set_raises:
    attribute_set_raises
    | /* empty */ { $$ = 0; }
    ;

attribute_set_raises:
    IDL_SET
    {
        if (static_cast< AstAttribute * >(idlc()->scopes()->top())->
            isReadonly())
        {
            idlc()->error()->error0(EIDL_READONLY_ATTRIBUTE_SET_EXCEPTIONS);
        }
    }
    raises ';'
    {
        $$ = $3;
    }
    ;

operation :
	operation_head
	op_type_spec
	{
		idlc()->setParseState(PS_OpTypeSeen);
	}
	identifier
	{
		idlc()->setParseState(PS_OpIDSeen);
       checkIdentifier($4);

		AstInterface * pScope = static_cast< AstInterface * >(
            idlc()->scopes()->top());
		AstOperation* 	pOp = NULL;
		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);

                AstInterface::DoubleMemberDeclarations doubleMembers(
                    pScope->checkMemberClashes(pOp));
                if (doubleMembers.empty()) {
                    pScope->addMember(pOp);
                } else {
                    reportDoubleMemberDeclarations(doubleMembers);
                }
			}
		}
		delete $4;
		/*
		 * Push the operation scope onto the scopes stack
		 */
		idlc()->scopes()->push(pOp);
	}
	'('
	{
		idlc()->setParseState(PS_OpSqSeen);
	}
	parameters
	{
		idlc()->setParseState(PS_OpParsCompleted);
	}
	')'
	{
		idlc()->setParseState(PS_OpQsSeen);
	}
	opt_raises
	{
		AstScope*		pScope = idlc()->scopes()->topNonNull();
		AstOperation* 	pOp = NULL;
		/*
		 * Add exceptions and context to the operation
		 */
		if ( pScope && pScope->getScopeNodeType() == NT_operation)
		{
			pOp = (AstOperation*)pScope;

			if ( pOp )
				pOp->setExceptions($12);
		}
        delete $12;
		/*
		 * Done with this operation. Pop its scope from the scopes stack
		 */
		idlc()->scopes()->pop();
	}
	;

operation_head :
	'['
	IDL_ONEWAY
	{
		idlc()->setParseState(PS_OpOnewaySeen);
	}
	']'
	{
		idlc()->setParseState(PS_OpHeadSeen);
		$$ = OP_ONEWAY;
	}
	| /* EMPTY */
	{
		$$ = OP_NONE;
	}
	;

op_type_spec :
	simple_type_spec
	| IDL_VOID
	{
		$$ = idlc()->scopes()->bottom()->lookupPrimitiveType(ET_void);
	}
	;

parameters :
	parameter
	| parameters
	','
	{
		idlc()->setParseState(PS_OpParCommaSeen);
	}
	parameter
	| /* EMPTY */
	| error ',' 
	{
		yyerror("parameter definition");
		yyerrok;
	}
	;

parameter :
	'['
	direction
	']'
	{
		idlc()->setParseState(PS_OpParDirSeen);
	}
	simple_type_spec
	{
		idlc()->setParseState(PS_OpParTypeSeen);
	}
    opt_rest
	declarator
	{
		idlc()->setParseState(PS_OpParDeclSeen);

        AstOperation * pScope = static_cast< AstOperation * >(
            idlc()->scopes()->top());
		AstParameter* 	pParam = NULL;
		AstType*		pType = NULL;

		/*
		 * Create a node representing an argument to an operation
		 * Add it to the enclosing scope (the operation scope)
		 */
		if ( pScope && $5 && $8 )
		{
            AstType const * pType = $8->compose($5);
			if ( pType )
			{
                if (pScope->isConstructor() && $2 != DIR_IN) {
                    idlc()->error()->error0(EIDL_CONSTRUCTOR_PARAMETER_NOT_IN);
                }
                if (pScope->isVariadic()) {
                    idlc()->error()->error0(EIDL_REST_PARAMETER_NOT_LAST);
                }
                if ($7) {
                    AstType const * type = resolveTypedefs(pType);
                    if (type->getNodeType() != NT_predefined
                        || (static_cast< AstBaseType const * >(type)->
                            getExprType() != ET_any))
                    {
                        idlc()->error()->error0(EIDL_REST_PARAMETER_NOT_ANY);
                    }
                    if (pScope->isConstructor()) {
                        if (pScope->getIteratorBegin()
                            != pScope->getIteratorEnd())
                        {
                            idlc()->error()->error0(
                                EIDL_CONSTRUCTOR_REST_PARAMETER_NOT_FIRST);
                        }
                    } else {
                        idlc()->error()->error0(EIDL_METHOD_HAS_REST_PARAMETER);
                    }
                }

				pParam = new AstParameter(
                    static_cast< Direction >($2), $7, pType, $8->getName(),
                    pScope);
								
				if ( !$8->checkType($5) )
				{
					// WARNING	
				}

				pScope->addDeclaration(pParam);
			}
		}
	}
	| error
	simple_type_spec
	{
		idlc()->setParseState(PS_NoState);
		yyerrok;
	}
	;

direction :
	IDL_IN
	{
		$$ = DIR_IN;
	}
	| IDL_OUT
	{
		$$ = DIR_OUT;
	}
	| IDL_INOUT
	{
		$$ = DIR_INOUT;
	}
	;

opt_rest:
    IDL_ELLIPSIS
    {
        $$ = true;
    }
    | /* empty */
    {
        $$ = false;
    }
    ;

opt_raises:
    raises
    | /* empty */
    {
        $$ = 0;
    }
    ;

raises:
    IDL_RAISES
    {
        idlc()->setParseState(PS_RaiseSeen);
    }
    '('
    {
        idlc()->setParseState(PS_RaiseSqSeen);
    }
    exception_list
    ')'
    {
        idlc()->setParseState(PS_RaiseQsSeen);
        $$ = $5;
    }
    ;

exception_list:
    exception_name exception_list_tail
    {
        $2->push_front($1);
        $$ = $2;
    }
    ;

exception_list_tail:
    exception_list_tail ',' exception_name
    {
        $1->push_back($3);
        $$ = $1;
    }
    | /* empty */
    {
        $$ = new DeclList;
    }
    ;

exception_name:
    scoped_name
    {
        // The topmost scope is either an AstOperation (for interface methods
        // and service constructors) or an AstAttribute (for interface
        // attributes), so look up exception names in the next-to-topmost scope:
        AstDeclaration * decl = idlc()->scopes()->nextToTop()->lookupByName(
            *$1);
        if (decl == 0) {
            idlc()->error()->lookupError(*$1);
        } else if (decl->getNodeType() != NT_exception) {
            idlc()->error()->error1(EIDL_ILLEGAL_RAISES, decl);
            decl = 0;
        }
        delete $1;
        $$ = decl;
    }
    ;

interface_inheritance_decl:
    optional_inherited_interface
    IDL_INTERFACE
    {
        idlc()->setParseState(PS_ServiceIFHeadSeen);
    }
    scoped_name
    {
        AstInterface * ifc = static_cast< AstInterface * >(
            idlc()->scopes()->top());
        if (ifc->usesSingleInheritance()) {
            idlc()->error()->error0(EIDL_MIXED_INHERITANCE);
        } else {
            addInheritedInterface(
                ifc, *$4, $1,
                rtl::OStringToOUString(
                    idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8));
        }
        delete $4;
    }

optional_inherited_interface:
    '[' IDL_OPTIONAL ']' { $$ = true; }
    | /* EMPTY */ { $$ = false; }

constants_exports :
	constants_export constants_exports
	| /* EMPTY */
	;

constants_export :
	const_dcl
	{
		idlc()->setParseState(PS_ConstantDeclSeen);
	}
	';' {};


const_dcl : <commit_msg>INTEGRATION: CWS ooo20040329 (1.5.6); FILE MERGED 2004/04/08 03:56:21 svesik 1.5.6.2: RESYNC: (1.5-1.6); FILE MERGED 2004/03/18 17:27:15 pjanik 1.5.6.1: #i26686#: Add missing semicolon.<commit_after>/*************************************************************************
 *
 *  $RCSfile: parser.y,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: svesik $ $Date: 2004-04-21 14:04:36 $
 *
 *  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

#include "attributeexceptions.hxx"

#include "rtl/strbuf.hxx"
    
#ifdef WNT
#include <stdarg.h>
namespace std {
int fprintf(FILE* stream, const char* format, ...)
{
    va_list va_param;

    va_start(va_param, format);
	int res = ::vfprintf(stream, format, va_param);
    va_end(va_param);

    return res;
}

void* malloc( size_t size )
{
    return ::malloc(size);
}

void free( void *memblock )
{
    ::free(memblock);
}
    
};
#endif

using namespace ::rtl;

#define YYDEBUG 1
#define YYERROR_VERBOSE 1

extern int yylex(void);
void yyerror(char *);

void checkIdentifier(::rtl::OString* id)
{
    static short check = 0;
    if (check == 0) {
        if (idlc()->getOptions()->isValid("-cid"))
            check = 1;
        else
            check = 2;
    }

    if ( id->indexOf('_') >= 0 )
        if ( (id->pData->buffer[0] >= 97 && id->pData->buffer[0] <= 122)
             || id->pData->buffer[0] == '_') {
            if (check == 1) {
                ::rtl::OStringBuffer msg(25 + id->getLength());
                msg.append("mismatched identifier '");
                msg.append(*id);
                msg.append("'");
                idlc()->error()->syntaxError(idlc()->getParseState(),
                                         idlc()->getLineNumber(),
                                         msg.getStr());
            }
            else
                idlc()->error()->warning0(WIDL_WRONG_NAMING_CONV, id->getStr());
        }
}

void reportDoubleMemberDeclarations(
    AstInterface::DoubleMemberDeclarations const & doubleMembers)
{
    for (AstInterface::DoubleMemberDeclarations::const_iterator i(
             doubleMembers.begin());
         i != doubleMembers.end(); ++i)
    {
        idlc()->error()->error2(EIDL_DOUBLE_MEMBER, i->first, i->second);
    }
}

void addInheritedInterface(
    AstInterface * ifc, rtl::OString const & name, bool optional,
    rtl::OUString const & documentation)
{
    AstDeclaration * decl = ifc->lookupByName(name);
    if (decl != 0 && decl->getNodeType() == NT_interface) {
        if (!static_cast< AstInterface * >(decl)->isDefined()) {
            idlc()->error()->inheritanceError(
                NT_interface, &ifc->getScopedName(), decl);
        } else {
            AstInterface::DoubleDeclarations doubleDecls(
                ifc->checkInheritedInterfaceClashes(
                    static_cast< AstInterface * >(decl), optional));
            if (doubleDecls.interfaces.empty() && doubleDecls.members.empty()) {
                ifc->addInheritedInterface(
                    static_cast< AstInterface * >(decl), optional,
                    documentation);
            } else {
                for (AstInterface::DoubleInterfaceDeclarations::iterator i(
                         doubleDecls.interfaces.begin());
                     i != doubleDecls.interfaces.end(); ++i)
                {
                    idlc()->error()->error1(
                        EIDL_DOUBLE_INHERITANCE, *i);
                }
                reportDoubleMemberDeclarations(doubleDecls.members);
            }
        }
    } else {
        idlc()->error()->lookupError(
            EIDL_INTERFACEMEMBER_LOOKUP, name, scopeAsDecl(ifc));
    }
}

%}
/*
 * Declare the type of values in the grammar
 */
%union {
	ExprType				etval;     /* Expression type */
	AstDeclaration*		dclval;    /* Declaration */
    AstDeclaration const * cdclval;
    DeclList * dclsval;
	AstExpression*		exval;		/* expression value */
	ExprList*				exlval;	/* expression list value */
	FeDeclarator*			fdval;		/* declarator value */
	FeDeclList*			dlval;		/* declarator list value */
	FeInheritanceHeader*	ihval;		/* inheritance header value */
	::rtl::OString*		sval;		/* OString value */
	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 */
    AttributeExceptions attexcval;
}

/*
 * Token types: These are returned by the lexer
 */

%token <sval>		IDL_IDENTIFIER
%token 			IDL_ATTRIBUTE
%token				IDL_BOUND
%token 			IDL_CASE
%token 			IDL_CONST
%token 			IDL_CONSTANTS
%token				IDL_CONSTRAINED
%token 			IDL_DEFAULT
%token 			IDL_ENUM
%token 			IDL_EXCEPTION
%token 			IDL_INTERFACE
%token 			IDL_MAYBEAMBIGUOUS
%token 			IDL_MAYBEDEFAULT
%token 			IDL_MAYBEVOID
%token 			IDL_MODULE
%token 			IDL_NEEDS
%token 			IDL_OBSERVES
%token 			IDL_OPTIONAL
%token 			IDL_PROPERTY
%token 			IDL_RAISES
%token 			IDL_READONLY
%token 			IDL_REMOVEABLE
%token 			IDL_SERVICE
%token 			IDL_SEQUENCE
%token 			IDL_SINGLETON
%token 			IDL_STRUCT
%token 			IDL_SWITCH
%token 			IDL_TYPEDEF
%token				IDL_TRANSIENT
%token 			IDL_UNION

%token 			IDL_ANY
%token 			IDL_CHAR
%token 			IDL_BOOLEAN
%token 			IDL_BYTE
%token 			IDL_DOUBLE
%token 			IDL_FLOAT
%token 			IDL_HYPER
%token 			IDL_LONG
%token 			IDL_SHORT
%token 			IDL_VOID
%token 			IDL_STRING
%token 			IDL_TYPE
%token 			IDL_UNSIGNED

%token 			IDL_TRUE
%token 			IDL_FALSE

%token 			IDL_IN
%token 			IDL_OUT
%token 			IDL_INOUT
%token 			IDL_ONEWAY

%token IDL_GET
%token IDL_SET

%token IDL_ELLIPSIS

%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
%type <dclval>	array_declarator
%type <dclval>  exception_name
%type <cdclval> array_type constructed_type_spec enum_type op_type_spec
%type <cdclval> sequence_type_spec simple_type_spec struct_type switch_type_spec
%type <cdclval> template_type_spec type_spec union_type
%type <dclsval> opt_raises raises exception_list exception_list_tail
%type <dclsval> opt_attribute_get_raises attribute_get_raises
%type <dclsval> opt_attribute_set_raises attribute_set_raises

%type <sval>    identifier
%type <sval>	interface_decl 
%type <sval>	scoped_name inheritance_spec
%type <slval>  	scoped_names at_least_one_scoped_name

%type <etval>	const_type integer_type char_type boolean_type
%type <etval>	floating_pt_type any_type signed_int string_type
%type <etval>	unsigned_int base_type_spec byte_type type_type 

%type <exval>	expression const_expr or_expr xor_expr and_expr
%type <exval>	add_expr mult_expr unary_expr primary_expr shift_expr
%type <exval>	literal positive_int_expr array_dim

%type <exlval> 	at_least_one_array_dim array_dims

%type <fdval> 	declarator simple_declarator complex_declarator
%type <dlval> 	declarators at_least_one_declarator

%type <ihval>	exception_header structure_header interfaceheader

%type <ulval> 	flag_header opt_attrflags opt_attrflag operation_head
%type <ulval>	direction service_interface_header service_service_header

%type <llval>	case_labels at_least_one_case_label
%type <lbval>	case_label
%type <mval>	element_spec

%type <bval>    optional_inherited_interface opt_rest

%type <attexcval> opt_attribute_block attribute_block_rest opt_attribute_raises

%%
/*
 * 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);
	}
	identifier
	{
        idlc()->setParseState(PS_ModuleIDSeen);
        checkIdentifier($3);

        AstScope* 		pScope = idlc()->scopes()->topNonNull();
        AstModule* 		pModule = NULL;
        AstDeclaration*	pExists = NULL;

        if ( pScope )
        {
        	pModule = new AstModule(*$3, pScope);
			if( (pExists = pScope->lookupForAdd(pModule)) )
			{
				pExists->setInMainfile(idlc()->isInMainFile());
				pExists->setFileName(pModule->getFileName());
				delete(pModule);
				pModule = (AstModule*)pExists;
			} else
			{
				pScope->addDeclaration(pModule);
			}
			idlc()->scopes()->push(pModule);
        }
        delete $3;
    }
    '{'
    {
        idlc()->setParseState(PS_ModuleSqSeen);
    }
	definitions
	{
		idlc()->setParseState(PS_ModuleBodySeen);
	}
	'}'
	{
		idlc()->setParseState(PS_ModuleQsSeen);
		/*
		 * Finished with this module - pop it from the scope stack
		 */
		idlc()->scopes()->pop();
	}
	;

interface :
	interface_dcl
	| forward_dcl
	; 

interface_decl :
	IDL_INTERFACE
	{
		idlc()->setParseState(PS_InterfaceSeen);
	}
	identifier
	{
		idlc()->setParseState(PS_InterfaceIDSeen);
       checkIdentifier($3);
		$$ = $3;
	}
	;

forward_dcl :
	interface_decl
	{
		idlc()->setParseState(PS_ForwardDeclSeen);

		AstScope* 		pScope = idlc()->scopes()->topNonNull();
		AstInterface*	pForward = NULL;
		AstDeclaration*	pDecl = NULL;

        /*
		 * Make a new forward interface node and add it to its enclosing scope
		 */
		if ( pScope && $1 ) 
		{
			pForward = new AstInterface(*$1, NULL, pScope);
			
			if ( pDecl = pScope->lookupByName(pForward->getScopedName()) ) 
			{
				if ( (pDecl != pForward) && 
					 (pDecl->getNodeType() == NT_interface) )
				{
					delete pForward;
				} else
				{
					idlc()->error()->error2(EIDL_REDEF_SCOPE, scopeAsDecl(pScope), pDecl);
				}
			} else
			{
				/*
				 * Add the interface to its definition scope
				 */
				pScope->addDeclaration(pForward);
			}
		}
		delete $1;
	}
	;

interface_dcl :
	interfaceheader
	{
		idlc()->setParseState(PS_InterfaceHeadSeen);

		AstScope* 		pScope = idlc()->scopes()->topNonNull();
		AstInterface*	pInterface = NULL;
		AstInterface*	pForward = NULL;
		AstDeclaration*	pDecl = NULL;

        /*
		 * Make a new interface node and add it to its enclosing scope
		 */
		if ( pScope && $1 ) 
		{
			pInterface = new AstInterface(
                *$1->getName(),
                static_cast< AstInterface * >($1->getInherits()), pScope);
			if ( pInterface &&
				(pDecl = pScope->lookupByName(pInterface->getScopedName())) ) 
			{
				/*
				 * See if we're defining a forward declared interface.
				 */
				if (pDecl->getNodeType() == NT_interface) 
				{
					pForward = (AstInterface*)pDecl;
					if ( !pForward->isDefined() ) 
					{
						/*
						 * Check if redefining in same scope
						 */
						if ( pForward->getScope() != pScope ) 
						{
							if ( pForward->getScopedName() != pInterface->getScopedName() )
							{
								idlc()->error()->error3(EIDL_SCOPE_CONFLICT,
										 pInterface, pForward, scopeAsDecl(pScope));
							}
						}
						/*
						 * All OK, set full definition
						 */
						else 
						{
                            pForward->forwardDefined(*pInterface);
							delete pInterface;
							pInterface = pForward;
						}
					}
				}
			} else
			{
				/*
				 * Add the interface to its definition scope
				 */
				pScope->addDeclaration(pInterface);
			}
		}
		/*
		 * Push it on the scope stack
		 */
		idlc()->scopes()->push(pInterface);
		delete($1);
	}
	'{'
	{
		idlc()->setParseState(PS_InterfaceSqSeen);
	}
	exports
	{
        AstInterface * ifc = static_cast< AstInterface * >(
            idlc()->scopes()->topNonNull());
        if (!ifc->hasMandatoryInheritedInterfaces()
            && ifc->getScopedName() != "com::sun::star::uno::XInterface")
        {
            addInheritedInterface(
                ifc, rtl::OString("::com::sun::star::uno::XInterface"), false,
                rtl::OUString());
        }
        ifc->setDefined();
		idlc()->setParseState(PS_InterfaceBodySeen);
	}
	'}'
	{
		idlc()->setParseState(PS_InterfaceQsSeen);
		/*
		 * Done with this interface - pop it off the scopes stack
		 */
		idlc()->scopes()->pop();
	}
	| error '}' 
	{
		yyerror("interface definition");
		yyerrok;
	}
	;

interfaceheader :
	interface_decl inheritance_spec
	{
		idlc()->setParseState(PS_InheritSpecSeen);

		$$ = new FeInheritanceHeader(NT_interface, $1, $2);
		delete $2;
	}
	;   

inheritance_spec :
	':'
	{
		idlc()->setParseState(PS_InheritColonSeen);
	}
	scoped_name
	{
        $$ = $3;
	}
	| /* EMPTY */
	{
		$$ = NULL;
	}
	;

exports :
	exports export
	| /* EMPTY */
	;

export :
    attribute
	{
		idlc()->setParseState(PS_AttributeDeclSeen);
	}
	';'
	{
		idlc()->setParseState(PS_NoState);
	}
	| operation
	{
		idlc()->setParseState(PS_OperationDeclSeen);
	}
	';'
	{
		idlc()->setParseState(PS_NoState);
	}
    | interface_inheritance_decl
    {
		idlc()->setParseState(PS_InterfaceInheritanceDeclSeen);
    }
    ';'
	{
		idlc()->setParseState(PS_NoState);
	}
    ;

attribute :
	flag_header
	simple_type_spec
	{
		idlc()->setParseState(PS_AttrTypeSeen);
	}
    simple_declarator
	{
		idlc()->setParseState(PS_AttrCompleted);
        if (($1 & ~(AF_BOUND | AF_READONLY)) != AF_ATTRIBUTE) {
            idlc()->error()->flagError(EIDL_BAD_ATTRIBUTE_FLAGS, $1);
        }
        AstInterface * scope = static_cast< AstInterface * >(
            idlc()->scopes()->top());
        AstAttribute * attr = new AstAttribute(
            $1, $4->compose($2), $4->getName(), scope);
        delete $4;
        AstInterface::DoubleMemberDeclarations doubleMembers(
            scope->checkMemberClashes(attr));
        if (doubleMembers.empty()) {
            scope->addMember(attr);
        } else {
            reportDoubleMemberDeclarations(doubleMembers);
        }
        idlc()->scopes()->push(attr);
    }
    opt_attribute_block
    {
        static_cast< AstAttribute * >(idlc()->scopes()->top())->setExceptions(
            $6.getExceptions, $6.setExceptions);
        delete $6.getExceptions;
        delete $6.setExceptions;
        idlc()->scopes()->pop();
    }
	;

flag_header :
	'[' opt_attrflags ']'
	{
		idlc()->setParseState(PS_FlagHeaderSeen);
		$$ = $2;
	}
	;

opt_attrflags :
	opt_attrflags ',' opt_attrflag 
	{
		if ( ($1 & $3) == $3 )
 			idlc()->error()->flagError(EIDL_DEFINED_ATTRIBUTEFLAG, $3);
 
 		$$ = $1 | $3;
	}
	| opt_attrflag
	{
		$$ = $1;
	}
	;

opt_attrflag :
	IDL_ATTRIBUTE
	{
		idlc()->setParseState(PS_AttrSeen);
		$$ = AF_ATTRIBUTE;
	}
	| IDL_PROPERTY
	{
		idlc()->setParseState(PS_PropertySeen);
		$$ = AF_PROPERTY;
	}
	| IDL_READONLY
	{
		idlc()->setParseState(PS_ReadOnlySeen);
		$$ = AF_READONLY;
	}
	| IDL_OPTIONAL
	{
		idlc()->setParseState(PS_OptionalSeen);
		$$ = AF_OPTIONAL;
	}
	| IDL_MAYBEVOID
	{
		idlc()->setParseState(PS_MayBeVoidSeen);
		$$ = AF_MAYBEVOID;
	}
	| IDL_BOUND
	{
		idlc()->setParseState(PS_BoundSeen);
		$$ = AF_BOUND;
	}
	| IDL_CONSTRAINED
	{
		idlc()->setParseState(PS_ConstrainedSeen);
		$$ = AF_CONSTRAINED;
	}
	| IDL_TRANSIENT
	{
		idlc()->setParseState(PS_TransientSeen);
		$$ = AF_TRANSIENT;
	}
	| IDL_MAYBEAMBIGUOUS
	{
		idlc()->setParseState(PS_MayBeAmbigiousSeen);
		$$ = AF_MAYBEAMBIGUOUS;
	}
	| IDL_MAYBEDEFAULT
	{
		idlc()->setParseState(PS_MayBeDefaultSeen);
		$$ = AF_MAYBEDEFAULT;
	}
	| IDL_REMOVEABLE
	{
		idlc()->setParseState(PS_RemoveableSeen);
		$$ = AF_REMOVEABLE;
	}
	| error ']' 
	{
       yyerror("unknown property|attribute flag");
		yyerrok;
	}
	;

opt_attribute_block:
    '{' attribute_block_rest { $$ = $2; }
    | /* empty */
    {
        $$.getExceptions = 0;
        $$.setExceptions = 0;
    }
    ;

attribute_block_rest:
    opt_attribute_raises '}'
    | error '}'
    {
        yyerror("bad attribute raises block");
        yyerrok;
        $$.getExceptions = 0;
        $$.setExceptions = 0;
    }
    ;

opt_attribute_raises:
    attribute_get_raises
    opt_attribute_set_raises
    {
        $$.getExceptions = $1;
        $$.setExceptions = $2;
    }
    | attribute_set_raises
    opt_attribute_get_raises
    {
        $$.getExceptions = $2;
        $$.setExceptions = $1;
    }
    | /* empty */
    {
        $$.getExceptions = 0;
        $$.setExceptions = 0;
    }
    ;

opt_attribute_get_raises:
    attribute_get_raises
    | /* empty */ { $$ = 0; }
    ;

attribute_get_raises:
    IDL_GET raises ';' { $$ = $2; }
    ;

opt_attribute_set_raises:
    attribute_set_raises
    | /* empty */ { $$ = 0; }
    ;

attribute_set_raises:
    IDL_SET
    {
        if (static_cast< AstAttribute * >(idlc()->scopes()->top())->
            isReadonly())
        {
            idlc()->error()->error0(EIDL_READONLY_ATTRIBUTE_SET_EXCEPTIONS);
        }
    }
    raises ';'
    {
        $$ = $3;
    }
    ;

operation :
	operation_head
	op_type_spec
	{
		idlc()->setParseState(PS_OpTypeSeen);
	}
	identifier
	{
		idlc()->setParseState(PS_OpIDSeen);
       checkIdentifier($4);

		AstInterface * pScope = static_cast< AstInterface * >(
            idlc()->scopes()->top());
		AstOperation* 	pOp = NULL;
		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);

                AstInterface::DoubleMemberDeclarations doubleMembers(
                    pScope->checkMemberClashes(pOp));
                if (doubleMembers.empty()) {
                    pScope->addMember(pOp);
                } else {
                    reportDoubleMemberDeclarations(doubleMembers);
                }
			}
		}
		delete $4;
		/*
		 * Push the operation scope onto the scopes stack
		 */
		idlc()->scopes()->push(pOp);
	}
	'('
	{
		idlc()->setParseState(PS_OpSqSeen);
	}
	parameters
	{
		idlc()->setParseState(PS_OpParsCompleted);
	}
	')'
	{
		idlc()->setParseState(PS_OpQsSeen);
	}
	opt_raises
	{
		AstScope*		pScope = idlc()->scopes()->topNonNull();
		AstOperation* 	pOp = NULL;
		/*
		 * Add exceptions and context to the operation
		 */
		if ( pScope && pScope->getScopeNodeType() == NT_operation)
		{
			pOp = (AstOperation*)pScope;

			if ( pOp )
				pOp->setExceptions($12);
		}
        delete $12;
		/*
		 * Done with this operation. Pop its scope from the scopes stack
		 */
		idlc()->scopes()->pop();
	}
	;

operation_head :
	'['
	IDL_ONEWAY
	{
		idlc()->setParseState(PS_OpOnewaySeen);
	}
	']'
	{
		idlc()->setParseState(PS_OpHeadSeen);
		$$ = OP_ONEWAY;
	}
	| /* EMPTY */
	{
		$$ = OP_NONE;
	}
	;

op_type_spec :
	simple_type_spec
	| IDL_VOID
	{
		$$ = idlc()->scopes()->bottom()->lookupPrimitiveType(ET_void);
	}
	;

parameters :
	parameter
	| parameters
	','
	{
		idlc()->setParseState(PS_OpParCommaSeen);
	}
	parameter
	| /* EMPTY */
	| error ',' 
	{
		yyerror("parameter definition");
		yyerrok;
	}
	;

parameter :
	'['
	direction
	']'
	{
		idlc()->setParseState(PS_OpParDirSeen);
	}
	simple_type_spec
	{
		idlc()->setParseState(PS_OpParTypeSeen);
	}
    opt_rest
	declarator
	{
		idlc()->setParseState(PS_OpParDeclSeen);

        AstOperation * pScope = static_cast< AstOperation * >(
            idlc()->scopes()->top());
		AstParameter* 	pParam = NULL;
		AstType*		pType = NULL;

		/*
		 * Create a node representing an argument to an operation
		 * Add it to the enclosing scope (the operation scope)
		 */
		if ( pScope && $5 && $8 )
		{
            AstType const * pType = $8->compose($5);
			if ( pType )
			{
                if (pScope->isConstructor() && $2 != DIR_IN) {
                    idlc()->error()->error0(EIDL_CONSTRUCTOR_PARAMETER_NOT_IN);
                }
                if (pScope->isVariadic()) {
                    idlc()->error()->error0(EIDL_REST_PARAMETER_NOT_LAST);
                }
                if ($7) {
                    AstType const * type = resolveTypedefs(pType);
                    if (type->getNodeType() != NT_predefined
                        || (static_cast< AstBaseType const * >(type)->
                            getExprType() != ET_any))
                    {
                        idlc()->error()->error0(EIDL_REST_PARAMETER_NOT_ANY);
                    }
                    if (pScope->isConstructor()) {
                        if (pScope->getIteratorBegin()
                            != pScope->getIteratorEnd())
                        {
                            idlc()->error()->error0(
                                EIDL_CONSTRUCTOR_REST_PARAMETER_NOT_FIRST);
                        }
                    } else {
                        idlc()->error()->error0(EIDL_METHOD_HAS_REST_PARAMETER);
                    }
                }

				pParam = new AstParameter(
                    static_cast< Direction >($2), $7, pType, $8->getName(),
                    pScope);
								
				if ( !$8->checkType($5) )
				{
					// WARNING	
				}

				pScope->addDeclaration(pParam);
			}
		}
	}
	| error
	simple_type_spec
	{
		idlc()->setParseState(PS_NoState);
		yyerrok;
	}
	;

direction :
	IDL_IN
	{
		$$ = DIR_IN;
	}
	| IDL_OUT
	{
		$$ = DIR_OUT;
	}
	| IDL_INOUT
	{
		$$ = DIR_INOUT;
	}
	;

opt_rest:
    IDL_ELLIPSIS
    {
        $$ = true;
    }
    | /* empty */
    {
        $$ = false;
    }
    ;

opt_raises:
    raises
    | /* empty */
    {
        $$ = 0;
    }
    ;

raises:
    IDL_RAISES
    {
        idlc()->setParseState(PS_RaiseSeen);
    }
    '('
    {
        idlc()->setParseState(PS_RaiseSqSeen);
    }
    exception_list
    ')'
    {
        idlc()->setParseState(PS_RaiseQsSeen);
        $$ = $5;
    }
    ;

exception_list:
    exception_name exception_list_tail
    {
        $2->push_front($1);
        $$ = $2;
    }
    ;

exception_list_tail:
    exception_list_tail ',' exception_name
    {
        $1->push_back($3);
        $$ = $1;
    }
    | /* empty */
    {
        $$ = new DeclList;
    }
    ;

exception_name:
    scoped_name
    {
        // The topmost scope is either an AstOperation (for interface methods
        // and service constructors) or an AstAttribute (for interface
        // attributes), so look up exception names in the next-to-topmost scope:
        AstDeclaration * decl = idlc()->scopes()->nextToTop()->lookupByName(
            *$1);
        if (decl == 0) {
            idlc()->error()->lookupError(*$1);
        } else if (decl->getNodeType() != NT_exception) {
            idlc()->error()->error1(EIDL_ILLEGAL_RAISES, decl);
            decl = 0;
        }
        delete $1;
        $$ = decl;
    }
    ;

interface_inheritance_decl:
    optional_inherited_interface
    IDL_INTERFACE
    {
        idlc()->setParseState(PS_ServiceIFHeadSeen);
    }
    scoped_name
    {
        AstInterface * ifc = static_cast< AstInterface * >(
            idlc()->scopes()->top());
        if (ifc->usesSingleInheritance()) {
            idlc()->error()->error0(EIDL_MIXED_INHERITANCE);
        } else {
            addInheritedInterface(
                ifc, *$4, $1,
                rtl::OStringToOUString(
                    idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8));
        }
        delete $4;
    }
    ;

optional_inherited_interface:
    '[' IDL_OPTIONAL ']' { $$ = true; }
    | /* EMPTY */ { $$ = false; }

constants_exports :
	constants_export constants_exports
	| /* EMPTY */
	;

constants_export :
	const_dcl
	{
		idlc()->setParseState(PS_ConstantDeclSeen);
	}
	';' {};


const_dcl : 
{'fraction_non_alphanumeric': 0.13758174580608473, 'fraction_numerical': 0.007819164060278647, 'mean_word_length': 2.665277144532013, 'pattern_counts': {'":': 2, '<': 153, '<?xml version=': 0, '>': 597, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7207795', 'n_tokens_mistral': 21712, 'n_tokens_neox': 20117, 'n_words': 3609}