@@ -137,13 +137,21 @@ trait Parsers {
137137 * @param next The parser's remaining input
138138 */
139139 case class Success [+ T ](result : T , override val next : Input ) extends ParseResult [T ] {
140- def map [U ](f : T => U ) = Success (f(result), next)
141- def mapPartial [U ](f : PartialFunction [T , U ], error : T => String ): ParseResult [U ]
142- = if (f.isDefinedAt(result)) Success (f(result), next)
143- else Failure (error(result), next)
140+ def lastFailure : Option [Failure ] = None
144141
145- def flatMapWithNext [U ](f : T => Input => ParseResult [U ]): ParseResult [U ]
146- = f(result)(next)
142+ def map [U ](f : T => U ) = Success (f(result), next, lastFailure)
143+
144+ def mapPartial [U ](f : PartialFunction [T , U ], error : T => String ): ParseResult [U ] =
145+ if (f.isDefinedAt(result)) Success (f(result), next, lastFailure)
146+ else Failure (error(result), next)
147+
148+ def flatMapWithNext [U ](f : T => Input => ParseResult [U ]): ParseResult [U ] = f(result)(next) match {
149+ case s @ Success (result, rest) =>
150+ val failure = selectLastFailure(this .lastFailure, s.lastFailure)
151+ Success (result, rest, failure)
152+ case f : Failure => selectLastFailure(Some (f), lastFailure).get
153+ case e : Error => e
154+ }
147155
148156 def filterWithError (p : T => Boolean , error : T => String , position : Input ): ParseResult [T ] =
149157 if (p(result)) this
@@ -192,10 +200,16 @@ trait Parsers {
192200 /** The toString method of a Failure yields an error message. */
193201 override def toString = " [" + next.pos+ " ] failure: " + msg+ " \n\n " + next.pos.longString
194202
195- def append [U >: Nothing ](a : => ParseResult [U ]): ParseResult [U ] = { val alt = a; alt match {
196- case Success (_, _) => alt
197- case ns : NoSuccess => if (alt.next.pos < next.pos) this else alt
198- }}
203+ def append [U >: Nothing ](a : => ParseResult [U ]): ParseResult [U ] = {
204+ val alt = a
205+
206+ alt match {
207+ case s @ Success (result, rest) =>
208+ val failure = selectLastFailure(Some (this ), s.lastFailure)
209+ Success (result, rest, failure)
210+ case ns : NoSuccess => if (alt.next.pos < next.pos) this else alt
211+ }
212+ }
199213 }
200214
201215 /** The fatal failure case of ParseResult: contains an error-message and
@@ -214,6 +228,19 @@ trait Parsers {
214228 def Parser [T ](f : Input => ParseResult [T ]): Parser [T ]
215229 = new Parser [T ]{ def apply (in : Input ) = f(in) }
216230
231+ private [combinator] def Success [U ](res : U , next : Input , failure : Option [Failure ]): ParseResult [U ] =
232+ new Success (res, next) { override val lastFailure : Option [Failure ] = failure }
233+
234+ private [combinator] def selectLastFailure (failure0 : Option [Failure ], failure1 : Option [Failure ]): Option [Failure ] =
235+ (failure0, failure1) match {
236+ case (Some (f0), Some (f1)) =>
237+ if (f0.next.pos < f1.next.pos) Some (f1)
238+ else Some (f0)
239+ case (Some (f0), _) => Some (f0)
240+ case (_, Some (f1)) => Some (f1)
241+ case _ => None
242+ }
243+
217244 def OnceParser [T ](f : Input => ParseResult [T ]): Parser [T ] with OnceParser [T ]
218245 = new Parser [T ] with OnceParser [T ] { def apply (in : Input ) = f(in) }
219246
@@ -634,7 +661,7 @@ trait Parsers {
634661 */
635662 def acceptIf (p : Elem => Boolean )(err : Elem => String ): Parser [Elem ] = Parser { in =>
636663 if (in.atEnd) Failure (" end of input" , in)
637- else if (p(in.first)) Success (in.first, in.rest)
664+ else if (p(in.first)) Success (in.first, in.rest, None )
638665 else Failure (err(in.first), in)
639666 }
640667
@@ -653,7 +680,7 @@ trait Parsers {
653680 */
654681 def acceptMatch [U ](expected : String , f : PartialFunction [Elem , U ]): Parser [U ] = Parser { in =>
655682 if (in.atEnd) Failure (" end of input" , in)
656- else if (f.isDefinedAt(in.first)) Success (f(in.first), in.rest)
683+ else if (f.isDefinedAt(in.first)) Success (f(in.first), in.rest, None )
657684 else Failure (expected+ " expected" , in)
658685 }
659686
@@ -686,7 +713,7 @@ trait Parsers {
686713 * @param v The result for the parser
687714 * @return A parser that always succeeds, with the given result `v`
688715 */
689- def success [T ](v : T ) = Parser { in => Success (v, in) }
716+ def success [T ](v : T ) = Parser { in => Success (v, in, None ) }
690717
691718 /** A helper method that turns a `Parser` into one that will
692719 * print debugging information to stdout before and after
@@ -751,19 +778,24 @@ trait Parsers {
751778 lazy val p = p0 // lazy argument
752779 val elems = new ListBuffer [T ]
753780
754- def continue (in : Input ): ParseResult [List [T ]] = {
781+ def continue (in : Input , failure : Option [ Failure ] ): ParseResult [List [T ]] = {
755782 val p0 = p // avoid repeatedly re-evaluating by-name parser
756- @ tailrec def applyp (in0 : Input ): ParseResult [List [T ]] = p0(in0) match {
757- case Success (x, rest) => elems += x ; applyp(rest)
783+ @ tailrec def applyp (in0 : Input , failure : Option [Failure ]): ParseResult [List [T ]] = p0(in0) match {
784+ case s @ Success (x, rest) =>
785+ val selectedFailure = selectLastFailure(s.lastFailure, failure)
786+ elems += x
787+ applyp(rest, selectedFailure)
758788 case e @ Error (_, _) => e // still have to propagate error
759- case _ => Success (elems.toList, in0)
789+ case f : Failure =>
790+ val selectedFailure = selectLastFailure(failure, Some (f))
791+ Success (elems.toList, in0, selectedFailure)
760792 }
761793
762- applyp(in)
794+ applyp(in, failure )
763795 }
764796
765797 first(in) match {
766- case Success (x, rest) => elems += x ; continue(rest)
798+ case s @ Success (x, rest) => elems += x ; continue(rest, s.lastFailure )
767799 case ns : NoSuccess => ns
768800 }
769801 }
@@ -783,14 +815,14 @@ trait Parsers {
783815 val elems = new ListBuffer [T ]
784816 val p0 = p // avoid repeatedly re-evaluating by-name parser
785817
786- @ tailrec def applyp (in0 : Input ): ParseResult [List [T ]] =
787- if (elems.length == num) Success (elems.toList, in0)
818+ @ tailrec def applyp (in0 : Input , failure : Option [ Failure ] ): ParseResult [List [T ]] =
819+ if (elems.length == num) Success (elems.toList, in0, failure )
788820 else p0(in0) match {
789- case Success (x, rest) => elems += x ; applyp(rest)
821+ case s @ Success (x, rest) => elems += x ; applyp(rest, s.lastFailure )
790822 case ns : NoSuccess => ns
791823 }
792824
793- applyp(in)
825+ applyp(in, None )
794826 }
795827
796828 /** A parser generator for non-empty repetitions.
@@ -872,7 +904,7 @@ trait Parsers {
872904 def not [T ](p : => Parser [T ]): Parser [Unit ] = Parser { in =>
873905 p(in) match {
874906 case Success (_, _) => Failure (" Expected failure" , in)
875- case _ => Success ((), in)
907+ case _ => Success ((), in, None )
876908 }
877909 }
878910
@@ -886,7 +918,7 @@ trait Parsers {
886918 */
887919 def guard [T ](p : => Parser [T ]): Parser [T ] = Parser { in =>
888920 p(in) match {
889- case s@ Success (s1,_) => Success (s1, in)
921+ case s@ Success (s1,_) => Success (s1, in, s.lastFailure )
890922 case e => e
891923 }
892924 }
@@ -901,7 +933,7 @@ trait Parsers {
901933 */
902934 def positioned [T <: Positional ](p : => Parser [T ]): Parser [T ] = Parser { in =>
903935 p(in) match {
904- case Success (t, in1) => Success (if (t.pos == NoPosition ) t setPos in.pos else t, in1)
936+ case s @ Success (t, in1) => Success (if (t.pos == NoPosition ) t setPos in.pos else t, in1, s.lastFailure )
905937 case ns : NoSuccess => ns
906938 }
907939 }
@@ -919,7 +951,10 @@ trait Parsers {
919951 def apply (in : Input ) = p(in) match {
920952 case s @ Success (out, in1) =>
921953 if (in1.atEnd) s
922- else Failure (" end of input expected" , in1)
954+ else s.lastFailure match {
955+ case Some (failure) => failure
956+ case _ => Failure (" end of input expected" , in1)
957+ }
923958 case ns => ns
924959 }
925960 }
0 commit comments