Copyright (c) 2020 Steven Obua
License: MIT License
ParsingKit is a Swift package for composable parsing. Its foundation is Local Lexing. It is experimental in the sense that its goal is to explore how practical Local Lexing is, and how much it can actually facilitate composable parsing.
Its API is not documented yet, and it hasn't been extensively tested yet. A document describing the principles on which ParsingKit is based is in the making. For now, to get a feel for the framework, you can examine the existing tests. Here is an example grammar taken from them:
import FirstOrderDeepEmbedding
import ParsingKit
class Calculator : TextGrammar {
typealias N = Nonterminal<UNIT, INT>
@Sym var Expr : N
@Sym var Sum : N
@Sym var Product : N
@Sym var Num : N
@Sym var Digit : N
override func build() {
add {
Expr.rule {
Sum
Sum.out --> Expr
}
Sum.rule {
Sum[1]
literal("+")
Product
Sum[1]~ + Product~ --> Sum
}
Sum.rule {
Product
Product~ --> Sum
}
Product.rule {
Product[1]
literal("*")
Num
Product[1]~ * Num~ --> Product
}
Product.rule {
Num
Num~ --> Product
}
Num.rule {
Digit
Digit~ --> Num
}
Num.rule {
Num[1]
Digit
Num[1]~ * 10 + Digit~ --> Num
}
Digit.rule {
Char
%?(Char~ >= "0" && Char~ <= "9")
Char~.match("0" => 0, "1" => 1, "2" => 2, "3" => 3, "4" => 4, "5" => 5, "6" => 6, "7" => 7, "8" => 8, "9" => 9) --> Digit
}
}
}
}
Parsing with this grammar is simple:
let calculator = Calculator()
let parser = calculator.parser()
let result = parser.parse(input: "32+4*7", start: calculator.Expr)
switch result {
case let .failed(position): print("parsing failed at position \(position)")
case let .success(length: length, results: results):
print("parsing succeeded (\(length) characters consumed): output parameter = \(results.first!.key)")
}