public
Created

Completing Parser Trait

  • Download Gist
CompletingParser.scala
Scala
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
import util.parsing.combinator.RegexParsers
 
 
/**
* A trait to make parsers for string literals return a nice list of possible completions if
* we're at the end of the input.
*
* @author Marcus Schulte
*/
 
trait CompletingParser extends RegexParsers {
 
/**
* A `Failure` which is curable by adding one of several possible completions.
*
* @param completions what would make the parser succeed if added to `in`.
* @param next the input about to be read
*/
case class MissingCompletionOrFailure( val completions: List[String],
override val msg: String,
override val next: Input )
extends Failure( msg, next ) {
 
override def append[U](a: => ParseResult[U]) = a match {
case MissingCompletionOrFailure( newCompletions, _, _ )
=> val comps = completions ++ newCompletions;
new MissingCompletionOrFailure( comps,
if (comps.isEmpty) msg else "expected one of " + comps,
next )
case ns: NoSuccess => this
case s: Success[U] => s
}
}
 
override implicit def literal( s: String ) : Parser[String] =new Parser[String] {
 
def apply(in: Input) = {
val source = in.source
val offset = in.offset
val start = handleWhiteSpace(source, offset)
var i = 0
var j = start
while (i < s.length && j < source.length && s.charAt(i) == source.charAt(j)) {
i += 1
j += 1
}
if (i == s.length)
Success(source.subSequence(start, j).toString, in.drop(j - offset))
else if (j == source.length()) {
val missing = s.substring(i)
MissingCompletionOrFailure( List(missing), "expected one of "+missing, in.drop(start - offset) )
} else {
MissingCompletionOrFailure( List(), "`"+s+"' expected but "+source.charAt(j)+" found", in.drop(start - offset))
}
}
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.