Commits

pchiusano  committed 736ebd6

some additional commit-based combinators

  • Participants
  • Parent commits 132de5f
  • Branches error-reporting

Comments (0)

Files changed (1)

File src/main/scala/nomo/Parser.scala

           case Done(t,rem,ann) => t flatMap (s => 
             g(Result(s, ann.get, ann.getUser)) match {
               case Status(c,Right(pb)) => 
-                (if (c) (pb.commit) else pb).feedAll(rem,ann)
+                (if (c) (pb.commitOnEnter) else pb).feedAll(rem,ann)
               case s => suspendS { 
                 (Done(s.asInstanceOf[Status[E,B]],rem,ann), a2) } 
             })
 
     /** Sequence `this` and `p`, ignoring the result of `this`. */
     def >>[B](p: => Parser[B]): Parser[B] = (this map2 p)((_,b) => b)
+    def >>![B](p: => Parser[B]): Parser[B] = this.commit >> p 
 
     /** Ignore the result of this parser. */
     def ignore: Parser[Unit] = this >> unit(())
 
     /** Sequence `this` and `p`, ignoring the result of `p`. */
     def <<[B](p: => Parser[B]) = (this map2 p)((a,_) => a)
+    def <<![B](p: => Parser[B]) = this.commit << p
 
     /** Feed this `Parser` all the tokens in the given `Iterable`. */
     def feedChunked(i: Iterable[I], ann: Accumulator[I,X,U], chunkSize: Int = 5000): (Parser[A], Accumulator[I,X,U]) = {
     /** Combines the results of this parser and p into a pair. */
     def ++[B](p: => Parser[B]): Parser[(A,B)] = (this map2 p)((a,b) => (a,b))
 
+    def commitOnEnter: Parser[A] = Parsers.this.commitOnEnter(this)
+
     /** Converts parse failures to errors, which prevents backtracking in `|`. */
     def commit: Parser[A] = Parsers.this.commit(this)
+    def ++![B](p: => Parser[B]) = this.commit ++ p 
 
     /** Like or but returns result in an Either. */
     def either[B](p: Parser[B]): Parser[Either[A,B]] =
   /** Parser which consumes no input and fails with the error generated from the current position. */
   def fail[A](f: X => E): Parser[A] = position.mapResult(r => r.status.flatMap(x => Failure(f(x))))
   
-  def commit[A](p: Parser[A]): Parser[A] = p mapStatus (_.commit)
+  /** Converts failures of this parser to errors. Use `commit` to do this only 
+    * after a successful parse of `p`. */
+  def commitOnEnter[A](p: Parser[A]): Parser[A] = p mapStatus (_.commit)
+
+  /** Converts any failing parses sequenced after `p` to errors. 
+    * Note that if `p` fails, this is considered before the commit point. */
+  def commit[A](p: Parser[A]): Parser[A] = p << unit(()).commit
 
   case class Cont[A](
       f: (Input[F,I], Accumulator[I,X,U]) => Trampoline[(Parser[A], Accumulator[I,X,U])]) extends Parser[A] {