Since this is my first post I'd like to take the opportunity to say: What a great site SO is!
Anyway, to the question:
I'm somewhat of a Scala newbie and I'm trying to solve a data extraction and parsing problem with the parser combinators in Scala and I'm getting java.lang.StackOverflowError exceptions.
My real world example is too big to include so I'm reusing code from another SO question with the same problem. The code is slighly modified though. I tried to solve the problem using the PackratParsers but did not succeed.
import scala.util.parsing.combinator.syntactical.StandardTokenParsers
import scala.util.parsing.combinator.PackratParsers
object ArithmeticParser1 extends StandardTokenParsers with PackratParsers {
lexical.delimiters ++= List("(", ")", "+", "-", "*", "/")
lazy val reduceList: Int ~ List[String ~ Int] => Int = {
case i ~ ps => (i /: ps)(reduce)
}
def reduce(x: Int, r: String ~ Int) = (r: @unchecked) match {
case "+" ~ y => x + y
case "-" ~ y => x - y
case "*" ~ y => x * y
case "/" ~ y => x / y
}
lazy val expr : PackratParser[Int] = term ~ rep ("+" ~ term | "-" ~ term) ^^ reduceList
lazy val term : PackratParser[Int] = factor ~ rep ("*" ~ factor | "/" ~ factor) ^^ reduceList
lazy val factor: PackratParser[Int] = "(" ~> expr <~ ")" | numericLit ^^ (_.toInt)
def main(args: Array[String]) {
val times = 500
val s = "(" * times + "1 + 1" + ")" * times
val tokens = new PackratReader(new lexical.Scanner(s))
println(phrase(expr)(tokens))
}
}
I've mixed in the PackratParsers trait, changed the defs to lazy vals and I'm using a PackratReader. What am I missunderstanding here? From reading Daniel C. Sobrals answer comments to the SO question How can I ignore non-matching preceding text when using Scala's parser combinators? it seems like PackratParsers should do the trick.
Ref: PackratParsers paper