scala-parser-combinators icon indicating copy to clipboard operation
scala-parser-combinators copied to clipboard

Incorrect mismatch location reported by RegexParsers

Open asarkar opened this issue 11 months ago • 0 comments

implicit def literal(s: String): Parser[String] = new Parser[String] {
  def apply(in: Input) = {
    val source = in.source
    val offset = in.offset
    val start = handleWhiteSpace(source, offset)
    var i = 0
    var j = start
    while (i < s.length && j < source.length && s.charAt(i) == source.charAt(j)) {
      i += 1
      j += 1
    }
    if (i == s.length)
      Success(source.subSequence(start, j).toString, in.drop(j - offset), None)
    else  {
      val found = if (start == source.length()) "end of source" else "'"+source.charAt(start)+"'"
      Failure("'"+s+"' expected but "+found+" found", in.drop(start - offset))
    }
  }
}

Note the error reporting at the end where the index of the mismatch is reported as start. If the string is "apple", and the input "...apply...", the mismatch is at the character 'y', which is pointed to by the variable j, not at the character 'a', which is pointed to by start.

println(parse("apple", "apply"))

Failure('apple' expected but 'a' found,CharSequenceReader('a', ...))

A potential fix may be as follows:

val rest = in.drop(start - offset)
if (start == source.length()) Failure(s"'$s' expected but end of source found", rest)
else Failure(s"'$s' expected but '${source.charAt(j)}' found at index $j", rest)

asarkar avatar Dec 15 '24 02:12 asarkar