Implemented two-pass parsing for PDDL problems.

This commit is contained in:
Patrick Lühne 2016-06-09 14:39:03 +02:00
parent fb15a131ac
commit 87889f5efe
5 changed files with 175 additions and 112 deletions

View File

@ -61,8 +61,6 @@ int main(int argc, char **argv)
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
try
{
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);
@ -102,13 +100,6 @@ int main(int argc, char **argv)
//std::cout << pddlDescription << std::endl; //std::cout << pddlDescription << std::endl;
} }
}
catch (const std::exception &e)
{
std::cerr << "Error: " << e.what() << std::endl << std::endl;
printHelp();
return EXIT_FAILURE;
}
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -22,10 +22,9 @@ class Problem
public: public:
Problem(Context &context, Domain &domain); Problem(Context &context, Domain &domain);
void findSections();
void parse(); void parse();
bool isDeclared() const;
Domain &domain(); Domain &domain();
const Domain &domain() const; const Domain &domain() const;
@ -44,8 +43,6 @@ class Problem
void checkConsistency(); void checkConsistency();
private: private:
void parseSection();
void parseRequirementSection(); void parseRequirementSection();
void computeDerivedRequirements(); void computeDerivedRequirements();
@ -57,13 +54,18 @@ class Problem
Context &m_context; Context &m_context;
Domain &m_domain; Domain &m_domain;
bool m_isDeclared;
std::string m_name; std::string m_name;
utils::Parser::Position m_domainPosition;
utils::Parser::Position m_requirementsPosition;
Requirements m_requirements; Requirements m_requirements;
utils::Parser::Position m_objectsPosition;
expressions::Constants m_objects; expressions::Constants m_objects;
utils::Parser::Position m_initialStatePosition;
std::unique_ptr<InitialState> m_initialState; std::unique_ptr<InitialState> m_initialState;
}; };

View File

