测试已测试 | ✗ |
Lang语言 | SwiftSwift |
许可 | MIT |
发布上次发布 | 2017年12月 |
SwiftSwift 版本 | 4.0 |
SPM支持 SPM | ✓ |
由Benjamin Herzog维护。
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 包管理器和 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.1")
]
)
要使用 Cocoapods 使用 Parsel,只需将以下条目添加到您的 Podfile,然后运行 pod install
。
target 'MyAwesomeApp' do
use_frameworks!
pod 'Parsel'
end
计算器是一个我用Parsel编写的简单示例。
请查看Github页面上的文档。
要开始为Parsel做贡献,请克隆该项目并初始配置。
$ git clone [email protected]:BenchR267/Parsel.git
$ cd Parsel
$ make initial
在您提交pull request之前,请运行make test
确保所有测试都是绿色。
如果您遇到bug或有一个功能请求的想法,但不知道从哪里开始:请随意打开一个issue,并附上自我解释的描述性文本。
如果您对现有功能有更好的(更易于阅读和/或更快的)实现想法:请随意更改代码并提交pull request。
我将非常乐意审查更改,以便使Parsel成为最好的项目。
Parsel处于MIT许可下。查看LICENSE文件了解详细信息。