1- extension BufferProtocol where Element == Byte {
1+ public let permittedLeafTagCharacters : Bytes = {
2+ var permitted = Bytes ( . a ... . z)
3+ permitted += Bytes ( . A ... . Z)
4+ permitted += Bytes ( . zero ... . nine)
5+ // -_.:
6+ permitted += [
7+ . hyphen,
8+ . underscore,
9+ . period,
10+ . colon
11+ ]
12+
13+ return permitted
14+ } ( )
15+
16+ extension Buffer {
217 mutating func components( stem: Stem ) throws -> [ Leaf . Component ] {
318 var comps : [ Leaf . Component ] = [ ]
419 while let next = try nextComponent ( stem: stem) {
520 if case let . tagTemplate( i) = next, i. isChain {
621 guard comps. count > 0 else {
7- throw ParseError . expectedLeadingTemplate ( have: nil )
22+ throw ParseError . expectedLeadingTemplate ( have: nil , line : line , column : column )
823 }
924 while let last = comps. last {
1025 var loop = true
@@ -16,7 +31,7 @@ extension BufferProtocol where Element == Byte {
1631 continue
1732 default :
1833 var mutable = last
19- try mutable. addToChain ( i)
34+ try mutable. addToChain ( i, line : line , column : column )
2035 comps. append ( mutable)
2136 loop = false
2237 }
@@ -31,10 +46,14 @@ extension BufferProtocol where Element == Byte {
3146 }
3247
3348 mutating func nextComponent( stem: Stem ) throws -> Leaf . Component ? {
34- guard let token = current else { return nil }
35- guard token == TOKEN else { return . raw( extractUntil { $0 == TOKEN } ) }
36- let tagTemplate = try extractInstruction ( stem: stem)
37- return . tagTemplate( tagTemplate)
49+ guard let _ = current else { return nil }
50+ if foundTag ( ) {
51+ let tagTemplate = try extractInstruction ( stem: stem)
52+ return . tagTemplate( tagTemplate)
53+ } else {
54+ let raw = nextRawComponent ( )
55+ return . raw( raw)
56+ }
3857 }
3958
4059 mutating func extractUntil( _ until: ( Element ) -> Bool ) -> [ Element ] {
@@ -49,22 +68,61 @@ extension BufferProtocol where Element == Byte {
4968
5069 return collection
5170 }
71+
72+ mutating func nextRawComponent( ) -> [ Element ] {
73+ var collection = Bytes ( )
74+ if let current = current {
75+ if foundTag ( ) { return [ ] }
76+
77+ if !escapeCurrent( ) {
78+ collection. append ( current)
79+ }
80+ }
81+
82+ while let value = moveForward ( ) {
83+ if foundTag ( ) {
84+ return collection
85+ }
86+
87+ guard !escapeCurrent( ) else { continue }
88+ collection. append ( value)
89+ }
90+
91+ return collection
92+ }
93+
94+ private func escapeCurrent( ) -> Bool {
95+ return next == TOKEN && current == . backSlash
96+ }
97+
98+ private func foundTag( ) -> Bool {
99+ guard let current = current, let next = next else { return false }
100+ // make sure we found a token
101+ guard current == TOKEN else { return false }
102+ // make sure said token isn't escaped
103+ guard previous != . backSlash else { return false }
104+
105+ // allow left parens, special case, ie: '#(' and any valid name
106+ // also allow special case double chained
107+ let isSpecialCase = ( next == . leftParenthesis || next == TOKEN)
108+ return isSpecialCase || permittedLeafTagCharacters. contains ( next)
109+ }
52110}
53111
54112enum ParseError : LeafError {
55113 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 ? )
114+ case missingBodyOpener( expected: String , have: String ? , line : Int , column : Int )
115+ case missingBodyCloser( expected: String , line : Int , column : Int )
116+ case expectedOpenParenthesis( line : Int , column : Int )
117+ case expectedLeadingTemplate( have: Leaf . Component ? , line : Int , column : Int )
60118}
61119
62120/*
63121 Syntax
64122
65123 @ + '<bodyName>` + `(` + `<[argument]>` + `)` + ` { ` + <body> + ` }`
66124 */
67- extension BufferProtocol where Element == Byte {
125+ extension Buffer {
68126 mutating func extractInstruction( stem: Stem ) throws -> TagTemplate {
69127 let name = try extractInstructionName ( )
70128 let parameters = try extractInstructionParameters ( )
@@ -93,7 +151,7 @@ extension BufferProtocol where Element == Byte {
93151 moveForward ( ) // drop initial token from name. a secondary token implies chain
94152 let name = extractUntil { $0 == . leftParenthesis }
95153 guard current == . leftParenthesis else {
96- throw ParseError . expectedOpenParenthesis
154+ throw ParseError . expectedOpenParenthesis ( line : line , column : column )
97155 }
98156 return name. makeString ( )
99157 }
@@ -112,7 +170,12 @@ extension BufferProtocol where Element == Byte {
112170 mutating func extractSection( opensWith opener: Byte , closesWith closer: Byte ) throws -> Bytes {
113171 guard current == opener else {
114172 let have = current. flatMap { [ $0] } ? . makeString ( )
115- throw ParseError . missingBodyOpener ( expected: [ opener ] . makeString ( ) , have: have)
173+ throw ParseError . missingBodyOpener (
174+ expected: [ opener ] . makeString ( ) ,
175+ have: have,
176+ line: line,
177+ column: column
178+ )
116179 }
117180
118181 var subBodies = 0
@@ -129,7 +192,11 @@ extension BufferProtocol where Element == Byte {
129192 }
130193
131194 guard current == closer else {
132- throw ParseError . missingBodyCloser ( expected: [ closer ] . makeString ( ) )
195+ throw ParseError . missingBodyCloser (
196+ expected: [ closer ] . makeString ( ) ,
197+ line: line,
198+ column: column
199+ )
133200 }
134201
135202 return body
0 commit comments