title: Scala Parser Combinators tricks for recursive bnf?
body: <p>Im trying to match this syntax:</p>
  
  <pre><code>pgm ::= exprs
  exprs ::= expr [; exprs]
  expr ::= ID | expr . [0-9]+
  </code></pre>
  
  <p>My scala packrat parser combinator looks like this:</p>
  
  <pre><code>import scala.util.parsing.combinator.PackratParsers
  import scala.util.parsing.combinator.syntactical._
  
  object Dotter extends StandardTokenParsers with PackratParsers {
      lexical.delimiters ++= List(".",";")
      def pgm = repsep(expr,";")
      def expr :Parser[Any]= ident | expr~"."~num
      def num = numericLit
  
         def parse(input: String) =
      phrase(pgm)(new PackratReader(new lexical.Scanner(input))) match {
        case Success(result, _) =&gt; println("Success!"); Some(result)
        case n @ _ =&gt; println(n);println("bla"); None
      }  
  
      def main(args: Array[String]) {
        val prg = "x.1.2.3;" +
              "y.4.1.1;" +
              "z;" +
              "n.1.10.30"
  
  
              parse(prg);
      }
  }
  </code></pre>
  
  <p>But this doesnt work. Either it "matches greedy" and tells me:</p>
  
  <pre><code>[1.2] failure: end of input expected 
  x.1.2.3;y.4.1.1;z;n.1.10.30
  </code></pre>
  
  <p>or if I change the <code>|</code> to a <code>|||</code> I get a stackoverflow:</p>
  
  <pre><code>Exception in thread "main" java.lang.StackOverflowError
  at java.lang.Character.isLetter(Unknown Source)
  at java.lang.Character.isLetter(Unknown Source)
  at scala.util.parsing.combinator.lexical.Lexical$$anonfun$letter$1.apply(Lexical.scala:32)
  at scala.util.parsing.combinator.lexical.Lexical$$anonfun$letter$1.apply(Lexical.scala:32)
  ...
  </code></pre>
  
  <p>I kindoff understand why I get the errors; what can I do to parse a syntax like the above? It doesnt seem that esoteric to me</p>
  
  <p>EDIT:
  Based on the paper referenced in <a href="http://scala-programming-language.1934581.n4.nabble.com/Packrat-parser-guidance-td1956908.html" rel="noreferrer">http://scala-programming-language.1934581.n4.nabble.com/Packrat-parser-guidance-td1956908.html</a> 
  I found out that my program didnt actually use the new packrat parser.</p>
  
  <p>Ie. change <code>Parser[Any]</code> to <code>PackratParser[Any]</code> and use <code>lazy val</code> instead of <code>def</code></p>
  
  <p>I rewrote the above to this:</p>
  
  <pre><code>import scala.util.parsing.combinator.PackratParsers
  import scala.util.parsing.combinator.syntactical._
  
  object Dotter extends StandardTokenParsers with PackratParsers {
      lexical.delimiters ++= List(".",";")
      lazy val pgm : PackratParser[Any] = repsep(expr,";")
      lazy val expr :PackratParser[Any]= expr~"."~num | ident
      lazy val num = numericLit
  
      def parse(input: String) =
      phrase(pgm)(new PackratReader(new lexical.Scanner(input))) match {
        case Success(result, _) =&gt; println("Success!"); Some(result)
        case n @ _ =&gt; println(n);println("bla"); None
      }  
  
      def main(args: Array[String]) {
        val prg = "x.1.2.3 ;" +
              "y.4.1.1;" +
              "z;" +
              "n.1.10.30"
  
  
              parse(prg);
      }
  }
  </code></pre>