我正在尝试构建一个小解析器,其中令牌(幸运的是)从不包含空格。空格(空格,制表符和换行符)本质上是令牌分隔符(除了有括号等的情况)。
我正在扩展RegexParsers
课程。如果我打开skipWhitespace
,当下一个标记与前一个标记的正则表达式匹配时,解析器会贪婪地加入标记。另一方面,如果我关闭skipWhitespace
,它会因为空格不属于定义而抱怨。我试图尽可能地匹配BNF,并且假设空格几乎总是分隔符(除了括号或其他在BNF中明确定义分隔符的情况),是否可以避免将空白正则表达式放在所有区域中我的定义?
更新
这是一个小型测试示例,其中令牌连接在一起:
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+) <~ ")"
答案 0 :(得分:4)
在每个生产规则之前跳过空白区域。所以,在这个片段中:
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
// ...