package better_parser import com.github.h0tk3y.betterParse.grammar.Grammar import com.github.h0tk3y.betterParse.grammar.parseToEnd import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource import prolog.ast.logic.Clause import prolog.ast.logic.Fact import prolog.ast.logic.Rule import prolog.ast.terms.CompoundTerm import prolog.ast.terms.Structure import prolog.ast.terms.Variable import prolog.builtins.Conjunction import prolog.builtins.Disjunction class SimpleSourcePrologParserTests { private lateinit var parser: Grammar> @BeforeEach fun setup() { parser = SimpleSourceParser() as Grammar> } @ParameterizedTest @ValueSource(strings = [ "john.", "mary.", "jimmy.", "male(john).", "male(jimmy).", "female(mary).", "not(not(true)).", "not(a, not(b, c), d, not(not(a)))." ]) fun `parse simple fact`(input: String) { val result = parser.parseToEnd(input) assertEquals(1, result.size, "Expected 1 fact") assertTrue(result[0] is Fact, "Expected a fact") assertEquals(input, "${result[0].toString()}.", "Expected fact to be '$input'") } @ParameterizedTest @ValueSource(strings = [ "john. mary.", "likes(john, mary). likes(mary, john).", "belgium. capital(belgium, brussels).", "plus(1, 2, 3). plus(3, 4, 7).", ]) fun `parse multiple facts`(input: String) { val result = parser.parseToEnd(input) assertEquals(2, result.size, "Expected 2 facts") assertTrue(result[0] is Fact, "Expected a fact") assertTrue(result[1] is Fact, "Expected a fact") } @Test fun `simplest rule`() { val input = "a :- b." val result = parser.parseToEnd(input) assertEquals(1, result.size, "Expected 1 rule") assertTrue(result[0] is Rule, "Expected a rule") assertEquals("a :- b", result[0].toString()) } @ParameterizedTest @ValueSource(strings = [ "parent(X, Y) :- father(X, Y).", "parent(X, Y) :- mother(X, Y)." ]) fun `parse simple rule`(input: String) { val result = parser.parseToEnd(input) assertEquals(1, result.size, "Expected 1 rule") assertTrue(result[0] is Rule, "Expected a rule") } @Test fun `parse rule with very verbose checks`() { val input = "parent(X, Y) :- father(X, Y)." val result = parser.parseToEnd(input) assertEquals(1, result.size, "Expected 1 rule") assertTrue(result[0] is Rule, "Expected a rule") val rule = result[0] as Rule assertTrue(rule.head is Structure, "Expected head to be a structure") val head = rule.head as Structure assertEquals("parent/2", head.functor, "Expected functor 'parent/2'") assertEquals(Variable("X"), head.arguments[0], "Expected first argument 'X'") assertEquals(Variable("Y"), head.arguments[1], "Expected second argument 'Y'") assertTrue(rule.body is Structure, "Expected body to be a structure") val body = rule.body as Structure assertEquals("father/2", body.functor, "Expected functor 'father/2'") assertEquals(Variable("X"), body.arguments[0], "Expected first argument 'X'") assertEquals(Variable("Y"), body.arguments[1], "Expected second argument 'Y'") } @Test fun `parse rule with conjunction`() { val input = "father(X, Y) :- parent(X, Y), male(X)." val result = parser.parseToEnd(input) assertEquals(1, result.size, "Expected 1 rule") assertInstanceOf(Rule::class.java, result[0], "Expected a rule") val rule = result[0] as Rule assertInstanceOf(Conjunction::class.java, rule.body, "Expected body to be a conjunction") } @Test fun `parse rule with nested conjunction`() { val input = "guest(X, Y) :- invited(Y, X), has_time(X), not(sick(Y))." val result = parser.parseToEnd(input) assertEquals(1, result.size, "Expected 1 rule") val rule = result[0] as Rule assertTrue(rule.body is Conjunction, "Expected body to be a conjunction") val conjunction = rule.body as Conjunction assertEquals("invited/2", (conjunction.left as CompoundTerm).functor, "Expected functor 'invited/2'") } }