@@ -137,13 +137,21 @@ trait Parsers {
137
137
* @param next The parser's remaining input
138
138
*/
139
139
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
144
141
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
+ }
147
155
148
156
def filterWithError (p : T => Boolean , error : T => String , position : Input ): ParseResult [T ] =
149
157
if (p(result)) this
@@ -192,10 +200,16 @@ trait Parsers {
192
200
/** The toString method of a Failure yields an error message. */
193
201
override def toString = " [" + next.pos+ " ] failure: " + msg+ " \n\n " + next.pos.longString
194
202
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
+ }
199
213
}
200
214
201
215
/** The fatal failure case of ParseResult: contains an error-message and
@@ -214,6 +228,19 @@ trait Parsers {
214
228
def Parser [T ](f : Input => ParseResult [T ]): Parser [T ]
215
229
= new Parser [T ]{ def apply (in : Input ) = f(in) }
216
230
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
+
217
244
def OnceParser [T ](f : Input => ParseResult [T ]): Parser [T ] with OnceParser [T ]
218
245
= new Parser [T ] with OnceParser [T ] { def apply (in : Input ) = f(in) }
219
246
@@ -634,7 +661,7 @@ trait Parsers {
634
661
*/
635
662
def acceptIf (p : Elem => Boolean )(err : Elem => String ): Parser [Elem ] = Parser { in =>
636
663
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 )
638
665
else Failure (err(in.first), in)
639
666
}
640
667
@@ -653,7 +680,7 @@ trait Parsers {
653
680
*/
654
681
def acceptMatch [U ](expected : String , f : PartialFunction [Elem , U ]): Parser [U ] = Parser { in =>
655
682
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 )
657
684
else Failure (expected+ " expected" , in)
658
685
}
659
686
@@ -686,7 +713,7 @@ trait Parsers {
686
713
* @param v The result for the parser
687
714
* @return A parser that always succeeds, with the given result `v`
688
715
*/
689
- def success [T ](v : T ) = Parser { in => Success (v, in) }
716
+ def success [T ](v : T ) = Parser { in => Success (v, in, None ) }
690
717
691
718
/** A helper method that turns a `Parser` into one that will
692
719
* print debugging information to stdout before and after
@@ -751,19 +778,24 @@ trait Parsers {
751
778
lazy val p = p0 // lazy argument
752
779
val elems = new ListBuffer [T ]
753
780
754
- def continue (in : Input ): ParseResult [List [T ]] = {
781
+ def continue (in : Input , failure : Option [ Failure ] ): ParseResult [List [T ]] = {
755
782
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)
758
788
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)
760
792
}
761
793
762
- applyp(in)
794
+ applyp(in, failure )
763
795
}
764
796
765
797
first(in) match {
766
- case Success (x, rest) => elems += x ; continue(rest)
798
+ case s @ Success (x, rest) => elems += x ; continue(rest, s.lastFailure )
767
799
case ns : NoSuccess => ns
768
800
}
769
801
}
@@ -783,14 +815,14 @@ trait Parsers {
783
815
val elems = new ListBuffer [T ]
784
816
val p0 = p // avoid repeatedly re-evaluating by-name parser
785
817
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 )
788
820
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 )
790
822
case ns : NoSuccess => ns
791
823
}
792
824
793
- applyp(in)
825
+ applyp(in, None )
794
826
}
795
827
796
828
/** A parser generator for non-empty repetitions.
@@ -872,7 +904,7 @@ trait Parsers {
872
904
def not [T ](p : => Parser [T ]): Parser [Unit ] = Parser { in =>
873
905
p(in) match {
874
906
case Success (_, _) => Failure (" Expected failure" , in)
875
- case _ => Success ((), in)
907
+ case _ => Success ((), in, None )
876
908
}
877
909
}
878
910
@@ -886,7 +918,7 @@ trait Parsers {
886
918
*/
887
919
def guard [T ](p : => Parser [T ]): Parser [T ] = Parser { in =>
888
920
p(in) match {
889
- case s@ Success (s1,_) => Success (s1, in)
921
+ case s@ Success (s1,_) => Success (s1, in, s.lastFailure )
890
922
case e => e
891
923
}
892
924
}
@@ -901,7 +933,7 @@ trait Parsers {
901
933
*/
902
934
def positioned [T <: Positional ](p : => Parser [T ]): Parser [T ] = Parser { in =>
903
935
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 )
905
937
case ns : NoSuccess => ns
906
938
}
907
939
}
@@ -919,7 +951,10 @@ trait Parsers {
919
951
def apply (in : Input ) = p(in) match {
920
952
case s @ Success (out, in1) =>
921
953
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
+ }
923
958
case ns => ns
924
959
}
925
960
}
0 commit comments