sw a11y: clang-format SidebarWinAccessible code
[LibreOffice.git] / unoidl / source / sourceprovider-parser.y
blob5e3dfac23be1139f1634d65777a5faed062b0c5a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 /*TODO: check Exception, RuntimeException, XInterface defns */
12 %locations
13 %pure-parser
17 #include <sal/config.h>
19 #include <o3tl/unreachable.hxx>
20 #include <o3tl/string_view.hxx>
21 #include <rtl/ustrbuf.hxx>
22 #include <unoidl/unoidl.hxx>
24 #include <algorithm>
25 #include <cassert>
26 #include <cerrno>
27 #include <cstddef>
28 #include <cstdlib>
29 #include <limits>
30 #include <new>
31 #include <utility>
32 #include <vector>
34 #include "sourceprovider-parser-requires.hxx"
38 %union {
39 sal_uInt64 ival;
40 double fval;
41 OString * sval;
43 bool bval;
44 std::vector<OUString> * excns;
45 unoidl::detail::SourceProviderAccessDecls decls;
46 unoidl::InterfaceTypeEntity::Method::Parameter::Direction dir;
47 unoidl::detail::SourceProviderFlags flags;
48 unoidl::detail::SourceProviderExpr expr;
49 unoidl::detail::SourceProviderType * type;
50 std::vector<unoidl::detail::SourceProviderType> * types;
53 /* TODO: %destructor { delete $$; } <sval> <excns> <type> <types> */
55 %lex-param {yyscan_t yyscanner}
56 %parse-param {yyscan_t yyscanner}
60 #include <osl/file.h>
61 #include <osl/thread.h>
62 #include <sal/log.hxx>
64 #include "sourceprovider-scanner.hxx"
66 #define YYLLOC_DEFAULT(Current, Rhs, N) \
67 do { (Current) = YYRHSLOC((Rhs), (N) ? 1 : 0); } while (0)
69 static void yyerror(YYLTYPE * locp, yyscan_t yyscanner, char const * msg) {
70 assert(locp != nullptr);
71 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
72 data->errorLine = *locp;
73 data->parserError = OString(msg);
76 namespace {
78 void error(YYLTYPE location, yyscan_t yyscanner, OUString const & message) {
79 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
80 data->errorLine = location;
81 data->errorMessage = message;
84 OUString flagName(unoidl::detail::SourceProviderFlags flag) {
85 switch (flag) {
86 case unoidl::detail::FLAG_ATTRIBUTE:
87 return u"attribute"_ustr;
88 case unoidl::detail::FLAG_BOUND:
89 return u"bound"_ustr;
90 case unoidl::detail::FLAG_CONSTRAINED:
91 return u"constrained"_ustr;
92 case unoidl::detail::FLAG_MAYBEAMBIGUOUS:
93 return u"maybeambiguous"_ustr;
94 case unoidl::detail::FLAG_MAYBEDEFAULT:
95 return u"maybedefault"_ustr;
96 case unoidl::detail::FLAG_MAYBEVOID:
97 return u"maybevoid"_ustr;
98 case unoidl::detail::FLAG_OPTIONAL:
99 return u"optional"_ustr;
100 case unoidl::detail::FLAG_PROPERTY:
101 return u"property"_ustr;
102 case unoidl::detail::FLAG_READONLY:
103 return u"readonly"_ustr;
104 case unoidl::detail::FLAG_REMOVABLE:
105 return u"removable"_ustr;
106 case unoidl::detail::FLAG_TRANSIENT:
107 return u"transient"_ustr;
108 default:
109 assert(false && "this cannot happen"); for (;;) { std::abort(); }
113 OUString convertName(OString const * name) {
114 assert(name != nullptr);
115 OUString s(OStringToOUString(*name, RTL_TEXTENCODING_ASCII_US));
116 delete name;
117 return s;
120 OUString convertToFullName(
121 unoidl::detail::SourceProviderScannerData const * data,
122 OString const * identifier)
124 assert(data != nullptr);
125 OUString pref;
126 if (!data->modules.empty()) {
127 pref = data->modules.back() + ".";
129 return pref + convertName(identifier);
132 void convertToCurrentName(
133 unoidl::detail::SourceProviderScannerData * data,
134 OString const * identifier)
136 assert(data != nullptr);
137 assert(data->currentName.isEmpty());
138 data->currentName = convertToFullName(data, identifier);
139 assert(!data->currentName.isEmpty());
142 void clearCurrentState(unoidl::detail::SourceProviderScannerData * data) {
143 assert(data != nullptr);
144 data->currentName.clear();
145 data->publishedContext = false;
148 unoidl::detail::SourceProviderEntity * getCurrentEntity(
149 unoidl::detail::SourceProviderScannerData * data)
151 assert(data != nullptr);
152 assert(!data->currentName.isEmpty());
153 std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator i(
154 data->entities.find(data->currentName));
155 assert(i != data->entities.end());
156 assert(i->second.kind == unoidl::detail::SourceProviderEntity::KIND_LOCAL);
157 assert(i->second.pad.is());
158 return &i->second;
161 template<typename T> rtl::Reference<T> getCurrentPad(
162 unoidl::detail::SourceProviderScannerData * data)
164 rtl::Reference<T> pad(dynamic_cast<T *>(getCurrentEntity(data)->pad.get()));
165 assert(pad.is());
166 return pad;
169 bool nameHasSameIdentifierAs(std::u16string_view name, std::u16string_view identifier)
171 std::u16string_view::size_type pos = name.rfind('.');
172 size_t i = (pos != std::u16string_view::npos) ? pos + 1 : 0;
173 return identifier.size() == name.size() - i
174 && o3tl::starts_with(name.substr(i), identifier);
177 bool coerce(
178 YYLTYPE location, yyscan_t yyscanner,
179 unoidl::detail::SourceProviderExpr * lhs,
180 unoidl::detail::SourceProviderExpr * rhs)
182 assert(lhs != nullptr);
183 assert(rhs != nullptr);
184 bool ok = bool(); // avoid warnings
185 switch (lhs->type) {
186 case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
187 ok = rhs->type != unoidl::detail::SourceProviderExpr::TYPE_BOOL;
188 break;
189 case unoidl::detail::SourceProviderExpr::TYPE_INT:
190 switch (rhs->type) {
191 case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
192 ok = false;
193 break;
194 case unoidl::detail::SourceProviderExpr::TYPE_INT:
195 ok = true;
196 break;
197 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
198 if (lhs->ival >= 0) {
199 lhs->type = unoidl::detail::SourceProviderExpr::TYPE_UINT;
200 ok = true;
201 } else if (rhs->uval <= SAL_MAX_INT64) {
202 rhs->type = unoidl::detail::SourceProviderExpr::TYPE_INT;
203 ok = true;
204 } else {
205 ok = false;
207 break;
208 case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
210 auto tmp = lhs->ival;
211 lhs->fval = tmp;
212 ok = true;
214 break;
216 break;
217 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
218 switch (rhs->type) {
219 case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
220 ok = false;
221 break;
222 case unoidl::detail::SourceProviderExpr::TYPE_INT:
223 if (rhs->ival >= 0) {
224 rhs->type = unoidl::detail::SourceProviderExpr::TYPE_UINT;
225 ok = true;
226 } else if (lhs->uval <= SAL_MAX_INT64) {
227 lhs->type = unoidl::detail::SourceProviderExpr::TYPE_INT;
228 ok = true;
229 } else {
230 ok = false;
232 break;
233 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
234 ok = true;
235 break;
236 case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
238 auto nTmp = lhs->uval;
239 lhs->fval = nTmp;
240 ok = true;
242 break;
244 break;
245 case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
246 switch (rhs->type) {
247 case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
248 ok = false;
249 break;
250 case unoidl::detail::SourceProviderExpr::TYPE_INT:
252 auto tmp = rhs->ival;
253 rhs->fval = tmp;
254 ok = true;
256 break;
257 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
259 auto tmp = rhs->uval;
260 rhs->fval = tmp;
261 ok = true;
263 break;
264 case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
265 ok = true;
266 break;
268 break;
270 if (!ok) {
271 error(location, yyscanner, u"cannot coerce binary expression arguments"_ustr);
273 return ok;
276 unoidl::detail::SourceProviderEntity * findEntity_(
277 unoidl::detail::SourceProviderScannerData * data, OUString * name)
279 assert(data != nullptr);
280 assert(name != nullptr);
281 OUString n;
282 if (!name->startsWith(".", &n)) {
283 for (auto i(data->modules.rbegin()); i != data->modules.rend(); ++i) {
284 n = *i + "." + *name;
285 std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator j(
286 data->entities.find(n));
287 if (j != data->entities.end()) {
288 *name = n;
289 return &j->second;
291 rtl::Reference<unoidl::Entity> ent(data->manager->findEntity(n));
292 if (ent.is()) {
293 std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator
294 k(data->entities.emplace(
296 unoidl::detail::SourceProviderEntity(
297 unoidl::detail::SourceProviderEntity::KIND_EXTERNAL,
298 ent)).
299 first);
300 *name = n;
301 return &k->second;
304 n = *name;
306 std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator i(
307 data->entities.find(n));
308 if (i != data->entities.end()) {
309 *name = n;
310 return &i->second;
312 rtl::Reference<unoidl::Entity> ent(data->manager->findEntity(n));
313 if (ent.is()) {
314 std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator
315 j(data->entities.emplace(
317 unoidl::detail::SourceProviderEntity(
318 unoidl::detail::SourceProviderEntity::KIND_EXTERNAL,
319 ent)).
320 first);
321 *name = n;
322 return &j->second;
324 return nullptr;
327 enum Found { FOUND_ERROR, FOUND_TYPE, FOUND_ENTITY };
329 Found findEntity(
330 YYLTYPE location, yyscan_t yyscanner,
331 unoidl::detail::SourceProviderScannerData * data,
332 bool resolveInterfaceDefinitions, OUString * name,
333 unoidl::detail::SourceProviderEntity const ** entity, bool * typedefed,
334 unoidl::detail::SourceProviderType * typedefedType)
336 //TODO: avoid recursion
337 assert(data != nullptr);
338 assert(name != nullptr);
339 assert(entity != nullptr);
340 unoidl::detail::SourceProviderEntity * e = findEntity_(data, name);
341 OUString n(*name);
342 OUString typeNucleus;
343 std::size_t rank = 0;
344 std::vector<unoidl::detail::SourceProviderType> args;
345 for (;;) {
346 if (e != nullptr) {
347 switch (e->kind) {
348 case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
349 if (e->pad.is()) {
350 break;
352 assert(e->entity.is());
353 [[fallthrough]];
354 case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
355 if (e->entity->getSort() == unoidl::Entity::SORT_TYPEDEF) {
356 if (typedefed != nullptr) {
357 *typedefed = true;
359 if (data->publishedContext
360 && !static_cast<unoidl::TypedefEntity *>(
361 e->entity.get())->isPublished())
363 error(
364 location, yyscanner,
365 ("type " + *name + " based on unpublished typedef "
366 + n + " used in published context"));
367 return FOUND_ERROR;
369 OUString t(
370 static_cast<unoidl::TypedefEntity *>(e->entity.get())
371 ->getType());
372 typeNucleus = t;
373 while (typeNucleus.startsWith("[]", &typeNucleus)) {
374 if (!args.empty()) {
375 error(
376 location, yyscanner,
377 ("inconsistent type manager: bad type " + *name
378 + (" based on instantiated polymorphic struct"
379 " type based on sequence type named ")
380 + t));
381 return FOUND_ERROR;
383 if (rank == std::numeric_limits<std::size_t>::max()) {
384 error(
385 location, yyscanner,
386 ("bad type " + *name
387 + " based on sequence type of too high rank"));
388 return FOUND_ERROR;
390 ++rank;
392 sal_Int32 i = typeNucleus.indexOf('<');
393 if (i != -1) {
394 if (!args.empty()) {
395 error(
396 location, yyscanner,
397 ("inconsistent type manager: bad type " + *name
398 + (" based on instantiated polymorphic struct"
399 " type based on instantiated polymorphic"
400 " struct type named ")
401 + t));
402 return FOUND_ERROR;
404 std::u16string_view tmpl(typeNucleus.subView(0, i));
405 do {
406 ++i; // skip '<' or ','
407 sal_Int32 j = i;
408 for (sal_Int32 level = 0;
409 j != typeNucleus.getLength(); ++j)
411 sal_Unicode c = typeNucleus[j];
412 if (c == ',') {
413 if (level == 0) {
414 break;
416 } else if (c == '<') {
417 ++level;
418 } else if (c == '>') {
419 if (level == 0) {
420 break;
422 --level;
425 if (j != typeNucleus.getLength()) {
426 OUString argName(typeNucleus.copy(i, j - i));
427 unoidl::detail::SourceProviderEntity const *
428 argEnt;
429 unoidl::detail::SourceProviderType argType;
430 switch (
431 findEntity(
432 location, yyscanner, data, false,
433 &argName, &argEnt, nullptr, &argType))
435 case FOUND_ERROR:
436 return FOUND_ERROR;
437 case FOUND_TYPE:
438 break;
439 case FOUND_ENTITY:
440 if (argEnt == nullptr) {
441 error(
442 location, yyscanner,
443 (("inconsistent type manager: bad"
444 " instantiated polymorphic struct"
445 " type template type argument ")
446 + argName));
447 return FOUND_ERROR;
448 } else {
449 unoidl::detail::SourceProviderType::Type
450 argT
451 = unoidl::detail::SourceProviderType::Type();
452 // avoid warnings
453 switch (argEnt->kind) {
454 case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
455 if (e->pad.is()) {
456 error(
457 location, yyscanner,
458 (("inconsistent type"
459 " manager: bad"
460 " instantiated"
461 " polymorphic struct type"
462 " template type"
463 " argument ")
464 + argName));
465 return FOUND_ERROR;
467 assert(e->entity.is());
468 [[fallthrough]];
469 case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
470 switch (e->entity->getSort()) {
471 case unoidl::Entity::SORT_ENUM_TYPE:
472 argT = unoidl::detail::SourceProviderType::TYPE_ENUM;
473 break;
474 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
475 argT = unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT;
476 break;
477 case unoidl::Entity::SORT_INTERFACE_TYPE:
478 argT = unoidl::detail::SourceProviderType::TYPE_INTERFACE;
479 break;
480 default:
481 error(
482 location, yyscanner,
483 (("inconsistent type"
484 "manager: bad"
485 " instantiated"
486 " polymorphic struct type"
487 " template type"
488 " argument ")
489 + argName));
490 return FOUND_ERROR;
492 break;
493 case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
494 case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
495 argT = unoidl::detail::SourceProviderType::TYPE_INTERFACE;
496 break;
497 case unoidl::detail::SourceProviderEntity::KIND_MODULE:
498 assert(false && "this cannot happen");
500 argType
501 = unoidl::detail::SourceProviderType(
502 argT, argName, argEnt);
504 break;
506 args.push_back(argType);
508 i = j;
509 } while (i != typeNucleus.getLength()
510 && typeNucleus[i] != '>');
511 if (i != typeNucleus.getLength() - 1
512 || typeNucleus[i] != '>')
514 error(
515 location, yyscanner,
516 ("inconsistent type manager: bad type name \""
517 + t + "\""));
518 return FOUND_ERROR;
520 assert(!args.empty());
521 typeNucleus = tmpl;
523 if (typeNucleus.isEmpty()) {
524 error(
525 location, yyscanner,
526 ("inconsistent type manager: bad type name \"" + t
527 + "\""));
528 return FOUND_ERROR;
530 if (typeNucleus == "void") {
531 error(
532 location, yyscanner,
533 ("inconsistent type manager: bad type " + *name
534 + " based on void"));
535 return FOUND_ERROR;
537 if (typeNucleus == "boolean" || typeNucleus == "byte"
538 || typeNucleus == "short"
539 || typeNucleus == "unsigned short"
540 || typeNucleus == "long"
541 || typeNucleus == "unsigned long"
542 || typeNucleus == "hyper"
543 || typeNucleus == "unsigned hyper"
544 || typeNucleus == "float" || typeNucleus == "double"
545 || typeNucleus == "char" || typeNucleus == "string"
546 || typeNucleus == "type" || typeNucleus == "any")
548 if (!args.empty()) {
549 error(
550 location, yyscanner,
551 ("inconsistent type manager: bad type " + *name
552 + (" based on instantiated polymorphic struct"
553 " type based on ")
554 + typeNucleus));
555 return FOUND_ERROR;
557 break;
559 n = "." + typeNucleus;
560 typeNucleus.clear();
561 e = findEntity_(data, &n);
562 continue;
564 break;
565 case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
566 case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
567 if (resolveInterfaceDefinitions) {
568 rtl::Reference<unoidl::Entity> ent(
569 data->manager->findEntity(n));
570 // Do not allow ent to be of SORT_TYPEDEF:
571 if (!ent.is()
572 || (ent->getSort()
573 != unoidl::Entity::SORT_INTERFACE_TYPE))
575 error(
576 location, yyscanner,
577 (*name + " is based on interface declaration " + n
578 + " that is not an interface type entity"));
579 return FOUND_ERROR;
581 e->kind
582 = unoidl::detail::SourceProviderEntity::KIND_EXTERNAL;
583 e->entity = std::move(ent);
585 break;
586 case unoidl::detail::SourceProviderEntity::KIND_MODULE:
587 error(
588 location, yyscanner,
589 *name + " is based on module entity " + n);
590 return FOUND_ERROR;
593 if (!typeNucleus.isEmpty() || rank != 0 || !args.empty()) {
594 if (typeNucleus.isEmpty() && e == nullptr) {
595 // Found a type name based on an unknown entity:
596 *entity = nullptr;
597 return FOUND_ENTITY;
599 unoidl::detail::SourceProviderType t;
600 if (args.empty()) {
601 if (typeNucleus == "boolean") {
602 t = unoidl::detail::SourceProviderType(
603 unoidl::detail::SourceProviderType::TYPE_BOOLEAN);
604 } else if (typeNucleus == "byte") {
605 t = unoidl::detail::SourceProviderType(
606 unoidl::detail::SourceProviderType::TYPE_BYTE);
607 } else if (typeNucleus == "short") {
608 t = unoidl::detail::SourceProviderType(
609 unoidl::detail::SourceProviderType::TYPE_SHORT);
610 } else if (typeNucleus == "unsigned short") {
611 t = unoidl::detail::SourceProviderType(
612 unoidl::detail::SourceProviderType::TYPE_UNSIGNED_SHORT);
613 } else if (typeNucleus == "long") {
614 t = unoidl::detail::SourceProviderType(
615 unoidl::detail::SourceProviderType::TYPE_LONG);
616 } else if (typeNucleus == "unsigned long") {
617 t = unoidl::detail::SourceProviderType(
618 unoidl::detail::SourceProviderType::TYPE_UNSIGNED_LONG);
619 } else if (typeNucleus == "hyper") {
620 t = unoidl::detail::SourceProviderType(
621 unoidl::detail::SourceProviderType::TYPE_HYPER);
622 } else if (typeNucleus == "unsigned hyper") {
623 t = unoidl::detail::SourceProviderType(
624 unoidl::detail::SourceProviderType::TYPE_UNSIGNED_HYPER);
625 } else if (typeNucleus == "float") {
626 t = unoidl::detail::SourceProviderType(
627 unoidl::detail::SourceProviderType::TYPE_FLOAT);
628 } else if (typeNucleus == "double") {
629 t = unoidl::detail::SourceProviderType(
630 unoidl::detail::SourceProviderType::TYPE_DOUBLE);
631 } else if (typeNucleus == "char") {
632 t = unoidl::detail::SourceProviderType(
633 unoidl::detail::SourceProviderType::TYPE_CHAR);
634 } else if (typeNucleus == "string") {
635 t = unoidl::detail::SourceProviderType(
636 unoidl::detail::SourceProviderType::TYPE_STRING);
637 } else if (typeNucleus == "type") {
638 t = unoidl::detail::SourceProviderType(
639 unoidl::detail::SourceProviderType::TYPE_TYPE);
640 } else if (typeNucleus == "any") {
641 t = unoidl::detail::SourceProviderType(
642 unoidl::detail::SourceProviderType::TYPE_ANY);
643 } else {
644 assert(typeNucleus.isEmpty());
645 assert(e != nullptr);
646 switch (e->kind) {
647 case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
648 if (e->pad.is()) {
649 if (dynamic_cast<unoidl::detail::SourceProviderEnumTypeEntityPad *>(
650 e->pad.get())
651 != nullptr)
653 t = unoidl::detail::SourceProviderType(
654 unoidl::detail::SourceProviderType::TYPE_ENUM,
655 n, e);
656 } else if (dynamic_cast<unoidl::detail::SourceProviderPlainStructTypeEntityPad *>(
657 e->pad.get())
658 != nullptr)
660 t = unoidl::detail::SourceProviderType(
661 unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT,
662 n, e);
663 } else if (dynamic_cast<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
664 e->pad.get())
665 != nullptr)
667 error(
668 location, yyscanner,
669 ("bad type " + *name
670 + (" based on recursive reference to"
671 " polymorphic struct type template ")
672 + n));
673 return FOUND_ERROR;
674 } else if (dynamic_cast<unoidl::detail::SourceProviderExceptionTypeEntityPad *>(
675 e->pad.get())
676 != nullptr)
678 t = unoidl::detail::SourceProviderType(
679 unoidl::detail::SourceProviderType::TYPE_EXCEPTION,
680 n, e);
681 } else if (dynamic_cast<unoidl::detail::SourceProviderInterfaceTypeEntityPad *>(
682 e->pad.get())
683 != nullptr)
685 t = unoidl::detail::SourceProviderType(
686 unoidl::detail::SourceProviderType::TYPE_INTERFACE,
687 n, e);
688 } else {
689 error(
690 location, yyscanner,
691 ("bad type " + *name
692 + " based on non-type entity " + n));
693 return FOUND_ERROR;
695 break;
697 assert(e->entity.is());
698 [[fallthrough]];
699 case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
700 switch (e->entity->getSort()) {
701 case unoidl::Entity::SORT_ENUM_TYPE:
702 t = unoidl::detail::SourceProviderType(
703 unoidl::detail::SourceProviderType::TYPE_ENUM,
704 n, e);
705 break;
706 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
707 t = unoidl::detail::SourceProviderType(
708 unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT,
709 n, e);
710 break;
711 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
712 error(
713 location, yyscanner,
714 ("bad type " + *name
715 + " based on polymorphic struct type template "
716 + n + " without type arguments"));
717 return FOUND_ERROR;
718 case unoidl::Entity::SORT_EXCEPTION_TYPE:
719 t = unoidl::detail::SourceProviderType(
720 unoidl::detail::SourceProviderType::TYPE_EXCEPTION,
721 n, e);
722 break;
723 case unoidl::Entity::SORT_INTERFACE_TYPE:
724 t = unoidl::detail::SourceProviderType(
725 unoidl::detail::SourceProviderType::TYPE_INTERFACE,
726 n, e);
727 break;
728 default:
729 error(
730 location, yyscanner,
731 ("bad type " + *name
732 + " based on non-type entity " + n));
733 return FOUND_ERROR;
735 break;
736 case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
737 case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
738 t = unoidl::detail::SourceProviderType(
739 unoidl::detail::SourceProviderType::TYPE_INTERFACE,
740 n, e);
741 break;
742 case unoidl::detail::SourceProviderEntity::KIND_MODULE:
743 assert(false && "this cannot happen");
746 } else {
747 assert(typeNucleus.isEmpty());
748 assert(e != nullptr);
749 switch (e->kind) {
750 case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
751 if (e->pad.is()) {
752 error(
753 location, yyscanner,
754 ("bad type " + *name
755 + (" based on instantiated polymorphic struct type"
756 " based on ")
758 + (" that is either not a polymorphic struct type"
759 " template or a recursive reference to a"
760 " polymorphic struct type template")));
761 return FOUND_ERROR;
763 assert(e->entity.is());
764 [[fallthrough]];
765 case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
766 if (e->entity->getSort()
767 == unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE)
769 if (args.size()
770 != (static_cast<
771 unoidl::PolymorphicStructTypeTemplateEntity *>(
772 e->entity.get())
773 ->getTypeParameters().size()))
775 error(
776 location, yyscanner,
777 ("bad type " + *name
778 + (" based on instantiated polymorphic struct"
779 " type with ")
780 + OUString::number(args.size())
781 + (" type arguments based on polymorphic"
782 " struct type template ")
783 + n + " with "
784 + OUString::number(
785 static_cast<
786 unoidl::PolymorphicStructTypeTemplateEntity *>(
787 e->entity.get())
788 ->getTypeParameters().size())
789 + " type parameters"));
790 return FOUND_ERROR;
792 t = unoidl::detail::SourceProviderType(n, e, std::move(args));
793 break;
795 [[fallthrough]];
796 case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
797 case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
798 error(
799 location, yyscanner,
800 ("bad type " + *name
801 + (" based on instantiated polymorphic struct type"
802 " based on ")
804 + " that is not a polymorphic struct type template"));
805 return FOUND_ERROR;
806 case unoidl::detail::SourceProviderEntity::KIND_MODULE:
807 assert(false && "this cannot happen");
810 if (typedefedType != nullptr) {
811 for (std::size_t i = 0; i != rank; ++i) {
812 t = unoidl::detail::SourceProviderType(&t);
814 *typedefedType = std::move(t);
815 typedefedType->typedefName = *name;
817 *entity = nullptr;
818 return FOUND_TYPE;
820 *entity = e;
821 return FOUND_ENTITY;
826 bool checkTypeArgument(
827 YYLTYPE location, yyscan_t yyscanner,
828 unoidl::detail::SourceProviderType const & type)
830 switch (type.type) {
831 case unoidl::detail::SourceProviderType::TYPE_VOID:
832 case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_SHORT:
833 case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_LONG:
834 case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_HYPER:
835 case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
836 case unoidl::detail::SourceProviderType::TYPE_PARAMETER: //TODO?
837 error(
838 location, yyscanner,
839 u"bad instantiated polymorphic struct type argument"_ustr);
840 return false;
841 case unoidl::detail::SourceProviderType::TYPE_SEQUENCE:
842 return checkTypeArgument(location, yyscanner, type.subtypes.front());
843 default:
844 return true;
848 bool checkInstantiatedPolymorphicStructTypeArgument(
849 unoidl::detail::SourceProviderType const & type, OUString const & name)
851 if (type.type
852 == unoidl::detail::SourceProviderType::TYPE_INSTANTIATED_POLYMORPHIC_STRUCT)
854 for (auto & i: type.subtypes) {
855 if (checkInstantiatedPolymorphicStructTypeArgument(i, name)
856 || i.getName() == name) // no need to worry about typedef
858 return true;
862 return false;
865 std::vector<OUString> annotations(bool deprecated) {
866 std::vector<OUString> ann;
867 if (deprecated) {
868 ann.push_back(u"deprecated"_ustr);
870 return ann;
877 %token TOK_ELLIPSIS
878 %token TOK_COLONS
879 %token TOK_LEFTSHIFT
880 %token TOK_RIGHTSHIFT
882 %token TOK_FALSE
883 %token TOK_TRUE
884 %token TOK_ANY
885 %token TOK_ATTRIBUTE
886 %token TOK_BOOLEAN
887 %token TOK_BOUND
888 %token TOK_BYTE
889 %token TOK_CHAR
890 %token TOK_CONST
891 %token TOK_CONSTANTS
892 %token TOK_CONSTRAINED
893 %token TOK_DOUBLE
894 %token TOK_ENUM
895 %token TOK_EXCEPTION
896 %token TOK_FLOAT
897 %token TOK_GET
898 %token TOK_HYPER
899 %token TOK_IN
900 %token TOK_INOUT
901 %token TOK_INTERFACE
902 %token TOK_LONG
903 %token TOK_MAYBEAMBIGUOUS
904 %token TOK_MAYBEDEFAULT
905 %token TOK_MAYBEVOID
906 %token TOK_MODULE
907 %token TOK_OPTIONAL
908 %token TOK_OUT
909 %token TOK_PROPERTY
910 %token TOK_PUBLISHED
911 %token TOK_RAISES
912 %token TOK_READONLY
913 %token TOK_REMOVABLE
914 %token TOK_SEQUENCE
915 %token TOK_SERVICE
916 %token TOK_SET
917 %token TOK_SHORT
918 %token TOK_SINGLETON
919 %token TOK_STRING
920 %token TOK_STRUCT
921 %token TOK_TRANSIENT
922 %token TOK_TYPE
923 %token TOK_TYPEDEF
924 %token TOK_UNSIGNED
925 %token TOK_VOID
927 %token<sval> TOK_IDENTIFIER
928 %token<ival> TOK_INTEGER
929 %token<fval> TOK_FLOATING
931 %token TOK_DEPRECATED
933 %token TOK_ERROR
935 %type<sval> identifier name singleInheritance singleInheritance_opt
936 %type<bval> ctors_opt deprecated_opt ellipsis_opt published_opt
937 %type<decls> attributeAccessDecl attributeAccessDecls
938 %type<dir> direction
939 %type<excns> exceptionSpec exceptionSpec_opt exceptions
940 %type<flags> flag flagSection flagSection_opt flags
941 %type<expr> addExpr andExpr expr multExpr orExpr primaryExpr shiftExpr unaryExpr
942 xorExpr
943 %type<type> type
944 %type<types> typeArguments
946 %initial-action { yylloc = 1; }
950 definitions:
951 definitions definition
952 | /* empty */
955 definition:
956 moduleDecl
957 | enumDefn
958 | plainStructDefn
959 | polymorphicStructTemplateDefn
960 | exceptionDefn
961 | interfaceDefn
962 | typedefDefn
963 | constantGroupDefn
964 | singleInterfaceBasedServiceDefn
965 | accumulationBasedServiceDefn
966 | interfaceBasedSingletonDefn
967 | serviceBasedSingletonDefn
968 | interfaceDecl
971 moduleDecl:
972 TOK_MODULE identifier
974 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
975 OUString name(convertToFullName(data, $2));
976 data->modules.push_back(name);
977 std::pair<std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator, bool> p(
978 data->entities.emplace(
979 name,
980 unoidl::detail::SourceProviderEntity(
981 unoidl::detail::SourceProviderEntity::KIND_MODULE)));
982 if (!p.second
983 && (p.first->second.kind
984 != unoidl::detail::SourceProviderEntity::KIND_MODULE))
986 error(@2, yyscanner, "multiple entities named " + name);
987 YYERROR;
990 '{' definitions '}' ';' { yyget_extra(yyscanner)->modules.pop_back(); }
993 enumDefn:
994 deprecated_opt published_opt TOK_ENUM identifier
996 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
997 data->publishedContext = $2;
998 convertToCurrentName(data, $4);
999 if (!data->entities.emplace(
1000 data->currentName,
1001 unoidl::detail::SourceProviderEntity(
1002 new unoidl::detail::SourceProviderEnumTypeEntityPad(
1003 $2))).
1004 second)
1006 error(@4, yyscanner, "multiple entities named " + data->currentName);
1007 YYERROR;
1010 '{' enumMembers '}' ';'
1012 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1013 unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
1014 unoidl::detail::SourceProviderEnumTypeEntityPad * pad =
1015 dynamic_cast<unoidl::detail::SourceProviderEnumTypeEntityPad *>(
1016 ent->pad.get());
1017 assert(pad != nullptr);
1018 ent->entity = new unoidl::EnumTypeEntity(
1019 pad->isPublished(), std::move(pad->members), annotations($1));
1020 ent->pad.clear();
1021 clearCurrentState(data);
1025 enumMembers:
1026 | enumMembers ',' enumMember
1027 | enumMember
1030 enumMember:
1031 deprecated_opt identifier
1033 OUString id(convertName($2));
1034 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1035 rtl::Reference<unoidl::detail::SourceProviderEnumTypeEntityPad> pad(
1036 getCurrentPad<unoidl::detail::SourceProviderEnumTypeEntityPad>(data));
1037 sal_Int32 v;
1038 if (pad->members.empty()) {
1039 v = 0;
1040 } else {
1041 v = pad->members.back().value;
1042 if (v == SAL_MAX_INT32) {
1043 error(
1044 @2, yyscanner,
1045 ("enum " + data->currentName + " member " + id
1046 + " would have out-of-range value 2^31"));
1047 YYERROR;
1049 ++v;
1051 pad->members.emplace_back(id, v, annotations($1));
1053 | deprecated_opt identifier '=' expr
1055 OUString id(convertName($2));
1056 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1057 rtl::Reference<unoidl::detail::SourceProviderEnumTypeEntityPad> pad(
1058 getCurrentPad<unoidl::detail::SourceProviderEnumTypeEntityPad>(data));
1059 sal_Int32 v;
1060 switch ($4.type) {
1061 case unoidl::detail::SourceProviderExpr::TYPE_INT:
1062 if ($4.ival < SAL_MIN_INT32 || $4.ival > SAL_MAX_INT32) {
1063 error(
1064 @4, yyscanner,
1065 ("out-of-range enum " + data->currentName + " member " + id
1066 + " value " + OUString::number($4.ival)));
1067 YYERROR;
1069 v = static_cast<sal_Int32>($4.ival);
1070 break;
1071 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
1072 if ($4.uval > SAL_MAX_INT32) {
1073 error(
1074 @4, yyscanner,
1075 ("out-of-range enum " + data->currentName + " member " + id
1076 + " value " + OUString::number($4.uval)));
1077 YYERROR;
1079 v = static_cast<sal_Int32>($4.uval);
1080 break;
1081 default:
1082 error(
1083 @4, yyscanner,
1084 ("non-integer enum " + data->currentName + " member " + id
1085 + " value"));
1086 YYERROR;
1087 break;
1089 pad->members.emplace_back(id, v, annotations($1));
1093 plainStructDefn:
1094 deprecated_opt published_opt TOK_STRUCT identifier singleInheritance_opt
1096 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1097 data->publishedContext = $2;
1098 convertToCurrentName(data, $4);
1099 OUString baseName;
1100 rtl::Reference<unoidl::PlainStructTypeEntity> baseEnt;
1101 if ($5 != nullptr) {
1102 baseName = convertName($5);
1103 unoidl::detail::SourceProviderEntity const * p;
1104 if (findEntity(
1105 @5, yyscanner, data, false, &baseName, &p, nullptr, nullptr)
1106 == FOUND_ERROR)
1108 YYERROR;
1110 if (p == nullptr || !p->entity.is()
1111 || p->entity->getSort() != unoidl::Entity::SORT_PLAIN_STRUCT_TYPE)
1113 error(
1114 @5, yyscanner,
1115 ("plain struct type " + data->currentName + " base "
1116 + baseName
1117 + " does not resolve to an existing plain struct type"));
1118 YYERROR;
1120 baseEnt = static_cast<unoidl::PlainStructTypeEntity *>(
1121 p->entity.get());
1122 if ($2 && !baseEnt->isPublished()) {
1123 error(
1124 @5, yyscanner,
1125 ("published plain struct type " + data->currentName + " base "
1126 + baseName + " is unpublished"));
1127 YYERROR;
1130 if (!data->entities.emplace(
1131 data->currentName,
1132 unoidl::detail::SourceProviderEntity(
1133 new unoidl::detail::SourceProviderPlainStructTypeEntityPad(
1134 $2, baseName, baseEnt))).
1135 second)
1137 error(@4, yyscanner, "multiple entities named " + data->currentName);
1138 YYERROR;
1141 '{' structMembers '}' ';'
1143 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1144 unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
1145 unoidl::detail::SourceProviderPlainStructTypeEntityPad * pad =
1146 dynamic_cast<
1147 unoidl::detail::SourceProviderPlainStructTypeEntityPad *>(
1148 ent->pad.get());
1149 assert(pad != nullptr);
1150 ent->entity = new unoidl::PlainStructTypeEntity(
1151 pad->isPublished(), pad->baseName, std::move(pad->members), annotations($1));
1152 ent->pad.clear();
1153 clearCurrentState(data);
1157 polymorphicStructTemplateDefn:
1158 deprecated_opt published_opt TOK_STRUCT identifier '<'
1160 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1161 data->publishedContext = $2;
1162 convertToCurrentName(data, $4);
1163 if (!data->entities.emplace(
1164 data->currentName,
1165 unoidl::detail::SourceProviderEntity(
1166 new unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad(
1167 $2))).
1168 second)
1170 error(@4, yyscanner, "multiple entities named " + data->currentName);
1171 YYERROR;
1174 typeParameters '>' '{' structMembers '}' ';'
1176 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1177 unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
1178 unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *
1179 pad = dynamic_cast<
1180 unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
1181 ent->pad.get());
1182 assert(pad != nullptr);
1183 ent->entity = new unoidl::PolymorphicStructTypeTemplateEntity(
1184 pad->isPublished(), std::move(pad->typeParameters), std::move(pad->members),
1185 annotations($1));
1186 ent->pad.clear();
1187 clearCurrentState(data);
1191 typeParameters:
1192 typeParameters ',' identifier
1194 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1195 rtl::Reference<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad>
1196 pad(getCurrentPad<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad>(
1197 data));
1198 OUString id(convertName($3));
1199 if (std::find(pad->typeParameters.begin(), pad->typeParameters.end(), id)
1200 != pad->typeParameters.end())
1202 error(
1203 @3, yyscanner,
1204 ("polymorphic struct type template " + data->currentName
1205 + " type parameter " + id
1206 + " has same identifier as another type parameter"));
1207 YYERROR;
1209 pad->typeParameters.push_back(id);
1211 | identifier
1213 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1214 rtl::Reference<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad>
1215 pad(getCurrentPad<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad>(
1216 data));
1217 OUString id(convertName($1));
1218 assert(pad->typeParameters.empty());
1219 pad->typeParameters.push_back(id);
1223 exceptionDefn:
1224 deprecated_opt published_opt TOK_EXCEPTION identifier singleInheritance_opt
1226 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1227 data->publishedContext = $2;
1228 convertToCurrentName(data, $4);
1229 OUString baseName;
1230 rtl::Reference<unoidl::ExceptionTypeEntity> baseEnt;
1231 if ($5 != nullptr) {
1232 baseName = convertName($5);
1233 unoidl::detail::SourceProviderEntity const * p;
1234 if (findEntity(
1235 @5, yyscanner, data, false, &baseName, &p, nullptr, nullptr)
1236 == FOUND_ERROR)
1238 YYERROR;
1240 if (p == nullptr || !p->entity.is()
1241 || p->entity->getSort() != unoidl::Entity::SORT_EXCEPTION_TYPE)
1243 error(
1244 @5, yyscanner,
1245 ("exception type " + data->currentName + " base " + baseName
1246 + " does not resolve to an existing exception type"));
1247 YYERROR;
1249 baseEnt = static_cast<unoidl::ExceptionTypeEntity *>(
1250 p->entity.get());
1251 if ($2 && !baseEnt->isPublished()) {
1252 error(
1253 @5, yyscanner,
1254 ("published exception type " + data->currentName + " base "
1255 + baseName + " is unpublished"));
1256 YYERROR;
1259 if (!data->entities.emplace(
1260 data->currentName,
1261 unoidl::detail::SourceProviderEntity(
1262 new unoidl::detail::SourceProviderExceptionTypeEntityPad(
1263 $2, baseName, baseEnt))).
1264 second)
1266 error(@4, yyscanner, "multiple entities named " + data->currentName);
1267 YYERROR;
1270 '{' structMembers '}' ';'
1272 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1273 unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
1274 unoidl::detail::SourceProviderExceptionTypeEntityPad * pad =
1275 dynamic_cast<unoidl::detail::SourceProviderExceptionTypeEntityPad *>(
1276 ent->pad.get());
1277 assert(pad != nullptr);
1278 ent->entity = new unoidl::ExceptionTypeEntity(
1279 pad->isPublished(), pad->baseName, std::move(pad->members), annotations($1));
1280 ent->pad.clear();
1281 clearCurrentState(data);
1285 structMembers:
1286 structMembers structMember
1287 | /* empty */
1290 structMember:
1291 deprecated_opt type identifier ';'
1293 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1294 unoidl::detail::SourceProviderType t(*$2);
1295 delete $2;
1296 OUString id(convertName($3));
1297 switch (t.type) {
1298 case unoidl::detail::SourceProviderType::TYPE_VOID:
1299 case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
1300 error(
1301 @2, yyscanner,
1302 ("illegal struct/exception type " + data->currentName
1303 + " direct member " + id + " type"));
1304 YYERROR;
1305 break;
1306 default:
1307 break;
1309 if (t.type != unoidl::detail::SourceProviderType::TYPE_PARAMETER
1310 && t.getName() == data->currentName) // no need to worry about typedef
1312 error(
1313 @2, yyscanner,
1314 ("struct/exception type " + data->currentName + " direct member "
1315 + id + " has same type as the type itself"));
1316 YYERROR;
1318 if (checkInstantiatedPolymorphicStructTypeArgument(t, data->currentName))
1320 error(
1321 @2, yyscanner,
1322 ("struct/exception type " + data->currentName + " direct member "
1323 + id
1324 + (" has instantiated polymorphic struct type that uses the type"
1325 " itself as an argument")));
1326 YYERROR;
1328 if (nameHasSameIdentifierAs(data->currentName, id)) {
1329 error(
1330 @3, yyscanner,
1331 ("struct/exception type " + data->currentName + " direct member "
1332 + id + " has same unqualified identifier as the type itself"));
1333 YYERROR;
1335 unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
1336 unoidl::detail::SourceProviderPlainStructTypeEntityPad * p1 =
1337 dynamic_cast<unoidl::detail::SourceProviderPlainStructTypeEntityPad *>(
1338 ent->pad.get());
1339 if (p1 != nullptr) {
1340 for (const auto & i: p1->members) {
1341 if (id == i.name) {
1342 error(
1343 @3, yyscanner,
1344 ("plain struct type " + data->currentName
1345 + " direct member " + id
1346 + " has same identifier as another direct member"));
1347 YYERROR;
1350 if (p1->baseEntity.is()) {
1351 OUString baseName(p1->baseName);
1352 for (auto baseEnt(p1->baseEntity);;) {
1353 if (nameHasSameIdentifierAs(baseName, id)) {
1354 error(
1355 @3, yyscanner,
1356 ("plain struct type " + data->currentName
1357 + " direct member " + id
1358 + " has same unqalified identifier as base "
1359 + baseName));
1360 YYERROR;
1362 for (auto & i: baseEnt->getDirectMembers()) {
1363 if (id == i.name) {
1364 error(
1365 @3, yyscanner,
1366 ("plain struct type " + data->currentName
1367 + " direct member " + id
1368 + " has same identifier as a member of base "
1369 + baseName));
1370 YYERROR;
1373 baseName = baseEnt->getDirectBase();
1374 if (baseName.isEmpty()) {
1375 break;
1377 unoidl::detail::SourceProviderEntity const * p;
1378 if (findEntity(
1379 @2, yyscanner, data, false, &baseName, &p, nullptr,
1380 nullptr)
1381 == FOUND_ERROR)
1383 YYERROR;
1385 if (p == nullptr || !p->entity.is()
1386 || (p->entity->getSort()
1387 != unoidl::Entity::SORT_PLAIN_STRUCT_TYPE))
1389 error(
1390 @2, yyscanner,
1391 ("inconsistent type manager: plain struct type "
1392 + data->currentName + " base " + baseName
1393 + (" does not resolve to an existing plain struct"
1394 " type")));
1395 YYERROR;
1397 baseEnt = static_cast<unoidl::PlainStructTypeEntity *>(
1398 p->entity.get());
1401 p1->members.emplace_back(id, t.getName(), annotations($1));
1402 } else {
1403 unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *
1404 p2 = dynamic_cast<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
1405 ent->pad.get());
1406 if (p2 != nullptr) {
1407 for (const auto & i: p2->members) {
1408 if (id == i.name) {
1409 error(
1410 @3, yyscanner,
1411 ("polymorphic struct type template "
1412 + data->currentName + " direct member " + id
1413 + " has same identifier as another direct member"));
1414 YYERROR;
1417 p2->members.emplace_back(
1418 id, t.getName(),
1419 t.type == unoidl::detail::SourceProviderType::TYPE_PARAMETER,
1420 annotations($1));
1421 } else {
1422 unoidl::detail::SourceProviderExceptionTypeEntityPad * p3
1423 = dynamic_cast<unoidl::detail::SourceProviderExceptionTypeEntityPad *>(
1424 ent->pad.get());
1425 assert(p3 != nullptr);
1426 for (const auto & i: p3->members) {
1427 if (id == i.name) {
1428 error(
1429 @3, yyscanner,
1430 ("exception type " + data->currentName
1431 + " direct member " + id
1432 + " has same identifier as another direct member"));
1433 YYERROR;
1436 if (p3->baseEntity.is()) {
1437 OUString baseName(p3->baseName);
1438 for (auto baseEnt(p3->baseEntity);;) {
1439 if (nameHasSameIdentifierAs(baseName, id)) {
1440 error(
1441 @3, yyscanner,
1442 ("exception type " + data->currentName
1443 + " direct member " + id
1444 + " has same unqalified identifier as base "
1445 + baseName));
1446 YYERROR;
1448 for (auto & i: baseEnt->getDirectMembers()) {
1449 if (id == i.name) {
1450 error(
1451 @3, yyscanner,
1452 ("exception type " + data->currentName
1453 + " direct member " + id
1454 + " has same identifier as a member of base "
1455 + baseName));
1456 YYERROR;
1459 baseName = baseEnt->getDirectBase();
1460 if (baseName.isEmpty()) {
1461 break;
1463 unoidl::detail::SourceProviderEntity const * p;
1464 if (findEntity(
1465 @2, yyscanner, data, false, &baseName, &p,
1466 nullptr, nullptr)
1467 == FOUND_ERROR)
1469 YYERROR;
1471 if (p == nullptr || !p->entity.is()
1472 || (p->entity->getSort()
1473 != unoidl::Entity::SORT_EXCEPTION_TYPE))
1475 error(
1476 @2, yyscanner,
1477 ("inconsistent type manager: exception type "
1478 + data->currentName + " base " + baseName
1479 + (" does not resolve to an existing exception"
1480 " type")));
1481 YYERROR;
1483 baseEnt = static_cast<unoidl::ExceptionTypeEntity *>(
1484 p->entity.get());
1487 p3->members.emplace_back(id, t.getName(), annotations($1));
1493 interfaceDefn:
1494 deprecated_opt published_opt TOK_INTERFACE identifier singleInheritance_opt
1496 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1497 data->publishedContext = $2;
1498 convertToCurrentName(data, $4);
1499 OUString baseName;
1500 rtl::Reference<unoidl::InterfaceTypeEntity> baseEnt;
1501 if ($5 != nullptr) {
1502 baseName = convertName($5);
1503 unoidl::detail::SourceProviderEntity const * p;
1504 if (findEntity(
1505 @5, yyscanner, data, true, &baseName, &p, nullptr, nullptr)
1506 == FOUND_ERROR)
1508 YYERROR;
1510 if (p == nullptr || !p->entity.is()
1511 || p->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
1513 error(
1514 @5, yyscanner,
1515 ("interface type " + data->currentName + " direct base "
1516 + baseName
1517 + " does not resolve to an existing interface type"));
1518 YYERROR;
1520 baseEnt = static_cast<unoidl::InterfaceTypeEntity *>(p->entity.get());
1521 if ($2 && !baseEnt->isPublished()) {
1522 error(
1523 @5, yyscanner,
1524 ("published interface type " + data->currentName
1525 + " direct base " + baseName + " is unpublished"));
1526 YYERROR;
1529 std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator i(
1530 data->entities.find(data->currentName));
1531 if (i != data->entities.end()) {
1532 switch (i->second.kind) {
1533 case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
1534 break;
1535 case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
1536 if (!$2) {
1537 error(
1538 @4, yyscanner,
1539 ("unpublished interface type " + data->currentName
1540 + " has been declared published"));
1541 YYERROR;
1543 break;
1544 default:
1545 error(
1546 @4, yyscanner,
1547 "multiple entities named " + data->currentName);
1548 YYERROR;
1549 break;
1552 rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad> pad(
1553 new unoidl::detail::SourceProviderInterfaceTypeEntityPad(
1554 $2, baseEnt.is()));
1555 if (baseEnt.is()
1556 && !pad->addDirectBase(
1557 @4, yyscanner, data,
1558 unoidl::detail::SourceProviderInterfaceTypeEntityPad::DirectBase(
1559 baseName, baseEnt, std::vector<OUString>()),
1560 false))
1562 YYERROR;
1564 data->entities[data->currentName] = unoidl::detail::SourceProviderEntity(
1565 pad);
1567 '{' interfaceMembers '}' ';'
1569 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1570 unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
1571 unoidl::detail::SourceProviderInterfaceTypeEntityPad * pad =
1572 dynamic_cast<unoidl::detail::SourceProviderInterfaceTypeEntityPad *>(
1573 ent->pad.get());
1574 assert(pad != nullptr);
1575 if (pad->directMandatoryBases.empty()
1576 && data->currentName != "com.sun.star.uno.XInterface")
1578 OUString base(u".com.sun.star.uno.XInterface"_ustr);
1579 unoidl::detail::SourceProviderEntity const * p;
1580 if (findEntity(@4, yyscanner, data, true, &base, &p, nullptr, nullptr)
1581 == FOUND_ERROR)
1583 YYERROR;
1585 if (p == nullptr || !p->entity.is()
1586 || p->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
1588 error(
1589 @3, yyscanner,
1590 ("interface type " + data->currentName
1591 + " implicit direct base " + base
1592 + " does not resolve to an existing interface type"));
1593 YYERROR;
1595 if (!pad->addDirectBase(
1596 @3, yyscanner, data,
1597 unoidl::detail::SourceProviderInterfaceTypeEntityPad::DirectBase(
1598 base,
1599 static_cast<unoidl::InterfaceTypeEntity *>(
1600 p->entity.get()),
1601 std::vector<OUString>()),
1602 false))
1604 YYERROR;
1607 std::vector<unoidl::AnnotatedReference> mbases;
1608 for (auto & i: pad->directMandatoryBases) {
1609 mbases.emplace_back(i.name, std::move(i.annotations));
1611 std::vector<unoidl::AnnotatedReference> obases;
1612 for (auto & i: pad->directOptionalBases) {
1613 obases.emplace_back(i.name, std::move(i.annotations));
1615 ent->entity = new unoidl::InterfaceTypeEntity(
1616 pad->isPublished(), std::move(mbases), std::move(obases), std::move(pad->directAttributes),
1617 std::move(pad->directMethods), annotations($1));
1618 ent->pad.clear();
1619 clearCurrentState(data);
1623 interfaceMembers:
1624 interfaceMembers interfaceMember
1625 | /* empty */
1628 interfaceMember:
1629 interfaceBase
1630 | interfaceAttribute
1631 | interfaceMethod
1634 interfaceBase:
1635 deprecated_opt flagSection_opt TOK_INTERFACE name ';'
1637 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1638 OUString name(convertName($4));
1639 rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad> pad(
1640 getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
1641 data));
1642 if (pad->singleBase) {
1643 error(
1644 @3, yyscanner,
1645 u"single-inheritance interface cannot have additional bases"_ustr);
1646 YYERROR;
1648 if (($2 & ~unoidl::detail::FLAG_OPTIONAL) != 0) {
1649 error(
1650 @2, yyscanner,
1651 u"interface base can only be flagged as [optional]"_ustr);
1652 YYERROR;
1654 bool opt = ($2 & unoidl::detail::FLAG_OPTIONAL) != 0;
1655 OUString orgName(name);
1656 unoidl::detail::SourceProviderEntity const * p;
1657 bool typedefed = false;
1658 if (findEntity(@4, yyscanner, data, true, &name, &p, &typedefed, nullptr)
1659 == FOUND_ERROR)
1661 YYERROR;
1663 if (p == nullptr || !p->entity.is()
1664 || p->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
1666 error(
1667 @4, yyscanner,
1668 ("interface type " + data->currentName + " direct base " + name
1669 + " does not resolve to an existing interface type"));
1670 YYERROR;
1672 if (typedefed) {
1673 error(
1674 @4, yyscanner,
1675 ("interface type " + data->currentName + " direct base " + orgName
1676 + " is a typedef"));
1677 YYERROR;
1679 rtl::Reference<unoidl::InterfaceTypeEntity> ent(
1680 static_cast<unoidl::InterfaceTypeEntity *>(p->entity.get()));
1681 if (data->publishedContext && !ent->isPublished()) {
1682 error(
1683 @4, yyscanner,
1684 ("published interface type " + data->currentName + " direct base "
1685 + name + " is unpublished"));
1686 YYERROR;
1688 if (!pad->addDirectBase(
1689 @4, yyscanner, data,
1690 unoidl::detail::SourceProviderInterfaceTypeEntityPad::DirectBase(
1691 name, ent, annotations($1)),
1692 opt))
1694 YYERROR;
1699 interfaceAttribute:
1700 deprecated_opt flagSection type identifier
1702 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1703 unoidl::detail::SourceProviderType t(*$3);
1704 delete $3;
1705 OUString id(convertName($4));
1706 if (($2 & unoidl::detail::FLAG_ATTRIBUTE) == 0) {
1707 error(
1708 @2, yyscanner,
1709 u"interface attribute must be flagged as [attribute]"_ustr);
1710 YYERROR;
1712 if (($2
1713 & ~(unoidl::detail::FLAG_ATTRIBUTE | unoidl::detail::FLAG_BOUND
1714 | unoidl::detail::FLAG_READONLY))
1715 != 0)
1717 error(
1718 @2, yyscanner,
1719 (u"interface attribute can only be flagged as [attribute,"
1720 " bound, readonly]"_ustr));
1721 YYERROR;
1723 switch (t.type) {
1724 case unoidl::detail::SourceProviderType::TYPE_VOID:
1725 case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
1726 error(
1727 @3, yyscanner,
1728 ("illegal interface type " + data->currentName
1729 + " direct attribute " + id + " type"));
1730 YYERROR;
1731 break;
1732 default:
1733 break;
1735 rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad> pad(
1736 getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
1737 data));
1738 if (!pad->addDirectMember(@4, yyscanner, data, id)) {
1739 YYERROR;
1741 pad->directAttributes.emplace_back(
1742 id, t.getName(), ($2 & unoidl::detail::FLAG_BOUND) != 0,
1743 ($2 & unoidl::detail::FLAG_READONLY) != 0,
1744 std::vector<OUString>(), std::vector<OUString>(), annotations($1));
1746 attributeAccessDecls_opt ';'
1749 attributeAccessDecls_opt:
1750 '{' attributeAccessDecls '}'
1751 | /* empty */
1754 attributeAccessDecls:
1755 attributeAccessDecls attributeAccessDecl
1757 if (($1 & $2) != 0) {
1758 error(
1759 @2, yyscanner, u"duplicate get/set attribute access declaration"_ustr);
1760 YYERROR;
1762 $$ = unoidl::detail::SourceProviderAccessDecls($1 | $2);
1764 | /* empty */ { $$ = unoidl::detail::SourceProviderAccessDecls(0); }
1767 attributeAccessDecl:
1768 TOK_GET exceptionSpec ';'
1770 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1771 rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
1772 pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
1773 data));
1774 assert(!pad->directAttributes.empty());
1775 pad->directAttributes.back().getExceptions = *$2;
1776 delete $2;
1777 $$ = unoidl::detail::ACCESS_DECL_GET;
1779 | TOK_SET exceptionSpec ';'
1781 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1782 rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
1783 pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
1784 data));
1785 assert(!pad->directAttributes.empty());
1786 pad->directAttributes.back().setExceptions = *$2;
1787 delete $2;
1788 if (pad->directAttributes.back().readOnly) {
1789 error(
1790 @1, yyscanner,
1791 ("interface type " + data->currentName
1792 + " direct read-only attribute "
1793 + pad->directAttributes.back().name
1794 + " cannot have set access declaration"));
1795 YYERROR;
1797 $$ = unoidl::detail::ACCESS_DECL_SET;
1801 interfaceMethod:
1802 deprecated_opt type identifier
1804 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1805 unoidl::detail::SourceProviderType t(*$2);
1806 delete $2;
1807 OUString id(convertName($3));
1808 if (t.type == unoidl::detail::SourceProviderType::TYPE_EXCEPTION) {
1809 error(
1810 @3, yyscanner,
1811 ("illegal interface type " + data->currentName
1812 + " direct method " + id + " return type"));
1813 YYERROR;
1815 rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad> pad(
1816 getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
1817 data));
1818 if (!pad->addDirectMember(@3, yyscanner, data, id)) {
1819 YYERROR;
1821 pad->directMethods.emplace_back(
1822 id, t.getName(),
1823 std::vector<unoidl::InterfaceTypeEntity::Method::Parameter>(),
1824 std::vector<OUString>(), annotations($1));
1826 '(' methodParams_opt ')' exceptionSpec_opt ';'
1828 if ($8 != nullptr) {
1829 unoidl::detail::SourceProviderScannerData * data
1830 = yyget_extra(yyscanner);
1831 rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
1832 pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
1833 data));
1834 assert(!pad->directMethods.empty());
1835 pad->directMethods.back().exceptions = *$8;
1836 delete $8;
1841 methodParams_opt:
1842 methodParams
1843 | /* empty */
1846 methodParams:
1847 methodParams ',' methodParam
1848 | methodParam
1851 methodParam:
1852 '[' direction ']' type identifier
1854 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1855 unoidl::detail::SourceProviderType t(*$4);
1856 delete $4;
1857 OUString id(convertName($5));
1858 rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
1859 pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
1860 data));
1861 assert(!pad->directMethods.empty());
1862 switch (t.type) {
1863 case unoidl::detail::SourceProviderType::TYPE_VOID:
1864 case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
1865 error(
1866 @4, yyscanner,
1867 ("illegal interface type " + data->currentName
1868 + " direct method " + pad->directMethods.back().name
1869 + " parameter " + id + " type"));
1870 YYERROR;
1871 break;
1872 default:
1873 break;
1875 for (const auto & i: pad->directMethods.back().parameters) {
1876 if (id == i.name) {
1877 error(
1878 @5, yyscanner,
1879 ("interface type " + data->currentName + " direct method "
1880 + pad->directMethods.back().name + " parameter " + id
1881 + " has same identifier as another parameter"));
1882 YYERROR;
1885 pad->directMethods.back().parameters.emplace_back(id, t.getName(), $2);
1889 direction:
1890 TOK_IN { $$ = unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN; }
1891 | TOK_OUT
1892 { $$ = unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT; }
1893 | TOK_INOUT
1894 { $$ = unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT; }
1897 typedefDefn:
1898 deprecated_opt published_opt TOK_TYPEDEF type identifier ';'
1900 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1901 data->publishedContext = $2;
1902 unoidl::detail::SourceProviderType t(*$4);
1903 delete $4;
1904 OUString name(convertToFullName(data, $5));
1905 // There is no good reason to forbid typedefs to VOID, to instantiated
1906 // polymorphic struct types, and to exception types, but some old client
1907 // code of registry data expects this typedef restriction (like the
1908 // assert(false) default in handleTypedef in
1909 // codemaker/source/javamaker/javatype.cxx), so forbid them for now:
1910 switch (t.type) {
1911 case unoidl::detail::SourceProviderType::TYPE_VOID:
1912 case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
1913 case unoidl::detail::SourceProviderType::TYPE_INSTANTIATED_POLYMORPHIC_STRUCT:
1914 error(@4, yyscanner, u"bad typedef type"_ustr);
1915 YYERROR;
1916 break;
1917 case unoidl::detail::SourceProviderType::TYPE_ENUM:
1918 case unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT:
1919 case unoidl::detail::SourceProviderType::TYPE_INTERFACE:
1920 if ($2) {
1921 bool unpub = false;
1922 switch (t.entity->kind) {
1923 case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
1924 unpub = true;
1925 break;
1926 case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
1927 break;
1928 case unoidl::detail::SourceProviderEntity::KIND_MODULE:
1929 O3TL_UNREACHABLE;
1930 default:
1931 assert(t.entity->entity.is() || t.entity->pad.is());
1932 unpub
1933 = !(t.entity->entity.is()
1934 ? static_cast<unoidl::PublishableEntity *>(
1935 t.entity->entity.get())->isPublished()
1936 : t.entity->pad->isPublished());
1937 break;
1939 if (unpub) {
1940 error(
1941 @4, yyscanner,
1942 "published typedef " + name + " type is unpublished");
1943 YYERROR;
1946 break;
1947 case unoidl::detail::SourceProviderType::TYPE_PARAMETER:
1948 O3TL_UNREACHABLE;
1949 default:
1950 break;
1952 if (!data->entities.emplace(
1953 name,
1954 unoidl::detail::SourceProviderEntity(
1955 unoidl::detail::SourceProviderEntity::KIND_LOCAL,
1956 new unoidl::TypedefEntity(
1957 $2, t.getName(), annotations($1)))).
1958 second)
1960 error(@5, yyscanner, "multiple entities named " + name);
1961 YYERROR;
1963 clearCurrentState(data);
1967 constantGroupDefn:
1968 deprecated_opt published_opt TOK_CONSTANTS identifier
1970 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1971 data->publishedContext = $2;
1972 convertToCurrentName(data, $4);
1973 if (!data->entities.emplace(
1974 data->currentName,
1975 unoidl::detail::SourceProviderEntity(
1976 new unoidl::detail::SourceProviderConstantGroupEntityPad(
1977 $2))).
1978 second)
1980 error(@4, yyscanner, "multiple entities named " + data->currentName);
1981 YYERROR;
1984 '{' constants '}' ';'
1986 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
1987 unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
1988 unoidl::detail::SourceProviderConstantGroupEntityPad * pad =
1989 dynamic_cast<unoidl::detail::SourceProviderConstantGroupEntityPad *>(
1990 ent->pad.get());
1991 assert(pad != nullptr);
1992 ent->entity = new unoidl::ConstantGroupEntity(
1993 pad->isPublished(), std::move(pad->members), annotations($1));
1994 ent->pad.clear();
1995 clearCurrentState(data);
1999 constants:
2000 constants constant
2001 | /* empty */
2004 constant:
2005 deprecated_opt TOK_CONST type identifier '=' expr ';'
2007 OUString id(convertName($4));
2008 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2009 rtl::Reference<unoidl::detail::SourceProviderConstantGroupEntityPad> pad(
2010 getCurrentPad<unoidl::detail::SourceProviderConstantGroupEntityPad>(
2011 data));
2012 unoidl::detail::SourceProviderType t(*$3);
2013 delete $3;
2014 unoidl::ConstantValue v(false); // dummy value
2015 switch (t.type) {
2016 case unoidl::detail::SourceProviderType::TYPE_BOOLEAN:
2017 if ($6.type != unoidl::detail::SourceProviderExpr::TYPE_BOOL) {
2018 error(
2019 @6, yyscanner,
2020 ("bad value of boolean-typed constant " + data->currentName
2021 + "." + id));
2022 YYERROR;
2024 v = unoidl::ConstantValue($6.bval);
2025 break;
2026 case unoidl::detail::SourceProviderType::TYPE_BYTE:
2027 switch ($6.type) {
2028 case unoidl::detail::SourceProviderExpr::TYPE_INT:
2029 if ($6.ival < SAL_MIN_INT8 || $6.ival > SAL_MAX_INT8) {
2030 error(
2031 @6, yyscanner,
2032 ("out-of-range byte-typed constant " + data->currentName
2033 + "." + id + " value " + OUString::number($6.ival)));
2034 YYERROR;
2036 v = unoidl::ConstantValue(static_cast<sal_Int8>($6.ival));
2037 break;
2038 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2039 if ($6.uval > SAL_MAX_INT8) {
2040 error(
2041 @6, yyscanner,
2042 ("out-of-range byte-typed constant " + data->currentName
2043 + "." + id + " value " + OUString::number($6.uval)));
2044 YYERROR;
2046 v = unoidl::ConstantValue(static_cast<sal_Int8>($6.uval));
2047 break;
2048 default:
2049 error(
2050 @6, yyscanner,
2051 ("bad value of byte-typed constant " + data->currentName + "."
2052 + id));
2053 YYERROR;
2054 break;
2056 break;
2057 case unoidl::detail::SourceProviderType::TYPE_SHORT:
2058 switch ($6.type) {
2059 case unoidl::detail::SourceProviderExpr::TYPE_INT:
2060 if ($6.ival < SAL_MIN_INT16 || $6.ival > SAL_MAX_INT16) {
2061 error(
2062 @6, yyscanner,
2063 ("out-of-range short-typed constant " + data->currentName
2064 + "." + id + " value " + OUString::number($6.ival)));
2065 YYERROR;
2067 v = unoidl::ConstantValue(static_cast<sal_Int16>($6.ival));
2068 break;
2069 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2070 if ($6.uval > SAL_MAX_INT16) {
2071 error(
2072 @6, yyscanner,
2073 ("out-of-range short-typed constant " + data->currentName
2074 + "." + id + " value " + OUString::number($6.uval)));
2075 YYERROR;
2077 v = unoidl::ConstantValue(static_cast<sal_Int16>($6.uval));
2078 break;
2079 default:
2080 error(
2081 @6, yyscanner,
2082 ("bad value of short-typed constant " + data->currentName
2083 + "." + id));
2084 YYERROR;
2085 break;
2087 break;
2088 case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_SHORT:
2089 switch ($6.type) {
2090 case unoidl::detail::SourceProviderExpr::TYPE_INT:
2091 if ($6.ival < 0 || $6.ival > SAL_MAX_UINT16) {
2092 error(
2093 @6, yyscanner,
2094 ("out-of-range unsigned-short-typed constant "
2095 + data->currentName + "." + id + " value "
2096 + OUString::number($6.ival)));
2097 YYERROR;
2099 v = unoidl::ConstantValue(static_cast<sal_uInt16>($6.ival));
2100 break;
2101 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2102 if ($6.uval > SAL_MAX_UINT16) {
2103 error(
2104 @6, yyscanner,
2105 ("out-of-range unsigned-short-typed constant "
2106 + data->currentName + "." + id + " value "
2107 + OUString::number($6.uval)));
2108 YYERROR;
2110 v = unoidl::ConstantValue(static_cast<sal_uInt16>($6.uval));
2111 break;
2112 default:
2113 error(
2114 @6, yyscanner,
2115 ("bad value of unsigned-short-typed constant "
2116 + data->currentName + "." + id));
2117 YYERROR;
2118 break;
2120 break;
2121 case unoidl::detail::SourceProviderType::TYPE_LONG:
2122 switch ($6.type) {
2123 case unoidl::detail::SourceProviderExpr::TYPE_INT:
2124 if ($6.ival < SAL_MIN_INT32 || $6.ival > SAL_MAX_INT32) {
2125 error(
2126 @6, yyscanner,
2127 ("out-of-range long-typed constant " + data->currentName
2128 + "." + id + " value " + OUString::number($6.ival)));
2129 YYERROR;
2131 v = unoidl::ConstantValue(static_cast<sal_Int32>($6.ival));
2132 break;
2133 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2134 if ($6.uval > SAL_MAX_INT32) {
2135 error(
2136 @6, yyscanner,
2137 ("out-of-range long-typed constant " + data->currentName
2138 + "." + id + " value " + OUString::number($6.uval)));
2139 YYERROR;
2141 v = unoidl::ConstantValue(static_cast<sal_Int32>($6.uval));
2142 break;
2143 default:
2144 error(
2145 @6, yyscanner,
2146 ("bad value of long-typed constant " + data->currentName
2147 + "." + id));
2148 YYERROR;
2149 break;
2151 break;
2152 case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_LONG:
2153 switch ($6.type) {
2154 case unoidl::detail::SourceProviderExpr::TYPE_INT:
2155 if ($6.ival < 0 || $6.ival > SAL_MAX_UINT32) {
2156 error(
2157 @6, yyscanner,
2158 ("out-of-range unsigned-long-typed constant "
2159 + data->currentName + "." + id + " value "
2160 + OUString::number($6.ival)));
2161 YYERROR;
2163 v = unoidl::ConstantValue(static_cast<sal_uInt32>($6.ival));
2164 break;
2165 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2166 if ($6.uval > SAL_MAX_UINT32) {
2167 error(
2168 @6, yyscanner,
2169 ("out-of-range unsigned-long-typed constant "
2170 + data->currentName + "." + id + " value "
2171 + OUString::number($6.uval)));
2172 YYERROR;
2174 v = unoidl::ConstantValue(static_cast<sal_uInt32>($6.uval));
2175 break;
2176 default:
2177 error(
2178 @6, yyscanner,
2179 ("bad value of unsigned-long-typed constant "
2180 + data->currentName + "." + id));
2181 YYERROR;
2182 break;
2184 break;
2185 case unoidl::detail::SourceProviderType::TYPE_HYPER:
2186 switch ($6.type) {
2187 case unoidl::detail::SourceProviderExpr::TYPE_INT:
2188 v = unoidl::ConstantValue($6.ival);
2189 break;
2190 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2191 if ($6.uval > SAL_MAX_INT64) {
2192 error(
2193 @6, yyscanner,
2194 ("out-of-range hyper-typed constant " + data->currentName
2195 + "." + id + " value " + OUString::number($6.uval)));
2196 YYERROR;
2198 v = unoidl::ConstantValue(static_cast<sal_Int64>($6.uval));
2199 break;
2200 default:
2201 error(
2202 @6, yyscanner,
2203 ("bad value of hyper-typed constant " + data->currentName
2204 + "." + id));
2205 YYERROR;
2206 break;
2208 break;
2209 case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_HYPER:
2210 switch ($6.type) {
2211 case unoidl::detail::SourceProviderExpr::TYPE_INT:
2212 if ($6.ival < 0) {
2213 error(
2214 @6, yyscanner,
2215 ("out-of-range unsigned-hyper-typed constant "
2216 + data->currentName + "." + id + " value "
2217 + OUString::number($6.ival)));
2218 YYERROR;
2220 v = unoidl::ConstantValue(static_cast<sal_uInt64>($6.ival));
2221 break;
2222 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2223 v = unoidl::ConstantValue($6.uval);
2224 break;
2225 default:
2226 error(
2227 @6, yyscanner,
2228 ("bad value of unsigned-hyper-typed constant "
2229 + data->currentName + "." + id));
2230 YYERROR;
2231 break;
2233 break;
2234 case unoidl::detail::SourceProviderType::TYPE_FLOAT:
2235 switch ($6.type) {
2236 case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
2237 error(
2238 @6, yyscanner,
2239 ("bad boolean value of float-typed constant "
2240 + data->currentName + "." + id));
2241 YYERROR;
2242 break;
2243 case unoidl::detail::SourceProviderExpr::TYPE_INT:
2244 v = unoidl::ConstantValue(static_cast<float>($6.ival));
2245 break;
2246 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2247 v = unoidl::ConstantValue(static_cast<float>($6.uval));
2248 break;
2249 case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
2250 v = unoidl::ConstantValue(static_cast<float>($6.fval));
2251 break;
2253 break;
2254 case unoidl::detail::SourceProviderType::TYPE_DOUBLE:
2255 switch ($6.type) {
2256 case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
2257 error(
2258 @6, yyscanner,
2259 ("bad boolean value of double-typed constant "
2260 + data->currentName + "." + id));
2261 YYERROR;
2262 break;
2263 case unoidl::detail::SourceProviderExpr::TYPE_INT:
2264 v = unoidl::ConstantValue(static_cast<double>($6.ival));
2265 break;
2266 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
2267 v = unoidl::ConstantValue(static_cast<double>($6.uval));
2268 break;
2269 case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
2270 v = unoidl::ConstantValue($6.fval);
2271 break;
2273 break;
2274 default:
2275 error(
2276 @3, yyscanner,
2277 "bad type for constant " + data->currentName + "." + id);
2278 YYERROR;
2279 break;
2281 pad->members.emplace_back(id, v, annotations($1));
2285 singleInterfaceBasedServiceDefn:
2286 deprecated_opt published_opt TOK_SERVICE identifier singleInheritance
2288 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2289 data->publishedContext = $2;
2290 convertToCurrentName(data, $4);
2291 OUString base(convertName($5));
2292 unoidl::detail::SourceProviderEntity const * p;
2293 if (findEntity(@5, yyscanner, data, false, &base, &p, nullptr, nullptr)
2294 == FOUND_ERROR)
2296 YYERROR;
2298 bool ifcBase = false;
2299 bool pubBase = false;
2300 if (p != nullptr) {
2301 switch (p->kind) {
2302 case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
2303 ifcBase = true;
2304 pubBase = false;
2305 break;
2306 case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
2307 ifcBase = true;
2308 pubBase = true;
2309 break;
2310 default:
2311 if (p->entity.is()
2312 && (p->entity->getSort()
2313 == unoidl::Entity::SORT_INTERFACE_TYPE))
2315 ifcBase = true;
2316 pubBase = static_cast<unoidl::InterfaceTypeEntity *>(
2317 p->entity.get())->isPublished();
2319 break;
2322 if (!ifcBase) {
2323 error(
2324 @5, yyscanner,
2325 ("single-interface--based service " + data->currentName + " base "
2326 + base + " does not resolve to an interface type"));
2327 YYERROR;
2329 if ($2 && !pubBase) {
2330 error(
2331 @5, yyscanner,
2332 ("published single-interface--based service " + data->currentName
2333 + " base " + base + " is unpublished"));
2334 YYERROR;
2336 if (!data->entities.emplace(
2337 data->currentName,
2338 unoidl::detail::SourceProviderEntity(
2339 new unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad(
2340 $2, base))).
2341 second)
2343 error(@4, yyscanner, "multiple entities named " + data->currentName);
2344 YYERROR;
2347 ctors_opt ';'
2349 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2350 unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
2351 unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad * pad =
2352 dynamic_cast<unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad *>(
2353 ent->pad.get());
2354 assert(pad != nullptr);
2355 std::vector<unoidl::SingleInterfaceBasedServiceEntity::Constructor> ctors;
2356 if ($7) {
2357 for (const auto & i: pad->constructors) {
2358 std::vector<unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter> parms;
2359 for (auto & j: i.parameters) {
2360 parms.emplace_back(j.name, j.type.getName(), j.rest);
2362 ctors.push_back(
2363 unoidl::SingleInterfaceBasedServiceEntity::Constructor(
2364 i.name, std::move(parms), std::vector(i.exceptions), std::vector(i.annotations)));
2366 } else {
2367 assert(pad->constructors.empty());
2368 ctors.push_back(
2369 unoidl::SingleInterfaceBasedServiceEntity::Constructor());
2371 ent->entity = new unoidl::SingleInterfaceBasedServiceEntity(
2372 pad->isPublished(), pad->base, std::move(ctors), annotations($1));
2373 ent->pad.clear();
2374 clearCurrentState(data);
2378 ctors_opt:
2379 '{' ctors '}' { $$ = true; }
2380 | /* empty */ { $$ = false; }
2383 ctors:
2384 ctors ctor
2385 | /* empty */
2388 ctor:
2389 deprecated_opt identifier
2391 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2392 OUString id(convertName($2));
2393 rtl::Reference<unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad>
2394 pad(getCurrentPad<unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad>(
2395 data));
2396 for (const auto & i: pad->constructors) {
2397 if (id == i.name) {
2398 error(
2399 @2, yyscanner,
2400 ("single-interface--based service " + data->currentName
2401 + " constructor " + id
2402 + " has same identifier as another constructor"));
2403 YYERROR;
2406 pad->constructors.push_back(
2407 unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad::Constructor(
2408 id, annotations($1)));
2410 '(' ctorParams_opt ')' exceptionSpec_opt ';'
2412 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2413 rtl::Reference<unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad>
2414 pad(getCurrentPad<unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad>(
2415 data));
2416 assert(!pad->constructors.empty());
2417 if ($7 != nullptr) {
2418 pad->constructors.back().exceptions = *$7;
2419 delete $7;
2421 for (auto i(pad->constructors.begin()); i != pad->constructors.end() - 1;
2422 ++i)
2424 if (i->parameters.size()
2425 == pad->constructors.back().parameters.size())
2427 bool same = true;
2428 for (auto
2429 j(i->parameters.begin()),
2430 k(pad->constructors.back().parameters.begin());
2431 j != i->parameters.end(); ++j, ++k)
2433 if (!j->type.equals(k->type) || j->rest != k->rest) {
2434 same = false;
2435 break;
2438 if (same) {
2439 error(
2440 @2, yyscanner,
2441 ("single-interface--based service " + data->currentName
2442 + " constructor " + pad->constructors.back().name
2443 + " has similar parameter list to constructor "
2444 + i->name));
2445 YYERROR;
2452 ctorParams_opt:
2453 ctorParams
2454 | /* empty */
2457 ctorParams:
2458 ctorParams ',' ctorParam
2459 | ctorParam
2462 ctorParam:
2463 '[' direction ']' type ellipsis_opt identifier
2465 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2466 unoidl::detail::SourceProviderType t(*$4);
2467 delete $4;
2468 OUString id(convertName($6));
2469 rtl::Reference<unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad>
2470 pad(getCurrentPad<unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad>(
2471 data));
2472 assert(!pad->constructors.empty());
2473 if ($2 != unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN) {
2474 error(
2475 @4, yyscanner,
2476 ("single-interface--based service " + data->currentName
2477 + " constructor " + pad->constructors.back().name + " parameter "
2478 + id + " direction must be [in]"));
2479 YYERROR;
2481 switch (t.type) {
2482 case unoidl::detail::SourceProviderType::TYPE_VOID:
2483 case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
2484 error(
2485 @4, yyscanner,
2486 ("illegal single-interface--based service " + data->currentName
2487 + " constructor " + pad->constructors.back().name + " parameter "
2488 + id + " type"));
2489 YYERROR;
2490 break;
2491 default:
2492 break;
2494 if ($5) {
2495 if (t.type != unoidl::detail::SourceProviderType::TYPE_ANY) {
2496 error(
2497 @4, yyscanner,
2498 ("illegal single-interface--based service "
2499 + data->currentName + " constructor "
2500 + pad->constructors.back().name + " rest parameter " + id
2501 + " non-any type"));
2502 YYERROR;
2504 if (!pad->constructors.back().parameters.empty()) {
2505 error(
2506 @5, yyscanner,
2507 ("single-interface--based service " + data->currentName
2508 + " constructor " + pad->constructors.back().name
2509 + " rest parameter " + id + " must be first parameter"));
2510 YYERROR;
2512 } else if (!pad->constructors.back().parameters.empty()
2513 && pad->constructors.back().parameters.back().rest)
2515 error(
2516 @1, yyscanner,
2517 ("single-interface--based service " + data->currentName
2518 + " constructor " + pad->constructors.back().name
2519 + " rest parameter must be last parameter"));
2520 YYERROR;
2522 for (const auto & i: pad->constructors.back().parameters) {
2523 if (id == i.name) {
2524 error(
2525 @6, yyscanner,
2526 ("single-interface--based service " + data->currentName
2527 + " constructor " + pad->constructors.back().name
2528 + " parameter " + id
2529 + " has same identifier as another parameter"));
2530 YYERROR;
2533 pad->constructors.back().parameters.push_back(
2534 unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad::Constructor::Parameter(
2535 id, std::move(t), $5));
2539 ellipsis_opt:
2540 TOK_ELLIPSIS { $$ = true; }
2541 | /* empty */ { $$ = false; }
2543 accumulationBasedServiceDefn:
2544 deprecated_opt published_opt TOK_SERVICE identifier
2546 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2547 data->publishedContext = $2;
2548 convertToCurrentName(data, $4);
2549 if (!data->entities.emplace(
2550 data->currentName,
2551 unoidl::detail::SourceProviderEntity(
2552 new unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad(
2553 $2))).
2554 second)
2556 error(@4, yyscanner, "multiple entities named " + data->currentName);
2557 YYERROR;
2560 '{' serviceMembers '}' ';'
2562 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2563 unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
2564 unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad * pad =
2565 dynamic_cast<unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad *>(
2566 ent->pad.get());
2567 assert(pad != nullptr);
2568 ent->entity = new unoidl::AccumulationBasedServiceEntity(
2569 pad->isPublished(), std::move(pad->directMandatoryBaseServices),
2570 std::move(pad->directOptionalBaseServices), std::move(pad->directMandatoryBaseInterfaces),
2571 std::move(pad->directOptionalBaseInterfaces), std::move(pad->directProperties),
2572 annotations($1));
2573 ent->pad.clear();
2574 clearCurrentState(data);
2578 serviceMembers:
2579 serviceMembers serviceMember
2580 | /* empty */
2583 serviceMember:
2584 serviceBase
2585 | serviceInterfaceBase
2586 | serviceProperty
2589 serviceBase:
2590 deprecated_opt flagSection_opt TOK_SERVICE name ';'
2592 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2593 OUString name(convertName($4));
2594 rtl::Reference<unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad> pad(
2595 getCurrentPad<unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad>(
2596 data));
2597 if (($2 & ~unoidl::detail::FLAG_OPTIONAL) != 0) {
2598 error(
2599 @2, yyscanner,
2600 u"service base can only be flagged as [optional]"_ustr);
2601 YYERROR;
2603 bool opt = ($2 & unoidl::detail::FLAG_OPTIONAL) != 0;
2604 unoidl::detail::SourceProviderEntity const * p;
2605 if (findEntity(@4, yyscanner, data, false, &name, &p, nullptr, nullptr)
2606 == FOUND_ERROR)
2608 YYERROR;
2610 if (p == nullptr || !p->entity.is()
2611 || (p->entity->getSort()
2612 != unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE))
2614 error(
2615 @4, yyscanner,
2616 ("accumulation-based service " + data->currentName
2617 + " direct base service " + name
2618 + " does not resolve to an accumulation-based service"));
2619 YYERROR;
2621 if (data->publishedContext
2622 && !static_cast<unoidl::AccumulationBasedServiceEntity *>(
2623 p->entity.get())->isPublished())
2625 error(
2626 @4, yyscanner,
2627 ("published accumulation-based service " + data->currentName
2628 + " direct base service " + name + " is unpublished"));
2629 YYERROR;
2631 std::vector<unoidl::AnnotatedReference> & v(
2633 ? pad->directOptionalBaseServices : pad->directMandatoryBaseServices);
2634 for (const auto & i: v) {
2635 if (name == i.name) {
2636 error(
2637 @4, yyscanner,
2638 ("accumulation-based service " + data->currentName
2639 + " duplicate direct base service " + name));
2640 YYERROR;
2643 v.emplace_back(name, annotations($1));
2647 serviceInterfaceBase:
2648 deprecated_opt flagSection_opt TOK_INTERFACE name ';'
2650 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2651 OUString name(convertName($4));
2652 rtl::Reference<unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad> pad(
2653 getCurrentPad<unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad>(
2654 data));
2655 if (($2 & ~unoidl::detail::FLAG_OPTIONAL) != 0) {
2656 error(
2657 @2, yyscanner,
2658 u"interface base can only be flagged as [optional]"_ustr);
2659 YYERROR;
2661 bool opt = ($2 & unoidl::detail::FLAG_OPTIONAL) != 0;
2662 unoidl::detail::SourceProviderEntity const * p;
2663 if (findEntity(@4, yyscanner, data, false, &name, &p, nullptr, nullptr)
2664 == FOUND_ERROR)
2666 YYERROR;
2668 bool ifcBase = false;
2669 bool pubBase = false;
2670 if (p != nullptr) {
2671 switch (p->kind) {
2672 case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
2673 ifcBase = true;
2674 pubBase = false;
2675 break;
2676 case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
2677 ifcBase = true;
2678 pubBase = true;
2679 break;
2680 default:
2681 if (p->entity.is()
2682 && (p->entity->getSort()
2683 == unoidl::Entity::SORT_INTERFACE_TYPE))
2685 ifcBase = true;
2686 pubBase = static_cast<unoidl::InterfaceTypeEntity *>(
2687 p->entity.get())->isPublished();
2689 break;
2692 if (!ifcBase) {
2693 error(
2694 @4, yyscanner,
2695 ("accumulation-based service " + data->currentName
2696 + " direct base interface " + name
2697 + " does not resolve to an interface type"));
2698 YYERROR;
2700 if (data->publishedContext && !opt && !pubBase) {
2701 error(
2702 @4, yyscanner,
2703 ("published accumulation-based service " + data->currentName
2704 + " direct base interface " + name + " is unpublished"));
2705 YYERROR;
2707 std::vector<unoidl::AnnotatedReference> & v(
2709 ? pad->directOptionalBaseInterfaces
2710 : pad->directMandatoryBaseInterfaces);
2711 for (const auto & i: v) {
2712 if (name == i.name) {
2713 error(
2714 @4, yyscanner,
2715 ("accumulation-based service " + data->currentName
2716 + " duplicate direct base interface " + name));
2717 YYERROR;
2720 v.emplace_back(name, annotations($1));
2724 serviceProperty:
2725 deprecated_opt flagSection type identifier ';'
2727 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2728 unoidl::detail::SourceProviderType t(*$3);
2729 delete $3;
2730 OUString id(convertName($4));
2731 if (($2 & unoidl::detail::FLAG_PROPERTY) == 0) {
2732 error(
2733 @2, yyscanner,
2734 (u"accumulation-based service property must be flagged as"
2735 " [property]"_ustr));
2736 YYERROR;
2738 if (($2
2739 & ~(unoidl::detail::FLAG_BOUND | unoidl::detail::FLAG_CONSTRAINED
2740 | unoidl::detail::FLAG_MAYBEAMBIGUOUS
2741 | unoidl::detail::FLAG_MAYBEDEFAULT
2742 | unoidl::detail::FLAG_MAYBEVOID | unoidl::detail::FLAG_OPTIONAL
2743 | unoidl::detail::FLAG_PROPERTY | unoidl::detail::FLAG_READONLY
2744 | unoidl::detail::FLAG_REMOVABLE
2745 | unoidl::detail::FLAG_TRANSIENT))
2746 != 0)
2748 error(
2749 @2, yyscanner,
2750 (u"accumulation-based service property can only be flagged as"
2751 " [property, bound, constrained, maybeambiguous, maybedefault,"
2752 " maybevoid, optional, readonly, removable, transient]"_ustr));
2753 YYERROR;
2755 int att = 0;
2756 if (($2 & unoidl::detail::FLAG_BOUND) != 0) {
2757 att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_BOUND;
2759 if (($2 & unoidl::detail::FLAG_CONSTRAINED) != 0) {
2760 att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_CONSTRAINED;
2762 if (($2 & unoidl::detail::FLAG_MAYBEAMBIGUOUS) != 0) {
2763 att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_MAYBE_AMBIGUOUS;
2765 if (($2 & unoidl::detail::FLAG_MAYBEDEFAULT) != 0) {
2766 att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_MAYBE_DEFAULT;
2768 if (($2 & unoidl::detail::FLAG_MAYBEVOID) != 0) {
2769 att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_MAYBE_VOID;
2771 if (($2 & unoidl::detail::FLAG_OPTIONAL) != 0) {
2772 att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_OPTIONAL;
2774 if (($2 & unoidl::detail::FLAG_READONLY) != 0) {
2775 att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_READ_ONLY;
2777 if (($2 & unoidl::detail::FLAG_REMOVABLE) != 0) {
2778 att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_REMOVABLE;
2780 if (($2 & unoidl::detail::FLAG_TRANSIENT) != 0) {
2781 att |= unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_TRANSIENT;
2783 switch (t.type) {
2784 case unoidl::detail::SourceProviderType::TYPE_VOID:
2785 case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
2786 error(
2787 @3, yyscanner,
2788 ("illegal accumulation-based service " + data->currentName
2789 + " direct property " + id + " type"));
2790 YYERROR;
2791 break;
2792 default:
2793 break;
2795 rtl::Reference<unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad>
2796 pad(getCurrentPad<unoidl::detail::SourceProviderAccumulationBasedServiceEntityPad>(
2797 data));
2798 for (const auto & i: pad->directProperties) {
2799 if (id == i.name) {
2800 error(
2801 @4, yyscanner,
2802 ("accumulation-based service " + data->currentName
2803 + " duplicate direct property " + id));
2804 YYERROR;
2807 pad->directProperties.emplace_back(
2808 id, t.getName(),
2809 unoidl::AccumulationBasedServiceEntity::Property::Attributes(att),
2810 annotations($1));
2814 interfaceBasedSingletonDefn:
2815 deprecated_opt published_opt TOK_SINGLETON identifier singleInheritance ';'
2817 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2818 data->publishedContext = $2;
2819 OUString name(convertToFullName(data, $4));
2820 OUString base(convertName($5));
2821 unoidl::detail::SourceProviderEntity const * p;
2822 if (findEntity(@5, yyscanner, data, false, &base, &p, nullptr, nullptr)
2823 == FOUND_ERROR)
2825 YYERROR;
2827 bool ifcBase = false;
2828 bool pubBase = false;
2829 if (p != nullptr) {
2830 switch (p->kind) {
2831 case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
2832 ifcBase = true;
2833 pubBase = false;
2834 break;
2835 case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
2836 ifcBase = true;
2837 pubBase = true;
2838 break;
2839 default:
2840 if (p->entity.is()
2841 && (p->entity->getSort()
2842 == unoidl::Entity::SORT_INTERFACE_TYPE))
2844 ifcBase = true;
2845 pubBase = static_cast<unoidl::InterfaceTypeEntity *>(
2846 p->entity.get())->isPublished();
2848 break;
2851 if (!ifcBase) {
2852 error(
2853 @5, yyscanner,
2854 ("interface-based singleton " + name + " base " + base
2855 + " does not resolve to an interface type"));
2856 YYERROR;
2858 if ($2 && !pubBase) {
2859 error(
2860 @5, yyscanner,
2861 ("published interface-based singleton " + name + " base " + base
2862 + " is unpublished"));
2863 YYERROR;
2865 if (!data->entities.emplace(
2866 name,
2867 unoidl::detail::SourceProviderEntity(
2868 unoidl::detail::SourceProviderEntity::KIND_LOCAL,
2869 new unoidl::InterfaceBasedSingletonEntity(
2870 $2, base, annotations($1)))).
2871 second)
2873 error(@4, yyscanner, "multiple entities named " + name);
2874 YYERROR;
2876 clearCurrentState(data);
2880 serviceBasedSingletonDefn:
2881 deprecated_opt published_opt TOK_SINGLETON identifier '{' TOK_SERVICE name ';'
2882 '}' ';'
2884 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2885 data->publishedContext = $2;
2886 OUString name(convertToFullName(data, $4));
2887 OUString base(convertName($7));
2888 unoidl::detail::SourceProviderEntity const * p;
2889 if (findEntity(@7, yyscanner, data, false, &base, &p, nullptr, nullptr)
2890 == FOUND_ERROR)
2892 YYERROR;
2894 if (p == nullptr
2895 || !p->entity.is()
2896 || (p->entity->getSort()
2897 != unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE))
2899 error(
2900 @7, yyscanner,
2901 ("service-based singleton " + name + " base " + base
2902 + " does not resolve to an accumulation-based service"));
2903 YYERROR;
2905 if ($2
2906 && !static_cast<unoidl::AccumulationBasedServiceEntity *>(
2907 p->entity.get())->isPublished())
2909 error(
2910 @7, yyscanner,
2911 ("published service-based singleton " + name + " base " + base
2912 + " is unpublished"));
2913 YYERROR;
2915 if (!data->entities.emplace(
2916 name,
2917 unoidl::detail::SourceProviderEntity(
2918 unoidl::detail::SourceProviderEntity::KIND_LOCAL,
2919 new unoidl::ServiceBasedSingletonEntity(
2920 $2, base, annotations($1)))).
2921 second)
2923 error(@4, yyscanner, "multiple entities named " + name);
2924 YYERROR;
2926 clearCurrentState(data);
2930 singleInheritance_opt:
2931 singleInheritance
2932 | /* empty */ { $$ = nullptr; }
2935 singleInheritance: ':' name { $$ = $2; }
2938 exceptionSpec_opt:
2939 exceptionSpec
2940 | /* empty */ { $$ = nullptr; }
2943 exceptionSpec: TOK_RAISES '(' exceptions ')' { $$ = $3; }
2946 exceptions:
2947 exceptions ',' name
2949 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2950 OUString name(convertName($3));
2951 unoidl::detail::SourceProviderEntity const * p;
2952 if (findEntity(@3, yyscanner, data, false, &name, &p, nullptr, nullptr)
2953 == FOUND_ERROR)
2955 delete $1; /* see commented-out %destructor above */
2956 YYERROR;
2958 if (p == nullptr
2959 || !p->entity.is()
2960 || (p->entity->getSort() != unoidl::Entity::SORT_EXCEPTION_TYPE))
2962 delete $1; /* see commented-out %destructor above */
2963 error(
2964 @3, yyscanner,
2965 ("exception " + name + " does not resolve to an exception type"));
2966 YYERROR;
2968 if (data->publishedContext
2969 && !(static_cast<unoidl::ExceptionTypeEntity *>(p->entity.get())
2970 ->isPublished()))
2972 delete $1; /* see commented-out %destructor above */
2973 error(
2974 @3, yyscanner,
2975 ("unpublished exception " + name + " used in published context"));
2976 YYERROR;
2978 if (std::find($1->begin(), $1->end(), name) != $1->end()) {
2979 delete $1; /* see commented-out %destructor above */
2980 error(
2981 @3, yyscanner, ("exception " + name + " listed more than once"));
2982 YYERROR;
2984 $1->push_back(name);
2985 $$ = $1;
2987 | name
2989 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
2990 OUString name(convertName($1));
2991 unoidl::detail::SourceProviderEntity const * p;
2992 if (findEntity(@1, yyscanner, data, false, &name, &p, nullptr, nullptr)
2993 == FOUND_ERROR)
2995 YYERROR;
2997 if (p == nullptr
2998 || !p->entity.is()
2999 || (p->entity->getSort() != unoidl::Entity::SORT_EXCEPTION_TYPE))
3001 error(
3002 @1, yyscanner,
3003 ("exception " + name + " does not resolve to an exception type"));
3004 YYERROR;
3006 if (data->publishedContext
3007 && !(static_cast<unoidl::ExceptionTypeEntity *>(p->entity.get())
3008 ->isPublished()))
3010 error(
3011 @1, yyscanner,
3012 ("unpublished exception " + name + " used in published context"));
3013 YYERROR;
3015 $$ = new std::vector<OUString>; $$->push_back(name);
3019 interfaceDecl:
3020 deprecated_opt/*ignored*/ published_opt TOK_INTERFACE identifier ';'
3022 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
3023 data->publishedContext = $2;
3024 OUString name(convertToFullName(data, $4));
3025 std::pair<std::map<OUString, unoidl::detail::SourceProviderEntity>::iterator, bool> p(
3026 data->entities.emplace(
3027 name,
3028 unoidl::detail::SourceProviderEntity(
3030 ? unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL
3031 : unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL)));
3032 if (!p.second) {
3033 switch (p.first->second.kind) {
3034 case unoidl::detail::SourceProviderEntity::KIND_INTERFACE_DECL:
3035 if ($2) {
3036 p.first->second.kind
3037 = unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL;
3039 break;
3040 case unoidl::detail::SourceProviderEntity::KIND_PUBLISHED_INTERFACE_DECL:
3041 break;
3042 default:
3043 assert(p.first->second.entity.is());
3044 if (p.first->second.entity->getSort()
3045 != unoidl::Entity::SORT_INTERFACE_TYPE)
3047 error(
3048 @4, yyscanner,
3049 "multiple entities named " + data->currentName);
3050 YYERROR;
3052 if ($2
3053 && !static_cast<unoidl::InterfaceTypeEntity *>(
3054 p.first->second.entity.get())->isPublished())
3056 error(
3057 @4, yyscanner,
3058 ("published interface type declaration "
3059 + data->currentName + " has been defined unpublished"));
3060 YYERROR;
3064 clearCurrentState(data);
3068 published_opt:
3069 TOK_PUBLISHED { $$ = true; }
3070 | /* empty */ { $$ = false; }
3073 flagSection_opt:
3074 flagSection
3075 | /* empty */ { $$ = unoidl::detail::SourceProviderFlags(0); }
3078 flagSection: '[' flags ']' { $$ = $2; }
3081 flags:
3082 flags ',' flag
3084 if (($1 & $3) != 0) {
3085 error(@3, yyscanner, "duplicate flag " + flagName($3));
3086 YYERROR;
3088 $$ = unoidl::detail::SourceProviderFlags($1 | $3);
3090 | flag
3093 flag:
3094 TOK_ATTRIBUTE { $$ = unoidl::detail::FLAG_ATTRIBUTE; }
3095 | TOK_BOUND { $$ = unoidl::detail::FLAG_BOUND; }
3096 | TOK_CONSTRAINED { $$ = unoidl::detail::FLAG_CONSTRAINED; }
3097 | TOK_MAYBEAMBIGUOUS { $$ = unoidl::detail::FLAG_MAYBEAMBIGUOUS; }
3098 | TOK_MAYBEDEFAULT { $$ = unoidl::detail::FLAG_MAYBEDEFAULT; }
3099 | TOK_MAYBEVOID { $$ = unoidl::detail::FLAG_MAYBEVOID; }
3100 | TOK_OPTIONAL { $$ = unoidl::detail::FLAG_OPTIONAL; }
3101 | TOK_PROPERTY { $$ = unoidl::detail::FLAG_PROPERTY; }
3102 | TOK_READONLY { $$ = unoidl::detail::FLAG_READONLY; }
3103 | TOK_REMOVABLE { $$ = unoidl::detail::FLAG_REMOVABLE; }
3104 | TOK_TRANSIENT { $$ = unoidl::detail::FLAG_TRANSIENT; }
3107 expr: orExpr
3110 orExpr:
3111 orExpr '|' xorExpr
3113 if (!coerce(@1, yyscanner, &$1, &$3)) {
3114 YYERROR;
3116 switch ($1.type) {
3117 case unoidl::detail::SourceProviderExpr::TYPE_INT:
3118 $$ = unoidl::detail::SourceProviderExpr::Int($1.ival | $3.ival);
3119 break;
3120 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3121 $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval | $3.uval);
3122 break;
3123 default:
3124 error(@1, yyscanner, u"arguments of non-integer type to \"|\""_ustr);
3125 YYERROR;
3126 break;
3129 | xorExpr
3132 xorExpr:
3133 xorExpr '^' andExpr
3135 if (!coerce(@1, yyscanner, &$1, &$3)) {
3136 YYERROR;
3138 switch ($1.type) {
3139 case unoidl::detail::SourceProviderExpr::TYPE_INT:
3140 $$ = unoidl::detail::SourceProviderExpr::Int($1.ival ^ $3.ival);
3141 break;
3142 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3143 $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval ^ $3.uval);
3144 break;
3145 default:
3146 error(@1, yyscanner, u"arguments of non-integer type to \"^\""_ustr);
3147 YYERROR;
3148 break;
3151 | andExpr
3154 andExpr:
3155 andExpr '&' shiftExpr
3157 if (!coerce(@1, yyscanner, &$1, &$3)) {
3158 YYERROR;
3160 switch ($1.type) {
3161 case unoidl::detail::SourceProviderExpr::TYPE_INT:
3162 $$ = unoidl::detail::SourceProviderExpr::Int($1.ival & $3.ival);
3163 break;
3164 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3165 $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval & $3.uval);
3166 break;
3167 default:
3168 error(@1, yyscanner, u"arguments of non-integer type to \"&\""_ustr);
3169 YYERROR;
3170 break;
3173 | shiftExpr
3176 shiftExpr:
3177 shiftExpr TOK_LEFTSHIFT addExpr
3179 int n;
3180 switch ($3.type) {
3181 case unoidl::detail::SourceProviderExpr::TYPE_INT:
3182 if ($3.ival < 0 || $3.ival > 63) {
3183 error(
3184 @3, yyscanner,
3185 ("out-of-range shift argument " + OUString::number($3.ival)
3186 + " to \"<<\" "));
3187 YYERROR;
3189 n = static_cast<int>($3.ival);
3190 break;
3191 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3192 if ($3.uval > 63) {
3193 error(
3194 @3, yyscanner,
3195 ("out-of-range shift argument " + OUString::number($3.uval)
3196 + " to \"<<\" "));
3197 YYERROR;
3199 n = static_cast<int>($3.uval);
3200 break;
3201 default:
3202 error(@3, yyscanner, u"right argument of non-integer type to \"<<\""_ustr);
3203 YYERROR;
3205 switch ($1.type) {
3206 case unoidl::detail::SourceProviderExpr::TYPE_INT:
3207 if ($1.ival < 0) {
3208 error(
3209 @1, yyscanner,
3210 ("cannot left-shift negative argument "
3211 + OUString::number($1.ival)));
3212 YYERROR;
3214 $$ = unoidl::detail::SourceProviderExpr::Int($1.ival << n);
3215 break;
3216 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3217 $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval << n);
3218 break;
3219 default:
3220 error(@1, yyscanner, u"left argument of non-integer type to \"<<\""_ustr);
3221 YYERROR;
3222 break;
3225 | shiftExpr TOK_RIGHTSHIFT addExpr
3227 int n;
3228 switch ($3.type) {
3229 case unoidl::detail::SourceProviderExpr::TYPE_INT:
3230 if ($3.ival < 0 || $3.ival > 63) {
3231 error(
3232 @3, yyscanner,
3233 ("out-of-range shift argument " + OUString::number($3.ival)
3234 + " to \">>\" "));
3235 YYERROR;
3237 n = static_cast<int>($3.ival);
3238 break;
3239 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3240 if ($3.uval > 63) {
3241 error(
3242 @3, yyscanner,
3243 ("out-of-range shift argument " + OUString::number($3.uval)
3244 + " to \">>\" "));
3245 YYERROR;
3247 n = static_cast<int>($3.uval);
3248 break;
3249 default:
3250 error(@3, yyscanner, u"right argument of non-integer type to \">>\""_ustr);
3251 YYERROR;
3252 break;
3254 switch ($1.type) {
3255 case unoidl::detail::SourceProviderExpr::TYPE_INT:
3256 $$ = unoidl::detail::SourceProviderExpr::Int($1.ival >> n);
3257 break;
3258 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3259 $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval >> n);
3260 break;
3261 default:
3262 error(@1, yyscanner, u"left argument of non-integer type to \">>\""_ustr);
3263 YYERROR;
3264 break;
3267 | addExpr
3270 addExpr:
3271 addExpr '+' multExpr
3273 if (!coerce(@1, yyscanner, &$1, &$3)) {
3274 YYERROR;
3276 switch ($1.type) {
3277 case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
3278 error(@1, yyscanner, u"arguments of boolean type to binary \"+\""_ustr);
3279 YYERROR;
3280 break;
3281 case unoidl::detail::SourceProviderExpr::TYPE_INT:
3282 $$ = unoidl::detail::SourceProviderExpr::Int($1.ival + $3.ival); //TODO: overflow
3283 break;
3284 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3285 $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval + $3.uval); //TODO: overflow
3286 break;
3287 case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
3288 $$ = unoidl::detail::SourceProviderExpr::Float($1.fval + $3.fval);
3289 break;
3292 | addExpr '-' multExpr
3294 if (!coerce(@1, yyscanner, &$1, &$3)) {
3295 YYERROR;
3297 switch ($1.type) {
3298 case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
3299 error(@1, yyscanner, u"arguments of boolean type to binary \"-\""_ustr);
3300 YYERROR;
3301 break;
3302 case unoidl::detail::SourceProviderExpr::TYPE_INT:
3303 $$ = unoidl::detail::SourceProviderExpr::Int($1.ival - $3.ival); //TODO: overflow
3304 break;
3305 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3306 $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval - $3.uval); //TODO: overflow
3307 break;
3308 case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
3309 $$ = unoidl::detail::SourceProviderExpr::Float($1.fval - $3.fval);
3310 break;
3313 | multExpr
3316 multExpr:
3317 multExpr '*' unaryExpr
3319 if (!coerce(@1, yyscanner, &$1, &$3)) {
3320 YYERROR;
3322 switch ($1.type) {
3323 case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
3324 error(@1, yyscanner, u"arguments of boolean type to \"*\""_ustr);
3325 YYERROR;
3326 break;
3327 case unoidl::detail::SourceProviderExpr::TYPE_INT:
3328 $$ = unoidl::detail::SourceProviderExpr::Int($1.ival * $3.ival); //TODO: overflow
3329 break;
3330 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3331 $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval * $3.uval); //TODO: overflow
3332 break;
3333 case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
3334 $$ = unoidl::detail::SourceProviderExpr::Float($1.fval * $3.fval);
3335 break;
3338 | multExpr '/' unaryExpr
3340 if (!coerce(@1, yyscanner, &$1, &$3)) {
3341 YYERROR;
3343 switch ($1.type) {
3344 case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
3345 error(@1, yyscanner, u"arguments of boolean type to \"/\""_ustr);
3346 YYERROR;
3347 break;
3348 case unoidl::detail::SourceProviderExpr::TYPE_INT:
3349 if ($3.ival == 0) {
3350 error(@3, yyscanner, u"cannot divide by zero"_ustr);
3351 YYERROR;
3353 $$ = unoidl::detail::SourceProviderExpr::Int($1.ival / $3.ival);
3354 break;
3355 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3356 if ($3.uval == 0) {
3357 error(@3, yyscanner, u"cannot divide by zero"_ustr);
3358 YYERROR;
3360 $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval / $3.uval);
3361 break;
3362 case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
3363 if ($3.fval == 0) {
3364 error(@3, yyscanner, u"cannot divide by zero"_ustr);
3365 YYERROR;
3367 $$ = unoidl::detail::SourceProviderExpr::Float($1.fval - $3.fval);
3368 break;
3371 | multExpr '%' unaryExpr
3373 if (!coerce(@1, yyscanner, &$1, &$3)) {
3374 YYERROR;
3376 switch ($1.type) {
3377 case unoidl::detail::SourceProviderExpr::TYPE_INT:
3378 if ($3.ival == 0) {
3379 error(@3, yyscanner, u"cannot divide by zero"_ustr);
3380 YYERROR;
3382 $$ = unoidl::detail::SourceProviderExpr::Int($1.ival % $3.ival);
3383 break;
3384 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3385 if ($3.uval == 0) {
3386 error(@3, yyscanner, u"cannot divide by zero"_ustr);
3387 YYERROR;
3389 $$ = unoidl::detail::SourceProviderExpr::Uint($1.uval % $3.uval);
3390 break;
3391 default:
3392 error(@1, yyscanner, u"arguments of non-integer type to \"%\""_ustr);
3393 YYERROR;
3394 break;
3397 | unaryExpr
3400 unaryExpr:
3401 '+' primaryExpr
3403 if ($2.type == unoidl::detail::SourceProviderExpr::TYPE_BOOL) {
3404 error(@2, yyscanner, u"argument of boolean type to unary \"+\""_ustr);
3405 YYERROR;
3407 $$ = $2;
3409 | '-' primaryExpr
3411 switch ($2.type) {
3412 case unoidl::detail::SourceProviderExpr::TYPE_BOOL:
3413 error(@2, yyscanner, u"argument of boolean type to unary \"-\""_ustr);
3414 YYERROR;
3415 break;
3416 case unoidl::detail::SourceProviderExpr::TYPE_INT:
3417 if ($2.ival == SAL_MIN_INT64) {
3418 error(@2, yyscanner, u"cannot negate -2^63"_ustr);
3419 YYERROR;
3421 $$ = unoidl::detail::SourceProviderExpr::Int(-$2.ival);
3422 break;
3423 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3424 if ($2.uval == SAL_CONST_UINT64(0x8000000000000000)) {
3425 $$ = unoidl::detail::SourceProviderExpr::Int(SAL_MIN_INT64);
3426 } else {
3427 if ($2.uval > SAL_MAX_INT64) {
3428 error(
3429 @2, yyscanner,
3430 ("cannot negate out-of-range value "
3431 + OUString::number($2.uval)));
3432 YYERROR;
3434 $$ = unoidl::detail::SourceProviderExpr::Int(
3435 -static_cast<sal_Int64>($2.uval));
3437 break;
3438 case unoidl::detail::SourceProviderExpr::TYPE_FLOAT:
3439 $$ = unoidl::detail::SourceProviderExpr::Float(-$2.fval);
3440 break;
3443 | '~' primaryExpr
3445 switch ($2.type) {
3446 case unoidl::detail::SourceProviderExpr::TYPE_INT:
3447 $$ = unoidl::detail::SourceProviderExpr::Int(~$2.ival);
3448 break;
3449 case unoidl::detail::SourceProviderExpr::TYPE_UINT:
3450 $$ = unoidl::detail::SourceProviderExpr::Uint(~$2.uval);
3451 break;
3452 default:
3453 error(@2, yyscanner, u"argument of non-integer type to \"~\""_ustr);
3454 YYERROR;
3455 break;
3458 | primaryExpr
3461 primaryExpr:
3462 '(' expr ')' { $$ = $2; }
3463 | TOK_FALSE { $$ = unoidl::detail::SourceProviderExpr::Bool(false); }
3464 | TOK_TRUE { $$ = unoidl::detail::SourceProviderExpr::Bool(true); }
3465 | TOK_INTEGER { $$ = unoidl::detail::SourceProviderExpr::Uint($1); }
3466 | TOK_FLOATING { $$ = unoidl::detail::SourceProviderExpr::Float($1); }
3467 | name
3469 OUString name(convertName($1));
3470 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
3471 unoidl::ConstantValue v(false); // dummy value
3472 bool found = false;
3473 bool unpub = false;
3474 sal_Int32 i = name.lastIndexOf('.');
3475 if (i == -1) {
3476 rtl::Reference<unoidl::detail::SourceProviderEntityPad> pad(
3477 getCurrentEntity(data)->pad);
3478 unoidl::detail::SourceProviderEnumTypeEntityPad * p1 = dynamic_cast<
3479 unoidl::detail::SourceProviderEnumTypeEntityPad *>(pad.get());
3480 if (p1 != nullptr) {
3481 for (const auto & j: p1->members) {
3482 if (j.name == name) {
3483 v = unoidl::ConstantValue(j.value);
3484 found = true;
3485 break;
3488 } else {
3489 unoidl::detail::SourceProviderConstantGroupEntityPad * p2
3490 = dynamic_cast<
3491 unoidl::detail::SourceProviderConstantGroupEntityPad *>(
3492 pad.get());
3493 if (p2 != nullptr) {
3494 for (const auto & j: p2->members) {
3495 if (j.name == name) {
3496 v = j.value;
3497 found = true;
3498 break;
3503 } else {
3504 OUString scope(name.copy(0, i));
3505 unoidl::detail::SourceProviderEntity const * ent;
3506 if (findEntity(
3507 @1, yyscanner, data, false, &scope, &ent, nullptr, nullptr)
3508 == FOUND_ERROR)
3510 YYERROR;
3512 if (ent != nullptr) {
3513 std::u16string_view id(name.subView(i + 1));
3514 // No need to check for enum members here, as they cannot be
3515 // referenced in expressions by qualified name (TODO: is that true?):
3516 if (ent->entity.is()) {
3517 if (ent->entity->getSort()
3518 == unoidl::Entity::SORT_CONSTANT_GROUP)
3520 std::vector<unoidl::ConstantGroupEntity::Member> const &
3521 mems(
3522 static_cast<unoidl::ConstantGroupEntity *>(
3523 ent->entity.get())->
3524 getMembers());
3525 for (auto & j: mems) {
3526 if (j.name == id) {
3527 v = j.value;
3528 found = true;
3529 unpub
3530 = !static_cast<unoidl::ConstantGroupEntity *>(
3531 ent->entity.get())->isPublished();
3532 break;
3536 } else if (ent->pad.is()) {
3537 unoidl::detail::SourceProviderConstantGroupEntityPad * pad
3538 = dynamic_cast<
3539 unoidl::detail::SourceProviderConstantGroupEntityPad *>(
3540 ent->pad.get());
3541 if (pad != nullptr) {
3542 for (const auto & j: pad->members) {
3543 if (j.name == id) {
3544 v = j.value;
3545 found = true;
3546 unpub = !ent->pad->isPublished();
3547 break;
3554 if (!found) {
3555 error(
3556 @1, yyscanner,
3557 (name
3558 + (" does not resolve to neither a constant nor an unqualified"
3559 " enum member")));
3560 YYERROR;
3562 if (data->publishedContext && unpub) {
3563 error(
3564 @1, yyscanner,
3565 "unpublished value " + name + " used in published context");
3566 YYERROR;
3568 switch (v.type) {
3569 case unoidl::ConstantValue::TYPE_BOOLEAN:
3570 $$ = unoidl::detail::SourceProviderExpr::Bool(v.booleanValue);
3571 break;
3572 case unoidl::ConstantValue::TYPE_BYTE:
3573 $$ = unoidl::detail::SourceProviderExpr::Int(v.byteValue);
3574 break;
3575 case unoidl::ConstantValue::TYPE_SHORT:
3576 $$ = unoidl::detail::SourceProviderExpr::Int(v.shortValue);
3577 break;
3578 case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
3579 $$ = unoidl::detail::SourceProviderExpr::Uint(v.unsignedShortValue);
3580 break;
3581 case unoidl::ConstantValue::TYPE_LONG:
3582 $$ = unoidl::detail::SourceProviderExpr::Int(v.longValue);
3583 break;
3584 case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
3585 $$ = unoidl::detail::SourceProviderExpr::Uint(v.unsignedLongValue);
3586 break;
3587 case unoidl::ConstantValue::TYPE_HYPER:
3588 $$ = unoidl::detail::SourceProviderExpr::Int(v.hyperValue);
3589 break;
3590 case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
3591 $$ = unoidl::detail::SourceProviderExpr::Uint(v.unsignedHyperValue);
3592 break;
3593 case unoidl::ConstantValue::TYPE_FLOAT:
3594 $$ = unoidl::detail::SourceProviderExpr::Float(v.floatValue);
3595 break;
3596 case unoidl::ConstantValue::TYPE_DOUBLE:
3597 $$ = unoidl::detail::SourceProviderExpr::Float(v.doubleValue);
3598 break;
3603 typeArguments:
3604 typeArguments ',' type
3606 unoidl::detail::SourceProviderType t(*$3);
3607 delete $3;
3608 if (!checkTypeArgument(@3, yyscanner, t)) {
3609 delete $1; /* see commented-out %destructor above */
3610 YYERROR;
3612 $1->push_back(t);
3613 $$ = $1;
3615 | type
3617 unoidl::detail::SourceProviderType t(*$1);
3618 delete $1;
3619 if (!checkTypeArgument(@1, yyscanner, t)) {
3620 YYERROR;
3622 $$ = new std::vector<unoidl::detail::SourceProviderType>;
3623 $$->push_back(t);
3627 type:
3628 TOK_VOID
3630 $$ = new unoidl::detail::SourceProviderType(
3631 unoidl::detail::SourceProviderType::TYPE_VOID);
3633 | TOK_BOOLEAN
3635 $$ = new unoidl::detail::SourceProviderType(
3636 unoidl::detail::SourceProviderType::TYPE_BOOLEAN);
3638 | TOK_BYTE
3640 $$ = new unoidl::detail::SourceProviderType(
3641 unoidl::detail::SourceProviderType::TYPE_BYTE);
3643 | TOK_SHORT
3645 $$ = new unoidl::detail::SourceProviderType(
3646 unoidl::detail::SourceProviderType::TYPE_SHORT);
3648 | TOK_UNSIGNED TOK_SHORT
3650 $$ = new unoidl::detail::SourceProviderType(
3651 unoidl::detail::SourceProviderType::TYPE_UNSIGNED_SHORT);
3653 | TOK_LONG
3655 $$ = new unoidl::detail::SourceProviderType(
3656 unoidl::detail::SourceProviderType::TYPE_LONG);
3658 | TOK_UNSIGNED TOK_LONG
3660 $$ = new unoidl::detail::SourceProviderType(
3661 unoidl::detail::SourceProviderType::TYPE_UNSIGNED_LONG);
3663 | TOK_HYPER
3665 $$ = new unoidl::detail::SourceProviderType(
3666 unoidl::detail::SourceProviderType::TYPE_HYPER);
3668 | TOK_UNSIGNED TOK_HYPER
3670 $$ = new unoidl::detail::SourceProviderType(
3671 unoidl::detail::SourceProviderType::TYPE_UNSIGNED_HYPER);
3673 | TOK_FLOAT
3675 $$ = new unoidl::detail::SourceProviderType(
3676 unoidl::detail::SourceProviderType::TYPE_FLOAT);
3678 | TOK_DOUBLE
3680 $$ = new unoidl::detail::SourceProviderType(
3681 unoidl::detail::SourceProviderType::TYPE_DOUBLE);
3683 | TOK_CHAR
3685 $$ = new unoidl::detail::SourceProviderType(
3686 unoidl::detail::SourceProviderType::TYPE_CHAR);
3688 | TOK_STRING
3690 $$ = new unoidl::detail::SourceProviderType(
3691 unoidl::detail::SourceProviderType::TYPE_STRING);
3693 | TOK_TYPE
3695 $$ = new unoidl::detail::SourceProviderType(
3696 unoidl::detail::SourceProviderType::TYPE_TYPE);
3698 | TOK_ANY
3700 $$ = new unoidl::detail::SourceProviderType(
3701 unoidl::detail::SourceProviderType::TYPE_ANY);
3703 | TOK_SEQUENCE '<' type '>'
3705 switch ($3->type) {
3706 case unoidl::detail::SourceProviderType::TYPE_VOID:
3707 case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
3708 case unoidl::detail::SourceProviderType::TYPE_PARAMETER: //TODO?
3709 error(@3, yyscanner, u"illegal sequence type component type"_ustr);
3710 YYERROR;
3711 break;
3712 default:
3713 break;
3715 $$ = new unoidl::detail::SourceProviderType($3);
3716 delete $3;
3718 | name
3720 unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
3721 OUString name(convertName($1));
3722 bool done = false;
3723 if (name.indexOf('.') == -1 && !data->currentName.isEmpty()) {
3724 unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
3725 unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *
3726 pad = dynamic_cast<
3727 unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
3728 ent->pad.get());
3729 if (pad != nullptr
3730 && (std::find(
3731 pad->typeParameters.begin(), pad->typeParameters.end(),
3732 name)
3733 != pad->typeParameters.end()))
3735 $$ = new unoidl::detail::SourceProviderType(name);
3736 done = true;
3739 if (!done) {
3740 unoidl::detail::SourceProviderEntity const * ent;
3741 unoidl::detail::SourceProviderType t;
3742 switch (findEntity(
3743 @1, yyscanner, data, false, &name, &ent, nullptr, &t))
3745 case FOUND_ERROR:
3746 YYERROR;
3747 break;
3748 case FOUND_TYPE:
3749 $$ = new unoidl::detail::SourceProviderType(t);
3750 break;
3751 case FOUND_ENTITY:
3752 if (ent == nullptr) {
3753 error(@1, yyscanner, "unknown entity " + name);
3754 YYERROR;
3756 bool ok = false;
3757 switch (ent->kind) {
3758 case unoidl::detail::SourceProviderEntity::KIND_LOCAL:
3759 if (ent->pad.is()) {
3760 if (data->publishedContext && !ent->pad->isPublished()) {
3761 error(
3762 @1, yyscanner,
3763 ("unpublished entity " + name
3764 + " used in published context"));
3765 YYERROR;
3767 if (dynamic_cast<unoidl::detail::SourceProviderEnumTypeEntityPad *>(
3768 ent->pad.get())
3769 != nullptr)
3771 $$ = new unoidl::detail::SourceProviderType(
3772 unoidl::detail::SourceProviderType::TYPE_ENUM,
3773 name, ent);
3774 ok = true;
3775 } else if (dynamic_cast<unoidl::detail::SourceProviderPlainStructTypeEntityPad *>(
3776 ent->pad.get())
3777 != nullptr)
3779 $$ = new unoidl::detail::SourceProviderType(
3780 unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT,
3781 name, ent);
3782 ok = true;
3783 } else if (dynamic_cast<unoidl::detail::SourceProviderPolymorphicStructTypeTemplateEntityPad *>(
3784 ent->pad.get())
3785 != nullptr)
3787 error(
3788 @1, yyscanner,
3789 (("recursive reference to polymorphic struct type"
3790 " template ")
3791 + name));
3792 YYERROR;
3793 } else if (dynamic_cast<unoidl::detail::SourceProviderExceptionTypeEntityPad *>(
3794 ent->pad.get())
3795 != nullptr)
3797 $$ = new unoidl::detail::SourceProviderType(
3798 unoidl::detail::SourceProviderType::TYPE_EXCEPTION,
3799 name, ent);
3800 ok = true;
3801 } else if (dynamic_cast<unoidl::detail::SourceProviderInterfaceTypeEntityPad *>(
3802 ent->pad.get())
3803 != nullptr)
3805 $$ = new unoidl::detail::SourceProviderType(
3806 unoidl::detail::SourceProviderType::TYPE_INTERFACE,
3807 name, ent);
3808 ok = true;
3810 break;
3812 assert(ent->entity.is());
3813 [[fallthrough]];
3814 case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
3815 if (data->publishedContext
3816 && ent->entity->getSort() != unoidl::Entity::SORT_MODULE
3817 && !static_cast<unoidl::PublishableEntity *>(
3818 ent->entity.get())->isPublished())
3820 error(
3821 @1, yyscanner,
3822 ("unpublished entity " + name
3823 + " used in published context"));
3824 YYERROR;
3826 switch (ent->entity->getSort()) {
3827 case unoidl::Entity::SORT_ENUM_TYPE:
3828 $$ = new unoidl::detail::SourceProviderType(
3829 unoidl::detail::SourceProviderType::TYPE_ENUM, name,
3830 ent);
3831 ok = true;
3832 break;
3833 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
3834 $$ = new unoidl::detail::SourceProviderType(
3835 unoidl::detail::SourceProviderType::TYPE_PLAIN_STRUCT,
3836 name, ent);
3837 ok = true;
3838 break;
3839 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
3840 error(
3841 @1, yyscanner,
3842 ("polymorphic struct type template " + name
3843 + " without type arguments"));
3844 YYERROR;
3845 break;
3846 case unoidl::Entity::SORT_EXCEPTION_TYPE:
3847 $$ = new unoidl::detail::SourceProviderType(
3848 unoidl::detail::SourceProviderType::TYPE_EXCEPTION,
3849 name, ent);
3850 ok = true;
3851 break;
3852 case unoidl::Entity::SORT_INTERFACE_TYPE:
3853 $$ = new unoidl::detail::SourceProviderType(
3854 unoidl::detail::SourceProviderType::TYPE_INTERFACE,
3855 name, ent);
3856 ok = true;
3857 break;
3858 case unoidl::Entity::SORT_TYPEDEF:
3859 O3TL_UNREACHABLE;
3860 default:
3861 break;
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;
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");
3882 if (!ok) {
3883 error(@1, yyscanner, "non-type entity " + name);
3884 YYERROR;
3886 break;
3890 | name '<' typeArguments '>'
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)
3900 YYERROR;
3902 if (ent == nullptr) {
3903 error(@1, yyscanner, "unknown entity " + name);
3904 YYERROR;
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)
3914 error(
3915 @1, yyscanner,
3916 (("recursive reference to polymorphic struct type"
3917 " template ")
3918 + name));
3919 YYERROR;
3921 break;
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)
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;
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;
3946 $$ = new unoidl::detail::SourceProviderType(name, ent, std::move(args));
3947 ok = true;
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");
3956 if (!ok) {
3957 error(@1, yyscanner, "non-type entity " + name);
3958 YYERROR;
3963 name:
3964 name TOK_COLONS identifier { *$1 += "." + *$3; delete $3; $$ = $1; }
3965 | TOK_COLONS identifier { *$2 = "." + *$2; $$ = $2; }
3966 | identifier
3969 identifier:
3970 TOK_IDENTIFIER
3971 | TOK_GET { $$ = new OString("get"_ostr); }
3972 | TOK_PUBLISHED { $$ = new OString("published"_ostr); }
3973 | TOK_SET { $$ = new OString("set"_ostr); }
3976 deprecated_opt:
3977 TOK_DEPRECATED { $$ = true; }
3978 | /* empty */ { $$ = false; }
3983 namespace unoidl::detail {
3985 OUString SourceProviderType::getName() const {
3986 if (!typedefName.isEmpty()) {
3987 return typedefName;
3989 switch (type) {
3990 case unoidl::detail::SourceProviderType::TYPE_VOID:
3991 return u"void"_ustr;
3992 case unoidl::detail::SourceProviderType::TYPE_BOOLEAN:
3993 return u"boolean"_ustr;
3994 case unoidl::detail::SourceProviderType::TYPE_BYTE:
3995 return u"byte"_ustr;
3996 case unoidl::detail::SourceProviderType::TYPE_SHORT:
3997 return u"short"_ustr;
3998 case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_SHORT:
3999 return u"unsigned short"_ustr;
4000 case unoidl::detail::SourceProviderType::TYPE_LONG:
4001 return u"long"_ustr;
4002 case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_LONG:
4003 return u"unsigned long"_ustr;
4004 case unoidl::detail::SourceProviderType::TYPE_HYPER:
4005 return u"hyper"_ustr;
4006 case unoidl::detail::SourceProviderType::TYPE_UNSIGNED_HYPER:
4007 return u"unsigned hyper"_ustr;
4008 case unoidl::detail::SourceProviderType::TYPE_FLOAT:
4009 return u"float"_ustr;
4010 case unoidl::detail::SourceProviderType::TYPE_DOUBLE:
4011 return u"double"_ustr;
4012 case unoidl::detail::SourceProviderType::TYPE_CHAR:
4013 return u"char"_ustr;
4014 case unoidl::detail::SourceProviderType::TYPE_STRING:
4015 return u"string"_ustr;
4016 case unoidl::detail::SourceProviderType::TYPE_TYPE:
4017 return u"type"_ustr;
4018 case unoidl::detail::SourceProviderType::TYPE_ANY:
4019 return u"any"_ustr;
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:
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(",");
4037 n.append(i->getName());
4039 return n.append(">").makeStringAndClear();
4041 default:
4042 assert(false && "this cannot happen"); for (;;) { std::abort(); }
4046 bool SourceProviderType::equals(SourceProviderType const & other) const {
4047 if (type != other.type || name != other.name
4048 || subtypes.size() != other.subtypes.size())
4050 return false;
4052 for (auto i(subtypes.begin()), j(other.subtypes.begin());
4053 i != subtypes.end(); ++i, ++j)
4055 if (!i->equals(*j)) {
4056 return false;
4059 return true;
4062 bool SourceProviderInterfaceTypeEntityPad::addDirectBase(
4063 YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
4064 DirectBase const & base, bool optional)
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)))
4074 return false;
4076 if (optional) {
4077 addOptionalBaseMembers(
4078 location, yyscanner, data, base.name, base.entity);
4080 (optional ? directOptionalBases : directMandatoryBases).push_back(base);
4081 return true;
4084 bool SourceProviderInterfaceTypeEntityPad::addDirectMember(
4085 YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
4086 OUString const & name)
4088 assert(data != nullptr);
4089 if (!checkMemberClashes(location, yyscanner, data, u"", name, true)) {
4090 return false;
4092 allMembers.emplace(name, Member(data->currentName));
4093 return true;
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
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;
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;
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;
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;
4144 return true;
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)
4156 return false;
4158 if (p == nullptr || !p->entity.is()
4159 || (p->entity->getSort()
4160 != unoidl::Entity::SORT_INTERFACE_TYPE))
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;
4169 if (!checkBaseClashes(
4170 location, yyscanner, data, n,
4171 static_cast<unoidl::InterfaceTypeEntity *>(
4172 p->entity.get()),
4173 false, false, outerOptional, seen))
4175 return false;
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)
4186 return false;
4188 if (p == nullptr || !p->entity.is()
4189 || (p->entity->getSort()
4190 != unoidl::Entity::SORT_INTERFACE_TYPE))
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;
4199 if (!checkBaseClashes(
4200 location, yyscanner, data, n,
4201 static_cast<unoidl::InterfaceTypeEntity *>(
4202 p->entity.get()),
4203 false, true, outerOptional, seen))
4205 return false;
4208 for (auto & j: entity->getDirectAttributes()) {
4209 if (!checkMemberClashes(
4210 location, yyscanner, data, name, j.name,
4211 !outerOptional))
4213 return false;
4216 for (auto & j: entity->getDirectMethods()) {
4217 if (!checkMemberClashes(
4218 location, yyscanner, data, name, j.name,
4219 !outerOptional))
4221 return false;
4226 return true;
4229 bool SourceProviderInterfaceTypeEntityPad::checkMemberClashes(
4230 YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
4231 std::u16string_view interfaceName, OUString const & memberName,
4232 bool checkOptional) const
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;
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;
4258 return true;
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)
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;
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)
4286 return false;
4288 if (q == nullptr || !q->entity.is()
4289 || q->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
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;
4298 if (!addBase(
4299 location, yyscanner, data, directBaseName, n,
4300 static_cast<unoidl::InterfaceTypeEntity *>(q->entity.get()),
4301 false, false))
4303 return false;
4306 for (auto & i: entity->getDirectOptionalBases())
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)
4314 return false;
4316 if (q == nullptr || !q->entity.is()
4317 || q->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
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;
4326 if (!addBase(
4327 location, yyscanner, data, directBaseName, n,
4328 static_cast<unoidl::InterfaceTypeEntity *>(q->entity.get()),
4329 false, true))
4331 return false;
4334 for (auto & i: entity->getDirectAttributes()) {
4335 allMembers.emplace(i.name, Member(name));
4337 for (auto & i: entity->getDirectMethods()) {
4338 allMembers.emplace(i.name, Member(name));
4341 return true;
4344 bool SourceProviderInterfaceTypeEntityPad::addOptionalBaseMembers(
4345 YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
4346 OUString const & name,
4347 rtl::Reference<unoidl::InterfaceTypeEntity> const & entity)
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)
4357 return false;
4359 if (p == nullptr || !p->entity.is()
4360 || p->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
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;
4369 if (!addOptionalBaseMembers(
4370 location, yyscanner, data, n,
4371 static_cast<unoidl::InterfaceTypeEntity *>(p->entity.get())))
4373 return false;
4376 for (auto & i: entity->getDirectAttributes()) {
4377 Member & m(
4378 allMembers.emplace(i.name, Member(u""_ustr))
4379 .first->second);
4380 if (m.mandatory.isEmpty()) {
4381 m.optional.insert(name);
4384 for (auto & i: entity->getDirectMethods()) {
4385 Member & m(
4386 allMembers.emplace(i.name, Member(u""_ustr))
4387 .first->second);
4388 if (m.mandatory.isEmpty()) {
4389 m.optional.insert(name);
4392 return true;
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));
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));
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));
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));
4438 int e2 = yyparse(yyscanner);
4439 yylex_destroy(yyscanner);
4440 switch (e2) {
4441 case 0:
4442 break;
4443 default:
4444 O3TL_UNREACHABLE;
4445 case 1:
4446 throw FileFormatException(
4447 uri,
4448 ("cannot parse"
4449 + (data->errorLine == 0
4450 ? OUString() : " line " + OUString::number(data->errorLine))
4451 + (data->parserError.isEmpty()
4452 ? OUString()
4453 : (", "
4454 + OStringToOUString(
4455 data->parserError, osl_getThreadTextEncoding())))
4456 + (data->errorMessage.isEmpty()
4457 ? OUString() : ": \"" + data->errorMessage + "\"")));
4458 case 2:
4459 throw std::bad_alloc();
4461 } catch (...) {
4462 e = osl_unmapMappedFile(handle, address, size);
4463 SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot unmap: " << +e);
4464 e = osl_closeFile(handle);
4465 SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot close: " << +e);
4466 throw;
4468 e = osl_unmapMappedFile(handle, address, size);
4469 SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot unmap: " << +e);
4470 e = osl_closeFile(handle);
4471 SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot close: " << +e);
4472 return true;
4477 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */