Skip to content
Snippets Groups Projects
Commit 6ebcea6a authored by Katja Goltsova's avatar Katja Goltsova Committed by Viktor Kunčak
Browse files

Kernel printer using scallion:

Add inverse functions for all parsing rules. Further simplify parsing
of binder formulas and factor out toplevel (iff, implies) connector
formulas to make printing implementation easier.
parent 35d23134
No related branches found
No related tags found
4 merge requests!62Easy tactics,!58Easy tactics,!54Front integration,!53Front integration
package lisa.utils package lisa.utils
import lisa.kernel.fol.FOL import lisa.kernel.fol.FOL
import lisa.kernel.fol.FOL._ import lisa.kernel.fol.FOL.*
import lisa.kernel.fol.FOL.equality import lisa.kernel.fol.FOL.equality
import lisa.kernel.proof.SequentCalculus.* import lisa.kernel.proof.SequentCalculus.*
import scallion.* import scallion.*
import scallion.util.Unfolds.unfoldRight
import silex.* import silex.*
object Parser { object Parser {
...@@ -29,6 +30,12 @@ object Parser { ...@@ -29,6 +30,12 @@ object Parser {
case SequentParser.UnexpectedEnd(_) => throw ParserException(s"Unexpected end of input") case SequentParser.UnexpectedEnd(_) => throw ParserException(s"Unexpected end of input")
} }
def printSequent(s: Sequent): String = SequentParser.printSequent(s).get
def printFormula(f: Formula): String = SequentParser.printFormula(f).get
def printTerm(t: Term): String = SequentParser.printTerm(t).get
private[Parser] sealed abstract class FormulaToken private[Parser] sealed abstract class FormulaToken
case object ForallToken extends FormulaToken case object ForallToken extends FormulaToken
case object ExistsOneToken extends FormulaToken case object ExistsOneToken extends FormulaToken
...@@ -85,6 +92,27 @@ object Parser { ...@@ -85,6 +92,27 @@ object Parser {
val source = Source.fromIterator(it, NoPositioner) val source = Source.fromIterator(it, NoPositioner)
lexer(source).filter(_ != SpaceToken) lexer(source).filter(_ != SpaceToken)
} }
// TODO: add spaces as needed
def unapply(tokens: Iterator[Token]): String = tokens.map {
case ForallToken => Forall.id
case ExistsOneToken => ExistsOne.id
case ExistsToken => Exists.id
case DotToken => "."
case AndToken => And.id
case OrToken => Or.id
case ImpliesToken => Implies.id
case IffToken => Iff.id
case NegationToken => Neg.id
case EqualityToken => equality.id
case ConstantToken(id) => id
case SchematicToken(id) => "?" + id
case ParenthesisToken(isOpen) => if (isOpen) "(" else ")"
case CommaToken => ","
case SemicolonToken => ";"
case SequentToken => "⊢"
case SpaceToken => " "
}.mkString
} }
private[Parser] object SequentParser extends Parsers { private[Parser] object SequentParser extends Parsers {
...@@ -146,25 +174,49 @@ object Parser { ...@@ -146,25 +174,49 @@ object Parser {
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
//////////////////////// LABELS /////////////////////////////////// //////////////////////// LABELS ///////////////////////////////////
val toplevelConnector: Syntax[Implies.type | Iff.type] = accept(TopLevelConnectorKind) { val toplevelConnector: Syntax[Implies.type | Iff.type] = accept(TopLevelConnectorKind)(
case ImpliesToken => Implies {
case IffToken => Iff case ImpliesToken => Implies
} case IffToken => Iff
},
{
case Implies => Seq(ImpliesToken)
case Iff => Seq(IffToken)
}
)
val negation: Syntax[Neg.type] = accept(NegationKind) { case NegationToken => Neg } val negation: Syntax[Neg.type] = accept(NegationKind)({ case NegationToken => Neg }, { case Neg => Seq(NegationToken) })
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
//////////////////////// TERMS //////////////////////////////////// //////////////////////// TERMS ////////////////////////////////////
lazy val args: Syntax[Seq[Term]] = recursive(open.skip ~ repsep(term, comma) ~ closed.skip) lazy val args: Syntax[Seq[Term]] = recursive(open.skip ~ repsep(term, comma) ~ closed.skip)
lazy val term: Syntax[Term] = recursive((elem(FunctionOrPredicateKind) ~ opt(args)).map { def invertTerm(t: Term): Token ~ Option[Seq[Term]] = t match {
case ConstantToken(id) ~ maybeArgs => case VariableTerm(label) => SchematicToken(label.id) ~ None
val args = maybeArgs.getOrElse(Seq()) case FunctionTerm(label, args) =>
FunctionTerm(ConstantFunctionLabel(id, args.length), args) val optArgs = args match {
case SchematicToken(id) ~ Some(args) => FunctionTerm(SchematicFunctionLabel(id, args.length), args) case Seq() => None
case SchematicToken(id) ~ None => VariableTerm(VariableLabel(id)) case _ => Some(args)
case _ => throw UnreachableException }
}) label match {
case ConstantFunctionLabel(id, _) => ConstantToken(id) ~ optArgs
case SchematicFunctionLabel(id, _) => SchematicToken(id) ~ optArgs
}
}
lazy val term: Syntax[Term] = recursive(
(elem(FunctionOrPredicateKind) ~ opt(args)).map(
{
case ConstantToken(id) ~ maybeArgs =>
val args = maybeArgs.getOrElse(Seq())
FunctionTerm(ConstantFunctionLabel(id, args.length), args)
case SchematicToken(id) ~ Some(args) => FunctionTerm(SchematicFunctionLabel(id, args.length), args)
case SchematicToken(id) ~ None => VariableTerm(VariableLabel(id))
case _ => throw UnreachableException
},
t => Seq(invertTerm(t))
)
)
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
//////////////////////// FORMULAS ///////////////////////////////// //////////////////////// FORMULAS /////////////////////////////////
...@@ -182,87 +234,164 @@ object Parser { ...@@ -182,87 +234,164 @@ object Parser {
case _ => throw UnreachableException case _ => throw UnreachableException
} }
val predicate: Syntax[PredicateFormula] = (elem(FunctionOrPredicateKind) ~ opt(args) ~ opt(eq.skip ~ elem(FunctionOrPredicateKind) ~ opt(args))).map { val predicate: Syntax[PredicateFormula] = (elem(FunctionOrPredicateKind) ~ opt(args) ~ opt(eq.skip ~ elem(FunctionOrPredicateKind) ~ opt(args))).map(
// predicate application {
case ConstantToken(id) ~ maybeArgs ~ None => // predicate application
val args = maybeArgs.getOrElse(Seq()) case ConstantToken(id) ~ maybeArgs ~ None =>
PredicateFormula(ConstantPredicateLabel(id, args.size), args) val args = maybeArgs.getOrElse(Seq())
case SchematicToken(id) ~ Some(args) ~ None => PredicateFormula(SchematicNPredicateLabel(id, args.size), args) PredicateFormula(ConstantPredicateLabel(id, args.size), args)
case SchematicToken(id) ~ None ~ None => PredicateFormula(VariableFormulaLabel(id), Seq()) case SchematicToken(id) ~ Some(args) ~ None => PredicateFormula(SchematicNPredicateLabel(id, args.size), args)
case SchematicToken(id) ~ None ~ None =>
PredicateFormula(VariableFormulaLabel(id), Seq())
// equality of two function applications // equality of two function applications
case fun1 ~ args1 ~ Some(fun2 ~ args2) => case fun1 ~ args1 ~ Some(fun2 ~ args2) =>
PredicateFormula(FOL.equality, Seq(createFunctionTerm(fun1, args1.getOrElse(Seq())), createFunctionTerm(fun2, args2.getOrElse(Seq())))) PredicateFormula(FOL.equality, Seq(createFunctionTerm(fun1, args1.getOrElse(Seq())), createFunctionTerm(fun2, args2.getOrElse(Seq()))))
case _ => throw UnreachableException case _ => throw UnreachableException
} },
{ case PredicateFormula(label, args) =>
label match {
case FOL.equality =>
args match {
case Seq(first, second) => Seq(invertTerm(first) ~ Some(invertTerm(second)))
case _ => Seq()
}
case other =>
val predicateApp = other match {
case ConstantPredicateLabel(id, 0) => ConstantToken(id) ~ None
case ConstantPredicateLabel(id, _) => ConstantToken(id) ~ Some(args)
case VariableFormulaLabel(id) => SchematicToken(id) ~ None
case SchematicNPredicateLabel(id, _) => SchematicToken(id) ~ Some(args)
}
Seq(predicateApp ~ None)
}
}
)
val negated: Syntax[ConnectorFormula] = recursive { val negated: Syntax[ConnectorFormula] = recursive {
(negation ~ subformula).map { case n ~ f => (negation ~ subformula).map(
ConnectorFormula(n, Seq(f)) { case n ~ f =>
} ConnectorFormula(n, Seq(f))
},
{
case ConnectorFormula(Neg, Seq(f)) => Seq(Neg ~ f)
case _ => throw UnreachableException
}
)
} }
// 'and' has higher priority than 'or' val and: Syntax[ConnectorLabel] = elem(AndKind).map[ConnectorLabel](
val connectorFormula: Syntax[Formula] = operators(subformula)( {
elem(AndKind) map {
case AndToken => And case AndToken => And
case _ => throw UnreachableException case _ => throw UnreachableException
} is LeftAssociative, },
elem(OrKind) map { {
case And => Seq(AndToken)
case _ => throw UnreachableException
}
)
val or: Syntax[ConnectorLabel] = elem(OrKind).map[ConnectorLabel](
{
case OrToken => Or case OrToken => Or
case _ => throw UnreachableException case _ => throw UnreachableException
} is LeftAssociative
)(
{ case (l, conn, r) =>
ConnectorFormula(conn, Seq(l, r))
}, },
{
case Or => Seq(OrToken)
case _ => throw UnreachableException
}
)
// 'and' has higher priority than 'or'
val connectorFormula: Syntax[Formula] = operators(subformula)(
and is LeftAssociative,
or is LeftAssociative
)(
(l, conn, r) => ConnectorFormula(conn, Seq(l, r)),
{ case ConnectorFormula(conn, Seq(l, r)) => { case ConnectorFormula(conn, Seq(l, r)) =>
(l, conn, r) (l, conn, r)
} }
) )
// consume binders and return a function that constructs a BinderFormula given the inner formula val binderLabel: Syntax[BinderLabel] = accept(BinderKind)(
val binder: Syntax[(BinderLabel, VariableLabel)] = (accept(BinderKind) { {
case ExistsToken => Exists case ExistsToken => Exists
case ExistsOneToken => ExistsOne case ExistsOneToken => ExistsOne
case ForallToken => Forall case ForallToken => Forall
} ~ accept(FunctionOrPredicateKind) { },
case ConstantToken(id) => VariableLabel(id) {
case SchematicToken(id) => VariableLabel(id) case Exists => Seq(ExistsToken)
} ~ elem(DotKind).unit(DotToken).skip) map { case b ~ v => case ExistsOne => Seq(ExistsOneToken)
(b, v) case Forall => Seq(ForallToken)
} }
)
val boundVariable: Syntax[VariableLabel] = accept(FunctionOrPredicateKind)(
{
case ConstantToken(id) => VariableLabel(id)
case SchematicToken(id) => VariableLabel(id)
},
{ case VariableLabel(id) =>
Seq(SchematicToken(id))
}
)
val binder: Syntax[BinderLabel ~ VariableLabel] = binderLabel ~ boundVariable ~ elem(DotKind).unit(DotToken).skip
val iffImpliesFormula: Syntax[Formula] = (connectorFormula ~ opt(toplevelConnector ~ connectorFormula)).map[Formula](
{
case left ~ Some(c ~ right) => ConnectorFormula(c, Seq(left, right))
case f ~ None => f
},
{
case ConnectorFormula(c @ (Iff | Implies), Seq(left, right)) => Seq(left ~ Some(c ~ right))
case f => Seq(f ~ None)
}
)
lazy val formula: Syntax[Formula] = recursive { lazy val formula: Syntax[Formula] = recursive {
(many(binder) ~ connectorFormula ~ opt(toplevelConnector ~ connectorFormula)) map { case binders ~ f ~ rest => prefixes(binder, iffImpliesFormula)(
val inner = rest match { { case (label ~ variable, f) => BinderFormula(label, variable, f) },
case Some(conn ~ f2) => ConnectorFormula(conn, Seq(f, f2)) { case BinderFormula(label, variable, f) =>
case None => f (label ~ variable, f)
} }
binders.foldRight(inner) { case ((binder, v), f) => )
BinderFormula(binder, v, f)
}
}
} }
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
val sequent: Syntax[Sequent] = repsep(formula, semicolon) ~ opt(sequentSymbol.skip ~ repsep(formula, semicolon)) map {
case left ~ Some(right) => Sequent(left.toSet, right.toSet) val sequent: Syntax[Sequent] = (repsep(formula, semicolon) ~ opt(sequentSymbol.skip ~ repsep(formula, semicolon))).map[Sequent](
case right ~ None => Sequent(Set(), right.toSet) {
} case left ~ Some(right) => Sequent(left.toSet, right.toSet)
case right ~ None => Sequent(Set(), right.toSet)
},
{
case Sequent(Seq(), right) => Seq(right.toSeq ~ None)
case Sequent(left, right) => Seq(left.toSeq ~ Some(right.toSeq))
}
)
val parser: Parser[Sequent] = Parser(sequent) val parser: Parser[Sequent] = Parser(sequent)
val printer: PrettyPrinter[Sequent] = PrettyPrinter(sequent)
val formulaParser: SequentParser.Parser[FOL.Formula] = Parser(formula) val formulaParser: SequentParser.Parser[Formula] = Parser(formula)
val formulaPrinter: SequentParser.PrettyPrinter[Formula] = PrettyPrinter(formula)
val termParser: SequentParser.Parser[FOL.Term] = Parser(term) val termParser: SequentParser.Parser[Term] = Parser(term)
val termPrinter: SequentParser.PrettyPrinter[Term] = PrettyPrinter(term)
def apply(it: Iterator[Token]): ParseResult[Sequent] = parseSequent(it) def apply(it: Iterator[Token]): ParseResult[Sequent] = parseSequent(it)
def unapply(s: Sequent): Option[String] = printSequent(s)
def parseSequent(it: Iterator[Token]): ParseResult[Sequent] = parser(it) def parseSequent(it: Iterator[Token]): ParseResult[Sequent] = parser(it)
def printSequent(s: Sequent): Option[String] = printer(s).map(SequentLexer.unapply)
def parseFormula(it: Iterator[Token]): ParseResult[Formula] = formulaParser(it) def parseFormula(it: Iterator[Token]): ParseResult[Formula] = formulaParser(it)
def printFormula(f: Formula): Option[String] = formulaPrinter(f).map(SequentLexer.unapply)
def parseTerm(it: Iterator[Token]): ParseResult[Term] = termParser(it) def parseTerm(it: Iterator[Token]): ParseResult[Term] = termParser(it)
def printTerm(t: Term): Option[String] = termPrinter(t).map(SequentLexer.unapply)
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment