Skip to content

Commit f1d958f

Browse files
authored
Merge pull request #47 from kareman/Readme-require-Swift-5.3
Readme: require Swift 5.3. Add part about pattern input types. Split up readme unit test to avoid warning about it taking too long to type check.
2 parents c693330 + eddb419 commit f1d958f

File tree

2 files changed

+83
-36
lines changed

2 files changed

+83
-36
lines changed

README.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<p align="center">
22
<a href="https://developer.apple.com/swift/">
3-
<img src="https://img.shields.io/badge/Swift-5.2-orange.svg?style=flat" alt="Swift 5.2">
3+
<img src="https://img.shields.io/badge/Swift-5.3-orange.svg?style=flat" alt="Swift 5.3">
44
</a>
55
<a href="https://github.com/apple/swift-package-manager">
66
<img src="https://img.shields.io/badge/Swift%20Package%20Manager-compatible-brightgreen.svg" alt="SPM">
@@ -17,6 +17,10 @@ For general information about PEGs, see [the original paper](https://dl.acm.org/
1717

1818
To try out Patterns in a playground, open Playground/Playground.xcworkspace in Xcode.
1919

20+
### Note
21+
22+
Patterns requires Swift 5.3, which is currently in beta. If using Xcode, version 12 (also in beta) is required.
23+
2024
## Example
2125

2226
```swift
@@ -183,6 +187,30 @@ let pointsAsSubstrings = parser.matches(in: text).map { match in
183187

184188
You can also use `match[multiple: name]` to get an array if captures with that name may be matched multiple times. `match[one: name]` only returns the first capture of that name.
185189

190+
### Inputs
191+
192+
By default, patterns have `String` as their input type. But you can use any `BidirectionalCollection` with `Hashable` elements for input. Just explicitly specify the input type of the first pattern, and the rest should get it automatically:
193+
194+
```swift
195+
let text = "This is a point: (43,7), so is (0, 5). But my final point is (3,-1).".utf8
196+
197+
let digit = OneOf<String.UTF8View>(UInt8(ascii: "0")...UInt8(ascii: "9"))
198+
let number = ("+" / "-" / "") digit+
199+
let point = "(" Capture(name: "x", number)
200+
"," " "¿ Capture(name: "y", number) ")"
201+
202+
struct Point: Codable {
203+
let x, y: Int
204+
}
205+
206+
let parser = try Parser(search: point)
207+
let pointsAsSubstrings = parser.matches(in: text).map { match in
208+
(text[match[one: "x"]!], text[match[one: "y"]!])
209+
}
210+
```
211+
212+
`Parser.decode` can (currently) only take String as input, but `.matches` handles all types.
213+
186214
## Setup
187215

188216
### [Swift Package Manager](https://swift.org/package-manager/)

Tests/PatternsTests/PatternTests.swift

Lines changed: 54 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -307,48 +307,67 @@ class PatternTests: XCTestCase {
307307
assertCaptures(point, input: text, result: [["43", "7"], ["0", "5"], ["3", "-1"]])
308308
}
309309

310-
func testReadme() throws {
311-
do {
312-
let l = OneOf(description: "ten") { character in
313-
character.wholeNumberValue == 10
314-
}
315-
316-
let arithmetic = Grammar { g in
317-
g.all <- g.expr !any
318-
g.expr <- g.sum
319-
g.sum <- g.product (("+" / "-") g.product)*
320-
g.product <- g.power (("*" / "/") g.power)*
321-
g.power <- g.value ("^" g.power)¿
322-
g.value <- digit+ / "(" g.expr ")"
323-
}
324-
325-
let parser = try Parser(search: l)
326-
for match in parser.matches(in: "text") {
327-
_ = match
328-
// ...
329-
}
330-
_ = arithmetic
310+
func testReadme1() throws {
311+
let l = OneOf(description: "ten") { character in
312+
character.wholeNumberValue == 10
331313
}
332314

333-
do {
334-
let text = "This is a point: (43,7), so is (0, 5). But my final point is (3,-1)."
315+
let arithmetic = Grammar { g in
316+
g.all <- g.expr !any
317+
g.expr <- g.sum
318+
g.sum <- g.product (("+" / "-") g.product)*
319+
g.product <- g.power (("*" / "/") g.power)*
320+
g.power <- g.value ("^" g.power)¿
321+
g.value <- digit+ / "(" g.expr ")"
322+
}
323+
324+
let parser = try Parser(search: l)
325+
for match in parser.matches(in: "text") {
326+
_ = match
327+
// ...
328+
}
329+
330+
_ = arithmetic
331+
}
332+
333+
func testReadme2() throws {
334+
let text = "This is a point: (43,7), so is (0, 5). But my final point is (3,-1)."
335+
336+
let number = ("+" / "-" / "") digit+
337+
let point = "(" Capture(name: "x", number)
338+
"," " "¿ Capture(name: "y", number) ")"
339+
340+
struct Point: Codable {
341+
let x, y: Int
342+
}
343+
344+
let parser = try Parser(search: point)
345+
let points = try parser.decode([Point].self, from: text)
335346

336-
let number = ("+" / "-" / "") digit+
337-
let point = "(" Capture(name: "x", number)
338-
"," " "¿ Capture(name: "y", number) ")"
347+
let pointsAsSubstrings = parser.matches(in: text).map { match in
348+
(text[match[one: "x"]!], text[match[one: "y"]!])
349+
}
350+
351+
_ = (points, pointsAsSubstrings)
352+
}
339353

340-
struct Point: Codable {
341-
let x, y: Int
342-
}
354+
func testReadme3() throws {
355+
let text = "This is a point: (43,7), so is (0, 5). But my final point is (3,-1).".utf8
343356

344-
let parser = try Parser(search: point)
345-
let points = try parser.decode([Point].self, from: text)
357+
let digit = OneOf<String.UTF8View>(UInt8(ascii: "0") ... UInt8(ascii: "9"))
358+
let number = ("+" / "-" / "") digit+
359+
let point = "(" Capture(name: "x", number)
360+
"," " "¿ Capture(name: "y", number) ")"
346361

347-
let pointsAsSubstrings = parser.matches(in: text).map { match in
348-
(text[match[one: "x"]!], text[match[one: "y"]!])
349-
}
362+
struct Point: Codable {
363+
let x, y: Int
364+
}
350365

351-
_ = (points, pointsAsSubstrings)
366+
let parser = try Parser(search: point)
367+
let pointsAsSubstrings = parser.matches(in: text).map { match in
368+
(text[match[one: "x"]!], text[match[one: "y"]!])
352369
}
370+
371+
_ = pointsAsSubstrings
353372
}
354373
}

0 commit comments

Comments
 (0)