@@ -132,14 +132,22 @@ trait Parsers {
132132 * @param result The parser's output
133133 * @param next The parser's remaining input
134134 */
135- 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)
135+ abstract case class Success [+ T ](result : T , override val next : Input ) extends ParseResult [T ] {
136+ val lastFailure : Option [Failure ]
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 = s " [ ${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
@@ -629,7 +656,7 @@ trait Parsers {
629656 */
630657 def acceptIf (p : Elem => Boolean )(err : Elem => String ): Parser [Elem ] = Parser { in =>
631658 if (in.atEnd) Failure (" end of input" , in)
632- else if (p(in.first)) Success (in.first, in.rest)
659+ else if (p(in.first)) Success (in.first, in.rest, None )
633660 else Failure (err(in.first), in)
634661 }
635662
@@ -648,7 +675,7 @@ trait Parsers {
648675 */
649676 def acceptMatch [U ](expected : String , f : PartialFunction [Elem , U ]): Parser [U ] = Parser { in =>
650677 if (in.atEnd) Failure (" end of input" , in)
651- else if (f.isDefinedAt(in.first)) Success (f(in.first), in.rest)
678+ else if (f.isDefinedAt(in.first)) Success (f(in.first), in.rest, None )
652679 else Failure (expected+ " expected" , in)
653680 }
654681
@@ -683,7 +710,7 @@ trait Parsers {
683710 * @param v The result for the parser
684711 * @return A parser that always succeeds, with the given result `v`
685712 */
686- def success [T ](v : T ) = Parser { in => Success (v, in) }
713+ def success [T ](v : T ) = Parser { in => Success (v, in, None ) }
687714
688715 /** A helper method that turns a `Parser` into one that will
689716 * print debugging information to stdout before and after
@@ -748,19 +775,24 @@ trait Parsers {
748775 lazy val p = p0 // lazy argument
749776 val elems = new ListBuffer [T ]
750777
751- def continue (in : Input ): ParseResult [List [T ]] = {
778+ def continue (in : Input , failure : Option [ Failure ] ): ParseResult [List [T ]] = {
752779 val p0 = p // avoid repeatedly re-evaluating by-name parser
753- @ tailrec def applyp (in0 : Input ): ParseResult [List [T ]] = p0(in0) match {
754- case Success (x, rest) => elems += x ; applyp(rest)
780+ @ tailrec def applyp (in0 : Input , failure : Option [Failure ]): ParseResult [List [T ]] = p0(in0) match {
781+ case s @ Success (x, rest) =>
782+ val selectedFailure = selectLastFailure(s.lastFailure, failure)
783+ elems += x
784+ applyp(rest, selectedFailure)
755785 case e @ Error (_, _) => e // still have to propagate error
756- case _ => Success (elems.toList, in0)
786+ case f : Failure =>
787+ val selectedFailure = selectLastFailure(failure, Some (f))
788+ Success (elems.toList, in0, selectedFailure)
757789 }
758790
759- applyp(in)
791+ applyp(in, failure )
760792 }
761793
762794 first(in) match {
763- case Success (x, rest) => elems += x ; continue(rest)
795+ case s @ Success (x, rest) => elems += x ; continue(rest, s.lastFailure )
764796 case ns : NoSuccess => ns
765797 }
766798 }
@@ -780,14 +812,14 @@ trait Parsers {
780812 val elems = new ListBuffer [T ]
781813 val p0 = p // avoid repeatedly re-evaluating by-name parser
782814
783- @ tailrec def applyp (in0 : Input ): ParseResult [List [T ]] =
784- if (elems.length == num) Success (elems.toList, in0)
815+ @ tailrec def applyp (in0 : Input , failure : Option [ Failure ] ): ParseResult [List [T ]] =
816+ if (elems.length == num) Success (elems.toList, in0, failure )
785817 else p0(in0) match {
786- case Success (x, rest) => elems += x ; applyp(rest)
818+ case s @ Success (x, rest) => elems += x ; applyp(rest, s.lastFailure )
787819 case ns : NoSuccess => ns
788820 }
789821
790- applyp(in)
822+ applyp(in, None )
791823 }
792824
793825 /** A parser generator for a specified range of repetitions interleaved by a
@@ -812,9 +844,9 @@ trait Parsers {
812844 def continue (in : Input ): ParseResult [List [T ]] = {
813845 val p0 = sep ~> p // avoid repeatedly re-evaluating by-name parser
814846 @ tailrec def applyp (in0 : Input ): ParseResult [List [T ]] = p0(in0) match {
815- case Success (x, rest) => elems += x; if (elems.length == m) Success (elems.toList, rest) else applyp(rest)
847+ case Success (x, rest) => elems += x; if (elems.length == m) Success (elems.toList, rest, None ) else applyp(rest)
816848 case e @ Error (_, _) => e // still have to propagate error
817- case _ => Success (elems.toList, in0)
849+ case _ => Success (elems.toList, in0, None )
818850 }
819851
820852 applyp(in)
@@ -905,7 +937,7 @@ trait Parsers {
905937 def not [T ](p : => Parser [T ]): Parser [Unit ] = Parser { in =>
906938 p(in) match {
907939 case Success (_, _) => Failure (" Expected failure" , in)
908- case _ => Success ((), in)
940+ case _ => Success ((), in, None )
909941 }
910942 }
911943
@@ -919,7 +951,7 @@ trait Parsers {
919951 */
920952 def guard [T ](p : => Parser [T ]): Parser [T ] = Parser { in =>
921953 p(in) match {
922- case s@ Success (s1,_) => Success (s1, in)
954+ case s@ Success (s1,_) => Success (s1, in, s.lastFailure )
923955 case e => e
924956 }
925957 }
@@ -934,7 +966,7 @@ trait Parsers {
934966 */
935967 def positioned [T <: Positional ](p : => Parser [T ]): Parser [T ] = Parser { in =>
936968 p(in) match {
937- case Success (t, in1) => Success (if (t.pos == NoPosition ) t setPos in.pos else t, in1)
969+ case s @ Success (t, in1) => Success (if (t.pos == NoPosition ) t setPos in.pos else t, in1, s.lastFailure )
938970 case ns : NoSuccess => ns
939971 }
940972 }
@@ -952,7 +984,10 @@ trait Parsers {
952984 def apply (in : Input ) = p(in) match {
953985 case s @ Success (out, in1) =>
954986 if (in1.atEnd) s
955- else Failure (" end of input expected" , in1)
987+ else s.lastFailure match {
988+ case Some (failure) => failure
989+ case _ => Failure (" end of input expected" , in1)
990+ }
956991 case ns => ns
957992 }
958993 }
0 commit comments