@@ -133,13 +133,21 @@ trait Parsers {
133133 * @param next The parser's remaining input
134134 */
135135 case class Success [+ T ](result : T , override val next : Input ) extends ParseResult [T ] {
136- def map [U ](f : T => U ) = Success (f(result), next)
137- def mapPartial [U ](f : PartialFunction [T , U ], error : T => String ): ParseResult [U ]
138- = if (f.isDefinedAt(result)) Success (f(result), next)
139- else Failure (error(result), next)
136+ def lastFailure : Option [Failure ] = None
140137
141- def flatMapWithNext [U ](f : T => Input => ParseResult [U ]): ParseResult [U ]
142- = f(result)(next)
138+ def map [U ](f : T => U ) = Success (f(result), next, lastFailure)
139+
140+ def mapPartial [U ](f : PartialFunction [T , U ], error : T => String ): ParseResult [U ] =
141+ if (f.isDefinedAt(result)) Success (f(result), next, lastFailure)
142+ else Failure (error(result), next)
143+
144+ def flatMapWithNext [U ](f : T => Input => ParseResult [U ]): ParseResult [U ] = f(result)(next) match {
145+ case s @ Success (result, rest) =>
146+ val failure = selectLastFailure(this .lastFailure, s.lastFailure)
147+ Success (result, rest, failure)
148+ case f : Failure => selectLastFailure(Some (f), lastFailure).get
149+ case e : Error => e
150+ }
143151
144152 def filterWithError (p : T => Boolean , error : T => String , position : Input ): ParseResult [T ] =
145153 if (p(result)) this
@@ -188,10 +196,16 @@ trait Parsers {
188196 /** The toString method of a Failure yields an error message. */
189197 override def toString = " [" + next.pos+ " ] failure: " + msg+ " \n\n " + next.pos.longString
190198
191- def append [U >: Nothing ](a : => ParseResult [U ]): ParseResult [U ] = { val alt = a; alt match {
192- case Success (_, _) => alt
193- case ns : NoSuccess => if (alt.next.pos < next.pos) this else alt
194- }}
199+ def append [U >: Nothing ](a : => ParseResult [U ]): ParseResult [U ] = {
200+ val alt = a
201+
202+ alt match {
203+ case s @ Success (result, rest) =>
204+ val failure = selectLastFailure(Some (this ), s.lastFailure)
205+ Success (result, rest, failure)
206+ case ns : NoSuccess => if (alt.next.pos < next.pos) this else alt
207+ }
208+ }
195209 }
196210
197211 /** The fatal failure case of ParseResult: contains an error-message and
@@ -210,6 +224,19 @@ trait Parsers {
210224 def Parser [T ](f : Input => ParseResult [T ]): Parser [T ]
211225 = new Parser [T ]{ def apply (in : Input ) = f(in) }
212226
227+ private [combinator] def Success [U ](res : U , next : Input , failure : Option [Failure ]): ParseResult [U ] =
228+ new Success (res, next) { override val lastFailure : Option [Failure ] = failure }
229+
230+ private [combinator] def selectLastFailure (failure0 : Option [Failure ], failure1 : Option [Failure ]): Option [Failure ] =
231+ (failure0, failure1) match {
232+ case (Some (f0), Some (f1)) =>
233+ if (f0.next.pos < f1.next.pos) Some (f1)
234+ else Some (f0)
235+ case (Some (f0), _) => Some (f0)
236+ case (_, Some (f1)) => Some (f1)
237+ case _ => None
238+ }
239+
213240 def OnceParser [T ](f : Input => ParseResult [T ]): Parser [T ] with OnceParser [T ]
214241 = new Parser [T ] with OnceParser [T ] { def apply (in : Input ) = f(in) }
215242
@@ -630,7 +657,7 @@ trait Parsers {
630657 */
631658 def acceptIf (p : Elem => Boolean )(err : Elem => String ): Parser [Elem ] = Parser { in =>
632659 if (in.atEnd) Failure (" end of input" , in)
633- else if (p(in.first)) Success (in.first, in.rest)
660+ else if (p(in.first)) Success (in.first, in.rest, None )
634661 else Failure (err(in.first), in)
635662 }
636663
@@ -649,7 +676,7 @@ trait Parsers {
649676 */
650677 def acceptMatch [U ](expected : String , f : PartialFunction [Elem , U ]): Parser [U ] = Parser { in =>
651678 if (in.atEnd) Failure (" end of input" , in)
652- else if (f.isDefinedAt(in.first)) Success (f(in.first), in.rest)
679+ else if (f.isDefinedAt(in.first)) Success (f(in.first), in.rest, None )
653680 else Failure (expected+ " expected" , in)
654681 }
655682
@@ -682,7 +709,7 @@ trait Parsers {
682709 * @param v The result for the parser
683710 * @return A parser that always succeeds, with the given result `v`
684711 */
685- def success [T ](v : T ) = Parser { in => Success (v, in) }
712+ def success [T ](v : T ) = Parser { in => Success (v, in, None ) }
686713
687714 /** A helper method that turns a `Parser` into one that will
688715 * print debugging information to stdout before and after
@@ -747,19 +774,24 @@ trait Parsers {
747774 lazy val p = p0 // lazy argument
748775 val elems = new ListBuffer [T ]
749776
750- def continue (in : Input ): ParseResult [List [T ]] = {
777+ def continue (in : Input , failure : Option [ Failure ] ): ParseResult [List [T ]] = {
751778 val p0 = p // avoid repeatedly re-evaluating by-name parser
752- @ tailrec def applyp (in0 : Input ): ParseResult [List [T ]] = p0(in0) match {
753- case Success (x, rest) => elems += x ; applyp(rest)
779+ @ tailrec def applyp (in0 : Input , failure : Option [Failure ]): ParseResult [List [T ]] = p0(in0) match {
780+ case s @ Success (x, rest) =>
781+ val selectedFailure = selectLastFailure(s.lastFailure, failure)
782+ elems += x
783+ applyp(rest, selectedFailure)
754784 case e @ Error (_, _) => e // still have to propagate error
755- case _ => Success (elems.toList, in0)
785+ case f : Failure =>
786+ val selectedFailure = selectLastFailure(failure, Some (f))
787+ Success (elems.toList, in0, selectedFailure)
756788 }
757789
758- applyp(in)
790+ applyp(in, failure )
759791 }
760792
761793 first(in) match {
762- case Success (x, rest) => elems += x ; continue(rest)
794+ case s @ Success (x, rest) => elems += x ; continue(rest, s.lastFailure )
763795 case ns : NoSuccess => ns
764796 }
765797 }
@@ -779,14 +811,14 @@ trait Parsers {
779811 val elems = new ListBuffer [T ]
780812 val p0 = p // avoid repeatedly re-evaluating by-name parser
781813
782- @ tailrec def applyp (in0 : Input ): ParseResult [List [T ]] =
783- if (elems.length == num) Success (elems.toList, in0)
814+ @ tailrec def applyp (in0 : Input , failure : Option [ Failure ] ): ParseResult [List [T ]] =
815+ if (elems.length == num) Success (elems.toList, in0, failure )
784816 else p0(in0) match {
785- case Success (x, rest) => elems += x ; applyp(rest)
817+ case s @ Success (x, rest) => elems += x ; applyp(rest, s.lastFailure )
786818 case ns : NoSuccess => ns
787819 }
788820
789- applyp(in)
821+ applyp(in, None )
790822 }
791823
792824 /** A parser generator for non-empty repetitions.
@@ -868,7 +900,7 @@ trait Parsers {
868900 def not [T ](p : => Parser [T ]): Parser [Unit ] = Parser { in =>
869901 p(in) match {
870902 case Success (_, _) => Failure (" Expected failure" , in)
871- case _ => Success ((), in)
903+ case _ => Success ((), in, None )
872904 }
873905 }
874906
@@ -882,7 +914,7 @@ trait Parsers {
882914 */
883915 def guard [T ](p : => Parser [T ]): Parser [T ] = Parser { in =>
884916 p(in) match {
885- case s@ Success (s1,_) => Success (s1, in)
917+ case s@ Success (s1,_) => Success (s1, in, s.lastFailure )
886918 case e => e
887919 }
888920 }
@@ -897,7 +929,7 @@ trait Parsers {
897929 */
898930 def positioned [T <: Positional ](p : => Parser [T ]): Parser [T ] = Parser { in =>
899931 p(in) match {
900- case Success (t, in1) => Success (if (t.pos == NoPosition ) t setPos in.pos else t, in1)
932+ case s @ Success (t, in1) => Success (if (t.pos == NoPosition ) t setPos in.pos else t, in1, s.lastFailure )
901933 case ns : NoSuccess => ns
902934 }
903935 }
@@ -915,7 +947,10 @@ trait Parsers {
915947 def apply (in : Input ) = p(in) match {
916948 case s @ Success (out, in1) =>
917949 if (in1.atEnd) s
918- else Failure (" end of input expected" , in1)
950+ else s.lastFailure match {
951+ case Some (failure) => failure
952+ case _ => Failure (" end of input expected" , in1)
953+ }
919954 case ns => ns
920955 }
921956 }
0 commit comments