@ -148,8 +148,8 @@ void Description::findSections()
m_problemPosition = position; m_problemPosition = position;
skipSection(parser); parser.seek(position);
skipSection(parser); m_problem->findSections();
} }
else else
{ {

View File

@ -69,6 +69,8 @@ void Domain::findSections()
parser.expect<std::string>("("); parser.expect<std::string>("(");
parser.expect<std::string>(":"); parser.expect<std::string>(":");
const auto sectionIdentifierPosition = parser.position();
// Save the parser position of the individual sections for later parsing // Save the parser position of the individual sections for later parsing
if (parser.probe<std::string>("requirements")) if (parser.probe<std::string>("requirements"))
setSectionPosition("requirements", m_requirementsPosition, position, true); setSectionPosition("requirements", m_requirementsPosition, position, true);
@ -88,9 +90,13 @@ void Domain::findSections()
|| parser.probe<std::string>("durative-action") || parser.probe<std::string>("durative-action")
|| parser.probe<std::string>("derived")) || parser.probe<std::string>("derived"))
{ {
parser.seek(position); parser.seek(sectionIdentifierPosition);
m_context.logger.parserWarning(parser, "Section type currently unsupported");
parser.advance(); const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
m_context.logger.parserWarning(parser, "Section type \"" + sectionIdentifier + "\" currently unsupported");
parser.seek(sectionIdentifierPosition);
} }
else else
{ {

View File

@ -23,45 +23,118 @@ namespace pddl
Problem::Problem(Context &context, Domain &domain) Problem::Problem(Context &context, Domain &domain)
: m_context(context), : m_context(context),
m_domain(domain), m_domain(domain),
m_isDeclared{false} m_domainPosition{-1},
m_requirementsPosition{-1},
m_objectsPosition{-1},
m_initialStatePosition{-1}
{ {
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::findSections()
{
auto &parser = m_context.parser;
parser.expect<std::string>("(");
parser.expect<std::string>("define");
parser.expect<std::string>("(");
parser.expect<std::string>("problem");
m_name = parser.parseIdentifier(isIdentifier);
std::cout << "Found problem " << m_name << std::endl;
parser.expect<std::string>(")");
const auto setSectionPosition =
[&](const std::string &sectionName, auto &sectionPosition, const auto value, bool unique = false)
{
if (unique && sectionPosition != -1)
throw utils::ParserException(parser, "Only one \":" + sectionName + "\" section allowed");
sectionPosition = value;
};
parser.skipWhiteSpace();
while (parser.currentCharacter() != ')')
{
const auto position = parser.position();
parser.expect<std::string>("(");
parser.expect<std::string>(":");
const auto sectionIdentifierPosition = parser.position();
// TODO: check order of the sections
if (parser.probe<std::string>("domain"))
setSectionPosition("domain", m_domainPosition, position, true);
else if (parser.probe<std::string>("requirements"))
setSectionPosition("requirements", m_requirementsPosition, position, true);
else if (parser.probe<std::string>("objects"))
setSectionPosition("objects", m_objectsPosition, position, true);
else if (parser.probe<std::string>("init"))
setSectionPosition("init", m_initialStatePosition, position, true);
else if (parser.probe<std::string>("goal")
|| parser.probe<std::string>("constraints")
|| parser.probe<std::string>("metric")
|| parser.probe<std::string>("length"))
{
parser.seek(sectionIdentifierPosition);
const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
m_context.logger.parserWarning(parser, "Section type \"" + sectionIdentifier + "\" currently unsupported");
parser.seek(sectionIdentifierPosition);
}
else
{
const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
throw utils::ParserException(m_context.parser, "Unknown problem section \"" + sectionIdentifier + "\"");
}
// Skip section for now and parse it later
skipSection(parser);
parser.skipWhiteSpace();
}
parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parse() void Problem::parse()
{ {
m_context.parser.expect<std::string>("("); auto &parser = m_context.parser;
m_context.parser.expect<std::string>("define");
m_context.parser.expect<std::string>("(");
m_context.parser.expect<std::string>("problem");
m_name = m_context.parser.parseIdentifier(isIdentifier); if (m_domainPosition == -1)
throw ConsistencyException("Problem description does not specify the corresponding domain");
std::cout << "Parsing problem " << m_name << std::endl; parser.seek(m_domainPosition);
parseDomainSection();
m_context.parser.expect<std::string>(")"); if (m_requirementsPosition != -1)
while (true)
{ {
m_context.parser.skipWhiteSpace(); parser.seek(m_requirementsPosition);
parseRequirementSection();
if (m_context.parser.currentCharacter() == ')')
break;
parseSection();
} }
computeDerivedRequirements(); if (m_objectsPosition != -1)
{
parser.seek(m_objectsPosition);
parseObjectSection();
}
m_isDeclared = true; if (m_initialStatePosition == -1)
} throw ConsistencyException("Problem description does not specify an initial state");
//////////////////////////////////////////////////////////////////////////////////////////////////// parser.seek(m_initialStatePosition);
parseInitialStateSection();
bool Problem::isDeclared() const
{
return m_isDeclared;
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -108,64 +181,43 @@ const expressions::Constants &Problem::objects() const
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseSection() void Problem::parseDomainSection()
{ {
auto &parser = m_context.parser; auto &parser = m_context.parser;
parser.expect<std::string>("("); parser.expect<std::string>("(");
parser.expect<std::string>(":"); parser.expect<std::string>(":");
parser.expect<std::string>("domain");
// TODO: check order of the sections parser.skipWhiteSpace();
if (parser.probe<std::string>("domain"))
parseDomainSection();
else if (parser.probe<std::string>("requirements"))
parseRequirementSection();
else if (parser.probe<std::string>("objects"))
parseObjectSection();
else if (parser.probe<std::string>("init"))
parseInitialStateSection();
else if (parser.probe<std::string>("goal")
|| parser.probe<std::string>("constraints")
|| parser.probe<std::string>("metric")
|| parser.probe<std::string>("length"))
{
std::cout << "Skipping section" << std::endl;
skipSection(m_context.parser);
}
else
{
const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
throw utils::ParserException(m_context.parser, "Unknown problem section \"" + sectionIdentifier + "\"");
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////// const auto domainName = parser.parseIdentifier(isIdentifier);
void Problem::parseDomainSection()
{
m_context.parser.skipWhiteSpace();
const auto domainName = m_context.parser.parseIdentifier(isIdentifier);
if (m_domain.name() != domainName) if (m_domain.name() != domainName)
throw utils::ParserException(m_context.parser, "Domains do not match (\"" + m_domain.name() + "\" and \"" + domainName + "\")"); throw utils::ParserException(parser, "Domains do not match (\"" + m_domain.name() + "\" and \"" + domainName + "\")");
m_context.parser.expect<std::string>(")"); parser.expect<std::string>(")");
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseRequirementSection() void Problem::parseRequirementSection()
{ {
m_context.parser.skipWhiteSpace(); auto &parser = m_context.parser;
while (m_context.parser.currentCharacter() != ')') parser.expect<std::string>("(");
parser.expect<std::string>(":");
parser.expect<std::string>("requirements");
parser.skipWhiteSpace();
while (parser.currentCharacter() != ')')
{ {
m_context.parser.expect<std::string>(":"); parser.expect<std::string>(":");
m_requirements.emplace_back(Requirement::parse(m_context)); m_requirements.emplace_back(Requirement::parse(m_context));
m_context.parser.skipWhiteSpace(); parser.skipWhiteSpace();
} }
// TODO: do this check only once the domain is parsed // TODO: do this check only once the domain is parsed
@ -173,7 +225,7 @@ void Problem::parseRequirementSection()
if (m_requirements.empty()) if (m_requirements.empty())
m_requirements.emplace_back(Requirement::Type::STRIPS); m_requirements.emplace_back(Requirement::Type::STRIPS);
m_context.parser.expect<std::string>(")"); parser.expect<std::string>(")");
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -246,21 +298,33 @@ void Problem::computeDerivedRequirements()
void Problem::parseObjectSection() void Problem::parseObjectSection()
{ {
m_context.parser.skipWhiteSpace(); auto &parser = m_context.parser;
parser.expect<std::string>("(");
parser.expect<std::string>(":");
parser.expect<std::string>("objects");
parser.skipWhiteSpace();
// Store constants // Store constants
expressions::Constant::parseTypedDeclarations(m_context, *this); expressions::Constant::parseTypedDeclarations(m_context, *this);
m_context.parser.expect<std::string>(")"); parser.expect<std::string>(")");
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseInitialStateSection() void Problem::parseInitialStateSection()
{ {
auto &parser = m_context.parser;
parser.expect<std::string>("(");
parser.expect<std::string>(":");
parser.expect<std::string>("init");
m_initialState = InitialState::parseDeclaration(m_context, *this); m_initialState = InitialState::parseDeclaration(m_context, *this);
m_context.parser.expect<std::string>(")"); parser.expect<std::string>(")");
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////