title: Scala parser combinators, failure on end of line
body: <p>I am trying to build an interpreter for the <a href="http://en.wikipedia.org/wiki/Icon_%28programming_language%29" rel="nofollow">Icon programming language</a>, in Scala. Right now I am working on setting up a parser for it.</p>
  
  <p>The code I have written so far is:</p>
  
  <pre><code>package interpreter
  import scala.util.parsing.combinator.syntactical._
  import scala.util.parsing.combinator.RegexParsers
  import scala.util.parsing.combinator.PackratParsers
  import scala.util.parsing.combinator.JavaTokenParsers
  
  object ExprParser extends JavaTokenParsers with PackratParsers{
  
  def exp : Parser[expr] =
      andexp |
      fail |
      ifexp |
      fromTo |
      write |
      string |
      arithm |
      "(" ~&gt; exp &lt;~ ")" |
      exp
  
  def integer : Parser[CstInt] = wholeNumber ^^ { s =&gt; { //println("matching int");
  new CstInt(s.toInt)}}
  def string : Parser[CstStr] = stringLiteral ^^ { s =&gt; { //println("matching string");
  new CstStr(s)}}
  
  
  def fail : Parser[Fail] = "&amp;fail" ^^ { e =&gt; Fail()}
  
  def  write : Parser[Write] =  "write" ~&gt; "(" ~&gt; exp &lt;~ ")" ^^ {  e =&gt; Write(e)}
  
  def ifexp : Parser[If] = ("if" ~&gt; exp) ~ ("then" ~&gt; exp) ~ ("else" ~&gt; exp) ^^ { case cond ~ suc ~ fail =&gt; If(cond, suc, fail)}
  
  
  // Arithmetic
  def arithm : Parser[expr] =
      term ~ ("+" ~&gt; arithm) ^^ { case l ~ r =&gt; Prim("+", l, r)} |
      term ~ ("-" ~&gt; arithm) ^^{ case l ~ r =&gt; Prim("-", l, r)} |
      term
  
  def term : Parser[expr] =
      factor ~ ("*" ~&gt; term) ^^ { case l ~ r =&gt; Prim("*", l, r)} |
      factor ~ ("/" ~&gt; term) ^^ { case l ~ r =&gt; Prim("/", l, r)} |
      factor
  
  def factor : Parser[expr] =
      integer |
      "-" ~&gt; arithm |
      "(" ~&gt; arithm &lt;~ ")"
  
  
  //PackratParser to allow left recursive grammars
  lazy val fromTo : PackratParser[FromTo] = exp ~ ("to" ~&gt; exp) ^^ { case from ~ to =&gt; FromTo(from, to)}
  
  lazy val andexp : PackratParser[And] = exp ~ ("&amp;" ~&gt; exp) ^^ { case e1 ~ e2 =&gt;{ println("matching and" + e1); println(" arg2: " + e2); And(e1, e2)}}
  
  def parseInput(input: String) : expr =
      parseAll (exp, input) match {
          case Success(tree, _) =&gt; tree
          case e: NoSuccess =&gt; throw new IllegalArgumentException(e.toString())
      }
  }
  </code></pre>
  
  <p>Now, my problem is that when I run this code on this input:</p>
  
  <p>write(1 to 5) &amp; write(3 to 5)</p>
  
  <p>I get the following output:</p>
  
  <pre><code>matching andWrite(FromTo(CstInt(1),CstInt(5)))
  arg2: Write(FromTo(CstInt(3),CstInt(5)))
  matching andWrite(FromTo(CstInt(1),CstInt(5)))
  arg2: Write(FromTo(CstInt(3),CstInt(5)))
  java.lang.IllegalArgumentException: [1.30] failure: `&amp;' expected but `' found
  
  write(1 to 5) &amp; write(3 to 5)
                               ^
  at interpreter.ExprParser$.parseInput(parser.scala:62)
  at interpreter.Main$.main(main.scala:9)
  at interpreter.Main.main(main.scala)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  at java.lang.reflect.Method.invoke(Method.java:597)
  at sbt.Run.run0(Run.scala:60)
  at sbt.Run.execute$1(Run.scala:47)
  at sbt.Run$$anonfun$run$2.apply(Run.scala:50)
  at sbt.Run$$anonfun$run$2.apply(Run.scala:50)
  at sbt.TrapExit$.executeMain$1(TrapExit.scala:33)
  at sbt.TrapExit$$anon$1.run(TrapExit.scala:42)
  </code></pre>
  
  <p>I added the printouts as a way of seeing whether it even matched the &amp; operator. </p>
  
  <p>The code runs fine on other weird inputs like:</p>
  
  <p>write((if &amp;fail then 3 else 5) to (3 to 5))</p>
  
  <p>So it seems to be a problem specifically related to the andexp parser.</p>
  
  <p>Any help would be much appreciated, as I am completely new to Scala and the parser combinators, and it is somewhat hard to find good documentation I think.</p>