From 2922e832e73202273ea21f24e3c157f2ffb24092 Mon Sep 17 00:00:00 2001 From: Jamie Willis Date: Sun, 30 Apr 2023 16:46:46 +0100 Subject: [PATCH] Backport 4.1/various error related bugs (#179) * Fixed overwide carets in trivial errors, hints from adjusting unexpected size to 0, and hints from getting reborn during an iterative combinator * version bump to 4.1.8 --- README.md | 2 +- .../src/main/scala/parsley/internal/errors/ParseError.scala | 2 +- .../src/main/scala/parsley/internal/machine/Context.scala | 2 +- .../parsley/internal/machine/errors/DefuncBuilders.scala | 6 +++--- .../scala/parsley/internal/machine/errors/DefuncError.scala | 3 +-- .../scala/parsley/internal/machine/errors/DefuncHints.scala | 2 +- .../internal/machine/instructions/IterativeInstrs.scala | 3 ++- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index cd16bbfb0..9a46cf1c1 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Parsley is a fast and modern parser combinator library for Scala based loosely o Parsley is distributed on Maven Central, and can be added to your project via: ```scala -libraryDependencies += "com.github.j-mie6" %% "parsley" % "4.1.7" +libraryDependencies += "com.github.j-mie6" %% "parsley" % "4.1.8" ``` Documentation can be found [**here**](https://javadoc.io/doc/com.github.j-mie6/parsley_2.13/latest/index.html) diff --git a/parsley/shared/src/main/scala/parsley/internal/errors/ParseError.scala b/parsley/shared/src/main/scala/parsley/internal/errors/ParseError.scala index 9f97ac3e0..c5c9c87dd 100644 --- a/parsley/shared/src/main/scala/parsley/internal/errors/ParseError.scala +++ b/parsley/shared/src/main/scala/parsley/internal/errors/ParseError.scala @@ -32,7 +32,7 @@ private [internal] case class TrivialError(offset: Int, line: Int, col: Int, builder.unexpected(unexpectedTok.toOption.map(_._1)), builder.expected(builder.combineExpectedItems(expecteds.map(_.formatExpect))), builder.combineMessages(reasons.map(builder.reason(_)).toSeq), - builder.lineInfo(line, beforeLines, afterLines, caret, caretSize)) + builder.lineInfo(line, beforeLines, afterLines, caret, math.min(caretSize, line.length-caret))) } } private [internal] case class FancyError(offset: Int, line: Int, col: Int, msgs: List[String], caretWidth: Int, lexicalError: Boolean) extends ParseError { diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/Context.scala b/parsley/shared/src/main/scala/parsley/internal/machine/Context.scala index 956ca1c80..2e17ad661 100644 --- a/parsley/shared/src/main/scala/parsley/internal/machine/Context.scala +++ b/parsley/shared/src/main/scala/parsley/internal/machine/Context.scala @@ -110,7 +110,7 @@ private [parsley] final class Context(private [machine] var instrs: Array[Instr] private [machine] def updateCheckOffsetAndHints() = { this.checkStack.offset = this.offset - this.hintsValidOffset = this.offset + //this.hintsValidOffset = this.offset // FIXME: verify that this is ok to remove, it seems stupid now that I think about it } // $COVERAGE-OFF$ diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/errors/DefuncBuilders.scala b/parsley/shared/src/main/scala/parsley/internal/machine/errors/DefuncBuilders.scala index 48394568e..37b8721c2 100644 --- a/parsley/shared/src/main/scala/parsley/internal/machine/errors/DefuncBuilders.scala +++ b/parsley/shared/src/main/scala/parsley/internal/machine/errors/DefuncBuilders.scala @@ -179,7 +179,7 @@ private [errors] final class HintCollector(hints: mutable.Set[ExpectItem]) { /** Creates a new collector that starts empty */ def this() = this(mutable.Set.empty) - private var width = 0 + private var width = Option.empty[Int] /** Adds a new hint into the collector. */ def +=(hint: ExpectItem): Unit = this.hints += hint @@ -187,11 +187,11 @@ private [errors] final class HintCollector(hints: mutable.Set[ExpectItem]) { def ++=(hints: Iterable[ExpectItem]): Unit = this.hints ++= hints /** Gets the width of the unexpected token that may have accompanied the original hints */ - def unexpectWidth: Int = width + def unexpectWidth: Option[Int] = width /** Updates the width of the unexpected token that may have accompanied these hints: this * can only get wider. */ - def updateWidth(sz: Int): Unit = width = Math.max(width, sz) + def updateWidth(sz: Int): Unit = width = Some(Math.max(width.getOrElse(0), sz)) /** Generates an immutable snapshot of this collector */ def mkSet: Set[ExpectItem] = this.hints.toSet diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/errors/DefuncError.scala b/parsley/shared/src/main/scala/parsley/internal/machine/errors/DefuncError.scala index 67aac7745..68f347e7d 100644 --- a/parsley/shared/src/main/scala/parsley/internal/machine/errors/DefuncError.scala +++ b/parsley/shared/src/main/scala/parsley/internal/machine/errors/DefuncError.scala @@ -351,8 +351,7 @@ private [errors] final class WithHints private [errors] (val err: TrivialDefuncE override def makeTrivial(builder: TrivialErrorBuilder): Unit = { err.makeTrivial(builder) builder.whenAcceptingExpected { - val size = hints.updateExpectedsAndGetSize(builder) - builder.updateUnexpected(size) + for (size <- hints.updateExpectedsAndGetSize(builder)) builder.updateUnexpected(size) } } } diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/errors/DefuncHints.scala b/parsley/shared/src/main/scala/parsley/internal/machine/errors/DefuncHints.scala index 515687d0f..1229b6024 100644 --- a/parsley/shared/src/main/scala/parsley/internal/machine/errors/DefuncHints.scala +++ b/parsley/shared/src/main/scala/parsley/internal/machine/errors/DefuncHints.scala @@ -20,7 +20,7 @@ private [machine] sealed abstract class DefuncHints { /** This function evaluates this `DefuncHints` structure into the actual set of * error items it represents and adds this directly into the provided `TrivialErrorBuilder` */ - private [machine] def updateExpectedsAndGetSize(builder: TrivialErrorBuilder): Int = { + private [machine] def updateExpectedsAndGetSize(builder: TrivialErrorBuilder): Option[Int] = { val hintCollector = builder.makeHintCollector collect(hintCollector) hintCollector.unexpectWidth diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/IterativeInstrs.scala b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/IterativeInstrs.scala index 20efa3a25..b33aec42e 100644 --- a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/IterativeInstrs.scala +++ b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/IterativeInstrs.scala @@ -8,11 +8,12 @@ import scala.collection.mutable import parsley.internal.machine.Context import parsley.internal.machine.XAssert._ +// TODO: Now PushHandlerAndCheck(label, false), so could be removed again! private [internal] final class PushHandlerIterative(var label: Int) extends InstrWithLabel { override def apply(ctx: Context): Unit = { ensureRegularInstruction(ctx) // This is used for iterative parsers, which must ensure that invalidated hints are invalided _now_ - ctx.invalidateHints() + //ctx.invalidateHints() // FIXME: This has been removed because hint setting in updateCheckOffsetAndHints has been disabled, pending deep thought ctx.pushCheck() ctx.pushHandler(label) ctx.inc()