@@ -3,7 +3,9 @@ extension BufferProtocol where Element == Byte {
3
3
var comps : [ Leaf . Component ] = [ ]
4
4
while let next = try nextComponent ( ) {
5
5
if case let . tagTemplate( i) = next, i. isChain {
6
- guard comps. count > 0 else { throw " invalid chain component w/o preceeding tagTemplate " }
6
+ guard comps. count > 0 else {
7
+ throw ParseError . expectedLeadingTemplate ( have: nil )
8
+ }
7
9
while let last = comps. last {
8
10
var loop = true
9
11
@@ -30,16 +32,12 @@ extension BufferProtocol where Element == Byte {
30
32
31
33
mutating func nextComponent( ) throws -> Leaf . Component ? {
32
34
guard let token = current else { return nil }
33
- if token == TOKEN {
34
- let tagTemplate = try extractInstruction ( )
35
- return . tagTemplate( tagTemplate)
36
- } else {
37
- let raw = extractUntil { $0 == TOKEN }
38
- return . raw( raw)
39
- }
35
+ guard token == TOKEN else { return . raw( extractUntil { $0 == TOKEN } ) }
36
+ let tagTemplate = try extractInstruction ( )
37
+ return . tagTemplate( tagTemplate)
40
38
}
41
39
42
- mutating func extractUntil( _ until: @ noescape ( Element ) -> Bool ) -> [ Element ] {
40
+ mutating func extractUntil( _ until: ( Element ) -> Bool ) -> [ Element ] {
43
41
var collection = Bytes ( )
44
42
if let current = current {
45
43
guard !until( current) else { return [ ] }
@@ -53,6 +51,14 @@ extension BufferProtocol where Element == Byte {
53
51
}
54
52
}
55
53
54
+ enum ParseError : LeafError {
55
+ case tagTemplateNotFound( name: String )
56
+ case missingBodyOpener( expected: String , have: String ? )
57
+ case missingBodyCloser( expected: String )
58
+ case expectedOpenParenthesis
59
+ case expectedLeadingTemplate( have: Leaf . Component ? )
60
+ }
61
+
56
62
/*
57
63
Syntax
58
64
@@ -77,11 +83,11 @@ extension BufferProtocol where Element == Byte {
77
83
}
78
84
79
85
mutating func extractInstructionName( ) throws -> String {
80
- // can't extract section because of @@
81
- guard current == TOKEN else { throw " tagTemplate name must lead with token " }
82
86
moveForward ( ) // drop initial token from name. a secondary token implies chain
83
87
let name = extractUntil { $0 == . openParenthesis }
84
- guard current == . openParenthesis else { throw " tagTemplate names must be alphanumeric and terminated with '(' " }
88
+ guard current == . openParenthesis else {
89
+ throw ParseError . expectedOpenParenthesis
90
+ }
85
91
return name. string
86
92
}
87
93
@@ -98,7 +104,8 @@ extension BufferProtocol where Element == Byte {
98
104
99
105
mutating func extractSection( opensWith opener: Byte , closesWith closer: Byte ) throws -> Bytes {
100
106
guard current == opener else {
101
- throw " invalid body, missing opener: \( [ opener ] . string) "
107
+ let have = current. flatMap { [ $0] } ? . string
108
+ throw ParseError . missingBodyOpener ( expected: [ opener ] . string, have: have)
102
109
}
103
110
104
111
var subBodies = 0
@@ -112,7 +119,7 @@ extension BufferProtocol where Element == Byte {
112
119
}
113
120
114
121
guard current == closer else {
115
- throw " invalid body, missing closer: \( [ closer ] . string) , got \( [ current ] ) "
122
+ throw ParseError . missingBodyCloser ( expected : [ closer ] . string)
116
123
}
117
124
118
125
return body
0 commit comments