parsers.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 961 行 · 第 1/3 页
SCALA
961 行
while(!these.isEmpty && in.first == these.head) { these = these.tail in = in.rest } if (these.isEmpty) Success((), in) else Failure("Expected: '"+these.head+"', found: '"+in.first+"'", in0) } } /** The parser that matches an element in the domain of the partial function `f' *<p> * If `f' is defined on the first element in the input, `f' is applied to it to produce * this parser's result.</p> *<p> * Example: The parser <code>accept("name", {case Identifier(n) => Name(n)})</code> * accepts an <code>Identifier(n)</code> and returns a <code>Name(n)</code>.</p> * * @param expected a description of the kind of element this parser expects (for error messages) * @param f a partial function that determines when this parser is successful and what its output is * @return A parser that succeeds if `f' is applicable to the first element of the input, * applying `f' to it to produce the result. */ def accept[U](expected: String, f: PartialFunction[Elem, U]): Parser[U] = new Parser[U] { def apply(in: Input) = if (f.isDefinedAt(in.first)) Success(f(in.first), in.rest) else Failure(expected+" expected", in) } /** A parser that always fails * * @param msg The error message describing the failure. * @return A parser that always fails with the specified error message. */ def failure(msg: String) = new Parser[Nothing] { def apply(in: Input) = Failure(msg, in) } /** A unit-parser that always fails * * @param msg The error message describing the failure. * @return A parser that always fails with the specified error message. */ def fail(msg: String) = new UnitParser { def apply(in: Input) = Failure(msg, in) } /** A parser that always succeeds * * @param v The result for the parser * @return A parser that always succeeds, with the given result `v' */ def success[T](v: T) = new Parser[T] { def apply(in: Input) = Success(v, in) } /** A unit-parser that always succeeds */ def success = new UnitParser { def apply(in: Input) = Success((), in) } /** A unit-parser that always succeeds, discarding `p's result * * @param p The parser whose result is to be discarded * @return A parser that always succeeds, with the empty result */ implicit def discard[T](p: => Parser[T]) = new UnitParser { def apply(in: Input) = p(in) map {(x) => ()} } def log[T](p: => Parser[T])(name: String): Parser[T] = new Parser[T] { def apply(in: Input) = {println("trying "+name+" at "+in.pos); val r = p(in); println(name+" --> "+r); r } } def log[Q <% UnitParser](p: => Q)(name: String): UnitParser = new UnitParser { def apply(in: Input) = {println("trying "+name+" at "+in.pos); val r = p(in); println(name+" --> "+r); r } } /** A parser generator for repetitions. * * <p> rep(p) repeatedly uses `p' to parse the input until `p' fails (the result is a List * of the consecutive results of `p') </p> * * @param p a `Parser' that is to be applied successively to the input * @return A parser that returns a list of results produced by repeatedly applying `p' to the input. */ def rep[T](p: => Parser[T]): Parser[List[T]] = rep1(p) | success(List()) /** A parser generator for repetitions. * * <p> rep(p) repeatedly uses `p' to parse the input until `p' fails</p> * * @param p a `Parser' that is to be applied successively to the input * @return A parser that repeatedly applies `p' to the input. */ def rep[Q <% UnitParser](p: => Q): UnitParser = rep1(p) | success /** A parser generator for interleaved repetitions. * * <p> repsep(p, q) repeatedly uses `p' interleaved with `q' to parse the input, until `p' fails. * (The result is a `List' of the results of `p'.) </p> * * <p>Example: <code>repsep(term, ",")</code> parses a comma-separated list of term's, * yielding a list of these terms</p> * * @param p a `Parser' that is to be applied successively to the input * @param q a `UnitParser' that parses the elements that separate the elements parsed by `p' * @return A parser that returns a list of results produced by repeatedly applying `p' (interleaved * with `q') to the input. */ def repsep[T, Q <% UnitParser](p: => Parser[T], q: => Q): Parser[List[T]] = rep1sep(p, q) | success(List()) /** A parser generator for non-empty repetitions. * * <p> rep1(p) repeatedly uses `p' to parse the input until `p' fails -- `p' must succeed at least * once (the result is a `List' of the consecutive results of `p')</p> * * @param p a `Parser' that is to be applied successively to the input * @return A parser that returns a list of results produced by repeatedly applying `p' to the input * (and that only succeeds if `p' matches at least once). */ def rep1[T](p: => Parser[T]): Parser[List[T]] = rep1(p, p) /** A parser generator for non-empty repetitions. * * <p> rep1(f, p) first uses `f' (which must succeed) and then repeatedly uses `p' to * parse the input until `p' fails * (the result is a `List' of the consecutive results of `f' and `p')</p> * * @param first a `Parser' that parses the first piece of input * @param p a `Parser' that is to be applied successively to the rest of the input (if any) * @return A parser that returns a list of results produced by first applying `f' and then * repeatedly `p' to the input (it only succeeds if `f' matches). */ def rep1[T](first: => Parser[T], p: => Parser[T]): Parser[List[T]] = first ~ rep(p) ^^ { case ~(x, xs) => x :: xs } /* new Parser[List[T]] { def apply(in0: Input) = { val xs = new scala.collection.mutable.ListBuffer[T] var in = in0 var res = first(in) while(res.successful) { xs += res.get in = res.next res = p(in) } if (!xs.isEmpty) Success(xs.toList, res.next) else Failure("TODO", TODO) } }*/ /** A parser generator for a specified number of repetitions. * * <p> repN(n, p) uses `p' exactly `n' time to parse the input * (the result is a `List' of the `n' consecutive results of `p')</p> * * @param p a `Parser' that is to be applied successively to the input * @param n the exact number of times `p' must succeed * @return A parser that returns a list of results produced by repeatedly applying `p' to the input * (and that only succeeds if `p' matches exactly `n' times). */ def repN[T](n: Int, p: => Parser[T]): Parser[List[T]] = if(n==0) success(Nil) else p ~ repN(n-1, p) ^^ { case ~(x, xs) => x :: xs } /** A parser generator for non-empty repetitions. * * <p> rep1(p) repeatedly uses `p' to parse the input until `p' fails -- `p' must succeed at least * once</p> * * @param p a `Parser' that is to be applied successively to the input * @return A unitparser that repeatedly applies `p' to the input * (and that only succeeds if `p' matches at least once). */ def rep1[Q <% UnitParser](p: => Q): UnitParser = p ~ rep(p) /** A parser generator for a specified number of repetitions. * * <p> repN(n, p) uses `p' exactly `n' time to parse the input</p> * * @param p a `Parser' that is to be applied successively to the input * @param n the exact number of times `p' must succeed * @return A unitparser that repeatedly applies `p' to the input * (and that only succeeds if `p' matches at exactly `n' times). */ def repN[Q <% UnitParser](n: Int, p: => Q): UnitParser = if(n==0) success else p ~ repN(n-1, p) /** A parser generator for non-empty repetitions. * * <p>rep1sep(first, p, q) starts by using `first', followed by repeatedly uses of `p' interleaved with `q' * to parse the input, until `p' fails. `first' must succeed (the result is a `List' of the * consecutive results of `first' and `p')</p> * * @param first a `Parser' that is to be applied to the first element of input * @param p a `Parser' that is to be applied successively to the input * @param q a `UnitParser' that parses the elements that separate the elements parsed by `p' * (interleaved with `q') * @return A parser that returns a list of results produced by repeatedly applying `p' to the input * (and that only succeeds if `p' matches at least once). */ def rep1sep[T, Q <% UnitParser](first: => Parser[T], p: => Parser[T], q: => Q): Parser[List[T]] = first ~ rep(q ~ p) ^^ { case x ~ y => x :: y } def rep1sep[T, Q <% UnitParser](p: => Parser[T], q: => Q): Parser[List[T]] = rep1sep(p, p, q) /** A parser generator that, roughly, generalises the rep1sep generator so that `q', which parses the separator, * produces a left-associative function that combines the elements it separates. * * <p> From: J. Fokker. Functional parsers. In J. Jeuring and E. Meijer, editors, Advanced Functional Programming, volume 925 of Lecture Notes in Computer Science, pages 1--23. Springer, 1995.</p> * * @param p a parser that parses the elements * @param q a parser that parses the token(s) separating the elements, yielding a left-associative function that * combines two elements into one */ def chainl1[T](p: => Parser[T], q: => Parser[(T, T) => T]): Parser[T] = p ~ rep(q ~ p) ^^ {case x ~ xs => xs.foldLeft(x)((a, f_b) => f_b._1(a, f_b._2))} // ((a, {f, b}) => f(a, b)) /** A parser generator that, roughly, generalises the rep1sep generator so that `q', which parses the separator, * produces a left-associative function that combines the elements it separates. * * @param first a parser that parses the first element * @param p a parser that parses the subsequent elements * @param q a parser that parses the token(s) separating the elements, yielding a left-associative function that * combines two elements into one */ def chainl1[T, U](first: => Parser[T], p: => Parser[U], q: => Parser[(T, U) => T]): Parser[T] = first ~ rep(q ~ p) ^^ {case x ~ xs => xs.foldLeft(x)((a, f_b) => f_b._1(a, f_b._2))} // ((a, {f, b}) => f(a, b)) /** A parser generator that generalises the rep1sep generator so that `q', which parses the separator, * produces a right-associative function that combines the elements it separates. Additionally, * The right-most (last) element and the left-most combinating function have to be supplied. * * rep1sep(p: Parser[T], q) corresponds to chainr1(p, q ^^ cons, cons, Nil) (where val cons = (x: T, y: List[T]) => x :: y) * * @param p a parser that parses the elements * @param q a parser that parses the token(s) separating the elements, yielding a right-associative function that * combines two elements into one * @param combine the "last" (left-most) combination function to be applied * @param first the "first" (right-most) element to be combined */ def chainr1[T, U](p: Parser[T], q: Parser[(T, U) => U], combine: (T, U) => U, first: U): Parser[U] = p ~ rep(q ~ p) ^^ {case x ~ xs => (new ~(combine, x) :: xs).foldRight(first)((f_a, b) => f_a._1(f_a._2, b))} // (({f, a}, b) => f(a, b)) /** A parser generator for optional sub-phrases. * * <p>opt(p) is a parser that returns `Some(x)' if `p' returns `x' and `None' if `p' fails</p> * * @param p A `Parser' that is tried on the input * @return a `Parser' that always succeeds: either with the result provided by `p' or * with the empty result */ def opt[T](p: => Parser[T]): Parser[Option[T]] = p ^^ (x => Some(x)) | success(None) /** Turns a unit-parser into a boolean-parser that denotes whether the unit-parser succeeded. */ def opt[Q <% UnitParser](q: => Q): Parser[Boolean] = q ^^ true | success(false) /** `positioned' decorates a parser's result with the start position of the input it consumed. * * @param p a `Parser' whose result conforms to `Positional'. * @return A parser that has the same behaviour as `p', but which marks its result with the * start position of the input it consumed, if it didn't already have a position. */ def positioned[T <: Positional](p: => Parser[T]): Parser[T] = new Parser[T] { def apply(in: Input) = p(in) match { case Success(t, in1) => Success(if (t.pos == NoPosition) t setPos in.pos else t, in1) case ns: NoSuccess => ns } } /** <code>positioned</code> decorates a unit-parser so that it returns the * start position of the input it consumed. * * @param p a `UnitParser'. * @return A parser that has the same behaviour as `p', but which returns * the start position of the input it consumed. */ def positioned[Q <% UnitParser](p: => Q) = new Parser[Position] { def apply(in: Input) = p(in) match { case Success(_, in1) => Success(in.pos, in1) case ns: NoSuccess => ns } } /** A parser whose ~ combinator disallows back-tracking. */ trait OnceParser[+T] extends Parser[T] { override def ~ [U](q: => Parser[U]): Parser[~[T, U]] = new Parser[~[T, U]] with OnceParser[~[T, U]] { def apply(in: Input) = seq(OnceParser.this, commit(q))((x, y) => new ~(x, y))(in) } override def ~ [Q <% UnitParser](q: => Q): Parser[T] = new Parser[T] with OnceParser[T] { def apply(in: Input) = seq(OnceParser.this, commit(q))((x, y) => x)(in) } } /** A parser whose ~ combinator disallows back-tracking. */ trait UnitOnceParser extends UnitParser { override def ~ [U](q: => Parser[U]): Parser[U] = new Parser[U] with OnceParser[U]{ def apply(in: Input): ParseResult[U] = seq(UnitOnceParser.this, commit(q))((x, y) => y)(in) } override def ~ [A <% UnitParser](q: => A): UnitParser = new UnitOnceParser { def apply(in: Input): ParseResult[Unit] = seq(UnitOnceParser.this, commit(q))((x, y) => y)(in) } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?