1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9 
10 /*TODO: check Exception, RuntimeException, XInterface defns */
11 
12 %locations
13 %pure-parser
14 
15 %{
16 
17 #include <sal/config.h>
18 
19 #include <o3tl/unreachable.hxx>
20 #include <rtl/ustrbuf.hxx>
21 #include <unoidl/unoidl.hxx>
22 
23 #include <algorithm>
24 #include <cassert>
25 #include <cerrno>
26 #include <cstddef>
27 #include <cstdlib>
28 #include <limits>
29 #include <new>
30 #include <utility>
31 #include <vector>
32 
33 #include "sourceprovider-parser-requires.hxx"
34 
35 %}
36 
37 %union {
38     sal_uInt64 ival;
39     double fval;
40     OString * sval;
41 
42     bool bval;
43     std::vector<OUString> * excns;
44     unoidl::detail::SourceProviderAccessDecls decls;
45     unoidl::InterfaceTypeEntity::Method::Parameter::Direction dir;
46     unoidl::detail::SourceProviderFlags flags;
47     unoidl::detail::SourceProviderExpr expr;
48     unoidl::detail::SourceProviderType * type;
49     std::vector<unoidl::detail::SourceProviderType> * types;
50 }
51 
52 /* TODO: %destructor { delete $$; } <sval> <excns> <type> <types> */
53 
54 %lex-param {yyscan_t yyscanner}
55 %parse-param {yyscan_t yyscanner}
56 
57 %{
58 
59 #include <osl/file.h>
60 #include <osl/thread.h>
61 #include <sal/log.hxx>
62 
63 #include "sourceprovider-scanner.hxx"
64 
65 #define YYLLOC_DEFAULT(Current, Rhs, N) \
66     do { (Current) = YYRHSLOC((Rhs), (N) ? 1 : 0); } while (0)
67 
yyerror(YYLTYPE * locp,yyscan_t yyscanner,char const * msg)68 static void yyerror(YYLTYPE * locp, yyscan_t yyscanner, char const * msg) {
69     assert(locp != nullptr);
70     unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
71     data->errorLine = *locp;
72     data->parserError = OString(msg);
73 }
74 
75 namespace {
76 
error(YYLTYPE location,yyscan_t yyscanner,OUString const & message)77 void error(YYLTYPE location, yyscan_t yyscanner, OUString const & message) {
78     unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
79     data->errorLine = location;
80     data->errorMessage = message;
81 }
82 
flagName(unoidl::detail::SourceProviderFlags flag)83 OUString flagName(unoidl::detail::SourceProviderFlags flag) {
84     switch (flag) {
85     case unoidl::detail::FLAG_ATTRIBUTE:
86         return "attribute";
87     case unoidl::detail::FLAG_BOUND:
88         return "bound";
89     case unoidl::detail::FLAG_CONSTRAINED:
90         return "constrained";
91     case unoidl::detail::FLAG_MAYBEAMBIGUOUS:
92         return "maybeambiguous";
93     case unoidl::detail::FLAG_MAYBEDEFAULT:
94         return "maybedefault";
95     case unoidl::detail::FLAG_MAYBEVOID:
96         return "maybevoid";
97     case unoidl::detail::FLAG_OPTIONAL:
98         return "optional";
99     case unoidl::detail::FLAG_PROPERTY:
100         return "property";
101     case unoidl::detail::FLAG_READONLY:
102         return "readonly";
103     case unoidl::detail::FLAG_REMOVABLE:
104         return "removable";
105     case unoidl::detail::FLAG_TRANSIENT:
106         return "transient";
107     default:
108         assert(false && "this cannot happen"); for (;;) { std::abort(); }
109     }
110 }
111 
convertName(OString const * name)112 OUString convertName(OString const * name) {
113     assert(name != nullptr);
114     OUString s(OStringToOUString(*name, RTL_TEXTENCODING_ASCII_US));
115     delete name;
116     return s;
117 }
118 
convertToFullName(unoidl::detail::SourceProviderScannerData const * data,OString const * identifier)119 OUString convertToFullName(
120     unoidl::detail::SourceProviderScannerData const * data,
121     OString const * identifier)
122 {
123     assert(data != nullptr);
124     OUString pref;
125     if (!data->modules.empty()) {
126         pref = data->modules.back() + ".";
127     }
128     return pref + convertName(identifier);
129 }
130 
convertToCurrentName(unoidl::detail::SourceProviderScannerData * data,OString const * identifier)131 void convertToCurrentName(
132     unoidl::detail::SourceProviderScannerData * data,
133     OString const * identifier)
134 {
135     assert(data != nullptr);
136     assert(data->currentName.isEmpty());
137     data->currentName = convertToFullName(data, identifier);
138     assert(!data->currentName.isEmpty());
139 }
140 
clearCurrentState(unoidl::detail::SourceProviderScannerData * data)141 void clearCurrentState(unoidl::detail::SourceProviderScannerData * data) {
142     assert(data != nullptr);
143     data->currentName.clear();
144     data->publishedContext = false;
145 }
146 
getCurrentEntity(unoidl::detail::SourceProviderScannerData * data)147 unoidl::detail::SourceProviderEntity * getCurrentEntity(
148     unoidl::detail::SourceProviderScannerData * data)
149 {
150     assert(data != nullptr);
151     assert(!data->currentName.isEmpty());
152     std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator i(
153         data->entities.find(data->currentName));
154     assert(i != data->entities.end());
155     assert(i->second.kind == unoidl::detail::SourceProviderEntity::KIND_LOCAL);
156     assert(i->second.pad.is());
157     return &i->second;
158 }
159 
getCurrentPad(unoidl::detail::SourceProviderScannerData * data)160 template<typename T> rtl::Reference<T> getCurrentPad(
161     unoidl::detail::SourceProviderScannerData * data)
162 {
163     rtl::Reference<T> pad(dynamic_cast<T *>(getCurrentEntity(data)->pad.get()));
164     assert(pad.is());
165     return pad;
166 }
167 
nameHasSameIdentifierAs(OUString const & name,OUString const & identifier)168 bool nameHasSameIdentifierAs(OUString const & name, OUString const & identifier)
169 {
170     sal_Int32 i = name.lastIndexOf('.') + 1;
171     return identifier.getLength() == name.getLength() - i
172         && name.match(identifier, i);
173 }
174 
coerce(YYLTYPE location,yyscan_t yyscanner,unoidl::detail::SourceProviderExpr * lhs,unoidl::detail::SourceProviderExpr * rhs)175 bool coerce(
176     YYLTYPE location, yyscan_t yyscanner,
177     unoidl::detail::SourceProviderExpr * lhs,
178     unoidl::detail::SourceProviderExpr * rhs)
179 {
180     assert(lhs != nullptr);
181     assert(rhs != nullptr);
182     bool ok = bool(); // avoid warnings
183     switch (lhs->type) {
184     case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
185         ok = rhs->type != unoidl::detail::SourceProviderExpr::TYPE_BOOL;
186         break;
187     case unoidl::detail::SourceProviderExpr::TYPE_INT:
188         switch (rhs->type) {
189         case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
190             ok = false;
191             break;
192         case unoidl::detail::SourceProviderExpr::TYPE_INT:
193             ok = true;
194             break;
195         case unoidl::detail::SourceProviderExpr::TYPE_UINT:
196             if (lhs->ival >= 0) {
197                 lhs->type = unoidl::detail::SourceProviderExpr::TYPE_UINT;
198                 ok = true;
199             } else if (rhs->uval <= SAL_MAX_INT64) {
200                 rhs->type = unoidl::detail::SourceProviderExpr::TYPE_INT;
201                 ok = true;
202             } else {
203                 ok = false;
204             }
205             break;
206         case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
207             {
208                 auto tmp = lhs->ival;
209                 lhs->fval = tmp;
210                 ok = true;
211             }
212             break;
213         }
214         break;
215     case unoidl::detail::SourceProviderExpr::TYPE_UINT:
216         switch (rhs->type) {
217         case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
218             ok = false;
219             break;
220         case unoidl::detail::SourceProviderExpr::TYPE_INT:
221             if (rhs->ival >= 0) {
222                 rhs->type = unoidl::detail::SourceProviderExpr::TYPE_UINT;
223                 ok = true;
224             } else if (lhs->uval <= SAL_MAX_INT64) {
225                 lhs->type = unoidl::detail::SourceProviderExpr::TYPE_INT;
226                 ok = true;
227             } else {
228                 ok = false;
229             }
230             break;
231         case unoidl::detail::SourceProviderExpr::TYPE_UINT:
232             ok = true;
233             break;
234         case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
235             {
236                 auto nTmp = lhs->uval;
237                 lhs->fval = nTmp;
238                 ok = true;
239             }
240             break;
241         }
242         break;
243     case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
244         switch (rhs->type) {
245         case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
246             ok = false;
247             break;
248         case unoidl::detail::SourceProviderExpr::TYPE_INT:
249             {
250                 auto tmp = rhs->ival;
251                 rhs->fval = tmp;
252                 ok = true;
253             }
254             break;
255         case unoidl::detail::SourceProviderExpr::TYPE_UINT:
256             {
257                 auto tmp = rhs->uval;
258                 rhs->fval = tmp;
259                 ok = true;
260             }
261             break;
262         case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
263             ok = true;
264             break;
265         }
266         break;
267     }
268     if (!ok) {
269         error(location, yyscanner, "cannot coerce binary expression arguments");
270     }
271     return ok;
272 }
273 
findEntity_(unoidl::detail::SourceProviderScannerData * data,OUString * name)274 unoidl::detail::SourceProviderEntity * findEntity_(
275     unoidl::detail::SourceProviderScannerData * data, OUString * name)
276 {
277     assert(data != nullptr);
278     assert(name != nullptr);
279     OUString n;
280     if (!name->startsWith(".", &n)) {
281         for (auto i(data->modules.rbegin()); i != data->modules.rend(); ++i) {
282             n = *i + "." + *name;
283             std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator j(
284                 data->entities.find(n));
285             if (j != data->entities.end()) {
286                 *name = n;
287                 return &j->second;
288             }
289             rtl::Reference<unoidl::Entity> ent(data->manager->findEntity(n));
290             if (ent.is()) {
291                 std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator
292                     k(data->entities.emplace(
293                               n,
294                               unoidl::detail::SourceProviderEntity(
295                                   unoidl::detail::SourceProviderEntity::KIND_EXTERNAL,
296                                   ent)).
297                       first);
298                 *name = n;
299                 return &k->second;
300             }
301         }
302         n = *name;
303     }
304     std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator i(
305         data->entities.find(n));
306     if (i != data->entities.end()) {
307         *name = n;
308         return &i->second;
309     }
310     rtl::Reference<unoidl::Entity> ent(data->manager->findEntity(n));
311     if (ent.is()) {
312         std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator
313             j(data->entities.emplace(
314                       n,
315                       unoidl::detail::SourceProviderEntity(
316                           unoidl::detail::SourceProviderEntity::KIND_EXTERNAL,
317                           ent)).
318               first);
319         *name = n;
320         return &j->second;
321     }
322     return nullptr;
323 }
324 
325 enum Found { FOUND_ERROR, FOUND_TYPE, FOUND_ENTITY };
326 
findEntity(YYLTYPE location,yyscan_t yyscanner,unoidl::detail::SourceProviderScannerData * data,bool resolveInterfaceDefinitions,OUString * name,unoidl::detail::SourceProviderEntity const ** entity,bool * typedefed,unoidl::detail::SourceProviderType * typedefedType)327 Found findEntity(
328     YYLTYPE location, yyscan_t yyscanner,
329     unoidl::detail::SourceProviderScannerData * data,
330     bool resolveInterfaceDefinitions, OUString * name,
331     unoidl::detail::SourceProviderEntity const ** entity, bool * typedefed,
332     unoidl::detail::SourceProviderType * typedefedType)
333 {
334     //TODO: avoid recursion
335     assert(data != nullptr);
336     assert(name != nullptr);
337     assert(entity != nullptr);
338     unoidl::detail::SourceProviderEntity * e = findEntity_(data, name);
339     OUString n(*name);
340     OUString typeNucleus;
341     std::size_t rank = 0;
342     std::vector<unoidl::detail::SourceProviderType> args;
343     for (;;) {
344         if (e != nullptr) {
345             switch (e->kind) {
346             case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
347                 if (e->pad.is()) {
348                     break;
349                 }
350                 assert(e->entity.is());
351                 [[fallthrough]];
352             case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
353                 if (e->entity->getSort() == unoidl::Entity::SORT_TYPEDEF) {
354                     if (typedefed != nullptr) {
355                         *typedefed = true;
356                     }
357                     if (data->publishedContext
358                         && !static_cast<unoidl::TypedefEntity *>(
359                             e->entity.get())->isPublished())
360                     {
361                         error(
362                             location, yyscanner,
363                             ("type " + *name + " based on unpublished typedef "
364                              + n + " used in published context"));
365                         return FOUND_ERROR;
366                     }
367                     OUString t(
368                         static_cast<unoidl::TypedefEntity *>(e->entity.get())
369                         ->getType());
370                     typeNucleus = t;
371                     while (typeNucleus.startsWith("[]", &typeNucleus)) {
372                         if (!args.empty()) {
373                             error(
374                                 location, yyscanner,
375                                 ("inconsistent type manager: bad type " + *name
376                                  + (" based on instantiated polymorphic struct"
377                                     " type based on sequence type named ")
378                                  + t));
379                             return FOUND_ERROR;
380                         }
381                         if (rank == std::numeric_limits<std::size_t>::max()) {
382                             error(
383                                 location, yyscanner,
384                                 ("bad type " + *name
385                                  + " based on sequence type of too high rank"));
386                             return FOUND_ERROR;
387                         }
388                         ++rank;
389                     }
390                     sal_Int32 i = typeNucleus.indexOf('<');
391                     if (i != -1) {
392                         if (!args.empty()) {
393                             error(
394                                 location, yyscanner,
395                                 ("inconsistent type manager: bad type " + *name
396                                  + (" based on instantiated polymorphic struct"
397                                     " type based on instantiated polymorphic"
398                                     " struct type named ")
399                                  + t));
400                             return FOUND_ERROR;
401                         }
402                         OUString tmpl(typeNucleus.copy(0, i));
403                         do {
404                             ++i; // skip '<' or ','
405                             sal_Int32 j = i;
406                             for (sal_Int32 level = 0;
407                                  j != typeNucleus.getLength(); ++j)
408                             {
409                                 sal_Unicode c = typeNucleus[j];
410                                 if (c == ',') {
411                                     if (level == 0) {
412                                         break;
413                                     }
414                                 } else if (c == '<') {
415                                     ++level;
416                                 } else if (c == '>') {
417                                     if (level == 0) {
418                                         break;
419                                     }
420                                     --level;
421                                 }
422                             }
423                             if (j != typeNucleus.getLength()) {
424                                 OUString argName(typeNucleus.copy(i, j - i));
425                                 unoidl::detail::SourceProviderEntity const *
426                                     argEnt;
427                                 unoidl::detail::SourceProviderType argType;
428                                 switch (
429                                     findEntity(
430                                         location, yyscanner, data, false,
431                                         &argName, &argEnt, nullptr, &argType))
432                                 {
433                                 case FOUND_ERROR:
434                                     return FOUND_ERROR;
435                                 case FOUND_TYPE:
436                                     break;
437                                 case FOUND_ENTITY:
438                                     if (argEnt == nullptr) {
439                                         error(
440                                             location, yyscanner,
441                                             (("inconsistent type manager: bad"
442                                               " instantiated polymorphic struct"
443                                               " type template type argument ")
444                                              + argName));
445                                         return FOUND_ERROR;
446                                     } else {
447                                         unoidl::detail::SourceProviderType::Type
448                                             argT
449                                             = unoidl::detail::SourceProviderType::Type();
450                                             // avoid warnings
451                                         switch (argEnt->kind) {
452                                         case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
453                                             if (e->pad.is()) {
454                                                 error(
455                                                     location, yyscanner,
456                                                     (("inconsistent type"
457                                                       " manager: bad"
458                                                       " instantiated"
459                                                       " polymorphic struct type"
460                                                       " template type"
461                                                       " argument ")
462                                                      + argName));
463                                                 return FOUND_ERROR;
464                                             }
465                                             assert(e->entity.is());
466                                             [[fallthrough]];
467                                         case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
468                                             switch (e->entity->getSort()) {
469                                             case unoidl::Entity::SORT_ENUM_TYPE:
470                                                 argT = unoidl::detail::SourceProviderType::TYPE_ENUM;
471                                                 break;
472                                             case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
473                                                 argT = unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT;
474                                                 break;
475                                             case unoidl::Entity::SORT_INTERFACE_TYPE:
476                                                 argT = unoidl::detail::SourceProviderType::TYPE_INTERFACE;
477                                                 break;
478                                             default:
479                                                 error(
480                                                     location, yyscanner,
481                                                     (("inconsistent type"
482                                                       "manager: bad"
483                                                       " instantiated"
484                                                       " polymorphic struct type"
485                                                       " template type"
486                                                       " argument ")
487                                                      + argName));
488                                                 return FOUND_ERROR;
489                                             }
490                                             break;
491                                         case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
492                                         case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
493                                             argT = unoidl::detail::SourceProviderType::TYPE_INTERFACE;
494                                             break;
495                                         case unoidl::detail::SourceProviderEntity::KIND_MODULE:
496                                             assert(false && "this cannot happen");
497                                         }
498                                         argType
499                                             = unoidl::detail::SourceProviderType(
500                                                 argT, argName, argEnt);
501                                     }
502                                     break;
503                                 }
504                                 args.push_back(argType);
505                             }
506                             i = j;
507                         } while (i != typeNucleus.getLength()
508                                  && typeNucleus[i] != '>');
509                         if (i != typeNucleus.getLength() - 1
510                             || typeNucleus[i] != '>')
511                         {
512                             error(
513                                 location, yyscanner,
514                                 ("inconsistent type manager: bad type name \""
515                                  + t + "\""));
516                             return FOUND_ERROR;
517                         }
518                         assert(!args.empty());
519                         typeNucleus = tmpl;
520                     }
521                     if (typeNucleus.isEmpty()) {
522                         error(
523                             location, yyscanner,
524                             ("inconsistent type manager: bad type name \"" + t
525                              + "\""));
526                         return FOUND_ERROR;
527                     }
528                     if (typeNucleus == "void") {
529                         error(
530                             location, yyscanner,
531                             ("inconsistent type manager: bad type " + *name
532                              + " based on void"));
533                         return FOUND_ERROR;
534                     }
535                     if (typeNucleus == "boolean" || typeNucleus == "byte"
536                         || typeNucleus == "short"
537                         || typeNucleus == "unsigned short"
538                         || typeNucleus == "long"
539                         || typeNucleus == "unsigned long"
540                         || typeNucleus == "hyper"
541                         || typeNucleus == "unsigned hyper"
542                         || typeNucleus == "float" || typeNucleus == "double"
543                         || typeNucleus == "char" || typeNucleus == "string"
544                         || typeNucleus == "type" || typeNucleus == "any")
545                     {
546                         if (!args.empty()) {
547                             error(
548                                 location, yyscanner,
549                                 ("inconsistent type manager: bad type " + *name
550                                  + (" based on instantiated polymorphic struct"
551                                     " type based on ")
552                                  + typeNucleus));
553                             return FOUND_ERROR;
554                         }
555                         break;
556                     }
557                     n = "." + typeNucleus;
558                     typeNucleus.clear();
559                     e = findEntity_(data, &n);
560                     continue;
561                 }
562                 break;
563             case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
564             case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
565                 if (resolveInterfaceDefinitions) {
566                     rtl::Reference<unoidl::Entity> ent(
567                         data->manager->findEntity(n));
568                     // Do not allow ent to be of SORT_TYPEDEF:
569                     if (!ent.is()
570                         || (ent->getSort()
571                             != unoidl::Entity::SORT_INTERFACE_TYPE))
572                     {
573                         error(
574                             location, yyscanner,
575                             (*name + " is based on interface declaration " + n
576                              + " that is not an interface type entity"));
577                         return FOUND_ERROR;
578                     }
579                     e->kind
580                         = unoidl::detail::SourceProviderEntity::KIND_EXTERNAL;
581                     e->entity = ent;
582                 }
583                 break;
584             case unoidl::detail::SourceProviderEntity::KIND_MODULE:
585                 error(
586                     location, yyscanner,
587                     *name + " is based on module entity " + n);
588                 return FOUND_ERROR;
589             }
590         }
591         if (!typeNucleus.isEmpty() || rank != 0 || !args.empty()) {
592             if (typeNucleus.isEmpty() && e == nullptr) {
593                 // Found a type name based on an unknown entity:
594                 *entity = nullptr;
595                 return FOUND_ENTITY;
596             }
597             unoidl::detail::SourceProviderType t;
598             if (args.empty()) {
599                 if (typeNucleus == "boolean") {
600                     t = unoidl::detail::SourceProviderType(
601                         unoidl::detail::SourceProviderType::TYPE_BOOLEAN);
602                 } else if (typeNucleus == "byte") {
603                     t = unoidl::detail::SourceProviderType(
604                         unoidl::detail::SourceProviderType::TYPE_BYTE);
605                 } else if (typeNucleus == "short") {
606                     t = unoidl::detail::SourceProviderType(
607                         unoidl::detail::SourceProviderType::TYPE_SHORT);
608                 } else if (typeNucleus == "unsigned short") {
609                     t = unoidl::detail::SourceProviderType(
610                         unoidl::detail::SourceProviderType::TYPE_UNSIGNED_SHORT);
611                 } else if (typeNucleus == "long") {
612                     t = unoidl::detail::SourceProviderType(
613                         unoidl::detail::SourceProviderType::TYPE_LONG);
614                 } else if (typeNucleus == "unsigned long") {
615                     t = unoidl::detail::SourceProviderType(
616                         unoidl::detail::SourceProviderType::TYPE_UNSIGNED_LONG);
617                 } else if (typeNucleus == "hyper") {
618                     t = unoidl::detail::SourceProviderType(
619                         unoidl::detail::SourceProviderType::TYPE_HYPER);
620                 } else if (typeNucleus == "unsigned hyper") {
621                     t = unoidl::detail::SourceProviderType(
622                         unoidl::detail::SourceProviderType::TYPE_UNSIGNED_HYPER);
623                 } else if (typeNucleus == "float") {
624                     t = unoidl::detail::SourceProviderType(
625                         unoidl::detail::SourceProviderType::TYPE_FLOAT);
626                 } else if (typeNucleus == "double") {
627                     t = unoidl::detail::SourceProviderType(
628                         unoidl::detail::SourceProviderType::TYPE_DOUBLE);
629                 } else if (typeNucleus == "char") {
630                     t = unoidl::detail::SourceProviderType(
631                         unoidl::detail::SourceProviderType::TYPE_CHAR);
632                 } else if (typeNucleus == "string") {
633                     t = unoidl::detail::SourceProviderType(
634                         unoidl::detail::SourceProviderType::TYPE_STRING);
635                 } else if (typeNucleus == "type") {
636                     t = unoidl::detail::SourceProviderType(
637                         unoidl::detail::SourceProviderType::TYPE_TYPE);
638                 } else if (typeNucleus == "any") {
639                     t = unoidl::detail::SourceProviderType(
640                         unoidl::detail::SourceProviderType::TYPE_ANY);
641                 } else {
642                     assert(typeNucleus.isEmpty());
643                     assert(e != nullptr);
644                     switch (e->kind) {
645                     case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
646                         if (e->pad.is()) {
647                             if (dynamic_cast<unoidl::detail::SourceProviderEnumTypeEntityPad *>(
648                                     e->pad.get())
649                                 != nullptr)
650                             {
651                                 t = unoidl::detail::SourceProviderType(
652                                     unoidl::detail::SourceProviderType::TYPE_ENUM,
653                                     n, e);
654                             } else if (dynamic_cast<unoidl::detail::SourceProviderPlainStructTypeEntityPad *>(
655                                            e->pad.get())
656                                        != nullptr)
657                             {
658                                 t = unoidl::detail::SourceProviderType(
659                                     unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT,
660                                     n, e);
661                             } else if (dynamic_cast<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
662                                            e->pad.get())
663                                        != nullptr)
664                             {
665                                 error(
666                                     location, yyscanner,
667                                     ("bad type " + *name
668                                      + (" based on recursive reference to"
669                                         " polymorphic struct type template ")
670                                      + n));
671                                 return FOUND_ERROR;
672                             } else if (dynamic_cast<unoidl::detail::SourceProviderExceptionTypeEntityPad *>(
673                                            e->pad.get())
674                                        != nullptr)
675                             {
676                                 t = unoidl::detail::SourceProviderType(
677                                     unoidl::detail::SourceProviderType::TYPE_EXCEPTION,
678                                     n, e);
679                             } else if (dynamic_cast<unoidl::detail::SourceProviderInterfaceTypeEntityPad *>(
680                                            e->pad.get())
681                                        != nullptr)
682                             {
683                                 t = unoidl::detail::SourceProviderType(
684                                     unoidl::detail::SourceProviderType::TYPE_INTERFACE,
685                                     n, e);
686                             } else {
687                                 error(
688                                     location, yyscanner,
689                                     ("bad type " + *name
690                                      + " based on non-type entity " + n));
691                                 return FOUND_ERROR;
692                             }
693                             break;
694                         }
695                         assert(e->entity.is());
696                         [[fallthrough]];
697                     case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
698                         switch (e->entity->getSort()) {
699                         case unoidl::Entity::SORT_ENUM_TYPE:
700                             t = unoidl::detail::SourceProviderType(
701                                 unoidl::detail::SourceProviderType::TYPE_ENUM,
702                                 n, e);
703                             break;
704                         case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
705                             t = unoidl::detail::SourceProviderType(
706                                 unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT,
707                                 n, e);
708                             break;
709                         case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
710                             error(
711                                 location, yyscanner,
712                                 ("bad type " + *name
713                                  + " based on polymorphic struct type template "
714                                  + n + " without type arguments"));
715                             return FOUND_ERROR;
716                         case unoidl::Entity::SORT_EXCEPTION_TYPE:
717                             t = unoidl::detail::SourceProviderType(
718                                 unoidl::detail::SourceProviderType::TYPE_EXCEPTION,
719                                 n, e);
720                             break;
721                         case unoidl::Entity::SORT_INTERFACE_TYPE:
722                             t = unoidl::detail::SourceProviderType(
723                                 unoidl::detail::SourceProviderType::TYPE_INTERFACE,
724                                 n, e);
725                             break;
726                         default:
727                             error(
728                                 location, yyscanner,
729                                 ("bad type " + *name
730                                  + " based on non-type entity " + n));
731                             return FOUND_ERROR;
732                         }
733                         break;
734                     case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
735                     case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
736                         t = unoidl::detail::SourceProviderType(
737                             unoidl::detail::SourceProviderType::TYPE_INTERFACE,
738                             n, e);
739                         break;
740                     case unoidl::detail::SourceProviderEntity::KIND_MODULE:
741                         assert(false && "this cannot happen");
742                     }
743                 }
744             } else {
745                 assert(typeNucleus.isEmpty());
746                 assert(e != nullptr);
747                 switch (e->kind) {
748                 case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
749                     if (e->pad.is()) {
750                         error(
751                             location, yyscanner,
752                             ("bad type " + *name
753                              + (" based on instantiated polymorphic struct type"
754                                 " based on ")
755                              + n
756                              + (" that is either not a polymorphic struct type"
757                                 " template or a recursive reference to a"
758                                 " polymorphic struct type template")));
759                         return FOUND_ERROR;
760                     }
761                     assert(e->entity.is());
762                     [[fallthrough]];
763                 case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
764                     if (e->entity->getSort()
765                         == unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE)
766                     {
767                         if (args.size()
768                             != (static_cast<
769                                     unoidl::PolymorphicStructTypeTemplateEntity *>(
770                                         e->entity.get())
771                                 ->getTypeParameters().size()))
772                         {
773                             error(
774                                 location, yyscanner,
775                                 ("bad type " + *name
776                                  + (" based on instantiated polymorphic struct"
777                                     " type with ")
778                                  + OUString::number(args.size())
779                                  + (" type arguments based on polymorphic"
780                                     " struct type template ")
781                                  + n + " with "
782                                  + OUString::number(
783                                      static_cast<
784                                          unoidl::PolymorphicStructTypeTemplateEntity *>(
785                                              e->entity.get())
786                                      ->getTypeParameters().size())
787                                  + " type parameters"));
788                             return FOUND_ERROR;
789                         }
790                         t = unoidl::detail::SourceProviderType(n, e, args);
791                         break;
792                     }
793                     [[fallthrough]];
794                 case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
795                 case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
796                     error(
797                         location, yyscanner,
798                         ("bad type " + *name
799                          + (" based on instantiated polymorphic struct type"
800                             " based on ")
801                          + n
802                          + " that is not a polymorphic struct type template"));
803                     return FOUND_ERROR;
804                 case unoidl::detail::SourceProviderEntity::KIND_MODULE:
805                     assert(false && "this cannot happen");
806                 }
807             }
808             if (typedefedType != nullptr) {
809                 for (std::size_t i = 0; i != rank; ++i) {
810                     t = unoidl::detail::SourceProviderType(&t);
811                 }
812                 *typedefedType = t;
813                 typedefedType->typedefName = *name;
814             }
815             *entity = nullptr;
816             return FOUND_TYPE;
817         }
818         *entity = e;
819         return FOUND_ENTITY;
820     }
821 }
822 
823 
checkTypeArgument(YYLTYPE location,yyscan_t yyscanner,unoidl::detail::SourceProviderType const & type)824 bool checkTypeArgument(
825     YYLTYPE location, yyscan_t yyscanner,
826     unoidl::detail::SourceProviderType const & type)
827 {
828     switch (type.type) {
829     case unoidl::detail::SourceProviderType::TYPE_VOID:
830     case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_SHORT:
831     case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_LONG:
832     case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_HYPER:
833     case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
834     case unoidl::detail::SourceProviderType::TYPE_PARAMETER: //TODO?
835         error(
836             location, yyscanner,
837             "bad instantiated polymorphic struct type argument");
838         return false;
839     case unoidl::detail::SourceProviderType::TYPE_SEQUENCE:
840         return checkTypeArgument(location, yyscanner, type.subtypes.front());
841     default:
842         return true;
843     }
844 }
845 
checkInstantiatedPolymorphicStructTypeArgument(unoidl::detail::SourceProviderType const & type,OUString const & name)846 bool checkInstantiatedPolymorphicStructTypeArgument(
847     unoidl::detail::SourceProviderType const & type, OUString const & name)
848 {
849     if (type.type
850         == unoidl::detail::SourceProviderType::TYPE_INSTANTIATED_POLYMORPHIC_STRUCT)
851     {
852         for (auto & i: type.subtypes) {
853             if (checkInstantiatedPolymorphicStructTypeArgument(i, name)
854                 || i.getName() == name) // no need to worry about typedef
855             {
856                 return true;
857             }
858         }
859     }
860     return false;
861 }
862 
annotations(bool deprecated)863 std::vector<OUString> annotations(bool deprecated) {
864     std::vector<OUString> ann;
865     if (deprecated) {
866         ann.push_back("deprecated");
867     }
868     return ann;
869 }
870 
871 }
872 
873 %}
874 
875 %token TOK_ELLIPSIS
876 %token TOK_COLONS
877 %token TOK_LEFTSHIFT
878 %token TOK_RIGHTSHIFT
879 
880 %token TOK_FALSE
881 %token TOK_TRUE
882 %token TOK_ANY
883 %token TOK_ATTRIBUTE
884 %token TOK_BOOLEAN
885 %token TOK_BOUND
886 %token TOK_BYTE
887 %token TOK_CHAR
888 %token TOK_CONST
889 %token TOK_CONSTANTS
890 %token TOK_CONSTRAINED
891 %token TOK_DOUBLE
892 %token TOK_ENUM
893 %token TOK_EXCEPTION
894 %token TOK_FLOAT
895 %token TOK_GET
896 %token TOK_HYPER
897 %token TOK_IN
898 %token TOK_INOUT
899 %token TOK_INTERFACE
900 %token TOK_LONG
901 %token TOK_MAYBEAMBIGUOUS
902 %token TOK_MAYBEDEFAULT
903 %token TOK_MAYBEVOID
904 %token TOK_MODULE
905 %token TOK_OPTIONAL
906 %token TOK_OUT
907 %token TOK_PROPERTY
908 %token TOK_PUBLISHED
909 %token TOK_RAISES
910 %token TOK_READONLY
911 %token TOK_REMOVABLE
912 %token TOK_SEQUENCE
913 %token TOK_SERVICE
914 %token TOK_SET
915 %token TOK_SHORT
916 %token TOK_SINGLETON
917 %token TOK_STRING
918 %token TOK_STRUCT
919 %token TOK_TRANSIENT
920 %token TOK_TYPE
921 %token TOK_TYPEDEF
922 %token TOK_UNSIGNED
923 %token TOK_VOID
924 
925 %token<sval> TOK_IDENTIFIER
926 %token<ival> TOK_INTEGER
927 %token<fval> TOK_FLOATING
928 
929 %token TOK_DEPRECATED
930 
931 %token TOK_ERROR
932 
933 %type<sval> identifier name singleInheritance singleInheritance_opt
934 %type<bval> ctors_opt deprecated_opt ellipsis_opt published_opt
935 %type<decls> attributeAccessDecl attributeAccessDecls
936 %type<dir> direction
937 %type<excns> exceptionSpec exceptionSpec_opt exceptions
938 %type<flags> flag flagSection flagSection_opt flags
939 %type<expr> addExpr andExpr expr multExpr orExpr primaryExpr shiftExpr unaryExpr
940   xorExpr
941 %type<type> type
942 %type<types> typeArguments
943 
944 %initial-action { yylloc = 1; }
945 
946 %%
947 
948 definitions:
949   definitions definition
950 | /* empty */
951 ;
952 
953 definition:
954   moduleDecl
955 | enumDefn
956 | plainStructDefn
957 | polymorphicStructTemplateDefn
958 | exceptionDefn
959 | interfaceDefn
960 | typedefDefn
961 | constantGroupDefn
962 | singleInterfaceBasedServiceDefn
963 | accumulationBasedServiceDefn
964 | interfaceBasedSingletonDefn
965 | serviceBasedSingletonDefn
966 | interfaceDecl
967 ;
968 
969 moduleDecl:
970   TOK_MODULE identifier
971   {
972       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
973       OUString name(convertToFullName(data, $2));
974       data->modules.push_back(name);
975       std::pair<std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator, bool> p(
976           data->entities.emplace(
977                   name,
978                   unoidl::detail::SourceProviderEntity(
979                       unoidl::detail::SourceProviderEntity::KIND_MODULE)));
980       if (!p.second
981           && (p.first->second.kind
982               != unoidl::detail::SourceProviderEntity::KIND_MODULE))
983       {
984           error(@2, yyscanner, "multiple entities named " + name);
985           YYERROR;
986       }
987   }
988   '{' definitions '}' ';' { yyget_extra(yyscanner)->modules.pop_back(); }
989 ;
990 
991 enumDefn:
992   deprecated_opt published_opt TOK_ENUM identifier
993   {
994       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
995       data->publishedContext = $2;
996       convertToCurrentName(data, $4);
997       if (!data->entities.emplace(
998                   data->currentName,
999                   unoidl::detail::SourceProviderEntity(
1000                       new unoidl::detail::SourceProviderEnumTypeEntityPad(
1001                           $2))).
1002           second)
1003       {
1004           error(@4, yyscanner, "multiple entities named " + data->currentName);
1005           YYERROR;
1006       }
1007   }
1008   '{' enumMembers '}' ';'
1009   {
1010       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1011       unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
1012       unoidl::detail::SourceProviderEnumTypeEntityPad * pad =
1013           dynamic_cast<unoidl::detail::SourceProviderEnumTypeEntityPad *>(
1014               ent->pad.get());
1015       assert(pad != nullptr);
1016       ent->entity = new unoidl::EnumTypeEntity(
1017           pad->isPublished(), pad->members, annotations($1));
1018       ent->pad.clear();
1019       clearCurrentState(data);
1020   }
1021 ;
1022 
1023 enumMembers:
1024 | enumMembers ',' enumMember
1025 | enumMember
1026 ;
1027 
1028 enumMember:
1029   deprecated_opt identifier
1030   {
1031       OUString id(convertName($2));
1032       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1033       rtl::Reference<unoidl::detail::SourceProviderEnumTypeEntityPad> pad(
1034           getCurrentPad<unoidl::detail::SourceProviderEnumTypeEntityPad>(data));
1035       sal_Int32 v;
1036       if (pad->members.empty()) {
1037           v = 0;
1038       } else {
1039           v = pad->members.back().value;
1040           if (v == SAL_MAX_INT32) {
1041               error(
1042                   @2, yyscanner,
1043                   ("enum " + data->currentName + " member " + id
1044                    + " would have out-of-range value 2^31"));
1045               YYERROR;
1046           }
1047           ++v;
1048       }
1049       pad->members.emplace_back(id, v, annotations($1));
1050   }
1051 | deprecated_opt identifier '=' expr
1052   {
1053       OUString id(convertName($2));
1054       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1055       rtl::Reference<unoidl::detail::SourceProviderEnumTypeEntityPad> pad(
1056           getCurrentPad<unoidl::detail::SourceProviderEnumTypeEntityPad>(data));
1057       sal_Int32 v;
1058       switch ($4.type) {
1059       case unoidl::detail::SourceProviderExpr::TYPE_INT:
1060           if ($4.ival < SAL_MIN_INT32 || $4.ival > SAL_MAX_INT32) {
1061               error(
1062                   @4, yyscanner,
1063                   ("out-of-range enum " + data->currentName + " member " + id
1064                    + " value " + OUString::number($4.ival)));
1065               YYERROR;
1066           }
1067           v = static_cast<sal_Int32>($4.ival);
1068           break;
1069       case unoidl::detail::SourceProviderExpr::TYPE_UINT:
1070           if ($4.uval > SAL_MAX_INT32) {
1071               error(
1072                   @4, yyscanner,
1073                   ("out-of-range enum " + data->currentName + " member " + id
1074                    + " value " + OUString::number($4.uval)));
1075               YYERROR;
1076           }
1077           v = static_cast<sal_Int32>($4.uval);
1078           break;
1079       default:
1080           error(
1081               @4, yyscanner,
1082               ("non-integer enum " + data->currentName + " member " + id
1083                + " value"));
1084           YYERROR;
1085           break;
1086       }
1087       pad->members.emplace_back(id, v, annotations($1));
1088   }
1089 ;
1090 
1091 plainStructDefn:
1092   deprecated_opt published_opt TOK_STRUCT identifier singleInheritance_opt
1093   {
1094       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1095       data->publishedContext = $2;
1096       convertToCurrentName(data, $4);
1097       OUString baseName;
1098       rtl::Reference<unoidl::PlainStructTypeEntity> baseEnt;
1099       if ($5 != nullptr) {
1100           baseName = convertName($5);
1101           unoidl::detail::SourceProviderEntity const * p;
1102           if (findEntity(
1103                   @5, yyscanner, data, false, &baseName, &p, nullptr, nullptr)
1104               == FOUND_ERROR)
1105           {
1106               YYERROR;
1107           }
1108           if (p == nullptr || !p->entity.is()
1109               || p->entity->getSort() != unoidl::Entity::SORT_PLAIN_STRUCT_TYPE)
1110           {
1111               error(
1112                   @5, yyscanner,
1113                   ("plain struct type " + data->currentName + " base "
1114                    + baseName
1115                    + " does not resolve to an existing plain struct type"));
1116               YYERROR;
1117           }
1118           baseEnt = static_cast<unoidl::PlainStructTypeEntity *>(
1119               p->entity.get());
1120           if ($2 && !baseEnt->isPublished()) {
1121               error(
1122                   @5, yyscanner,
1123                   ("published plain struct type " + data->currentName + " base "
1124                    + baseName + " is unpublished"));
1125               YYERROR;
1126           }
1127       }
1128       if (!data->entities.emplace(
1129                   data->currentName,
1130                   unoidl::detail::SourceProviderEntity(
1131                       new unoidl::detail::SourceProviderPlainStructTypeEntityPad(
1132                           $2, baseName, baseEnt))).
1133           second)
1134       {
1135           error(@4, yyscanner, "multiple entities named " + data->currentName);
1136           YYERROR;
1137       }
1138   }
1139   '{' structMembers '}' ';'
1140   {
1141       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1142       unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
1143       unoidl::detail::SourceProviderPlainStructTypeEntityPad * pad =
1144           dynamic_cast<
1145               unoidl::detail::SourceProviderPlainStructTypeEntityPad *>(
1146                   ent->pad.get());
1147       assert(pad != nullptr);
1148       ent->entity = new unoidl::PlainStructTypeEntity(
1149           pad->isPublished(), pad->baseName, pad->members, annotations($1));
1150       ent->pad.clear();
1151       clearCurrentState(data);
1152   }
1153 ;
1154 
1155 polymorphicStructTemplateDefn:
1156   deprecated_opt published_opt TOK_STRUCT identifier '<'
1157   {
1158       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1159       data->publishedContext = $2;
1160       convertToCurrentName(data, $4);
1161       if (!data->entities.emplace(
1162                   data->currentName,
1163                   unoidl::detail::SourceProviderEntity(
1164                       new unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad(
1165                           $2))).
1166           second)
1167       {
1168           error(@4, yyscanner, "multiple entities named " + data->currentName);
1169           YYERROR;
1170       }
1171   }
1172   typeParameters '>' '{' structMembers '}' ';'
1173   {
1174       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1175       unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
1176       unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *
1177           pad = dynamic_cast<
1178               unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
1179                   ent->pad.get());
1180       assert(pad != nullptr);
1181       ent->entity = new unoidl::PolymorphicStructTypeTemplateEntity(
1182           pad->isPublished(), pad->typeParameters, pad->members,
1183           annotations($1));
1184       ent->pad.clear();
1185       clearCurrentState(data);
1186   }
1187 ;
1188 
1189 typeParameters:
1190   typeParameters ',' identifier
1191   {
1192       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1193       rtl::Reference<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad>
1194           pad(getCurrentPad<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad>(
1195                   data));
1196       OUString id(convertName($3));
1197       if (std::find(pad->typeParameters.begin(), pad->typeParameters.end(), id)
1198           != pad->typeParameters.end())
1199       {
1200           error(
1201               @3, yyscanner,
1202               ("polymorphic struct type template " + data->currentName
1203                + " type parameter " + id
1204                + " has same identifier as another type parameter"));
1205           YYERROR;
1206       }
1207       pad->typeParameters.push_back(id);
1208   }
1209 | identifier
1210   {
1211       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1212       rtl::Reference<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad>
1213           pad(getCurrentPad<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad>(
1214                   data));
1215       OUString id(convertName($1));
1216       assert(pad->typeParameters.empty());
1217       pad->typeParameters.push_back(id);
1218   }
1219 ;
1220 
1221 exceptionDefn:
1222   deprecated_opt published_opt TOK_EXCEPTION identifier singleInheritance_opt
1223   {
1224       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1225       data->publishedContext = $2;
1226       convertToCurrentName(data, $4);
1227       OUString baseName;
1228       rtl::Reference<unoidl::ExceptionTypeEntity> baseEnt;
1229       if ($5 != nullptr) {
1230           baseName = convertName($5);
1231           unoidl::detail::SourceProviderEntity const * p;
1232           if (findEntity(
1233                   @5, yyscanner, data, false, &baseName, &p, nullptr, nullptr)
1234               == FOUND_ERROR)
1235           {
1236               YYERROR;
1237           }
1238           if (p == nullptr || !p->entity.is()
1239               || p->entity->getSort() != unoidl::Entity::SORT_EXCEPTION_TYPE)
1240           {
1241               error(
1242                   @5, yyscanner,
1243                   ("exception type " + data->currentName + " base " + baseName
1244                    + " does not resolve to an existing exception type"));
1245               YYERROR;
1246           }
1247           baseEnt = static_cast<unoidl::ExceptionTypeEntity *>(
1248               p->entity.get());
1249           if ($2 && !baseEnt->isPublished()) {
1250               error(
1251                   @5, yyscanner,
1252                   ("published exception type " + data->currentName + " base "
1253                    + baseName + " is unpublished"));
1254               YYERROR;
1255           }
1256       }
1257       if (!data->entities.emplace(
1258                   data->currentName,
1259                   unoidl::detail::SourceProviderEntity(
1260                       new unoidl::detail::SourceProviderExceptionTypeEntityPad(
1261                           $2, baseName, baseEnt))).
1262           second)
1263       {
1264           error(@4, yyscanner, "multiple entities named " + data->currentName);
1265           YYERROR;
1266       }
1267   }
1268  '{' structMembers '}' ';'
1269   {
1270       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1271       unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
1272       unoidl::detail::SourceProviderExceptionTypeEntityPad * pad =
1273           dynamic_cast<unoidl::detail::SourceProviderExceptionTypeEntityPad *>(
1274               ent->pad.get());
1275       assert(pad != nullptr);
1276       ent->entity = new unoidl::ExceptionTypeEntity(
1277           pad->isPublished(), pad->baseName, pad->members, annotations($1));
1278       ent->pad.clear();
1279       clearCurrentState(data);
1280   }
1281 ;
1282 
1283 structMembers:
1284   structMembers structMember
1285 | /* empty */
1286 ;
1287 
1288 structMember:
1289   deprecated_opt type identifier ';'
1290   {
1291       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1292       unoidl::detail::SourceProviderType t(*$2);
1293       delete $2;
1294       OUString id(convertName($3));
1295       switch (t.type) {
1296       case unoidl::detail::SourceProviderType::TYPE_VOID:
1297       case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
1298           error(
1299               @2, yyscanner,
1300               ("illegal struct/exception type " + data->currentName
1301                + " direct member " + id + " type"));
1302           YYERROR;
1303           break;
1304       default:
1305           break;
1306       }
1307       if (t.type != unoidl::detail::SourceProviderType::TYPE_PARAMETER
1308           && t.getName() == data->currentName) // no need to worry about typedef
1309       {
1310           error(
1311               @2, yyscanner,
1312               ("struct/exception type " + data->currentName + " direct member "
1313                + id + " has same type as the type itself"));
1314           YYERROR;
1315       }
1316       if (checkInstantiatedPolymorphicStructTypeArgument(t, data->currentName))
1317       {
1318           error(
1319               @2, yyscanner,
1320               ("struct/exception type " + data->currentName + " direct member "
1321                + id
1322                + (" has instantiated polymorphic struct type that uses the type"
1323                   " itself as an argument")));
1324           YYERROR;
1325       }
1326       if (nameHasSameIdentifierAs(data->currentName, id)) {
1327           error(
1328               @3, yyscanner,
1329               ("struct/exception type " + data->currentName + " direct member "
1330                + id + " has same unqualified identifier as the type itself"));
1331           YYERROR;
1332       }
1333       unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
1334       unoidl::detail::SourceProviderPlainStructTypeEntityPad * p1 =
1335           dynamic_cast<unoidl::detail::SourceProviderPlainStructTypeEntityPad *>(
1336               ent->pad.get());
1337       if (p1 != nullptr) {
1338           for (const auto & i: p1->members) {
1339               if (id == i.name) {
1340                   error(
1341                       @3, yyscanner,
1342                       ("plain struct type " + data->currentName
1343                        + " direct member " + id
1344                        + " has same identifier as another direct member"));
1345                   YYERROR;
1346               }
1347           }
1348           if (p1->baseEntity.is()) {
1349               OUString baseName(p1->baseName);
1350               for (auto baseEnt(p1->baseEntity);;) {
1351                   if (nameHasSameIdentifierAs(baseName, id)) {
1352                       error(
1353                           @3, yyscanner,
1354                           ("plain struct type " + data->currentName
1355                            + " direct member " + id
1356                            + " has same unqalified identifier as base "
1357                            + baseName));
1358                       YYERROR;
1359                   }
1360                   for (auto & i: baseEnt->getDirectMembers()) {
1361                       if (id == i.name) {
1362                           error(
1363                               @3, yyscanner,
1364                               ("plain struct type " + data->currentName
1365                                + " direct member " + id
1366                                + " has same identifier as a member of base "
1367                                + baseName));
1368                           YYERROR;
1369                       }
1370                   }
1371                   baseName = baseEnt->getDirectBase();
1372                   if (baseName.isEmpty()) {
1373                       break;
1374                   }
1375                   unoidl::detail::SourceProviderEntity const * p;
1376                   if (findEntity(
1377                           @2, yyscanner, data, false, &baseName, &p, nullptr,
1378                           nullptr)
1379                       == FOUND_ERROR)
1380                   {
1381                       YYERROR;
1382                   }
1383                   if (p == nullptr || !p->entity.is()
1384                       || (p->entity->getSort()
1385                           != unoidl::Entity::SORT_PLAIN_STRUCT_TYPE))
1386                   {
1387                       error(
1388                           @2, yyscanner,
1389                           ("inconsistent type manager: plain struct type "
1390                            + data->currentName + " base " + baseName
1391                            + (" does not resolve to an existing plain struct"
1392                               " type")));
1393                       YYERROR;
1394                   }
1395                   baseEnt = static_cast<unoidl::PlainStructTypeEntity *>(
1396                       p->entity.get());
1397               }
1398           }
1399           p1->members.emplace_back(id, t.getName(), annotations($1));
1400       } else {
1401           unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *
1402               p2 = dynamic_cast<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
1403                   ent->pad.get());
1404           if (p2 != nullptr) {
1405               for (const auto & i: p2->members) {
1406                   if (id == i.name) {
1407                       error(
1408                           @3, yyscanner,
1409                           ("polymorphic struct type template "
1410                            + data->currentName + " direct member " + id
1411                            + " has same identifier as another direct member"));
1412                       YYERROR;
1413                   }
1414               }
1415               p2->members.emplace_back(
1416                   id, t.getName(),
1417                   t.type == unoidl::detail::SourceProviderType::TYPE_PARAMETER,
1418                   annotations($1));
1419           } else {
1420               unoidl::detail::SourceProviderExceptionTypeEntityPad * p3
1421                   = dynamic_cast<unoidl::detail::SourceProviderExceptionTypeEntityPad *>(
1422                       ent->pad.get());
1423               assert(p3 != nullptr);
1424               for (const auto & i: p3->members) {
1425                   if (id == i.name) {
1426                       error(
1427                           @3, yyscanner,
1428                           ("exception type " + data->currentName
1429                            + " direct member " + id
1430                            + " has same identifier as another direct member"));
1431                       YYERROR;
1432                   }
1433               }
1434               if (p3->baseEntity.is()) {
1435                   OUString baseName(p3->baseName);
1436                   for (auto baseEnt(p3->baseEntity);;) {
1437                       if (nameHasSameIdentifierAs(baseName, id)) {
1438                           error(
1439                               @3, yyscanner,
1440                               ("exception type " + data->currentName
1441                                + " direct member " + id
1442                                + " has same unqalified identifier as base "
1443                                + baseName));
1444                           YYERROR;
1445                       }
1446                       for (auto & i: baseEnt->getDirectMembers()) {
1447                           if (id == i.name) {
1448                               error(
1449                                   @3, yyscanner,
1450                                   ("exception type " + data->currentName
1451                                    + " direct member " + id
1452                                    + " has same identifier as a member of base "
1453                                    + baseName));
1454                               YYERROR;
1455                           }
1456                       }
1457                       baseName = baseEnt->getDirectBase();
1458                       if (baseName.isEmpty()) {
1459                           break;
1460                       }
1461                       unoidl::detail::SourceProviderEntity const * p;
1462                       if (findEntity(
1463                               @2, yyscanner, data, false, &baseName, &p,
1464                               nullptr, nullptr)
1465                           == FOUND_ERROR)
1466                       {
1467                           YYERROR;
1468                       }
1469                       if (p == nullptr || !p->entity.is()
1470                           || (p->entity->getSort()
1471                               != unoidl::Entity::SORT_EXCEPTION_TYPE))
1472                       {
1473                           error(
1474                               @2, yyscanner,
1475                               ("inconsistent type manager: exception type "
1476                                + data->currentName + " base " + baseName
1477                                + (" does not resolve to an existing exception"
1478                                   " type")));
1479                           YYERROR;
1480                       }
1481                       baseEnt = static_cast<unoidl::ExceptionTypeEntity *>(
1482                           p->entity.get());
1483                   }
1484               }
1485               p3->members.emplace_back(id, t.getName(), annotations($1));
1486           }
1487       }
1488   }
1489 ;
1490 
1491 interfaceDefn:
1492   deprecated_opt published_opt TOK_INTERFACE identifier singleInheritance_opt
1493   {
1494       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1495       data->publishedContext = $2;
1496       convertToCurrentName(data, $4);
1497       OUString baseName;
1498       rtl::Reference<unoidl::InterfaceTypeEntity> baseEnt;
1499       if ($5 != nullptr) {
1500           baseName = convertName($5);
1501           unoidl::detail::SourceProviderEntity const * p;
1502           if (findEntity(
1503                   @5, yyscanner, data, true, &baseName, &p, nullptr, nullptr)
1504               == FOUND_ERROR)
1505           {
1506               YYERROR;
1507           }
1508           if (p == nullptr || !p->entity.is()
1509               || p->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
1510           {
1511               error(
1512                   @5, yyscanner,
1513                   ("interface type " + data->currentName + " direct base "
1514                    + baseName
1515                    + " does not resolve to an existing interface type"));
1516               YYERROR;
1517           }
1518           baseEnt = static_cast<unoidl::InterfaceTypeEntity *>(p->entity.get());
1519           if ($2 && !baseEnt->isPublished()) {
1520               error(
1521                   @5, yyscanner,
1522                   ("published interface type " + data->currentName
1523                    + " direct base " + baseName + " is unpublished"));
1524               YYERROR;
1525           }
1526       }
1527       std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator i(
1528           data->entities.find(data->currentName));
1529       if (i != data->entities.end()) {
1530           switch (i->second.kind) {
1531           case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
1532               break;
1533           case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
1534               if (!$2) {
1535                   error(
1536                       @4, yyscanner,
1537                       ("unpublished interface type " + data->currentName
1538                        + " has been declared published"));
1539                   YYERROR;
1540               }
1541               break;
1542           default:
1543               error(
1544                   @4, yyscanner,
1545                   "multiple entities named " + data->currentName);
1546               YYERROR;
1547               break;
1548           }
1549       }
1550       rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad> pad(
1551           new unoidl::detail::SourceProviderInterfaceTypeEntityPad(
1552               $2, baseEnt.is()));
1553       if (baseEnt.is()
1554           && !pad->addDirectBase(
1555               @4, yyscanner, data,
1556               unoidl::detail::SourceProviderInterfaceTypeEntityPad::DirectBase(
1557                   baseName, baseEnt, std::vector<OUString>()),
1558               false))
1559       {
1560           YYERROR;
1561       }
1562       data->entities[data->currentName] = unoidl::detail::SourceProviderEntity(
1563           pad);
1564   }
1565   '{' interfaceMembers '}' ';'
1566   {
1567       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1568       unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
1569       unoidl::detail::SourceProviderInterfaceTypeEntityPad * pad =
1570           dynamic_cast<unoidl::detail::SourceProviderInterfaceTypeEntityPad *>(
1571               ent->pad.get());
1572       assert(pad != nullptr);
1573       if (pad->directMandatoryBases.empty()
1574           && data->currentName != "com.sun.star.uno.XInterface")
1575       {
1576           OUString base(".com.sun.star.uno.XInterface");
1577           unoidl::detail::SourceProviderEntity const * p;
1578           if (findEntity(@4, yyscanner, data, true, &base, &p, nullptr, nullptr)
1579               == FOUND_ERROR)
1580           {
1581               YYERROR;
1582           }
1583           if (p == nullptr || !p->entity.is()
1584               || p->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
1585           {
1586               error(
1587                   @3, yyscanner,
1588                   ("interface type " + data->currentName
1589                    + " implicit direct base " + base
1590                    + " does not resolve to an existing interface type"));
1591               YYERROR;
1592           }
1593           if (!pad->addDirectBase(
1594                   @3, yyscanner, data,
1595                   unoidl::detail::SourceProviderInterfaceTypeEntityPad::DirectBase(
1596                       base,
1597                       static_cast<unoidl::InterfaceTypeEntity *>(
1598                           p->entity.get()),
1599                       std::vector<OUString>()),
1600                   false))
1601           {
1602               YYERROR;
1603           }
1604       }
1605       std::vector<unoidl::AnnotatedReference> mbases;
1606       for (auto & i: pad->directMandatoryBases) {
1607           mbases.emplace_back(i.name, i.annotations);
1608       }
1609       std::vector<unoidl::AnnotatedReference> obases;
1610       for (auto & i: pad->directOptionalBases) {
1611           obases.emplace_back(i.name, i.annotations);
1612       }
1613       ent->entity = new unoidl::InterfaceTypeEntity(
1614           pad->isPublished(), mbases, obases, pad->directAttributes,
1615           pad->directMethods, annotations($1));
1616       ent->pad.clear();
1617       clearCurrentState(data);
1618   }
1619 ;
1620 
1621 interfaceMembers:
1622  interfaceMembers interfaceMember
1623 | /* empty */
1624 ;
1625 
1626 interfaceMember:
1627   interfaceBase
1628 | interfaceAttribute
1629 | interfaceMethod
1630 ;
1631 
1632 interfaceBase:
1633   deprecated_opt flagSection_opt TOK_INTERFACE name ';'
1634   {
1635       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1636       OUString name(convertName($4));
1637       rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad> pad(
1638           getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
1639               data));
1640       if (pad->singleBase) {
1641           error(
1642               @3, yyscanner,
1643               "single-inheritance interface cannot have additional bases");
1644           YYERROR;
1645       }
1646       if (($2 & ~unoidl::detail::FLAG_OPTIONAL) != 0) {
1647           error(
1648               @2, yyscanner,
1649               "interface base can only be flagged as [optional]");
1650           YYERROR;
1651       }
1652       bool opt = ($2 & unoidl::detail::FLAG_OPTIONAL) != 0;
1653       OUString orgName(name);
1654       unoidl::detail::SourceProviderEntity const * p;
1655       bool typedefed = false;
1656       if (findEntity(@4, yyscanner, data, true, &name, &p, &typedefed, nullptr)
1657           == FOUND_ERROR)
1658       {
1659           YYERROR;
1660       }
1661       if (p == nullptr || !p->entity.is()
1662           || p->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
1663       {
1664           error(
1665               @4, yyscanner,
1666               ("interface type " + data->currentName + " direct base " + name
1667                + " does not resolve to an existing interface type"));
1668           YYERROR;
1669       }
1670       if (typedefed) {
1671           error(
1672               @4, yyscanner,
1673               ("interface type " + data->currentName + " direct base " + orgName
1674                + " is a typedef"));
1675           YYERROR;
1676       }
1677       rtl::Reference<unoidl::InterfaceTypeEntity> ent(
1678           static_cast<unoidl::InterfaceTypeEntity *>(p->entity.get()));
1679       if (data->publishedContext && !ent->isPublished()) {
1680           error(
1681               @4, yyscanner,
1682               ("published interface type " + data->currentName + " direct base "
1683                + name + " is unpublished"));
1684           YYERROR;
1685       }
1686       if (!pad->addDirectBase(
1687               @4, yyscanner, data,
1688               unoidl::detail::SourceProviderInterfaceTypeEntityPad::DirectBase(
1689                   name, ent, annotations($1)),
1690               opt))
1691       {
1692           YYERROR;
1693       }
1694   }
1695 ;
1696 
1697 interfaceAttribute:
1698   deprecated_opt flagSection type identifier
1699   {
1700       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1701       unoidl::detail::SourceProviderType t(*$3);
1702       delete $3;
1703       OUString id(convertName($4));
1704       if (($2 & unoidl::detail::FLAG_ATTRIBUTE) == 0) {
1705           error(
1706               @2, yyscanner,
1707               "interface attribute must be flagged as [attribute]");
1708           YYERROR;
1709       }
1710       if (($2
1711            & ~(unoidl::detail::FLAG_ATTRIBUTE | unoidl::detail::FLAG_BOUND
1712                | unoidl::detail::FLAG_READONLY))
1713           != 0)
1714       {
1715           error(
1716               @2, yyscanner,
1717               ("interface attribute can only be flagged as [attribute,"
1718                " bound, readonly]"));
1719           YYERROR;
1720       }
1721       switch (t.type) {
1722       case unoidl::detail::SourceProviderType::TYPE_VOID:
1723       case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
1724           error(
1725               @3, yyscanner,
1726               ("illegal interface type " + data->currentName
1727                + " direct attribute " + id + " type"));
1728           YYERROR;
1729           break;
1730       default:
1731           break;
1732       }
1733       rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad> pad(
1734           getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
1735               data));
1736       if (!pad->addDirectMember(@4, yyscanner, data, id)) {
1737           YYERROR;
1738       }
1739       pad->directAttributes.emplace_back(
1740           id, t.getName(), ($2 & unoidl::detail::FLAG_BOUND) != 0,
1741           ($2 & unoidl::detail::FLAG_READONLY) != 0,
1742           std::vector<OUString>(), std::vector<OUString>(), annotations($1));
1743   }
1744   attributeAccessDecls_opt ';'
1745 ;
1746 
1747 attributeAccessDecls_opt:
1748   '{' attributeAccessDecls '}'
1749 | /* empty */
1750 ;
1751 
1752 attributeAccessDecls:
1753   attributeAccessDecls attributeAccessDecl
1754   {
1755       if (($1 & $2) != 0) {
1756           error(
1757               @2, yyscanner, "duplicate get/set attribute access declaration");
1758           YYERROR;
1759       }
1760       $$ = unoidl::detail::SourceProviderAccessDecls($1 | $2);
1761   }
1762 | /* empty */ { $$ = unoidl::detail::SourceProviderAccessDecls(0); }
1763 ;
1764 
1765 attributeAccessDecl:
1766   TOK_GET exceptionSpec ';'
1767   {
1768       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1769       rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
1770           pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
1771               data));
1772       assert(!pad->directAttributes.empty());
1773       pad->directAttributes.back().getExceptions = *$2;
1774       delete $2;
1775       $$ = unoidl::detail::ACCESS_DECL_GET;
1776   }
1777 | TOK_SET exceptionSpec ';'
1778   {
1779       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1780       rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
1781           pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
1782               data));
1783       assert(!pad->directAttributes.empty());
1784       pad->directAttributes.back().setExceptions = *$2;
1785       delete $2;
1786       if (pad->directAttributes.back().readOnly) {
1787           error(
1788               @1, yyscanner,
1789               ("interface type " + data->currentName
1790                + " direct read-only attribute "
1791                + pad->directAttributes.back().name
1792                + " cannot have set access declaration"));
1793           YYERROR;
1794       }
1795       $$ = unoidl::detail::ACCESS_DECL_SET;
1796   }
1797 ;
1798 
1799 interfaceMethod:
1800   deprecated_opt type identifier
1801   {
1802       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1803       unoidl::detail::SourceProviderType t(*$2);
1804       delete $2;
1805       OUString id(convertName($3));
1806       if (t.type == unoidl::detail::SourceProviderType::TYPE_EXCEPTION) {
1807           error(
1808               @3, yyscanner,
1809               ("illegal interface type " + data->currentName
1810                + " direct method " + id + " return type"));
1811           YYERROR;
1812       }
1813       rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad> pad(
1814           getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
1815               data));
1816       if (!pad->addDirectMember(@3, yyscanner, data, id)) {
1817           YYERROR;
1818       }
1819       pad->directMethods.emplace_back(
1820           id, t.getName(),
1821           std::vector<unoidl::InterfaceTypeEntity::Method::Parameter>(),
1822           std::vector<OUString>(), annotations($1));
1823   }
1824   '(' methodParams_opt ')' exceptionSpec_opt ';'
1825   {
1826       if ($8 != nullptr) {
1827           unoidl::detail::SourceProviderScannerData * data
1828               = yyget_extra(yyscanner);
1829           rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
1830               pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
1831                   data));
1832           assert(!pad->directMethods.empty());
1833           pad->directMethods.back().exceptions = *$8;
1834           delete $8;
1835       }
1836   }
1837 ;
1838 
1839 methodParams_opt:
1840   methodParams
1841 | /* empty */
1842 ;
1843 
1844 methodParams:
1845   methodParams ',' methodParam
1846 | methodParam
1847 ;
1848 
1849 methodParam:
1850   '[' direction ']' type identifier
1851   {
1852       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1853       unoidl::detail::SourceProviderType t(*$4);
1854       delete $4;
1855       OUString id(convertName($5));
1856       rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
1857           pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
1858               data));
1859       assert(!pad->directMethods.empty());
1860       switch (t.type) {
1861       case unoidl::detail::SourceProviderType::TYPE_VOID:
1862       case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
1863           error(
1864               @4, yyscanner,
1865               ("illegal interface type " + data->currentName
1866                + " direct method " + pad->directMethods.back().name
1867                + " parameter " + id + " type"));
1868           YYERROR;
1869           break;
1870       default:
1871           break;
1872       }
1873       for (const auto & i: pad->directMethods.back().parameters) {
1874           if (id == i.name) {
1875               error(
1876                   @5, yyscanner,
1877                   ("interface type " + data->currentName + " direct method "
1878                    + pad->directMethods.back().name + " parameter " + id
1879                    + " has same identifier as another parameter"));
1880               YYERROR;
1881           }
1882       }
1883       pad->directMethods.back().parameters.emplace_back(id, t.getName(), $2);
1884   }
1885 ;
1886 
1887 direction:
1888   TOK_IN { $$ = unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN; }
1889 | TOK_OUT
1890   { $$ = unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT; }
1891 | TOK_INOUT
1892   { $$ = unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT; }
1893 ;
1894 
1895 typedefDefn:
1896   deprecated_opt published_opt TOK_TYPEDEF type identifier ';'
1897   {
1898       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1899       data->publishedContext = $2;
1900       unoidl::detail::SourceProviderType t(*$4);
1901       delete $4;
1902       OUString name(convertToFullName(data, $5));
1903       // There is no good reason to forbid typedefs to VOID, to instantiated
1904       // polymorphic struct types, and to exception types, but some old client
1905       // code of registry data expects this typedef restriction (like the
1906       // assert(false) default in handleTypedef in
1907       // codemaker/source/javamaker/javatype.cxx), so forbid them for now:
1908       switch (t.type) {
1909       case unoidl::detail::SourceProviderType::TYPE_VOID:
1910       case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
1911       case unoidl::detail::SourceProviderType::TYPE_INSTANTIATED_POLYMORPHIC_STRUCT:
1912           error(@4, yyscanner, "bad typedef type");
1913           YYERROR;
1914           break;
1915       case unoidl::detail::SourceProviderType::TYPE_ENUM:
1916       case unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT:
1917       case unoidl::detail::SourceProviderType::TYPE_INTERFACE:
1918           if ($2) {
1919               bool unpub = false;
1920               switch (t.entity->kind) {
1921               case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
1922                   unpub = true;
1923                   break;
1924               case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
1925                   break;
1926               case unoidl::detail::SourceProviderEntity::KIND_MODULE:
1927                   O3TL_UNREACHABLE;
1928               default:
1929                   assert(t.entity->entity.is() || t.entity->pad.is());
1930                   unpub
1931                       = !(t.entity->entity.is()
1932                           ? static_cast<unoidl::PublishableEntity *>(
1933                               t.entity->entity.get())->isPublished()
1934                           : t.entity->pad->isPublished());
1935                   break;
1936               }
1937               if (unpub) {
1938                   error(
1939                       @4, yyscanner,
1940                       "published typedef " + name + " type is unpublished");
1941                   YYERROR;
1942               }
1943           }
1944           break;
1945       case unoidl::detail::SourceProviderType::TYPE_PARAMETER:
1946           O3TL_UNREACHABLE;
1947       default:
1948           break;
1949       }
1950       if (!data->entities.emplace(
1951                   name,
1952                   unoidl::detail::SourceProviderEntity(
1953                       unoidl::detail::SourceProviderEntity::KIND_LOCAL,
1954                       new unoidl::TypedefEntity(
1955                           $2, t.getName(), annotations($1)))).
1956           second)
1957       {
1958           error(@5, yyscanner, "multiple entities named " + name);
1959           YYERROR;
1960       }
1961       clearCurrentState(data);
1962   }
1963 ;
1964 
1965 constantGroupDefn:
1966   deprecated_opt published_opt TOK_CONSTANTS identifier
1967   {
1968       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1969       data->publishedContext = $2;
1970       convertToCurrentName(data, $4);
1971       if (!data->entities.emplace(
1972                   data->currentName,
1973                   unoidl::detail::SourceProviderEntity(
1974                       new unoidl::detail::SourceProviderConstantGroupEntityPad(
1975                           $2))).
1976           second)
1977       {
1978           error(@4, yyscanner, "multiple entities named " + data->currentName);
1979           YYERROR;
1980       }
1981   }
1982   '{' constants '}' ';'
1983   {
1984       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1985       unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
1986       unoidl::detail::SourceProviderConstantGroupEntityPad * pad =
1987           dynamic_cast<unoidl::detail::SourceProviderConstantGroupEntityPad *>(
1988               ent->pad.get());
1989       assert(pad != nullptr);
1990       ent->entity = new unoidl::ConstantGroupEntity(
1991           pad->isPublished(), pad->members, annotations($1));
1992       ent->pad.clear();
1993       clearCurrentState(data);
1994   }
1995 ;
1996 
1997 constants:
1998   constants constant
1999 | /* empty */
2000 ;
2001 
2002 constant:
2003   deprecated_opt TOK_CONST type identifier '=' expr ';'
2004   {
2005       OUString id(convertName($4));
2006       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2007       rtl::Reference<unoidl::detail::SourceProviderConstantGroupEntityPad> pad(
2008           getCurrentPad<unoidl::detail::SourceProviderConstantGroupEntityPad>(
2009               data));
2010       unoidl::detail::SourceProviderType t(*$3);
2011       delete $3;
2012       unoidl::ConstantValue v(false); // dummy value
2013       switch (t.type) {
2014       case unoidl::detail::SourceProviderType::TYPE_BOOLEAN:
2015           if ($6.type != unoidl::detail::SourceProviderExpr::TYPE_BOOL) {
2016               error(
2017                   @6, yyscanner,
2018                   ("bad value of boolean-typed constant " + data->currentName
2019                    + "." + id));
2020               YYERROR;
2021           }
2022           v = unoidl::ConstantValue($6.bval);
2023           break;
2024       case unoidl::detail::SourceProviderType::TYPE_BYTE:
2025           switch ($6.type) {
2026           case unoidl::detail::SourceProviderExpr::TYPE_INT:
2027               if ($6.ival < SAL_MIN_INT8 || $6.ival > SAL_MAX_INT8) {
2028                   error(
2029                       @6, yyscanner,
2030                       ("out-of-range byte-typed constant " + data->currentName
2031                        + "." + id + " value " + OUString::number($6.ival)));
2032                   YYERROR;
2033               }
2034               v = unoidl::ConstantValue(static_cast<sal_Int8>($6.ival));
2035               break;
2036           case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2037               if ($6.uval > SAL_MAX_INT8) {
2038                   error(
2039                       @6, yyscanner,
2040                       ("out-of-range byte-typed constant " + data->currentName
2041                        + "." + id + " value " + OUString::number($6.uval)));
2042                   YYERROR;
2043               }
2044               v = unoidl::ConstantValue(static_cast<sal_Int8>($6.uval));
2045               break;
2046           default:
2047               error(
2048                   @6, yyscanner,
2049                   ("bad value of byte-typed constant " + data->currentName + "."
2050                    + id));
2051               YYERROR;
2052               break;
2053           }
2054           break;
2055       case unoidl::detail::SourceProviderType::TYPE_SHORT:
2056           switch ($6.type) {
2057           case unoidl::detail::SourceProviderExpr::TYPE_INT:
2058               if ($6.ival < SAL_MIN_INT16 || $6.ival > SAL_MAX_INT16) {
2059                   error(
2060                       @6, yyscanner,
2061                       ("out-of-range short-typed constant " + data->currentName
2062                        + "." + id + " value " + OUString::number($6.ival)));
2063                   YYERROR;
2064               }
2065               v = unoidl::ConstantValue(static_cast<sal_Int16>($6.ival));
2066               break;
2067           case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2068               if ($6.uval > SAL_MAX_INT16) {
2069                   error(
2070                       @6, yyscanner,
2071                       ("out-of-range short-typed constant " + data->currentName
2072                        + "." + id + " value " + OUString::number($6.uval)));
2073                   YYERROR;
2074               }
2075               v = unoidl::ConstantValue(static_cast<sal_Int16>($6.uval));
2076               break;
2077           default:
2078               error(
2079                   @6, yyscanner,
2080                   ("bad value of short-typed constant " + data->currentName
2081                    + "." + id));
2082               YYERROR;
2083               break;
2084           }
2085           break;
2086       case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_SHORT:
2087           switch ($6.type) {
2088           case unoidl::detail::SourceProviderExpr::TYPE_INT:
2089               if ($6.ival < 0 || $6.ival > SAL_MAX_UINT16) {
2090                   error(
2091                       @6, yyscanner,
2092                       ("out-of-range unsigned-short-typed constant "
2093                        + data->currentName + "." + id + " value "
2094                        + OUString::number($6.ival)));
2095                   YYERROR;
2096               }
2097               v = unoidl::ConstantValue(static_cast<sal_uInt16>($6.ival));
2098               break;
2099           case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2100               if ($6.uval > SAL_MAX_UINT16) {
2101                   error(
2102                       @6, yyscanner,
2103                       ("out-of-range unsigned-short-typed constant "
2104                        + data->currentName + "." + id + " value "
2105                        + OUString::number($6.uval)));
2106                   YYERROR;
2107               }
2108               v = unoidl::ConstantValue(static_cast<sal_uInt16>($6.uval));
2109               break;
2110           default:
2111               error(
2112                   @6, yyscanner,
2113                   ("bad value of unsigned-short-typed constant "
2114                    + data->currentName + "." + id));
2115               YYERROR;
2116               break;
2117           }
2118           break;
2119       case unoidl::detail::SourceProviderType::TYPE_LONG:
2120           switch ($6.type) {
2121           case unoidl::detail::SourceProviderExpr::TYPE_INT:
2122               if ($6.ival < SAL_MIN_INT32 || $6.ival > SAL_MAX_INT32) {
2123                   error(
2124                       @6, yyscanner,
2125                       ("out-of-range long-typed constant " + data->currentName
2126                        + "." + id + " value " + OUString::number($6.ival)));
2127                   YYERROR;
2128               }
2129               v = unoidl::ConstantValue(static_cast<sal_Int32>($6.ival));
2130               break;
2131           case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2132               if ($6.uval > SAL_MAX_INT32) {
2133                   error(
2134                       @6, yyscanner,
2135                       ("out-of-range long-typed constant " + data->currentName
2136                        + "." + id + " value " + OUString::number($6.uval)));
2137                   YYERROR;
2138               }
2139               v = unoidl::ConstantValue(static_cast<sal_Int32>($6.uval));
2140               break;
2141           default:
2142               error(
2143                   @6, yyscanner,
2144                   ("bad value of long-typed constant " + data->currentName
2145                    + "." + id));
2146               YYERROR;
2147               break;
2148           }
2149           break;
2150       case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_LONG:
2151           switch ($6.type) {
2152           case unoidl::detail::SourceProviderExpr::TYPE_INT:
2153               if ($6.ival < 0 || $6.ival > SAL_MAX_UINT32) {
2154                   error(
2155                       @6, yyscanner,
2156                       ("out-of-range unsigned-long-typed constant "
2157                        + data->currentName + "." + id + " value "
2158                        + OUString::number($6.ival)));
2159                   YYERROR;
2160               }
2161               v = unoidl::ConstantValue(static_cast<sal_uInt32>($6.ival));
2162               break;
2163           case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2164               if ($6.uval > SAL_MAX_UINT32) {
2165                   error(
2166                       @6, yyscanner,
2167                       ("out-of-range unsigned-long-typed constant "
2168                        + data->currentName + "." + id + " value "
2169                        + OUString::number($6.uval)));
2170                   YYERROR;
2171               }
2172               v = unoidl::ConstantValue(static_cast<sal_uInt32>($6.uval));
2173               break;
2174           default:
2175               error(
2176                   @6, yyscanner,
2177                   ("bad value of unsigned-long-typed constant "
2178                    + data->currentName + "." + id));
2179               YYERROR;
2180               break;
2181           }
2182           break;
2183       case unoidl::detail::SourceProviderType::TYPE_HYPER:
2184           switch ($6.type) {
2185           case unoidl::detail::SourceProviderExpr::TYPE_INT:
2186               v = unoidl::ConstantValue($6.ival);
2187               break;
2188           case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2189               if ($6.uval > SAL_MAX_INT64) {
2190                   error(
2191                       @6, yyscanner,
2192                       ("out-of-range hyper-typed constant " + data->currentName
2193                        + "." + id + " value " + OUString::number($6.uval)));
2194                   YYERROR;
2195               }
2196               v = unoidl::ConstantValue(static_cast<sal_Int64>($6.uval));
2197               break;
2198           default:
2199               error(
2200                   @6, yyscanner,
2201                   ("bad value of hyper-typed constant " + data->currentName
2202                    + "." + id));
2203               YYERROR;
2204               break;
2205           }
2206           break;
2207       case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_HYPER:
2208           switch ($6.type) {
2209           case unoidl::detail::SourceProviderExpr::TYPE_INT:
2210               if ($6.ival < 0) {
2211                   error(
2212                       @6, yyscanner,
2213                       ("out-of-range unsigned-hyper-typed constant "
2214                        + data->currentName + "." + id + " value "
2215                        + OUString::number($6.ival)));
2216                   YYERROR;
2217               }
2218               v = unoidl::ConstantValue(static_cast<sal_uInt64>($6.ival));
2219               break;
2220           case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2221               v = unoidl::ConstantValue($6.uval);
2222               break;
2223           default:
2224               error(
2225                   @6, yyscanner,
2226                   ("bad value of unsigned-hyper-typed constant "
2227                    + data->currentName + "." + id));
2228               YYERROR;
2229               break;
2230           }
2231           break;
2232       case unoidl::detail::SourceProviderType::TYPE_FLOAT:
2233           switch ($6.type) {
2234           case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
2235               error(
2236                   @6, yyscanner,
2237                   ("bad boolean value of float-typed constant "
2238                    + data->currentName + "." + id));
2239               YYERROR;
2240               break;
2241           case unoidl::detail::SourceProviderExpr::TYPE_INT:
2242               v = unoidl::ConstantValue(static_cast<float>($6.ival));
2243               break;
2244           case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2245               v = unoidl::ConstantValue(static_cast<float>($6.uval));
2246               break;
2247           case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
2248               v = unoidl::ConstantValue(static_cast<float>($6.fval));
2249               break;
2250           }
2251           break;
2252       case unoidl::detail::SourceProviderType::TYPE_DOUBLE:
2253           switch ($6.type) {
2254           case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
2255               error(
2256                   @6, yyscanner,
2257                   ("bad boolean value of double-typed constant "
2258                    + data->currentName + "." + id));
2259               YYERROR;
2260               break;
2261           case unoidl::detail::SourceProviderExpr::TYPE_INT:
2262               v = unoidl::ConstantValue(static_cast<double>($6.ival));
2263               break;
2264           case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2265               v = unoidl::ConstantValue(static_cast<double>($6.uval));
2266               break;
2267           case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
2268               v = unoidl::ConstantValue($6.fval);
2269               break;
2270           }
2271           break;
2272       default:
2273           error(
2274               @3, yyscanner,
2275               "bad type for constant " + data->currentName + "." + id);
2276           YYERROR;
2277           break;
2278       }
2279       pad->members.emplace_back(id, v, annotations($1));
2280   }
2281 ;
2282 
2283 singleInterfaceBasedServiceDefn:
2284   deprecated_opt published_opt TOK_SERVICE identifier singleInheritance
2285   {
2286       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2287       data->publishedContext = $2;
2288       convertToCurrentName(data, $4);
2289       OUString base(convertName($5));
2290       unoidl::detail::SourceProviderEntity const * p;
2291       if (findEntity(@5, yyscanner, data, false, &base, &p, nullptr, nullptr)
2292           == FOUND_ERROR)
2293       {
2294           YYERROR;
2295       }
2296       bool ifcBase = false;
2297       bool pubBase = false;
2298       if (p != nullptr) {
2299           switch (p->kind) {
2300           case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
2301               ifcBase = true;
2302               pubBase = false;
2303               break;
2304           case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
2305               ifcBase = true;
2306               pubBase = true;
2307               break;
2308           default:
2309               if (p->entity.is()
2310                   && (p->entity->getSort()
2311                       == unoidl::Entity::SORT_INTERFACE_TYPE))
2312               {
2313                   ifcBase = true;
2314                   pubBase = static_cast<unoidl::InterfaceTypeEntity *>(
2315                       p->entity.get())->isPublished();
2316               }
2317               break;
2318           }
2319       }
2320       if (!ifcBase) {
2321           error(
2322               @5, yyscanner,
2323               ("single-interface--based service " + data->currentName + " base "
2324                + base + " does not resolve to an interface type"));
2325           YYERROR;
2326       }
2327       if ($2 && !pubBase) {
2328           error(
2329               @5, yyscanner,
2330               ("published single-interface--based service " + data->currentName
2331                + " base " + base + " is unpublished"));
2332           YYERROR;
2333       }
2334       if (!data->entities.emplace(
2335                   data->currentName,
2336                   unoidl::detail::SourceProviderEntity(
2337                       new unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad(
2338                           $2, base))).
2339           second)
2340       {
2341           error(@4, yyscanner, "multiple entities named " + data->currentName);
2342           YYERROR;
2343       }
2344   }
2345   ctors_opt ';'
2346   {
2347       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2348       unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
2349       unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad * pad =
2350           dynamic_cast<unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad *>(
2351               ent->pad.get());
2352       assert(pad != nullptr);
2353       std::vector<unoidl::SingleInterfaceBasedServiceEntity::Constructor> ctors;
2354       if ($7) {
2355           for (const auto & i: pad->constructors) {
2356               std::vector<unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter> parms;
2357               for (auto & j: i.parameters) {
2358                   parms.emplace_back(j.name, j.type.getName(), j.rest);
2359               }
2360               ctors.push_back(
2361                   unoidl::SingleInterfaceBasedServiceEntity::Constructor(
2362                       i.name, parms, i.exceptions, i.annotations));
2363           }
2364       } else {
2365           assert(pad->constructors.empty());
2366           ctors.push_back(
2367               unoidl::SingleInterfaceBasedServiceEntity::Constructor());
2368       }
2369       ent->entity = new unoidl::SingleInterfaceBasedServiceEntity(
2370           pad->isPublished(), pad->base, ctors, annotations($1));
2371       ent->pad.clear();
2372       clearCurrentState(data);
2373   }
2374 ;
2375 
2376 ctors_opt:
2377   '{' ctors '}' { $$ = true; }
2378 | /* empty */ { $$ = false; }
2379 ;
2380 
2381 ctors:
2382   ctors ctor
2383 | /* empty */
2384 ;
2385 
2386 ctor:
2387   deprecated_opt identifier
2388   {
2389       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2390       OUString id(convertName($2));
2391       rtl::Reference<unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad>
2392           pad(getCurrentPad<unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad>(
2393                   data));
2394       for (const auto & i: pad->constructors) {
2395           if (id == i.name) {
2396               error(
2397                   @2, yyscanner,
2398                   ("single-interface--based service " + data->currentName
2399                    + " constructor " + id
2400                    + " has same identifier as another constructor"));
2401               YYERROR;
2402           }
2403       }
2404       pad->constructors.push_back(
2405           unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad::Constructor(
2406               id, annotations($1)));
2407   }
2408   '(' ctorParams_opt ')' exceptionSpec_opt ';'
2409   {
2410       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2411       rtl::Reference<unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad>
2412           pad(getCurrentPad<unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad>(
2413                   data));
2414       assert(!pad->constructors.empty());
2415       if ($7 != nullptr) {
2416           pad->constructors.back().exceptions = *$7;
2417           delete $7;
2418       }
2419       for (auto i(pad->constructors.begin()); i != pad->constructors.end() - 1;
2420            ++i)
2421       {
2422           if (i->parameters.size()
2423               == pad->constructors.back().parameters.size())
2424           {
2425               bool same = true;
2426               for (auto
2427                        j(i->parameters.begin()),
2428                        k(pad->constructors.back().parameters.begin());
2429                    j != i->parameters.end(); ++j, ++k)
2430               {
2431                   if (!j->type.equals(k->type) || j->rest != k->rest) {
2432                       same = false;
2433                       break;
2434                   }
2435               }
2436               if (same) {
2437                   error(
2438                       @2, yyscanner,
2439                       ("single-interface--based service " + data->currentName
2440                        + " constructor " + pad->constructors.back().name
2441                        + " has similar paramete list to constructor "
2442                        + i->name));
2443                   YYERROR;
2444               }
2445           }
2446       }
2447   }
2448 ;
2449 
2450 ctorParams_opt:
2451   ctorParams
2452 | /* empty */
2453 ;
2454 
2455 ctorParams:
2456   ctorParams ',' ctorParam
2457 | ctorParam
2458 ;
2459 
2460 ctorParam:
2461   '[' direction ']' type ellipsis_opt identifier
2462   {
2463       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2464       unoidl::detail::SourceProviderType t(*$4);
2465       delete $4;
2466       OUString id(convertName($6));
2467       rtl::Reference<unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad>
2468           pad(getCurrentPad<unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad>(
2469               data));
2470       assert(!pad->constructors.empty());
2471       if ($2 != unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN) {
2472           error(
2473               @4, yyscanner,
2474               ("single-interface--based service " + data->currentName
2475                + " constructor " + pad->constructors.back().name + " parameter "
2476                + id + " direction must be [in]"));
2477           YYERROR;
2478       }
2479       switch (t.type) {
2480       case unoidl::detail::SourceProviderType::TYPE_VOID:
2481       case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
2482           error(
2483               @4, yyscanner,
2484               ("illegal single-interface--based service " + data->currentName
2485                + " constructor " + pad->constructors.back().name + " parameter "
2486                + id + " type"));
2487           YYERROR;
2488           break;
2489       default:
2490           break;
2491       }
2492       if ($5) {
2493           if (t.type != unoidl::detail::SourceProviderType::TYPE_ANY) {
2494               error(
2495                   @4, yyscanner,
2496                   ("illegal single-interface--based service "
2497                    + data->currentName + " constructor "
2498                    + pad->constructors.back().name + " rest parameter " + id
2499                    + " non-any type"));
2500               YYERROR;
2501           }
2502           if (!pad->constructors.back().parameters.empty()) {
2503               error(
2504                   @5, yyscanner,
2505                   ("single-interface--based service " + data->currentName
2506                    + " constructor " + pad->constructors.back().name
2507                    + " rest parameter " + id + " must be first parameter"));
2508               YYERROR;
2509           }
2510       } else if (!pad->constructors.back().parameters.empty()
2511                  && pad->constructors.back().parameters.back().rest)
2512       {
2513           error(
2514               @1, yyscanner,
2515               ("single-interface--based service " + data->currentName
2516                + " constructor " + pad->constructors.back().name
2517                + " rest parameter must be last parameter"));
2518           YYERROR;
2519       }
2520       for (const auto & i: pad->constructors.back().parameters) {
2521           if (id == i.name) {
2522               error(
2523                   @6, yyscanner,
2524                   ("single-interface--based service " + data->currentName
2525                    + " constructor " + pad->constructors.back().name
2526                    + " parameter " + id
2527                    + " has same identifier as another parameter"));
2528               YYERROR;
2529           }
2530       }
2531       pad->constructors.back().parameters.push_back(
2532           unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad::Constructor::Parameter(
2533               id, t, $5));
2534   }
2535 ;
2536 
2537 ellipsis_opt:
2538   TOK_ELLIPSIS { $$ = true; }
2539 | /* empty */ { $$ = false; }
2540 
2541 accumulationBasedServiceDefn:
2542   deprecated_opt published_opt TOK_SERVICE identifier
2543   {
2544       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2545       data->publishedContext = $2;
2546       convertToCurrentName(data, $4);
2547       if (!data->entities.emplace(
2548                   data->currentName,
2549                   unoidl::detail::SourceProviderEntity(
2550                       new unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad(
2551                           $2))).
2552           second)
2553       {
2554           error(@4, yyscanner, "multiple entities named " + data->currentName);
2555           YYERROR;
2556       }
2557   }
2558   '{' serviceMembers '}' ';'
2559   {
2560       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2561       unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
2562       unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad * pad =
2563           dynamic_cast<unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad *>(
2564               ent->pad.get());
2565       assert(pad != nullptr);
2566       ent->entity = new unoidl::AccumulationBasedServiceEntity(
2567           pad->isPublished(), pad->directMandatoryBaseServices,
2568           pad->directOptionalBaseServices, pad->directMandatoryBaseInterfaces,
2569           pad->directOptionalBaseInterfaces, pad->directProperties,
2570           annotations($1));
2571       ent->pad.clear();
2572       clearCurrentState(data);
2573   }
2574 ;
2575 
2576 serviceMembers:
2577   serviceMembers serviceMember
2578 | /* empty */
2579 ;
2580 
2581 serviceMember:
2582   serviceBase
2583 | serviceInterfaceBase
2584 | serviceProperty
2585 ;
2586 
2587 serviceBase:
2588   deprecated_opt flagSection_opt TOK_SERVICE name ';'
2589   {
2590       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2591       OUString name(convertName($4));
2592       rtl::Reference<unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad> pad(
2593           getCurrentPad<unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad>(
2594               data));
2595       if (($2 & ~unoidl::detail::FLAG_OPTIONAL) != 0) {
2596           error(
2597               @2, yyscanner,
2598               "service base can only be flagged as [optional]");
2599           YYERROR;
2600       }
2601       bool opt = ($2 & unoidl::detail::FLAG_OPTIONAL) != 0;
2602       unoidl::detail::SourceProviderEntity const * p;
2603       if (findEntity(@4, yyscanner, data, false, &name, &p, nullptr, nullptr)
2604           == FOUND_ERROR)
2605       {
2606           YYERROR;
2607       }
2608       if (p == nullptr || !p->entity.is()
2609           || (p->entity->getSort()
2610               != unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE))
2611       {
2612           error(
2613               @4, yyscanner,
2614               ("accumulation-based service " + data->currentName
2615                + " direct base service " + name
2616                + " does not resolve to an accumulation-based service"));
2617           YYERROR;
2618       }
2619       if (data->publishedContext
2620           && !static_cast<unoidl::AccumulationBasedServiceEntity *>(
2621               p->entity.get())->isPublished())
2622       {
2623           error(
2624               @4, yyscanner,
2625               ("published accumulation-based service " + data->currentName
2626                + " direct base service " + name + " is unpublished"));
2627           YYERROR;
2628       }
2629       std::vector<unoidl::AnnotatedReference> & v(
2630           opt
2631           ? pad->directOptionalBaseServices : pad->directMandatoryBaseServices);
2632       for (const auto & i: v) {
2633           if (name == i.name) {
2634               error(
2635                   @4, yyscanner,
2636                   ("accumulation-based service " + data->currentName
2637                    + " duplicate direct base service " + name));
2638               YYERROR;
2639           }
2640       }
2641       v.emplace_back(name, annotations($1));
2642   }
2643 ;
2644 
2645 serviceInterfaceBase:
2646   deprecated_opt flagSection_opt TOK_INTERFACE name ';'
2647   {
2648       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2649       OUString name(convertName($4));
2650       rtl::Reference<unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad> pad(
2651           getCurrentPad<unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad>(
2652               data));
2653       if (($2 & ~unoidl::detail::FLAG_OPTIONAL) != 0) {
2654           error(
2655               @2, yyscanner,
2656               "interface base can only be flagged as [optional]");
2657           YYERROR;
2658       }
2659       bool opt = ($2 & unoidl::detail::FLAG_OPTIONAL) != 0;
2660       unoidl::detail::SourceProviderEntity const * p;
2661       if (findEntity(@4, yyscanner, data, false, &name, &p, nullptr, nullptr)
2662           == FOUND_ERROR)
2663       {
2664           YYERROR;
2665       }
2666       bool ifcBase = false;
2667       bool pubBase = false;
2668       if (p != nullptr) {
2669           switch (p->kind) {
2670           case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
2671               ifcBase = true;
2672               pubBase = false;
2673               break;
2674           case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
2675               ifcBase = true;
2676               pubBase = true;
2677               break;
2678           default:
2679               if (p->entity.is()
2680                   && (p->entity->getSort()
2681                       == unoidl::Entity::SORT_INTERFACE_TYPE))
2682               {
2683                   ifcBase = true;
2684                   pubBase = static_cast<unoidl::InterfaceTypeEntity *>(
2685                       p->entity.get())->isPublished();
2686               }
2687               break;
2688           }
2689       }
2690       if (!ifcBase) {
2691           error(
2692               @4, yyscanner,
2693               ("accumulation-based service " + data->currentName
2694                + " direct base interface " + name
2695                + " does not resolve to an interface type"));
2696           YYERROR;
2697       }
2698       if (data->publishedContext && !opt && !pubBase) {
2699           error(
2700               @4, yyscanner,
2701               ("published accumulation-based service " + data->currentName
2702                + " direct base interface " + name + " is unpublished"));
2703           YYERROR;
2704       }
2705       std::vector<unoidl::AnnotatedReference> & v(
2706           opt
2707           ? pad->directOptionalBaseInterfaces
2708           : pad->directMandatoryBaseInterfaces);
2709       for (const auto & i: v) {
2710           if (name == i.name) {
2711               error(
2712                   @4, yyscanner,
2713                   ("accumulation-based service " + data->currentName
2714                    + " duplicate direct base interface " + name));
2715               YYERROR;
2716           }
2717       }
2718       v.emplace_back(name, annotations($1));
2719   }
2720 ;
2721 
2722 serviceProperty:
2723   deprecated_opt flagSection type identifier ';'
2724   {
2725       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2726       unoidl::detail::SourceProviderType t(*$3);
2727       delete $3;
2728       OUString id(convertName($4));
2729       if (($2 & unoidl::detail::FLAG_PROPERTY) == 0) {
2730           error(
2731               @2, yyscanner,
2732               ("accumulation-based service property must be flagged as"
2733                " [property]"));
2734           YYERROR;
2735       }
2736       if (($2
2737            & ~(unoidl::detail::FLAG_BOUND | unoidl::detail::FLAG_CONSTRAINED
2738                | unoidl::detail::FLAG_MAYBEAMBIGUOUS
2739                | unoidl::detail::FLAG_MAYBEDEFAULT
2740                | unoidl::detail::FLAG_MAYBEVOID | unoidl::detail::FLAG_OPTIONAL
2741                | unoidl::detail::FLAG_PROPERTY | unoidl::detail::FLAG_READONLY
2742                | unoidl::detail::FLAG_REMOVABLE
2743                | unoidl::detail::FLAG_TRANSIENT))
2744           != 0)
2745       {
2746           error(
2747               @2, yyscanner,
2748               ("accumulation-based service property can only be flagged as"
2749                " [property, bound, constrained, maybeambiguous, maybedefault,"
2750                " maybevoid, optional, readonly, removable, transient]"));
2751           YYERROR;
2752       }
2753       int att = 0;
2754       if (($2 & unoidl::detail::FLAG_BOUND) != 0) {
2755           att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_BOUND;
2756       }
2757       if (($2 & unoidl::detail::FLAG_CONSTRAINED) != 0) {
2758           att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_CONSTRAINED;
2759       }
2760       if (($2 & unoidl::detail::FLAG_MAYBEAMBIGUOUS) != 0) {
2761           att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_MAYBE_AMBIGUOUS;
2762       }
2763       if (($2 & unoidl::detail::FLAG_MAYBEDEFAULT) != 0) {
2764           att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_MAYBE_DEFAULT;
2765       }
2766       if (($2 & unoidl::detail::FLAG_MAYBEVOID) != 0) {
2767           att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_MAYBE_VOID;
2768       }
2769       if (($2 & unoidl::detail::FLAG_OPTIONAL) != 0) {
2770           att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_OPTIONAL;
2771       }
2772       if (($2 & unoidl::detail::FLAG_READONLY) != 0) {
2773           att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_READ_ONLY;
2774       }
2775       if (($2 & unoidl::detail::FLAG_REMOVABLE) != 0) {
2776           att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_REMOVABLE;
2777       }
2778       if (($2 & unoidl::detail::FLAG_TRANSIENT) != 0) {
2779           att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_TRANSIENT;
2780       }
2781       switch (t.type) {
2782       case unoidl::detail::SourceProviderType::TYPE_VOID:
2783       case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
2784           error(
2785               @3, yyscanner,
2786               ("illegal accumulation-based service " + data->currentName
2787                + " direct property " + id + " type"));
2788           YYERROR;
2789           break;
2790       default:
2791           break;
2792       }
2793       rtl::Reference<unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad>
2794           pad(getCurrentPad<unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad>(
2795                   data));
2796       for (const auto & i: pad->directProperties) {
2797           if (id == i.name) {
2798               error(
2799                   @4, yyscanner,
2800                   ("accumulation-based service " + data->currentName
2801                    + " duplicate direct property " + id));
2802               YYERROR;
2803           }
2804       }
2805       pad->directProperties.emplace_back(
2806           id, t.getName(),
2807           unoidl::AccumulationBasedServiceEntity::Property::Attributes(att),
2808           annotations($1));
2809   }
2810 ;
2811 
2812 interfaceBasedSingletonDefn:
2813   deprecated_opt published_opt TOK_SINGLETON identifier singleInheritance ';'
2814   {
2815       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2816       data->publishedContext = $2;
2817       OUString name(convertToFullName(data, $4));
2818       OUString base(convertName($5));
2819       unoidl::detail::SourceProviderEntity const * p;
2820       if (findEntity(@5, yyscanner, data, false, &base, &p, nullptr, nullptr)
2821           == FOUND_ERROR)
2822       {
2823           YYERROR;
2824       }
2825       bool ifcBase = false;
2826       bool pubBase = false;
2827       if (p != nullptr) {
2828           switch (p->kind) {
2829           case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
2830               ifcBase = true;
2831               pubBase = false;
2832               break;
2833           case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
2834               ifcBase = true;
2835               pubBase = true;
2836               break;
2837           default:
2838               if (p->entity.is()
2839                   && (p->entity->getSort()
2840                       == unoidl::Entity::SORT_INTERFACE_TYPE))
2841               {
2842                   ifcBase = true;
2843                   pubBase = static_cast<unoidl::InterfaceTypeEntity *>(
2844                       p->entity.get())->isPublished();
2845               }
2846               break;
2847           }
2848       }
2849       if (!ifcBase) {
2850           error(
2851               @5, yyscanner,
2852               ("interface-based singleton " + name + " base " + base
2853                + " does not resolve to an interface type"));
2854           YYERROR;
2855       }
2856       if ($2 && !pubBase) {
2857           error(
2858               @5, yyscanner,
2859               ("published interface-based singleton " + name + " base " + base
2860                + " is unpublished"));
2861           YYERROR;
2862       }
2863       if (!data->entities.emplace(
2864                   name,
2865                   unoidl::detail::SourceProviderEntity(
2866                       unoidl::detail::SourceProviderEntity::KIND_LOCAL,
2867                       new unoidl::InterfaceBasedSingletonEntity(
2868                           $2, base, annotations($1)))).
2869           second)
2870       {
2871           error(@4, yyscanner, "multiple entities named " + name);
2872           YYERROR;
2873       }
2874       clearCurrentState(data);
2875   }
2876 ;
2877 
2878 serviceBasedSingletonDefn:
2879   deprecated_opt published_opt TOK_SINGLETON identifier '{' TOK_SERVICE name ';'
2880   '}' ';'
2881   {
2882       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2883       data->publishedContext = $2;
2884       OUString name(convertToFullName(data, $4));
2885       OUString base(convertName($7));
2886       unoidl::detail::SourceProviderEntity const * p;
2887       if (findEntity(@7, yyscanner, data, false, &base, &p, nullptr, nullptr)
2888           == FOUND_ERROR)
2889       {
2890           YYERROR;
2891       }
2892       if (p == nullptr
2893           || !p->entity.is()
2894           || (p->entity->getSort()
2895               != unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE))
2896       {
2897           error(
2898               @7, yyscanner,
2899               ("service-based singleton " + name + " base " + base
2900                + " does not resolve to an accumulation-based service"));
2901           YYERROR;
2902       }
2903       if ($2
2904           && !static_cast<unoidl::AccumulationBasedServiceEntity *>(
2905               p->entity.get())->isPublished())
2906       {
2907           error(
2908               @7, yyscanner,
2909               ("published service-based singleton " + name + " base " + base
2910                + " is unpublished"));
2911           YYERROR;
2912       }
2913       if (!data->entities.emplace(
2914                   name,
2915                   unoidl::detail::SourceProviderEntity(
2916                       unoidl::detail::SourceProviderEntity::KIND_LOCAL,
2917                       new unoidl::ServiceBasedSingletonEntity(
2918                           $2, base, annotations($1)))).
2919           second)
2920       {
2921           error(@4, yyscanner, "multiple entities named " + name);
2922           YYERROR;
2923       }
2924       clearCurrentState(data);
2925   }
2926 ;
2927 
2928 singleInheritance_opt:
2929   singleInheritance
2930 | /* empty */ { $$ = nullptr; }
2931 ;
2932 
2933 singleInheritance: ':' name { $$ = $2; }
2934 ;
2935 
2936 exceptionSpec_opt:
2937   exceptionSpec
2938 | /* empty */ { $$ = nullptr; }
2939 ;
2940 
2941 exceptionSpec: TOK_RAISES '(' exceptions ')' { $$ = $3; }
2942 ;
2943 
2944 exceptions:
2945   exceptions ',' name
2946   {
2947       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2948       OUString name(convertName($3));
2949       unoidl::detail::SourceProviderEntity const * p;
2950       if (findEntity(@3, yyscanner, data, false, &name, &p, nullptr, nullptr)
2951           == FOUND_ERROR)
2952       {
2953           delete $1; /* see commented-out %destructor above */
2954           YYERROR;
2955       }
2956       if (p == nullptr
2957           || !p->entity.is()
2958           || (p->entity->getSort() != unoidl::Entity::SORT_EXCEPTION_TYPE))
2959       {
2960           delete $1; /* see commented-out %destructor above */
2961           error(
2962               @3, yyscanner,
2963               ("exception " + name + " does not resolve to an exception type"));
2964           YYERROR;
2965       }
2966       if (data->publishedContext
2967           && !(static_cast<unoidl::ExceptionTypeEntity *>(p->entity.get())
2968                ->isPublished()))
2969       {
2970           delete $1; /* see commented-out %destructor above */
2971           error(
2972               @3, yyscanner,
2973               ("unpublished exception " + name + " used in published context"));
2974           YYERROR;
2975       }
2976       if (std::find($1->begin(), $1->end(), name) != $1->end()) {
2977           delete $1; /* see commented-out %destructor above */
2978           error(
2979               @3, yyscanner, ("exception " + name + " listed more than once"));
2980           YYERROR;
2981       }
2982       $1->push_back(name);
2983       $$ = $1;
2984   }
2985 | name
2986   {
2987       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2988       OUString name(convertName($1));
2989       unoidl::detail::SourceProviderEntity const * p;
2990       if (findEntity(@1, yyscanner, data, false, &name, &p, nullptr, nullptr)
2991           == FOUND_ERROR)
2992       {
2993           YYERROR;
2994       }
2995       if (p == nullptr
2996           || !p->entity.is()
2997           || (p->entity->getSort() != unoidl::Entity::SORT_EXCEPTION_TYPE))
2998       {
2999           error(
3000               @1, yyscanner,
3001               ("exception " + name + " does not resolve to an exception type"));
3002           YYERROR;
3003       }
3004       if (data->publishedContext
3005           && !(static_cast<unoidl::ExceptionTypeEntity *>(p->entity.get())
3006                ->isPublished()))
3007       {
3008           error(
3009               @1, yyscanner,
3010               ("unpublished exception " + name + " used in published context"));
3011           YYERROR;
3012       }
3013       $$ = new std::vector<OUString>; $$->push_back(name);
3014   }
3015 ;
3016 
3017 interfaceDecl:
3018   deprecated_opt/*ignored*/ published_opt TOK_INTERFACE identifier ';'
3019   {
3020       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
3021       data->publishedContext = $2;
3022       OUString name(convertToFullName(data, $4));
3023       std::pair<std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator, bool> p(
3024           data->entities.emplace(
3025                   name,
3026                   unoidl::detail::SourceProviderEntity(
3027                       $2
3028                       ? unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL
3029                       : unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL)));
3030       if (!p.second) {
3031           switch (p.first->second.kind) {
3032           case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
3033               if ($2) {
3034                   p.first->second.kind
3035                       = unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL;
3036               }
3037               break;
3038           case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
3039               break;
3040           default:
3041               assert(p.first->second.entity.is());
3042               if (p.first->second.entity->getSort()
3043                   != unoidl::Entity::SORT_INTERFACE_TYPE)
3044               {
3045                   error(
3046                       @4, yyscanner,
3047                       "multiple entities named " + data->currentName);
3048                   YYERROR;
3049               }
3050               if ($2
3051                   && !static_cast<unoidl::InterfaceTypeEntity *>(
3052                       p.first->second.entity.get())->isPublished())
3053               {
3054                   error(
3055                       @4, yyscanner,
3056                       ("published interface type declaration "
3057                        + data->currentName + " has been defined unpublished"));
3058                   YYERROR;
3059               }
3060           }
3061       }
3062       clearCurrentState(data);
3063   }
3064 ;
3065 
3066 published_opt:
3067   TOK_PUBLISHED { $$ = true; }
3068 | /* empty */ { $$ = false; }
3069 ;
3070 
3071 flagSection_opt:
3072   flagSection
3073 | /* empty */ { $$ = unoidl::detail::SourceProviderFlags(0); }
3074 ;
3075 
3076 flagSection: '[' flags ']' { $$ = $2; }
3077 ;
3078 
3079 flags:
3080   flags ',' flag
3081   {
3082       if (($1 & $3) != 0) {
3083           error(@3, yyscanner, "duplicate flag " + flagName($3));
3084           YYERROR;
3085       }
3086       $$ = unoidl::detail::SourceProviderFlags($1 | $3);
3087   }
3088 | flag
3089 ;
3090 
3091 flag:
3092   TOK_ATTRIBUTE { $$ = unoidl::detail::FLAG_ATTRIBUTE; }
3093 | TOK_BOUND { $$ = unoidl::detail::FLAG_BOUND; }
3094 | TOK_CONSTRAINED { $$ = unoidl::detail::FLAG_CONSTRAINED; }
3095 | TOK_MAYBEAMBIGUOUS { $$ = unoidl::detail::FLAG_MAYBEAMBIGUOUS; }
3096 | TOK_MAYBEDEFAULT { $$ = unoidl::detail::FLAG_MAYBEDEFAULT; }
3097 | TOK_MAYBEVOID { $$ = unoidl::detail::FLAG_MAYBEVOID; }
3098 | TOK_OPTIONAL { $$ = unoidl::detail::FLAG_OPTIONAL; }
3099 | TOK_PROPERTY { $$ = unoidl::detail::FLAG_PROPERTY; }
3100 | TOK_READONLY { $$ = unoidl::detail::FLAG_READONLY; }
3101 | TOK_REMOVABLE { $$ = unoidl::detail::FLAG_REMOVABLE; }
3102 | TOK_TRANSIENT { $$ = unoidl::detail::FLAG_TRANSIENT; }
3103 ;
3104 
3105 expr: orExpr
3106 ;
3107 
3108 orExpr:
3109   orExpr '|' xorExpr
3110   {
3111       if (!coerce(@1, yyscanner, &$1, &$3)) {
3112           YYERROR;
3113       }
3114       switch ($1.type) {
3115       case unoidl::detail::SourceProviderExpr::TYPE_INT:
3116           $$ = unoidl::detail::SourceProviderExpr::Int($1.ival | $3.ival);
3117           break;
3118       case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3119           $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval | $3.uval);
3120           break;
3121       default:
3122           error(@1, yyscanner, "arguments of non-integer type to \"|\"");
3123           YYERROR;
3124           break;
3125       }
3126   }
3127 | xorExpr
3128 ;
3129 
3130 xorExpr:
3131   xorExpr '^' andExpr
3132   {
3133       if (!coerce(@1, yyscanner, &$1, &$3)) {
3134           YYERROR;
3135       }
3136       switch ($1.type) {
3137       case unoidl::detail::SourceProviderExpr::TYPE_INT:
3138           $$ = unoidl::detail::SourceProviderExpr::Int($1.ival ^ $3.ival);
3139           break;
3140       case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3141           $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval ^ $3.uval);
3142           break;
3143       default:
3144           error(@1, yyscanner, "arguments of non-integer type to \"^\"");
3145           YYERROR;
3146           break;
3147       }
3148   }
3149 | andExpr
3150 ;
3151 
3152 andExpr:
3153   andExpr '&' shiftExpr
3154   {
3155       if (!coerce(@1, yyscanner, &$1, &$3)) {
3156           YYERROR;
3157       }
3158       switch ($1.type) {
3159       case unoidl::detail::SourceProviderExpr::TYPE_INT:
3160           $$ = unoidl::detail::SourceProviderExpr::Int($1.ival & $3.ival);
3161           break;
3162       case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3163           $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval & $3.uval);
3164           break;
3165       default:
3166           error(@1, yyscanner, "arguments of non-integer type to \"&\"");
3167           YYERROR;
3168           break;
3169       }
3170   }
3171 | shiftExpr
3172 ;
3173 
3174 shiftExpr:
3175   shiftExpr TOK_LEFTSHIFT addExpr
3176   {
3177       int n;
3178       switch ($3.type) {
3179       case unoidl::detail::SourceProviderExpr::TYPE_INT:
3180           if ($3.ival < 0 || $3.ival > 63) {
3181               error(
3182                   @3, yyscanner,
3183                   ("out-of-range shift argument " + OUString::number($3.ival)
3184                    + " to \"<<\" "));
3185               YYERROR;
3186           }
3187           n = static_cast<int>($3.ival);
3188           break;
3189       case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3190           if ($3.uval > 63) {
3191               error(
3192                   @3, yyscanner,
3193                   ("out-of-range shift argument " + OUString::number($3.uval)
3194                    + " to \"<<\" "));
3195               YYERROR;
3196           }
3197           n = static_cast<int>($3.uval);
3198           break;
3199       default:
3200           error(@3, yyscanner, "right argument of non-integer type to \"<<\"");
3201           YYERROR;
3202       }
3203       switch ($1.type) {
3204       case unoidl::detail::SourceProviderExpr::TYPE_INT:
3205           if ($1.ival < 0) {
3206               error(
3207                   @1, yyscanner,
3208                   ("cannot left-shift negative argument "
3209                    + OUString::number($1.ival)));
3210               YYERROR;
3211           }
3212           $$ = unoidl::detail::SourceProviderExpr::Int($1.ival << n);
3213           break;
3214       case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3215           $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval << n);
3216           break;
3217       default:
3218           error(@1, yyscanner, "left argument of non-integer type to \"<<\"");
3219           YYERROR;
3220           break;
3221       }
3222   }
3223 | shiftExpr TOK_RIGHTSHIFT addExpr
3224   {
3225       int n;
3226       switch ($3.type) {
3227       case unoidl::detail::SourceProviderExpr::TYPE_INT:
3228           if ($3.ival < 0 || $3.ival > 63) {
3229               error(
3230                   @3, yyscanner,
3231                   ("out-of-range shift argument " + OUString::number($3.ival)
3232                    + " to \">>\" "));
3233               YYERROR;
3234           }
3235           n = static_cast<int>($3.ival);
3236           break;
3237       case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3238           if ($3.uval > 63) {
3239               error(
3240                   @3, yyscanner,
3241                   ("out-of-range shift argument " + OUString::number($3.uval)
3242                    + " to \">>\" "));
3243               YYERROR;
3244           }
3245           n = static_cast<int>($3.uval);
3246           break;
3247       default:
3248           error(@3, yyscanner, "right argument of non-integer type to \">>\"");
3249           YYERROR;
3250           break;
3251       }
3252       switch ($1.type) {
3253       case unoidl::detail::SourceProviderExpr::TYPE_INT:
3254           $$ = unoidl::detail::SourceProviderExpr::Int($1.ival >> n);
3255           break;
3256       case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3257           $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval >> n);
3258           break;
3259       default:
3260           error(@1, yyscanner, "left argument of non-integer type to \">>\"");
3261           YYERROR;
3262           break;
3263       }
3264   }
3265 | addExpr
3266 ;
3267 
3268 addExpr:
3269   addExpr '+' multExpr
3270   {
3271       if (!coerce(@1, yyscanner, &$1, &$3)) {
3272           YYERROR;
3273       }
3274       switch ($1.type) {
3275       case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
3276           error(@1, yyscanner, "arguments of boolean type to binary \"+\"");
3277           YYERROR;
3278           break;
3279       case unoidl::detail::SourceProviderExpr::TYPE_INT:
3280           $$ = unoidl::detail::SourceProviderExpr::Int($1.ival + $3.ival); //TODO: overflow
3281           break;
3282       case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3283           $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval + $3.uval); //TODO: overflow
3284           break;
3285       case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
3286           $$ = unoidl::detail::SourceProviderExpr::Float($1.fval + $3.fval);
3287           break;
3288       }
3289   }
3290 | addExpr '-' multExpr
3291   {
3292       if (!coerce(@1, yyscanner, &$1, &$3)) {
3293           YYERROR;
3294       }
3295       switch ($1.type) {
3296       case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
3297           error(@1, yyscanner, "arguments of boolean type to binary \"-\"");
3298           YYERROR;
3299           break;
3300       case unoidl::detail::SourceProviderExpr::TYPE_INT:
3301           $$ = unoidl::detail::SourceProviderExpr::Int($1.ival - $3.ival); //TODO: overflow
3302           break;
3303       case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3304           $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval - $3.uval); //TODO: overflow
3305           break;
3306       case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
3307           $$ = unoidl::detail::SourceProviderExpr::Float($1.fval - $3.fval);
3308           break;
3309       }
3310   }
3311 | multExpr
3312 ;
3313 
3314 multExpr:
3315   multExpr '*' unaryExpr
3316   {
3317       if (!coerce(@1, yyscanner, &$1, &$3)) {
3318           YYERROR;
3319       }
3320       switch ($1.type) {
3321       case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
3322           error(@1, yyscanner, "arguments of boolean type to \"*\"");
3323           YYERROR;
3324           break;
3325       case unoidl::detail::SourceProviderExpr::TYPE_INT:
3326           $$ = unoidl::detail::SourceProviderExpr::Int($1.ival * $3.ival); //TODO: overflow
3327           break;
3328       case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3329           $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval * $3.uval); //TODO: overflow
3330           break;
3331       case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
3332           $$ = unoidl::detail::SourceProviderExpr::Float($1.fval * $3.fval);
3333           break;
3334       }
3335   }
3336 | multExpr '/' unaryExpr
3337   {
3338       if (!coerce(@1, yyscanner, &$1, &$3)) {
3339           YYERROR;
3340       }
3341       switch ($1.type) {
3342       case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
3343           error(@1, yyscanner, "arguments of boolean type to \"/\"");
3344           YYERROR;
3345           break;
3346       case unoidl::detail::SourceProviderExpr::TYPE_INT:
3347           if ($3.ival == 0) {
3348               error(@3, yyscanner, "cannot divide by zero");
3349               YYERROR;
3350           }
3351           $$ = unoidl::detail::SourceProviderExpr::Int($1.ival / $3.ival);
3352           break;
3353       case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3354           if ($3.uval == 0) {
3355               error(@3, yyscanner, "cannot divide by zero");
3356               YYERROR;
3357           }
3358           $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval / $3.uval);
3359           break;
3360       case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
3361           if ($3.fval == 0) {
3362               error(@3, yyscanner, "cannot divide by zero");
3363               YYERROR;
3364           }
3365           $$ = unoidl::detail::SourceProviderExpr::Float($1.fval - $3.fval);
3366           break;
3367       }
3368   }
3369 | multExpr '%' unaryExpr
3370   {
3371       if (!coerce(@1, yyscanner, &$1, &$3)) {
3372           YYERROR;
3373       }
3374       switch ($1.type) {
3375       case unoidl::detail::SourceProviderExpr::TYPE_INT:
3376           if ($3.ival == 0) {
3377               error(@3, yyscanner, "cannot divide by zero");
3378               YYERROR;
3379           }
3380           $$ = unoidl::detail::SourceProviderExpr::Int($1.ival % $3.ival);
3381           break;
3382       case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3383           if ($3.uval == 0) {
3384               error(@3, yyscanner, "cannot divide by zero");
3385               YYERROR;
3386           }
3387           $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval % $3.uval);
3388           break;
3389       default:
3390           error(@1, yyscanner, "arguments of non-integer type to \"%\"");
3391           YYERROR;
3392           break;
3393       }
3394   }
3395 | unaryExpr
3396 ;
3397 
3398 unaryExpr:
3399   '+' primaryExpr
3400   {
3401       if ($2.type == unoidl::detail::SourceProviderExpr::TYPE_BOOL) {
3402           error(@2, yyscanner, "argument of boolean type to unary \"+\"");
3403           YYERROR;
3404       }
3405       $$ = $2;
3406   }
3407 | '-' primaryExpr
3408   {
3409       switch ($2.type) {
3410       case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
3411           error(@2, yyscanner, "argument of boolean type to unary \"-\"");
3412           YYERROR;
3413           break;
3414       case unoidl::detail::SourceProviderExpr::TYPE_INT:
3415           if ($2.ival == SAL_MIN_INT64) {
3416               error(@2, yyscanner, "cannot negate -2^63");
3417               YYERROR;
3418           }
3419           $$ = unoidl::detail::SourceProviderExpr::Int(-$2.ival);
3420           break;
3421       case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3422           if ($2.uval == SAL_CONST_UINT64(0x8000000000000000)) {
3423               $$ = unoidl::detail::SourceProviderExpr::Int(SAL_MIN_INT64);
3424           } else {
3425               if ($2.uval > SAL_MAX_INT64) {
3426                   error(
3427                       @2, yyscanner,
3428                       ("cannot negate out-of-range value "
3429                        + OUString::number($2.uval)));
3430                   YYERROR;
3431               }
3432               $$ = unoidl::detail::SourceProviderExpr::Int(
3433                   -static_cast<sal_Int64>($2.uval));
3434           }
3435           break;
3436       case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
3437           $$ = unoidl::detail::SourceProviderExpr::Float(-$2.fval);
3438           break;
3439       }
3440   }
3441 | '~' primaryExpr
3442   {
3443       switch ($2.type) {
3444       case unoidl::detail::SourceProviderExpr::TYPE_INT:
3445           $$ = unoidl::detail::SourceProviderExpr::Int(~$2.ival);
3446           break;
3447       case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3448           $$ = unoidl::detail::SourceProviderExpr::Uint(~$2.uval);
3449           break;
3450       default:
3451           error(@2, yyscanner, "argument of non-integer type to \"~\"");
3452           YYERROR;
3453           break;
3454       }
3455   }
3456 | primaryExpr
3457 ;
3458 
3459 primaryExpr:
3460   '(' expr ')' { $$ = $2; }
3461 | TOK_FALSE { $$ = unoidl::detail::SourceProviderExpr::Bool(false); }
3462 | TOK_TRUE { $$ = unoidl::detail::SourceProviderExpr::Bool(true); }
3463 | TOK_INTEGER { $$ = unoidl::detail::SourceProviderExpr::Uint($1); }
3464 | TOK_FLOATING { $$ = unoidl::detail::SourceProviderExpr::Float($1); }
3465 | name
3466   {
3467       OUString name(convertName($1));
3468       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
3469       unoidl::ConstantValue v(false); // dummy value
3470       bool found = false;
3471       bool unpub = false;
3472       sal_Int32 i = name.lastIndexOf('.');
3473       if (i == -1) {
3474           rtl::Reference<unoidl::detail::SourceProviderEntityPad> pad(
3475               getCurrentEntity(data)->pad);
3476           unoidl::detail::SourceProviderEnumTypeEntityPad * p1 = dynamic_cast<
3477               unoidl::detail::SourceProviderEnumTypeEntityPad *>(pad.get());
3478           if (p1 != nullptr) {
3479               for (const auto & j: p1->members) {
3480                   if (j.name == name) {
3481                       v = unoidl::ConstantValue(j.value);
3482                       found = true;
3483                       break;
3484                   }
3485               }
3486           } else {
3487               unoidl::detail::SourceProviderConstantGroupEntityPad * p2
3488                   = dynamic_cast<
3489                       unoidl::detail::SourceProviderConstantGroupEntityPad *>(
3490                           pad.get());
3491               if (p2 != nullptr) {
3492                   for (const auto & j: p2->members) {
3493                       if (j.name == name) {
3494                           v = j.value;
3495                           found = true;
3496                           break;
3497                       }
3498                   }
3499               }
3500           }
3501       } else {
3502           OUString scope(name.copy(0, i));
3503           unoidl::detail::SourceProviderEntity const * ent;
3504           if (findEntity(
3505                   @1, yyscanner, data, false, &scope, &ent, nullptr, nullptr)
3506               == FOUND_ERROR)
3507           {
3508               YYERROR;
3509           }
3510           if (ent != nullptr) {
3511               OUString id(name.copy(i + 1));
3512               // No need to check for enum members here, as they cannot be
3513               // referenced in expressions by qualified name (TODO: is that true?):
3514               if (ent->entity.is()) {
3515                   if (ent->entity->getSort()
3516                       == unoidl::Entity::SORT_CONSTANT_GROUP)
3517                   {
3518                       std::vector<unoidl::ConstantGroupEntity::Member> const &
3519                           mems(
3520                               static_cast<unoidl::ConstantGroupEntity *>(
3521                                   ent->entity.get())->
3522                               getMembers());
3523                       for (auto & j: mems) {
3524                           if (j.name == id) {
3525                               v = j.value;
3526                               found = true;
3527                               unpub
3528                                   = !static_cast<unoidl::ConstantGroupEntity *>(
3529                                       ent->entity.get())->isPublished();
3530                               break;
3531                           }
3532                       }
3533                   }
3534               } else if (ent->pad.is()) {
3535                   unoidl::detail::SourceProviderConstantGroupEntityPad * pad
3536                       = dynamic_cast<
3537                           unoidl::detail::SourceProviderConstantGroupEntityPad *>(
3538                               ent->pad.get());
3539                   if (pad != nullptr) {
3540                       for (const auto & j: pad->members) {
3541                           if (j.name == id) {
3542                               v = j.value;
3543                               found = true;
3544                               unpub = !ent->pad->isPublished();
3545                               break;
3546                           }
3547                       }
3548                   }
3549               }
3550           }
3551       }
3552       if (!found) {
3553           error(
3554               @1, yyscanner,
3555               (name
3556                + (" does not resolve to neither a constant nor an unqualified"
3557                   " enum member")));
3558           YYERROR;
3559       }
3560       if (data->publishedContext && unpub) {
3561           error(
3562               @1, yyscanner,
3563               "unpublished value " + name + " used in published context");
3564           YYERROR;
3565       }
3566       switch (v.type) {
3567       case unoidl::ConstantValue::TYPE_BOOLEAN:
3568           $$ = unoidl::detail::SourceProviderExpr::Bool(v.booleanValue);
3569           break;
3570       case unoidl::ConstantValue::TYPE_BYTE:
3571           $$ = unoidl::detail::SourceProviderExpr::Int(v.byteValue);
3572           break;
3573       case unoidl::ConstantValue::TYPE_SHORT:
3574           $$ = unoidl::detail::SourceProviderExpr::Int(v.shortValue);
3575           break;
3576       case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
3577           $$ = unoidl::detail::SourceProviderExpr::Uint(v.unsignedShortValue);
3578           break;
3579       case unoidl::ConstantValue::TYPE_LONG:
3580           $$ = unoidl::detail::SourceProviderExpr::Int(v.longValue);
3581           break;
3582       case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
3583           $$ = unoidl::detail::SourceProviderExpr::Uint(v.unsignedLongValue);
3584           break;
3585       case unoidl::ConstantValue::TYPE_HYPER:
3586           $$ = unoidl::detail::SourceProviderExpr::Int(v.hyperValue);
3587           break;
3588       case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
3589           $$ = unoidl::detail::SourceProviderExpr::Uint(v.unsignedHyperValue);
3590           break;
3591       case unoidl::ConstantValue::TYPE_FLOAT:
3592           $$ = unoidl::detail::SourceProviderExpr::Float(v.floatValue);
3593           break;
3594       case unoidl::ConstantValue::TYPE_DOUBLE:
3595           $$ = unoidl::detail::SourceProviderExpr::Float(v.doubleValue);
3596           break;
3597       }
3598   }
3599 ;
3600 
3601 typeArguments:
3602   typeArguments ',' type
3603   {
3604       unoidl::detail::SourceProviderType t(*$3);
3605       delete $3;
3606       if (!checkTypeArgument(@3, yyscanner, t)) {
3607           delete $1; /* see commented-out %destructor above */
3608           YYERROR;
3609       }
3610       $1->push_back(t);
3611       $$ = $1;
3612   }
3613 | type
3614   {
3615       unoidl::detail::SourceProviderType t(*$1);
3616       delete $1;
3617       if (!checkTypeArgument(@1, yyscanner, t)) {
3618           YYERROR;
3619       }
3620       $$ = new std::vector<unoidl::detail::SourceProviderType>;
3621       $$->push_back(t);
3622   }
3623 ;
3624 
3625 type:
3626   TOK_VOID
3627   {
3628       $$ = new unoidl::detail::SourceProviderType(
3629           unoidl::detail::SourceProviderType::TYPE_VOID);
3630   }
3631 | TOK_BOOLEAN
3632   {
3633       $$ = new unoidl::detail::SourceProviderType(
3634           unoidl::detail::SourceProviderType::TYPE_BOOLEAN);
3635   }
3636 | TOK_BYTE
3637   {
3638       $$ = new unoidl::detail::SourceProviderType(
3639           unoidl::detail::SourceProviderType::TYPE_BYTE);
3640   }
3641 | TOK_SHORT
3642   {
3643       $$ = new unoidl::detail::SourceProviderType(
3644           unoidl::detail::SourceProviderType::TYPE_SHORT);
3645   }
3646 | TOK_UNSIGNED TOK_SHORT
3647   {
3648       $$ = new unoidl::detail::SourceProviderType(
3649           unoidl::detail::SourceProviderType::TYPE_UNSIGNED_SHORT);
3650   }
3651 | TOK_LONG
3652   {
3653       $$ = new unoidl::detail::SourceProviderType(
3654           unoidl::detail::SourceProviderType::TYPE_LONG);
3655   }
3656 | TOK_UNSIGNED TOK_LONG
3657   {
3658       $$ = new unoidl::detail::SourceProviderType(
3659           unoidl::detail::SourceProviderType::TYPE_UNSIGNED_LONG);
3660   }
3661 | TOK_HYPER
3662   {
3663       $$ = new unoidl::detail::SourceProviderType(
3664           unoidl::detail::SourceProviderType::TYPE_HYPER);
3665   }
3666 | TOK_UNSIGNED TOK_HYPER
3667   {
3668       $$ = new unoidl::detail::SourceProviderType(
3669           unoidl::detail::SourceProviderType::TYPE_UNSIGNED_HYPER);
3670   }
3671 | TOK_FLOAT
3672   {
3673       $$ = new unoidl::detail::SourceProviderType(
3674           unoidl::detail::SourceProviderType::TYPE_FLOAT);
3675   }
3676 | TOK_DOUBLE
3677   {
3678       $$ = new unoidl::detail::SourceProviderType(
3679           unoidl::detail::SourceProviderType::TYPE_DOUBLE);
3680   }
3681 | TOK_CHAR
3682   {
3683       $$ = new unoidl::detail::SourceProviderType(
3684           unoidl::detail::SourceProviderType::TYPE_CHAR);
3685   }
3686 | TOK_STRING
3687   {
3688       $$ = new unoidl::detail::SourceProviderType(
3689           unoidl::detail::SourceProviderType::TYPE_STRING);
3690   }
3691 | TOK_TYPE
3692   {
3693       $$ = new unoidl::detail::SourceProviderType(
3694           unoidl::detail::SourceProviderType::TYPE_TYPE);
3695   }
3696 | TOK_ANY
3697   {
3698       $$ = new unoidl::detail::SourceProviderType(
3699           unoidl::detail::SourceProviderType::TYPE_ANY);
3700   }
3701 | TOK_SEQUENCE '<' type '>'
3702   {
3703       switch ($3->type) {
3704       case unoidl::detail::SourceProviderType::TYPE_VOID:
3705       case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
3706       case unoidl::detail::SourceProviderType::TYPE_PARAMETER: //TODO?
3707           error(@3, yyscanner, "illegal sequence type component type");
3708           YYERROR;
3709           break;
3710       default:
3711           break;
3712       }
3713       $$ = new unoidl::detail::SourceProviderType($3);
3714       delete $3;
3715   }
3716 | name
3717   {
3718       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
3719       OUString name(convertName($1));
3720       bool done = false;
3721       if (name.indexOf('.') == -1 && !data->currentName.isEmpty()) {
3722           unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
3723           unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *
3724               pad = dynamic_cast<
3725                   unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
3726                       ent->pad.get());
3727           if (pad != nullptr
3728               && (std::find(
3729                       pad->typeParameters.begin(), pad->typeParameters.end(),
3730                       name)
3731                   != pad->typeParameters.end()))
3732           {
3733               $$ = new unoidl::detail::SourceProviderType(name);
3734               done = true;
3735           }
3736       }
3737       if (!done) {
3738           unoidl::detail::SourceProviderEntity const * ent;
3739           unoidl::detail::SourceProviderType t;
3740           switch (findEntity(
3741                       @1, yyscanner, data, false, &name, &ent, nullptr, &t))
3742           {
3743           case FOUND_ERROR:
3744               YYERROR;
3745               break;
3746           case FOUND_TYPE:
3747               $$ = new unoidl::detail::SourceProviderType(t);
3748               break;
3749           case FOUND_ENTITY:
3750               if (ent == nullptr) {
3751                   error(@1, yyscanner, "unknown entity " + name);
3752                   YYERROR;
3753               }
3754               bool ok = false;
3755               switch (ent->kind) {
3756               case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
3757                   if (ent->pad.is()) {
3758                       if (data->publishedContext && !ent->pad->isPublished()) {
3759                           error(
3760                               @1, yyscanner,
3761                               ("unpublished entity " + name
3762                                + " used in published context"));
3763                           YYERROR;
3764                       }
3765                       if (dynamic_cast<unoidl::detail::SourceProviderEnumTypeEntityPad *>(
3766                               ent->pad.get())
3767                           != nullptr)
3768                       {
3769                           $$ = new unoidl::detail::SourceProviderType(
3770                               unoidl::detail::SourceProviderType::TYPE_ENUM,
3771                               name, ent);
3772                           ok = true;
3773                       } else if (dynamic_cast<unoidl::detail::SourceProviderPlainStructTypeEntityPad *>(
3774                                      ent->pad.get())
3775                                  != nullptr)
3776                       {
3777                           $$ = new unoidl::detail::SourceProviderType(
3778                               unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT,
3779                               name, ent);
3780                           ok = true;
3781                       } else if (dynamic_cast<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
3782                                      ent->pad.get())
3783                                  != nullptr)
3784                       {
3785                           error(
3786                               @1, yyscanner,
3787                               (("recursive reference to polymorphic struct type"
3788                                 " template ")
3789                                + name));
3790                           YYERROR;
3791                       } else if (dynamic_cast<unoidl::detail::SourceProviderExceptionTypeEntityPad *>(
3792                                      ent->pad.get())
3793                                  != nullptr)
3794                       {
3795                           $$ = new unoidl::detail::SourceProviderType(
3796                               unoidl::detail::SourceProviderType::TYPE_EXCEPTION,
3797                               name, ent);
3798                           ok = true;
3799                       } else if (dynamic_cast<unoidl::detail::SourceProviderInterfaceTypeEntityPad *>(
3800                                      ent->pad.get())
3801                                  != nullptr)
3802                       {
3803                           $$ = new unoidl::detail::SourceProviderType(
3804                               unoidl::detail::SourceProviderType::TYPE_INTERFACE,
3805                               name, ent);
3806                           ok = true;
3807                       }
3808                       break;
3809                   }
3810                   assert(ent->entity.is());
3811                   [[fallthrough]];
3812               case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
3813                   if (data->publishedContext
3814                       && ent->entity->getSort() != unoidl::Entity::SORT_MODULE
3815                       && !static_cast<unoidl::PublishableEntity *>(
3816                           ent->entity.get())->isPublished())
3817                   {
3818                       error(
3819                           @1, yyscanner,
3820                           ("unpublished entity " + name
3821                            + " used in published context"));
3822                       YYERROR;
3823                   }
3824                   switch (ent->entity->getSort()) {
3825                   case unoidl::Entity::SORT_ENUM_TYPE:
3826                       $$ = new unoidl::detail::SourceProviderType(
3827                           unoidl::detail::SourceProviderType::TYPE_ENUM, name,
3828                           ent);
3829                       ok = true;
3830                       break;
3831                   case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
3832                       $$ = new unoidl::detail::SourceProviderType(
3833                           unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT,
3834                           name, ent);
3835                       ok = true;
3836                       break;
3837                   case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
3838                       error(
3839                           @1, yyscanner,
3840                           ("polymorphic struct type template " + name
3841                            + " without type arguments"));
3842                       YYERROR;
3843                       break;
3844                   case unoidl::Entity::SORT_EXCEPTION_TYPE:
3845                       $$ = new unoidl::detail::SourceProviderType(
3846                           unoidl::detail::SourceProviderType::TYPE_EXCEPTION,
3847                           name, ent);
3848                       ok = true;
3849                       break;
3850                   case unoidl::Entity::SORT_INTERFACE_TYPE:
3851                       $$ = new unoidl::detail::SourceProviderType(
3852                           unoidl::detail::SourceProviderType::TYPE_INTERFACE,
3853                           name, ent);
3854                       ok = true;
3855                       break;
3856                   case unoidl::Entity::SORT_TYPEDEF:
3857                       O3TL_UNREACHABLE;
3858                   default:
3859                       break;
3860                   }
3861                   break;
3862               case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
3863                   if (data->publishedContext) {
3864                       error(
3865                           @1, yyscanner,
3866                           ("unpublished entity " + name
3867                            + " used in published context"));
3868                       YYERROR;
3869                   }
3870                   [[fallthrough]];
3871               case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
3872                   $$ = new unoidl::detail::SourceProviderType(
3873                       unoidl::detail::SourceProviderType::TYPE_INTERFACE, name,
3874                       ent);
3875                   ok = true;
3876                   break;
3877               case unoidl::detail::SourceProviderEntity::KIND_MODULE:
3878                   assert(false && "this cannot happen");
3879               }
3880               if (!ok) {
3881                   error(@1, yyscanner, "non-type entity " + name);
3882                   YYERROR;
3883               }
3884               break;
3885           }
3886       }
3887   }
3888 | name '<' typeArguments '>'
3889   {
3890       unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
3891       OUString name(convertName($1));
3892       std::vector<unoidl::detail::SourceProviderType> args(*$3);
3893       delete $3;
3894       unoidl::detail::SourceProviderEntity const * ent;
3895       if (findEntity(@1, yyscanner, data, false, &name, &ent, nullptr, nullptr)
3896           == FOUND_ERROR)
3897       {
3898           YYERROR;
3899       }
3900       if (ent == nullptr) {
3901           error(@1, yyscanner, "unknown entity " + name);
3902           YYERROR;
3903       }
3904       bool ok = false;
3905       switch (ent->kind) {
3906       case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
3907           if (ent->pad.is()) {
3908               if (dynamic_cast<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
3909                       ent->pad.get())
3910                   != nullptr)
3911               {
3912                   error(
3913                       @1, yyscanner,
3914                       (("recursive reference to polymorphic struct type"
3915                         " template ")
3916                        + name));
3917                   YYERROR;
3918               }
3919               break;
3920           }
3921           assert(ent->entity.is());
3922           [[fallthrough]];
3923       case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
3924           if (ent->entity->getSort()
3925               == unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE)
3926           {
3927               rtl::Reference<unoidl::PolymorphicStructTypeTemplateEntity> e(
3928                   static_cast<unoidl::PolymorphicStructTypeTemplateEntity *>(
3929                       ent->entity.get()));
3930               if (args.size() != e->getTypeParameters().size()) {
3931                   error(
3932                       @1, yyscanner,
3933                       ("bad number of polymorphic struct type template " + name
3934                        + " type arguments"));
3935                   YYERROR;
3936               }
3937               if (data->publishedContext && !e->isPublished()) {
3938                   error(
3939                       @1, yyscanner,
3940                       ("unpublished polymorphic struct type template " + name
3941                        + " used in published context"));
3942                   YYERROR;
3943               }
3944               $$ = new unoidl::detail::SourceProviderType(name, ent, args);
3945               ok = true;
3946           }
3947           break;
3948       case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
3949       case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
3950           break;
3951       case unoidl::detail::SourceProviderEntity::KIND_MODULE:
3952           assert(false && "this cannot happen");
3953       }
3954       if (!ok) {
3955           error(@1, yyscanner, "non-type entity " + name);
3956           YYERROR;
3957       }
3958   }
3959 ;
3960 
3961 name:
3962   name TOK_COLONS identifier { *$1 += "." + *$3; delete $3; $$ = $1; }
3963 | TOK_COLONS identifier { *$2 = "." + *$2; $$ = $2; }
3964 | identifier
3965 ;
3966 
3967 identifier:
3968   TOK_IDENTIFIER
3969 | TOK_GET { $$ = new OString("get"); }
3970 | TOK_PUBLISHED { $$ = new OString("published"); }
3971 | TOK_SET { $$ = new OString("set"); }
3972 ;
3973 
3974 deprecated_opt:
3975   TOK_DEPRECATED { $$ = true; }
3976 | /* empty */ { $$ = false; }
3977 ;
3978 
3979 %%
3980 
3981 namespace unoidl::detail {
3982 
getName()3983 OUString SourceProviderType::getName() const {
3984     if (!typedefName.isEmpty()) {
3985         return typedefName;
3986     }
3987     switch (type) {
3988     case unoidl::detail::SourceProviderType::TYPE_VOID:
3989         return "void";
3990     case unoidl::detail::SourceProviderType::TYPE_BOOLEAN:
3991         return "boolean";
3992     case unoidl::detail::SourceProviderType::TYPE_BYTE:
3993         return "byte";
3994     case unoidl::detail::SourceProviderType::TYPE_SHORT:
3995         return "short";
3996     case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_SHORT:
3997         return "unsigned short";
3998     case unoidl::detail::SourceProviderType::TYPE_LONG:
3999         return "long";
4000     case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_LONG:
4001         return "unsigned long";
4002     case unoidl::detail::SourceProviderType::TYPE_HYPER:
4003         return "hyper";
4004     case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_HYPER:
4005         return "unsigned hyper";
4006     case unoidl::detail::SourceProviderType::TYPE_FLOAT:
4007         return "float";
4008     case unoidl::detail::SourceProviderType::TYPE_DOUBLE:
4009         return "double";
4010     case unoidl::detail::SourceProviderType::TYPE_CHAR:
4011         return "char";
4012     case unoidl::detail::SourceProviderType::TYPE_STRING:
4013         return "string";
4014     case unoidl::detail::SourceProviderType::TYPE_TYPE:
4015         return "type";
4016     case unoidl::detail::SourceProviderType::TYPE_ANY:
4017         return "any";
4018     case unoidl::detail::SourceProviderType::TYPE_SEQUENCE:
4019         assert(subtypes.size() == 1);
4020         return "[]" + subtypes.front().getName();
4021     case unoidl::detail::SourceProviderType::TYPE_ENUM:
4022     case unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT:
4023     case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
4024     case unoidl::detail::SourceProviderType::TYPE_INTERFACE:
4025     case unoidl::detail::SourceProviderType::TYPE_PARAMETER:
4026         return name;
4027     case unoidl::detail::SourceProviderType::TYPE_INSTANTIATED_POLYMORPHIC_STRUCT:
4028         {
4029             OUStringBuffer n(512);
4030             n.append(name + "<");
4031             for (auto i(subtypes.begin()); i != subtypes.end(); ++i) {
4032                 if (i != subtypes.begin()) {
4033                     n.append(",");
4034                 }
4035                 n.append(i->getName());
4036             }
4037             return n.append(">").makeStringAndClear();
4038         }
4039     default:
4040         assert(false && "this cannot happen"); for (;;) { std::abort(); }
4041     }
4042 }
4043 
equals(SourceProviderType const & other)4044 bool SourceProviderType::equals(SourceProviderType const & other) const {
4045     if (type != other.type || name != other.name
4046         || subtypes.size() != other.subtypes.size())
4047     {
4048         return false;
4049     }
4050     for (auto i(subtypes.begin()), j(other.subtypes.begin());
4051          i != subtypes.end(); ++i, ++j)
4052     {
4053         if (!i->equals(*j)) {
4054             return false;
4055         }
4056     }
4057     return true;
4058 }
4059 
addDirectBase(YYLTYPE location,yyscan_t yyscanner,SourceProviderScannerData * data,DirectBase const & base,bool optional)4060 bool SourceProviderInterfaceTypeEntityPad::addDirectBase(
4061     YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
4062     DirectBase const & base, bool optional)
4063 {
4064     std::set<OUString> seen;
4065     if (!(checkBaseClashes(
4066               location, yyscanner, data, base.name, base.entity, true, optional,
4067               optional, &seen)
4068           && addBase(
4069               location, yyscanner, data, base.name, base.name, base.entity,
4070               true, optional)))
4071     {
4072         return false;
4073     }
4074     if (optional) {
4075         addOptionalBaseMembers(
4076             location, yyscanner, data, base.name, base.entity);
4077     }
4078     (optional ? directOptionalBases : directMandatoryBases).push_back(base);
4079     return true;
4080 }
4081 
addDirectMember(YYLTYPE location,yyscan_t yyscanner,SourceProviderScannerData * data,OUString const & name)4082 bool SourceProviderInterfaceTypeEntityPad::addDirectMember(
4083     YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
4084     OUString const & name)
4085 {
4086     assert(data != nullptr);
4087     if (!checkMemberClashes(location, yyscanner, data, u"", name, true)) {
4088         return false;
4089     }
4090     allMembers.emplace(name, Member(data->currentName));
4091     return true;
4092 }
4093 
checkBaseClashes(YYLTYPE location,yyscan_t yyscanner,SourceProviderScannerData * data,OUString const & name,rtl::Reference<unoidl::InterfaceTypeEntity> const & entity,bool direct,bool optional,bool outerOptional,std::set<OUString> * seen)4094 bool SourceProviderInterfaceTypeEntityPad::checkBaseClashes(
4095     YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
4096     OUString const & name,
4097     rtl::Reference<unoidl::InterfaceTypeEntity> const & entity, bool direct,
4098     bool optional, bool outerOptional, std::set<OUString> * seen) const
4099 {
4100     assert(data != nullptr);
4101     assert(entity.is());
4102     assert(seen != nullptr);
4103     if (direct || optional || seen->insert(name).second) {
4104         std::map<OUString, BaseKind>::const_iterator i(allBases.find(name));
4105         if (i != allBases.end()) {
4106             switch (i->second) {
4107             case BASE_INDIRECT_OPTIONAL:
4108                 if (direct && optional) {
4109                     error(
4110                         location, yyscanner,
4111                         ("interface type " + data->currentName
4112                          + " duplicate base " + name));
4113                     return false;
4114                 }
4115                 break;
4116             case BASE_DIRECT_OPTIONAL:
4117                 if (direct || !outerOptional) {
4118                     error(
4119                         location, yyscanner,
4120                         ("interface type " + data->currentName
4121                          + " duplicate base " + name));
4122                     return false;
4123                 }
4124                 return true;
4125             case BASE_INDIRECT_MANDATORY:
4126                 if (direct) {
4127                     error(
4128                         location, yyscanner,
4129                         ("interface type " + data->currentName
4130                          + " duplicate base " + name));
4131                     return false;
4132                 }
4133                 return true;
4134             case BASE_DIRECT_MANDATORY:
4135                 if (direct || (!optional && !outerOptional)) {
4136                     error(
4137                         location, yyscanner,
4138                         ("interface type " + data->currentName
4139                          + " duplicate base " + name));
4140                     return false;
4141                 }
4142                 return true;
4143             }
4144         }
4145         if (direct || !optional) {
4146             for (auto & j: entity->getDirectMandatoryBases()) {
4147                 OUString n("." + j.name);
4148                 unoidl::detail::SourceProviderEntity const * p;
4149                 if (findEntity(
4150                         location, yyscanner, data, true, &n, &p, nullptr,
4151                         nullptr)
4152                     == FOUND_ERROR)
4153                 {
4154                     return false;
4155                 }
4156                 if (p == nullptr || !p->entity.is()
4157                     || (p->entity->getSort()
4158                         != unoidl::Entity::SORT_INTERFACE_TYPE))
4159                 {
4160                     error(
4161                         location, yyscanner,
4162                         ("inconsistent type manager: interface type "
4163                          + data->currentName + " base " + n
4164                          + " does not resolve to an existing interface type"));
4165                     return false;
4166                 }
4167                 if (!checkBaseClashes(
4168                         location, yyscanner, data, n,
4169                         static_cast<unoidl::InterfaceTypeEntity *>(
4170                             p->entity.get()),
4171                         false, false, outerOptional, seen))
4172                 {
4173                     return false;
4174                 }
4175             }
4176             for (auto & j: entity->getDirectOptionalBases()) {
4177                 OUString n("." + j.name);
4178                 unoidl::detail::SourceProviderEntity const * p;
4179                 if (findEntity(
4180                         location, yyscanner, data, true, &n, &p, nullptr,
4181                         nullptr)
4182                     == FOUND_ERROR)
4183                 {
4184                     return false;
4185                 }
4186                 if (p == nullptr || !p->entity.is()
4187                     || (p->entity->getSort()
4188                         != unoidl::Entity::SORT_INTERFACE_TYPE))
4189                 {
4190                     error(
4191                         location, yyscanner,
4192                         ("inconsistent type manager: interface type "
4193                          + data->currentName + " base " + n
4194                          + " does not resolve to an existing interface type"));
4195                     return false;
4196                 }
4197                 if (!checkBaseClashes(
4198                         location, yyscanner, data, n,
4199                         static_cast<unoidl::InterfaceTypeEntity *>(
4200                             p->entity.get()),
4201                         false, true, outerOptional, seen))
4202                 {
4203                     return false;
4204                 }
4205             }
4206             for (auto & j: entity->getDirectAttributes()) {
4207                 if (!checkMemberClashes(
4208                         location, yyscanner, data, name, j.name,
4209                         !outerOptional))
4210                 {
4211                     return false;
4212                 }
4213             }
4214             for (auto & j: entity->getDirectMethods()) {
4215                 if (!checkMemberClashes(
4216                         location, yyscanner, data, name, j.name,
4217                         !outerOptional))
4218                 {
4219                     return false;
4220                 }
4221             }
4222         }
4223     }
4224     return true;
4225 }
4226 
checkMemberClashes(YYLTYPE location,yyscan_t yyscanner,SourceProviderScannerData * data,std::u16string_view interfaceName,OUString const & memberName,bool checkOptional)4227 bool SourceProviderInterfaceTypeEntityPad::checkMemberClashes(
4228     YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
4229     std::u16string_view interfaceName, OUString const & memberName,
4230     bool checkOptional) const
4231 {
4232     std::map<OUString, Member>::const_iterator i(allMembers.find(memberName));
4233     if (i != allMembers.end()) {
4234         if (!i->second.mandatory.isEmpty()) {
4235             // For a direct member, interfaceName will be empty, so this will
4236             // catch two direct members with the same name:
4237             if (i->second.mandatory != interfaceName) {
4238                 error(
4239                     location, yyscanner,
4240                     ("interface type " + data->currentName
4241                      + " duplicate member " + memberName));
4242                 return false;
4243             }
4244         } else if (checkOptional) {
4245             for (auto & j: i->second.optional) {
4246                 if (j != interfaceName) {
4247                     error(
4248                         location, yyscanner,
4249                         ("interface type " + data->currentName
4250                          + " duplicate member " + memberName));
4251                     return false;
4252                 }
4253             }
4254         }
4255     }
4256     return true;
4257 }
4258 
addBase(YYLTYPE location,yyscan_t yyscanner,SourceProviderScannerData * data,OUString const & directBaseName,OUString const & name,rtl::Reference<unoidl::InterfaceTypeEntity> const & entity,bool direct,bool optional)4259 bool SourceProviderInterfaceTypeEntityPad::addBase(
4260     YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
4261     OUString const & directBaseName, OUString const & name,
4262     rtl::Reference<unoidl::InterfaceTypeEntity> const & entity, bool direct,
4263     bool optional)
4264 {
4265     assert(data != nullptr);
4266     assert(entity.is());
4267     BaseKind kind = optional
4268         ? direct ? BASE_DIRECT_OPTIONAL : BASE_INDIRECT_OPTIONAL
4269         : direct ? BASE_DIRECT_MANDATORY : BASE_INDIRECT_MANDATORY;
4270     std::pair<std::map<OUString, BaseKind>::iterator, bool> p(
4271         allBases.emplace(name, kind));
4272     bool seen = !p.second && p.first->second >= BASE_INDIRECT_MANDATORY;
4273     if (!p.second && kind > p.first->second) {
4274         p.first->second = kind;
4275     }
4276     if (!optional && !seen) {
4277         for (auto & i: entity->getDirectMandatoryBases()) {
4278             OUString n("." + i.name);
4279             unoidl::detail::SourceProviderEntity const * q;
4280             if (findEntity(
4281                     location, yyscanner, data, true, &n, &q, nullptr, nullptr)
4282                 == FOUND_ERROR)
4283             {
4284                 return false;
4285             }
4286             if (q == nullptr || !q->entity.is()
4287                 || q->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
4288             {
4289                 error(
4290                     location, yyscanner,
4291                     ("inconsistent type manager: interface type "
4292                      + data->currentName + " base " + n
4293                      + " does not resolve to an existing interface type"));
4294                 return false;
4295             }
4296             if (!addBase(
4297                     location, yyscanner, data, directBaseName, n,
4298                     static_cast<unoidl::InterfaceTypeEntity *>(q->entity.get()),
4299                     false, false))
4300             {
4301                 return false;
4302             }
4303         }
4304         for (auto & i: entity->getDirectOptionalBases())
4305         {
4306             OUString n("." + i.name);
4307             unoidl::detail::SourceProviderEntity const * q;
4308             if (findEntity(
4309                     location, yyscanner, data, true, &n, &q, nullptr, nullptr)
4310                 == FOUND_ERROR)
4311             {
4312                 return false;
4313             }
4314             if (q == nullptr || !q->entity.is()
4315                 || q->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
4316             {
4317                 error(
4318                     location, yyscanner,
4319                     ("inconsistent type manager: interface type "
4320                      + data->currentName + " base " + n
4321                      + " does not resolve to an existing interface type"));
4322                 return false;
4323             }
4324             if (!addBase(
4325                     location, yyscanner, data, directBaseName, n,
4326                     static_cast<unoidl::InterfaceTypeEntity *>(q->entity.get()),
4327                     false, true))
4328             {
4329                 return false;
4330             }
4331         }
4332         for (auto & i: entity->getDirectAttributes()) {
4333             allMembers.emplace(i.name, Member(name));
4334         }
4335         for (auto & i: entity->getDirectMethods()) {
4336             allMembers.emplace(i.name, Member(name));
4337         }
4338     }
4339     return true;
4340 }
4341 
addOptionalBaseMembers(YYLTYPE location,yyscan_t yyscanner,SourceProviderScannerData * data,OUString const & name,rtl::Reference<unoidl::InterfaceTypeEntity> const & entity)4342 bool SourceProviderInterfaceTypeEntityPad::addOptionalBaseMembers(
4343     YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
4344     OUString const & name,
4345     rtl::Reference<unoidl::InterfaceTypeEntity> const & entity)
4346 {
4347     assert(entity.is());
4348     for (auto & i: entity->getDirectMandatoryBases()) {
4349         OUString n("." + i.name);
4350         unoidl::detail::SourceProviderEntity const * p;
4351         if (findEntity(
4352                 location, yyscanner, data, true, &n, &p, nullptr, nullptr)
4353             == FOUND_ERROR)
4354         {
4355             return false;
4356         }
4357         if (p == nullptr || !p->entity.is()
4358             || p->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
4359         {
4360             error(
4361                 location, yyscanner,
4362                 ("inconsistent type manager: interface type "
4363                  + data->currentName + " base " + n
4364                  + " does not resolve to an existing interface type"));
4365             return false;
4366         }
4367         if (!addOptionalBaseMembers(
4368                 location, yyscanner, data, n,
4369                 static_cast<unoidl::InterfaceTypeEntity *>(p->entity.get())))
4370         {
4371             return false;
4372         }
4373     }
4374     for (auto & i: entity->getDirectAttributes()) {
4375         Member & m(
4376             allMembers.emplace(i.name, Member(""))
4377             .first->second);
4378         if (m.mandatory.isEmpty()) {
4379             m.optional.insert(name);
4380         }
4381     }
4382     for (auto & i: entity->getDirectMethods()) {
4383         Member & m(
4384             allMembers.emplace(i.name, Member(""))
4385             .first->second);
4386         if (m.mandatory.isEmpty()) {
4387             m.optional.insert(name);
4388         }
4389     }
4390     return true;
4391 }
4392 
parse(OUString const & uri,SourceProviderScannerData * data)4393 bool parse(OUString const & uri, SourceProviderScannerData * data) {
4394     assert(data != nullptr);
4395     oslFileHandle handle;
4396     oslFileError e = osl_openFile(uri.pData, &handle, osl_File_OpenFlag_Read);
4397     switch (e) {
4398     case osl_File_E_None:
4399         break;
4400     case osl_File_E_NOENT:
4401         return false;
4402     default:
4403         throw FileFormatException(uri, "cannot open: " + OUString::number(e));
4404     }
4405     sal_uInt64 size;
4406     e = osl_getFileSize(handle, &size);
4407     if (e != osl_File_E_None) {
4408         oslFileError e2 = osl_closeFile(handle);
4409         SAL_WARN_IF(
4410             e2 != osl_File_E_None, "unoidl",
4411             "cannot close " << uri << ": " << +e2);
4412         throw FileFormatException(
4413             uri, "cannot get size: " + OUString::number(e));
4414     }
4415     void * address;
4416     e = osl_mapFile(handle, &address, size, 0, osl_File_MapFlag_RandomAccess);
4417     if (e != osl_File_E_None) {
4418         oslFileError e2 = osl_closeFile(handle);
4419         SAL_WARN_IF(
4420             e2 != osl_File_E_None, "unoidl",
4421             "cannot close " << uri << ": " << +e2);
4422         throw FileFormatException(uri, "cannot mmap: " + OUString::number(e));
4423     }
4424     try {
4425         data->setSource(address, size);
4426         yyscan_t yyscanner;
4427         if (yylex_init_extra(data, &yyscanner) != 0) {
4428             // Checking errno for the specific EINVAL, ENOMEM documented for
4429             // yylex_init_extra would not work as those values are not defined
4430             // by the C++ Standard:
4431             int e2 = errno;
4432             throw FileFormatException(
4433                 uri,
4434                 "yylex_init_extra failed with errno " + OUString::number(e2));
4435         }
4436         int e2 = yyparse(yyscanner);
4437         yylex_destroy(yyscanner);
4438         switch (e2) {
4439         case 0:
4440             break;
4441         default:
4442             O3TL_UNREACHABLE;
4443         case 1:
4444             throw FileFormatException(
4445                 uri,
4446                 ("cannot parse"
4447                  + (data->errorLine == 0
4448                     ? OUString() : " line " + OUString::number(data->errorLine))
4449                  + (data->parserError.isEmpty()
4450                     ? OUString()
4451                     : (", "
4452                        + OStringToOUString(
4453                            data->parserError, osl_getThreadTextEncoding())))
4454                  + (data->errorMessage.isEmpty()
4455                     ? OUString() : ": \"" + data->errorMessage + "\"")));
4456         case 2:
4457             throw std::bad_alloc();
4458         }
4459     } catch (...) {
4460         e = osl_unmapMappedFile(handle, address, size);
4461         SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot unmap: " << +e);
4462         e = osl_closeFile(handle);
4463         SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot close: " << +e);
4464         throw;
4465     }
4466     e = osl_unmapMappedFile(handle, address, size);
4467     SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot unmap: " << +e);
4468     e = osl_closeFile(handle);
4469     SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot close: " << +e);
4470     return true;
4471 }
4472 
4473 }
4474 
4475 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
4476