Skip to content

Commit

Permalink
refactor error handling part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
drexlerd committed Apr 23, 2024
1 parent e714ffc commit eca676e
Show file tree
Hide file tree
Showing 12 changed files with 295 additions and 206 deletions.
1 change: 1 addition & 0 deletions src/pddl/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "loki/details/pddl/type.hpp"
#include "parser/common.hpp"
#include "parser/constants.hpp"
#include "parser/error_handling.hpp"
#include "parser/functions.hpp"
#include "parser/goal.hpp"
#include "parser/initial.hpp"
Expand Down
44 changes: 6 additions & 38 deletions src/pddl/parser/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "common.hpp"

#include "error_handling.hpp"
#include "loki/details/pddl/exceptions.hpp"

using namespace std;
Expand All @@ -31,9 +32,7 @@ string parse(const ast::Name& node) { return node.characters; }
Variable parse(const ast::Variable& node, Context& context)
{
const auto variable = context.factories.get_or_create_variable(node.characters);
// Declare variable as being referenced.
context.references.untrack(variable);
// Add position of PDDL object
context.positions.push_back(variable, node);
return variable;
}
Expand All @@ -44,39 +43,21 @@ TermDeclarationTermVisitor::TermDeclarationTermVisitor(Context& context_) : cont
Term TermDeclarationTermVisitor::operator()(const ast::Name& node) const
{
const auto constant_name = parse(node);
// Test for undefined constant.
const auto binding = context.scopes.top().get_object(constant_name);
if (!binding.has_value())
{
throw UndefinedConstantError(constant_name, context.scopes.top().get_error_handler()(node, ""));
}
test_undefined_constant(constant_name, node, context);
// Constant are not tracked and hence must not be untracked.
// Construct Term and return it
const auto binding = context.scopes.top().get_object(constant_name);
const auto [constant, _position, _error_handler] = binding.value();
const auto term = context.factories.get_or_create_term_object(constant);
// Add position of PDDL object
context.positions.push_back(term, node);
return term;
}

