Checkpoint
This commit is contained in:
parent
23b2ce9362
commit
f9017da734
18 changed files with 814 additions and 412 deletions
|
@ -59,6 +59,7 @@ open class Preprocessor {
|
|||
Structure(Atom("!"), emptyList()) -> Cut()
|
||||
Atom("inf") -> Integer(Int.MAX_VALUE)
|
||||
Atom("nl") -> Nl
|
||||
Variable("_") -> AnonymousVariable.create()
|
||||
is Structure -> {
|
||||
// Preprocess the arguments first to recognize builtins
|
||||
val args = term.arguments.map { preprocess(it, nested = true) }
|
||||
|
@ -86,6 +87,10 @@ open class Preprocessor {
|
|||
Not(args[0] as Goal)
|
||||
}
|
||||
|
||||
term.functor == "==/2" -> {
|
||||
Equivalent(args[0], args[1])
|
||||
}
|
||||
|
||||
term.functor == "=\\=/2" && args.all { it is Expression } -> {
|
||||
EvaluatesToDifferent(args[0] as Expression, args[1] as Expression)
|
||||
}
|
||||
|
@ -133,7 +138,10 @@ open class Preprocessor {
|
|||
term.functor == "read/1" -> Read(args[0])
|
||||
term.functor == "initialization/1" -> Initialization(args[0] as Goal)
|
||||
|
||||
else -> term
|
||||
else -> {
|
||||
term.arguments = args
|
||||
term
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ import prolog.ast.terms.*
|
|||
open class TermsGrammar : Tokens() {
|
||||
|
||||
// Basic named terms
|
||||
protected val variable: Parser<Variable> by variableToken use { Variable(text) }
|
||||
protected val simpleAtom: Parser<Atom> by nameToken use { Atom(text) }
|
||||
protected val variable: Parser<Variable> by (variableToken or anonymousVariableToken) use { Variable(text) }
|
||||
protected val simpleAtom: Parser<Atom> by (nameToken or exclamation) use { Atom(text) }
|
||||
protected val quotedAtom: Parser<Atom> by (dummy
|
||||
or ticked
|
||||
or doubleTicked
|
||||
|
@ -85,7 +85,7 @@ open class TermsGrammar : Tokens() {
|
|||
}
|
||||
|
||||
// Level 700 - comparison operators
|
||||
protected val op700: Parser<String> by (equals or notEquals) use { text }
|
||||
protected val op700: Parser<String> by (equivalent or equals or notEquals or isOp) use { text }
|
||||
protected val term700: Parser<Term> by (term500 * optional(op700 * term500)) use {
|
||||
if (t2 == null) t1 else CompoundTerm(Atom(t2!!.t1), listOf(t1, t2!!.t2))
|
||||
}
|
||||
|
|
|
@ -8,28 +8,32 @@ import com.github.h0tk3y.betterParse.lexer.regexToken
|
|||
import com.github.h0tk3y.betterParse.lexer.token
|
||||
|
||||
abstract class Tokens : Grammar<Any>() {
|
||||
// Prolog tokens
|
||||
protected val nameToken: Token by regexToken("[a-z][a-zA-Z0-9_]*")
|
||||
protected val variableToken: Token by regexToken("[A-Z][a-zA-Z0-9_]*")
|
||||
|
||||
// Arithmetic tokens
|
||||
protected val floatToken: Token by regexToken("-?[1-9][0-9]*\\.[0-9]+")
|
||||
protected val integerToken: Token by regexToken("-?([1-9][0-9]*|0)")
|
||||
|
||||
// Special tokens
|
||||
protected val neck by literalToken(":-")
|
||||
protected val leftParenthesis: Token by literalToken("(")
|
||||
protected val rightParenthesis: Token by literalToken(")")
|
||||
protected val comma: Token by literalToken(",")
|
||||
protected val semicolon: Token by literalToken(";")
|
||||
protected val equivalent: Token by literalToken("==")
|
||||
protected val equals: Token by literalToken("=")
|
||||
protected val notEquals: Token by literalToken("\\=")
|
||||
protected val plus: Token by literalToken("+")
|
||||
protected val minus: Token by literalToken("-")
|
||||
protected val multiply: Token by literalToken("*")
|
||||
protected val divide: Token by literalToken("/")
|
||||
protected val exclamation: Token by literalToken("!")
|
||||
protected val isOp: Token by literalToken("is")
|
||||
protected val dot by literalToken(".")
|
||||
|
||||
// Prolog tokens
|
||||
protected val nameToken: Token by regexToken("[a-z][a-zA-Z0-9_]*")
|
||||
protected val variableToken: Token by regexToken("[A-Z][a-zA-Z0-9_]*")
|
||||
protected val anonymousVariableToken: Token by literalToken("_")
|
||||
|
||||
// Arithmetic tokens
|
||||
protected val floatToken: Token by regexToken("-?[1-9][0-9]*\\.[0-9]+")
|
||||
protected val integerToken: Token by regexToken("-?([1-9][0-9]*|0)")
|
||||
|
||||
// Ignored tokens
|
||||
protected val whitespace: Token by regexToken("\\s+", ignore = true)
|
||||
protected val singleLineComment: Token by regexToken("%[^\\n]*", ignore = true)
|
||||
|
@ -41,4 +45,4 @@ abstract class Tokens : Grammar<Any>() {
|
|||
|
||||
// Helper
|
||||
protected val dummy by token { _, _ -> -1 } use { throw IllegalStateException("This parser should not be used") }
|
||||
}
|
||||
}
|
||||
|
|
17
src/prolog/ast/terms/AnonymousVariable.kt
Normal file
17
src/prolog/ast/terms/AnonymousVariable.kt
Normal file
|
@ -0,0 +1,17 @@
|
|||
package prolog.ast.terms
|
||||
|
||||
import io.Logger
|
||||
|
||||
class AnonymousVariable(id: Int) : Variable("_$id") {
|
||||
companion object {
|
||||
private var counter = 0
|
||||
fun create(): AnonymousVariable {
|
||||
val id = counter
|
||||
counter++
|
||||
Logger.debug("Creating anonymous variable: _${id}")
|
||||
return AnonymousVariable(id)
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String = "_"
|
||||
}
|
|
@ -6,7 +6,7 @@ import prolog.ast.arithmetic.Expression
|
|||
import prolog.ast.arithmetic.Simplification
|
||||
import prolog.ast.logic.LogicOperand
|
||||
|
||||
data class Variable(val name: String) : Term, Body, Expression, LogicOperand() {
|
||||
open class Variable(val name: String) : Term, Body, Expression, LogicOperand() {
|
||||
override fun simplify(subs: Substitutions): Simplification {
|
||||
// If the variable is bound, return the value of the binding
|
||||
// If the variable is not bound, return the variable itself
|
||||
|
@ -28,5 +28,15 @@ data class Variable(val name: String) : Term, Body, Expression, LogicOperand() {
|
|||
return sequenceOf(Result.failure(IllegalArgumentException("Unbound variable: $this")))
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null || other !is Variable) return false
|
||||
return name == other.name
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return name.hashCode()
|
||||
}
|
||||
|
||||
override fun toString(): String = name
|
||||
}
|
|
@ -3,10 +3,10 @@ package prolog.builtins
|
|||
import prolog.Answers
|
||||
import prolog.Substitutions
|
||||
import prolog.ast.logic.LogicOperand
|
||||
import prolog.ast.logic.LogicOperator
|
||||
import prolog.ast.terms.Atom
|
||||
import prolog.ast.terms.Body
|
||||
import prolog.ast.terms.Goal
|
||||
import prolog.ast.logic.LogicOperator
|
||||
import prolog.flags.AppliedCut
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,12 +18,7 @@ import prolog.logic.unifyLazy
|
|||
*/
|
||||
class Write(private val term: Term) : Operator(Atom("write"), null, term), Satisfiable {
|
||||
override fun satisfy(subs: Substitutions): Answers {
|
||||
var t = term
|
||||
var temp = applySubstitution(t, subs)
|
||||
while (t != temp) {
|
||||
t = temp
|
||||
temp = applySubstitution(t, subs)
|
||||
}
|
||||
val t = applySubstitution(term, subs)
|
||||
|
||||
Terminal().say(t.toString())
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ fun succ(term1: Expression, term2: Expression, subs: Substitutions): Answers {
|
|||
it.fold(
|
||||
onSuccess = { result ->
|
||||
val t1 = applySubstitution(term1, result)
|
||||
if (t1 in result) {
|
||||
if (t1 in result || t1 in result.values) {
|
||||
val e1 = t1.simplify(result)
|
||||
if (e1.to is Integer && e1.to.value < 0) {
|
||||
return@sequence
|
||||
|
|
|
@ -13,7 +13,15 @@ import prolog.ast.arithmetic.Float
|
|||
|
||||
// Apply substitutions to a term
|
||||
fun applySubstitution(term: Term, subs: Substitutions): Term = when {
|
||||
variable(term, emptyMap()) -> subs[(term as Variable)] ?: term
|
||||
variable(term, emptyMap()) -> {
|
||||
var result = subs[(term as Variable)]
|
||||
|
||||
while (result != null && result is Variable && result in subs) {
|
||||
result = subs[result]
|
||||
}
|
||||
|
||||
result ?: term
|
||||
}
|
||||
atomic(term, subs) -> term
|
||||
compound(term, subs) -> {
|
||||
val structure = term as Structure
|
||||
|
@ -25,7 +33,7 @@ fun applySubstitution(term: Term, subs: Substitutions): Term = when {
|
|||
|
||||
//TODO Combine with the other applySubstitution function
|
||||
fun applySubstitution(expr: Expression, subs: Substitutions): Expression = when {
|
||||
variable(expr, subs) -> applySubstitution(expr as Term, subs) as Expression
|
||||
variable(expr, emptyMap()) -> applySubstitution(expr as Term, subs) as Expression
|
||||
atomic(expr, subs) -> expr
|
||||
expr is LogicOperator -> {
|
||||
expr.arguments = expr.arguments.map { applySubstitution(it, subs) }
|
||||
|
|
Reference in a new issue