这段代码尝试在 Swift 中实现类似 Scala 解析器组合子的功能。 在某种程度上它是成功的,因为它可以用来创建简单的解析器。 中间解析结果被缓存用于复杂的规则,因此复杂表达式的解析仍然应该是线性时间的(参见 Packrat)。
通过运算符重载,创建了一个嵌套的函数集,构成了解析器。 这些函数接受一个解析器实例和一个读取器对象,该读取器对象为函数提供要解析的字符。
目前支持以下解析操作
// "a" followed by "b"
let rule = "a" ~ "b"
// "a" followed by "b", with possible whitespace in between
// to change what is considered whitespace, change the parser.whitespace rule
let rule = "a" ~~ "b"
// at least one "a", but possibly more
let rule = "a"++
// "a" or "b"
let rule = "a" | "b"
// "a" followed by something other than "b"
let rule = "a" ~ !"b"
// "a" followed by one or more "b"
let rule = "a" ~ "b"+
// "a" followed by zero or more "b"
let rule = "a" ~ "b"*
// "a" followed by a numeric digit
let rule = "a" ~ ("0"-"9")
// "a" followed by the rule named "blah"
let rule = "a" ~ ^"blah"
// "a" optionally followed by "b"
let rule = "a" ~ "b"/~
// "a" followed by the end of input
let rule = "a"*!*
// a single ","
let rule = %","
// regular expression: consecutive word or space characters
let rule = %!"[\\w\\s]+"
要让解析器在规则匹配时调用您的代码,请使用 => 运算符。 例如
import SwiftParser
class Adder : Parser {
var stack: Int[] = []
func push(_ text: String) {
stack.append(text.toInt()!)
}
func add() {
let left = stack.removeLast()
let right = stack.removeLast()
stack.append(left + right)
}
override init() {
super.init()
self.grammar = Grammar { [unowned self] g in
g["number"] = ("0"-"9")+ => { [unowned self] parser in self.push(parser.text) }
return (^"number" ~ "+" ~ ^"number") => add
}
}
}
此示例展示了如何使用解析器的几个细节。 解析器在名为 grammar
的对象中定义,该对象定义了命名的规则以及开始规则,以告诉解析器从哪里开始。
以下代码片段取自其中一个单元测试。 它展示了如何实现包含相互递归规则的解析器
self.grammar = Grammar { [unowned self] g in
g["number"] = ("0"-"9")+ => { [unowned self] parser in self.push(parser.text) }
g["primary"] = ^"secondary" ~ (("+" ~ ^"secondary" => add) | ("-" ~ ^"secondary" => sub))*
g["secondary"] = ^"tertiary" ~ (("*" ~ ^"tertiary" => mul) | ("/" ~ ^"tertiary" => div))*
g["tertiary"] = ("(" ~ ^"primary" ~ ")") | ^"number"
return (^"primary")*!*
}
您可以使用 Swift Package Manager 安装该驱动程序,方法是将以下行作为依赖项添加到您的 Package.swift
中
.Package(url: "https://github.com/dparnell/swift-parser-generator.git", majorVersion: 1)
要在 Xcode 项目中使用该驱动程序,请使用 SPM 生成一个 Xcode 项目文件
swift package generate-xcodeproj
将 SwiftParser.xcodeproj 拖到您自己的项目中,然后将 SwiftParser 添加为依赖项(构建目标)并链接到它。 然后您应该能够简单地从 Swift 代码中 'import SwiftParser'。