I'm trying to write a simple parser in scala but when I add a repeated token Scala seems to get stuck in an infinite loop...
object RewriteRuleParsers extends RegexParsers {
private def space = regex(new Regex("[ \\n]+"))
private def number = regex(new Regex("[0-9]+"))
private def equals = (space?)~"="~(space?)
private def word = regex(new Regex("[a-zA-Z][a-zA-Z0-9-]*"))
private def string = regex(new Regex("[0-9]+")) >> { len => ":" ~> regex(new Regex(".{" + len + "}")) }
private def matchTokenPartContent: Parser[Any] = (space?)~word~equals~word<~ space?
private def matchTokenPart: Parser[Any] = ((space?) ~> "{" ~> matchTokenPartContent <~ "}"<~ space?)
private def matchTokenParts = (matchTokenPart *)
private def matchToken: Parser[Any] = ("[" ~> matchTokenParts ~ "]")
def parseMatchToken(str: String): ParseResult[Any] = parse(matchToken, str)
}
and the code to call it
val parseResult = RewriteRuleParsers.parseMatchToken("[{tag=hello}]")
Any advice gratefull received
The problem is the precedence of ?
. Take the following, for example:
object simpleParser extends RegexParsers {
val a = literal("a")
val b = literal("b")
def apply(s: String) = this.parseAll(a <~ b?, s)
}
The a <~ b?
here is interpreted as (a <~ b)?
, so it will accept "ab"
or ""
, but not "a"
. We'd need to write a <~ (b?)
if we want it to accept "a"
.
In your case you can just parenthesize space?
at the end of matchTokenPartContent
and matchTokenPart
and it'll work as expected.