Skip to content

Commit

Permalink
Fixed partial amend
Browse files Browse the repository at this point in the history
  • Loading branch information
j-mie6 committed Jan 18, 2023
1 parent 75c9895 commit 0003083
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ object combinator {
* @since 3.1.0
* @group adj
*/
def amend[A](p: Parsley[A]): Parsley[A] = new Parsley(new frontend.ErrorAmend(p.internal))
def amend[A](p: Parsley[A]): Parsley[A] = new Parsley(new frontend.ErrorAmend(p.internal, partial = false))

/** This combinator prevents the action of any enclosing `amend` on the errors generated by the given
* parser.
Expand Down Expand Up @@ -144,6 +144,8 @@ object combinator {
// TODO: Documentation and testing ahead of future release
private [parsley] def dislodge[A](p: Parsley[A]): Parsley[A] = new Parsley(new frontend.ErrorDislodge(p.internal))
private [parsley] def amendThenDislodge[A](p: Parsley[A]): Parsley[A] = dislodge(amend(p))
private [parsley] def partialAmend[A](p: Parsley[A]): Parsley[A] = new Parsley(new frontend.ErrorAmend(p.internal, partial = true))
private [parsley] def partialAmendThenDislodge[A](p: Parsley[A]): Parsley[A] = dislodge(partialAmend(p))

/** This combinator marks any errors within the given parser as being ''lexical errors''.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ private [deepembedding] final class ErrorExplain[A](val p: StrictParsley[A], rea
// $COVERAGE-ON$
}

private [deepembedding] final class ErrorAmend[A](val p: StrictParsley[A]) extends ScopedUnaryWithState[A, A](false) {
private [deepembedding] final class ErrorAmend[A](val p: StrictParsley[A], partial: Boolean) extends ScopedUnaryWithState[A, A](false) {
override val instr: instructions.Instr = instructions.PopHandlerAndState
override def instrNeedsLabel: Boolean = false
override def handlerLabel(state: CodeGenState): Int = state.getLabel(instructions.AmendAndFail)
override def handlerLabel(state: CodeGenState): Int = state.getLabel(instructions.AmendAndFail(partial))
// $COVERAGE-OFF$
final override def pretty(p: String): String = s"amend($p)"
// $COVERAGE-ON$
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ private [parsley] final class ErrorExplain[A](p: LazyParsley[A], reason: String)
override def make(p: StrictParsley[A]): StrictParsley[A] = new backend.ErrorExplain(p, reason)
}

private [parsley] final class ErrorAmend[A](p: LazyParsley[A]) extends Unary[A, A](p) {
override def make(p: StrictParsley[A]): StrictParsley[A] = new backend.ErrorAmend(p)
private [parsley] final class ErrorAmend[A](p: LazyParsley[A], partial: Boolean) extends Unary[A, A](p) {
override def make(p: StrictParsley[A]): StrictParsley[A] = new backend.ErrorAmend(p, partial)
}
private [parsley] final class ErrorEntrench[A](p: LazyParsley[A]) extends Unary[A, A](p) {
override def make(p: StrictParsley[A]): StrictParsley[A] = new backend.ErrorEntrench(p)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ private [internal] class ApplyReasonAndFail(reason: String) extends Instr {
// $COVERAGE-ON$
}

private [internal] object AmendAndFail extends Instr {
private [internal] class AmendAndFail private (partial: Boolean) extends Instr {
override def apply(ctx: Context): Unit = {
ensureHandlerInstruction(ctx)
ctx.errs.error = ctx.errs.error.amend(ctx.states.offset, ctx.states.line, ctx.states.col)
ctx.errs.error = ctx.errs.error.amend(if (partial) ctx.offset else ctx.states.offset, ctx.states.line, ctx.states.col)
ctx.states = ctx.states.tail
ctx.fail()
}
Expand All @@ -98,6 +98,11 @@ private [internal] object AmendAndFail extends Instr {
override def toString: String = "AmendAndFail"
// $COVERAGE-ON$
}
private [internal] object AmendAndFail {
private [this] val partial = new AmendAndFail(partial = true)
private [this] val full = new AmendAndFail(partial = false)
def apply(partial: Boolean): AmendAndFail = if (partial) this.partial else this.full
}

private [internal] object EntrenchAndFail extends Instr {
override def apply(ctx: Context): Unit = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ private [parsley] object FilterOps {
if (full) combinator.amendThenDislodge(p)
else p
}
def amendThenDislodgeOrPartial[A](full: Boolean)(p: Parsley[A]): Parsley[A] = {
if (full) combinator.amendThenDislodge(p)
else combinator.partialAmendThenDislodge(p)
}
def entrench[A](full: Boolean)(p: Parsley[A]): Parsley[A] = {
if (full) combinator.entrench(p)
else p
}
}

/** This trait, and its subclasses, can be used to configure how filters should be used within the `Lexer`.
Expand Down Expand Up @@ -46,12 +54,12 @@ abstract class SpecialisedMessage[A](fullAmend: Boolean) extends SpecialisedFilt
def message(x: A): Seq[String]

private [parsley] final override def filter(p: Parsley[A])(f: A => Boolean) = FilterOps.amendThenDislodge(fullAmend) {
p.guardAgainst {
FilterOps.entrench(fullAmend)(p).guardAgainst {
case x if !f(x) => message(x)
}
}
private [parsley] final override def collect[B](p: Parsley[A])(f: PartialFunction[A, B]) = FilterOps.amendThenDislodge(fullAmend) {
p.collectMsg(message(_))(f)
FilterOps.entrench(fullAmend)(p).collectMsg(message(_))(f)
}
private [parsley] final override def injectLeft[B] = new SpecialisedMessage[Either[A, B]](fullAmend) {
def message(xy: Either[A, B]) = {
Expand Down Expand Up @@ -80,7 +88,7 @@ abstract class Unexpected[A](fullAmend: Boolean) extends VanillaFilterConfig[A]
def unexpected(x: A): String

private [parsley] final override def filter(p: Parsley[A])(f: A => Boolean) = FilterOps.amendThenDislodge(fullAmend) {
p.unexpectedWhen {
FilterOps.entrench(fullAmend)(p).unexpectedWhen {
case x if !f(x) => unexpected(x)
}
}
Expand Down Expand Up @@ -111,7 +119,7 @@ abstract class Because[A](fullAmend: Boolean) extends VanillaFilterConfig[A] { s
def reason(x: A): String

private [parsley] final override def filter(p: Parsley[A])(f: A => Boolean) = FilterOps.amendThenDislodge(fullAmend) {
p.filterOut {
FilterOps.entrench(fullAmend)(p).filterOut {
case x if !f(x) => reason(x)
}
}
Expand Down Expand Up @@ -146,12 +154,11 @@ abstract class UnexpectedBecause[A](fullAmend: Boolean) extends VanillaFilterCon
*/
def reason(x: A): String

private [parsley] final override def filter(p: Parsley[A])(f: A => Boolean) = FilterOps.amendThenDislodge(fullAmend) {
combinator.amendThenDislodge {
position.internalOffsetSpan(combinator.entrench(p)).flatMap { case (os, x, oe) =>
if (f(x)) combinator.unexpected(oe - os, this.unexpected(x)).explain(reason(x))
else pure(x)
}
// TODO: factor this combinator out with the "Great Move" in 4.2
private [parsley] final override def filter(p: Parsley[A])(f: A => Boolean) = FilterOps.amendThenDislodgeOrPartial(fullAmend) {
position.internalOffsetSpan(combinator.entrench(p)).flatMap { case (os, x, oe) =>
if (f(x)) combinator.unexpected(oe - os, this.unexpected(x)).explain(reason(x))
else pure(x)
}
}
private [parsley] final override def injectLeft[B] = new UnexpectedBecause[Either[A, B]](fullAmend) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ object UnexpectedZeroDot {
def apply(unexpected: String): PreventDotIsZeroConfig = new UnexpectedZeroDot(unexpected)
}

// TODO: factor this combinator out with the "Great Move" in 4.2
private final class UnexpectedZeroDotWithReason private (unexpected: String, reason: String) extends PreventDotIsZeroConfig {
private [token] override def apply(p: Parsley[Boolean]): Parsley[Boolean] = combinator.amendThenDislodge {
private [token] override def apply(p: Parsley[Boolean]): Parsley[Boolean] = combinator.partialAmendThenDislodge {
position.internalOffsetSpan(combinator.entrench(p)).flatMap { case (os, x, oe) =>
if (x) combinator.unexpected(oe - os, unexpected).explain(reason)
else pure(x)
Expand Down

0 comments on commit 0003083

Please sign in to comment.