Started parsing in a two-pass approach.

This commit is contained in:
Patrick Lühne 2016-06-08 00:34:59 +02:00
parent ee9626e4d2
commit 31fb8ba79b
3 changed files with 60 additions and 44 deletions

View File

@ -31,14 +31,16 @@ class Description
Description(); Description();
void parseContent(); void parseContent();
void parseSection(); void findSections();
void checkConsistency(); void checkConsistency();
utils::Parser m_parser; utils::Parser m_parser;
Context m_context; Context m_context;
utils::Parser::Position m_domainPosition;
std::unique_ptr<Domain> m_domain; std::unique_ptr<Domain> m_domain;
utils::Parser::Position m_problemPosition;
std::unique_ptr<Problem> m_problem; std::unique_ptr<Problem> m_problem;
}; };

View File

@ -5,6 +5,7 @@
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <plasp/pddl/IO.h>
#include <plasp/utils/ParserException.h> #include <plasp/utils/ParserException.h>
namespace plasp namespace plasp
@ -20,7 +21,9 @@ namespace pddl
Description::Description() Description::Description()
: m_context(m_parser), : m_context(m_parser),
m_domainPosition{-1},
m_domain{std::make_unique<Domain>(Domain(m_context))}, m_domain{std::make_unique<Domain>(Domain(m_context))},
m_problemPosition{-1},
m_problem{std::make_unique<Problem>(Problem(m_context, *m_domain))} m_problem{std::make_unique<Problem>(Problem(m_context, *m_domain))}
{ {
m_parser.setCaseSensitive(false); m_parser.setCaseSensitive(false);
@ -72,6 +75,26 @@ const Domain &Description::domain() const
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parseContent() void Description::parseContent()
{
// First, determine the locations of domain and problem
findSections();
if (m_domainPosition == -1)
throw ConsistencyException("No PDDL domain specified");
m_context.parser.seek(m_domainPosition);
m_domain->readPDDL();
if (m_problemPosition != -1)
{
m_context.parser.seek(m_problemPosition);
m_problem->readPDDL();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::findSections()
{ {
while (true) while (true)
{ {
@ -80,57 +103,43 @@ void Description::parseContent()
if (m_context.parser.atEndOfStream()) if (m_context.parser.atEndOfStream())
return; return;
const auto position = m_context.parser.position();
m_context.parser.expect<std::string>("("); m_context.parser.expect<std::string>("(");
m_context.parser.expect<std::string>("define"); m_context.parser.expect<std::string>("define");
parseSection();
m_context.parser.expect<std::string>(")");
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parseSection()
{
// Parse domain/problem identifier
m_context.parser.expect<std::string>("("); m_context.parser.expect<std::string>("(");
const auto sectionIdentifier = m_context.parser.parse<std::string>(); if (m_context.parser.probe<std::string>("domain"))
if (sectionIdentifier == "domain")
{ {
BOOST_ASSERT(m_domain); std::cout << "Found domain at " << position << std::endl;
if (m_domain->isDeclared()) if (m_domainPosition != -1)
throw utils::ParserException(m_context.parser, "PDDL description may not contain two domains"); throw utils::ParserException(m_context.parser, "PDDL description may not contain two domains");
m_domain->readPDDL(); m_domainPosition = position;
} }
else if (sectionIdentifier == "problem") else if (m_context.parser.probe<std::string>("problem"))
{ {
BOOST_ASSERT(m_problem); if (m_problemPosition != -1)
if (m_problem->isDeclared())
throw utils::ParserException(m_context.parser, "PDDL description may currently not contain two problems"); throw utils::ParserException(m_context.parser, "PDDL description may currently not contain two problems");
m_problem->readPDDL(); m_problemPosition = position;
} }
else else
{
const auto sectionIdentifier = m_context.parser.parse<std::string>();
throw utils::ParserException(m_context.parser, "Unknown PDDL section \"" + sectionIdentifier + "\""); throw utils::ParserException(m_context.parser, "Unknown PDDL section \"" + sectionIdentifier + "\"");
} }
skipSection(m_context.parser);
skipSection(m_context.parser);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::checkConsistency() void Description::checkConsistency()
{ {
if (!m_domain->isDeclared())
throw ConsistencyException("No PDDL domain specified");
if (m_problem->hasRequirement(Requirement::Type::Typing)
&& !m_domain->hasRequirement(Requirement::Type::Typing))
{
throw ConsistencyException("PDDL problems may not add the \"typing\" requirement");
}
m_domain->checkConsistency(); m_domain->checkConsistency();
m_problem->checkConsistency(); m_problem->checkConsistency();
} }

View File

@ -33,6 +33,11 @@ Domain::Domain(Context &context)
void Domain::readPDDL() void Domain::readPDDL()
{ {
m_context.parser.expect<std::string>("(");
m_context.parser.expect<std::string>("define");
m_context.parser.expect<std::string>("(");
m_context.parser.expect<std::string>("domain");
const auto domainName = m_context.parser.parseIdentifier(isIdentifier); const auto domainName = m_context.parser.parseIdentifier(isIdentifier);
if (m_name.empty()) if (m_name.empty())
@ -49,7 +54,7 @@ void Domain::readPDDL()
{ {
m_context.parser.skipWhiteSpace(); m_context.parser.skipWhiteSpace();
if (m_context.parser.currentCharacter() == ')') if (m_context.parser.probe(')'))
break; break;
parseSection(); parseSection();