我正在研究一种解析器,该解析器解析一些术语,这些术语的可选初始字符对于所有术语都是相同的。我的问题是,某些术语“第一个字符”与初始字符相同。我试图避免使用和不使用初始字符来重写每个术语。我发现一个packrat解析器听起来像是解决方案,但是我还没有按照我想要的方式使它工作。以下是我要完成的最小示例。
import scala.util.parsing.combinator._
import scala.util.parsing.input._
object test extends App {
object MyParser extends RegexParsers with PackratParsers {
lazy val p1:Parser[String] = "ab"
lazy val p2:Parser[String] = "cd"
lazy val parser:PackratParser[String] = ("a".?) ~> ( p2 | p1 )
}
def parsing[T](s: String)(implicit p: MyParser.Parser[T]): T = {
import MyParser._
val phraseParser = phrase(p)
val input = new PackratReader(new CharSequenceReader(s))
phraseParser(input) match {
case Success(t, _) => t
case NoSuccess(msg, _) => throw new IllegalArgumentException(
"Could not parse '"+s+"': "+msg)
}
} //> parsing: [T](s: String)(implicit p: test.MyParser.Parser[T])T
implicit val parser = MyParser.log(MyParser.parser)("parser")
println(parsing("cd")) /* works */
println(parsing("acd")) /* works */
println(parsing("aab")) /* works */
// Should work but doesn't.
println(parsing("ab")) /* expected "ab" but found "b" */
}
在查看@ishaaq的答案后,我想出了一个我认为更优雅的解决方案。
implicit class ParserExtension[T](val p: Parser[T]) extends AnyVal {
def ?~[U](q: => Parser[U]): Parser[Option[T] ~ U] = {
((p ^^ Some.apply) ~ q) | (success(None) ~ q)
}
}
这个隐式类为我的所有解析器添加了一个方法,因此我可以有一个可选的解析器,它具有反向跟踪功能。您可以这样使用它:
val a:Parser[String] = "a"
val parser:Parser[Option[String] ~ String] = a ?~ ( p2 | p1 )
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句