patrick
/
plasp
Archived
1
0
Fork 0

Implemented multi-file input.

This commit is contained in:
Patrick Lühne 2016-06-07 15:54:01 +02:00
parent 64190ba55a
commit 4228ca01dc
13 changed files with 154 additions and 51 deletions

View File

@ -16,7 +16,7 @@ int main(int argc, char **argv)
description.add_options() description.add_options()
("help,h", "Display this help message.") ("help,h", "Display this help message.")
("version,v", "Display version information.") ("version,v", "Display version information.")
("input,i", po::value<std::string>(), "Specify the SAS input file.") ("input,i", po::value<std::vector<std::string>>(), "Specify the SAS input file.")
("format,f", po::value<std::string>()->default_value("SAS"), "Specify the file format (SAS or PDDL)."); ("format,f", po::value<std::string>()->default_value("SAS"), "Specify the file format (SAS or PDDL).");
po::positional_options_description positionalOptionsDescription; po::positional_options_description positionalOptionsDescription;
@ -66,10 +66,19 @@ int main(int argc, char **argv)
auto format = variablesMap["format"].as<std::string>(); auto format = variablesMap["format"].as<std::string>();
std::transform(format.begin(), format.end(), format.begin(), ::tolower); std::transform(format.begin(), format.end(), format.begin(), ::tolower);
const auto &inputFiles = variablesMap["input"].as<std::vector<std::string>>();
if (format == "sas") if (format == "sas")
{ {
if (inputFiles.size() > 0)
{
std::cerr << "Error: Only one input file allowed for SAS translation" << std::endl;
printHelp();
return EXIT_FAILURE;
}
const auto sasDescription = variablesMap.count("input") const auto sasDescription = variablesMap.count("input")
? plasp::sas::Description::fromFile(variablesMap["input"].as<std::string>()) ? plasp::sas::Description::fromFile(inputFiles.front())
: plasp::sas::Description::fromStream(std::cin); : plasp::sas::Description::fromStream(std::cin);
const auto sasTranslator = plasp::sas::TranslatorASP(sasDescription); const auto sasTranslator = plasp::sas::TranslatorASP(sasDescription);
sasTranslator.translate(std::cout); sasTranslator.translate(std::cout);
@ -77,7 +86,7 @@ int main(int argc, char **argv)
else if (format == "pddl") else if (format == "pddl")
{ {
const auto pddlDescription = variablesMap.count("input") const auto pddlDescription = variablesMap.count("input")
? plasp::pddl::Description::fromFile(variablesMap["input"].as<std::string>()) ? plasp::pddl::Description::fromFiles(inputFiles)
: plasp::pddl::Description::fromStream(std::cin); : plasp::pddl::Description::fromStream(std::cin);
//std::cout << pddlDescription << std::endl; //std::cout << pddlDescription << std::endl;
} }

View File

@ -22,7 +22,7 @@ class Description
{ {
public: public:
static Description fromStream(std::istream &istream); static Description fromStream(std::istream &istream);
static Description fromFile(const boost::filesystem::path &path); static Description fromFiles(const std::vector<std::string> &paths);
public: public:
const Domain &domain() const; const Domain &domain() const;

View File

@ -30,9 +30,11 @@ class Domain
bool isDeclared() const; bool isDeclared() const;
void setName(std::string name);
const std::string &name() const; const std::string &name() const;
const Requirements &requirements() const; const Requirements &requirements() const;
bool hasRequirement(Requirement::Type requirementType) const;
expressions::PrimitiveTypes &types(); expressions::PrimitiveTypes &types();
const expressions::PrimitiveTypes &types() const; const expressions::PrimitiveTypes &types() const;
@ -52,7 +54,6 @@ class Domain
void parseSection(); void parseSection();
void parseRequirementSection(); void parseRequirementSection();
bool hasRequirement(Requirement::Type requirementType) const;
void computeDerivedRequirements(); void computeDerivedRequirements();
void parseTypeSection(); void parseTypeSection();

View File

@ -44,6 +44,8 @@ class Problem
bool hasRequirement(Requirement::Type requirementType) const; bool hasRequirement(Requirement::Type requirementType) const;
void computeDerivedRequirements(); void computeDerivedRequirements();
void parseDomainSection();
void parseObjectSection(); void parseObjectSection();
Context &m_context; Context &m_context;

View File

@ -21,6 +21,11 @@ class Parser
public: public:
explicit Parser(std::istream &istream); explicit Parser(std::istream &istream);
void setFileName(std::string fileName);
const std::string &fileName() const;
void resetPosition();
size_t row() const; size_t row() const;
size_t column() const; size_t column() const;
@ -60,6 +65,7 @@ class Parser
uint64_t parseIntegerBody(); uint64_t parseIntegerBody();
std::istream &m_istream; std::istream &m_istream;
std::string m_fileName;
std::istreambuf_iterator<char> m_position; std::istreambuf_iterator<char> m_position;
size_t m_row; size_t m_row;
@ -67,7 +73,7 @@ class Parser
bool m_isCaseSensitive; bool m_isCaseSensitive;
bool m_endOfFile; bool m_atEndOfFile;
}; };
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -31,7 +31,7 @@ class ParserException: public std::exception
} }
explicit ParserException(const utils::Parser &parser, const std::string &message) explicit ParserException(const utils::Parser &parser, const std::string &message)
: m_message{std::to_string(parser.row()) + ":" + std::to_string(parser.column()) + "\t" + message} : m_message{parser.fileName() + ":" + std::to_string(parser.row()) + ":" + std::to_string(parser.column()) + " " + message}
{ {
} }

