xref: /AOO41X/main/idlc/source/parser.y (revision 54628ca40d27d15cc98fe861da7fff7e60c2f7d6)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 /*
25  * parser.yy - BISON grammar for IDLC 1.0
26  */
27 
28 %{
29 #include <string.h>
30 
31 #ifndef _IDLC_IDLC_HXX_
32 #include <idlc/idlc.hxx>
33 #endif
34 #ifndef _IDLC_ERRORHANDLER_HXX_
35 #include <idlc/errorhandler.hxx>
36 #endif
37 #ifndef _IDLC_FEHELPER_HXX_
38 #include <idlc/fehelper.hxx>
39 #endif
40 #ifndef _IDLC_EXPRESSION_HXX_
41 #include <idlc/astexpression.hxx>
42 #endif
43 #ifndef _IDLC_ASTCONSTANTS_HXX_
44 #include <idlc/astconstants.hxx>
45 #endif
46 #ifndef _IDLC_ASTCONSTANT_HXX_
47 #include <idlc/astconstant.hxx>
48 #endif
49 #ifndef _IDLC_ASTARRAY_HXX_
50 #include <idlc/astarray.hxx>
51 #endif
52 #ifndef _IDLC_ASTBASETYPE_HXX_
53 #include <idlc/astbasetype.hxx>
54 #endif
55 #ifndef _IDLC_ASTTYPEDEF_HXX_
56 #include <idlc/asttypedef.hxx>
57 #endif
58 #ifndef _IDLC_ASTEXCEPTION_HXX_
59 #include <idlc/astexception.hxx>
60 #endif
61 #ifndef _IDLC_ASTMEMBER_HXX_
62 #include <idlc/astmember.hxx>
63 #endif
64 #ifndef _IDLC_ASTENUM_HXX_
65 #include <idlc/astenum.hxx>
66 #endif
67 #ifndef _IDLC_ASTSEQUENCE_HXX_
68 #include <idlc/astsequence.hxx>
69 #endif
70 #ifndef _IDLC_ASTATTRIBUTE_HXX_
71 #include <idlc/astattribute.hxx>
72 #endif
73 #ifndef _IDLC_ASTOPERATION_HXX_
74 #include <idlc/astoperation.hxx>
75 #endif
76 #ifndef _IDLC_ASTPARAMETER_HXX_
77 #include <idlc/astparameter.hxx>
78 #endif
79 #ifndef _IDLC_ASTINTERFACEMEMBER_HXX_
80 #include <idlc/astinterfacemember.hxx>
81 #endif
82 #ifndef _IDLC_ASTSERVICEMEMBER_HXX_
83 #include <idlc/astservicemember.hxx>
84 #endif
85 #ifndef _IDLC_ASTOBSERVES_HXX_
86 #include <idlc/astobserves.hxx>
87 #endif
88 #ifndef _IDLC_ASTNEEDS_HXX_
89 #include <idlc/astneeds.hxx>
90 #endif
91 #ifndef _IDLC_ASTUNION_HXX_
92 #include <idlc/astunion.hxx>
93 #endif
94 #include "idlc/aststructinstance.hxx"
95 
96 #include "attributeexceptions.hxx"
97 
98 #include "rtl/strbuf.hxx"
99 
100 #include <algorithm>
101 #include <vector>
102 
103 using namespace ::rtl;
104 
105 #define YYDEBUG 1
106 #define YYERROR_VERBOSE 1
107 
108 extern int yylex(void);
109 void yyerror(char const *);
110 
111 void checkIdentifier(::rtl::OString* id)
112 {
113     static short check = 0;
114     if (check == 0) {
115         if (idlc()->getOptions()->isValid("-cid"))
116             check = 1;
117         else
118             check = 2;
119     }
120 
121     if ( id->indexOf('_') >= 0 )
122         if ( (id->pData->buffer[0] >= 97 && id->pData->buffer[0] <= 122)
123              || id->pData->buffer[0] == '_') {
124             if (check == 1) {
125                 ::rtl::OStringBuffer msg(25 + id->getLength());
126                 msg.append("mismatched identifier '");
127                 msg.append(*id);
128                 msg.append("'");
129                 idlc()->error()->syntaxError(idlc()->getParseState(),
130                                          idlc()->getLineNumber(),
131                                          msg.getStr());
132             }
133             else
134                 idlc()->error()->warning0(WIDL_WRONG_NAMING_CONV, id->getStr());
135         }
136 }
137 
138 void reportDoubleMemberDeclarations(
139     AstInterface::DoubleMemberDeclarations const & doubleMembers)
140 {
141     for (AstInterface::DoubleMemberDeclarations::const_iterator i(
142              doubleMembers.begin());
143          i != doubleMembers.end(); ++i)
144     {
145         idlc()->error()->error2(EIDL_DOUBLE_MEMBER, i->first, i->second);
146     }
147 }
148 
149 void addInheritedInterface(
150     AstInterface * ifc, rtl::OString const & name, bool optional,
151     rtl::OUString const & documentation)
152 {
153     AstDeclaration * decl = ifc->lookupByName(name);
154     AstDeclaration const * resolved = resolveTypedefs(decl);
155     if (resolved != 0 && resolved->getNodeType() == NT_interface) {
156         if (idlc()->error()->checkPublished(decl)) {
157             if (!static_cast< AstInterface const * >(resolved)->isDefined()) {
158                 idlc()->error()->inheritanceError(
159                     NT_interface, &ifc->getScopedName(), decl);
160             } else {
161                 AstInterface::DoubleDeclarations doubleDecls(
162                     ifc->checkInheritedInterfaceClashes(
163                         static_cast< AstInterface const * >(resolved),
164                         optional));
165                 if (doubleDecls.interfaces.empty()
166                     && doubleDecls.members.empty())
167                 {
168                     ifc->addInheritedInterface(
169                         static_cast< AstType * >(decl), optional,
170                         documentation);
171                 } else {
172                     for (AstInterface::DoubleInterfaceDeclarations::iterator i(
173                              doubleDecls.interfaces.begin());
174                          i != doubleDecls.interfaces.end(); ++i)
175                     {
176                         idlc()->error()->error1(
177                             EIDL_DOUBLE_INHERITANCE, *i);
178                     }
179                     reportDoubleMemberDeclarations(doubleDecls.members);
180                 }
181             }
182         }
183     } else {
184         idlc()->error()->lookupError(
185             EIDL_INTERFACEMEMBER_LOOKUP, name, scopeAsDecl(ifc));
186     }
187 }
188 
189 AstDeclaration const * createNamedType(
190     rtl::OString const * scopedName, DeclList const * typeArgs)
191 {
192     AstDeclaration * decl = idlc()->scopes()->topNonNull()->lookupByName(
193         *scopedName);
194     AstDeclaration const * resolved = resolveTypedefs(decl);
195     if (decl == 0) {
196         idlc()->error()->lookupError(*scopedName);
197     } else if (!idlc()->error()->checkPublished(decl)) {
198         decl = 0;
199     } else if (resolved->getNodeType() == NT_struct) {
200         if (static_cast< AstStruct const * >(resolved)->getTypeParameterCount()
201             != (typeArgs == 0 ? 0 : typeArgs->size()))
202         {
203             idlc()->error()->error0(EIDL_WRONG_NUMBER_OF_TYPE_ARGUMENTS);
204             decl = 0;
205         } else if (typeArgs != 0) {
206             AstScope * global = idlc()->scopes()->bottom();
207             AstDeclaration * inst = new AstStructInstance(
208                 static_cast< AstType * >(decl), typeArgs, global);
209             decl = global->addDeclaration(inst);
210             if (decl != inst) {
211                 delete inst;
212             }
213         }
214     } else if (decl->isType()) {
215         if (typeArgs != 0) {
216             idlc()->error()->error0(EIDL_WRONG_NUMBER_OF_TYPE_ARGUMENTS);
217             decl = 0;
218         }
219     } else {
220         idlc()->error()->noTypeError(decl);
221         decl = 0;
222     }
223     delete scopedName;
224     delete typeArgs;
225     return decl;
226 }
227 
228 bool includes(AstDeclaration const * type1, AstDeclaration const * type2) {
229     OSL_ASSERT(type2 != 0);
230     if (type1 != 0) {
231         if (type1->getNodeType() == NT_instantiated_struct) {
232             AstStructInstance const * inst
233                 = static_cast< AstStructInstance const * >(type1);
234             if (inst->getTypeTemplate() == type2) {
235                 return true;
236             }
237             for (DeclList::const_iterator i(inst->getTypeArgumentsBegin());
238                  i != inst->getTypeArgumentsEnd(); ++i)
239             {
240                 if (includes(*i, type2)) {
241                     return true;
242                 }
243             }
244         } else if (type1 == type2) {
245             return true;
246         }
247     }
248     return false;
249 }
250 
251 // Suppress any warnings from generated code:
252 #if defined __GNUC__
253 #pragma GCC system_header
254 #elif defined __SUNPRO_CC
255 #pragma disable_warn
256 #elif defined _MSC_VER
257 #pragma warning(push, 1)
258 #pragma warning(disable: 4273 4701 4706)
259 #endif
260 %}
261 /*
262  * Declare the type of values in the grammar
263  */
264 %union {
265     ExprType                etval;     /* Expression type */
266     AstDeclaration*     dclval;    /* Declaration */
267     AstDeclaration const * cdclval;
268     DeclList * dclsval;
269     AstExpression*      exval;      /* expression value */
270     ExprList*               exlval; /* expression list value */
271     FeDeclarator*           fdval;      /* declarator value */
272     FeDeclList*         dlval;      /* declarator list value */
273     FeInheritanceHeader*    ihval;      /* inheritance header value */
274     ::rtl::OString*     sval;       /* OString value */
275     std::vector< rtl::OString > * svals;
276     sal_Char*           strval; /* sal_Char* value */
277     sal_Bool                bval;       /* sal_Boolean* value */
278     sal_Int64               ival;       /* sal_Int64 value */
279     sal_uInt64 uval; /* sal_uInt64 value */
280     sal_uInt32          ulval;      /* sal_uInt32 value */
281     double                  dval;       /* double value */
282     float                   fval;       /* float value */
283     StringList*         slval;      /* StringList value */
284     LabelList*          llval;      /* LabelList value  */
285     AstUnionLabel*      lbval;      /* union label value */
286     AstMember*          mval;       /* member value */
287     AttributeExceptions::Part attexcpval;
288     AttributeExceptions attexcval;
289 }
290 
291 /*
292  * Token types: These are returned by the lexer
293  */
294 
295 %token <sval>       IDL_IDENTIFIER
296 %token          IDL_ATTRIBUTE
297 %token              IDL_BOUND
298 %token          IDL_CASE
299 %token          IDL_CONST
300 %token          IDL_CONSTANTS
301 %token              IDL_CONSTRAINED
302 %token          IDL_DEFAULT
303 %token          IDL_ENUM
304 %token          IDL_EXCEPTION
305 %token          IDL_INTERFACE
306 %token          IDL_MAYBEAMBIGUOUS
307 %token          IDL_MAYBEDEFAULT
308 %token          IDL_MAYBEVOID
309 %token          IDL_MODULE
310 %token          IDL_NEEDS
311 %token          IDL_OBSERVES
312 %token          IDL_OPTIONAL
313 %token          IDL_PROPERTY
314 %token          IDL_RAISES
315 %token          IDL_READONLY
316 %token          IDL_REMOVEABLE
317 %token          IDL_SERVICE
318 %token          IDL_SEQUENCE
319 %token          IDL_SINGLETON
320 %token          IDL_STRUCT
321 %token          IDL_SWITCH
322 %token          IDL_TYPEDEF
323 %token              IDL_TRANSIENT
324 %token          IDL_UNION
325 
326 %token          IDL_ANY
327 %token          IDL_CHAR
328 %token          IDL_BOOLEAN
329 %token          IDL_BYTE
330 %token          IDL_DOUBLE
331 %token          IDL_FLOAT
332 %token          IDL_HYPER
333 %token          IDL_LONG
334 %token          IDL_SHORT
335 %token          IDL_VOID
336 %token          IDL_STRING
337 %token          IDL_TYPE
338 %token          IDL_UNSIGNED
339 
340 %token          IDL_TRUE
341 %token          IDL_FALSE
342 
343 %token          IDL_IN
344 %token          IDL_OUT
345 %token          IDL_INOUT
346 %token          IDL_ONEWAY
347 
348 %token IDL_GET
349 %token IDL_SET
350 
351 %token IDL_PUBLISHED
352 
353 %token IDL_ELLIPSIS
354 
355 %token <strval> IDL_LEFTSHIFT
356 %token <strval> IDL_RIGHTSHIFT
357 %token <strval>     IDL_SCOPESEPARATOR
358 
359 %token <ival>       IDL_INTEGER_LITERAL
360 %token <uval> IDL_INTEGER_ULITERAL
361 %token <dval>       IDL_FLOATING_PT_LITERAL
362 
363 /*
364  * These are production names:
365  */
366 %type <dclval>  type_dcl const_dcl
367 %type <dclval>  array_declarator
368 %type <dclval>  exception_name
369 %type <cdclval> array_type constructed_type_spec enum_type op_type_spec
370 %type <cdclval> sequence_type_spec simple_type_spec struct_type switch_type_spec
371 %type <cdclval> template_type_spec type_spec union_type
372 %type <cdclval> fundamental_type type_arg type_or_parameter
373 %type <dclsval> opt_raises raises exception_list
374 %type <attexcpval> opt_attribute_get_raises attribute_get_raises
375 %type <attexcpval> opt_attribute_set_raises attribute_set_raises
376 %type <dclsval> opt_type_args type_args
377 
378 %type <sval>    identifier
379 %type <sval>    interface_decl
380 %type <sval>    scoped_name inheritance_spec
381 %type <slval>   scoped_names at_least_one_scoped_name
382 
383 %type <etval>   const_type integer_type char_type boolean_type
384 %type <etval>   floating_pt_type any_type signed_int string_type
385 %type <etval>   unsigned_int base_type_spec byte_type type_type
386 
387 %type <exval>   expression const_expr or_expr xor_expr and_expr
388 %type <exval>   add_expr mult_expr unary_expr primary_expr shift_expr
389 %type <exval>   literal positive_int_expr array_dim
390 
391 %type <exlval>  at_least_one_array_dim array_dims
392 
393 %type <fdval>   declarator simple_declarator complex_declarator
394 %type <dlval>   declarators at_least_one_declarator
395 
396 %type <ihval>   exception_header structure_header interfaceheader
397 
398 %type <ulval>   flag_header opt_attrflags opt_attrflag operation_head
399 %type <ulval>   direction service_interface_header service_service_header
400 
401 %type <llval>   case_labels at_least_one_case_label
402 %type <lbval>   case_label
403 %type <mval>    element_spec
404 
405 %type <bval>    optional_inherited_interface opt_rest opt_service_body
406 
407 %type <attexcval> opt_attribute_block attribute_block_rest opt_attribute_raises
408 
409 %type <svals> opt_type_params type_params
410 
411 %%
412 /*
413  * Grammar start here
414  */
415 start : definitions;
416 
417 definitions :
418     definition definitions
419     | /* EMPTY */
420     ;
421 
422 definition :
423     opt_published publishable_definition
424     | module_dcl
425     {
426         idlc()->setParseState(PS_ModuleDeclSeen);
427     }
428     ';'
429     {
430         idlc()->setParseState(PS_NoState);
431     }
432     | error ';'
433     {
434         yyerror("definitions");
435         yyerrok;
436     }
437     ;
438 
439 opt_published:
440     IDL_PUBLISHED { idlc()->setPublished(true); }
441     | /* empty */ { idlc()->setPublished(false); }
442     ;
443 
444 publishable_definition:
445     type_dcl
446     {
447         idlc()->setParseState(PS_TypeDeclSeen);
448     }
449     ';'
450     {
451         idlc()->setParseState(PS_NoState);
452     }
453     | const_dcl
454     {
455         idlc()->setParseState(PS_ConstantDeclSeen);
456     }
457     ';'
458     {
459         idlc()->setParseState(PS_NoState);
460     }
461     | exception_dcl
462     {
463         idlc()->setParseState(PS_ExceptionDeclSeen);
464     }
465     ';'
466     {
467         idlc()->setParseState(PS_NoState);
468     }
469     | interface
470     {
471         idlc()->setParseState(PS_InterfaceDeclSeen);
472     }
473     ';'
474     {
475         idlc()->setParseState(PS_NoState);
476     }
477     | service_dcl
478     {
479         idlc()->setParseState(PS_ServiceDeclSeen);
480     }
481     ';'
482     {
483         idlc()->setParseState(PS_NoState);
484     }
485     | singleton_dcl
486     {
487         idlc()->setParseState(PS_SingletonDeclSeen);
488     }
489     ';'
490     {
491         idlc()->setParseState(PS_NoState);
492     }
493     | constants_dcl
494     {
495         idlc()->setParseState(PS_ConstantsDeclSeen);
496     }
497     ';'
498     {
499         idlc()->setParseState(PS_NoState);
500     }
501     ;
502 
503 module_dcl :
504     IDL_MODULE
505     {
506         idlc()->setParseState(PS_ModuleSeen);
507         idlc()->setPublished(false);
508     }
509     identifier
510     {
511         idlc()->setParseState(PS_ModuleIDSeen);
512         checkIdentifier($3);
513 
514         AstScope*       pScope = idlc()->scopes()->topNonNull();
515         AstModule*      pModule = NULL;
516         AstDeclaration* pExists = NULL;
517 
518         if ( pScope )
519         {
520             pModule = new AstModule(*$3, pScope);
521             if( (pExists = pScope->lookupForAdd(pModule)) )
522             {
523                 pExists->setInMainfile(idlc()->isInMainFile());
524                 pExists->setFileName(pModule->getFileName());
525                 if (pExists->isPredefined())
526                 {
527                     pExists->setPredefined(false);
528                     if (pExists->getDocumentation().getLength() == 0 &&
529                         pModule->getDocumentation().getLength() > 0)
530                     {
531                         pExists->setDocumentation(pModule->getDocumentation());
532                     }
533                 }
534                 delete(pModule);
535                 pModule = (AstModule*)pExists;
536             } else
537             {
538                 pScope->addDeclaration(pModule);
539             }
540             idlc()->scopes()->push(pModule);
541         }
542         delete $3;
543     }
544     '{'
545     {
546         idlc()->setParseState(PS_ModuleSqSeen);
547     }
548     definitions
549     {
550         idlc()->setParseState(PS_ModuleBodySeen);
551     }
552     '}'
553     {
554         idlc()->setParseState(PS_ModuleQsSeen);
555         /*
556          * Finished with this module - pop it from the scope stack
557          */
558         idlc()->scopes()->pop();
559     }
560     ;
561 
562 interface :
563     interface_dcl
564     | forward_dcl
565     ;
566 
567 interface_decl :
568     IDL_INTERFACE
569     {
570         idlc()->setParseState(PS_InterfaceSeen);
571     }
572     identifier
573     {
574         idlc()->setParseState(PS_InterfaceIDSeen);
575        checkIdentifier($3);
576         $$ = $3;
577     }
578     ;
579 
580 forward_dcl :
581     interface_decl
582     {
583         idlc()->setParseState(PS_ForwardDeclSeen);
584 
585         AstScope*       pScope = idlc()->scopes()->topNonNull();
586         AstInterface*   pForward = NULL;
587         AstDeclaration* pDecl = NULL;
588 
589         /*
590          * Make a new forward interface node and add it to its enclosing scope
591          */
592         if ( pScope && $1 )
593         {
594             pForward = new AstInterface(*$1, NULL, pScope);
595 
596             if ( pDecl = pScope->lookupByName(pForward->getScopedName()) )
597             {
598                 if ( (pDecl != pForward) &&
599                      (pDecl->getNodeType() == NT_interface) )
600                 {
601                     delete pForward;
602                 } else
603                 {
604                     idlc()->error()->error2(EIDL_REDEF_SCOPE, scopeAsDecl(pScope), pDecl);
605                 }
606             } else
607             {
608                 /*
609                  * Add the interface to its definition scope
610                  */
611                 pScope->addDeclaration(pForward);
612             }
613         }
614         delete $1;
615     }
616     ;
617 
618 interface_dcl :
619     interfaceheader
620     {
621         idlc()->setParseState(PS_InterfaceHeadSeen);
622 
623         AstScope*       pScope = idlc()->scopes()->topNonNull();
624         AstInterface*   pInterface = NULL;
625         AstInterface*   pForward = NULL;
626         AstDeclaration* pDecl = NULL;
627 
628         /*
629          * Make a new interface node and add it to its enclosing scope
630          */
631         if ( pScope && $1 )
632         {
633             pInterface = new AstInterface(
634                 *$1->getName(),
635                 static_cast< AstInterface * >($1->getInherits()), pScope);
636             if ( pInterface &&
637                 (pDecl = pScope->lookupByName(pInterface->getScopedName())) )
638             {
639                 /*
640                  * See if we're defining a forward declared interface.
641                  */
642                 if (pDecl->getNodeType() == NT_interface)
643                 {
644                     pForward = (AstInterface*)pDecl;
645                     if ( !pForward->isDefined() )
646                     {
647                         /*
648                          * Check if redefining in same scope
649                          */
650                         if ( pForward->getScope() != pScope )
651                         {
652                             if ( pForward->getScopedName() != pInterface->getScopedName() )
653                             {
654                                 idlc()->error()->error3(EIDL_SCOPE_CONFLICT,
655                                          pInterface, pForward, scopeAsDecl(pScope));
656                             }
657                         }
658                         else if ( !pInterface->isPublished()
659                                   && pForward->isPublished() )
660                         {
661                             idlc()->error()->error0(EIDL_PUBLISHED_FORWARD);
662                         }
663                         /*
664                          * All OK, set full definition
665                          */
666                         else
667                         {
668                             pForward->forwardDefined(*pInterface);
669                             delete pInterface;
670                             pInterface = pForward;
671                         }
672                     } else {
673                         // special handling for XInterface because it is predefined
674                         if ( pForward->isPredefined() &&
675                              pForward->getScopedName() == "com::sun::star::uno::XInterface")
676                         {
677                             /* replace the predefined XInterface */
678                             *pForward = *pInterface;
679                             delete pInterface;
680                             pInterface = pForward;
681                         }
682 
683                     }
684                 }
685             } else
686             {
687                 /*
688                  * Add the interface to its definition scope
689                  */
690                 pScope->addDeclaration(pInterface);
691             }
692         }
693         /*
694          * Push it on the scope stack
695          */
696         idlc()->scopes()->push(pInterface);
697         delete($1);
698     }
699     '{'
700     {
701         idlc()->setParseState(PS_InterfaceSqSeen);
702     }
703     exports
704     {
705         AstInterface * ifc = static_cast< AstInterface * >(
706             idlc()->scopes()->topNonNull());
707         if (!ifc->hasMandatoryInheritedInterfaces()
708             && ifc->getScopedName() != "com::sun::star::uno::XInterface")
709         {
710             addInheritedInterface(
711                 ifc, rtl::OString("::com::sun::star::uno::XInterface"), false,
712                 rtl::OUString());
713         }
714         ifc->setDefined();
715         idlc()->setParseState(PS_InterfaceBodySeen);
716     }
717     '}'
718     {
719         idlc()->setParseState(PS_InterfaceQsSeen);
720         /*
721          * Done with this interface - pop it off the scopes stack
722          */
723         idlc()->scopes()->pop();
724     }
725     | error '}'
726     {
727         yyerror("interface definition");
728         yyerrok;
729     }
730     ;
731 
732 interfaceheader :
733     interface_decl inheritance_spec
734     {
735         idlc()->setParseState(PS_InheritSpecSeen);
736 
737         $$ = new FeInheritanceHeader(NT_interface, $1, $2, 0);
738         delete $2;
739     }
740     ;
741 
742 inheritance_spec :
743     ':'
744     {
745         idlc()->setParseState(PS_InheritColonSeen);
746     }
747     scoped_name
748     {
749         $$ = $3;
750     }
751     | /* EMPTY */
752     {
753         $$ = NULL;
754     }
755     ;
756 
757 exports :
758     exports export
759     | /* EMPTY */
760     ;
761 
762 export :
763     attribute
764     {
765         idlc()->setParseState(PS_AttributeDeclSeen);
766     }
767     ';'
768     {
769         idlc()->setParseState(PS_NoState);
770     }
771     | operation
772     {
773         idlc()->setParseState(PS_OperationDeclSeen);
774     }
775     ';'
776     {
777         idlc()->setParseState(PS_NoState);
778     }
779     | interface_inheritance_decl
780     {
781         idlc()->setParseState(PS_InterfaceInheritanceDeclSeen);
782     }
783     ';'
784     {
785         idlc()->setParseState(PS_NoState);
786     }
787     ;
788 
789 attribute :
790     flag_header
791     simple_type_spec
792     {
793         idlc()->setParseState(PS_AttrTypeSeen);
794     }
795     simple_declarator
796     {
797         idlc()->setParseState(PS_AttrCompleted);
798         if (($1 & ~(AF_BOUND | AF_READONLY)) != AF_ATTRIBUTE) {
799             idlc()->error()->flagError(EIDL_BAD_ATTRIBUTE_FLAGS, $1);
800         }
801         AstInterface * scope = static_cast< AstInterface * >(
802             idlc()->scopes()->top());
803         AstAttribute * attr = new AstAttribute(
804             $1, $4->compose($2), $4->getName(), scope);
805         delete $4;
806         AstInterface::DoubleMemberDeclarations doubleMembers(
807             scope->checkMemberClashes(attr));
808         if (doubleMembers.empty()) {
809             scope->addMember(attr);
810         } else {
811             reportDoubleMemberDeclarations(doubleMembers);
812         }
813         idlc()->scopes()->push(attr);
814     }
815     opt_attribute_block
816     {
817         static_cast< AstAttribute * >(idlc()->scopes()->top())->setExceptions(
818             $6.get.documentation, $6.get.exceptions, $6.set.documentation,
819             $6.set.exceptions);
820         delete $6.get.documentation;
821         delete $6.get.exceptions;
822         delete $6.set.documentation;
823         delete $6.set.exceptions;
824         idlc()->scopes()->pop();
825     }
826     ;
827 
828 flag_header :
829     '[' opt_attrflags ']'
830     {
831         idlc()->setParseState(PS_FlagHeaderSeen);
832         $$ = $2;
833     }
834     ;
835 
836 opt_attrflags :
837     opt_attrflags ',' opt_attrflag
838     {
839         if ( ($1 & $3) == $3 )
840             idlc()->error()->flagError(EIDL_DEFINED_ATTRIBUTEFLAG, $3);
841 
842         $$ = $1 | $3;
843     }
844     | opt_attrflag
845     {
846         $$ = $1;
847     }
848     ;
849 
850 opt_attrflag :
851     IDL_ATTRIBUTE
852     {
853         idlc()->setParseState(PS_AttrSeen);
854         $$ = AF_ATTRIBUTE;
855     }
856     | IDL_PROPERTY
857     {
858         idlc()->setParseState(PS_PropertySeen);
859         $$ = AF_PROPERTY;
860     }
861     | IDL_READONLY
862     {
863         idlc()->setParseState(PS_ReadOnlySeen);
864         $$ = AF_READONLY;
865     }
866     | IDL_OPTIONAL
867     {
868         idlc()->setParseState(PS_OptionalSeen);
869         $$ = AF_OPTIONAL;
870     }
871     | IDL_MAYBEVOID
872     {
873         idlc()->setParseState(PS_MayBeVoidSeen);
874         $$ = AF_MAYBEVOID;
875     }
876     | IDL_BOUND
877     {
878         idlc()->setParseState(PS_BoundSeen);
879         $$ = AF_BOUND;
880     }
881     | IDL_CONSTRAINED
882     {
883         idlc()->setParseState(PS_ConstrainedSeen);
884         $$ = AF_CONSTRAINED;
885     }
886     | IDL_TRANSIENT
887     {
888         idlc()->setParseState(PS_TransientSeen);
889         $$ = AF_TRANSIENT;
890     }
891     | IDL_MAYBEAMBIGUOUS
892     {
893         idlc()->setParseState(PS_MayBeAmbigiousSeen);
894         $$ = AF_MAYBEAMBIGUOUS;
895     }
896     | IDL_MAYBEDEFAULT
897     {
898         idlc()->setParseState(PS_MayBeDefaultSeen);
899         $$ = AF_MAYBEDEFAULT;
900     }
901     | IDL_REMOVEABLE
902     {
903         idlc()->setParseState(PS_RemoveableSeen);
904         $$ = AF_REMOVEABLE;
905     }
906     | error ']'
907     {
908        yyerror("unknown property|attribute flag");
909         yyerrok;
910     }
911     ;
912 
913 opt_attribute_block:
914     '{' attribute_block_rest { $$ = $2; }
915     | /* empty */
916     {
917         $$.get.documentation = 0;
918         $$.get.exceptions = 0;
919         $$.set.documentation = 0;
920         $$.set.exceptions = 0;
921     }
922     ;
923 
924 attribute_block_rest:
925     opt_attribute_raises '}'
926     | error '}'
927     {
928         yyerror("bad attribute raises block");
929         yyerrok;
930         $$.get.documentation = 0;
931         $$.get.exceptions = 0;
932         $$.set.documentation = 0;
933         $$.set.exceptions = 0;
934     }
935     ;
936 
937 opt_attribute_raises:
938     attribute_get_raises
939     opt_attribute_set_raises
940     {
941         $$.get = $1;
942         $$.set = $2;
943     }
944     | attribute_set_raises
945     opt_attribute_get_raises
946     {
947         $$.get = $2;
948         $$.set = $1;
949     }
950     | /* empty */
951     {
952         $$.get.documentation = 0;
953         $$.get.exceptions = 0;
954         $$.set.documentation = 0;
955         $$.set.exceptions = 0;
956     }
957     ;
958 
959 opt_attribute_get_raises:
960     attribute_get_raises
961     | /* empty */ { $$.documentation = 0; $$.exceptions = 0; }
962     ;
963 
964 attribute_get_raises:
965     IDL_GET raises ';'
966     {
967         $$.documentation = new rtl::OUString(
968             rtl::OStringToOUString(
969                 idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8));
970         $$.exceptions = $2;
971     }
972     ;
973 
974 opt_attribute_set_raises:
975     attribute_set_raises
976     | /* empty */ { $$.documentation = 0; $$.exceptions = 0; }
977     ;
978 
979 attribute_set_raises:
980     IDL_SET
981     {
982         if (static_cast< AstAttribute * >(idlc()->scopes()->top())->
983             isReadonly())
984         {
985             idlc()->error()->error0(EIDL_READONLY_ATTRIBUTE_SET_EXCEPTIONS);
986         }
987     }
988     raises ';'
989     {
990         $$.documentation = new rtl::OUString(
991             rtl::OStringToOUString(
992                 idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8));
993         $$.exceptions = $3;
994     }
995     ;
996 
997 operation :
998     operation_head
999     op_type_spec
1000     {
1001         idlc()->setParseState(PS_OpTypeSeen);
1002     }
1003     identifier
1004     {
1005         idlc()->setParseState(PS_OpIDSeen);
1006        checkIdentifier($4);
1007 
1008         AstInterface * pScope = static_cast< AstInterface * >(
1009             idlc()->scopes()->top());
1010         AstOperation*   pOp = NULL;
1011 
1012         /*
1013          * Create a node representing an operation on an interface
1014          * and add it to its enclosing scope
1015          */
1016         if ( pScope && $2 )
1017         {
1018             AstType *pType = (AstType*)$2;
1019             if ( !pType || (pType->getNodeType() == NT_exception) )
1020             {
1021                 // type ERROR
1022             } else
1023             {
1024                 pOp = new AstOperation($1, pType, *$4, pScope);
1025 
1026                 AstInterface::DoubleMemberDeclarations doubleMembers(
1027                     pScope->checkMemberClashes(pOp));
1028                 if (doubleMembers.empty()) {
1029                     pScope->addMember(pOp);
1030                 } else {
1031                     reportDoubleMemberDeclarations(doubleMembers);
1032                 }
1033             }
1034         }
1035         delete $4;
1036         /*
1037          * Push the operation scope onto the scopes stack
1038          */
1039         idlc()->scopes()->push(pOp);
1040     }
1041     '('
1042     {
1043         idlc()->setParseState(PS_OpSqSeen);
1044     }
1045     parameters
1046     {
1047         idlc()->setParseState(PS_OpParsCompleted);
1048     }
1049     ')'
1050     {
1051         idlc()->setParseState(PS_OpQsSeen);
1052     }
1053     opt_raises
1054     {
1055         AstScope*       pScope = idlc()->scopes()->topNonNull();
1056         AstOperation*   pOp = NULL;
1057         /*
1058          * Add exceptions and context to the operation
1059          */
1060         if ( pScope && pScope->getScopeNodeType() == NT_operation)
1061         {
1062             pOp = (AstOperation*)pScope;
1063 
1064             if ( pOp )
1065                 pOp->setExceptions($12);
1066         }
1067         delete $12;
1068         /*
1069          * Done with this operation. Pop its scope from the scopes stack
1070          */
1071         idlc()->scopes()->pop();
1072     }
1073     ;
1074 
1075 operation_head :
1076     '['
1077     IDL_ONEWAY
1078     {
1079         idlc()->setParseState(PS_OpOnewaySeen);
1080     }
1081     ']'
1082     {
1083         idlc()->setParseState(PS_OpHeadSeen);
1084         $$ = OP_ONEWAY;
1085     }
1086     | /* EMPTY */
1087     {
1088         $$ = OP_NONE;
1089     }
1090     ;
1091 
1092 op_type_spec :
1093     simple_type_spec
1094     | IDL_VOID
1095     {
1096         $$ = idlc()->scopes()->bottom()->lookupPrimitiveType(ET_void);
1097     }
1098     ;
1099 
1100 parameters :
1101     parameter
1102     | parameters
1103     ','
1104     {
1105         idlc()->setParseState(PS_OpParCommaSeen);
1106     }
1107     parameter
1108     | /* EMPTY */
1109     | error ','
1110     {
1111         yyerror("parameter definition");
1112         yyerrok;
1113     }
1114     ;
1115 
1116 parameter :
1117     '['
1118     direction
1119     ']'
1120     {
1121         idlc()->setParseState(PS_OpParDirSeen);
1122     }
1123     simple_type_spec
1124     {
1125         idlc()->setParseState(PS_OpParTypeSeen);
1126     }
1127     opt_rest
1128     declarator
1129     {
1130         idlc()->setParseState(PS_OpParDeclSeen);
1131 
1132         AstOperation * pScope = static_cast< AstOperation * >(
1133             idlc()->scopes()->top());
1134         AstParameter*   pParam = NULL;
1135 
1136         /*
1137          * Create a node representing an argument to an operation
1138          * Add it to the enclosing scope (the operation scope)
1139          */
1140         if ( pScope && $5 && $8 )
1141         {
1142             AstType const * pType = $8->compose($5);
1143             if ( pType )
1144             {
1145                 if (pScope->isConstructor() && $2 != DIR_IN) {
1146                     idlc()->error()->error0(EIDL_CONSTRUCTOR_PARAMETER_NOT_IN);
1147                 }
1148                 if (pScope->isVariadic()) {
1149                     idlc()->error()->error0(EIDL_REST_PARAMETER_NOT_LAST);
1150                 }
1151                 if ($7) {
1152                     AstDeclaration const * type = resolveTypedefs(pType);
1153                     if (type->getNodeType() != NT_predefined
1154                         || (static_cast< AstBaseType const * >(type)->
1155                             getExprType() != ET_any))
1156                     {
1157                         idlc()->error()->error0(EIDL_REST_PARAMETER_NOT_ANY);
1158                     }
1159                     if (pScope->isConstructor()) {
1160                         if (pScope->getIteratorBegin()
1161                             != pScope->getIteratorEnd())
1162                         {
1163                             idlc()->error()->error0(
1164                                 EIDL_CONSTRUCTOR_REST_PARAMETER_NOT_FIRST);
1165                         }
1166                     } else {
1167                         idlc()->error()->error0(EIDL_METHOD_HAS_REST_PARAMETER);
1168                     }
1169                 }
1170 
1171                 pParam = new AstParameter(
1172                     static_cast< Direction >($2), $7, pType, $8->getName(),
1173                     pScope);
1174 
1175                 if ( !$8->checkType($5) )
1176                 {
1177                     // WARNING
1178                 }
1179 
1180                 pScope->addDeclaration(pParam);
1181             }
1182         }
1183     }
1184     | error
1185     simple_type_spec
1186     {
1187         idlc()->setParseState(PS_NoState);
1188         yyerrok;
1189     }
1190     ;
1191 
1192 direction :
1193     IDL_IN
1194     {
1195         $$ = DIR_IN;
1196     }
1197     | IDL_OUT
1198     {
1199         $$ = DIR_OUT;
1200     }
1201     | IDL_INOUT
1202     {
1203         $$ = DIR_INOUT;
1204     }
1205     ;
1206 
1207 opt_rest:
1208     IDL_ELLIPSIS
1209     {
1210         $$ = true;
1211     }
1212     | /* empty */
1213     {
1214         $$ = false;
1215     }
1216     ;
1217 
1218 opt_raises:
1219     raises
1220     | /* empty */
1221     {
1222         $$ = 0;
1223     }
1224     ;
1225 
1226 raises:
1227     IDL_RAISES
1228     {
1229         idlc()->setParseState(PS_RaiseSeen);
1230     }
1231     '('
1232     {
1233         idlc()->setParseState(PS_RaiseSqSeen);
1234     }
1235     exception_list
1236     ')'
1237     {
1238         idlc()->setParseState(PS_RaiseQsSeen);
1239         $$ = $5;
1240     }
1241     ;
1242 
1243 exception_list:
1244     exception_name
1245     {
1246         $$ = new DeclList;
1247         $$->push_back($1);
1248     }
1249     | exception_list ',' exception_name
1250     {
1251         $1->push_back($3);
1252         $$ = $1;
1253     }
1254     ;
1255 
1256 exception_name:
1257     scoped_name
1258     {
1259         // The topmost scope is either an AstOperation (for interface methods
1260         // and service constructors) or an AstAttribute (for interface
1261         // attributes), so look up exception names in the next-to-topmost scope:
1262         AstDeclaration * decl = idlc()->scopes()->nextToTop()->lookupByName(
1263             *$1);
1264         if (decl == 0) {
1265             idlc()->error()->lookupError(*$1);
1266         } else if (!idlc()->error()->checkPublished(decl)) {
1267             decl = 0;
1268         } else if (decl->getNodeType() != NT_exception) {
1269             idlc()->error()->error1(EIDL_ILLEGAL_RAISES, decl);
1270             decl = 0;
1271         }
1272         delete $1;
1273         $$ = decl;
1274     }
1275     ;
1276 
1277 interface_inheritance_decl:
1278     optional_inherited_interface
1279     IDL_INTERFACE
1280     {
1281         idlc()->setParseState(PS_ServiceIFHeadSeen);
1282     }
1283     scoped_name
1284     {
1285         AstInterface * ifc = static_cast< AstInterface * >(
1286             idlc()->scopes()->top());
1287         if (ifc->usesSingleInheritance()) {
1288             idlc()->error()->error0(EIDL_MIXED_INHERITANCE);
1289         } else {
1290             addInheritedInterface(
1291                 ifc, *$4, $1,
1292                 rtl::OStringToOUString(
1293                     idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8));
1294         }
1295         delete $4;
1296     }
1297     ;
1298 
1299 optional_inherited_interface:
1300     '[' IDL_OPTIONAL ']' { $$ = true; }
1301     | /* EMPTY */ { $$ = false; }
1302     ;
1303 
1304 constants_exports :
1305     constants_export constants_exports
1306     | /* EMPTY */
1307     ;
1308 
1309 constants_export :
1310     const_dcl
1311     {
1312         idlc()->setParseState(PS_ConstantDeclSeen);
1313     }
1314     ';' {};
1315 
1316 const_dcl :
1317     IDL_CONST
1318     {
1319         idlc()->setParseState(PS_ConstSeen);
1320     }
1321     const_type
1322     {
1323         idlc()->setParseState(PS_ConstTypeSeen);
1324     }
1325     identifier
1326     {
1327         idlc()->setParseState(PS_ConstIDSeen);
1328         checkIdentifier($5);
1329     }
1330     '='
1331     {
1332         idlc()->setParseState(PS_ConstAssignSeen);
1333     }
1334     expression
1335     {
1336         idlc()->setParseState(PS_ConstExprSeen);
1337 
1338         AstScope*       pScope = idlc()->scopes()->topNonNull();
1339         AstConstant*    pConstant = NULL;
1340 
1341         if ( $9 && pScope )
1342         {
1343             if ( !$9->coerce($3) )
1344             {
1345                 idlc()->error()->coercionError($9, $3);
1346             } else
1347             {
1348                 pConstant = new AstConstant($3, $9, *$5, pScope);
1349                 pScope->addDeclaration(pConstant);
1350             }
1351         }
1352         delete $5;
1353     }
1354     ;
1355 
1356 constants_dcl :
1357     IDL_CONSTANTS
1358     {
1359         idlc()->setParseState(PS_ConstantsSeen);
1360     }
1361     identifier
1362     {
1363         idlc()->setParseState(PS_ConstantsIDSeen);
1364         checkIdentifier($3);
1365     }
1366     '{'
1367     {
1368         idlc()->setParseState(PS_ConstantsSqSeen);
1369 
1370         AstScope*       pScope = idlc()->scopes()->topNonNull();
1371         AstConstants*   pConstants = NULL;
1372         AstDeclaration* pExists = NULL;
1373 
1374         if ( pScope )
1375         {
1376             pConstants = new AstConstants(*$3, pScope);
1377             if( (pExists = pScope->lookupForAdd(pConstants)) )
1378             {
1379                 pExists->setInMainfile(idlc()->isInMainFile());
1380                 delete(pConstants);
1381                 pConstants = (AstConstants*)pExists;
1382             } else
1383             {
1384                 pScope->addDeclaration(pConstants);
1385             }
1386             idlc()->scopes()->push(pConstants);
1387         }
1388         delete $3;
1389     }
1390     constants_exports
1391     {
1392         idlc()->setParseState(PS_ConstantsBodySeen);
1393     }
1394     '}'
1395     {
1396         idlc()->setParseState(PS_ConstantsQsSeen);
1397         /*
1398          * Finished with this constants - pop it from the scope stack
1399          */
1400         idlc()->scopes()->pop();
1401     }
1402     ;
1403 
1404 expression : const_expr ;
1405 
1406 const_expr : or_expr ;
1407 
1408 or_expr :
1409     xor_expr
1410     | or_expr '|' xor_expr
1411     {
1412         $$ = new AstExpression(EC_or, $1, $3);
1413     }
1414     ;
1415 
1416 xor_expr :
1417     and_expr
1418     | xor_expr '^' and_expr
1419     {
1420         $$ = new AstExpression(EC_xor, $1, $3);
1421     }
1422     ;
1423 
1424 and_expr :
1425     shift_expr
1426     | and_expr '&' shift_expr
1427     {
1428         $$ = new AstExpression(EC_and, $1, $3);
1429     }
1430     ;
1431 
1432 shift_expr :
1433     add_expr
1434     | shift_expr IDL_LEFTSHIFT add_expr
1435     {
1436         $$ = new AstExpression(EC_left, $1, $3);
1437     }
1438     | shift_expr IDL_RIGHTSHIFT add_expr
1439     {
1440         $$ = new AstExpression(EC_right, $1, $3);
1441     }
1442     ;
1443 
1444 add_expr :
1445     mult_expr
1446     | add_expr '+' mult_expr
1447     {
1448         $$ = new AstExpression(EC_add, $1, $3);
1449     }
1450     | add_expr '-' mult_expr
1451     {
1452         $$ = new AstExpression(EC_minus, $1, $3);
1453     }
1454     ;
1455 
1456 mult_expr :
1457     unary_expr
1458     | mult_expr '*' unary_expr
1459     {
1460         $$ = new AstExpression(EC_mul, $1, $3);
1461     }
1462     | mult_expr '/' unary_expr
1463     {
1464         $$ = new AstExpression(EC_div, $1, $3);
1465     }
1466     | mult_expr '%' unary_expr
1467     {
1468         $$ = new AstExpression(EC_mod, $1, $3);
1469     }
1470     ;
1471 
1472 unary_expr :
1473     primary_expr
1474     | '+' primary_expr
1475     {
1476         $$ = new AstExpression(EC_u_plus, $2, NULL);
1477     }
1478     | '-' primary_expr
1479     {
1480         $$ = new AstExpression(EC_u_minus, $2, NULL);
1481     }
1482     | '~' primary_expr
1483     {
1484     }
1485     ;
1486 
1487 primary_expr :
1488     scoped_name
1489     {
1490         /*
1491          * An expression which is a scoped name is not resolved now,
1492          * but only when it is evaluated (such as when it is assigned
1493          * as a constant value)
1494          */
1495         $$ = new AstExpression($1);
1496     }
1497     | literal
1498     | '(' const_expr ')'
1499     {
1500         $$ = $2;
1501     }
1502     ;
1503 
1504 literal :
1505     IDL_INTEGER_LITERAL
1506     {
1507         $$ = new AstExpression($1);
1508     }
1509     | IDL_INTEGER_ULITERAL
1510     {
1511         $$ = new AstExpression($1);
1512     }
1513     | IDL_FLOATING_PT_LITERAL
1514     {
1515         $$ = new AstExpression($1);
1516     }
1517     | IDL_TRUE
1518     {
1519         $$ = new AstExpression((sal_Int32)1, ET_boolean);
1520     }
1521     | IDL_FALSE
1522     {
1523         $$ = new AstExpression((sal_Int32)0, ET_boolean);
1524     }
1525     ;
1526 
1527 positive_int_expr :
1528     const_expr
1529     {
1530         $1->evaluate(EK_const);
1531         if ( !$1->coerce(ET_ulong) )
1532         {
1533             idlc()->error()->coercionError($1, ET_ulong);
1534             delete $1;
1535             $$ = NULL;
1536         }
1537     }
1538     ;
1539 
1540 const_type :
1541     integer_type
1542     | char_type
1543     | byte_type
1544     | boolean_type
1545     | floating_pt_type
1546     | scoped_name
1547     {
1548         AstScope*       pScope = idlc()->scopes()->topNonNull();
1549         AstDeclaration const * type = 0;
1550 
1551         /*
1552          * If the constant's type is a scoped name, it must resolve
1553          * to a scalar constant type
1554          */
1555         if ( pScope && (type = pScope->lookupByName(*$1)) ) {
1556             if (!idlc()->error()->checkPublished(type))
1557             {
1558                 type = 0;
1559             }
1560             else
1561             {
1562                 type = resolveTypedefs(type);
1563                 if (type->getNodeType() == NT_predefined)
1564                 {
1565                     $$ = static_cast< AstBaseType const * >(type)->
1566                         getExprType();
1567                 } else
1568                     $$ = ET_any;
1569             }
1570         } else
1571             $$ = ET_any;
1572     }
1573     ;
1574 
1575 exception_header :
1576     IDL_EXCEPTION
1577     {
1578         idlc()->setParseState(PS_ExceptSeen);
1579     }
1580     identifier
1581     {
1582         idlc()->setParseState(PS_ExceptIDSeen);
1583         checkIdentifier($3);
1584     }
1585     inheritance_spec
1586     {
1587         idlc()->setParseState(PS_InheritSpecSeen);
1588 
1589         $$ = new FeInheritanceHeader(NT_exception, $3, $5, 0);
1590         delete $5;
1591     }
1592     ;
1593 
1594 exception_dcl :
1595     exception_header
1596     {
1597         idlc()->setParseState(PS_ExceptHeaderSeen);
1598 
1599         AstScope*       pScope = idlc()->scopes()->topNonNull();
1600         AstException*   pExcept = NULL;
1601 
1602         if ( pScope )
1603         {
1604             AstException* pBase = static_cast< AstException* >(
1605                 $1->getInherits());
1606             pExcept = new AstException(*$1->getName(), pBase, pScope);
1607             pScope->addDeclaration(pExcept);
1608         }
1609         /*
1610          * Push the scope of the exception on the scopes stack
1611          */
1612         idlc()->scopes()->push(pExcept);
1613         delete $1;
1614     }
1615     '{'
1616     {
1617         idlc()->setParseState(PS_ExceptSqSeen);
1618     }
1619     members
1620     {
1621         idlc()->setParseState(PS_ExceptBodySeen);
1622     }
1623     '}'
1624     {
1625         idlc()->setParseState(PS_ExceptQsSeen);
1626         /* this exception is finished, pop its scope from the stack */
1627         idlc()->scopes()->pop();
1628     }
1629     ;
1630 
1631 property :
1632     flag_header
1633     simple_type_spec
1634     {
1635         idlc()->setParseState(PS_PropertyTypeSeen);
1636     }
1637     at_least_one_declarator
1638     {
1639         idlc()->setParseState(PS_PropertyCompleted);
1640 
1641         AstScope*       pScope = idlc()->scopes()->topNonNull();
1642         AstAttribute*   pAttr = NULL;
1643         FeDeclList*     pList = $4;
1644         FeDeclarator*   pDecl = NULL;
1645         AstType const * pType = NULL;
1646 
1647         if ( pScope->getScopeNodeType() == NT_singleton )
1648         {
1649             idlc()->error()->error0(EIDL_ILLEGAL_ADD);
1650         } else
1651         {
1652             if ( ($1 & AF_ATTRIBUTE) == AF_ATTRIBUTE )
1653                 idlc()->error()->flagError(EIDL_WRONGATTRIBUTEKEYWORD, AF_ATTRIBUTE);
1654 
1655             if ( ($1 & AF_PROPERTY) != AF_PROPERTY )
1656                 idlc()->error()->flagError(EIDL_MISSINGATTRIBUTEKEYWORD, AF_PROPERTY);
1657 
1658             /*
1659              * Create nodes representing attributes and add them to the
1660              * enclosing scope
1661              */
1662             if ( pScope && $2 && pList )
1663             {
1664                 FeDeclList::iterator iter = pList->begin();
1665                 FeDeclList::iterator end = pList->end();
1666 
1667                 while (iter != end)
1668                 {
1669                     pDecl = (*iter);
1670                     if ( !pDecl )
1671                     {
1672                         iter++;
1673                         continue;
1674                     }
1675 
1676                     pType = pDecl->compose($2);
1677 
1678                     if ( !pType )
1679                     {
1680                         iter++;
1681                         continue;
1682                     }
1683 
1684                     pAttr = new AstAttribute(NT_property, $1, pType, pDecl->getName(), pScope);
1685 
1686                     pScope->addDeclaration(pAttr);
1687                     iter++;
1688                     delete pDecl;
1689                 }
1690             }
1691         }
1692 
1693         if ( pList )
1694             delete pList;
1695     }
1696     | error ';'
1697     {
1698         yyerror("property");
1699         yyerrok;
1700     }
1701     ;
1702 
1703 service_exports :
1704     service_exports service_export
1705     | /* EMPTY */
1706     ;
1707 
1708 service_export :
1709     service_interface_header
1710     at_least_one_scoped_name
1711     ';'
1712     {
1713         idlc()->setParseState(PS_ServiceMemberSeen);
1714 
1715         AstScope*           pScope = idlc()->scopes()->topNonNull();
1716         AstDeclaration*     pDecl = NULL;
1717         AstInterfaceMember* pIMember = NULL;
1718 
1719         if ( pScope->getScopeNodeType() == NT_singleton )
1720         {
1721             idlc()->error()->error0(EIDL_ILLEGAL_ADD);
1722         } else
1723         {
1724             /*
1725              * Create a node representing a class member.
1726              * Store it in the enclosing scope
1727              */
1728             if ( pScope && $2 )
1729             {
1730                 StringList::iterator iter = $2->begin();
1731                 StringList::iterator end = $2->end();
1732 
1733                 while ( iter != end )
1734                 {
1735                     pDecl = pScope->lookupByName(*iter);
1736                     if ( pDecl && (pDecl->getNodeType() == NT_interface) )
1737                     {
1738                         /* we relax the strict published check and allow to add new
1739                          * interfaces if they are optional
1740                          */
1741                         bool bOptional = (($1 & AF_OPTIONAL) == AF_OPTIONAL);
1742                         if ( idlc()->error()->checkPublished(pDecl, bOptional) )
1743                         {
1744                             pIMember = new AstInterfaceMember(
1745                                 $1, (AstInterface*)pDecl, *iter, pScope);
1746                             pScope->addDeclaration(pIMember);
1747                         }
1748                     } else
1749                     {
1750                         idlc()->error()->
1751                             lookupError(EIDL_INTERFACEMEMBER_LOOKUP, *iter, scopeAsDecl(pScope));
1752                     }
1753                     iter++;
1754                 }
1755             }
1756         }
1757         delete $2;
1758     }
1759     | service_service_header
1760     at_least_one_scoped_name
1761     ';'
1762     {
1763         idlc()->setParseState(PS_ServiceMemberSeen);
1764 
1765         AstScope*         pScope = idlc()->scopes()->topNonNull();
1766         AstDeclaration*   pDecl = NULL;
1767         AstServiceMember* pSMember = NULL;
1768 
1769         /*
1770          * Create a node representing a class member.
1771          * Store it in the enclosing scope
1772          */
1773         if ( pScope && $2 )
1774         {
1775             StringList::iterator iter = $2->begin();
1776             StringList::iterator end = $2->end();
1777 
1778             while ( iter != end )
1779             {
1780                 pDecl = pScope->lookupByName(*iter);
1781                 if ( pDecl && (pDecl->getNodeType() == NT_service) )
1782                 {
1783                     if ( pScope->getScopeNodeType() == NT_singleton && pScope->nMembers() > 0 )
1784                         idlc()->error()->error0(EIDL_ILLEGAL_ADD);
1785                     else if ( idlc()->error()->checkPublished(pDecl) )
1786                     {
1787                         pSMember = new AstServiceMember(
1788                             $1, (AstService*)pDecl, *iter, pScope);
1789                         pScope->addDeclaration(pSMember);
1790                     }
1791                 } else
1792                 {
1793                     idlc()->error()->
1794                         lookupError(EIDL_SERVICEMEMBER_LOOKUP, *iter, scopeAsDecl(pScope));
1795                 }
1796                 iter++;
1797             }
1798         }
1799         delete $2;
1800     }
1801     | IDL_OBSERVES
1802     at_least_one_scoped_name
1803     ';'
1804     {
1805         idlc()->setParseState(PS_ServiceMemberSeen);
1806 
1807         AstScope*       pScope = idlc()->scopes()->topNonNull();
1808         AstDeclaration* pDecl = NULL;
1809         AstObserves*    pObserves = NULL;
1810 
1811         if ( pScope->getScopeNodeType() == NT_singleton )
1812         {
1813             idlc()->error()->error0(EIDL_ILLEGAL_ADD);
1814         } else
1815         {
1816             /*
1817              * Create a node representing a class member.
1818              * Store it in the enclosing scope
1819              */
1820             if ( pScope && $2 )
1821             {
1822                 StringList::iterator iter = $2->begin();
1823                 StringList::iterator end = $2->end();
1824 
1825                 while ( iter != end )
1826                 {
1827                     pDecl = pScope->lookupByName(*iter);
1828                     if ( pDecl && (pDecl->getNodeType() == NT_interface) )
1829                     {
1830                         pObserves = new AstObserves((AstInterface*)pDecl, *iter, pScope);
1831                         pScope->addDeclaration(pObserves);
1832                     } else
1833                     {
1834                         idlc()->error()->
1835                             lookupError(EIDL_INTERFACEMEMBER_LOOKUP, *iter, scopeAsDecl(pScope));
1836                     }
1837                     iter++;
1838                 }
1839             }
1840         }
1841         delete $2;
1842     }
1843     | IDL_NEEDS
1844     at_least_one_scoped_name
1845     ';'
1846     {
1847         idlc()->setParseState(PS_ServiceMemberSeen);
1848 
1849         AstScope*       pScope = idlc()->scopes()->topNonNull();
1850         AstDeclaration* pDecl = NULL;
1851         AstNeeds*       pNeeds = NULL;
1852 
1853         if ( pScope->getScopeNodeType() == NT_singleton )
1854         {
1855             idlc()->error()->error0(EIDL_ILLEGAL_ADD);
1856         } else
1857         {
1858             /*
1859              * Create a node representing a class member.
1860              * Store it in the enclosing scope
1861              */
1862             if ( pScope && $2 )
1863             {
1864                 StringList::iterator iter = $2->begin();
1865                 StringList::iterator end = $2->end();
1866 
1867                 while ( iter != end )
1868                 {
1869                     pDecl = pScope->lookupByName(*iter);
1870                     if ( pDecl && (pDecl->getNodeType() == NT_service) )
1871                     {
1872                         pNeeds = new AstNeeds((AstService*)pDecl, *iter, pScope);
1873                         pScope->addDeclaration(pNeeds);
1874                     } else
1875                     {
1876                         idlc()->error()->
1877                             lookupError(EIDL_SERVICEMEMBER_LOOKUP, *iter, scopeAsDecl(pScope));
1878                     }
1879                     iter++;
1880                 }
1881             }
1882         }
1883         delete $2;
1884     }
1885     | property
1886     ';'
1887     {
1888         idlc()->setParseState(PS_PropertyDeclSeen);
1889     }
1890     ;
1891 
1892 service_interface_header :
1893     IDL_INTERFACE
1894     {
1895         idlc()->setParseState(PS_ServiceIFHeadSeen);
1896         $$ = AF_INVALID;
1897     }
1898     | flag_header
1899     IDL_INTERFACE
1900     {
1901         idlc()->setParseState(PS_ServiceIFHeadSeen);
1902         if ( (AF_OPTIONAL != $1) && ( AF_INVALID != $1) )
1903             idlc()->error()->flagError(EIDL_OPTIONALEXPECTED, $1);
1904         $$ = $1;
1905     }
1906     ;
1907 
1908 service_service_header :
1909     IDL_SERVICE
1910     {
1911         idlc()->setParseState(PS_ServiceSHeadSeen);
1912         $$ = AF_INVALID;
1913     }
1914     | flag_header
1915     IDL_SERVICE
1916     {
1917         idlc()->setParseState(PS_ServiceSHeadSeen);
1918         if ( (AF_OPTIONAL != $1) && ( AF_INVALID != $1) )
1919             idlc()->error()->flagError(EIDL_OPTIONALEXPECTED, $1);
1920         $$ = $1;
1921     }
1922     ;
1923 
1924 service_dcl :
1925     IDL_SERVICE
1926     {
1927         idlc()->setParseState(PS_ServiceSeen);
1928     }
1929     identifier
1930     {
1931         idlc()->setParseState(PS_ServiceIDSeen);
1932         checkIdentifier($3);
1933 
1934         AstScope*   pScope = idlc()->scopes()->topNonNull();
1935         AstService* pService = NULL;
1936 
1937         /*
1938          * Make a new service and add it to the enclosing scope
1939          */
1940         if (pScope != NULL)
1941         {
1942             pService = new AstService(*$3, pScope);
1943             pScope->addDeclaration(pService);
1944         }
1945         delete $3;
1946         /*
1947          * Push it on the stack
1948          */
1949         idlc()->scopes()->push(pService);
1950     }
1951     service_dfn
1952     {
1953         /* this service is finished, pop its scope from the stack */
1954         idlc()->scopes()->pop();
1955     }
1956     ;
1957 
1958 service_dfn:
1959     service_interface_dfn
1960     | service_obsolete_dfn
1961     ;
1962 
1963 service_interface_dfn:
1964     ':' scoped_name
1965     {
1966         AstScope * scope = idlc()->scopes()->nextToTop();
1967             // skip the scope pushed by service_dcl
1968         AstDeclaration * decl = scope->lookupByName(*$2);
1969         if (decl != 0 && resolveTypedefs(decl)->getNodeType() == NT_interface) {
1970             if (idlc()->error()->checkPublished(decl)) {
1971                 idlc()->scopes()->top()->addDeclaration(decl);
1972             }
1973         } else {
1974             idlc()->error()->lookupError(
1975                 EIDL_INTERFACEMEMBER_LOOKUP, *$2, scopeAsDecl(scope));
1976         }
1977         delete $2;
1978     }
1979     opt_service_body
1980     {
1981         AstService * s = static_cast< AstService * >(idlc()->scopes()->top());
1982         if (s != 0) {
1983             s->setDefaultConstructor(!$4);
1984         }
1985     }
1986     ;
1987 
1988 opt_service_body:
1989     service_body { $$ = true; }
1990     | /* empty */ { $$ = false; }
1991     ;
1992 
1993 service_body:
1994     '{'
1995     constructors
1996     '}'
1997     ;
1998 
1999 constructors:
2000     constructors constructor
2001     | /* empty */
2002     ;
2003 
2004 constructor:
2005     identifier
2006     {
2007         checkIdentifier($1);
2008         AstScope * scope = idlc()->scopes()->top();
2009         AstOperation * ctor = new AstOperation(OP_NONE, 0, *$1, scope);
2010         delete $1;
2011         scope->addDeclaration(ctor);
2012         idlc()->scopes()->push(ctor);
2013     }
2014     '('
2015     parameters
2016     ')'
2017     opt_raises
2018     {
2019         static_cast< AstOperation * >(idlc()->scopes()->top())->setExceptions(
2020             $6);
2021         delete $6;
2022         idlc()->scopes()->pop();
2023         if (static_cast< AstService * >(idlc()->scopes()->top())->
2024             checkLastConstructor())
2025         {
2026             idlc()->error()->error0(EIDL_SIMILAR_CONSTRUCTORS);
2027         }
2028     }
2029     ';'
2030     ;
2031 
2032 singleton_dcl :
2033     IDL_SINGLETON
2034     {
2035         idlc()->setParseState(PS_SingletonSeen);
2036     }
2037     identifier
2038     {
2039         idlc()->setParseState(PS_SingletonIDSeen);
2040         checkIdentifier($3);
2041 
2042         AstScope*   pScope = idlc()->scopes()->topNonNull();
2043         AstService* pService = NULL;
2044 
2045         /*
2046          * Make a new service and add it to the enclosing scope
2047          */
2048         if (pScope != NULL)
2049         {
2050             pService = new AstService(NT_singleton, *$3, pScope);
2051             pScope->addDeclaration(pService);
2052         }
2053         delete $3;
2054         /*
2055          * Push it on the stack
2056          */
2057         idlc()->scopes()->push(pService);
2058     }
2059     singleton_dfn
2060     {
2061         /* this singelton is finished, pop its scope from the stack */
2062         idlc()->scopes()->pop();
2063     }
2064     ;
2065 
2066 singleton_dfn:
2067     singleton_interface_dfn
2068     | service_obsolete_dfn
2069     ;
2070 
2071 singleton_interface_dfn:
2072     ':' scoped_name
2073     {
2074         AstScope * scope = idlc()->scopes()->nextToTop();
2075             // skip the scope (needlessly) pushed by singleton_dcl
2076         AstDeclaration * decl = scope->lookupByName(*$2);
2077         if (decl != 0 && resolveTypedefs(decl)->getNodeType() == NT_interface) {
2078             if (idlc()->error()->checkPublished(decl)) {
2079                 idlc()->scopes()->top()->addDeclaration(decl);
2080             }
2081         } else {
2082             idlc()->error()->lookupError(
2083                 EIDL_INTERFACEMEMBER_LOOKUP, *$2, scopeAsDecl(scope));
2084         }
2085         delete $2;
2086     }
2087     ;
2088 
2089 service_obsolete_dfn:
2090     '{'
2091     {
2092         idlc()->setParseState(
2093             idlc()->scopes()->top()->getScopeNodeType() == NT_service
2094             ? PS_ServiceSqSeen : PS_SingletonSqSeen);
2095     }
2096     service_exports
2097     {
2098         idlc()->setParseState(
2099             idlc()->scopes()->top()->getScopeNodeType() == NT_service
2100             ? PS_ServiceBodySeen : PS_SingletonBodySeen);
2101     }
2102     '}'
2103     {
2104         idlc()->setParseState(
2105             idlc()->scopes()->top()->getScopeNodeType() == NT_service
2106             ? PS_ServiceQsSeen : PS_SingletonQsSeen);
2107     }
2108     ;
2109 
2110 type_dcl :
2111     IDL_TYPEDEF
2112     {
2113         idlc()->setParseState(PS_TypedefSeen);
2114     }
2115     type_declarator {}
2116     | struct_type {}
2117     | union_type {}
2118     | enum_type {}
2119     ;
2120 
2121 type_declarator :
2122     type_spec
2123     {
2124         idlc()->setParseState(PS_TypeSpecSeen);
2125         if ($1 != 0 && $1->getNodeType() == NT_instantiated_struct) {
2126             idlc()->error()->error0(EIDL_INSTANTIATED_STRUCT_TYPE_TYPEDEF);
2127         }
2128     }
2129     at_least_one_declarator
2130     {
2131         idlc()->setParseState(PS_DeclaratorsSeen);
2132 
2133         AstScope*       pScope = idlc()->scopes()->topNonNull();
2134         AstTypeDef*     pTypeDef = NULL;
2135         FeDeclList*     pList = $3;
2136         FeDeclarator*   pDecl = NULL;
2137         AstType const * pType = NULL;
2138 
2139         /*
2140          * Create nodes representing typedefs and add them to the
2141          * enclosing scope
2142          */
2143         if ( pScope && $1 && pList )
2144         {
2145             FeDeclList::iterator iter = pList->begin();
2146             FeDeclList::iterator end = pList->end();
2147 
2148             while (iter != end)
2149             {
2150                 pDecl = (*iter);
2151                 if ( !pDecl )
2152                 {
2153                     iter++;
2154                     continue;
2155                 }
2156 
2157                 pType = pDecl->compose($1);
2158 
2159                 if ( !pType )
2160                 {
2161                     iter++;
2162                     continue;
2163                 }
2164 
2165                 pTypeDef = new AstTypeDef(pType, pDecl->getName(), pScope);
2166 
2167                 pScope->addDeclaration(pTypeDef);
2168                 iter++;
2169                 delete pDecl;
2170             }
2171             delete pList;
2172         }
2173     }
2174     ;
2175 
2176 at_least_one_declarator :
2177     declarator declarators
2178     {
2179         if ( $2 )
2180         {
2181             $2->push_back($1);
2182             $$ = $2;
2183         } else
2184         {
2185             FeDeclList* pList = new FeDeclList();
2186             pList->push_back($1);
2187             $$ = pList;
2188         }
2189     }
2190     ;
2191 
2192 declarators :
2193     declarators
2194     ','
2195     {
2196         idlc()->setParseState(PS_DeclsCommaSeen);
2197     }
2198     declarator
2199     {
2200         idlc()->setParseState(PS_DeclsDeclSeen);
2201         if ( $1 )
2202         {
2203             $1->push_back($4);
2204             $$ = $1;
2205         } else
2206         {
2207             FeDeclList* pList = new FeDeclList();
2208             pList->push_back($4);
2209             $$ = pList;
2210         }
2211     }
2212     | /* EMPTY */
2213     {
2214         $$ = NULL;
2215     }
2216     ;
2217 
2218 declarator :
2219     simple_declarator
2220     | complex_declarator
2221     ;
2222 
2223 simple_declarator :
2224     identifier
2225     {
2226         // For historic reasons, the struct com.sun.star.uno.Uik contains
2227         // members with illegal names (of the form "m_DataN"); avoid useless
2228         // warnings about them:
2229         AstScope * scope = idlc()->scopes()->top();
2230         if (scope == 0 || scope->getScopeNodeType() != NT_struct
2231             || (scopeAsDecl(scope)->getScopedName()
2232                 != "com::sun::star::uno::Uik"))
2233         {
2234             checkIdentifier($1);
2235         }
2236 
2237         $$ = new FeDeclarator(*$1, FeDeclarator::FD_simple, NULL);
2238         delete $1;
2239     }
2240     ;
2241 
2242 complex_declarator :
2243     array_declarator
2244     {
2245         $$ = new FeDeclarator($1->getLocalName(), FeDeclarator::FD_complex, $1);
2246     }
2247     ;
2248 
2249 array_declarator :
2250     identifier
2251     {
2252         idlc()->setParseState(PS_ArrayIDSeen);
2253         checkIdentifier($1);
2254     }
2255     at_least_one_array_dim
2256     {
2257         idlc()->setParseState(PS_ArrayCompleted);
2258         $$ = new AstArray(*$1, NULL, *$3, idlc()->scopes()->bottom());
2259         delete $1;
2260     }
2261     ;
2262 
2263 at_least_one_array_dim :
2264     array_dim array_dims
2265     {
2266         if( $2 )
2267         {
2268             $2->push_front($1);
2269             $$ = $2;
2270         } else
2271         {
2272             ExprList* pList = new ExprList();
2273             pList->push_back($1);
2274             $$ = pList;
2275         }
2276     }
2277     ;
2278 
2279 array_dims :
2280     array_dims array_dim
2281     {
2282         if( $1 )
2283         {
2284             $1->push_back($2);
2285             $$ = $1;
2286         } else
2287         {
2288             ExprList* pList = new ExprList();
2289             pList->push_back($2);
2290             $$ = pList;
2291         }
2292     }
2293     | /* EMPTY */
2294     {
2295         $$ = NULL;
2296     }
2297     ;
2298 
2299 array_dim :
2300     '['
2301     {
2302         idlc()->setParseState(PS_DimSqSeen);
2303     }
2304     positive_int_expr
2305     {
2306         idlc()->setParseState(PS_DimExprSeen);
2307     }
2308     ']'
2309     {
2310         idlc()->setParseState(PS_DimQsSeen);
2311         /*
2312          * Array dimensions are expressions which must be coerced to
2313          * positive integers
2314          */
2315         if ( !$3 || !$3->coerce(ET_uhyper) )
2316         {
2317             idlc()->error()->coercionError($3, ET_uhyper);
2318             $$ = NULL;
2319         } else
2320             $$ = $3;
2321     }
2322     ;
2323 
2324 at_least_one_scoped_name :
2325     scoped_name scoped_names
2326     {
2327         if ($2)
2328         {
2329             $2->push_front(*$1);
2330             $$ = $2;
2331         } else
2332         {
2333             StringList* pNames = new StringList();
2334             pNames->push_back(*$1);
2335             $$ = pNames;
2336         }
2337         delete($1);
2338     }
2339     ;
2340 
2341 scoped_names :
2342     scoped_names
2343     ','
2344     {
2345         idlc()->setParseState(PS_SNListCommaSeen);
2346     }
2347     scoped_name
2348     {
2349         idlc()->setParseState(PS_ScopedNameSeen);
2350         if ($1)
2351         {
2352             $1->push_back(*$4);
2353             $$ = $1;
2354         } else
2355         {
2356             StringList* pNames = new StringList();
2357             pNames->push_back(*$4);
2358             $$ = pNames;
2359         }
2360         delete($4);
2361     }
2362     | /* EMPTY */
2363     {
2364         $$ = NULL;
2365     }
2366     ;
2367 
2368 scoped_name :
2369     identifier
2370     {
2371         idlc()->setParseState(PS_SN_IDSeen);
2372         checkIdentifier($1);
2373         $$ = $1;
2374     }
2375     | IDL_SCOPESEPARATOR
2376     {
2377         idlc()->setParseState(PS_ScopeDelimSeen);
2378     }
2379     identifier
2380     {
2381         checkIdentifier($3);
2382         OString* pName = new OString("::");
2383         *pName += *$3;
2384         delete $3;
2385         $$ = pName;
2386     }
2387     | scoped_name
2388     IDL_SCOPESEPARATOR
2389     {
2390     }
2391     identifier
2392     {
2393         checkIdentifier($4);
2394         *$1 += ::rtl::OString("::");
2395         *$1 += *$4;
2396         delete $4;
2397         $$ = $1;
2398     }
2399     ;
2400 
2401 type_spec :
2402     simple_type_spec
2403     | constructed_type_spec
2404     ;
2405 
2406 simple_type_spec :
2407     fundamental_type
2408     | scoped_name opt_type_args
2409     {
2410         $$ = createNamedType($1, $2);
2411     }
2412     ;
2413 
2414 fundamental_type:
2415     base_type_spec
2416     {
2417         $$ = idlc()->scopes()->bottom()->lookupPrimitiveType($1);
2418     }
2419     | template_type_spec
2420     ;
2421 
2422 opt_type_args:
2423     '<' type_args '>' { $$ = $2; }
2424     | /* empty */ { $$ = 0; }
2425     ;
2426 
2427 type_args:
2428     type_arg
2429     {
2430         $$ = new DeclList;
2431         $$->push_back(const_cast< AstDeclaration * >($1)); //TODO: const_cast
2432     }
2433     | type_args ',' type_arg
2434     {
2435         $1->push_back(const_cast< AstDeclaration * >($3)); //TODO: const_cast
2436         $$ = $1;
2437     }
2438     ;
2439 
2440 type_arg:
2441     simple_type_spec
2442     {
2443         if ($1 != 0 && static_cast< AstType const * >($1)->isUnsigned()) {
2444             idlc()->error()->error0(EIDL_UNSIGNED_TYPE_ARGUMENT);
2445         }
2446         $$ = $1;
2447     }
2448     ;
2449 
2450 base_type_spec :
2451     integer_type
2452     | floating_pt_type
2453     | char_type
2454     | boolean_type
2455     | byte_type
2456     | any_type
2457     | type_type
2458     | string_type
2459     ;
2460 
2461 integer_type :
2462     signed_int
2463     | unsigned_int
2464     ;
2465 
2466 signed_int :
2467     IDL_LONG
2468     {
2469         $$ = ET_long;
2470     }
2471     | IDL_HYPER
2472     {
2473         $$ = ET_hyper;
2474     }
2475     | IDL_SHORT
2476     {
2477         $$ = ET_short;
2478     }
2479     ;
2480 
2481 unsigned_int :
2482     IDL_UNSIGNED IDL_LONG
2483     {
2484         $$ = ET_ulong;
2485     }
2486     | IDL_UNSIGNED IDL_HYPER
2487     {
2488         $$ = ET_uhyper;
2489     }
2490     | IDL_UNSIGNED IDL_SHORT
2491     {
2492         $$ = ET_ushort;
2493     }
2494     ;
2495 
2496 floating_pt_type :
2497     IDL_DOUBLE
2498     {
2499         $$ = ET_double;
2500     }
2501     | IDL_FLOAT
2502     {
2503         $$ = ET_float;
2504     }
2505     ;
2506 
2507 char_type :
2508     IDL_CHAR
2509     {
2510         $$ = ET_char;
2511     }
2512     ;
2513 
2514 byte_type :
2515     IDL_BYTE
2516     {
2517         $$ = ET_byte;
2518     }
2519     ;
2520 
2521 boolean_type :
2522     IDL_BOOLEAN
2523     {
2524         $$ = ET_boolean;
2525     }
2526     ;
2527 
2528 any_type :
2529     IDL_ANY
2530     {
2531         $$ = ET_any;
2532     }
2533     ;
2534 
2535 type_type :
2536     IDL_TYPE
2537     {
2538         $$ = ET_type;
2539     }
2540     ;
2541 
2542 string_type :
2543     IDL_STRING
2544     {
2545         $$ = ET_string;
2546     }
2547     ;
2548 
2549 template_type_spec :
2550     sequence_type_spec
2551     | array_type
2552     ;
2553 
2554 constructed_type_spec :
2555     struct_type
2556     | union_type
2557     | enum_type
2558     ;
2559 
2560 array_type :
2561     simple_type_spec
2562     {
2563         idlc()->setParseState(PS_ArrayTypeSeen);
2564     }
2565     at_least_one_array_dim
2566     {
2567         idlc()->setParseState(PS_ArrayCompleted);
2568 
2569         AstScope* pScope = idlc()->scopes()->bottom();
2570         AstDeclaration* pDecl = NULL;
2571         AstDeclaration* pArray = NULL;
2572 
2573         if ( $1 )
2574         {
2575             pArray = new AstArray((AstType*)$1, *$3, idlc()->scopes()->bottom());
2576             if ( pScope )
2577             {
2578                 pDecl = pScope->addDeclaration(pArray);
2579                 if ( pArray != pDecl )
2580                 {
2581                     // if array type already defined then use it
2582                     delete pArray;
2583                     pArray = pDecl;
2584                 }
2585             }
2586         }
2587         $$ = pArray;
2588     }
2589     ;
2590 
2591 sequence_type_spec :
2592     IDL_SEQUENCE
2593     {
2594         idlc()->setParseState(PS_SequenceSeen);
2595         /*
2596          * Push a sequence marker on scopes stack
2597          */
2598         idlc()->scopes()->push(NULL);
2599     }
2600     '<'
2601     {
2602         idlc()->setParseState(PS_SequenceSqSeen);
2603     }
2604     simple_type_spec
2605     {
2606         idlc()->setParseState(PS_SequenceTypeSeen);
2607     }
2608     '>'
2609     {
2610         idlc()->setParseState(PS_SequenceQsSeen);
2611         /*
2612          * Remove sequence marker from scopes stack
2613          */
2614         if (idlc()->scopes()->top() == NULL)
2615             idlc()->scopes()->pop();
2616         /*
2617          * Create a node representing a sequence
2618          */
2619         AstScope* pScope = idlc()->scopes()->bottom();
2620         AstDeclaration* pDecl = NULL;
2621         AstDeclaration* pSeq = NULL;
2622 
2623         if ( $5 )
2624         {
2625             AstType *pType = (AstType*)$5;
2626             if ( pType )
2627             {
2628                 pSeq = new AstSequence(pType, pScope);
2629                 /*
2630                  * Add this AstSequence to the types defined in the global scope
2631                  */
2632                 pDecl = pScope->addDeclaration(pSeq);
2633                 if ( pSeq != pDecl )
2634                 {
2635                     // if sequence type already defined then use it
2636                     delete pSeq;
2637                     pSeq = pDecl;
2638                 }
2639             }
2640         }
2641         $$ = pSeq;
2642     }
2643     | error '>'
2644     {
2645         yyerror("sequence declaration");
2646         yyerrok;
2647         $$ = 0;
2648     }
2649     ;
2650 
2651 struct_type :
2652     structure_header
2653     {
2654         idlc()->setParseState(PS_StructHeaderSeen);
2655 
2656         AstScope*   pScope = idlc()->scopes()->topNonNull();
2657         AstStruct*  pStruct = NULL;
2658 
2659         if ( pScope )
2660         {
2661             AstStruct* pBase= static_cast< AstStruct* >($1->getInherits());
2662             pStruct = new AstStruct(
2663                 *$1->getName(), $1->getTypeParameters(), pBase, pScope);
2664             pScope->addDeclaration(pStruct);
2665         }
2666         /*
2667          * Push the scope of the struct on the scopes stack
2668          */
2669         idlc()->scopes()->push(pStruct);
2670         delete $1;
2671     }
2672     '{'
2673     {
2674         idlc()->setParseState(PS_StructSqSeen);
2675     }
2676     at_least_one_member
2677     {
2678         idlc()->setParseState(PS_StructBodySeen);
2679     }
2680     '}'
2681     {
2682         idlc()->setParseState(PS_StructQsSeen);
2683         /* this exception is finished, pop its scope from the stack */
2684         idlc()->scopes()->pop();
2685     }
2686     ;
2687 
2688 structure_header :
2689     IDL_STRUCT
2690     {
2691         idlc()->setParseState(PS_StructSeen);
2692     }
2693     identifier
2694     {
2695         idlc()->setParseState(PS_StructIDSeen);
2696         checkIdentifier($3);
2697     }
2698     opt_type_params
2699     inheritance_spec
2700     {
2701         idlc()->setParseState(PS_InheritSpecSeen);
2702 
2703         // Polymorphic struct type templates with base types would cause various
2704         // problems in language bindings, so forbid them here.  For example,
2705         // GCC prior to version 3.4 fails with code like
2706         //
2707         //  struct Base { ... };
2708         //  template< typename typeparam_T > struct Derived: public Base {
2709         //      int member1 CPPU_GCC3_ALIGN(Base);
2710         //      ... };
2711         //
2712         // (Note that plain struct types with instantiated polymorphic struct
2713         // type bases, which might also cause problems in language bindings, are
2714         // already rejected on a syntactic level.)
2715         if ($5 != 0 && $6 != 0) {
2716             idlc()->error()->error0(EIDL_STRUCT_TYPE_TEMPLATE_WITH_BASE);
2717         }
2718 
2719         $$ = new FeInheritanceHeader(NT_struct, $3, $6, $5);
2720         delete $5;
2721         delete $6;
2722     }
2723     ;
2724 
2725 opt_type_params:
2726     '<' type_params '>' { $$ = $2; }
2727     | /* empty */ { $$ = 0; }
2728     ;
2729 
2730 type_params:
2731     identifier
2732     {
2733         $$ = new std::vector< rtl::OString >;
2734         $$->push_back(*$1);
2735         delete $1;
2736     }
2737     | type_params ',' identifier
2738     {
2739         if (std::find($1->begin(), $1->end(), *$3) != $1->end()) {
2740             idlc()->error()->error0(EIDL_IDENTICAL_TYPE_PARAMETERS);
2741         }
2742         $1->push_back(*$3);
2743         delete $3;
2744         $$ = $1;
2745     }
2746     ;
2747 
2748 at_least_one_member : member members ;
2749 
2750 members :
2751     members member
2752     | /* EMPTY */
2753     ;
2754 
2755 member :
2756     type_or_parameter
2757     {
2758         idlc()->setParseState(PS_MemberTypeSeen);
2759     }
2760     at_least_one_declarator
2761     {
2762         idlc()->setParseState(PS_MemberDeclsSeen);
2763     }
2764     ';'
2765     {
2766         idlc()->setParseState(PS_MemberDeclsCompleted);
2767 
2768         AstScope*       pScope = idlc()->scopes()->topNonNull();
2769         AstMember*      pMember = NULL;
2770         FeDeclList*     pList = $3;
2771         FeDeclarator*   pDecl = NULL;
2772         AstType const * pType = NULL;
2773 
2774         // !!! check recursive type
2775 
2776         if ( pScope && pList && $1 )
2777         {
2778             FeDeclList::iterator iter = pList->begin();
2779             FeDeclList::iterator end = pList->end();
2780             while (iter != end)
2781             {
2782                 pDecl = (*iter);
2783                 if ( !pDecl )
2784                 {
2785                     iter++;
2786                     continue;
2787                 }
2788 
2789                 pType = pDecl->compose($1);
2790 
2791                 if ( !pType )
2792                 {
2793                     iter++;
2794                     continue;
2795                 }
2796 
2797                 pMember = new AstMember(pType, pDecl->getName(), pScope);
2798 
2799                 if ( !pDecl->checkType($1) )
2800                 {
2801                     // WARNING
2802                 }
2803 
2804                 pScope->addDeclaration(pMember);
2805                 iter++;
2806                 delete pDecl;
2807             }
2808             delete pList;
2809         }
2810     }
2811     | error ';'
2812     {
2813         yyerror("member definition");
2814         yyerrok;
2815     }
2816     ;
2817 
2818 type_or_parameter:
2819     fundamental_type
2820     | scoped_name opt_type_args
2821     {
2822         AstDeclaration const * decl = 0;
2823         AstStruct * scope = static_cast< AstStruct * >(idlc()->scopes()->top());
2824         if (scope != 0 && $2 == 0) {
2825             decl = scope->findTypeParameter(*$1);
2826         }
2827         if (decl != 0) {
2828             delete $1;
2829             delete $2;
2830         } else {
2831             decl = createNamedType($1, $2);
2832             if (scope != 0 && includes(decl, scopeAsDecl(scope))) {
2833                 idlc()->error()->error1(
2834                     EIDL_RECURSIVE_TYPE, scopeAsDecl(scope));
2835                 decl = 0;
2836             }
2837         }
2838         $$ = decl;
2839     }
2840     ;
2841 
2842 enum_type :
2843     IDL_ENUM
2844     {
2845         idlc()->setParseState(PS_EnumSeen);
2846     }
2847     identifier
2848     {
2849         idlc()->setParseState(PS_EnumIDSeen);
2850         checkIdentifier($3);
2851 
2852         AstScope*       pScope = idlc()->scopes()->topNonNull();
2853         AstEnum*        pEnum = NULL;
2854 
2855         /*
2856          * Create a node representing an enum and add it to its
2857          * enclosing scope
2858          */
2859         if (pScope != NULL)
2860         {
2861             pEnum = new AstEnum(*$3, pScope);
2862             /*
2863              * Add it to its defining scope
2864              */
2865             pScope->addDeclaration(pEnum);
2866         }
2867         delete $3;
2868         /*
2869          * Push the enum scope on the scopes stack
2870          */
2871         idlc()->scopes()->push(pEnum);
2872 
2873     }
2874     '{'
2875     {
2876         idlc()->setParseState(PS_EnumSqSeen);
2877     }
2878     at_least_one_enumerator
2879     {
2880         idlc()->setParseState(PS_EnumBodySeen);
2881     }
2882     '}'
2883     {
2884         idlc()->setParseState(PS_EnumQsSeen);
2885         /*
2886          * Done with this enum. Pop its scope from the scopes stack
2887          */
2888         if (idlc()->scopes()->top() == NULL)
2889             $$ = NULL;
2890         else
2891         {
2892             $$ = (AstEnum*)idlc()->scopes()->topNonNull();
2893             idlc()->scopes()->pop();
2894         }
2895     }
2896     ;
2897 
2898 at_least_one_enumerator : enumerator enumerators ;
2899 
2900 enumerators :
2901     enumerators
2902     ','
2903     {
2904         idlc()->setParseState(PS_EnumCommaSeen);
2905     }
2906     enumerator
2907     | /* EMPTY */
2908     | error ','
2909     {
2910         yyerror("enumerator definition");
2911         yyerrok;
2912     }
2913     ;
2914 
2915 enumerator :
2916     identifier
2917     {
2918         checkIdentifier($1);
2919 
2920         AstScope*       pScope = idlc()->scopes()->topNonNull();
2921         AstEnum*        pEnum = NULL;
2922         AstConstant*    pEnumVal = NULL;
2923 
2924         if ( pScope && pScope->getScopeNodeType() == NT_enum)
2925         {
2926             pEnum = (AstEnum*)pScope;
2927             if (pEnum && $1)
2928             {
2929                 AstExpression* pExpr = new AstExpression(pEnum->getEnumValueCount());
2930                 pEnumVal = new AstConstant(ET_long , NT_enum_val,
2931                                            pExpr, *$1, pScope);
2932             }
2933             if ( pEnum->checkValue(pEnumVal->getConstValue()) )
2934                 idlc()->error()->error1(EIDL_EVAL_ERROR, pEnum);
2935 
2936             pScope->addDeclaration(pEnumVal);
2937         }
2938         delete $1;
2939     }
2940     | identifier
2941     '='
2942     const_expr
2943     {
2944         checkIdentifier($1);
2945 
2946         AstScope*       pScope = idlc()->scopes()->topNonNull();
2947         AstEnum*        pEnum = NULL;
2948         AstConstant*    pEnumVal = NULL;
2949 
2950         if ( $3 && pScope && pScope->getScopeNodeType() == NT_enum)
2951         {
2952             $3->evaluate(EK_const);
2953             if ( $3->coerce(ET_long) )
2954             {
2955                 pEnum = (AstEnum*)pScope;
2956                 if (pEnum)
2957                 {
2958                     pEnumVal = new AstConstant(ET_long , NT_enum_val,
2959                                                $3, *$1, pScope);
2960                 }
2961                 if ( pEnum->checkValue(pEnumVal->getConstValue()) )
2962                     idlc()->error()->error1(EIDL_EVAL_ERROR, pEnum);
2963 
2964                 pScope->addDeclaration(pEnumVal);
2965             } else
2966             {
2967                 idlc()->error()->coercionError($3, ET_long);
2968                 delete $3;
2969             }
2970         }
2971         delete $1;
2972     }
2973     ;
2974 
2975 union_type :
2976     IDL_UNION
2977     {
2978         idlc()->setParseState(PS_UnionSeen);
2979     }
2980     identifier
2981     {
2982         idlc()->setParseState(PS_UnionIDSeen);
2983         checkIdentifier($3);
2984     }
2985     IDL_SWITCH
2986     {
2987         idlc()->setParseState(PS_SwitchSeen);
2988     }
2989     '('
2990     {
2991         idlc()->setParseState(PS_SwitchOpenParSeen);
2992     }
2993     switch_type_spec
2994     {
2995         idlc()->setParseState(PS_SwitchTypeSeen);
2996     }
2997     ')'
2998     {
2999         idlc()->setParseState(PS_SwitchCloseParSeen);
3000 
3001         AstScope*       pScope = idlc()->scopes()->topNonNull();
3002         AstUnion*       pUnion = NULL;
3003 
3004         /*
3005          * Create a node representing a union. Add it to its enclosing
3006          * scope
3007          */
3008         if ( $9 && pScope )
3009         {
3010             AstType* pType = (AstType*)$9;
3011             if ( !pType)
3012             {
3013                 idlc()->error()->noTypeError($9);
3014             } else
3015             {
3016                 pUnion = new AstUnion(*$3, pType, pScope);
3017                 pScope->addDeclaration(pUnion);
3018             }
3019         }
3020         delete $3;
3021         /*
3022          * Push the scope of the union on the scopes stack
3023          */
3024         idlc()->scopes()->push(pUnion);
3025     }
3026     '{'
3027     {
3028         idlc()->setParseState(PS_UnionSqSeen);
3029     }
3030     at_least_one_case_branch
3031     {
3032         idlc()->setParseState(PS_UnionBodySeen);
3033     }
3034     '}'
3035     {
3036         idlc()->setParseState(PS_UnionQsSeen);
3037         /* this union is finished, pop its scope from the stack */
3038         idlc()->scopes()->pop();
3039     }
3040     ;
3041 
3042 switch_type_spec :
3043     integer_type
3044     {
3045         $$ = idlc()->scopes()->bottom()->lookupPrimitiveType($1);
3046     }
3047     | char_type
3048     {
3049         $$ = idlc()->scopes()->bottom()->lookupPrimitiveType($1);
3050     }
3051     | boolean_type
3052     {
3053         $$ = idlc()->scopes()->bottom()->lookupPrimitiveType($1);
3054     }
3055     | enum_type
3056     | scoped_name
3057     {
3058         AstScope*       pScope = idlc()->scopes()->topNonNull();
3059         AstBaseType*    pBaseType = NULL;
3060         AstDeclaration const * pDecl = NULL;
3061         AstTypeDef*     pTypeDef = NULL;
3062         sal_Bool        bFound = sal_False;
3063         /*
3064          * If the constant's type is a scoped name, it must resolve
3065          * to a scalar constant type
3066          */
3067         if ( pScope && (pDecl = pScope->lookupByName(*$1)) )
3068         {
3069             /*
3070              * Look through typedefs
3071              */
3072             while ( !bFound )
3073             {
3074                 switch (pDecl->getNodeType())
3075                 {
3076                     case NT_enum:
3077                         $$ = pDecl;
3078                         bFound = sal_True;
3079                         break;
3080                     case NT_predefined:
3081                         pBaseType = (AstBaseType*)pDecl;
3082                         if ( pBaseType )
3083                         {
3084                             switch (pBaseType->getExprType())
3085                             {
3086                                 case ET_short:
3087                                 case ET_ushort:
3088                                 case ET_long:
3089                                 case ET_ulong:
3090                                 case ET_hyper:
3091                                 case ET_uhyper:
3092                                 case ET_char:
3093                                 case ET_byte:
3094                                 case ET_boolean:
3095                                     $$ = pBaseType;
3096                                     bFound = sal_True;
3097                                     break;
3098                                 default:
3099                                     $$ = NULL;
3100                                     bFound = sal_True;
3101                                     break;
3102                             }
3103                         }
3104                         break;
3105                     case NT_typedef:
3106                         pTypeDef = (AstTypeDef*)pDecl;
3107                         if ( pTypeDef )
3108                             pDecl = pTypeDef->getBaseType();
3109                         break;
3110                     default:
3111                         $$ = NULL;
3112                         bFound = sal_True;
3113                        break;
3114                 }
3115             }
3116         } else
3117             $$ = NULL;
3118 
3119         if ($$ == NULL)
3120             idlc()->error()->lookupError(*$1);
3121     }
3122     ;
3123 
3124 at_least_one_case_branch : case_branch case_branches ;
3125 
3126 case_branches :
3127     case_branches case_branch
3128     | /* EMPTY */
3129     ;
3130 
3131 case_branch :
3132     at_least_one_case_label
3133     {
3134         idlc()->setParseState(PS_UnionLabelSeen);
3135     }
3136     element_spec
3137     {
3138         idlc()->setParseState(PS_UnionElemSeen);
3139 
3140         AstScope*       pScope = idlc()->scopes()->topNonNull();
3141         AstUnionLabel*  pLabel = NULL;
3142         AstUnionBranch* pBranch = NULL;
3143         AstMember*      pMember = $3;
3144 
3145         /*
3146          * Create several nodes representing branches of a union.
3147          * Add them to the enclosing scope (the union scope)
3148          */
3149         if ( pScope && $1 && $3 )
3150         {
3151             LabelList::iterator iter = $1->begin();
3152             LabelList::iterator end = $1->end();
3153             for (;iter != end; iter++)
3154             {
3155                 pLabel = *iter;
3156                 if ( !pLabel )
3157                 {
3158                     iter++;
3159                     continue;
3160                 }
3161                 pBranch = new AstUnionBranch(pLabel, pMember->getType(),
3162                                              pMember->getLocalName(), pScope);
3163                 pScope->addDeclaration(pBranch);
3164             }
3165         }
3166         if ( $1 ) delete($1);
3167     }
3168     ;
3169 
3170 at_least_one_case_label :
3171     case_label case_labels
3172     {
3173         if ( $2 )
3174         {
3175             $2->push_front($1);
3176             $$ = $2;
3177         } else
3178         {
3179             LabelList* pLabels = new LabelList();
3180             pLabels->push_back($1);
3181             $$ = pLabels;
3182         }
3183     }
3184     ;
3185 
3186 case_labels :
3187     case_labels case_label
3188     {
3189         if ( $1 )
3190         {
3191             $1->push_back($2);
3192             $$ = $1;
3193         } else
3194         {
3195             LabelList* pLabels = new LabelList();
3196             pLabels->push_back($2);
3197             $$ = pLabels;
3198         }
3199     }
3200     | /* EMPTY */
3201     {
3202         $$ = NULL;
3203     }
3204     ;
3205 
3206 case_label :
3207     IDL_DEFAULT
3208     {
3209         idlc()->setParseState(PS_DefaultSeen);
3210     }
3211     ':'
3212     {
3213         idlc()->setParseState(PS_LabelColonSeen);
3214         $$ = new AstUnionLabel(UL_default, NULL);
3215     }
3216     | IDL_CASE
3217     {
3218         idlc()->setParseState(PS_CaseSeen);
3219     }
3220     const_expr
3221     {
3222         idlc()->setParseState(PS_LabelExprSeen);
3223     }
3224     ':'
3225     {
3226         idlc()->setParseState(PS_LabelColonSeen);
3227         $$ = new AstUnionLabel(UL_label, $3);
3228     }
3229     ;
3230 
3231 element_spec :
3232     type_spec
3233     {
3234         idlc()->setParseState(PS_UnionElemTypeSeen);
3235     }
3236     declarator
3237     {
3238         idlc()->setParseState(PS_UnionElemDeclSeen);
3239     }
3240     ';'
3241     {
3242         idlc()->setParseState(PS_UnionElemCompleted);
3243 
3244         AstScope* pScope = idlc()->scopes()->topNonNull();
3245         /*
3246          * Check for illegal recursive use of type
3247          */
3248 //      if ( $1 && AST_illegal_recursive_type($1))
3249 //          idlc()->error()->error1(EIDL_RECURSIVE_TYPE, $1);
3250         /*
3251          * Create a field in a union branch
3252          */
3253         if ( $1 && $3 )
3254         {
3255             AstType const * pType = $3->compose($1);
3256             if ( !pType )
3257                 $$ = NULL;
3258             else
3259                 $$ = new AstMember(pType, $3->getName(), pScope);
3260         } else
3261             $$ = NULL;
3262 
3263         if ( $3 ) delete $3;
3264     }
3265     | error
3266     ';'
3267     {
3268         $$ = NULL;
3269     }
3270     ;
3271 
3272 identifier:
3273     IDL_IDENTIFIER
3274     | IDL_GET { $$ = new OString("get"); }
3275     | IDL_SET { $$ = new OString("set"); }
3276     | IDL_PUBLISHED { $$ = new OString("published"); }
3277     ;
3278 
3279 %%
3280 
3281 /*
3282  * Report an error situation discovered in a production
3283  */
3284 void yyerror(char const *errmsg)
3285 {
3286     idlc()->error()->syntaxError(idlc()->getParseState(), idlc()->getLineNumber(), errmsg);
3287     idlc()->setParseState(PS_NoState);
3288 }
3289