This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Failure in combinator parser

5 replies
Andres Taylor 2
Joined: 2011-06-18,
User offline. Last seen 42 years 45 weeks ago.
Hey there,
I'm trying to emit readable parser errors, and am following this here.
On the page 637 on this PDF, there's an example on how to emit failures, by using the failure method on the Parsers class. I wrote it down and simplified it a tiny bit to be easy to work with. It's here.
My problem is that this snippet does not produce what the PDF claims. The failure comes from the "false" parser and not the failure(".."). Why is that, and what should it look like?
I'm a bit lost here...
Regards,
Andrés
Andres Taylor 2
Joined: 2011-06-18,
User offline. Last seen 42 years 45 weeks ago.
Re: Failure in combinator parser

I'm running on 2.9.1

On Jan 15, 2012 2:47 PM, "Andres Taylor" <andres.taylor@neotechnology.com> wrote:
Hey there,
I'm trying to emit readable parser errors, and am following this here.
On the page 637 on this PDF, there's an example on how to emit failures, by using the failure method on the Parsers class. I wrote it down and simplified it a tiny bit to be easy to work with. It's here.
My problem is that this snippet does not produce what the PDF claims. The failure comes from the "false" parser and not the failure(".."). Why is that, and what should it look like?
I'm a bit lost here...
Regards,
Andrés
dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Failure in combinator parser

On Sun, Jan 15, 2012 at 11:47, Andres Taylor
wrote:
> Hey there,
>
> I'm trying to emit readable parser errors, and am following this here.
>
> On the page 637 on this PDF, there's an example on how to emit failures, by
> using the failure method on the Parsers class. I wrote it down and
> simplified it a tiny bit to be easy to work with. It's here.
>
> My problem is that this snippet does not produce what the PDF claims. The
> failure comes from the "false" parser and not the failure(".."). Why is
> that, and what should it look like?
>
> I'm a bit lost here...

The technical reason is that the "false" parser skips whitespace, and
the failure parser doesn't. This means that "false" managed to parse
more of the input than failure, so it's likely in a better position to
produce an error.

Because of this unfortunate interaction between whitspace-skipping in
Regex and JavaTokenParsers and the way failure error messages are
selected, I opened this ticket with an alternative way of providing
error messages: https://issues.scala-lang.org/browse/SI-5192.

Cay Horstmann
Joined: 2009-09-04,
User offline. Last seen 42 years 45 weeks ago.
Re: Failure in combinator parser

On Sun, Jan 15, 2012 at 7:44 AM, Daniel Sobral wrote:
> On Sun, Jan 15, 2012 at 11:47, Andres Taylor
> wrote:
>> Hey there,
>>
>> I'm trying to emit readable parser errors, and am following this here.
>>
>> On the page 637 on this PDF, there's an example on how to emit failures, by
>> using the failure method on the Parsers class. I wrote it down and
>> simplified it a tiny bit to be easy to work with. It's here.
>>
>> My problem is that this snippet does not produce what the PDF claims. The
>> failure comes from the "false" parser and not the failure(".."). Why is
>> that, and what should it look like?
>>
>> I'm a bit lost here...
>
> The technical reason is that the "false" parser skips whitespace, and
> the failure parser doesn't. This means that "false" managed to parse
> more of the input than failure, so it's likely in a better position to
> produce an error.
>
> Because of this unfortunate interaction between whitspace-skipping in
> Regex and JavaTokenParsers and the way failure error messages are
> selected, I opened this ticket with an alternative way of providing
> error messages: https://issues.scala-lang.org/browse/SI-5192.
>
> --

A remedy is to use StandardTokenParsers, like this:

import scala.util.parsing.combinator.syntactical._
import scala.util.parsing.input._

object ParserTest extends StandardTokenParsers {
lexical.reserved += ("null", "true", "false")
lexical.delimiters += ("{", "}", "[", "]", ",", ":")

def main(args: Array[String]) {
val json = """{ "address book": John }"""

val r = parse(json)
println(r)
}

def obj: Parser[Map[String, Any]] =
"{" ~> repsep(member, ",") <~ "}" ^^ (Map() ++ _)

def arr: Parser[List[Any]] =
"[" ~> repsep(value, ",") <~ "]"

def member: Parser[(String, Any)] =
stringLit ~ ":" ~ value ^^ {
case name ~ ":" ~ value => (name, value)
}

def value: Parser[Any] = obj | arr | stringLit | numericLit ^^
(_.toDouble) | "null" ^^ (x => null) | "true" ^^ (x => true) | "false"
^^ (x => false) | failure("illegal start of value")

def parse(txt: String) = phrase(obj)(new lexical.Scanner(txt))
}

Tony Sloane
Joined: 2009-01-07,
User offline. Last seen 2 years 32 weeks ago.
Re: Failure in combinator parser

On 16/01/2012, at 2:44 AM, Daniel Sobral wrote:

> On Sun, Jan 15, 2012 at 11:47, Andres Taylor
> wrote:
>> Hey there,
>>
>> I'm trying to emit readable parser errors, and am following this here.
>>
>> On the page 637 on this PDF, there's an example on how to emit failures, by
>> using the failure method on the Parsers class. I wrote it down and
>> simplified it a tiny bit to be easy to work with. It's here.
>>
>> My problem is that this snippet does not produce what the PDF claims. The
>> failure comes from the "false" parser and not the failure(".."). Why is
>> that, and what should it look like?
>>
>> I'm a bit lost here...
>
> The technical reason is that the "false" parser skips whitespace, and
> the failure parser doesn't. This means that "false" managed to parse
> more of the input than failure, so it's likely in a better position to
> produce an error.
>
> Because of this unfortunate interaction between whitspace-skipping in
> Regex and JavaTokenParsers and the way failure error messages are
> selected, I opened this ticket with an alternative way of providing
> error messages: https://issues.scala-lang.org/browse/SI-5192.

That's a nice enhancement.

Another way to avoid the whitespace-skipping problem that I've used on occasion is to define

override def err (msg : String) : Parser[Nothing] =
"" ~> super.err (msg)

override def failure (msg : String) : Parser[Nothing] =
"" ~> super.failure (msg)

so that the errors and failures are reported after the whitespace has been skipped.

Tony

Andres Taylor 2
Joined: 2011-06-18,
User offline. Last seen 42 years 45 weeks ago.
Re: Failure in combinator parser
Thanks all of you for your answers.
Tony's suggestion seems least intrusive, so that's what I opted for.
https://github.com/neo4j/community/commit/42277a551b0130cb5a3ea4b6ae8d2d871505a772#L0R90
Andrés

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland