@@ -133,13 +133,21 @@ trait Parsers {
133
133
* @param next The parser's remaining input
134
134
*/
135
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)
136
+ def lastFailure : Option [Failure ] = None
140
137
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
+ }
143
151
144
152
def filterWithError (p : T => Boolean , error : T => String , position : Input ): ParseResult [T ] =
145
153
if (p(result)) this
@@ -188,10 +196,16 @@ trait Parsers {
188
196
/** The toString method of a Failure yields an error message. */
189
197
override def toString = " [" + next.pos+ " ] failure: " + msg+ " \n\n " + next.pos.longString
190
198
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
+ }
195
209
}
196
210
197
211
/** The fatal failure case of ParseResult: contains an error-message and
@@ -210,6 +224,19 @@ trait Parsers {
210
224
def Parser [T ](f : Input => ParseResult [T ]): Parser [T ]
211
225
= new Parser [T ]{ def apply (in : Input ) = f(in) }
212
226
227
+ private [combinator] def Success [U ](res : U , next : Input , failure : Option [Failure ]): Success [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
+
213
240
def OnceParser [T ](f : Input => ParseResult [T ]): Parser [T ] with OnceParser [T ]
214
241
= new Parser [T ] with OnceParser [T ] { def apply (in : Input ) = f(in) }
215
242
@@ -630,7 +657,7 @@ trait Parsers {
630
657
*/
631
658
def acceptIf (p : Elem => Boolean )(err : Elem => String ): Parser [Elem ] = Parser { in =>
632
659
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 )
634
661
else Failure (err(in.first), in)
635
662
}
636
663
@@ -649,7 +676,7 @@ trait Parsers {
649
676
*/
650
677
def acceptMatch [U ](expected : String , f : PartialFunction [Elem , U ]): Parser [U ] = Parser { in =>
651
678
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 )
653
680
else Failure (expected+ " expected" , in)
654
681
}
655
682
@@ -682,7 +709,7 @@ trait Parsers {
682
709
* @param v The result for the parser
683
710
* @return A parser that always succeeds, with the given result `v`
684
711
*/
685
- def success [T ](v : T ) = Parser { in => Success (v, in) }
712
+ def success [T ](v : T ) = Parser { in => Success (v, in, None ) }
686
713
687
714
/** A helper method that turns a `Parser` into one that will
688
715
* print debugging information to stdout before and after
@@ -747,19 +774,24 @@ trait Parsers {
747
774
lazy val p = p0 // lazy argument
748
775
val elems = new ListBuffer [T ]
749
776
750
- def continue (in : Input ): ParseResult [List [T ]] = {
777
+ def continue (in : Input , failure : Option [ Failure ] ): ParseResult [List [T ]] = {
751
778
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)
754
784
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)
756
788
}
757
789
758
- applyp(in)
790
+ applyp(in, failure )
759
791
}
760
792
761
793
first(in) match {
762
- case Success (x, rest) => elems += x ; continue(rest)
794
+ case s @ Success (x, rest) => elems += x ; continue(rest, s.lastFailure )
763
795
case ns : NoSuccess => ns
764
796
}
765
797
}
@@ -779,14 +811,14 @@ trait Parsers {
779
811
val elems = new ListBuffer [T ]
780
812
val p0 = p // avoid repeatedly re-evaluating by-name parser
781
813
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 )
784
816
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 )
786
818
case ns : NoSuccess => ns
787
819
}
788
820
789
- applyp(in)
821
+ applyp(in, None )
790
822
}
791
823
792
824
/** A parser generator for non-empty repetitions.
@@ -868,7 +900,7 @@ trait Parsers {
868
900
def not [T ](p : => Parser [T ]): Parser [Unit ] = Parser { in =>
869
901
p(in) match {
870
902
case Success (_, _) => Failure (" Expected failure" , in)
871
- case _ => Success ((), in)
903
+ case _ => Success ((), in, None )
872
904
}
873
905
}
874
906
@@ -882,7 +914,7 @@ trait Parsers {
882
914
*/
883
915
def guard [T ](p : => Parser [T ]): Parser [T ] = Parser { in =>
884
916
p(in) match {
885
- case s@ Success (s1,_) => Success (s1, in)
917
+ case s@ Success (s1,_) => Success (s1, in, s.lastFailure )
886
918
case e => e
887
919
}
888
920
}
@@ -897,7 +929,7 @@ trait Parsers {
897
929
*/
898
930
def positioned [T <: Positional ](p : => Parser [T ]): Parser [T ] = Parser { in =>
899
931
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 )
901
933
case ns : NoSuccess => ns
902
934
}
903
935
}
@@ -915,7 +947,10 @@ trait Parsers {
915
947
def apply (in : Input ) = p(in) match {
916
948
case s @ Success (out, in1) =>
917
949
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
+ }
919
954
case ns => ns
920
955
}
921
956
}
0 commit comments