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