@@ -138,7 +138,93 @@ extension BufferProtocol where Element == Byte {
138138
139139extension Sequence where Iterator. Element == Byte {
140140 func extractParameters( ) throws -> [ Parameter ] {
141- return try split ( separator: . comma)
142- . map { try Parameter ( $0) }
141+ let parser = ParameterParser ( self . array)
142+ return try parser. process ( )
143+ }
144+ }
145+
146+ import Core
147+
148+ fileprivate final class ParameterParser {
149+ var buffer : Buffer
150+
151+ init ( _ bytes: Bytes ) {
152+ buffer = Buffer ( bytes: bytes)
153+ }
154+
155+ func process( ) throws -> [ Parameter ] {
156+ var params = [ Parameter] ( )
157+ while let next = try nextParameter ( ) {
158+ params. append ( next)
159+ }
160+ return params
161+ }
162+
163+ private func nextParameter( ) throws -> Parameter ? {
164+ try buffer. skipWhitespace ( )
165+
166+ guard try ! buffer. next ( matchesAny: . rightParenthesis) else { return nil }
167+ guard let next = try buffer. next ( ) else { return nil }
168+ guard next != . comma else { return try nextParameter ( ) }
169+ buffer. returnToBuffer ( next)
170+
171+ if next == . quote {
172+ return try nextConstant ( )
173+ } else {
174+ return try nextVariable ( )
175+ }
176+ }
177+
178+ private func nextVariable( ) throws -> Parameter {
179+ let collected = try buffer. collect ( until: . comma, . rightParenthesis)
180+ // discard `,` or ')'
181+ try buffer. discardNext ( 1 )
182+ try buffer. skipWhitespace ( )
183+
184+ let variable = collected
185+ . makeString ( )
186+ . components ( separatedBy: " . " )
187+ return . variable( path: variable)
188+
189+ }
190+
191+ private func nextConstant( ) throws -> Parameter {
192+ // discard leading `"`
193+ try buffer. discardNext ( 1 )
194+
195+ var collected = Bytes ( )
196+ while let next = try buffer. next ( ) {
197+ if next == . quote, buffer. previous != . backSlash {
198+ break
199+ }
200+ collected. append ( next)
201+ }
202+
203+ return . constant( value: collected. makeString ( ) )
204+ }
205+ }
206+
207+
208+ extension ParameterParser {
209+ fileprivate final class Buffer : StaticDataBuffer {
210+ var previous : Byte ? = nil
211+ var current : Byte ? = nil
212+
213+ override init < B: Sequence > ( bytes: B ) where B. Iterator. Element == Byte {
214+ super. init ( bytes: bytes)
215+ }
216+
217+ override func next( ) throws -> Byte ? {
218+ let n = try super. next ( )
219+ previous = current
220+ current = n
221+ return n
222+ }
223+
224+ func skipWhitespace( ) throws {
225+ while try next ( matches: Bytes . whitespace. contains) {
226+ try discardNext ( 1 )
227+ }
228+ }
143229 }
144230}
0 commit comments