Skip to content

Commit 271cbf8

Browse files
committed
Apply feedback
1 parent c926ad7 commit 271cbf8

File tree

4 files changed

+254
-193
lines changed

4 files changed

+254
-193
lines changed

v2/codetags/parser.go

Lines changed: 56 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package codetags
1818

1919
import (
20-
"bytes"
2120
"fmt"
2221
"strings"
2322
"unicode"
@@ -159,52 +158,34 @@ const (
159158
func 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
248220
parseLoop:
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

Comments
 (0)