Term TermDeclarationTermVisitor::operator()(const ast::Variable& node) const
{
const auto variable = parse(node, context);
// Test for multiple definition
const auto binding = context.scopes.top().get_variable(variable->get_name());
if (binding.has_value())
{
const auto message_1 = context.scopes.top().get_error_handler()(node, "Defined here:");
const auto [_constant, position, error_handler] = binding.value();
assert(position.has_value());
const auto message_2 = error_handler(position.value(), "First defined here:");
throw MultiDefinitionVariableError(variable->get_name(), message_1 + message_2);
}
// Add binding to scope
test_multiple_definition_variable(variable, node, context);
context.scopes.top().insert_variable(variable->get_name(), variable, node);
// Construct Term and return it
const auto term = context.factories.get_or_create_term_variable(variable);
// Add position of PDDL object
context.positions.push_back(term, node);
return term;
}
Expand All @@ -86,33 +67,20 @@ TermReferenceTermVisitor::TermReferenceTermVisitor(Context& context_) : context(
Term TermReferenceTermVisitor::operator()(const ast::Name& node) const
{
const auto object_name = parse(node);
// Test for undefined constant.
test_undefined_constant(object_name, node, context);
const auto binding = context.scopes.top().get_object(object_name);
if (!binding.has_value())
{
throw UndefinedConstantError(object_name, context.scopes.top().get_error_handler()(node, ""));
}
// Construct Term and return it
const auto [object, _position, _error_handler] = binding.value();
context.references.untrack(object);
const auto term = context.factories.get_or_create_term_object(object);
// Add position of PDDL object
context.positions.push_back(term, node);
return term;
}

Term TermReferenceTermVisitor::operator()(const ast::Variable& node) const
{
const auto variable = parse(node, context);
// Test for undefined variable
const auto binding = context.scopes.top().get_variable(variable->get_name());
if (!binding.has_value())
{
throw UndefinedVariableError(variable->get_name(), context.scopes.top().get_error_handler()(node, ""));
}
// Construct Term and return it
test_undefined_variable(variable, node, context);
const auto term = context.factories.get_or_create_term_variable(variable);
// Add position of PDDL object
context.positions.push_back(term, node);
return term;
}
Expand Down
46 changes: 10 additions & 36 deletions src/pddl/parser/conditions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "conditions.hpp"

#include "error_handling.hpp"
#include "literal.hpp"
#include "loki/details/pddl/exceptions.hpp"
#include "parameters.hpp"
Expand Down Expand Up @@ -48,10 +49,7 @@ Condition parse(const ast::GoalDescriptorAtom& node, Context& context)
Condition parse(const ast::GoalDescriptorLiteral& node, Context& context)
{
// requires :negative-preconditions
if (!context.requirements->test(RequirementEnum::NEGATIVE_PRECONDITIONS))
{
throw UndefinedRequirementError(RequirementEnum::NEGATIVE_PRECONDITIONS, context.scopes.top().get_error_handler()(node, ""));
}
test_undefined_requirement(RequirementEnum::NEGATIVE_PRECONDITIONS, node, context);
context.references.untrack(RequirementEnum::NEGATIVE_PRECONDITIONS);
const auto condition = context.factories.get_or_create_condition_literal(parse(node.literal, context));
context.positions.push_back(condition, node);
Expand All @@ -69,10 +67,7 @@ Condition parse(const ast::GoalDescriptorAnd& node, Context& context)
Condition parse(const ast::GoalDescriptorOr& node, Context& context)
{
// requires :disjunctive-preconditions
if (!context.requirements->test(RequirementEnum::DISJUNCTIVE_PRECONDITIONS))
{
throw UndefinedRequirementError(RequirementEnum::DISJUNCTIVE_PRECONDITIONS, context.scopes.top().get_error_handler()(node, ""));
}
test_undefined_requirement(RequirementEnum::DISJUNCTIVE_PRECONDITIONS, node, context);
context.references.untrack(RequirementEnum::DISJUNCTIVE_PRECONDITIONS);
auto condition_list = parse(node.goal_descriptors, context);
const auto condition = context.factories.get_or_create_condition_or(condition_list);
Expand All @@ -83,10 +78,7 @@ Condition parse(const ast::GoalDescriptorOr& node, Context& context)
Condition parse(const ast::GoalDescriptorNot& node, Context& context)
{
// requires :disjunctive-preconditions
if (!context.requirements->test(RequirementEnum::NEGATIVE_PRECONDITIONS))
{
throw UndefinedRequirementError(RequirementEnum::NEGATIVE_PRECONDITIONS, context.scopes.top().get_error_handler()(node, ""));
}
test_undefined_requirement(RequirementEnum::NEGATIVE_PRECONDITIONS, node, context);
context.references.untrack(RequirementEnum::NEGATIVE_PRECONDITIONS);
auto child_condition = parse(node.goal_descriptor, context);
const auto condition = context.factories.get_or_create_condition_not(child_condition);
Expand All @@ -96,10 +88,7 @@ Condition parse(const ast::GoalDescriptorNot& node, Context& context)

Condition parse(const ast::GoalDescriptorImply& node, Context& context)
{
if (!context.requirements->test(RequirementEnum::DISJUNCTIVE_PRECONDITIONS))
{
throw UndefinedRequirementError(RequirementEnum::DISJUNCTIVE_PRECONDITIONS, context.scopes.top().get_error_handler()(node, ""));
}
test_undefined_requirement(RequirementEnum::DISJUNCTIVE_PRECONDITIONS, node, context);
context.references.untrack(RequirementEnum::DISJUNCTIVE_PRECONDITIONS);
auto condition_left = parse(node.goal_descriptor_left, context);
auto condition_right = parse(node.goal_descriptor_right, context);
Expand All @@ -110,10 +99,7 @@ Condition parse(const ast::GoalDescriptorImply& node, Context& context)

Condition parse(const ast::GoalDescriptorExists& node, Context& context)
{
if (!context.requirements->test(RequirementEnum::EXISTENTIAL_PRECONDITIONS))
{
throw UndefinedRequirementError(RequirementEnum::EXISTENTIAL_PRECONDITIONS, context.scopes.top().get_error_handler()(node, ""));
}
test_undefined_requirement(RequirementEnum::EXISTENTIAL_PRECONDITIONS, node, context);
context.references.untrack(RequirementEnum::EXISTENTIAL_PRECONDITIONS);
context.scopes.open_scope();
auto parameter_list = boost::apply_visitor(ParameterListVisitor(context), node.typed_list_of_variables);
Expand Down Expand Up @@ -142,10 +128,7 @@ Condition parse_condition_forall(const ast::TypedListOfVariables& parameters_nod

Condition parse(const ast::GoalDescriptorForall& node, Context& context)
{
if (!context.requirements->test(RequirementEnum::UNIVERSAL_PRECONDITIONS))
{
throw UndefinedRequirementError(RequirementEnum::UNIVERSAL_PRECONDITIONS, context.scopes.top().get_error_handler()(node, ""));
}
test_undefined_requirement(RequirementEnum::UNIVERSAL_PRECONDITIONS, node, context);
context.references.untrack(RequirementEnum::UNIVERSAL_PRECONDITIONS);
return parse_condition_forall(node.typed_list_of_variables, node.goal_descriptor, context);
}
Expand Down Expand Up @@ -175,10 +158,7 @@ Condition parse(const ast::ConstraintGoalDescriptorAnd& node, Context& context)

Condition parse(const ast::ConstraintGoalDescriptorForall& node, Context& context)
{
if (!context.requirements->test(RequirementEnum::UNIVERSAL_PRECONDITIONS))
{
throw UndefinedRequirementError(RequirementEnum::UNIVERSAL_PRECONDITIONS, context.scopes.top().get_error_handler()(node, ""));
}
test_undefined_requirement(RequirementEnum::UNIVERSAL_PRECONDITIONS, node, context);
context.references.untrack(RequirementEnum::UNIVERSAL_PRECONDITIONS);
return parse_condition_forall(node.typed_list_of_variables, node.constraint_goal_descriptor, context);
}
Expand Down Expand Up @@ -251,19 +231,13 @@ Condition parse(const ast::PreconditionGoalDescriptorAnd& node, Context& context

Condition parse(const ast::PreconditionGoalDescriptorPreference& node, Context& context)
{
if (!context.requirements->test(RequirementEnum::PREFERENCES))
{
throw UndefinedRequirementError(RequirementEnum::PREFERENCES, context.scopes.top().get_error_handler()(node, ""));
}
test_undefined_requirement(RequirementEnum::PREFERENCES, node, context);
throw NotImplementedError("parse(const ast::PreconditionGoalDescriptorPreference& node, Context& context)");
}

Condition parse(const ast::PreconditionGoalDescriptorForall& node, Context& context)
{
if (!context.requirements->test(RequirementEnum::UNIVERSAL_PRECONDITIONS))
{
throw UndefinedRequirementError(RequirementEnum::UNIVERSAL_PRECONDITIONS, context.scopes.top().get_error_handler()(node, ""));
}
test_undefined_requirement(RequirementEnum::UNIVERSAL_PRECONDITIONS, node, context);
context.references.untrack(RequirementEnum::UNIVERSAL_PRECONDITIONS);
return parse_condition_forall(node.typed_list_of_variables, node.precondition_goal_descriptor, context);
}
Expand Down
24 changes: 3 additions & 21 deletions src/pddl/parser/constants.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,14 @@
#include "constants.hpp"

#include "common.hpp"
#include "error_handling.hpp"
#include "loki/details/pddl/exceptions.hpp"
#include "types.hpp"

using namespace std;

namespace loki
{
static void test_multiple_definition(const Object& constant, const ast::Name& node, const Context& context)
{
const auto constant_name = constant->get_name();
const auto binding = context.scopes.top().get_object(constant_name);
if (binding.has_value())
{
const auto message_1 = context.scopes.top().get_error_handler()(node, "Defined here:");
auto message_2 = std::string("");
const auto [_object, position, error_handler] = binding.value();
if (position.has_value())
{
message_2 = error_handler(position.value(), "First defined here:");
}
throw MultiDefinitionConstantError(constant_name, message_1 + message_2);
}
}

static void insert_context_information(const Object& constant, const ast::Name& node, Context& context)
{
Expand All @@ -51,7 +36,7 @@ static void insert_context_information(const Object& constant, const ast::Name&
static Object parse_constant_definition(const ast::Name& node, const TypeList& type_list, Context& context)
{
const auto constant = context.factories.get_or_create_object(parse(node), type_list);
test_multiple_definition(constant, node, context);
test_multiple_definition_constant(constant, node, context);
insert_context_information(constant, node, context);
return constant;
}
Expand Down Expand Up @@ -83,10 +68,7 @@ ObjectList ConstantListVisitor::operator()(const std::vector<ast::Name>& name_no

ObjectList ConstantListVisitor::operator()(const ast::TypedListOfNamesRecursively& typed_list_of_names_recursively_node)
{
if (!context.requirements->test(RequirementEnum::TYPING))
{
throw UndefinedRequirementError(RequirementEnum::TYPING, context.scopes.top().get_error_handler()(typed_list_of_names_recursively_node, ""));
}
test_undefined_requirement(RequirementEnum::TYPING, typed_list_of_names_recursively_node, context);
context.references.untrack(RequirementEnum::TYPING);
const auto type_list = boost::apply_visitor(TypeReferenceTypeVisitor(context), typed_list_of_names_recursively_node.type);
// TypedListOfNamesRecursively has user defined base types
Expand Down
22 changes: 5 additions & 17 deletions src/pddl/parser/effects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "common.hpp"
#include "conditions.hpp"
#include "error_handling.hpp"
#include "functions.hpp"
#include "literal.hpp"
#include "loki/details/pddl/exceptions.hpp"
Expand Down Expand Up @@ -80,19 +81,13 @@ Effect parse(const ast::EffectProductionLiteral& node, Context& context)

Effect parse(const ast::EffectProductionNumericFluentTotalCost& node, Context& context)
{
if (!context.requirements->test(RequirementEnum::ACTION_COSTS))
{
throw UndefinedRequirementError(RequirementEnum::ACTION_COSTS, context.scopes.top().get_error_handler()(node, ""));
}
test_undefined_requirement(RequirementEnum::ACTION_COSTS, node, context);
context.references.untrack(RequirementEnum::ACTION_COSTS);
const auto assign_operator_increase = parse(node.assign_operator_increase);
auto function_name = parse(node.function_symbol_total_cost.name);
assert(function_name == "total-cost");
test_undefined_function_skeleton(function_name, node.function_symbol_total_cost, context);
auto binding = context.scopes.top().get_function_skeleton(function_name);
if (!binding.has_value())
{
throw UndefinedFunctionSkeletonError(function_name, context.scopes.top().get_error_handler()(node.function_symbol_total_cost, ""));
}
const auto [function_skeleton, _position, _error_handler] = binding.value();
const auto function = context.factories.get_or_create_function(function_skeleton, TermList {});
context.references.untrack(function->get_function_skeleton());
Expand All @@ -104,10 +99,7 @@ Effect parse(const ast::EffectProductionNumericFluentTotalCost& node, Context& c

Effect parse(const ast::EffectProductionNumericFluentGeneral& node, Context& context)
{
if (!context.requirements->test(RequirementEnum::NUMERIC_FLUENTS))
{
throw UndefinedRequirementError(RequirementEnum::NUMERIC_FLUENTS, context.scopes.top().get_error_handler()(node, ""));
}
test_undefined_requirement(RequirementEnum::NUMERIC_FLUENTS, node, context);
context.references.untrack(RequirementEnum::NUMERIC_FLUENTS);
const auto assign_operator = parse(node.assign_operator);
const auto function = parse(node.function_head, context);
Expand Down Expand Up @@ -146,11 +138,7 @@ Effect parse(const ast::EffectConditionalWhen& node, Context& context)

Effect parse(const ast::EffectConditional& node, Context& context)
{
// requires :conditional-effects
if (!context.requirements->test(RequirementEnum::CONDITIONAL_EFFECTS))
{
throw UndefinedRequirementError(RequirementEnum::CONDITIONAL_EFFECTS, context.scopes.top().get_error_handler()(node, ""));
}
test_undefined_requirement(RequirementEnum::CONDITIONAL_EFFECTS, node, context);
context.references.untrack(RequirementEnum::CONDITIONAL_EFFECTS);
const auto effect = boost::apply_visitor(EffectVisitor(context), node);
context.positions.push_back(effect, node);
Expand Down
Loading

0 comments on commit eca676e

Please sign in to comment.