@@ -143,16 +143,13 @@ func RawValues(enabled bool) ParseOption {
143143}
144144
145145const (
146- stBegin = "stBegin"
147- stTag = "stTag"
148- stMaybeArgs = "stMaybeArgs"
149- stArg = "stArg"
150- stArgEndOfToken = "stArgEndOfToken"
151- stMaybeValue = "stMaybeValue"
152- stValue = "stValue"
153- stMaybeComment = "stMaybeComment"
154- stTrailingSlash = "stTrailingSlash"
155- stTrailingComment = "stTrailingComment"
146+ stTag = "stTag"
147+ stMaybeArgs = "stMaybeArgs"
148+ stArg = "stArg"
149+ stArgEndOfToken = "stArgEndOfToken"
150+ stMaybeValue = "stMaybeValue"
151+ stValue = "stValue"
152+ stMaybeComment = "stMaybeComment"
156153)
157154
158155func parseTag (input string , opts parseOpts ) (Tag , error ) {
@@ -216,56 +213,44 @@ func parseTag(input string, opts parseOpts) (Tag, error) {
216213 endTag .Value = value
217214 endTag .ValueType = valueType
218215 }
219- st := stBegin
216+ var err error
217+ st := stTag
220218parseLoop:
221- for r := s .peek (); r != EOF ; r = s .peek () {
219+ for r := s .skipWhitespacePeek (); r != EOF ; r = s .skipWhitespacePeek () {
222220 switch st {
223- case stBegin :
224- switch {
225- case s .skipWhitespace ():
226- case isIdentBegin (r ):
227- // did not consume
228- st = stTag
229- default :
230- break parseLoop
231- }
232221 case stTag :
233222 switch {
234- case s .skipWhitespace ():
235223 case isIdentBegin (r ):
236- ident , err : = s .nextIdent (isTagNameInterior )
224+ tagName , err = s .nextIdent (isTagNameInterior )
237225 if err != nil {
238226 return Tag {}, err
239227 }
240- tagName = ident
241228 st = stMaybeArgs
242229 default :
243230 break parseLoop
244231 }
245232 case stMaybeArgs :
246233 switch {
247234 case r == '(' :
248- s .next ()
235+ s .next () // consume (
249236 incomplete = true
250237 st = stArg
251238 case r == '=' :
252- s .next ()
239+ s .next () // consume =
253240 if opts .rawValues {
241+ // only raw values support empty values following =
254242 valueType = ValueTypeRaw
255243 } else {
256244 incomplete = true
257245 }
258246 st = stValue
259- case s .skipWhitespace ():
260- st = stMaybeComment
261247 default :
262- break parseLoop
248+ st = stMaybeComment
263249 }
264250 case stArg :
265251 switch {
266- case s .skipWhitespace ():
267252 case r == ')' :
268- s .next ()
253+ s .next () // consume )
269254 incomplete = false
270255 st = stMaybeValue
271256 case r == '-' || r == '+' || unicode .IsDigit (r ):
@@ -288,26 +273,28 @@ parseLoop:
288273 return Tag {}, err
289274 }
290275 r = s .peek () // reset r after nextIdent
276+
291277 switch {
292- case r == ',' || r == ')' || s . skipWhitespace ():
278+ case r == ',' || r == ')' : // positional arg
293279 saveBoolOrString (identifier )
294280 st = stArgEndOfToken
295- case r == ':' :
296- s .next ()
281+ case r == ':' : // named arg
282+ s .next () // consume :
297283 saveName (identifier )
298284 st = stArg
285+ default :
286+ break parseLoop
299287 }
300288 default :
301289 break parseLoop
302290 }
303291 case stArgEndOfToken :
304292 switch {
305- case s .skipWhitespace ():
306293 case r == ',' :
307- s .next ()
294+ s .next () // consume ,
308295 st = stArg
309296 case r == ')' :
310- s .next ()
297+ s .next () // consume )
311298 incomplete = false
312299 st = stMaybeValue
313300 default :
@@ -316,29 +303,32 @@ parseLoop:
316303 case stMaybeValue :
317304 switch {
318305 case r == '=' :
319- s .next ()
306+ s .next () // consume =
320307 if opts .rawValues {
308+ // Empty values are allowed for raw.
309+ // Since = might be the last char in the input, we need
310+ // to record the valueType as raw immediately.
321311 valueType = ValueTypeRaw
322312 }
323313 st = stValue
324- case s .skipWhitespace ():
325- st = stMaybeComment
326314 default :
327- break parseLoop
315+ st = stMaybeComment
328316 }
329317 case stValue :
330- incomplete = false
331318 switch {
332319 case opts .rawValues : // When enabled, consume all remaining chars
320+ incomplete = false
333321 value = s .remainder ()
334322 break parseLoop
335323 case r == '+' && isIdentBegin (s .peekN (1 )): // tag value
324+ incomplete = false
336325 s .next () // consume +
337326 if err := saveTag (); err != nil {
338327 return Tag {}, err
339328 }
340329 st = stTag
341330 case r == '-' || r == '+' || unicode .IsDigit (r ):
331+ incomplete = false
342332 number , err := s .nextNumber ()
343333 valueType = ValueTypeInt
344334 if err != nil {
@@ -347,6 +337,7 @@ parseLoop:
347337 value = number
348338 st = stMaybeComment
349339 case r == '"' || r == '`' :
340+ incomplete = false
350341 str , err := s .nextString ()
351342 if err != nil {
352343 return Tag {}, err
@@ -355,6 +346,7 @@ parseLoop:
355346 valueType = ValueTypeString
356347 st = stMaybeComment
357348 case isIdentBegin (r ):
349+ incomplete = false
358350 str , err := s .nextIdent (isIdentInterior )
359351 if err != nil {
360352 return Tag {}, err
@@ -371,27 +363,11 @@ parseLoop:
371363 }
372364 case stMaybeComment :
373365 switch {
374- case s .skipWhitespace ():
375- case r == '/' :
376- s .next ()
377- incomplete = true
378- st = stTrailingSlash
379- default :
380- break parseLoop
381- }
382- case stTrailingSlash :
383- switch {
384- case r == '/' :
385- s .next ()
386- incomplete = false
387- st = stTrailingComment
366+ case r == '/' && s .peekN (1 ) == '/' :
367+ s .remainder ()
388368 default :
389369 break parseLoop
390370 }
391- case stTrailingComment :
392- s .next ()
393- s .pos = len (s .buf )
394- break parseLoop
395371 default :
396372 return Tag {}, fmt .Errorf ("unexpected internal parser error: unknown state: %s at position %d" , st , s .pos )
397373 }
0 commit comments