-
Notifications
You must be signed in to change notification settings - Fork 81
/
Copy pathPeekTests.swift
136 lines (113 loc) · 3.39 KB
/
PeekTests.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import Parsing
import XCTest
class PeekTests: XCTestCase {
func testPeekMatches() throws {
var input = "_foo1 = nil"[...]
let identifier = Parse(input: Substring.self) {
Peek { Prefix(1) { $0.isLetter || $0 == "_" } }
Prefix { $0.isNumber || $0.isLetter || $0 == "_" }
}
XCTAssertEqual("_foo1"[...], try identifier.parse(&input))
XCTAssertEqual(" = nil", input)
}
func testPeekFails() throws {
var input = "1foo = nil"[...]
let identifier = Parse(input: Substring.self) {
Peek { Prefix(1) { $0.isLetter || $0 == "_" } }
Prefix { $0.isNumber || $0.isLetter || $0 == "_" }
}
XCTAssertThrowsError(try identifier.parse(&input)) { error in
XCTAssertEqual(
"""
error: unexpected input
--> input:1:1
1 | 1foo = nil
| ^ expected 1 element satisfying predicate
""",
"\(error)"
)
}
XCTAssertEqual("1foo = nil", input)
}
func testBacktracking() throws {
var input = "fooblah"[...]
let parser = Peek {
"foo"
"bar"
}
XCTAssertThrowsError(try parser.parse(&input)) { error in
XCTAssertEqual(
"""
error: unexpected input
--> input:1:4
1 | fooblah
| ^ expected "bar"
""",
"\(error)"
)
}
XCTAssertEqual("blah"[...], input)
}
func testPrintSkippedPeekSucceeds() {
var input = "!"[...]
let identifier = Parse(input: Substring.self) {
Peek {
Prefix(1) { $0.isLetter || $0 == "_" }
}
.printing("") // this will bypass actually printing the upstream parser in `Skip`
Prefix { $0.isNumber || $0.isLetter || $0 == "_" }
}
XCTAssertNoThrow(try identifier.print("foo"[...], into: &input))
XCTAssertEqual(input, "foo!")
}
func testPrintSkippedPeekSucceedsUnexpectedly() {
var input = "!"[...]
let identifier = Parse(input: Substring.self) {
Peek {
Prefix(1) { $0.isLetter || $0 == "_" }
}
.printing("") // this will bypass actually printing the upstream parser in `Skip`
Prefix { $0.isNumber || $0.isLetter || $0 == "_" }
}
// Should fail because '1' is not allowed for the first character, checked by the `Peek`,
// but parses because of `.printing("")` statement bypasses the `Peek`.
XCTAssertNoThrow(try identifier.print("1foo"[...], into: &input))
XCTAssertEqual(input, "1foo!")
}
func testPrintUpstreamParses() {
var input = "// a comment"[...]
let parser = Peek { "//" }
XCTAssertNoThrow(try parser.print((), into: &input))
XCTAssertEqual(input, "// a comment"[...])
}
func testPrintUpstreamFails() {
var input = "not a comment"[...]
let parser = Peek { "//" }
XCTAssertThrowsError(try parser.print((), into: &input))
XCTAssertEqual(input, "not a comment"[...])
}
func testPrintComplexParserSucceeds() {
var input = ""[...]
let commentedLine = Parse {
Peek { "//" }
Rest()
}
XCTAssertNoThrow(try commentedLine.print("// commented line"[...], into: &input))
XCTAssertEqual(
input,
"// commented line"
)
}
func testPrintComplexParserFails() {
var input = ""[...]
let commentedLine = Parse {
Peek { "//" }
Rest()
}
XCTAssertThrowsError(try commentedLine.print("uncommented line"[...], into: &input))
XCTAssertEqual(
input,
"uncommented line"
)
}
}