Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 38 additions & 5 deletions conf/lex.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ func (lx *lexer) pop() stateFn {

func (lx *lexer) emit(typ itemType) {
val := strings.Join(lx.stringParts, "") + lx.input[lx.start:lx.pos]

// Position of item in line where it started.
pos := lx.pos - lx.ilstart - len(val)
lx.items <- item{typ, val, lx.line, pos}
Expand Down Expand Up @@ -329,6 +328,9 @@ func lexBlockStart(lx *lexer) stateFn {
case topOptStart:
lx.push(lexBlockEnd)
return lexSkip(lx, lexBlockStart)
case topOptTerm:
lx.ignore()
return lx.pop()
case commentHashStart:
lx.push(lexBlockEnd)
return lexCommentStart
Expand All @@ -351,23 +353,54 @@ func lexBlockStart(lx *lexer) stateFn {
// At this point, the only valid item can be a key, so we back up
// and let the key lexer do the rest.
lx.backup()
lx.push(lexBlockEnd)
lx.push(lexBlockValueEnd)
return lexKeyStart
}

// lexBlockValueEnd is entered whenever a block-level value has been consumed.
// It must see only whitespace, and will turn back to lexBlockStart upon a new line.
// If it sees EOF, it will quit the lexer successfully.
func lexBlockValueEnd(lx *lexer) stateFn {
r := lx.next()
switch {
case r == commentHashStart:
// a comment will read to a new line for us.
lx.push(lexBlockValueEnd)
return lexCommentStart
case r == commentSlashStart:
rn := lx.next()
if rn == commentSlashStart {
lx.push(lexBlockValueEnd)
return lexCommentStart
}
lx.backup()
fallthrough
case isWhitespace(r):
return lexBlockValueEnd
case isNL(r) || r == optValTerm || r == topOptValTerm:
lx.ignore()
return lexBlockStart
case r == topOptTerm:
lx.backup()
return lexBlockEnd
}
return lx.errorf("Expected a block-level value to end with a new line, "+
"comment or EOF, but got '%v' instead.", r)
}

// lexBlockEnd is entered whenever a block-level value has been consumed.
// It must see only whitespace, and will turn back to lexTop upon a "}".
func lexBlockEnd(lx *lexer) stateFn {
r := lx.next()
switch {
case r == commentHashStart:
// a comment will read to a new line for us.
lx.push(lexBlockEnd)
lx.push(lexBlockStart)
return lexCommentStart
case r == commentSlashStart:
rn := lx.next()
if rn == commentSlashStart {
lx.push(lexBlockEnd)
lx.push(lexBlockStart)
return lexCommentStart
}
lx.backup()
Expand All @@ -381,7 +414,7 @@ func lexBlockEnd(lx *lexer) stateFn {
lx.ignore()
return lx.pop()
}
return lx.errorf("Expected a block-level value to end with a '}', but got '%v' instead.", r)
return lx.errorf("Expected a block-level to end with a '}', but got '%v' instead.", r)
}

// lexKeyStart consumes a key name up until the first non-whitespace character.
Expand Down
16 changes: 16 additions & 0 deletions conf/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,22 @@ func TestBlocks(t *testing.T) {
},
"", "",
},
{
"top line values in block scope",
`
{
"debug": False
"prof_port": 8221
"server_name": "aws-useast2-natscj1-1"
}
`,
map[string]any{
"debug": false,
"prof_port": int64(8221),
"server_name": "aws-useast2-natscj1-1",
},
"", "",
},
} {
t.Run(test.name, func(t *testing.T) {
f, err := os.CreateTemp(t.TempDir(), "nats.conf-")
Expand Down