diff --git a/lib/pddlparse/src/pddlparse/detail/parsing/PrimitiveTypeDeclaration.cpp b/lib/pddlparse/src/pddlparse/detail/parsing/PrimitiveTypeDeclaration.cpp index 83e3ba7..56657b2 100644 --- a/lib/pddlparse/src/pddlparse/detail/parsing/PrimitiveTypeDeclaration.cpp +++ b/lib/pddlparse/src/pddlparse/detail/parsing/PrimitiveTypeDeclaration.cpp @@ -44,9 +44,9 @@ void parseAndAddPrimitiveTypeDeclarations(Context &context, ast::Domain &domain) auto &tokenizer = context.tokenizer; tokenizer.skipWhiteSpace(); - // Index on the first element of the current inheritance list - size_t inheritanceIndex = 0; + const auto position = tokenizer.position(); + // First pass: collect all primitive types while (tokenizer.currentCharacter() != ')') { parseAndAddUntypedPrimitiveTypeDeclaration(context, domain); @@ -56,18 +56,43 @@ void parseAndAddPrimitiveTypeDeclarations(Context &context, ast::Domain &domain) if (!tokenizer.testAndSkip('-')) continue; + // Skip parent type information for now + tokenizer.getIdentifier(); + } + + tokenizer.seek(position); + + // Second pass: link parent types correctly + // Index on the first element of the current inheritance list + size_t inheritanceIndex = 0; + size_t i = 0; + + while (tokenizer.currentCharacter() != ')') + { + // Skip type declaration + tokenizer.getIdentifier(); + tokenizer.skipWhiteSpace(); + + if (!tokenizer.testAndSkip('-')) + { + i++; + continue; + } + // If existing, parse and store parent type auto parentType = parsePrimitiveType(context, domain); auto &types = domain.types; - for (size_t i = inheritanceIndex; i < types.size(); i++) - types[i]->parentTypes.emplace_back(ast::deepCopy(parentType)); + for (size_t j = inheritanceIndex; j <= i; j++) + types[j]->parentTypes.emplace_back(ast::deepCopy(parentType)); // All types up to now are labeled with their parent types - inheritanceIndex = types.size(); + inheritanceIndex = i + 1; tokenizer.skipWhiteSpace(); + + i++; } } diff --git a/lib/pddlparse/tests/TestOfficialPDDLInstances.cpp b/lib/pddlparse/tests/TestOfficialPDDLInstances.cpp index 858a0a0..8d6f046 100644 --- a/lib/pddlparse/tests/TestOfficialPDDLInstances.cpp +++ b/lib/pddlparse/tests/TestOfficialPDDLInstances.cpp @@ -236,4 +236,46 @@ TEST_CASE("[PDDL parser] The official PDDL instances are parsed correctly", "[PD CHECK(constants[13]->name == "smooth"); CHECK(constants[13]->type.value().get()->declaration->name == "surface"); } + + SECTION("type inheritance in logistics domain") + { + context.mode = pddl::Mode::Compatibility; + + const auto domainFile = pddlInstanceBasePath / "ipc-2000" / "domains" / "logistics-strips-typed" / "domain.pddl"; + context.tokenizer.read(domainFile); + auto description = pddl::parseDescription(context); + + const auto &types = description.domain->types; + + REQUIRE(types.size() == 10); + CHECK(types[0]->name == "truck"); + REQUIRE(types[0]->parentTypes.size() == 1); + CHECK(types[0]->parentTypes[0]->declaration->name == "vehicle"); + CHECK(types[1]->name == "airplane"); + REQUIRE(types[1]->parentTypes.size() == 1); + CHECK(types[1]->parentTypes[0]->declaration->name == "vehicle"); + CHECK(types[2]->name == "package"); + REQUIRE(types[2]->parentTypes.size() == 1); + CHECK(types[2]->parentTypes[0]->declaration->name == "physobj"); + CHECK(types[3]->name == "vehicle"); + REQUIRE(types[3]->parentTypes.size() == 1); + CHECK(types[3]->parentTypes[0]->declaration->name == "physobj"); + CHECK(types[4]->name == "airport"); + REQUIRE(types[4]->parentTypes.size() == 1); + CHECK(types[4]->parentTypes[0]->declaration->name == "place"); + CHECK(types[5]->name == "location"); + REQUIRE(types[5]->parentTypes.size() == 1); + CHECK(types[5]->parentTypes[0]->declaration->name == "place"); + CHECK(types[6]->name == "city"); + REQUIRE(types[6]->parentTypes.size() == 1); + CHECK(types[6]->parentTypes[0]->declaration->name == "object"); + CHECK(types[7]->name == "place"); + REQUIRE(types[7]->parentTypes.size() == 1); + CHECK(types[7]->parentTypes[0]->declaration->name == "object"); + CHECK(types[8]->name == "physobj"); + REQUIRE(types[8]->parentTypes.size() == 1); + CHECK(types[8]->parentTypes[0]->declaration->name == "object"); + CHECK(types[9]->name == "object"); + REQUIRE(types[9]->parentTypes.empty()); + } }