Refactored type parsing.
This commit is contained in:
		
							
								
								
									
										27
									
								
								include/plasp/pddl/Context.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								include/plasp/pddl/Context.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
#ifndef __PLASP__PDDL__CONTEXT_H
 | 
			
		||||
#define __PLASP__PDDL__CONTEXT_H
 | 
			
		||||
 | 
			
		||||
#include <plasp/pddl/Type.h>
 | 
			
		||||
 | 
			
		||||
namespace plasp
 | 
			
		||||
{
 | 
			
		||||
namespace pddl
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
//
 | 
			
		||||
// Context
 | 
			
		||||
//
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
struct Context
 | 
			
		||||
{
 | 
			
		||||
	TypeHashMap types;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -32,6 +32,7 @@ class Description
 | 
			
		||||
		void parseContent(utils::Parser &parser);
 | 
			
		||||
		void parseSection(utils::Parser &parser);
 | 
			
		||||
 | 
			
		||||
		Context m_context;
 | 
			
		||||
		std::unique_ptr<Domain> m_domain;
 | 
			
		||||
		//std::unique_ptr<Problem> m_problem;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
 | 
			
		||||
#include <plasp/pddl/Context.h>
 | 
			
		||||
#include <plasp/pddl/Requirement.h>
 | 
			
		||||
#include <plasp/pddl/Type.h>
 | 
			
		||||
#include <plasp/utils/Parser.h>
 | 
			
		||||
@@ -21,17 +22,15 @@ namespace pddl
 | 
			
		||||
class Domain
 | 
			
		||||
{
 | 
			
		||||
	public:
 | 
			
		||||
		static Domain fromPDDL(utils::Parser &parser);
 | 
			
		||||
 | 
			
		||||
		using TypesHashMap = std::unordered_map<std::string, Type>;
 | 
			
		||||
		static Domain fromPDDL(utils::Parser &parser, Context &context);
 | 
			
		||||
 | 
			
		||||
	public:
 | 
			
		||||
		const std::string &name() const;
 | 
			
		||||
		const Requirement::Types &requirements() const;
 | 
			
		||||
		const TypesHashMap &types() const;
 | 
			
		||||
		const TypeHashMap &types() const;
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		Domain() = default;
 | 
			
		||||
		Domain(Context &context);
 | 
			
		||||
 | 
			
		||||
		void parseSection(utils::Parser &parser);
 | 
			
		||||
 | 
			
		||||
@@ -43,9 +42,10 @@ class Domain
 | 
			
		||||
 | 
			
		||||
		void checkConsistency();
 | 
			
		||||
 | 
			
		||||
		Context &m_context;
 | 
			
		||||
 | 
			
		||||
		std::string m_name;
 | 
			
		||||
		Requirement::Types m_requirements;
 | 
			
		||||
		TypesHashMap m_types;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include <plasp/utils/Parser.h>
 | 
			
		||||
@@ -18,21 +19,30 @@ namespace pddl
 | 
			
		||||
//
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
class Context;
 | 
			
		||||
 | 
			
		||||
class Type;
 | 
			
		||||
using TypeHashMap = std::unordered_map<std::string, Type>;
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
class Type
 | 
			
		||||
{
 | 
			
		||||
	public:
 | 
			
		||||
		Type(std::string name);
 | 
			
		||||
		static void parsePDDL(utils::Parser &parser, Context &context);
 | 
			
		||||
 | 
			
		||||
	public:
 | 
			
		||||
		void setDirty(bool isDirty = true);
 | 
			
		||||
		bool isDirty() const;
 | 
			
		||||
 | 
			
		||||
		const std::string &name() const;
 | 
			
		||||
 | 
			
		||||
		void addParentType(const Type &parentType);
 | 
			
		||||
		const std::vector<const Type *> &parentTypes() const;
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		Type(std::string name);
 | 
			
		||||
 | 
			
		||||
		void setDirty(bool isDirty = true);
 | 
			
		||||
		bool isDirty() const;
 | 
			
		||||
 | 
			
		||||
		void addParentType(const Type &parentType);
 | 
			
		||||
 | 
			
		||||
		bool m_isDirty;
 | 
			
		||||
 | 
			
		||||
		std::string m_name;
 | 
			
		||||
 
 | 
			
		||||
@@ -81,7 +81,7 @@ void Description::parseSection(utils::Parser &parser)
 | 
			
		||||
	std::cout << "Parsing section " << sectionIdentifier << std::endl;
 | 
			
		||||
 | 
			
		||||
	if (sectionIdentifier == "domain")
 | 
			
		||||
		m_domain = std::make_unique<Domain>(Domain::fromPDDL(parser));
 | 
			
		||||
		m_domain = std::make_unique<Domain>(Domain::fromPDDL(parser, m_context));
 | 
			
		||||
	//else if (sectionIdentifier == "problem")
 | 
			
		||||
	//	m_problem = std::make_unique<Problem>(Problem::fromPDDL(parser));
 | 
			
		||||
	else
 | 
			
		||||
 
 | 
			
		||||
@@ -17,9 +17,16 @@ namespace pddl
 | 
			
		||||
//
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
Domain Domain::fromPDDL(utils::Parser &parser)
 | 
			
		||||
Domain::Domain(Context &context)
 | 
			
		||||
:	m_context(context)
 | 
			
		||||
{
 | 
			
		||||
	Domain domain;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
Domain Domain::fromPDDL(utils::Parser &parser, Context &context)
 | 
			
		||||
{
 | 
			
		||||
	Domain domain(context);
 | 
			
		||||
 | 
			
		||||
	domain.m_name = parser.parseIdentifier(isIdentifier);
 | 
			
		||||
 | 
			
		||||
@@ -60,9 +67,9 @@ const Requirement::Types &Domain::requirements() const
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
const Domain::TypesHashMap &Domain::types() const
 | 
			
		||||
const TypeHashMap &Domain::types() const
 | 
			
		||||
{
 | 
			
		||||
	return m_types;
 | 
			
		||||
	return m_context.types;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
@@ -193,48 +200,12 @@ void Domain::computeDerivedRequirements()
 | 
			
		||||
 | 
			
		||||
void Domain::parseTypingSection(utils::Parser &parser)
 | 
			
		||||
{
 | 
			
		||||
	// Parses a single type identifier
 | 
			
		||||
	const auto parseType =
 | 
			
		||||
		[&]() -> auto &
 | 
			
		||||
		{
 | 
			
		||||
			parser.skipWhiteSpace();
 | 
			
		||||
 | 
			
		||||
			const auto typeName = parser.parseIdentifier(isIdentifier);
 | 
			
		||||
			const auto insertionResult = m_types.emplace(std::make_pair(typeName, Type(typeName)));
 | 
			
		||||
			auto &type = insertionResult.first->second;
 | 
			
		||||
 | 
			
		||||
			// Flag type for potentially upcoming parent type declaration
 | 
			
		||||
			type.setDirty();
 | 
			
		||||
 | 
			
		||||
			parser.skipWhiteSpace();
 | 
			
		||||
 | 
			
		||||
			return type;
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
	// Parses a type and potentially its parent type
 | 
			
		||||
	while (parser.currentCharacter() != ')')
 | 
			
		||||
	{
 | 
			
		||||
		parseType();
 | 
			
		||||
		Type::parsePDDL(parser, m_context);
 | 
			
		||||
 | 
			
		||||
		// Check for type inheritance
 | 
			
		||||
		if (!parser.advanceIf('-'))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		// If existing, parse parent type
 | 
			
		||||
		auto &parentType = parseType();
 | 
			
		||||
 | 
			
		||||
		parentType.setDirty(false);
 | 
			
		||||
 | 
			
		||||
		// Assign parent type to all types that were previously flagged
 | 
			
		||||
		std::for_each(m_types.begin(), m_types.end(),
 | 
			
		||||
			[&](auto &childType)
 | 
			
		||||
			{
 | 
			
		||||
				if (!childType.second.isDirty())
 | 
			
		||||
					return;
 | 
			
		||||
 | 
			
		||||
				childType.second.addParentType(parentType);
 | 
			
		||||
				childType.second.setDirty(false);
 | 
			
		||||
			});
 | 
			
		||||
		parser.skipWhiteSpace();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parser.expect<std::string>(")");
 | 
			
		||||
@@ -244,7 +215,7 @@ void Domain::parseTypingSection(utils::Parser &parser)
 | 
			
		||||
 | 
			
		||||
void Domain::checkConsistency()
 | 
			
		||||
{
 | 
			
		||||
	if (!m_types.empty() && !hasRequirement(Requirement::Type::Typing))
 | 
			
		||||
	if (!m_context.types.empty() && !hasRequirement(Requirement::Type::Typing))
 | 
			
		||||
	{
 | 
			
		||||
		throw ConsistencyException("Domain contains typing information but does not declare typing requirement");
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,10 @@
 | 
			
		||||
#include <plasp/pddl/Type.h>
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
#include <plasp/pddl/Context.h>
 | 
			
		||||
#include <plasp/pddl/Identifier.h>
 | 
			
		||||
 | 
			
		||||
namespace plasp
 | 
			
		||||
{
 | 
			
		||||
namespace pddl
 | 
			
		||||
@@ -13,12 +18,69 @@ namespace pddl
 | 
			
		||||
 | 
			
		||||
Type::Type(std::string name)
 | 
			
		||||
:	m_isDirty{false},
 | 
			
		||||
	m_name{name}
 | 
			
		||||
	m_name(name)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
void Type::parsePDDL(utils::Parser &parser, Context &context)
 | 
			
		||||
{
 | 
			
		||||
	// Parses a single type identifier
 | 
			
		||||
	const auto parseType =
 | 
			
		||||
		[&]() -> auto &
 | 
			
		||||
		{
 | 
			
		||||
			parser.skipWhiteSpace();
 | 
			
		||||
 | 
			
		||||
			const auto typeName = parser.parseIdentifier(isIdentifier);
 | 
			
		||||
			const auto match = context.types.find(typeName);
 | 
			
		||||
			const auto typeExists = (match != context.types.cend());
 | 
			
		||||
 | 
			
		||||
			if (typeExists)
 | 
			
		||||
			{
 | 
			
		||||
				auto &type = match->second;
 | 
			
		||||
 | 
			
		||||
				type.setDirty();
 | 
			
		||||
 | 
			
		||||
				return type;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			const auto insertionResult = context.types.emplace(std::make_pair(typeName, Type(typeName)));
 | 
			
		||||
			auto &type = insertionResult.first->second;
 | 
			
		||||
 | 
			
		||||
			// Flag type for potentially upcoming parent type declaration
 | 
			
		||||
			type.setDirty();
 | 
			
		||||
 | 
			
		||||
			return type;
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
	parseType();
 | 
			
		||||
 | 
			
		||||
	parser.skipWhiteSpace();
 | 
			
		||||
 | 
			
		||||
	// Check for type inheritance
 | 
			
		||||
	if (!parser.advanceIf('-'))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	// If existing, parse parent type
 | 
			
		||||
	auto &parentType = parseType();
 | 
			
		||||
 | 
			
		||||
	parentType.setDirty(false);
 | 
			
		||||
 | 
			
		||||
	// Assign parent type to all types that were previously flagged
 | 
			
		||||
	std::for_each(context.types.begin(), context.types.end(),
 | 
			
		||||
		[&](auto &childType)
 | 
			
		||||
		{
 | 
			
		||||
			if (!childType.second.isDirty())
 | 
			
		||||
				return;
 | 
			
		||||
 | 
			
		||||
			childType.second.addParentType(parentType);
 | 
			
		||||
			childType.second.setDirty(false);
 | 
			
		||||
		});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
void Type::setDirty(bool isDirty)
 | 
			
		||||
{
 | 
			
		||||
	m_isDirty = isDirty;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user