From 7d2066e7c27b35f22e380746fd30bee7e8968eaa Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 22 Aug 2024 12:07:00 +0200 Subject: [PATCH] Don't eat opening parens on nested list --- src/ifcparse/IfcFile.cpp | 99 +++-------------------------------- src/ifcparse/IfcParse.cpp | 5 ++ src/ifcparse/IfcSpfHeader.cpp | 1 + src/ifcparse/variantarray.h | 2 +- 4 files changed, 15 insertions(+), 92 deletions(-) diff --git a/src/ifcparse/IfcFile.cpp b/src/ifcparse/IfcFile.cpp index 5a8db304e5..27b27c1b2e 100644 --- a/src/ifcparse/IfcFile.cpp +++ b/src/ifcparse/IfcFile.cpp @@ -41,86 +41,6 @@ namespace { template constexpr bool is_type_in_variant_v = is_type_in_variant::value; - - IfcUtil::ArgumentType get_element_type(IfcUtil::ArgumentType aggregate) { - switch (aggregate) { - case IfcUtil::Argument_AGGREGATE_OF_INT: - return IfcUtil::Argument_INT; - case IfcUtil::Argument_AGGREGATE_OF_DOUBLE: - return IfcUtil::Argument_DOUBLE; - case IfcUtil::Argument_AGGREGATE_OF_STRING: - return IfcUtil::Argument_STRING; - case IfcUtil::Argument_AGGREGATE_OF_BINARY: - return IfcUtil::Argument_BINARY; - case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: - return IfcUtil::Argument_ENTITY_INSTANCE; - - case IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE: - return IfcUtil::Argument_EMPTY_AGGREGATE; - case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT: - return IfcUtil::Argument_AGGREGATE_OF_INT; - case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE: - return IfcUtil::Argument_AGGREGATE_OF_DOUBLE; - case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: - return IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE; - - default: - return IfcUtil::Argument_UNKNOWN; - } - } - - bool can_coerce(IfcUtil::ArgumentType target, IfcUtil::ArgumentType source) { - if (source == IfcUtil::Argument_EMPTY_AGGREGATE) { - return target == IfcUtil::Argument_AGGREGATE_OF_INT || - target == IfcUtil::Argument_AGGREGATE_OF_DOUBLE || - target == IfcUtil::Argument_AGGREGATE_OF_STRING || - target == IfcUtil::Argument_AGGREGATE_OF_BINARY || - target == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE || - target == IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE || - target == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT || - target == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE || - target == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE; - } if (source == IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE) { - return target == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT || - target == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE || - target == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE; - } else if (source == IfcUtil::Argument_BOOL && target == IfcUtil::Argument_LOGICAL) { - return true; - } else { - // @todo make it configurable to coerce int to double, which is not standard compliant? - auto elt = get_element_type(target); - auto els = get_element_type(source); - if (elt != IfcUtil::Argument_UNKNOWN && els != IfcUtil::Argument_UNKNOWN) { - return can_coerce(elt, els); - } - return false; - } - } - - // we need to have a compatibility between (#123, IfcLengthMeasure(123.)) - // which are different token kinds - void get_token_type(std::vector& r, const boost::variant& v) { - r.push_back((uint8_t)v.which()); - if (v.which() == 0) { - // pass - } else if (v.which() == 1) { - r.push_back((uint8_t)boost::get(v).type); - } else if (v.which() == 2) { - // @todo check for empty aggregate - get_token_type(r, boost::get(v)->tokens_.front()); - } - } - - bool can_coerce(const std::vector& target, const std::vector& source) { - if (target == std::vector{0, 0} && source == std::vector{1, IfcParse::Token_IDENTIFIER}) { - return true; - } - if (source == std::vector{0, 0} && target == std::vector{1, IfcParse::Token_IDENTIFIER}) { - return true; - } - return source == target; - } - struct InstanceReference { int v; operator int() const { @@ -149,7 +69,7 @@ namespace { } } - template + template void construct_(IfcParse::parse_context& p, const IfcParse::aggregation_type* aggr, Fn fn) { if (p.tokens_.empty()) { // @todo instead of ugly if-else we could also default initialize the respective @@ -203,6 +123,7 @@ namespace { vec_ptr->push_back(v); } else { // inconsistent aggregate valuation + // @todo boolean -> logical upgrade } } } else { @@ -216,14 +137,10 @@ namespace { // @todo get aggregate of enumeration dispatch_token(v, aggr && aggr->type_of_element()->as_named_type() ? aggr->type_of_element()->as_named_type()->declared_type() : nullptr, append_to_aggregate_storage); } else if constexpr (std::is_same_v, IfcParse::parse_context*>) { - /*construct_(*v, [&aggregate_storage](auto& v) { - if (aggregate_storage.which() == 0) { - aggregate_storage = std::vector>{ v }; - } else { - boost::get>>(aggregate_storage).push_back(v); - } - });*/ - // Too deeply nested list + if constexpr (Depth < 3) { + construct_(*v, nullptr, append_to_aggregate_storage); + } + // nested list } else { append_to_aggregate_storage(v); } @@ -294,11 +211,11 @@ IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_re } else if constexpr (std::is_same_v, IfcParse::parse_context*>) { const auto *pt = param_type; if (pt) { - while (pt->as_named_type()) { + while (pt->as_named_type() && pt->as_named_type()->declared_type()->as_type_declaration()) { pt = pt->as_named_type()->declared_type()->as_type_declaration()->declared_type(); } } - construct_(*v, pt ? pt->as_aggregation_type() : nullptr, [this, &storage, name, &references_to_resolve, index](const auto& v) { + construct_<0>(*v, pt ? pt->as_aggregation_type() : nullptr, [this, &storage, name, &references_to_resolve, index](const auto& v) { if constexpr (std::is_same_v, std::vector>) { references_to_resolve.push_back({ {name, index }, v }); } else if constexpr (std::is_same_v, std::vector>>) { diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index a31bc7d11e..a7ba6a6a4b 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -689,9 +689,11 @@ std::string TokenFunc::toString(const Token& token) { void IfcParse::IfcFile::load(unsigned entity_instance_name, const IfcParse::entity* entity, parse_context& context, int attribute_index) { Token next = tokens->Next(); + /* if (TokenFunc::isOperator(next, '(')) { next = tokens->Next(); } + */ size_t attribute_index_within_data = 0; size_t return_value = 0; @@ -715,6 +717,7 @@ void IfcParse::IfcFile::load(unsigned entity_instance_name, const IfcParse::enti if (TokenFunc::isKeyword(next)) { try { parse_context ps; + tokens->Next(); load(0, nullptr, ps, -1); const auto *decl = schema_->declaration_by_name(TokenFunc::asStringRef(next)); auto* simple_type_instance = schema_->instantiate(decl, ps.construct(-1, references_to_resolve, decl)); @@ -744,6 +747,7 @@ IfcEntityInstanceData IfcParse::read(unsigned int i, IfcFile* f) { } const IfcParse::declaration* ty = f->schema()->declaration_by_name(TokenFunc::asStringRef(datatype)); parse_context pc; + f->tokens->Next(); f->load(i, ty->as_entity(), pc, -1); return IfcEntityInstanceData(pc.construct(i, f->references_to_resolve, ty)); } @@ -1295,6 +1299,7 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) { } parse_context ps; + tokens->Next(); load(current_id, entity_type->as_entity(), ps, -1); instance = schema_->instantiate(entity_type, ps.construct(current_id, references_to_resolve, entity_type)); instance->file_ = this; diff --git a/src/ifcparse/IfcSpfHeader.cpp b/src/ifcparse/IfcSpfHeader.cpp index 0cef9e3dfd..aaebe0a4c1 100644 --- a/src/ifcparse/IfcSpfHeader.cpp +++ b/src/ifcparse/IfcSpfHeader.cpp @@ -39,6 +39,7 @@ using namespace IfcParse; namespace { IfcEntityInstanceData read_from_file(IfcFile* f, size_t s) { parse_context pc; + f->tokens->Next(); f->load(-1, nullptr, pc, -1); return pc.construct(-1, f->references_to_resolve, nullptr); /*std::ostringstream oss; diff --git a/src/ifcparse/variantarray.h b/src/ifcparse/variantarray.h index 5307ab3562..960921312a 100644 --- a/src/ifcparse/variantarray.h +++ b/src/ifcparse/variantarray.h @@ -223,7 +223,7 @@ public: // in various places. throw IfcParse::IfcException( "Type held at index " + std::to_string(index) + " is " + - get_type_name(index) + " and not " + typeid(T).name() + get_type_name(size_and_indices_[index + 1]) + " and not " + typeid(T).name() ); } using V = typename std::tuple_element, impl::MapTypes_t>::type;