Preprocessing
This commit is contained in:
parent
82a8fccf87
commit
174855d7a3
5 changed files with 284 additions and 7 deletions
|
@ -1,4 +1,93 @@
|
|||
package interpreter
|
||||
|
||||
class Preprocessor {
|
||||
import io.Logger
|
||||
import prolog.ast.logic.Clause
|
||||
import prolog.ast.logic.Fact
|
||||
import prolog.ast.logic.LogicOperand
|
||||
import prolog.ast.logic.Rule
|
||||
import prolog.ast.terms.Atom
|
||||
import prolog.ast.terms.Body
|
||||
import prolog.ast.terms.Goal
|
||||
import prolog.ast.terms.Head
|
||||
import prolog.ast.terms.Structure
|
||||
import prolog.ast.terms.Term
|
||||
import prolog.builtins.Conjunction
|
||||
import prolog.builtins.Cut
|
||||
import prolog.builtins.Disjunction
|
||||
import prolog.builtins.Fail
|
||||
import prolog.builtins.False
|
||||
import prolog.builtins.Not
|
||||
import prolog.builtins.Query
|
||||
import prolog.builtins.True
|
||||
|
||||
/**
|
||||
* Preprocessor for Prolog
|
||||
*
|
||||
* This class preprocesses Prolog code and applies various transformations such as recognizing builtins.
|
||||
*/
|
||||
open class Preprocessor {
|
||||
/**
|
||||
* Preprocesses the input Prolog code.
|
||||
*
|
||||
* @param input The already parsed Prolog code as a list of clauses.
|
||||
* @return The preprocessed Prolog code as a list of clauses.
|
||||
*/
|
||||
fun preprocess(input: List<Clause>): List<Clause> {
|
||||
return input.map { preprocess(it) }
|
||||
}
|
||||
|
||||
fun preprocess(input: Query): Query {
|
||||
return Query(preprocess(input.query) as Goal)
|
||||
}
|
||||
|
||||
private fun preprocess(clause: Clause): Clause {
|
||||
return when (clause) {
|
||||
is Fact -> {
|
||||
Fact(preprocess(clause.head) as Head)
|
||||
}
|
||||
is Rule -> {
|
||||
Rule(
|
||||
preprocess(clause.head) as Head,
|
||||
preprocess(clause.body as Term) as Body
|
||||
)
|
||||
}
|
||||
else -> clause
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun preprocess(term: Term): Term {
|
||||
val prepped = when (term) {
|
||||
Atom("true") -> True
|
||||
Structure(Atom("true"), emptyList()) -> True
|
||||
Atom("false") -> False
|
||||
Structure(Atom("false"), emptyList()) -> False
|
||||
Atom("fail") -> Fail
|
||||
Structure(Atom("fail"), emptyList()) -> Fail
|
||||
Atom("!") -> Cut()
|
||||
Structure(Atom("!"), emptyList()) -> Cut()
|
||||
else -> {
|
||||
when {
|
||||
term is Structure && term.functor == ",/2" -> {
|
||||
val args = term.arguments.map { preprocess(it) }
|
||||
Conjunction(args[0] as LogicOperand, args[1] as LogicOperand)
|
||||
}
|
||||
term is Structure && term.functor == ";/2" -> {
|
||||
val args = term.arguments.map { preprocess(it) }
|
||||
Disjunction(args[0] as LogicOperand, args[1] as LogicOperand)
|
||||
}
|
||||
term is Structure && term.functor == "\\+/1" -> {
|
||||
val args = term.arguments.map { preprocess(it) }
|
||||
Not(args[0] as Goal)
|
||||
}
|
||||
else -> term
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (prepped != term || prepped::class != term::class) {
|
||||
Logger.debug("Preprocessed term: $term -> $prepped (${prepped::class})")
|
||||
}
|
||||
|
||||
return prepped
|
||||
}
|
||||
}
|
|
@ -152,8 +152,8 @@ class Between(private val expr1: Expression, private val expr2: Expression, priv
|
|||
|
||||
require(e1.to is Integer && e2.to is Integer) { "Arguments must be integers" }
|
||||
|
||||
val v1 = e1.to as Integer
|
||||
val v2 = e2.to as Integer
|
||||
val v1 = e1.to
|
||||
val v2 = e2.to
|
||||
|
||||
return if (variable(e3.to, subs)) {
|
||||
between(v1, v2, e3.to as Variable).map { answer ->
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package repl
|
||||
|
||||
import interpreter.Preprocessor
|
||||
import io.Logger
|
||||
import io.Terminal
|
||||
import parser.ReplParser
|
||||
|
@ -9,6 +10,7 @@ import prolog.Answers
|
|||
class Repl {
|
||||
private val io = Terminal()
|
||||
private val parser = ReplParser()
|
||||
private val preprocessor = Preprocessor()
|
||||
|
||||
fun start() {
|
||||
io.say("Prolog REPL. Type '^D' to quit.\n")
|
||||
|
@ -23,7 +25,8 @@ class Repl {
|
|||
|
||||
fun query(): Answers {
|
||||
val queryString = io.prompt("?-", { "" })
|
||||
val query = parser.parse(queryString)
|
||||
val simpleQuery = parser.parse(queryString)
|
||||
val query = preprocessor.preprocess(simpleQuery)
|
||||
return query.satisfy(emptyMap())
|
||||
}
|
||||
|
||||
|
@ -46,7 +49,10 @@ class Repl {
|
|||
}
|
||||
|
||||
when (command) {
|
||||
";" -> previous = iterator.next()
|
||||
";" -> {
|
||||
previous = iterator.next()
|
||||
io.say(prettyPrint(previous))
|
||||
}
|
||||
"a" -> return
|
||||
"." -> return
|
||||
"h" -> {
|
||||
|
@ -55,8 +61,6 @@ class Repl {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
io.say(prettyPrint(previous))
|
||||
}
|
||||
|
||||
io.say("\n")
|
||||
|
|
Reference in a new issue