View File

@ -31,7 +31,7 @@ class ParserWarning: public std::exception
} }
explicit ParserWarning(const utils::Parser &parser, const std::string &message) explicit ParserWarning(const utils::Parser &parser, const std::string &message)
: m_message{std::to_string(parser.row()) + ":" + std::to_string(parser.column()) + "\t" + message} : m_message{parser.fileName() + ":" + std::to_string(parser.row()) + ":" + std::to_string(parser.column()) + " " + message}
{ {
} }

View File

@ -20,7 +20,9 @@ namespace pddl
Description::Description(std::istream &istream) Description::Description(std::istream &istream)
: m_parser(istream), : m_parser(istream),
m_context(m_parser) m_context(m_parser),
m_domain{std::make_unique<Domain>(Domain(m_context))},
m_problem{std::make_unique<Problem>(Problem(m_context, *m_domain))}
{ {
m_parser.setCaseSensitive(false); m_parser.setCaseSensitive(false);
} }
@ -31,19 +33,9 @@ Description Description::fromStream(std::istream &istream)
{ {
Description description(istream); Description description(istream);
description.m_domain = std::make_unique<Domain>(Domain(description.m_context)); description.m_parser.setFileName("std::cin");
description.m_problem = std::make_unique<Problem>(Problem(description.m_context, *description.m_domain));
while (true)
{
description.m_context.parser.skipWhiteSpace();
if (description.m_context.parser.atEndOfFile())
break;
description.parseContent();
}
description.parseContent();
description.checkConsistency(); description.checkConsistency();
return description; return description;
@ -51,14 +43,36 @@ Description Description::fromStream(std::istream &istream)
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
Description Description::fromFile(const boost::filesystem::path &path) Description Description::fromFiles(const std::vector<std::string> &paths)
{ {
if (!boost::filesystem::is_regular_file(path)) BOOST_ASSERT(!paths.empty());
throw std::runtime_error("File does not exist: \"" + path.string() + "\"");
std::ifstream fileStream(path.string(), std::ios::in); std::for_each(paths.cbegin(), paths.cend(),
[&](const auto &path)
{
if (!boost::filesystem::is_regular_file(path))
throw std::runtime_error("File does not exist: \"" + path + "\"");
});
return Description::fromStream(fileStream); std::ifstream fileStream;
Description description(fileStream);
std::for_each(paths.cbegin(), paths.cend(),
[&](const auto &path)
{
fileStream.close();
fileStream.clear();
fileStream.open(path, std::ios::in);
description.m_parser.setFileName(path);
description.m_parser.resetPosition();
description.parseContent();
});
description.checkConsistency();
return description;
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -74,12 +88,18 @@ const Domain &Description::domain() const
void Description::parseContent() void Description::parseContent()
{ {
std::cout << "Parsing file content" << std::endl; while (true)
{
m_context.parser.skipWhiteSpace();
m_context.parser.expect<std::string>("("); if (m_context.parser.atEndOfFile())
m_context.parser.expect<std::string>("define"); return;
parseSection();
m_context.parser.expect<std::string>(")"); m_context.parser.expect<std::string>("(");
m_context.parser.expect<std::string>("define");
parseSection();
m_context.parser.expect<std::string>(")");
}
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -91,8 +111,6 @@ void Description::parseSection()
const auto sectionIdentifier = m_context.parser.parse<std::string>(); const auto sectionIdentifier = m_context.parser.parse<std::string>();
std::cout << "Parsing section " << sectionIdentifier << std::endl;
if (sectionIdentifier == "domain") if (sectionIdentifier == "domain")
{ {
BOOST_ASSERT(m_domain); BOOST_ASSERT(m_domain);
@ -119,6 +137,9 @@ void Description::parseSection()
void Description::checkConsistency() void Description::checkConsistency()
{ {
if (!m_domain->isDeclared())
throw ConsistencyException("No PDDL domain specified");
m_domain->checkConsistency(); m_domain->checkConsistency();
m_problem->checkConsistency(); m_problem->checkConsistency();
} }

View File

@ -32,7 +32,13 @@ Domain::Domain(Context &context)
void Domain::readPDDL() void Domain::readPDDL()
{ {
m_name = m_context.parser.parseIdentifier(isIdentifier); const auto domainName = m_context.parser.parseIdentifier(isIdentifier);
if (m_name.empty())
m_name = domainName;
// If the domain has previously been referenced, check that the name matches
else if (m_name != domainName)
throw utils::ParserException(m_context.parser, "Domains do not match (\"" + domainName + "\" and \"" + m_name + "\")");
std::cout << "Parsing domain " << m_name << std::endl; std::cout << "Parsing domain " << m_name << std::endl;
@ -62,6 +68,13 @@ bool Domain::isDeclared() const
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::setName(std::string name)
{
m_name = name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Domain::name() const const std::string &Domain::name() const
{ {
return m_name; return m_name;
@ -334,11 +347,22 @@ void Domain::checkConsistency()
// Verify that typing requirement is correctly declared if used // Verify that typing requirement is correctly declared if used
if (!m_primitiveTypes.empty() && !hasRequirement(Requirement::Type::Typing)) if (!m_primitiveTypes.empty() && !hasRequirement(Requirement::Type::Typing))
{ {
throw ConsistencyException("Domain contains typing information but does not declare typing requirement"); m_context.logger.parserWarning(m_context.parser, "Domain contains typing information but does not declare typing requirement");
m_requirements.push_back(Requirement(Requirement::Type::Typing)); m_requirements.push_back(Requirement(Requirement::Type::Typing));
} }
// Verify that all variables and constants have types
if (hasRequirement(Requirement::Type::Typing))
{
std::for_each(m_constants.cbegin(), m_constants.cend(),
[&](const auto &constant)
{
if (constant->type() == nullptr)
throw ConsistencyException("Constant \"" + constant->name() + "\" has no type");
});
}
// Verify that all used types have been declared // Verify that all used types have been declared
std::for_each(m_primitiveTypes.cbegin(), m_primitiveTypes.cend(), std::for_each(m_primitiveTypes.cbegin(), m_primitiveTypes.cend(),
[&](const auto &type) [&](const auto &type)
@ -366,7 +390,6 @@ void Domain::checkConsistency()
throw ConsistencyException("Predicate \"" + predicate->name() + "\" used but never declared"); throw ConsistencyException("Predicate \"" + predicate->name() + "\" used but never declared");
}); });
// Verify that all variables have types
// Verify that constants are unique // Verify that constants are unique
// Verify that all primitive types are unique // Verify that all primitive types are unique
// Check for case-sensitivity issues // Check for case-sensitivity issues

View File

@ -2,6 +2,7 @@
#include <algorithm> #include <algorithm>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/Identifier.h> #include <plasp/pddl/Identifier.h>
#include <plasp/pddl/expressions/Constant.h> #include <plasp/pddl/expressions/Constant.h>
#include <plasp/utils/IO.h> #include <plasp/utils/IO.h>
@ -134,7 +135,7 @@ void Problem::parseSection()
// TODO: check order of the sections // TODO: check order of the sections
if (sectionIdentifier == "domain") if (sectionIdentifier == "domain")
skipSection(); parseDomainSection();
else if (sectionIdentifier == "requirements") else if (sectionIdentifier == "requirements")
parseRequirementSection(); parseRequirementSection();
else if (sectionIdentifier == "objects") else if (sectionIdentifier == "objects")
@ -155,6 +156,23 @@ void Problem::parseSection()
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseDomainSection()
{
m_context.parser.skipWhiteSpace();
const auto domainName = m_context.parser.parseIdentifier(isIdentifier);
if (m_domain.isDeclared() && m_domain.name() != domainName)
throw utils::ParserException(m_context.parser, "Domains do not match (\"" + m_domain.name() + "\" and \"" + domainName + "\")");
if (!m_domain.isDeclared())
m_domain.setName(domainName);
m_context.parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseRequirementSection() void Problem::parseRequirementSection()
{ {
m_context.parser.skipWhiteSpace(); m_context.parser.skipWhiteSpace();
@ -238,7 +256,7 @@ void Problem::parseObjectSection()
// Store constants // Store constants
while (m_context.parser.currentCharacter() != ')') while (m_context.parser.currentCharacter() != ')')
{ {
//expressions::Constant::parseTypedDeclaration(m_context); expressions::Constant::parseTypedDeclaration(m_context, *this);
m_context.parser.skipWhiteSpace(); m_context.parser.skipWhiteSpace();
} }
@ -250,6 +268,14 @@ void Problem::parseObjectSection()
void Problem::checkConsistency() void Problem::checkConsistency()
{ {
// Verify that all objects have types
if (hasRequirement(Requirement::Type::Typing) || m_domain.hasRequirement(Requirement::Type::Typing))
std::for_each(m_objects.cbegin(), m_objects.cend(),
[&](const auto &constant)
{
if (constant->type() == nullptr)
throw ConsistencyException("Object \"" + constant->name() + "\" has no type");
});
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -61,11 +61,13 @@ void PrimitiveType::parseDeclaration(Context &context, Domain &domain)
auto *type = match->get(); auto *type = match->get();
type->setDirty(); type->setDirty();
type->setDeclared();
return; return;
} }
types.emplace_back(std::make_unique<PrimitiveType>(typeName)); types.emplace_back(std::make_unique<PrimitiveType>(typeName));
types.back()->setDeclared();
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -77,11 +79,6 @@ void PrimitiveType::parseTypedDeclaration(Context &context, Domain &domain)
// Parse and store type // Parse and store type
parseDeclaration(context, domain); parseDeclaration(context, domain);
auto *type = types.back().get();
// Flag type as correctly declared in the types section
type->setDeclared();
context.parser.skipWhiteSpace(); context.parser.skipWhiteSpace();
// Check for type inheritance // Check for type inheritance
@ -129,12 +126,8 @@ PrimitiveType *PrimitiveType::parseAndFindOrCreate(Context &context, Domain &dom
if (match == types.cend()) if (match == types.cend())
{ {
// Primitive type "object" is implicitly declared // If necessary, insert new primitive type but don't declare it
if (typeName != "object")
context.logger.parserWarning(context.parser, "Primitive type \"" + typeName + "\" used but never declared");
types.emplace_back(std::make_unique<expressions::PrimitiveType>(typeName)); types.emplace_back(std::make_unique<expressions::PrimitiveType>(typeName));
types.back()->setDeclared();
return types.back().get(); return types.back().get();
} }

View File

@ -32,7 +32,7 @@ void Logger::parserWarning(const Parser &parser, const std::string &text)
if (m_isPedantic) if (m_isPedantic)
throw ParserWarning(parser, text); throw ParserWarning(parser, text);
std::cerr << "Warning: " << parser.row() << ":" << parser.column() << "\t" << text << std::endl; std::cerr << "Warning: " << parser.fileName() << ":" << parser.row() << ":" << parser.column() << " " << text << std::endl;
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -27,14 +27,36 @@ Parser::Parser(std::istream &istream)
m_row{1}, m_row{1},
m_column{1}, m_column{1},
m_isCaseSensitive{true}, m_isCaseSensitive{true},
m_endOfFile{false} m_atEndOfFile{false}
{ {
std::setlocale(LC_NUMERIC, "C"); std::setlocale(LC_NUMERIC, "C");
// Dont skip whitespace // Dont skip whitespace
istream.exceptions(std::istream::badbit); istream.exceptions(std::istream::badbit);
}
checkStream(); ////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::setFileName(std::string fileName)
{
m_fileName = fileName;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Parser::fileName() const
{
return m_fileName;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::resetPosition()
{
m_row = 1;
m_column = 1;
m_atEndOfFile = false;
m_position = std::istreambuf_iterator<char>(m_istream);
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////