【问题标题】:Scala Parser Combinators: Parsing terms with optional initial characterScala Parser Combinators:使用可选的初始字符解析术语
【发布时间】:2014-03-26 10:44:07
【问题描述】:

我正在开发一个解析器,它可以解析一些具有可选初始字符的术语,该字符对于所有术语都是相同的。我的问题是,某些术语的第一个字符与初始字符相同。我试图避免使用和不使用初始字符来重写每个术语。我认为 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" */
}

【问题讨论】:

    标签: scala parsing parser-combinators


    【解决方案1】:

    看了@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 )
    

    Here is a gist with the full source for my example

    【讨论】:

      【解决方案2】:

      我认为问题在于,让 RegexParsers 在部分成功的匹配中回溯并重试替代路径并不容易,即"ab" 中的"a" 匹配可选的"a".? 部分,然后匹配"b"随后的匹配失败,但在失败之后,不再尝试与可选前缀匹配。

      请参阅this answer 了解更多详细信息和(重要的)解决方案。

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多