scala - 如何跳过空格但将其用作解析器组合器中的标记分隔符

标签 scala parser-combinators

我正在尝试构建一个小型解析器,其中标记(幸运的是)从不包含空格。空白(空格、制表符和换行符)本质上是标记分隔符(除了有括号等的情况)。

我正在扩展 RegexParsers 类。如果我打开“skipWhitespace”,当下一个标记与前一个标记的正则表达式匹配时,解析器就会贪婪地将标记连接在一起。另一方面,如果我关闭 skipWhitespace,它会提示,因为空格不是定义的一部分。我试图尽可能匹配 BNF,并且考虑到空格几乎总是分隔符(除了括号或 BNF 中明确定义分隔符的其他一些情况),是否可以避免将空格正则表达式放在所有我的定义?

更新

这是一个小型测试示例,其中 token 连接在一起:

import scala.util.parsing.combinator.RegexParsers

object TestParser extends RegexParsers {
  def test  = "(test" ~> name <~ ")"

  def name : Parser[String] = (letter ~ (anyChar*)) ^^ { case first ~ rest => (first :: rest).mkString}

  def anyChar = letter | digit | "_".r | "-".r
  def letter = """[a-zA-Z]""".r
  def digit = """\d""".r

  def main(args: Array[String]) {

    val s = "(test hello these should not be joined and I should get an error)"

    val res = parseAll(test, s)
    res match {
      case Success(r, n) => println(r)
      case Failure(msg, n) => println(msg)
      case Error(msg, n) => println(msg)
    }

  }

}

在上面的例子中,我只是将字符串连接在一起。 类似的效果是,如果我将 test 更改为以下内容,期望它在测试后给出单独单词的列表,但相反,它将它们连接在一起,只给我一个带有长字符串的单元素列表,没有中间空格:

def test  = "(test" ~> (name+) <~ ")"

最佳答案

在每个产生规则之前都会跳过空格。所以,在这个片段中:

def name : Parser[String] = (letter ~ (anyChar*)) ^^ { case first ~ rest => (first :: rest).mkString}

它将跳过每个字母之前的空格,更糟糕的是,跳过每个字符串(因为anyChar*可以为空)。

对每个标记使用正则表达式(或纯字符串),而不是每个词法元素。像这样:

object TestParser extends RegexParsers {
  def test  = "(test" ~> name <~ ")"
  def name : Parser[String] = """[a-zA-Z][a-zA-Z0-9_-]*""".r

  // ...

关于scala - 如何跳过空格但将其用作解析器组合器中的标记分隔符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20793058/

相关文章:

scala - Scala 对 Java 类文字的模拟是什么,例如Foo.class?

scala - 如何在 case 类中使用另一个字段初始化一个字段?

scala 组合器解析器保留原始输入

f# - FParsec:如何组合解析器以便它们以任意顺序匹配

QtConcurrent的Scala类似物

scala - 检查 DataFrame(Scala) 是否为空的最快方法?

scala - 如何在 Scala 中生成方法

parsing - Scala组合器解析器,>>是什么意思?

c++ - GLL Parser Combinator or Generator in/for C or C++

parsing - 深度扩展解析器库的方法