2010-12-07 01:48:49 +01:00
|
|
|
/* sbt -- Simple Build Tool
|
2011-01-22 20:01:59 +01:00
|
|
|
* Copyright 2008, 2010, 2011 Mark Harrah
|
2010-12-07 01:48:49 +01:00
|
|
|
*/
|
2011-01-22 20:01:59 +01:00
|
|
|
package sbt.complete
|
2010-12-07 01:48:49 +01:00
|
|
|
|
|
|
|
|
import Parser._
|
2011-04-19 23:58:05 +02:00
|
|
|
import sbt.Types.{left, right, some}
|
2010-12-07 01:48:49 +01:00
|
|
|
|
|
|
|
|
sealed trait Parser[+T]
|
|
|
|
|
{
|
|
|
|
|
def derive(i: Char): Parser[T]
|
|
|
|
|
def resultEmpty: Option[T]
|
|
|
|
|
def result: Option[T] = None
|
|
|
|
|
def completions: Completions
|
2011-01-22 20:01:59 +01:00
|
|
|
def valid: Boolean
|
2010-12-07 01:48:49 +01:00
|
|
|
def isTokenStart = false
|
|
|
|
|
}
|
|
|
|
|
sealed trait RichParser[A]
|
|
|
|
|
{
|
|
|
|
|
/** Produces a Parser that applies the original Parser and then applies `next` (in order).*/
|
|
|
|
|
def ~[B](next: Parser[B]): Parser[(A,B)]
|
|
|
|
|
/** Produces a Parser that applies the original Parser one or more times.*/
|
|
|
|
|
def + : Parser[Seq[A]]
|
|
|
|
|
/** Produces a Parser that applies the original Parser zero or more times.*/
|
|
|
|
|
def * : Parser[Seq[A]]
|
|
|
|
|
/** Produces a Parser that applies the original Parser zero or one times.*/
|
|
|
|
|
def ? : Parser[Option[A]]
|
2011-02-21 16:00:40 +01:00
|
|
|
/** Produces a Parser that applies either the original Parser or `b`.*/
|
2010-12-09 04:16:12 +01:00
|
|
|
def |[B >: A](b: Parser[B]): Parser[B]
|
2011-02-21 16:00:40 +01:00
|
|
|
/** Produces a Parser that applies either the original Parser or `b`.*/
|
2010-12-09 04:16:12 +01:00
|
|
|
def ||[B](b: Parser[B]): Parser[Either[A,B]]
|
2010-12-07 01:48:49 +01:00
|
|
|
/** Produces a Parser that applies the original Parser to the input and then applies `f` to the result.*/
|
|
|
|
|
def map[B](f: A => B): Parser[B]
|
|
|
|
|
/** Returns the original parser. This is useful for converting literals to Parsers.
|
|
|
|
|
* For example, `'c'.id` or `"asdf".id`*/
|
|
|
|
|
def id: Parser[A]
|
2010-12-09 04:16:12 +01:00
|
|
|
|
2010-12-14 04:44:25 +01:00
|
|
|
def ^^^[B](value: B): Parser[B]
|
|
|
|
|
def ??[B >: A](alt: B): Parser[B]
|
|
|
|
|
def <~[B](b: Parser[B]): Parser[A]
|
|
|
|
|
def ~>[B](b: Parser[B]): Parser[B]
|
|
|
|
|
|
2010-12-09 04:16:12 +01:00
|
|
|
def unary_- : Parser[Unit]
|
|
|
|
|
def & (o: Parser[_]): Parser[A]
|
|
|
|
|
def - (o: Parser[_]): Parser[A]
|
|
|
|
|
/** Explicitly defines the completions for the original Parser.*/
|
|
|
|
|
def examples(s: String*): Parser[A]
|
|
|
|
|
/** Explicitly defines the completions for the original Parser.*/
|
2011-03-25 02:22:09 +01:00
|
|
|
def examples(s: Set[String], check: Boolean = false): Parser[A]
|
2010-12-09 04:16:12 +01:00
|
|
|
/** Converts a Parser returning a Char sequence to a Parser returning a String.*/
|
|
|
|
|
def string(implicit ev: A <:< Seq[Char]): Parser[String]
|
|
|
|
|
/** Produces a Parser that filters the original parser.
|
|
|
|
|
* If 'f' is not true when applied to the output of the original parser, the Parser returned by this method fails.*/
|
|
|
|
|
def filter(f: A => Boolean): Parser[A]
|
|
|
|
|
|
|
|
|
|
def flatMap[B](f: A => Parser[B]): Parser[B]
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
2011-01-22 20:01:59 +01:00
|
|
|
object Parser extends ParserMain
|
2010-12-07 01:48:49 +01:00
|
|
|
{
|
2010-12-09 04:16:12 +01:00
|
|
|
def checkMatches(a: Parser[_], completions: Seq[String])
|
|
|
|
|
{
|
|
|
|
|
val bad = completions.filter( apply(a)(_).resultEmpty.isEmpty)
|
|
|
|
|
if(!bad.isEmpty) error("Invalid example completions: " + bad.mkString("'", "', '", "'"))
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-07 01:48:49 +01:00
|
|
|
def mapParser[A,B](a: Parser[A], f: A => B): Parser[B] =
|
|
|
|
|
if(a.valid) {
|
|
|
|
|
a.result match
|
|
|
|
|
{
|
|
|
|
|
case Some(av) => success( f(av) )
|
|
|
|
|
case None => new MapParser(a, f)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else Invalid
|
|
|
|
|
|
2010-12-09 04:16:12 +01:00
|
|
|
def bindParser[A,B](a: Parser[A], f: A => Parser[B]): Parser[B] =
|
|
|
|
|
if(a.valid) {
|
|
|
|
|
a.result match
|
|
|
|
|
{
|
|
|
|
|
case Some(av) => f(av)
|
|
|
|
|
case None => new BindParser(a, f)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else Invalid
|
|
|
|
|
|
|
|
|
|
def filterParser[T](a: Parser[T], f: T => Boolean): Parser[T] =
|
|
|
|
|
if(a.valid) {
|
|
|
|
|
a.result match
|
|
|
|
|
{
|
2011-01-22 21:01:10 +01:00
|
|
|
case Some(av) => if( f(av) ) success( av ) else Invalid
|
2010-12-09 04:16:12 +01:00
|
|
|
case None => new Filter(a, f)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else Invalid
|
|
|
|
|
|
2010-12-07 01:48:49 +01:00
|
|
|
def seqParser[A,B](a: Parser[A], b: Parser[B]): Parser[(A,B)] =
|
2011-01-22 20:01:59 +01:00
|
|
|
if(a.valid && b.valid)
|
2010-12-07 01:48:49 +01:00
|
|
|
(a.result, b.result) match {
|
2011-01-22 21:01:10 +01:00
|
|
|
case (Some(av), Some(bv)) => success( (av, bv) )
|
2010-12-07 01:48:49 +01:00
|
|
|
case (Some(av), None) => b map { bv => (av, bv) }
|
|
|
|
|
case (None, Some(bv)) => a map { av => (av, bv) }
|
|
|
|
|
case (None, None) => new SeqParser(a,b)
|
|
|
|
|
}
|
|
|
|
|
else Invalid
|
|
|
|
|
|
|
|
|
|
def choiceParser[A,B](a: Parser[A], b: Parser[B]): Parser[Either[A,B]] =
|
2010-12-09 04:16:12 +01:00
|
|
|
if(a.valid)
|
2011-04-19 23:58:05 +02:00
|
|
|
if(b.valid) new HetParser(a,b) else a.map( left.fn )
|
2010-12-07 01:48:49 +01:00
|
|
|
else
|
2011-04-19 23:58:05 +02:00
|
|
|
b.map( right.fn )
|
2010-12-09 04:16:12 +01:00
|
|
|
|
2010-12-07 01:48:49 +01:00
|
|
|
def opt[T](a: Parser[T]): Parser[Option[T]] =
|
2011-01-22 21:01:10 +01:00
|
|
|
if(a.valid) new Optional(a) else success(None)
|
2010-12-07 01:48:49 +01:00
|
|
|
|
|
|
|
|
def zeroOrMore[T](p: Parser[T]): Parser[Seq[T]] = repeat(p, 0, Infinite)
|
|
|
|
|
def oneOrMore[T](p: Parser[T]): Parser[Seq[T]] = repeat(p, 1, Infinite)
|
|
|
|
|
|
|
|
|
|
def repeat[T](p: Parser[T], min: Int = 0, max: UpperBound = Infinite): Parser[Seq[T]] =
|
|
|
|
|
repeat(None, p, min, max, Nil)
|
2011-01-22 20:01:59 +01:00
|
|
|
private[complete] def repeat[T](partial: Option[Parser[T]], repeated: Parser[T], min: Int, max: UpperBound, revAcc: List[T]): Parser[Seq[T]] =
|
2010-12-07 01:48:49 +01:00
|
|
|
{
|
2010-12-09 04:16:12 +01:00
|
|
|
assume(min >= 0, "Minimum must be greater than or equal to zero (was " + min + ")")
|
|
|
|
|
assume(max >= min, "Minimum must be less than or equal to maximum (min: " + min + ", max: " + max + ")")
|
|
|
|
|
|
2010-12-07 01:48:49 +01:00
|
|
|
def checkRepeated(invalidButOptional: => Parser[Seq[T]]): Parser[Seq[T]] =
|
|
|
|
|
if(repeated.valid)
|
|
|
|
|
repeated.result match
|
|
|
|
|
{
|
2011-01-22 21:01:10 +01:00
|
|
|
case Some(value) => success(revAcc reverse_::: value :: Nil) // revAcc should be Nil here
|
|
|
|
|
case None => if(max.isZero) success(revAcc.reverse) else new Repeat(partial, repeated, min, max, revAcc)
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
|
|
|
|
else if(min == 0)
|
|
|
|
|
invalidButOptional
|
|
|
|
|
else
|
|
|
|
|
Invalid
|
|
|
|
|
|
|
|
|
|
partial match
|
|
|
|
|
{
|
|
|
|
|
case Some(part) =>
|
|
|
|
|
if(part.valid)
|
|
|
|
|
part.result match
|
|
|
|
|
{
|
|
|
|
|
case Some(value) => repeat(None, repeated, min, max, value :: revAcc)
|
|
|
|
|
case None => checkRepeated(part.map(lv => (lv :: revAcc).reverse))
|
|
|
|
|
}
|
|
|
|
|
else Invalid
|
2011-01-22 21:01:10 +01:00
|
|
|
case None => checkRepeated(success(Nil))
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-22 20:01:59 +01:00
|
|
|
def sub[T](a: Parser[T], b: Parser[_]): Parser[T] = and(a, not(b))
|
|
|
|
|
|
|
|
|
|
def and[T](a: Parser[T], b: Parser[_]): Parser[T] = if(a.valid && b.valid) new And(a, b) else Invalid
|
|
|
|
|
}
|
|
|
|
|
trait ParserMain
|
|
|
|
|
{
|
|
|
|
|
implicit def richParser[A](a: Parser[A]): RichParser[A] = new RichParser[A]
|
|
|
|
|
{
|
|
|
|
|
def ~[B](b: Parser[B]) = seqParser(a, b)
|
|
|
|
|
def ||[B](b: Parser[B]) = choiceParser(a,b)
|
|
|
|
|
def |[B >: A](b: Parser[B]) = homParser(a,b)
|
|
|
|
|
def ? = opt(a)
|
|
|
|
|
def * = zeroOrMore(a)
|
|
|
|
|
def + = oneOrMore(a)
|
|
|
|
|
def map[B](f: A => B) = mapParser(a, f)
|
|
|
|
|
def id = a
|
|
|
|
|
|
|
|
|
|
def ^^^[B](value: B): Parser[B] = a map { _ => value }
|
|
|
|
|
def ??[B >: A](alt: B): Parser[B] = a.? map { _ getOrElse alt }
|
|
|
|
|
def <~[B](b: Parser[B]): Parser[A] = (a ~ b) map { case av ~ _ => av }
|
|
|
|
|
def ~>[B](b: Parser[B]): Parser[B] = (a ~ b) map { case _ ~ bv => bv }
|
|
|
|
|
|
|
|
|
|
def unary_- = not(a)
|
|
|
|
|
def & (o: Parser[_]) = and(a, o)
|
|
|
|
|
def - (o: Parser[_]) = sub(a, o)
|
|
|
|
|
def examples(s: String*): Parser[A] = examples(s.toSet)
|
2011-03-25 02:22:09 +01:00
|
|
|
def examples(s: Set[String], check: Boolean = false): Parser[A] = Parser.examples(a, s, check)
|
2011-01-22 20:01:59 +01:00
|
|
|
def filter(f: A => Boolean): Parser[A] = filterParser(a, f)
|
|
|
|
|
def string(implicit ev: A <:< Seq[Char]): Parser[String] = map(_.mkString)
|
|
|
|
|
def flatMap[B](f: A => Parser[B]) = bindParser(a, f)
|
|
|
|
|
}
|
|
|
|
|
implicit def literalRichParser(c: Char): RichParser[Char] = richParser(c)
|
|
|
|
|
implicit def literalRichParser(s: String): RichParser[String] = richParser(s)
|
|
|
|
|
|
|
|
|
|
def failure[T](msg: String): Parser[T] = Invalid(msg)
|
2011-01-22 21:01:10 +01:00
|
|
|
def success[T](value: T): Parser[T] = new ValidParser[T] {
|
|
|
|
|
override def result = Some(value)
|
2010-12-07 01:48:49 +01:00
|
|
|
def resultEmpty = result
|
|
|
|
|
def derive(c: Char) = Invalid
|
|
|
|
|
def completions = Completions.empty
|
2011-01-22 21:01:10 +01:00
|
|
|
override def toString = "success(" + value + ")"
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
|
|
|
|
|
2010-12-09 04:16:12 +01:00
|
|
|
implicit def range(r: collection.immutable.NumericRange[Char]): Parser[Char] =
|
|
|
|
|
new CharacterClass(r contains _).examples(r.map(_.toString) : _*)
|
|
|
|
|
def chars(legal: String): Parser[Char] =
|
|
|
|
|
{
|
|
|
|
|
val set = legal.toSet
|
|
|
|
|
new CharacterClass(set) examples(set.map(_.toString))
|
|
|
|
|
}
|
2010-12-07 01:48:49 +01:00
|
|
|
def charClass(f: Char => Boolean): Parser[Char] = new CharacterClass(f)
|
2010-12-14 04:44:25 +01:00
|
|
|
|
2011-01-22 20:01:59 +01:00
|
|
|
implicit def literal(ch: Char): Parser[Char] = new ValidParser[Char] {
|
2010-12-07 01:48:49 +01:00
|
|
|
def resultEmpty = None
|
2011-01-22 21:01:10 +01:00
|
|
|
def derive(c: Char) = if(c == ch) success(ch) else Invalid
|
2010-12-14 04:44:25 +01:00
|
|
|
def completions = Completions.single(Completion.suggestStrict(ch.toString))
|
|
|
|
|
override def toString = "'" + ch + "'"
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
2011-04-19 23:58:05 +02:00
|
|
|
implicit def literal(s: String): Parser[String] = stringLiteral(s, 0)
|
2010-12-14 04:44:25 +01:00
|
|
|
object ~ {
|
|
|
|
|
def unapply[A,B](t: (A,B)): Some[(A,B)] = Some(t)
|
|
|
|
|
}
|
2011-01-22 20:01:59 +01:00
|
|
|
|
|
|
|
|
// intended to be temporary pending proper error feedback
|
|
|
|
|
def result[T](p: Parser[T], s: String): Either[(String,Int), T] =
|
|
|
|
|
{
|
2011-02-19 02:57:39 +01:00
|
|
|
def loop(i: Int, a: Parser[T]): Either[(String,Int), T] =
|
|
|
|
|
if(a.valid)
|
2011-01-22 20:01:59 +01:00
|
|
|
{
|
2011-02-19 02:57:39 +01:00
|
|
|
val ci = i+1
|
|
|
|
|
if(ci >= s.length)
|
|
|
|
|
a.resultEmpty.toRight(("Unexpected end of input", ci))
|
|
|
|
|
else
|
|
|
|
|
loop(ci, a derive s(ci) )
|
2011-01-22 20:01:59 +01:00
|
|
|
}
|
2011-02-19 02:57:39 +01:00
|
|
|
else
|
|
|
|
|
Left(("Parse error",i))
|
|
|
|
|
loop(-1, p)
|
2011-01-22 20:01:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def apply[T](p: Parser[T])(s: String): Parser[T] =
|
|
|
|
|
(p /: s)(derive1)
|
|
|
|
|
|
|
|
|
|
def derive1[T](p: Parser[T], c: Char): Parser[T] =
|
|
|
|
|
if(p.valid) p.derive(c) else p
|
|
|
|
|
|
|
|
|
|
// The x Completions.empty removes any trailing token completions where append.isEmpty
|
|
|
|
|
def completions(p: Parser[_], s: String): Completions = apply(p)(s).completions x Completions.empty
|
|
|
|
|
|
|
|
|
|
def examples[A](a: Parser[A], completions: Set[String], check: Boolean = false): Parser[A] =
|
|
|
|
|
if(a.valid) {
|
|
|
|
|
a.result match
|
|
|
|
|
{
|
2011-01-22 21:01:10 +01:00
|
|
|
case Some(av) => success( av )
|
2011-01-22 20:01:59 +01:00
|
|
|
case None =>
|
|
|
|
|
if(check) checkMatches(a, completions.toSeq)
|
|
|
|
|
new Examples(a, completions)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else a
|
|
|
|
|
|
2011-04-20 04:20:16 +02:00
|
|
|
def matched(t: Parser[_], seen: Vector[Char] = Vector.empty, partial: Boolean = false): Parser[String] =
|
2011-01-22 20:01:59 +01:00
|
|
|
if(!t.valid)
|
2011-04-19 23:58:05 +02:00
|
|
|
if(partial && !seen.isEmpty) success(seen.mkString) else Invalid
|
2011-01-22 20:01:59 +01:00
|
|
|
else if(t.result.isEmpty)
|
2011-04-19 23:58:05 +02:00
|
|
|
new MatchedString(t, seen, partial)
|
2011-01-22 20:01:59 +01:00
|
|
|
else
|
2011-04-19 23:58:05 +02:00
|
|
|
success(seen.mkString)
|
2011-01-22 20:01:59 +01:00
|
|
|
|
|
|
|
|
def token[T](t: Parser[T]): Parser[T] = token(t, "", true)
|
|
|
|
|
def token[T](t: Parser[T], description: String): Parser[T] = token(t, description, false)
|
|
|
|
|
def token[T](t: Parser[T], seen: String, track: Boolean): Parser[T] =
|
|
|
|
|
if(t.valid && !t.isTokenStart)
|
|
|
|
|
if(t.result.isEmpty) new TokenStart(t, seen, track) else t
|
|
|
|
|
else
|
|
|
|
|
t
|
|
|
|
|
|
|
|
|
|
def homParser[A](a: Parser[A], b: Parser[A]): Parser[A] =
|
|
|
|
|
if(a.valid)
|
|
|
|
|
if(b.valid) new HomParser(a, b) else a
|
|
|
|
|
else
|
|
|
|
|
b
|
|
|
|
|
|
|
|
|
|
def not(p: Parser[_]): Parser[Unit] = new Not(p)
|
|
|
|
|
|
2011-02-21 16:00:40 +01:00
|
|
|
def seq[T](p: Seq[Parser[T]]): Parser[Seq[T]] =
|
|
|
|
|
{
|
|
|
|
|
val valid = p.filter(_.valid)
|
|
|
|
|
if(valid.isEmpty) failure("") else new ParserSeq(valid)
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-19 23:58:05 +02:00
|
|
|
def stringLiteral(s: String, start: Int): Parser[String] =
|
|
|
|
|
{
|
|
|
|
|
val len = s.length
|
|
|
|
|
if(len == 0) error("String literal cannot be empty") else if(start >= len) success(s) else new StringLiteral(s, start)
|
|
|
|
|
}
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
2011-01-22 20:01:59 +01:00
|
|
|
sealed trait ValidParser[T] extends Parser[T]
|
|
|
|
|
{
|
|
|
|
|
final def valid = true
|
|
|
|
|
}
|
|
|
|
|
private object Invalid extends Invalid("inv")
|
|
|
|
|
private sealed case class Invalid(val message: String) extends Parser[Nothing]
|
2010-12-07 01:48:49 +01:00
|
|
|
{
|
|
|
|
|
def resultEmpty = None
|
|
|
|
|
def derive(c: Char) = error("Invalid.")
|
|
|
|
|
override def valid = false
|
2010-12-09 04:16:12 +01:00
|
|
|
def completions = Completions.nil
|
2011-01-22 20:01:59 +01:00
|
|
|
override def toString = message
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
2011-01-22 20:01:59 +01:00
|
|
|
private final class SeqParser[A,B](a: Parser[A], b: Parser[B]) extends ValidParser[(A,B)]
|
2010-12-07 01:48:49 +01:00
|
|
|
{
|
|
|
|
|
def cross(ao: Option[A], bo: Option[B]): Option[(A,B)] = for(av <- ao; bv <- bo) yield (av,bv)
|
|
|
|
|
lazy val resultEmpty = cross(a.resultEmpty, b.resultEmpty)
|
|
|
|
|
def derive(c: Char) =
|
|
|
|
|
{
|
|
|
|
|
val common = a.derive(c) ~ b
|
|
|
|
|
a.resultEmpty match
|
|
|
|
|
{
|
2010-12-09 04:16:12 +01:00
|
|
|
case Some(av) => common | b.derive(c).map(br => (av,br))
|
2010-12-07 01:48:49 +01:00
|
|
|
case None => common
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lazy val completions = a.completions x b.completions
|
2010-12-14 04:44:25 +01:00
|
|
|
override def toString = "(" + a + " ~ " + b + ")"
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
|
|
|
|
|
2011-01-22 20:01:59 +01:00
|
|
|
private final class HomParser[A](a: Parser[A], b: Parser[A]) extends ValidParser[A]
|
2010-12-07 01:48:49 +01:00
|
|
|
{
|
2010-12-09 04:16:12 +01:00
|
|
|
def derive(c: Char) = (a derive c) | (b derive c)
|
2010-12-07 01:48:49 +01:00
|
|
|
lazy val resultEmpty = a.resultEmpty orElse b.resultEmpty
|
|
|
|
|
lazy val completions = a.completions ++ b.completions
|
2010-12-14 04:44:25 +01:00
|
|
|
override def toString = "(" + a + " | " + b + ")"
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
2011-01-22 20:01:59 +01:00
|
|
|
private final class HetParser[A,B](a: Parser[A], b: Parser[B]) extends ValidParser[Either[A,B]]
|
2010-12-07 01:48:49 +01:00
|
|
|
{
|
2010-12-09 04:16:12 +01:00
|
|
|
def derive(c: Char) = (a derive c) || (b derive c)
|
2011-04-19 23:58:05 +02:00
|
|
|
lazy val resultEmpty = a.resultEmpty.map(left.fn) orElse b.resultEmpty.map(right.fn)
|
2010-12-07 01:48:49 +01:00
|
|
|
lazy val completions = a.completions ++ b.completions
|
2010-12-14 04:44:25 +01:00
|
|
|
override def toString = "(" + a + " || " + b + ")"
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
2011-02-21 16:00:40 +01:00
|
|
|
private final class ParserSeq[T](a: Seq[Parser[T]]) extends ValidParser[Seq[T]]
|
|
|
|
|
{
|
|
|
|
|
assert(!a.isEmpty)
|
|
|
|
|
lazy val resultEmpty = { val rs = a.flatMap(_.resultEmpty); if(rs.isEmpty) None else Some(rs) }
|
|
|
|
|
lazy val completions = a.map(_.completions).reduceLeft(_ ++ _)
|
|
|
|
|
def derive(c: Char) = seq(a.map(_ derive c))
|
|
|
|
|
override def toString = "seq(" + a + ")"
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-22 20:01:59 +01:00
|
|
|
private final class BindParser[A,B](a: Parser[A], f: A => Parser[B]) extends ValidParser[B]
|
2010-12-09 04:16:12 +01:00
|
|
|
{
|
|
|
|
|
lazy val resultEmpty = a.resultEmpty match { case None => None; case Some(av) => f(av).resultEmpty }
|
2011-01-22 20:01:59 +01:00
|
|
|
lazy val completions =
|
2010-12-09 04:16:12 +01:00
|
|
|
a.completions flatMap { c =>
|
|
|
|
|
apply(a)(c.append).resultEmpty match {
|
2010-12-14 04:44:25 +01:00
|
|
|
case None => Completions.strict(Set.empty + c)
|
2010-12-09 04:16:12 +01:00
|
|
|
case Some(av) => c x f(av).completions
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-12-14 12:08:20 +01:00
|
|
|
|
|
|
|
|
def derive(c: Char) =
|
|
|
|
|
{
|
|
|
|
|
val common = a derive c flatMap f
|
|
|
|
|
a.resultEmpty match
|
|
|
|
|
{
|
2011-01-22 20:01:59 +01:00
|
|
|
case Some(av) => common | derive1(f(av), c)
|
2010-12-14 12:08:20 +01:00
|
|
|
case None => common
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-01-22 20:01:59 +01:00
|
|
|
override def isTokenStart = a.isTokenStart
|
2010-12-14 04:44:25 +01:00
|
|
|
override def toString = "bind(" + a + ")"
|
2010-12-09 04:16:12 +01:00
|
|
|
}
|
2011-01-22 20:01:59 +01:00
|
|
|
private final class MapParser[A,B](a: Parser[A], f: A => B) extends ValidParser[B]
|
2010-12-07 01:48:49 +01:00
|
|
|
{
|
|
|
|
|
lazy val resultEmpty = a.resultEmpty map f
|
|
|
|
|
def derive(c: Char) = (a derive c) map f
|
|
|
|
|
def completions = a.completions
|
|
|
|
|
override def isTokenStart = a.isTokenStart
|
2010-12-14 04:44:25 +01:00
|
|
|
override def toString = "map(" + a + ")"
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
2011-01-22 20:01:59 +01:00
|
|
|
private final class Filter[T](p: Parser[T], f: T => Boolean) extends ValidParser[T]
|
2010-12-09 04:16:12 +01:00
|
|
|
{
|
|
|
|
|
lazy val resultEmpty = p.resultEmpty filter f
|
|
|
|
|
def derive(c: Char) = (p derive c) filter f
|
|
|
|
|
lazy val completions = p.completions filterS { s => apply(p)(s).resultEmpty.filter(f).isDefined }
|
2010-12-14 04:44:25 +01:00
|
|
|
override def toString = "filter(" + p + ")"
|
2011-01-22 20:01:59 +01:00
|
|
|
override def isTokenStart = p.isTokenStart
|
2010-12-09 04:16:12 +01:00
|
|
|
}
|
2011-04-19 23:58:05 +02:00
|
|
|
private final class MatchedString(delegate: Parser[_], seenV: Vector[Char], partial: Boolean) extends ValidParser[String]
|
2011-01-22 20:01:59 +01:00
|
|
|
{
|
2011-04-19 23:58:05 +02:00
|
|
|
lazy val seen = seenV.mkString
|
|
|
|
|
def derive(c: Char) = matched(delegate derive c, seenV :+ c, partial)
|
2011-01-22 20:01:59 +01:00
|
|
|
def completions = delegate.completions
|
|
|
|
|
def resultEmpty = if(delegate.resultEmpty.isDefined) Some(seen) else if(partial) Some(seen) else None
|
|
|
|
|
override def isTokenStart = delegate.isTokenStart
|
|
|
|
|
override def toString = "matched(" + partial + ", " + seen + ", " + delegate + ")"
|
|
|
|
|
}
|
|
|
|
|
private final class TokenStart[T](delegate: Parser[T], seen: String, track: Boolean) extends ValidParser[T]
|
2010-12-07 01:48:49 +01:00
|
|
|
{
|
2010-12-14 04:44:25 +01:00
|
|
|
def derive(c: Char) = token( delegate derive c, if(track) seen + c else seen, track)
|
2010-12-07 01:48:49 +01:00
|
|
|
lazy val completions =
|
2010-12-14 04:44:25 +01:00
|
|
|
if(track)
|
|
|
|
|
{
|
|
|
|
|
val dcs = delegate.completions
|
|
|
|
|
Completions( for(c <- dcs.get) yield Completion.token(seen, c.append) )
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
Completions.single(Completion.displayStrict(seen))
|
|
|
|
|
|
2010-12-07 01:48:49 +01:00
|
|
|
def resultEmpty = delegate.resultEmpty
|
|
|
|
|
override def isTokenStart = true
|
2010-12-14 04:44:25 +01:00
|
|
|
override def toString = "token('" + seen + "', " + track + ", " + delegate + ")"
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
2011-01-22 20:01:59 +01:00
|
|
|
private final class And[T](a: Parser[T], b: Parser[_]) extends ValidParser[T]
|
2010-12-09 04:16:12 +01:00
|
|
|
{
|
|
|
|
|
def derive(c: Char) = (a derive c) & (b derive c)
|
|
|
|
|
lazy val completions = a.completions.filterS(s => apply(b)(s).resultEmpty.isDefined )
|
|
|
|
|
lazy val resultEmpty = if(b.resultEmpty.isDefined) a.resultEmpty else None
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-22 20:01:59 +01:00
|
|
|
private final class Not(delegate: Parser[_]) extends ValidParser[Unit]
|
2010-12-09 04:16:12 +01:00
|
|
|
{
|
|
|
|
|
def derive(c: Char) = if(delegate.valid) not(delegate derive c) else this
|
|
|
|
|
def completions = Completions.empty
|
|
|
|
|
lazy val resultEmpty = if(delegate.resultEmpty.isDefined) None else Some(())
|
|
|
|
|
}
|
2011-01-22 20:01:59 +01:00
|
|
|
private final class Examples[T](delegate: Parser[T], fixed: Set[String]) extends ValidParser[T]
|
2010-12-07 01:48:49 +01:00
|
|
|
{
|
2011-01-22 20:01:59 +01:00
|
|
|
def derive(c: Char) = examples(delegate derive c, fixed.collect { case x if x.length > 0 && x(0) == c => x substring 1 })
|
|
|
|
|
lazy val resultEmpty = delegate.resultEmpty
|
|
|
|
|
lazy val completions =
|
|
|
|
|
if(fixed.isEmpty)
|
|
|
|
|
if(resultEmpty.isEmpty) Completions.nil else Completions.empty
|
|
|
|
|
else
|
|
|
|
|
Completions(fixed map(f => Completion.suggestion(f)) )
|
2010-12-14 04:44:25 +01:00
|
|
|
override def toString = "examples(" + delegate + ", " + fixed.take(2) + ")"
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
2011-04-19 23:58:05 +02:00
|
|
|
private final class StringLiteral(str: String, start: Int) extends ValidParser[String]
|
2010-12-07 01:48:49 +01:00
|
|
|
{
|
2011-04-19 23:58:05 +02:00
|
|
|
assert(0 <= start && start < str.length)
|
2010-12-07 01:48:49 +01:00
|
|
|
def resultEmpty = None
|
2011-04-19 23:58:05 +02:00
|
|
|
def derive(c: Char) = if(str.charAt(start) == c) stringLiteral(str, start+1) else Invalid
|
|
|
|
|
lazy val completions = Completions.single(Completion.suggestion(str.substring(start)))
|
2010-12-14 04:44:25 +01:00
|
|
|
override def toString = '"' + str + '"'
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
2011-01-22 20:01:59 +01:00
|
|
|
private final class CharacterClass(f: Char => Boolean) extends ValidParser[Char]
|
2010-12-07 01:48:49 +01:00
|
|
|
{
|
|
|
|
|
def resultEmpty = None
|
2011-01-22 21:01:10 +01:00
|
|
|
def derive(c: Char) = if( f(c) ) success(c) else Invalid
|
2010-12-07 01:48:49 +01:00
|
|
|
def completions = Completions.empty
|
2010-12-14 04:44:25 +01:00
|
|
|
override def toString = "class()"
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
2011-01-22 20:01:59 +01:00
|
|
|
private final class Optional[T](delegate: Parser[T]) extends ValidParser[Option[T]]
|
2010-12-07 01:48:49 +01:00
|
|
|
{
|
|
|
|
|
def resultEmpty = Some(None)
|
2011-04-19 23:58:05 +02:00
|
|
|
def derive(c: Char) = (delegate derive c).map(some.fn)
|
2010-12-07 01:48:49 +01:00
|
|
|
lazy val completions = Completion.empty +: delegate.completions
|
2010-12-14 04:44:25 +01:00
|
|
|
override def toString = delegate.toString + "?"
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|
2011-01-22 20:01:59 +01:00
|
|
|
private final class Repeat[T](partial: Option[Parser[T]], repeated: Parser[T], min: Int, max: UpperBound, accumulatedReverse: List[T]) extends ValidParser[Seq[T]]
|
2010-12-07 01:48:49 +01:00
|
|
|
{
|
|
|
|
|
assume(0 <= min, "Minimum occurences must be non-negative")
|
|
|
|
|
assume(max >= min, "Minimum occurences must be less than the maximum occurences")
|
|
|
|
|
|
|
|
|
|
def derive(c: Char) =
|
|
|
|
|
partial match
|
|
|
|
|
{
|
|
|
|
|
case Some(part) =>
|
|
|
|
|
val partD = repeat(Some(part derive c), repeated, min, max, accumulatedReverse)
|
|
|
|
|
part.resultEmpty match
|
|
|
|
|
{
|
2010-12-09 04:16:12 +01:00
|
|
|
case Some(pv) => partD | repeatDerive(c, pv :: accumulatedReverse)
|
2010-12-07 01:48:49 +01:00
|
|
|
case None => partD
|
|
|
|
|
}
|
|
|
|
|
case None => repeatDerive(c, accumulatedReverse)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def repeatDerive(c: Char, accRev: List[T]): Parser[Seq[T]] = repeat(Some(repeated derive c), repeated, (min - 1) max 0, max.decrement, accRev)
|
|
|
|
|
|
|
|
|
|
lazy val completions =
|
|
|
|
|
{
|
2010-12-09 04:16:12 +01:00
|
|
|
def pow(comp: Completions, exp: Completions, n: Int): Completions =
|
|
|
|
|
if(n == 1) comp else pow(comp x exp, exp, n - 1)
|
|
|
|
|
|
2010-12-07 01:48:49 +01:00
|
|
|
val repC = repeated.completions
|
2010-12-09 04:16:12 +01:00
|
|
|
val fin = if(min == 0) Completion.empty +: repC else pow(repC, repC, min)
|
2010-12-07 01:48:49 +01:00
|
|
|
partial match
|
|
|
|
|
{
|
|
|
|
|
case Some(p) => p.completions x fin
|
|
|
|
|
case None => fin
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lazy val resultEmpty: Option[Seq[T]] =
|
|
|
|
|
{
|
|
|
|
|
val partialAccumulatedOption =
|
|
|
|
|
partial match
|
|
|
|
|
{
|
|
|
|
|
case None => Some(accumulatedReverse)
|
|
|
|
|
case Some(partialPattern) => partialPattern.resultEmpty.map(_ :: accumulatedReverse)
|
|
|
|
|
}
|
|
|
|
|
for(partialAccumulated <- partialAccumulatedOption; repeatEmpty <- repeatedParseEmpty) yield
|
|
|
|
|
partialAccumulated reverse_::: repeatEmpty
|
|
|
|
|
}
|
|
|
|
|
private def repeatedParseEmpty: Option[List[T]] =
|
|
|
|
|
{
|
|
|
|
|
if(min == 0)
|
|
|
|
|
Some(Nil)
|
|
|
|
|
else
|
|
|
|
|
// forced determinism
|
|
|
|
|
for(value <- repeated.resultEmpty) yield
|
|
|
|
|
List.make(min, value)
|
|
|
|
|
}
|
2010-12-14 04:44:25 +01:00
|
|
|
override def toString = "repeat(" + min + "," + max +"," + partial + "," + repeated + ")"
|
2010-12-07 01:48:49 +01:00
|
|
|
}
|