@@ -17,7 +17,6 @@ limitations under the License.
1717package codetags
1818
1919import (
20- "bytes"
2120 "fmt"
2221 "strings"
2322 "unicode"
@@ -159,52 +158,34 @@ const (
159158func parseTag (input string , opts parseOpts ) (TypedTag , error ) {
160159 var startTag , endTag * TypedTag // both ends of the chain when parsing chained tags
161160
162- tag := bytes. Buffer {} // current tag name
163- var args [] Arg // all tag arguments
164- value := bytes. Buffer {} // current tag value
161+ // accumulators
162+ var tagName string // current tag name
163+ var value string // current value
165164 var valueType ValueType // current value type
166- var hasValue bool // true if the tag has a value
165+ cur := Arg {} // current argument
166+ var args []Arg // current arguments slice
167167
168- cur := Arg {} // current argument accumulator
169- buf := bytes. Buffer {} // string accumulator
168+ s := scanner { buf : [] rune ( input )} // scanner for parsing the tag string
169+ var incomplete bool // tracks if a token is incomplete
170170
171171 // These are defined outside the loop to make errors easier.
172- s := scanner {buf : []rune (input )}
173- var incomplete bool
174-
175- saveInt := func () error {
176- s := buf .String ()
177- cur .Value = s
178- cur .Type = ArgTypeInt
179- args = append (args , cur )
180- cur = Arg {}
181- buf .Reset ()
182- return nil
183- }
184- saveString := func () {
185- s := buf .String ()
186- cur .Value = s
187- cur .Type = ArgTypeString
172+ saveArg := func (v string , t ArgType ) {
173+ cur .Value = v
174+ cur .Type = t
188175 args = append (args , cur )
189176 cur = Arg {}
190- buf .Reset ()
191177 }
192- saveBoolOrString := func () {
193- s := buf . String ()
194- if s == "true" || s == "false" {
195- cur . Value = s
196- cur . Type = ArgTypeBool
178+ saveInt := func (v string ) { saveArg ( v , ArgTypeInt ) }
179+ saveString := func ( v string ) { saveArg ( v , ArgTypeString ) }
180+ saveBoolOrString := func ( value string ) {
181+ if value == "true" || value == "false" {
182+ saveArg ( value , ArgTypeBool )
197183 } else {
198- cur .Value = s
199- cur .Type = ArgTypeString
184+ saveArg (value , ArgTypeString )
200185 }
201- args = append (args , cur )
202- cur = Arg {}
203- buf .Reset ()
204186 }
205- saveName := func () {
206- cur .Name = buf .String ()
207- buf .Reset ()
187+ saveName := func (value string ) {
188+ cur .Name = value
208189 }
209190 saveTag := func () error {
210191 usingNamedArgs := false
@@ -219,8 +200,7 @@ func parseTag(input string, opts parseOpts) (TypedTag, error) {
219200 if ! usingNamedArgs && len (args ) > 1 {
220201 return fmt .Errorf ("multiple arguments must use 'name: value' syntax" )
221202 }
222-
223- newTag := & TypedTag {Name : tag .String (), Args : args }
203+ newTag := & TypedTag {Name : tagName , Args : args }
224204 if startTag == nil {
225205 startTag = newTag
226206 endTag = newTag
@@ -230,42 +210,34 @@ func parseTag(input string, opts parseOpts) (TypedTag, error) {
230210 endTag = newTag
231211 }
232212 args = nil // Reset to nil instead of empty slice
233- tag .Reset ()
234213 return nil
235214 }
236215 saveValue := func () {
237- endTag .Value = value .String ()
238- if opts .rawValues {
239- endTag .ValueType = ValueTypeRaw
240- return
241- }
216+ endTag .Value = value
242217 endTag .ValueType = valueType
243- if valueType == ValueTypeString && (endTag .Value == "true" || endTag .Value == "false" ) {
244- endTag .ValueType = ValueTypeBool
245- }
246218 }
247219 st := stBegin
248220parseLoop:
249221 for r := s .peek (); r != EOF ; r = s .peek () {
250222 switch st {
251223 case stBegin :
252224 switch {
253- case unicode .IsSpace (r ):
254- s .next ()
255- continue
225+ case s .skipWhitespace ():
256226 case isIdentBegin (r ):
227+ // did not consume
257228 st = stTag
258229 default :
259230 break parseLoop
260231 }
261232 case stTag :
262233 switch {
234+ case s .skipWhitespace ():
263235 case isIdentBegin (r ):
264236 ident , err := s .nextIdent (isTagNameInterior )
265237 if err != nil {
266238 return TypedTag {}, err
267239 }
268- tag . WriteString ( ident )
240+ tagName = ident
269241 st = stMaybeArgs
270242 default :
271243 break parseLoop
@@ -278,19 +250,20 @@ parseLoop:
278250 st = stArg
279251 case r == '=' :
280252 s .next ()
281- hasValue = true
253+ if opts .rawValues {
254+ valueType = ValueTypeRaw
255+ } else {
256+ incomplete = true
257+ }
282258 st = stValue
283- case unicode .IsSpace (r ):
284- s .next ()
259+ case s .skipWhitespace ():
285260 st = stMaybeComment
286261 default :
287262 break parseLoop
288263 }
289264 case stArg :
290265 switch {
291- case unicode .IsSpace (r ):
292- s .next ()
293- continue
266+ case s .skipWhitespace ():
294267 case r == ')' :
295268 s .next ()
296269 incomplete = false
@@ -300,43 +273,36 @@ parseLoop:
300273 if err != nil {
301274 return TypedTag {}, err
302275 }
303- buf .WriteString (number )
304- if err := saveInt (); err != nil {
305- return TypedTag {}, err
306- }
276+ saveInt (number )
307277 st = stArgEndOfToken
308278 case r == '"' || r == '`' :
309279 str , err := s .nextString ()
310280 if err != nil {
311281 return TypedTag {}, err
312282 }
313- buf .WriteString (str )
314- saveString ()
283+ saveString (str )
315284 st = stArgEndOfToken
316285 case isIdentBegin (r ):
317- str , err := s .nextIdent (isIdentInterior )
286+ identifier , err := s .nextIdent (isIdentInterior )
318287 if err != nil {
319288 return TypedTag {}, err
320289 }
321- buf .WriteString (str )
322- r = s .peek ()
290+ r = s .peek () // reset r after nextIdent
323291 switch {
324- case r == ',' || r == ')' || unicode . IsSpace ( r ):
325- saveBoolOrString ()
292+ case r == ',' || r == ')' || s . skipWhitespace ( ):
293+ saveBoolOrString (identifier )
326294 st = stArgEndOfToken
327295 case r == ':' :
328296 s .next ()
329- saveName ()
297+ saveName (identifier )
330298 st = stArg
331299 }
332300 default :
333301 break parseLoop
334302 }
335303 case stArgEndOfToken :
336304 switch {
337- case unicode .IsSpace (r ):
338- s .next ()
339- continue
305+ case s .skipWhitespace ():
340306 case r == ',' :
341307 s .next ()
342308 st = stArg
@@ -351,18 +317,21 @@ parseLoop:
351317 switch {
352318 case r == '=' :
353319 s .next ()
354- hasValue = true
320+ if opts .rawValues {
321+ valueType = ValueTypeRaw
322+ }
355323 st = stValue
356- case unicode .IsSpace (r ):
357- s .next ()
324+ case s .skipWhitespace ():
358325 st = stMaybeComment
359326 default :
360327 break parseLoop
361328 }
362329 case stValue :
330+ incomplete = false
363331 switch {
364332 case opts .rawValues : // When enabled, consume all remaining chars
365- value .WriteRune (s .next ())
333+ value = s .remainder ()
334+ break parseLoop
366335 case r == '+' && isIdentBegin (s .peekN (1 )): // tag value
367336 s .next () // consume +
368337 if err := saveTag (); err != nil {
@@ -375,32 +344,34 @@ parseLoop:
375344 if err != nil {
376345 return TypedTag {}, err
377346 }
378- value . WriteString ( number )
347+ value = number
379348 st = stMaybeComment
380349 case r == '"' || r == '`' :
381350 str , err := s .nextString ()
382351 if err != nil {
383352 return TypedTag {}, err
384353 }
385- value . WriteString ( str )
354+ value = str
386355 valueType = ValueTypeString
387356 st = stMaybeComment
388357 case isIdentBegin (r ):
389358 str , err := s .nextIdent (isIdentInterior )
390359 if err != nil {
391360 return TypedTag {}, err
392361 }
393- value .WriteString (str )
394- valueType = ValueTypeString
362+ value = str
363+ if str == "true" || str == "false" {
364+ valueType = ValueTypeBool
365+ } else {
366+ valueType = ValueTypeString
367+ }
395368 st = stMaybeComment
396369 default :
397370 break parseLoop
398371 }
399372 case stMaybeComment :
400373 switch {
401- case unicode .IsSpace (r ):
402- s .next ()
403- continue
374+ case s .skipWhitespace ():
404375 case r == '/' :
405376 s .next ()
406377 incomplete = true
@@ -434,7 +405,7 @@ parseLoop:
434405 if err := saveTag (); err != nil {
435406 return TypedTag {}, err
436407 }
437- if hasValue {
408+ if len ( valueType ) > 0 {
438409 saveValue ()
439410 }
440411 if startTag == nil {
0 commit comments