1 %{
2 
3 //
4 // Copyright (c) ZeroC, Inc. All rights reserved.
5 //
6 
7 #include <Slice/GrammarUtil.h>
8 #include <IceUtil/InputUtil.h>
9 #include <IceUtil/UUID.h>
10 #include <cstring>
11 
12 #ifdef _MSC_VER
13 // warning C4102: 'yyoverflowlab' : unreferenced label
14 #   pragma warning(disable:4102)
15 // warning C4065: switch statement contains 'default' but no 'case' labels
16 #   pragma warning(disable:4065)
17 // warning C4244: '=': conversion from 'int' to 'yytype_int16', possible loss of data
18 #   pragma warning(disable:4244)
19 #endif
20 
21 //
22 // Avoid old style cast warnings in generated grammar
23 //
24 #ifdef __GNUC__
25 #  pragma GCC diagnostic ignored "-Wold-style-cast"
26 #endif
27 
28 using namespace std;
29 using namespace Slice;
30 
31 void
slice_error(const char * s)32 slice_error(const char* s)
33 {
34     // yacc and recent versions of Bison use "syntax error" instead
35     // of "parse error".
36 
37     if (strcmp(s, "parse error") == 0)
38     {
39         unit->error("syntax error");
40     }
41     else
42     {
43         unit->error(s);
44     }
45 }
46 
47 %}
48 
49 %pure-parser
50 
51 //
52 // All keyword tokens. Make sure to modify the "keyword" rule in this
53 // file if the list of keywords is changed. Also make sure to add the
54 // keyword to the keyword table in Scanner.l.
55 //
56 %token ICE_MODULE
57 %token ICE_CLASS
58 %token ICE_INTERFACE
59 %token ICE_EXCEPTION
60 %token ICE_STRUCT
61 %token ICE_SEQUENCE
62 %token ICE_DICTIONARY
63 %token ICE_ENUM
64 %token ICE_OUT
65 %token ICE_EXTENDS
66 %token ICE_IMPLEMENTS
67 %token ICE_THROWS
68 %token ICE_VOID
69 %token ICE_BYTE
70 %token ICE_BOOL
71 %token ICE_SHORT
72 %token ICE_INT
73 %token ICE_LONG
74 %token ICE_FLOAT
75 %token ICE_DOUBLE
76 %token ICE_STRING
77 %token ICE_OBJECT
78 %token ICE_LOCAL_OBJECT
79 %token ICE_LOCAL
80 %token ICE_CONST
81 %token ICE_FALSE
82 %token ICE_TRUE
83 %token ICE_IDEMPOTENT
84 %token ICE_OPTIONAL
85 %token ICE_VALUE
86 
87 //
88 // Other tokens.
89 //
90 %token ICE_IDENTIFIER
91 %token ICE_SCOPED_IDENTIFIER
92 %token ICE_STRING_LITERAL
93 %token ICE_INTEGER_LITERAL
94 %token ICE_FLOATING_POINT_LITERAL
95 %token ICE_IDENT_OP
96 %token ICE_KEYWORD_OP
97 %token ICE_OPTIONAL_OP
98 %token ICE_METADATA_OPEN
99 %token ICE_METADATA_CLOSE
100 %token ICE_GLOBAL_METADATA_OPEN
101 %token ICE_GLOBAL_METADATA_CLOSE
102 
103 %token BAD_CHAR
104 
105 %%
106 
107 // ----------------------------------------------------------------------
108 start
109 // ----------------------------------------------------------------------
110 : definitions
111 {
112 }
113 ;
114 
115 // ----------------------------------------------------------------------
116 opt_semicolon
117 // ----------------------------------------------------------------------
118 : ';'
119 {
120 }
121 |
122 {
123 }
124 ;
125 
126 // ----------------------------------------------------------------------
127 global_meta_data
128 // ----------------------------------------------------------------------
129 : ICE_GLOBAL_METADATA_OPEN string_list ICE_GLOBAL_METADATA_CLOSE
130 {
131     $$ = $2;
132 }
133 ;
134 
135 // ----------------------------------------------------------------------
136 meta_data
137 // ----------------------------------------------------------------------
138 : ICE_METADATA_OPEN string_list ICE_METADATA_CLOSE
139 {
140     $$ = $2;
141 }
142 |
143 {
144     $$ = new StringListTok;
145 }
146 ;
147 
148 // ----------------------------------------------------------------------
149 definitions
150 // ----------------------------------------------------------------------
151 : global_meta_data
152 {
153     StringListTokPtr metaData = StringListTokPtr::dynamicCast($1);
154     if(!metaData->v.empty())
155     {
156         unit->addGlobalMetaData(metaData->v);
157     }
158 }
159 definitions
160 | meta_data definition
161 {
162     StringListTokPtr metaData = StringListTokPtr::dynamicCast($1);
163     ContainedPtr contained = ContainedPtr::dynamicCast($2);
164     if(contained && !metaData->v.empty())
165     {
166         contained->setMetaData(metaData->v);
167     }
168 }
169 definitions
170 |
171 {
172 }
173 ;
174 
175 // ----------------------------------------------------------------------
176 definition
177 // ----------------------------------------------------------------------
178 : module_def
179 {
180     assert($1 == 0 || ModulePtr::dynamicCast($1));
181 }
182 opt_semicolon
183 | class_decl
184 {
185     assert($1 == 0 || ClassDeclPtr::dynamicCast($1));
186 }
187 ';'
188 | class_decl
189 {
190     unit->error("`;' missing after class forward declaration");
191 }
192 | class_def
193 {
194     assert($1 == 0 || ClassDefPtr::dynamicCast($1));
195 }
196 opt_semicolon
197 | interface_decl
198 {
199     assert($1 == 0 || ClassDeclPtr::dynamicCast($1));
200 }
201 ';'
202 | interface_decl
203 {
204     unit->error("`;' missing after interface forward declaration");
205 }
206 | interface_def
207 {
208     assert($1 == 0 || ClassDefPtr::dynamicCast($1));
209 }
210 opt_semicolon
211 | exception_decl
212 {
213     assert($1 == 0);
214 }
215 ';'
216 | exception_decl
217 {
218     unit->error("`;' missing after exception forward declaration");
219 }
220 | exception_def
221 {
222     assert($1 == 0 || ExceptionPtr::dynamicCast($1));
223 }
224 opt_semicolon
225 | struct_decl
226 {
227     assert($1 == 0);
228 }
229 ';'
230 | struct_decl
231 {
232     unit->error("`;' missing after struct forward declaration");
233 }
234 | struct_def
235 {
236     assert($1 == 0 || StructPtr::dynamicCast($1));
237 }
238 opt_semicolon
239 | sequence_def
240 {
241     assert($1 == 0 || SequencePtr::dynamicCast($1));
242 }
243 ';'
244 | sequence_def
245 {
246     unit->error("`;' missing after sequence definition");
247 }
248 | dictionary_def
249 {
250     assert($1 == 0 || DictionaryPtr::dynamicCast($1));
251 }
252 ';'
253 | dictionary_def
254 {
255     unit->error("`;' missing after dictionary definition");
256 }
257 | enum_def
258 {
259     assert($1 == 0 || EnumPtr::dynamicCast($1));
260 }
261 opt_semicolon
262 | const_def
263 {
264     assert($1 == 0 || ConstPtr::dynamicCast($1));
265 }
266 ';'
267 | const_def
268 {
269     unit->error("`;' missing after const definition");
270 }
271 | error ';'
272 {
273     yyerrok;
274 }
275 ;
276 
277 // ----------------------------------------------------------------------
278 module_def
279 // ----------------------------------------------------------------------
280 : ICE_MODULE ICE_IDENTIFIER
281 {
282     unit->setSeenDefinition();
283     StringTokPtr ident = StringTokPtr::dynamicCast($2);
284     ContainerPtr cont = unit->currentContainer();
285     ModulePtr module = cont->createModule(ident->v);
286     if(module)
287     {
288         cont->checkIntroduced(ident->v, module);
289         unit->pushContainer(module);
290         $$ = module;
291     }
292     else
293     {
294         $$ = 0;
295     }
296 }
297 '{' definitions '}'
298 {
299     if($3)
300     {
301         unit->popContainer();
302         $$ = $3;
303     }
304     else
305     {
306         $$ = 0;
307     }
308 }
309 ;
310 
311 // ----------------------------------------------------------------------
312 exception_id
313 // ----------------------------------------------------------------------
314 : ICE_EXCEPTION ICE_IDENTIFIER
315 {
316     $$ = $2;
317 }
318 | ICE_EXCEPTION keyword
319 {
320     StringTokPtr ident = StringTokPtr::dynamicCast($2);
321     unit->error("keyword `" + ident->v + "' cannot be used as exception name");
322     $$ = $2; // Dummy
323 }
324 ;
325 
326 // ----------------------------------------------------------------------
327 exception_decl
328 // ----------------------------------------------------------------------
329 : local_qualifier exception_id
330 {
331     unit->error("exceptions cannot be forward declared");
332     $$ = 0;
333 }
334 ;
335 
336 // ----------------------------------------------------------------------
337 exception_def
338 // ----------------------------------------------------------------------
339 : local_qualifier exception_id exception_extends
340 {
341     BoolTokPtr local = BoolTokPtr::dynamicCast($1);
342     StringTokPtr ident = StringTokPtr::dynamicCast($2);
343     ExceptionPtr base = ExceptionPtr::dynamicCast($3);
344     ContainerPtr cont = unit->currentContainer();
345     ExceptionPtr ex = cont->createException(ident->v, base, local->v);
346     if(ex)
347     {
348         cont->checkIntroduced(ident->v, ex);
349         unit->pushContainer(ex);
350     }
351     $$ = ex;
352 }
353 '{' exception_exports '}'
354 {
355     if($4)
356     {
357         unit->popContainer();
358     }
359     $$ = $4;
360 }
361 ;
362 
363 // ----------------------------------------------------------------------
364 exception_extends
365 // ----------------------------------------------------------------------
366 : ICE_EXTENDS scoped_name
367 {
368     StringTokPtr scoped = StringTokPtr::dynamicCast($2);
369     ContainerPtr cont = unit->currentContainer();
370     ContainedPtr contained = cont->lookupException(scoped->v);
371     cont->checkIntroduced(scoped->v);
372     $$ = contained;
373 }
374 |
375 {
376     $$ = 0;
377 }
378 ;
379 
380 // ----------------------------------------------------------------------
381 exception_exports
382 // ----------------------------------------------------------------------
383 : meta_data exception_export ';' exception_exports
384 {
385     StringListTokPtr metaData = StringListTokPtr::dynamicCast($1);
386     ContainedPtr contained = ContainedPtr::dynamicCast($2);
387     if(contained && !metaData->v.empty())
388     {
389         contained->setMetaData(metaData->v);
390     }
391 }
392 | error ';' exception_exports
393 {
394 }
395 | meta_data exception_export
396 {
397     unit->error("`;' missing after definition");
398 }
399 |
400 {
401 }
402 ;
403 
404 // ----------------------------------------------------------------------
405 type_id
406 // ----------------------------------------------------------------------
407 : type ICE_IDENTIFIER
408 {
409     TypePtr type = TypePtr::dynamicCast($1);
410     StringTokPtr ident = StringTokPtr::dynamicCast($2);
411     TypeStringTokPtr typestring = new TypeStringTok;
412     typestring->v = make_pair(type, ident->v);
413     $$ = typestring;
414 }
415 ;
416 
417 // ----------------------------------------------------------------------
418 optional
419 // ----------------------------------------------------------------------
420 : ICE_OPTIONAL_OP ICE_INTEGER_LITERAL ')'
421 {
422     IntegerTokPtr i = IntegerTokPtr::dynamicCast($2);
423 
424     int tag;
425     if(i->v < 0 || i->v > Int32Max)
426     {
427         unit->error("tag for optional is out of range");
428         tag = -1;
429     }
430     else
431     {
432         tag = static_cast<int>(i->v);
433     }
434 
435     OptionalDefTokPtr m = new OptionalDefTok;
436     m->v.optional = tag >= 0;
437     m->v.tag = tag;
438     $$ = m;
439 }
440 | ICE_OPTIONAL_OP scoped_name ')'
441 {
442     StringTokPtr scoped = StringTokPtr::dynamicCast($2);
443 
444     ContainerPtr cont = unit->currentContainer();
445     assert(cont);
446     ContainedList cl = cont->lookupContained(scoped->v, false);
447     if(cl.empty())
448     {
449         EnumeratorList enumerators = cont->enumerators(scoped->v);
450         if(enumerators.size() == 1)
451         {
452             // Found
453             cl.push_back(enumerators.front());
454             scoped->v = enumerators.front()->scoped();
455             unit->warning(Deprecated, string("referencing enumerator `") + scoped->v
456                           + "' without its enumeration's scope is deprecated");
457         }
458         else if(enumerators.size() > 1)
459         {
460             ostringstream os;
461             os << "enumerator `" << scoped->v << "' could designate";
462             bool first = true;
463             for(EnumeratorList::iterator p = enumerators.begin(); p != enumerators.end(); ++p)
464             {
465                 if(first)
466                 {
467                     first = false;
468                 }
469                 else
470                 {
471                     os << " or";
472                 }
473 
474                 os << " `" << (*p)->scoped() << "'";
475             }
476             unit->error(os.str());
477         }
478         else
479         {
480             unit->error(string("`") + scoped->v + "' is not defined");
481         }
482     }
483 
484     if(cl.empty())
485     {
486         YYERROR; // Can't continue, jump to next yyerrok
487     }
488     cont->checkIntroduced(scoped->v);
489 
490     int tag = -1;
491     EnumeratorPtr enumerator = EnumeratorPtr::dynamicCast(cl.front());
492     ConstPtr constant = ConstPtr::dynamicCast(cl.front());
493     if(constant)
494     {
495         BuiltinPtr b = BuiltinPtr::dynamicCast(constant->type());
496         if(b)
497         {
498             switch(b->kind())
499             {
500             case Builtin::KindByte:
501             case Builtin::KindShort:
502             case Builtin::KindInt:
503             case Builtin::KindLong:
504             {
505                 IceUtil::Int64 l = IceUtilInternal::strToInt64(constant->value().c_str(), 0, 0);
506                 if(l < 0 || l > Int32Max)
507                 {
508                     unit->error("tag for optional is out of range");
509                 }
510                 tag = static_cast<int>(l);
511                 break;
512             }
513             default:
514                 break;
515             }
516         }
517     }
518     else if(enumerator)
519     {
520         tag = enumerator->value();
521     }
522 
523     if(tag < 0)
524     {
525         unit->error("invalid tag `" + scoped->v + "' for optional");
526     }
527 
528     OptionalDefTokPtr m = new OptionalDefTok;
529     m->v.optional = tag >= 0;
530     m->v.tag = tag;
531     $$ = m;
532 }
533 | ICE_OPTIONAL_OP ')'
534 {
535     unit->error("missing tag for optional");
536     OptionalDefTokPtr m = new OptionalDefTok; // Dummy
537     m->v.optional = false;
538     m->v.tag = -1;
539     $$ = m;
540 }
541 | ICE_OPTIONAL
542 {
543     unit->error("missing tag for optional");
544     OptionalDefTokPtr m = new OptionalDefTok; // Dummy
545     m->v.optional = false;
546     m->v.tag = -1;
547     $$ = m;
548 }
549 ;
550 
551 // ----------------------------------------------------------------------
552 optional_type_id
553 // ----------------------------------------------------------------------
554 : optional type_id
555 {
556     OptionalDefTokPtr m = OptionalDefTokPtr::dynamicCast($1);
557     TypeStringTokPtr ts = TypeStringTokPtr::dynamicCast($2);
558     m->v.type = ts->v.first;
559     m->v.name = ts->v.second;
560     $$ = m;
561 }
562 | type_id
563 {
564     TypeStringTokPtr ts = TypeStringTokPtr::dynamicCast($1);
565     OptionalDefTokPtr m = new OptionalDefTok;
566     m->v.type = ts->v.first;
567     m->v.name = ts->v.second;
568     m->v.optional = false;
569     m->v.tag = -1;
570     $$ = m;
571 }
572 ;
573 
574 // ----------------------------------------------------------------------
575 exception_export
576 // ----------------------------------------------------------------------
577 : data_member
578 ;
579 
580 // ----------------------------------------------------------------------
581 struct_id
582 // ----------------------------------------------------------------------
583 : ICE_STRUCT ICE_IDENTIFIER
584 {
585     $$ = $2;
586 }
587 | ICE_STRUCT keyword
588 {
589     StringTokPtr ident = StringTokPtr::dynamicCast($2);
590     unit->error("keyword `" + ident->v + "' cannot be used as struct name");
591     $$ = $2; // Dummy
592 }
593 ;
594 
595 // ----------------------------------------------------------------------
596 struct_decl
597 // ----------------------------------------------------------------------
598 : local_qualifier struct_id
599 {
600     unit->error("structs cannot be forward declared");
601     $$ = 0; // Dummy
602 }
603 ;
604 
605 // ----------------------------------------------------------------------
606 struct_def
607 // ----------------------------------------------------------------------
608 : local_qualifier struct_id
609 {
610     BoolTokPtr local = BoolTokPtr::dynamicCast($1);
611     StringTokPtr ident = StringTokPtr::dynamicCast($2);
612     ContainerPtr cont = unit->currentContainer();
613     StructPtr st = cont->createStruct(ident->v, local->v);
614     if(st)
615     {
616         cont->checkIntroduced(ident->v, st);
617         unit->pushContainer(st);
618     }
619     else
620     {
621         st = cont->createStruct(IceUtil::generateUUID(), local->v); // Dummy
622         assert(st);
623         unit->pushContainer(st);
624     }
625     $$ = st;
626 }
627 '{' struct_exports '}'
628 {
629     if($3)
630     {
631         unit->popContainer();
632     }
633     $$ = $3;
634 
635     //
636     // Empty structures are not allowed
637     //
638     StructPtr st = StructPtr::dynamicCast($$);
639     assert(st);
640     if(st->dataMembers().empty())
641     {
642         unit->error("struct `" + st->name() + "' must have at least one member"); // $$ is a dummy
643     }
644 }
645 ;
646 
647 // ----------------------------------------------------------------------
648 struct_exports
649 // ----------------------------------------------------------------------
650 : meta_data struct_export ';' struct_exports
651 {
652     StringListTokPtr metaData = StringListTokPtr::dynamicCast($1);
653     ContainedPtr contained = ContainedPtr::dynamicCast($2);
654     if(contained && !metaData->v.empty())
655     {
656         contained->setMetaData(metaData->v);
657     }
658 }
659 | error ';' struct_exports
660 {
661 }
662 | meta_data struct_export
663 {
664     unit->error("`;' missing after definition");
665 }
666 |
667 {
668 }
669 ;
670 
671 // ----------------------------------------------------------------------
672 struct_export
673 // ----------------------------------------------------------------------
674 : struct_data_member
675 ;
676 
677 // ----------------------------------------------------------------------
678 class_name
679 // ----------------------------------------------------------------------
680 : ICE_CLASS ICE_IDENTIFIER
681 {
682     $$ = $2;
683 }
684 | ICE_CLASS keyword
685 {
686     StringTokPtr ident = StringTokPtr::dynamicCast($2);
687     unit->error("keyword `" + ident->v + "' cannot be used as class name");
688     $$ = $2; // Dummy
689 }
690 ;
691 
692 // ----------------------------------------------------------------------
693 class_id
694 // ----------------------------------------------------------------------
695 : ICE_CLASS ICE_IDENT_OP ICE_INTEGER_LITERAL ')'
696 {
697     IceUtil::Int64 id = IntegerTokPtr::dynamicCast($3)->v;
698     if(id < 0)
699     {
700         unit->error("invalid compact id for class: id must be a positive integer");
701     }
702     else if(id > Int32Max)
703     {
704         unit->error("invalid compact id for class: value is out of range");
705     }
706     else
707     {
708         string typeId = unit->getTypeId(static_cast<int>(id));
709         if(!typeId.empty() && !unit->ignRedefs())
710         {
711             unit->error("invalid compact id for class: already assigned to class `" + typeId + "'");
712         }
713     }
714 
715     ClassIdTokPtr classId = new ClassIdTok();
716     classId->v = StringTokPtr::dynamicCast($2)->v;
717     classId->t = static_cast<int>(id);
718     $$ = classId;
719 }
720 | ICE_CLASS ICE_IDENT_OP scoped_name ')'
721 {
722     StringTokPtr scoped = StringTokPtr::dynamicCast($3);
723 
724     ContainerPtr cont = unit->currentContainer();
725     assert(cont);
726     ContainedList cl = cont->lookupContained(scoped->v, false);
727     if(cl.empty())
728     {
729         EnumeratorList enumerators = cont->enumerators(scoped->v);
730         if(enumerators.size() == 1)
731         {
732             // Found
733             cl.push_back(enumerators.front());
734             scoped->v = enumerators.front()->scoped();
735             unit->warning(Deprecated, string("referencing enumerator `") + scoped->v
736                           + "' without its enumeration's scope is deprecated");
737         }
738         else if(enumerators.size() > 1)
739         {
740             ostringstream os;
741             os << "enumerator `" << scoped->v << "' could designate";
742             bool first = true;
743             for(EnumeratorList::iterator p = enumerators.begin(); p != enumerators.end(); ++p)
744             {
745                 if(first)
746                 {
747                     first = false;
748                 }
749                 else
750                 {
751                     os << " or";
752                 }
753 
754                 os << " `" << (*p)->scoped() << "'";
755             }
756             unit->error(os.str());
757         }
758         else
759         {
760             unit->error(string("`") + scoped->v + "' is not defined");
761         }
762     }
763 
764     if(cl.empty())
765     {
766         YYERROR; // Can't continue, jump to next yyerrok
767     }
768     cont->checkIntroduced(scoped->v);
769 
770     int id = -1;
771     EnumeratorPtr enumerator = EnumeratorPtr::dynamicCast(cl.front());
772     ConstPtr constant = ConstPtr::dynamicCast(cl.front());
773     if(constant)
774     {
775         BuiltinPtr b = BuiltinPtr::dynamicCast(constant->type());
776         if(b)
777         {
778             switch(b->kind())
779             {
780             case Builtin::KindByte:
781             case Builtin::KindShort:
782             case Builtin::KindInt:
783             case Builtin::KindLong:
784             {
785                 IceUtil::Int64 l = IceUtilInternal::strToInt64(constant->value().c_str(), 0, 0);
786                 if(l < 0 || l > Int32Max)
787                 {
788                     unit->error("compact id for class is out of range");
789                 }
790                 id = static_cast<int>(l);
791                 break;
792             }
793             default:
794                 break;
795             }
796         }
797     }
798     else if(enumerator)
799     {
800         id = enumerator->value();
801     }
802 
803     if(id < 0)
804     {
805         unit->error("invalid compact id for class: id must be a positive integer");
806     }
807     else
808     {
809         string typeId = unit->getTypeId(id);
810         if(!typeId.empty() && !unit->ignRedefs())
811         {
812             unit->error("invalid compact id for class: already assigned to class `" + typeId + "'");
813         }
814     }
815 
816     ClassIdTokPtr classId = new ClassIdTok();
817     classId->v = StringTokPtr::dynamicCast($2)->v;
818     classId->t = id;
819     $$ = classId;
820 
821 }
822 | class_name
823 {
824     ClassIdTokPtr classId = new ClassIdTok();
825     classId->v = StringTokPtr::dynamicCast($1)->v;
826     classId->t = -1;
827     $$ = classId;
828 }
829 ;
830 
831 // ----------------------------------------------------------------------
832 class_decl
833 // ----------------------------------------------------------------------
834 : local_qualifier class_name
835 {
836     BoolTokPtr local = BoolTokPtr::dynamicCast($1);
837     StringTokPtr ident = StringTokPtr::dynamicCast($2);
838     ContainerPtr cont = unit->currentContainer();
839     ClassDeclPtr cl = cont->createClassDecl(ident->v, false, local->v);
840     $$ = cl;
841 }
842 ;
843 
844 // ----------------------------------------------------------------------
845 class_def
846 // ----------------------------------------------------------------------
847 : local_qualifier class_id class_extends implements
848 {
849     BoolTokPtr local = BoolTokPtr::dynamicCast($1);
850     ClassIdTokPtr ident = ClassIdTokPtr::dynamicCast($2);
851     ContainerPtr cont = unit->currentContainer();
852     ClassDefPtr base = ClassDefPtr::dynamicCast($3);
853     ClassListTokPtr bases = ClassListTokPtr::dynamicCast($4);
854     if(base)
855     {
856     bases->v.push_front(base);
857     }
858     ClassDefPtr cl = cont->createClassDef(ident->v, ident->t, false, bases->v, local->v);
859     if(cl)
860     {
861         cont->checkIntroduced(ident->v, cl);
862         unit->pushContainer(cl);
863         $$ = cl;
864     }
865     else
866     {
867         $$ = 0;
868     }
869 }
870 '{' class_exports '}'
871 {
872     if($5)
873     {
874         unit->popContainer();
875         $$ = $5;
876     }
877     else
878     {
879         $$ = 0;
880     }
881 }
882 ;
883 
884 // ----------------------------------------------------------------------
885 class_extends
886 // ----------------------------------------------------------------------
887 : ICE_EXTENDS scoped_name
888 {
889     StringTokPtr scoped = StringTokPtr::dynamicCast($2);
890     ContainerPtr cont = unit->currentContainer();
891     TypeList types = cont->lookupType(scoped->v);
892     $$ = 0;
893     if(!types.empty())
894     {
895         ClassDeclPtr cl = ClassDeclPtr::dynamicCast(types.front());
896         if(!cl || cl->isInterface())
897         {
898             string msg = "`";
899             msg += scoped->v;
900             msg += "' is not a class";
901             unit->error(msg);
902         }
903         else
904         {
905             ClassDefPtr def = cl->definition();
906             if(!def)
907             {
908                 string msg = "`";
909                 msg += scoped->v;
910                 msg += "' has been declared but not defined";
911                 unit->error(msg);
912             }
913             else
914             {
915                 cont->checkIntroduced(scoped->v);
916                 $$ = def;
917             }
918         }
919     }
920 }
921 |
922 {
923     $$ = 0;
924 }
925 ;
926 
927 // ----------------------------------------------------------------------
928 implements
929 // ----------------------------------------------------------------------
930 : ICE_IMPLEMENTS interface_list
931 {
932     $$ = $2;
933 }
934 |
935 {
936     $$ = new ClassListTok;
937 }
938 ;
939 
940 // ----------------------------------------------------------------------
941 class_exports
942 // ----------------------------------------------------------------------
943 : meta_data class_export ';' class_exports
944 {
945     StringListTokPtr metaData = StringListTokPtr::dynamicCast($1);
946     ContainedPtr contained = ContainedPtr::dynamicCast($2);
947     if(contained && !metaData->v.empty())
948     {
949         contained->setMetaData(metaData->v);
950     }
951 }
952 | error ';' class_exports
953 {
954 }
955 | meta_data class_export
956 {
957     unit->error("`;' missing after definition");
958 }
959 |
960 {
961 }
962 ;
963 
964 // ----------------------------------------------------------------------
965 data_member
966 // ----------------------------------------------------------------------
967 : optional_type_id
968 {
969     OptionalDefTokPtr def = OptionalDefTokPtr::dynamicCast($1);
970     ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer());
971     DataMemberPtr dm;
972     if(cl)
973     {
974         dm = cl->createDataMember(def->v.name, def->v.type, def->v.optional, def->v.tag, 0, "", "");
975     }
976     StructPtr st = StructPtr::dynamicCast(unit->currentContainer());
977     if(st)
978     {
979         dm = st->createDataMember(def->v.name, def->v.type, def->v.optional, def->v.tag, 0, "", "");
980     }
981     ExceptionPtr ex = ExceptionPtr::dynamicCast(unit->currentContainer());
982     if(ex)
983     {
984         dm = ex->createDataMember(def->v.name, def->v.type, def->v.optional, def->v.tag, 0, "", "");
985     }
986     unit->currentContainer()->checkIntroduced(def->v.name, dm);
987     $$ = dm;
988 }
989 | optional_type_id '=' const_initializer
990 {
991     OptionalDefTokPtr def = OptionalDefTokPtr::dynamicCast($1);
992     ConstDefTokPtr value = ConstDefTokPtr::dynamicCast($3);
993 
994     ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer());
995     DataMemberPtr dm;
996     if(cl)
997     {
998         dm = cl->createDataMember(def->v.name, def->v.type, def->v.optional, def->v.tag, value->v.value,
999                                   value->v.valueAsString, value->v.valueAsLiteral);
1000     }
1001     StructPtr st = StructPtr::dynamicCast(unit->currentContainer());
1002     if(st)
1003     {
1004         dm = st->createDataMember(def->v.name, def->v.type, def->v.optional, def->v.tag, value->v.value,
1005                                   value->v.valueAsString, value->v.valueAsLiteral);
1006     }
1007     ExceptionPtr ex = ExceptionPtr::dynamicCast(unit->currentContainer());
1008     if(ex)
1009     {
1010         dm = ex->createDataMember(def->v.name, def->v.type, def->v.optional, def->v.tag, value->v.value,
1011                                   value->v.valueAsString, value->v.valueAsLiteral);
1012     }
1013     unit->currentContainer()->checkIntroduced(def->v.name, dm);
1014     $$ = dm;
1015 }
1016 | type keyword
1017 {
1018     TypePtr type = TypePtr::dynamicCast($1);
1019     string name = StringTokPtr::dynamicCast($2)->v;
1020     ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer());
1021     if(cl)
1022     {
1023         $$ = cl->createDataMember(name, type, false, 0, 0, "", ""); // Dummy
1024     }
1025     StructPtr st = StructPtr::dynamicCast(unit->currentContainer());
1026     if(st)
1027     {
1028         $$ = st->createDataMember(name, type, false, 0, 0, "", ""); // Dummy
1029     }
1030     ExceptionPtr ex = ExceptionPtr::dynamicCast(unit->currentContainer());
1031     if(ex)
1032     {
1033         $$ = ex->createDataMember(name, type, false, 0, 0, "", ""); // Dummy
1034     }
1035     assert($$);
1036     unit->error("keyword `" + name + "' cannot be used as data member name");
1037 }
1038 | type
1039 {
1040     TypePtr type = TypePtr::dynamicCast($1);
1041     ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer());
1042     if(cl)
1043     {
1044         $$ = cl->createDataMember(IceUtil::generateUUID(), type, false, 0, 0, "", ""); // Dummy
1045     }
1046     StructPtr st = StructPtr::dynamicCast(unit->currentContainer());
1047     if(st)
1048     {
1049         $$ = st->createDataMember(IceUtil::generateUUID(), type, false, 0, 0, "", ""); // Dummy
1050     }
1051     ExceptionPtr ex = ExceptionPtr::dynamicCast(unit->currentContainer());
1052     if(ex)
1053     {
1054         $$ = ex->createDataMember(IceUtil::generateUUID(), type, false, 0, 0, "", ""); // Dummy
1055     }
1056     assert($$);
1057     unit->error("missing data member name");
1058 }
1059 ;
1060 
1061 // ----------------------------------------------------------------------
1062 struct_data_member
1063 // ----------------------------------------------------------------------
1064 : type_id
1065 {
1066     TypeStringTokPtr ts = TypeStringTokPtr::dynamicCast($1);
1067     StructPtr st = StructPtr::dynamicCast(unit->currentContainer());
1068     assert(st);
1069     DataMemberPtr dm = st->createDataMember(ts->v.second, ts->v.first, false, -1, 0, "", "");
1070     unit->currentContainer()->checkIntroduced(ts->v.second, dm);
1071     $$ = dm;
1072 }
1073 | type_id '=' const_initializer
1074 {
1075     TypeStringTokPtr ts = TypeStringTokPtr::dynamicCast($1);
1076     ConstDefTokPtr value = ConstDefTokPtr::dynamicCast($3);
1077     StructPtr st = StructPtr::dynamicCast(unit->currentContainer());
1078     assert(st);
1079     DataMemberPtr dm = st->createDataMember(ts->v.second, ts->v.first, false, -1, value->v.value,
1080                                             value->v.valueAsString, value->v.valueAsLiteral);
1081     unit->currentContainer()->checkIntroduced(ts->v.second, dm);
1082     $$ = dm;
1083 }
1084 | optional type_id
1085 {
1086     TypeStringTokPtr ts = TypeStringTokPtr::dynamicCast($2);
1087     StructPtr st = StructPtr::dynamicCast(unit->currentContainer());
1088     assert(st);
1089     $$ = st->createDataMember(ts->v.second, ts->v.first, false, 0, 0, "", ""); // Dummy
1090     assert($$);
1091     unit->error("optional data members not supported in struct");
1092 }
1093 | optional type_id '=' const_initializer
1094 {
1095     TypeStringTokPtr ts = TypeStringTokPtr::dynamicCast($2);
1096     StructPtr st = StructPtr::dynamicCast(unit->currentContainer());
1097     assert(st);
1098     $$ = st->createDataMember(ts->v.second, ts->v.first, false, 0, 0, "", ""); // Dummy
1099     assert($$);
1100     unit->error("optional data members not supported in struct");
1101 }
1102 | type keyword
1103 {
1104     TypePtr type = TypePtr::dynamicCast($1);
1105     string name = StringTokPtr::dynamicCast($2)->v;
1106     StructPtr st = StructPtr::dynamicCast(unit->currentContainer());
1107     assert(st);
1108     $$ = st->createDataMember(name, type, false, 0, 0, "", ""); // Dummy
1109     assert($$);
1110     unit->error("keyword `" + name + "' cannot be used as data member name");
1111 }
1112 | type
1113 {
1114     TypePtr type = TypePtr::dynamicCast($1);
1115     StructPtr st = StructPtr::dynamicCast(unit->currentContainer());
1116     assert(st);
1117     $$ = st->createDataMember(IceUtil::generateUUID(), type, false, 0, 0, "", ""); // Dummy
1118     assert($$);
1119     unit->error("missing data member name");
1120 }
1121 ;
1122 
1123 // ----------------------------------------------------------------------
1124 return_type
1125 // ----------------------------------------------------------------------
1126 : optional type
1127 {
1128     OptionalDefTokPtr m = OptionalDefTokPtr::dynamicCast($1);
1129     m->v.type = TypePtr::dynamicCast($2);
1130     $$ = m;
1131 }
1132 | type
1133 {
1134     OptionalDefTokPtr m = new OptionalDefTok();
1135     m->v.type = TypePtr::dynamicCast($1);
1136     m->v.optional = false;
1137     m->v.tag = -1;
1138     $$ = m;
1139 }
1140 | ICE_VOID
1141 {
1142     OptionalDefTokPtr m = new OptionalDefTok;
1143     m->v.optional = false;
1144     m->v.tag = -1;
1145     $$ = m;
1146 }
1147 ;
1148 
1149 // ----------------------------------------------------------------------
1150 operation_preamble
1151 // ----------------------------------------------------------------------
1152 : return_type ICE_IDENT_OP
1153 {
1154     OptionalDefTokPtr returnType = OptionalDefTokPtr::dynamicCast($1);
1155     string name = StringTokPtr::dynamicCast($2)->v;
1156     ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer());
1157     if(cl)
1158     {
1159         OperationPtr op = cl->createOperation(name, returnType->v.type, returnType->v.optional, returnType->v.tag);
1160         if(op)
1161         {
1162             cl->checkIntroduced(name, op);
1163             unit->pushContainer(op);
1164             $$ = op;
1165         }
1166         else
1167         {
1168             $$ = 0;
1169         }
1170     }
1171     else
1172     {
1173         $$ = 0;
1174     }
1175 }
1176 | ICE_IDEMPOTENT return_type ICE_IDENT_OP
1177 {
1178     OptionalDefTokPtr returnType = OptionalDefTokPtr::dynamicCast($2);
1179     string name = StringTokPtr::dynamicCast($3)->v;
1180     ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer());
1181     if(cl)
1182     {
1183         OperationPtr op = cl->createOperation(name, returnType->v.type, returnType->v.optional, returnType->v.tag,
1184                                                 Operation::Idempotent);
1185         if(op)
1186         {
1187             cl->checkIntroduced(name, op);
1188             unit->pushContainer(op);
1189             $$ = op;
1190         }
1191         else
1192         {
1193             $$ = 0;
1194         }
1195     }
1196     else
1197     {
1198         $$ = 0;
1199     }
1200 }
1201 | return_type ICE_KEYWORD_OP
1202 {
1203     OptionalDefTokPtr returnType = OptionalDefTokPtr::dynamicCast($1);
1204     string name = StringTokPtr::dynamicCast($2)->v;
1205     ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer());
1206     if(cl)
1207     {
1208         OperationPtr op = cl->createOperation(name, returnType->v.type, returnType->v.optional, returnType->v.tag);
1209         if(op)
1210         {
1211             unit->pushContainer(op);
1212             unit->error("keyword `" + name + "' cannot be used as operation name");
1213             $$ = op; // Dummy
1214         }
1215         else
1216         {
1217             $$ = 0;
1218         }
1219     }
1220     else
1221     {
1222         $$ = 0;
1223     }
1224 }
1225 | ICE_IDEMPOTENT return_type ICE_KEYWORD_OP
1226 {
1227     OptionalDefTokPtr returnType = OptionalDefTokPtr::dynamicCast($2);
1228     string name = StringTokPtr::dynamicCast($3)->v;
1229     ClassDefPtr cl = ClassDefPtr::dynamicCast(unit->currentContainer());
1230     if(cl)
1231     {
1232         OperationPtr op = cl->createOperation(name, returnType->v.type, returnType->v.optional, returnType->v.tag,
1233                                                 Operation::Idempotent);
1234         if(op)
1235         {
1236             unit->pushContainer(op);
1237             unit->error("keyword `" + name + "' cannot be used as operation name");
1238             $$ = op; // Dummy
1239         }
1240         else
1241         {
1242             return 0;
1243         }
1244     }
1245     else
1246     {
1247         $$ = 0;
1248     }
1249 }
1250 ;
1251 
1252 // ----------------------------------------------------------------------
1253 operation
1254 // ----------------------------------------------------------------------
1255 : operation_preamble parameters ')'
1256 {
1257     if($1)
1258     {
1259         unit->popContainer();
1260         $$ = $1;
1261     }
1262     else
1263     {
1264         $$ = 0;
1265     }
1266 }
1267 throws
1268 {
1269     OperationPtr op = OperationPtr::dynamicCast($4);
1270     ExceptionListTokPtr el = ExceptionListTokPtr::dynamicCast($5);
1271     assert(el);
1272     if(op)
1273     {
1274         op->setExceptionList(el->v);
1275     }
1276 }
1277 | operation_preamble error ')'
1278 {
1279     if($1)
1280     {
1281         unit->popContainer();
1282     }
1283     yyerrok;
1284 }
1285 throws
1286 {
1287     OperationPtr op = OperationPtr::dynamicCast($4);
1288     ExceptionListTokPtr el = ExceptionListTokPtr::dynamicCast($5);
1289     assert(el);
1290     if(op)
1291     {
1292         op->setExceptionList(el->v); // Dummy
1293     }
1294 }
1295 ;
1296 
1297 // ----------------------------------------------------------------------
1298 class_export
1299 // ----------------------------------------------------------------------
1300 : data_member
1301 | operation
1302 ;
1303 
1304 // ----------------------------------------------------------------------
1305 interface_id
1306 // ----------------------------------------------------------------------
1307 : ICE_INTERFACE ICE_IDENTIFIER
1308 {
1309     $$ = $2;
1310 }
1311 | ICE_INTERFACE keyword
1312 {
1313     StringTokPtr ident = StringTokPtr::dynamicCast($2);
1314     unit->error("keyword `" + ident->v + "' cannot be used as interface name");
1315     $$ = $2; // Dummy
1316 }
1317 ;
1318 
1319 // ----------------------------------------------------------------------
1320 interface_decl
1321 // ----------------------------------------------------------------------
1322 : local_qualifier interface_id
1323 {
1324     BoolTokPtr local = BoolTokPtr::dynamicCast($1);
1325     StringTokPtr ident = StringTokPtr::dynamicCast($2);
1326     ContainerPtr cont = unit->currentContainer();
1327     ClassDeclPtr cl = cont->createClassDecl(ident->v, true, local->v);
1328     cont->checkIntroduced(ident->v, cl);
1329     $$ = cl;
1330 }
1331 ;
1332 
1333 // ----------------------------------------------------------------------
1334 interface_def
1335 // ----------------------------------------------------------------------
1336 : local_qualifier interface_id interface_extends
1337 {
1338     BoolTokPtr local = BoolTokPtr::dynamicCast($1);
1339     StringTokPtr ident = StringTokPtr::dynamicCast($2);
1340     ContainerPtr cont = unit->currentContainer();
1341     ClassListTokPtr bases = ClassListTokPtr::dynamicCast($3);
1342     ClassDefPtr cl = cont->createClassDef(ident->v, -1, true, bases->v, local->v);
1343     if(cl)
1344     {
1345     cont->checkIntroduced(ident->v, cl);
1346     unit->pushContainer(cl);
1347     $$ = cl;
1348     }
1349     else
1350     {
1351         $$ = 0;
1352     }
1353 }
1354 '{' interface_exports '}'
1355 {
1356     if($4)
1357     {
1358     unit->popContainer();
1359     $$ = $4;
1360     }
1361     else
1362     {
1363     $$ = 0;
1364     }
1365 }
1366 ;
1367 
1368 // ----------------------------------------------------------------------
1369 interface_list
1370 // ----------------------------------------------------------------------
1371 : scoped_name ',' interface_list
1372 {
1373     ClassListTokPtr intfs = ClassListTokPtr::dynamicCast($3);
1374     StringTokPtr scoped = StringTokPtr::dynamicCast($1);
1375     ContainerPtr cont = unit->currentContainer();
1376     TypeList types = cont->lookupType(scoped->v);
1377     if(!types.empty())
1378     {
1379     ClassDeclPtr cl = ClassDeclPtr::dynamicCast(types.front());
1380     if(!cl || !cl->isInterface())
1381     {
1382         string msg = "`";
1383         msg += scoped->v;
1384         msg += "' is not an interface";
1385         unit->error(msg);
1386     }
1387     else
1388     {
1389         ClassDefPtr def = cl->definition();
1390         if(!def)
1391         {
1392         string msg = "`";
1393         msg += scoped->v;
1394         msg += "' has been declared but not defined";
1395         unit->error(msg);
1396         }
1397         else
1398         {
1399             cont->checkIntroduced(scoped->v);
1400         intfs->v.push_front(def);
1401         }
1402     }
1403     }
1404     $$ = intfs;
1405 }
1406 | scoped_name
1407 {
1408     ClassListTokPtr intfs = new ClassListTok;
1409     StringTokPtr scoped = StringTokPtr::dynamicCast($1);
1410     ContainerPtr cont = unit->currentContainer();
1411     TypeList types = cont->lookupType(scoped->v);
1412     if(!types.empty())
1413     {
1414     ClassDeclPtr cl = ClassDeclPtr::dynamicCast(types.front());
1415     if(!cl || !cl->isInterface())
1416     {
1417         string msg = "`";
1418         msg += scoped->v;
1419         msg += "' is not an interface";
1420         unit->error(msg); // $$ is a dummy
1421     }
1422     else
1423     {
1424         ClassDefPtr def = cl->definition();
1425         if(!def)
1426         {
1427         string msg = "`";
1428         msg += scoped->v;
1429         msg += "' has been declared but not defined";
1430         unit->error(msg); // $$ is a dummy
1431         }
1432         else
1433         {
1434             cont->checkIntroduced(scoped->v);
1435         intfs->v.push_front(def);
1436         }
1437     }
1438     }
1439     $$ = intfs;
1440 }
1441 | ICE_OBJECT
1442 {
1443     unit->error("illegal inheritance from type Object");
1444     $$ = new ClassListTok; // Dummy
1445 }
1446 | ICE_VALUE
1447 {
1448     unit->error("illegal inheritance from type Value");
1449     $$ = new ClassListTok; // Dummy
1450 }
1451 ;
1452 
1453 // ----------------------------------------------------------------------
1454 interface_extends
1455 // ----------------------------------------------------------------------
1456 : ICE_EXTENDS interface_list
1457 {
1458     $$ = $2;
1459 }
1460 |
1461 {
1462     $$ = new ClassListTok;
1463 }
1464 ;
1465 
1466 // ----------------------------------------------------------------------
1467 interface_exports
1468 // ----------------------------------------------------------------------
1469 : meta_data interface_export ';' interface_exports
1470 {
1471     StringListTokPtr metaData = StringListTokPtr::dynamicCast($1);
1472     ContainedPtr contained = ContainedPtr::dynamicCast($2);
1473     if(contained && !metaData->v.empty())
1474     {
1475     contained->setMetaData(metaData->v);
1476     }
1477 }
1478 | error ';' interface_exports
1479 {
1480 }
1481 | meta_data interface_export
1482 {
1483     unit->error("`;' missing after definition");
1484 }
1485 |
1486 {
1487 }
1488 ;
1489 
1490 // ----------------------------------------------------------------------
1491 interface_export
1492 // ----------------------------------------------------------------------
1493 : operation
1494 ;
1495 
1496 // ----------------------------------------------------------------------
1497 exception_list
1498 // ----------------------------------------------------------------------
1499 : exception ',' exception_list
1500 {
1501     ExceptionPtr exception = ExceptionPtr::dynamicCast($1);
1502     ExceptionListTokPtr exceptionList = ExceptionListTokPtr::dynamicCast($3);
1503     exceptionList->v.push_front(exception);
1504     $$ = exceptionList;
1505 }
1506 | exception
1507 {
1508     ExceptionPtr exception = ExceptionPtr::dynamicCast($1);
1509     ExceptionListTokPtr exceptionList = new ExceptionListTok;
1510     exceptionList->v.push_front(exception);
1511     $$ = exceptionList;
1512 }
1513 ;
1514 
1515 // ----------------------------------------------------------------------
1516 exception
1517 // ----------------------------------------------------------------------
1518 : scoped_name
1519 {
1520     StringTokPtr scoped = StringTokPtr::dynamicCast($1);
1521     ContainerPtr cont = unit->currentContainer();
1522     ExceptionPtr exception = cont->lookupException(scoped->v);
1523     if(!exception)
1524     {
1525     exception = cont->createException(IceUtil::generateUUID(), 0, false, Dummy); // Dummy
1526     }
1527     cont->checkIntroduced(scoped->v, exception);
1528     $$ = exception;
1529 }
1530 | keyword
1531 {
1532     StringTokPtr ident = StringTokPtr::dynamicCast($1);
1533     unit->error("keyword `" + ident->v + "' cannot be used as exception name");
1534     $$ = unit->currentContainer()->createException(IceUtil::generateUUID(), 0, false, Dummy); // Dummy
1535 }
1536 ;
1537 
1538 // ----------------------------------------------------------------------
1539 sequence_def
1540 // ----------------------------------------------------------------------
1541 : local_qualifier ICE_SEQUENCE '<' meta_data type '>' ICE_IDENTIFIER
1542 {
1543     BoolTokPtr local = BoolTokPtr::dynamicCast($1);
1544     StringTokPtr ident = StringTokPtr::dynamicCast($7);
1545     StringListTokPtr metaData = StringListTokPtr::dynamicCast($4);
1546     TypePtr type = TypePtr::dynamicCast($5);
1547     ContainerPtr cont = unit->currentContainer();
1548     $$ = cont->createSequence(ident->v, type, metaData->v, local->v);
1549 }
1550 | local_qualifier ICE_SEQUENCE '<' meta_data type '>' keyword
1551 {
1552     BoolTokPtr local = BoolTokPtr::dynamicCast($1);
1553     StringTokPtr ident = StringTokPtr::dynamicCast($7);
1554     StringListTokPtr metaData = StringListTokPtr::dynamicCast($4);
1555     TypePtr type = TypePtr::dynamicCast($5);
1556     ContainerPtr cont = unit->currentContainer();
1557     $$ = cont->createSequence(ident->v, type, metaData->v, local->v); // Dummy
1558     unit->error("keyword `" + ident->v + "' cannot be used as sequence name");
1559 }
1560 ;
1561 
1562 // ----------------------------------------------------------------------
1563 dictionary_def
1564 // ----------------------------------------------------------------------
1565 : local_qualifier ICE_DICTIONARY '<' meta_data type ',' meta_data type '>' ICE_IDENTIFIER
1566 {
1567     BoolTokPtr local = BoolTokPtr::dynamicCast($1);
1568     StringTokPtr ident = StringTokPtr::dynamicCast($10);
1569     StringListTokPtr keyMetaData = StringListTokPtr::dynamicCast($4);
1570     TypePtr keyType = TypePtr::dynamicCast($5);
1571     StringListTokPtr valueMetaData = StringListTokPtr::dynamicCast($7);
1572     TypePtr valueType = TypePtr::dynamicCast($8);
1573     ContainerPtr cont = unit->currentContainer();
1574     $$ = cont->createDictionary(ident->v, keyType, keyMetaData->v, valueType, valueMetaData->v, local->v);
1575 }
1576 | local_qualifier ICE_DICTIONARY '<' meta_data type ',' meta_data type '>' keyword
1577 {
1578     BoolTokPtr local = BoolTokPtr::dynamicCast($1);
1579     StringTokPtr ident = StringTokPtr::dynamicCast($10);
1580     StringListTokPtr keyMetaData = StringListTokPtr::dynamicCast($4);
1581     TypePtr keyType = TypePtr::dynamicCast($5);
1582     StringListTokPtr valueMetaData = StringListTokPtr::dynamicCast($7);
1583     TypePtr valueType = TypePtr::dynamicCast($8);
1584     ContainerPtr cont = unit->currentContainer();
1585     $$ = cont->createDictionary(ident->v, keyType, keyMetaData->v, valueType, valueMetaData->v, local->v); // Dummy
1586     unit->error("keyword `" + ident->v + "' cannot be used as dictionary name");
1587 }
1588 ;
1589 
1590 // ----------------------------------------------------------------------
1591 enum_id
1592 // ----------------------------------------------------------------------
1593 : ICE_ENUM ICE_IDENTIFIER
1594 {
1595     $$ = $2;
1596 }
1597 | ICE_ENUM keyword
1598 {
1599     StringTokPtr ident = StringTokPtr::dynamicCast($2);
1600     unit->error("keyword `" + ident->v + "' cannot be used as enumeration name");
1601     $$ = $2; // Dummy
1602 }
1603 ;
1604 
1605 // ----------------------------------------------------------------------
1606 enum_def
1607 // ----------------------------------------------------------------------
1608 : local_qualifier enum_id
1609 {
1610     BoolTokPtr local = BoolTokPtr::dynamicCast($1);
1611     StringTokPtr ident = StringTokPtr::dynamicCast($2);
1612     ContainerPtr cont = unit->currentContainer();
1613     EnumPtr en = cont->createEnum(ident->v, local->v);
1614     if(en)
1615     {
1616         cont->checkIntroduced(ident->v, en);
1617     }
1618     else
1619     {
1620         en = cont->createEnum(IceUtil::generateUUID(), local->v, Dummy);
1621     }
1622     unit->pushContainer(en);
1623     $$ = en;
1624 }
1625 '{' enumerator_list '}'
1626 {
1627     EnumPtr en = EnumPtr::dynamicCast($3);
1628     if(en)
1629     {
1630         EnumeratorListTokPtr enumerators = EnumeratorListTokPtr::dynamicCast($5);
1631         if(enumerators->v.empty())
1632         {
1633             unit->error("enum `" + en->name() + "' must have at least one enumerator");
1634         }
1635         unit->popContainer();
1636     }
1637     $$ = $3;
1638 }
1639 |
1640 local_qualifier ICE_ENUM
1641 {
1642     unit->error("missing enumeration name");
1643     BoolTokPtr local = BoolTokPtr::dynamicCast($1);
1644     ContainerPtr cont = unit->currentContainer();
1645     EnumPtr en = cont->createEnum(IceUtil::generateUUID(), local->v, Dummy);
1646     unit->pushContainer(en);
1647     $$ = en;
1648 }
1649 '{' enumerator_list '}'
1650 {
1651     unit->popContainer();
1652     $$ = $2;
1653 }
1654 ;
1655 
1656 // ----------------------------------------------------------------------
1657 enumerator_list
1658 // ----------------------------------------------------------------------
1659 : enumerator ',' enumerator_list
1660 {
1661     EnumeratorListTokPtr ens = EnumeratorListTokPtr::dynamicCast($1);
1662     ens->v.splice(ens->v.end(), EnumeratorListTokPtr::dynamicCast($3)->v);
1663     $$ = ens;
1664 }
1665 | enumerator
1666 {
1667 }
1668 ;
1669 
1670 // ----------------------------------------------------------------------
1671 enumerator
1672 // ----------------------------------------------------------------------
1673 : ICE_IDENTIFIER
1674 {
1675     StringTokPtr ident = StringTokPtr::dynamicCast($1);
1676     EnumeratorListTokPtr ens = new EnumeratorListTok;
1677     ContainerPtr cont = unit->currentContainer();
1678     EnumeratorPtr en = cont->createEnumerator(ident->v);
1679     if(en)
1680     {
1681         ens->v.push_front(en);
1682     }
1683     $$ = ens;
1684 }
1685 | ICE_IDENTIFIER '=' enumerator_initializer
1686 {
1687     StringTokPtr ident = StringTokPtr::dynamicCast($1);
1688     EnumeratorListTokPtr ens = new EnumeratorListTok;
1689     ContainerPtr cont = unit->currentContainer();
1690     IntegerTokPtr intVal = IntegerTokPtr::dynamicCast($3);
1691     if(intVal)
1692     {
1693         if(intVal->v < 0 || intVal->v > Int32Max)
1694         {
1695             unit->error("value for enumerator `" + ident->v + "' is out of range");
1696         }
1697         else
1698         {
1699             EnumeratorPtr en = cont->createEnumerator(ident->v, static_cast<int>(intVal->v));
1700             ens->v.push_front(en);
1701         }
1702     }
1703     $$ = ens;
1704 }
1705 | keyword
1706 {
1707     StringTokPtr ident = StringTokPtr::dynamicCast($1);
1708     unit->error("keyword `" + ident->v + "' cannot be used as enumerator");
1709     EnumeratorListTokPtr ens = new EnumeratorListTok; // Dummy
1710     $$ = ens;
1711 }
1712 |
1713 {
1714     EnumeratorListTokPtr ens = new EnumeratorListTok;
1715     $$ = ens; // Dummy
1716 }
1717 ;
1718 
1719 // ----------------------------------------------------------------------
1720 enumerator_initializer
1721 // ----------------------------------------------------------------------
1722 : ICE_INTEGER_LITERAL
1723 {
1724     $$ = $1;
1725 }
1726 | scoped_name
1727 {
1728     StringTokPtr scoped = StringTokPtr::dynamicCast($1);
1729     ContainedList cl = unit->currentContainer()->lookupContained(scoped->v);
1730     IntegerTokPtr tok;
1731     if(!cl.empty())
1732     {
1733         ConstPtr constant = ConstPtr::dynamicCast(cl.front());
1734         if(constant)
1735         {
1736             unit->currentContainer()->checkIntroduced(scoped->v, constant);
1737             BuiltinPtr b = BuiltinPtr::dynamicCast(constant->type());
1738             if(b && (b->kind() == Builtin::KindByte || b->kind() == Builtin::KindShort ||
1739                      b->kind() == Builtin::KindInt || b->kind() == Builtin::KindLong))
1740             {
1741                 IceUtil::Int64 v;
1742                 if(IceUtilInternal::stringToInt64(constant->value(), v))
1743                 {
1744                     tok = new IntegerTok;
1745                     tok->v = v;
1746                     tok->literal = constant->value();
1747                 }
1748             }
1749         }
1750     }
1751 
1752     if(!tok)
1753     {
1754         string msg = "illegal initializer: `" + scoped->v + "' is not an integer constant";
1755         unit->error(msg); // $$ is dummy
1756     }
1757 
1758     $$ = tok;
1759 }
1760 ;
1761 
1762 // ----------------------------------------------------------------------
1763 out_qualifier
1764 // ----------------------------------------------------------------------
1765 : ICE_OUT
1766 {
1767     BoolTokPtr out = new BoolTok;
1768     out->v = true;
1769     $$ = out;
1770 }
1771 |
1772 {
1773     BoolTokPtr out = new BoolTok;
1774     out->v = false;
1775     $$ = out;
1776 }
1777 ;
1778 
1779 // ----------------------------------------------------------------------
1780 parameters
1781 // ----------------------------------------------------------------------
1782 : // empty
1783 {
1784 }
1785 | out_qualifier meta_data optional_type_id
1786 {
1787     BoolTokPtr isOutParam = BoolTokPtr::dynamicCast($1);
1788     OptionalDefTokPtr tsp = OptionalDefTokPtr::dynamicCast($3);
1789     OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer());
1790     if(op)
1791     {
1792         ParamDeclPtr pd = op->createParamDecl(tsp->v.name, tsp->v.type, isOutParam->v, tsp->v.optional, tsp->v.tag);
1793         unit->currentContainer()->checkIntroduced(tsp->v.name, pd);
1794         StringListTokPtr metaData = StringListTokPtr::dynamicCast($2);
1795         if(!metaData->v.empty())
1796         {
1797             pd->setMetaData(metaData->v);
1798         }
1799     }
1800 }
1801 | parameters ',' out_qualifier meta_data optional_type_id
1802 {
1803     BoolTokPtr isOutParam = BoolTokPtr::dynamicCast($3);
1804     OptionalDefTokPtr tsp = OptionalDefTokPtr::dynamicCast($5);
1805     OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer());
1806     if(op)
1807     {
1808         ParamDeclPtr pd = op->createParamDecl(tsp->v.name, tsp->v.type, isOutParam->v, tsp->v.optional, tsp->v.tag);
1809         unit->currentContainer()->checkIntroduced(tsp->v.name, pd);
1810         StringListTokPtr metaData = StringListTokPtr::dynamicCast($4);
1811         if(!metaData->v.empty())
1812         {
1813             pd->setMetaData(metaData->v);
1814         }
1815     }
1816 }
1817 | out_qualifier meta_data type keyword
1818 {
1819     BoolTokPtr isOutParam = BoolTokPtr::dynamicCast($1);
1820     TypePtr type = TypePtr::dynamicCast($3);
1821     StringTokPtr ident = StringTokPtr::dynamicCast($4);
1822     OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer());
1823     if(op)
1824     {
1825         op->createParamDecl(ident->v, type, isOutParam->v, false, 0); // Dummy
1826         unit->error("keyword `" + ident->v + "' cannot be used as parameter name");
1827     }
1828 }
1829 | parameters ',' out_qualifier meta_data type keyword
1830 {
1831     BoolTokPtr isOutParam = BoolTokPtr::dynamicCast($3);
1832     TypePtr type = TypePtr::dynamicCast($5);
1833     StringTokPtr ident = StringTokPtr::dynamicCast($6);
1834     OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer());
1835     if(op)
1836     {
1837         op->createParamDecl(ident->v, type, isOutParam->v, false, 0); // Dummy
1838         unit->error("keyword `" + ident->v + "' cannot be used as parameter name");
1839     }
1840 }
1841 | out_qualifier meta_data type
1842 {
1843     BoolTokPtr isOutParam = BoolTokPtr::dynamicCast($1);
1844     TypePtr type = TypePtr::dynamicCast($3);
1845     OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer());
1846     if(op)
1847     {
1848         op->createParamDecl(IceUtil::generateUUID(), type, isOutParam->v, false, 0); // Dummy
1849         unit->error("missing parameter name");
1850     }
1851 }
1852 | parameters ',' out_qualifier meta_data type
1853 {
1854     BoolTokPtr isOutParam = BoolTokPtr::dynamicCast($3);
1855     TypePtr type = TypePtr::dynamicCast($5);
1856     OperationPtr op = OperationPtr::dynamicCast(unit->currentContainer());
1857     if(op)
1858     {
1859         op->createParamDecl(IceUtil::generateUUID(), type, isOutParam->v, false, 0); // Dummy
1860         unit->error("missing parameter name");
1861     }
1862 }
1863 ;
1864 
1865 // ----------------------------------------------------------------------
1866 throws
1867 // ----------------------------------------------------------------------
1868 : ICE_THROWS exception_list
1869 {
1870     $$ = $2;
1871 }
1872 |
1873 {
1874     $$ = new ExceptionListTok;
1875 }
1876 ;
1877 
1878 // ----------------------------------------------------------------------
1879 scoped_name
1880 // ----------------------------------------------------------------------
1881 : ICE_IDENTIFIER
1882 {
1883 }
1884 | ICE_SCOPED_IDENTIFIER
1885 {
1886 }
1887 ;
1888 
1889 // ----------------------------------------------------------------------
1890 type
1891 // ----------------------------------------------------------------------
1892 : ICE_BYTE
1893 {
1894     $$ = unit->builtin(Builtin::KindByte);
1895 }
1896 | ICE_BOOL
1897 {
1898     $$ = unit->builtin(Builtin::KindBool);
1899 }
1900 | ICE_SHORT
1901 {
1902     $$ = unit->builtin(Builtin::KindShort);
1903 }
1904 | ICE_INT
1905 {
1906     $$ = unit->builtin(Builtin::KindInt);
1907 }
1908 | ICE_LONG
1909 {
1910     $$ = unit->builtin(Builtin::KindLong);
1911 }
1912 | ICE_FLOAT
1913 {
1914     $$ = unit->builtin(Builtin::KindFloat);
1915 }
1916 | ICE_DOUBLE
1917 {
1918     $$ = unit->builtin(Builtin::KindDouble);
1919 }
1920 | ICE_STRING
1921 {
1922     $$ = unit->builtin(Builtin::KindString);
1923 }
1924 | ICE_OBJECT
1925 {
1926     $$ = unit->builtin(Builtin::KindObject);
1927 }
1928 | ICE_OBJECT '*'
1929 {
1930     $$ = unit->builtin(Builtin::KindObjectProxy);
1931 }
1932 | ICE_LOCAL_OBJECT
1933 {
1934     $$ = unit->builtin(Builtin::KindLocalObject);
1935 }
1936 | ICE_VALUE
1937 {
1938     $$ = unit->builtin(Builtin::KindValue);
1939 }
1940 | scoped_name
1941 {
1942     StringTokPtr scoped = StringTokPtr::dynamicCast($1);
1943     ContainerPtr cont = unit->currentContainer();
1944     if(cont)
1945     {
1946         TypeList types = cont->lookupType(scoped->v);
1947         if(types.empty())
1948         {
1949             YYERROR; // Can't continue, jump to next yyerrok
1950         }
1951         cont->checkIntroduced(scoped->v);
1952         $$ = types.front();
1953     }
1954     else
1955     {
1956         $$ = 0;
1957     }
1958 }
1959 | scoped_name '*'
1960 {
1961     StringTokPtr scoped = StringTokPtr::dynamicCast($1);
1962     ContainerPtr cont = unit->currentContainer();
1963     if(cont)
1964     {
1965         TypeList types = cont->lookupType(scoped->v);
1966         if(types.empty())
1967         {
1968             YYERROR; // Can't continue, jump to next yyerrok
1969         }
1970         for(TypeList::iterator p = types.begin(); p != types.end(); ++p)
1971         {
1972             ClassDeclPtr cl = ClassDeclPtr::dynamicCast(*p);
1973             if(!cl)
1974             {
1975                 string msg = "`";
1976                 msg += scoped->v;
1977                 msg += "' must be class or interface";
1978                 unit->error(msg);
1979                 YYERROR; // Can't continue, jump to next yyerrok
1980             }
1981             cont->checkIntroduced(scoped->v);
1982             if(cl->isLocal())
1983             {
1984                 unit->error("cannot create proxy for " + cl->kindOf() + " `" + cl->name() + "'"); // $$ is dummy
1985             }
1986             *p = new Proxy(cl);
1987         }
1988         $$ = types.front();
1989     }
1990     else
1991     {
1992         $$ = 0;
1993     }
1994 }
1995 ;
1996 
1997 // ----------------------------------------------------------------------
1998 string_literal
1999 // ----------------------------------------------------------------------
2000 : ICE_STRING_LITERAL string_literal // Adjacent string literals are concatenated
2001 {
2002     StringTokPtr str1 = StringTokPtr::dynamicCast($1);
2003     StringTokPtr str2 = StringTokPtr::dynamicCast($2);
2004     str1->v += str2->v;
2005 }
2006 | ICE_STRING_LITERAL
2007 {
2008 }
2009 ;
2010 
2011 // ----------------------------------------------------------------------
2012 string_list
2013 // ----------------------------------------------------------------------
2014 : string_list ',' string_literal
2015 {
2016     StringTokPtr str = StringTokPtr::dynamicCast($3);
2017     StringListTokPtr stringList = StringListTokPtr::dynamicCast($1);
2018     stringList->v.push_back(str->v);
2019     $$ = stringList;
2020 }
2021 | string_literal
2022 {
2023     StringTokPtr str = StringTokPtr::dynamicCast($1);
2024     StringListTokPtr stringList = new StringListTok;
2025     stringList->v.push_back(str->v);
2026     $$ = stringList;
2027 }
2028 ;
2029 
2030 // ----------------------------------------------------------------------
2031 local_qualifier
2032 // ----------------------------------------------------------------------
2033 : ICE_LOCAL
2034 {
2035     BoolTokPtr local = new BoolTok;
2036     local->v = true;
2037     $$ = local;
2038 }
2039 |
2040 {
2041     BoolTokPtr local = new BoolTok;
2042     local->v = false;
2043     $$ = local;
2044 }
2045 ;
2046 
2047 // ----------------------------------------------------------------------
2048 const_initializer
2049 // ----------------------------------------------------------------------
2050 : ICE_INTEGER_LITERAL
2051 {
2052     BuiltinPtr type = unit->builtin(Builtin::KindLong);
2053     IntegerTokPtr intVal = IntegerTokPtr::dynamicCast($1);
2054     ostringstream sstr;
2055     sstr << intVal->v;
2056     ConstDefTokPtr def = new ConstDefTok;
2057     def->v.type = type;
2058     def->v.value = type;
2059     def->v.valueAsString = sstr.str();
2060     def->v.valueAsLiteral = intVal->literal;
2061     $$ = def;
2062 }
2063 | ICE_FLOATING_POINT_LITERAL
2064 {
2065     BuiltinPtr type = unit->builtin(Builtin::KindDouble);
2066     FloatingTokPtr floatVal = FloatingTokPtr::dynamicCast($1);
2067     ostringstream sstr;
2068     sstr << floatVal->v;
2069     ConstDefTokPtr def = new ConstDefTok;
2070     def->v.type = type;
2071     def->v.value = type;
2072     def->v.valueAsString = sstr.str();
2073     def->v.valueAsLiteral = floatVal->literal;
2074     $$ = def;
2075 }
2076 | scoped_name
2077 {
2078     StringTokPtr scoped = StringTokPtr::dynamicCast($1);
2079     ConstDefTokPtr def = new ConstDefTok;
2080     ContainedList cl = unit->currentContainer()->lookupContained(scoped->v, false);
2081     if(cl.empty())
2082     {
2083         // Could be an enumerator
2084         def->v.type = TypePtr(0);
2085         def->v.value = SyntaxTreeBasePtr(0);
2086         def->v.valueAsString = scoped->v;
2087         def->v.valueAsLiteral = scoped->v;
2088     }
2089     else
2090     {
2091         EnumeratorPtr enumerator = EnumeratorPtr::dynamicCast(cl.front());
2092         ConstPtr constant = ConstPtr::dynamicCast(cl.front());
2093         if(enumerator)
2094         {
2095             unit->currentContainer()->checkIntroduced(scoped->v, enumerator);
2096             def->v.type = enumerator->type();
2097             def->v.value = enumerator;
2098             def->v.valueAsString = scoped->v;
2099             def->v.valueAsLiteral = scoped->v;
2100         }
2101         else if(constant)
2102         {
2103             unit->currentContainer()->checkIntroduced(scoped->v, constant);
2104             def->v.value = constant;
2105             def->v.valueAsString = constant->value();
2106             def->v.valueAsLiteral = constant->value();
2107         }
2108         else
2109         {
2110             string msg = "illegal initializer: `" + scoped->v + "' is a";
2111             static const string vowels = "aeiou";
2112             string kindOf = cl.front()->kindOf();
2113             if(vowels.find_first_of(kindOf[0]) != string::npos)
2114             {
2115                 msg += "n";
2116             }
2117             msg += " " + kindOf;
2118             unit->error(msg); // $$ is dummy
2119         }
2120     }
2121     $$ = def;
2122 }
2123 | ICE_STRING_LITERAL
2124 {
2125     BuiltinPtr type = unit->builtin(Builtin::KindString);
2126     StringTokPtr literal = StringTokPtr::dynamicCast($1);
2127     ConstDefTokPtr def = new ConstDefTok;
2128     def->v.type = type;
2129     def->v.value = type;
2130     def->v.valueAsString = literal->v;
2131     def->v.valueAsLiteral = literal->literal;
2132     $$ = def;
2133 }
2134 | ICE_FALSE
2135 {
2136     BuiltinPtr type = unit->builtin(Builtin::KindBool);
2137     StringTokPtr literal = StringTokPtr::dynamicCast($1);
2138     ConstDefTokPtr def = new ConstDefTok;
2139     def->v.type = type;
2140     def->v.value = type;
2141     def->v.valueAsString = "false";
2142     def->v.valueAsLiteral = "false";
2143     $$ = def;
2144 }
2145 | ICE_TRUE
2146 {
2147     BuiltinPtr type = unit->builtin(Builtin::KindBool);
2148     StringTokPtr literal = StringTokPtr::dynamicCast($1);
2149     ConstDefTokPtr def = new ConstDefTok;
2150     def->v.type = type;
2151     def->v.value = type;
2152     def->v.valueAsString = "true";
2153     def->v.valueAsLiteral = "true";
2154     $$ = def;
2155 }
2156 ;
2157 
2158 // ----------------------------------------------------------------------
2159 const_def
2160 // ----------------------------------------------------------------------
2161 : ICE_CONST meta_data type ICE_IDENTIFIER '=' const_initializer
2162 {
2163     StringListTokPtr metaData = StringListTokPtr::dynamicCast($2);
2164     TypePtr const_type = TypePtr::dynamicCast($3);
2165     StringTokPtr ident = StringTokPtr::dynamicCast($4);
2166     ConstDefTokPtr value = ConstDefTokPtr::dynamicCast($6);
2167     $$ = unit->currentContainer()->createConst(ident->v, const_type, metaData->v, value->v.value,
2168                                                value->v.valueAsString, value->v.valueAsLiteral);
2169 }
2170 | ICE_CONST meta_data type '=' const_initializer
2171 {
2172     StringListTokPtr metaData = StringListTokPtr::dynamicCast($2);
2173     TypePtr const_type = TypePtr::dynamicCast($3);
2174     ConstDefTokPtr value = ConstDefTokPtr::dynamicCast($5);
2175     unit->error("missing constant name");
2176     $$ = unit->currentContainer()->createConst(IceUtil::generateUUID(), const_type, metaData->v, value->v.value,
2177                                                value->v.valueAsString, value->v.valueAsLiteral, Dummy); // Dummy
2178 }
2179 ;
2180 
2181 // ----------------------------------------------------------------------
2182 keyword
2183 // ----------------------------------------------------------------------
2184 : ICE_MODULE
2185 {
2186 }
2187 | ICE_CLASS
2188 {
2189 }
2190 | ICE_INTERFACE
2191 {
2192 }
2193 | ICE_EXCEPTION
2194 {
2195 }
2196 | ICE_STRUCT
2197 {
2198 }
2199 | ICE_SEQUENCE
2200 {
2201 }
2202 | ICE_DICTIONARY
2203 {
2204 }
2205 | ICE_ENUM
2206 {
2207 }
2208 | ICE_OUT
2209 {
2210 }
2211 | ICE_EXTENDS
2212 {
2213 }
2214 | ICE_IMPLEMENTS
2215 {
2216 }
2217 | ICE_THROWS
2218 {
2219 }
2220 | ICE_VOID
2221 {
2222 }
2223 | ICE_BYTE
2224 {
2225 }
2226 | ICE_BOOL
2227 {
2228 }
2229 | ICE_SHORT
2230 {
2231 }
2232 | ICE_INT
2233 {
2234 }
2235 | ICE_LONG
2236 {
2237 }
2238 | ICE_FLOAT
2239 {
2240 }
2241 | ICE_DOUBLE
2242 {
2243 }
2244 | ICE_STRING
2245 {
2246 }
2247 | ICE_OBJECT
2248 {
2249 }
2250 | ICE_LOCAL_OBJECT
2251 {
2252 }
2253 | ICE_LOCAL
2254 {
2255 }
2256 | ICE_CONST
2257 {
2258 }
2259 | ICE_FALSE
2260 {
2261 }
2262 | ICE_TRUE
2263 {
2264 }
2265 | ICE_IDEMPOTENT
2266 {
2267 }
2268 | ICE_OPTIONAL
2269 {
2270 }
2271 | ICE_VALUE
2272 {
2273 }
2274 ;
2275 
2276 %%
2277