diff --git a/src/aspif_text.cpp b/src/aspif_text.cpp index cebf43b..ec90c1c 100644 --- a/src/aspif_text.cpp +++ b/src/aspif_text.cpp @@ -384,9 +384,17 @@ void AspifTextOutput::rule(Head_t ht, const AtomSpan& head, Weight_t bound, cons void AspifTextOutput::minimize(Weight_t prio, const WeightLitSpan& lits) { push(Directive_t::Minimize).push(lits).push(prio); } +static bool isAtom(const StringSpan& s) { + std::size_t sz = size(s); + char first = sz > 0 ? s[0] : char(0); + if (first == '-' && sz > 1) { + first = s[1]; + } + return std::islower(static_cast(first)) || first == '_'; +} + void AspifTextOutput::output(const StringSpan& str, const LitSpan& cond) { - bool isAtom = size(str) > 0 && (std::islower(static_cast(*begin(str))) || *begin(str) == '_'); - if (size(cond) == 1 && lit(*begin(cond)) > 0 && isAtom) { + if (size(cond) == 1 && lit(*begin(cond)) > 0 && isAtom(str)) { addAtom(Potassco::atom(*begin(cond)), str); } else { @@ -462,8 +470,8 @@ void AspifTextOutput::writeDirectives() { case Directive_t::Rule: if (get() != 0) { os_ << "{"; term = "}"; } for (uint32_t n = get(); n--; sep = !*term ? "|" : ";") { printName(os_ << sep, get()); } - if (*sep) { os_ << term; sep = " :- "; } - else { os_ << ":- "; } + if (*sep || *term) { os_ << term; sep = " :- "; } + else { os_ << ":- "; } term = "."; switch (uint32_t bt = get()) { case Body_t::Normal: diff --git a/tests/test_text.cpp b/tests/test_text.cpp index 38b7300..16dca4d 100644 --- a/tests/test_text.cpp +++ b/tests/test_text.cpp @@ -209,6 +209,11 @@ TEST_CASE("Text writer ", "[text]") { read(prg, input); REQUIRE(output.str() == "{foo;x_2}.\n"); } + SECTION("empty choice") { + input << "{}."; + read(prg, input); + REQUIRE(output.str() == "{}.\n"); + } SECTION("integrity constraint") { input << ":- x1,x2.\n#output foo : x1."; read(prg, input); @@ -219,6 +224,27 @@ TEST_CASE("Text writer ", "[text]") { read(prg, input); REQUIRE(output.str() == ":- .\n"); } + SECTION("classical negation") { + Atom_t head(1); + Lit_t cond(1); + out.beginStep(); + out.rule(Head_t::Choice, toSpan(&head, 1), {}); + out.output(toSpan("-a"), toSpan(&cond, 1)); + out.output(toSpan("-8"), toSpan(&cond, 1)); + out.endStep(); + REQUIRE(output.str() == "{-a}.\n#show -8 : -a.\n"); + } + SECTION("classical negation tricky") { + std::vector head{1,2}; + Lit_t cond1(1); + Lit_t cond2(2); + out.beginStep(); + out.rule(Head_t::Choice, toSpan(head), {}); + out.output(toSpan("-a"), toSpan(&cond1, 1)); + out.output(toSpan("x_1"), toSpan(&cond2, 1)); + out.endStep(); + REQUIRE(output.str() == "{-a;x_1}.\n"); + } SECTION("basic rule") { input << "x1 :- x2, not x3, x4.\n#output foo : x1.\n#output bar : x3."; read(prg, input);