13
13
package scala
14
14
package util .parsing .combinator
15
15
16
+ import scala .util .DynamicVariable
16
17
import scala .util .parsing .input ._
17
18
import scala .collection .mutable .ListBuffer
18
19
import scala .annotation .tailrec
@@ -221,7 +222,7 @@ trait Parsers {
221
222
}
222
223
223
224
def Parser [T ](f :Input => ParseResult [T ]): Parser [T ]
224
- = new Parser [T ]{def apply (in :Input )= f(in) }
225
+ = new Parser [T ]{def parse (in :Input )= f(in) }
225
226
226
227
private [combinator]def Success [U ](res :U ,next :Input ,failure :Option [Failure ]): ParseResult [U ]=
227
228
new Success (res, next) {override val lastFailure : Option [Failure ]= failure }
@@ -236,8 +237,27 @@ trait Parsers {
236
237
case _=> None
237
238
}
238
239
240
+ val skipParser : DynamicVariable [Option [Parser [Any ]]]= new DynamicVariable (None );
241
+
242
+ final def skip (in :Input ): Input = {
243
+ skipParser.valuematch {
244
+ case None => in
245
+ case Some (parser)=> {
246
+ skipParser.withValue(None ) {
247
+ parser(in)match {
248
+ case Success (_,next)=> {
249
+ next
250
+ }
251
+ // A parser whose purpose is to skip shouldn't fail; it should just not skip stuff
252
+ case _=> in
253
+ }
254
+ }
255
+ }
256
+ }
257
+ }
258
+
239
259
def OnceParser [T ](f :Input => ParseResult [T ]): Parser [T ]with OnceParser [T ]
240
- = new Parser [T ]with OnceParser [T ] {def apply (in :Input )= f(in) }
260
+ = new Parser [T ]with OnceParser [T ] {def parse (in :Input )= f(in) }
241
261
242
262
/** The root class of parsers.
243
263
* Parsers are functions from the Input type to ParseResult.
@@ -248,7 +268,10 @@ trait Parsers {
248
268
override def toString = s " Parser ( $name) "
249
269
250
270
/** An unspecified method that defines the behaviour of this parser.*/
251
- def apply (in :Input ): ParseResult [T ]
271
+ def parse (in :Input ): ParseResult [T ]
272
+ def apply (in :Input ): ParseResult [T ]= {
273
+ parse(skip(in))
274
+ }
252
275
253
276
def flatMap [U ](f :T => Parser [U ]): Parser [U ]
254
277
= Parser { in=> this (in) flatMapWithNext(f)}
@@ -268,6 +291,20 @@ trait Parsers {
268
291
Parser { in=> this (in) append p(in)}
269
292
}
270
293
294
+ /** A parser combinator that changes skipping behavior
295
+ */
296
+ def << (toSkip :=> Option [Parser [Any ]]): Parser [T ]= {
297
+ val originalParse : Input => ParseResult [T ]= parse
298
+ new Parser [T ] {
299
+ override def apply (in :Input ): ParseResult [T ]= {
300
+ skipParser.withValue(toSkip) {
301
+ parse(skip(in))
302
+ }
303
+ }
304
+ def parse (in :Input ): ParseResult [T ]= originalParse(in)
305
+ }.named(name)
306
+ }
307
+
271
308
// the operator formerly known as +++, ++, &, but now, behold the venerable ~
272
309
// it's short, light (looks like whitespace), has few overloaded meaning (thanks to the recent change from ~ to unary_~)
273
310
// and we love it! (or do we like `,` better?)
@@ -324,7 +361,7 @@ trait Parsers {
324
361
325
362
/* not really useful: V cannot be inferred because Parser is covariant in first type parameter (V is always trivially Nothing)
326
363
def ~~ [U, V](q: => Parser[U])(implicit combine: (T, U) => V): Parser[V] = new Parser[V] {
327
- defapply (in: Input) = seq(Parser.this, q)((x, y) => combine(x,y))(in)
364
+ defparse (in: Input) = seq(Parser.this, q)((x, y) => combine(x,y))(in)
328
365
}*/
329
366
330
367
/** A parser combinator for non-back-tracking sequential composition.
@@ -391,7 +428,7 @@ trait Parsers {
391
428
*/
392
429
def ||| [U >: T ](q0 :=> Parser [U ]): Parser [U ]= new Parser [U ] {
393
430
lazy val q = q0// lazy argument
394
- def apply (in :Input )= {
431
+ def parse (in :Input )= {
395
432
val res1 = Parser .this (in)
396
433
val res2 = q(in)
397
434
@@ -427,7 +464,7 @@ trait Parsers {
427
464
*/
428
465
def ^^^ [U ](v :=> U ): Parser [U ]= new Parser [U ] {
429
466
lazy val v0 = v// lazy argument
430
- def apply (in :Input )= Parser .this (in) map (x=> v0)
467
+ def parse (in :Input )= Parser .this (in) map (x=> v0)
431
468
}.named(toString+ " ^^^" )
432
469
433
470
/** A parser combinator for partial function application.
@@ -769,18 +806,18 @@ trait Parsers {
769
806
770
807
def continue (in :Input ,failure :Option [Failure ]): ParseResult [List [T ]]= {
771
808
val p0 = p// avoid repeatedly re-evaluating by-name parser
772
- @ tailrecdef applyp (in0 :Input ,failure :Option [Failure ]): ParseResult [List [T ]]= p0(in0)match {
809
+ @ tailrecdef parsep (in0 :Input ,failure :Option [Failure ]): ParseResult [List [T ]]= p0(in0)match {
773
810
case s@ Success (x, rest)=>
774
811
val selectedFailure = selectLastFailure(s.lastFailure, failure)
775
812
elems+= x
776
- applyp (rest, selectedFailure)
813
+ parsep (rest, selectedFailure)
777
814
case e@ Error (_, _)=> e// still have to propagate error
778
815
case f :Failure =>
779
816
val selectedFailure = selectLastFailure(failure,Some (f))
780
817
Success (elems.toList, in0, selectedFailure)
781
818
}
782
819
783
- applyp (in, failure)
820
+ parsep (in, failure)
784
821
}
785
822
786
823
first(in)match {
@@ -804,14 +841,14 @@ trait Parsers {
804
841
val elems = new ListBuffer [T ]
805
842
val p0 = p// avoid repeatedly re-evaluating by-name parser
806
843
807
- @ tailrecdef applyp (in0 :Input ,failure :Option [Failure ]): ParseResult [List [T ]]=
844
+ @ tailrecdef parsep (in0 :Input ,failure :Option [Failure ]): ParseResult [List [T ]]=
808
845
if (elems.length== num)Success (elems.toList, in0, failure)
809
846
else p0(in0)match {
810
- case s@ Success (x, rest)=> elems+= x ;applyp (rest, s.lastFailure)
847
+ case s@ Success (x, rest)=> elems+= x ;parsep (rest, s.lastFailure)
811
848
case ns :NoSuccess => ns
812
849
}
813
850
814
- applyp (in,None )
851
+ parsep (in,None )
815
852
}
816
853
817
854
/** A parser generator for a specified range of repetitions interleaved by a
@@ -835,13 +872,13 @@ trait Parsers {
835
872
836
873
def continue (in :Input ): ParseResult [List [T ]]= {
837
874
val p0 = sep~> p// avoid repeatedly re-evaluating by-name parser
838
- @ tailrecdef applyp (in0 :Input ): ParseResult [List [T ]]= p0(in0)match {
839
- case Success (x, rest)=> elems+= x;if (elems.length== m)Success (elems.toList, rest,None )else applyp (rest)
875
+ @ tailrecdef parsep (in0 :Input ): ParseResult [List [T ]]= p0(in0)match {
876
+ case Success (x, rest)=> elems+= x;if (elems.length== m)Success (elems.toList, rest,None )else parsep (rest)
840
877
case e@ Error (_, _)=> e// still have to propagate error
841
878
case _=> Success (elems.toList, in0,None )
842
879
}
843
880
844
- applyp (in)
881
+ parsep (in)
845
882
}
846
883
847
884
mandatory(in)match {
@@ -973,7 +1010,7 @@ trait Parsers {
973
1010
* if `p` consumed all the input.
974
1011
*/
975
1012
def phrase [T ](p :Parser [T ])= new Parser [T ] {
976
- def apply (in :Input )= p(in)match {
1013
+ def parse (in :Input )= p(in)match {
977
1014
case s@ Success (out, in1)=>
978
1015
if (in1.atEnd) s
979
1016
else s.lastFailurematch {