Parsel 是一个解析器组合子库,它可以轻松编写解析器。解析器组合子让你可以创建简单的解析器,并将它们组合成非常复杂的解析器。例如,假设我们需要一个从给定字符串中解析数字的解析器:(你可以使用预定义的词法解析器来解析数字:L.digit
)
let digit = Parser<String, Int> { input in
guard let first = input.first, let number = Int(String(first)) else {
return .fail(/* some pre-defined error */)
}
return .success(result: number, rest: String(input.dropFirst()))
}
现在我们可以简单地扩展它,创建一个从字符串中解析两个数字相加的解析器
let addition = (digit ~ L.plus ~ digit).map { a, _, b in a + b } // `L.plus` is a predefined parser that parses the `+` sign
let result = addition.parse("2+4")
try! result.unwrap() // Int: 6
解析是一项非常常见的任务,它并不总是意味着解析源代码或 JSON 字符串。解析意味着将非结构化的输入转换为结构化的输出。在源代码的情况下,这意味着将原始字符串解析为 AST(抽象语法树),在加法的情况下,这意味着从字符串中解析出两个数字相加的结果。如果输入不符合所需的语法,解析总是可能失败。如果在上面的例子中,输入字符串是 1+
,那么解析将会失败,因为缺少第二个数字。解析器组合子的优点在于,你可以从一个非常基础的解析器开始。在上面的例子中,digit
只解析一个数字。但是,添加一个解析多个数字的解析器并不难。一个数字是多个数字的重复。对于重复,我们可以使用 rep
,它会尝试应用解析器直到失败,并将结果收集为一个数组。解析整数加法就像这样简单
func intFromDigits(_ digits: [Int]) -> Int {
return digits.reduce(0) { res, e in
return res * 10 + e
}
}
let number = digit.rep.map(intFromDigits)
let addition = number ~ L.plus ~ number ^^ { a, _, b in // ^^ is convenience for map
return a + b
}
let result = addition.parse("123+456")
try! result.unwrap() // Int: 579
(还有一个预定义的词法解析器用于数字 L.number
,它能够解析不同格式的数字 [二进制、八进制、十六进制、十进制])
由于解析器组合子非常高级,它们在很大程度上抽象了整个解析过程。这意味着它更容易使用,但也意味着其性能不如优化的手写解析器。
Parsel 目前通过 Swift Package Manager 和 Cocoapods 提供。对 Carthage 的支持将在稍后推出。
要在你的项目中使用 Parsel,只需将其作为依赖项添加到你的 Package.swift
文件中,并运行 swift package update
。
import PackageDescription
let package = Package(
name: "MyAwesomeApp",
dependencies: [
.package(url: "https://github.com/BenchR267/Parsel", from: "3.0.2")
]
)
要将 Parsel 与 Cocoapods 一起使用,只需将此条目添加到你的 Podfile 中,并运行 pod install
target 'MyAwesomeApp' do
use_frameworks!
pod 'Parsel'
end
Calculator 是我用 Parsel 编写的一个小例子。
请查看 Github 页面上的文档。
要开始为 Parsel 做出贡献,请克隆项目并进行初始配置
$ git clone git@github.com:BenchR267/Parsel.git
$ cd Parsel
$ make initial
在提交拉取请求之前,请通过运行 make test
确保所有测试都是绿色的。
如果您遇到错误或对功能请求有想法,但不知道从哪里开始:请随时打开一个 issue,并附上自我解释的描述文本。
如果您对现有功能的更好(更易读和/或更快)的实现有想法:请随时更改代码并提交拉取请求。我将非常乐意审查这些更改,以使 Parsel 成为最好的项目!
Parsel 使用 MIT 许可证。有关更多信息,请参阅 LICENSE 文件。