internal/rosa/azalea: refactor delimiter insertion, add test

This commit is contained in:
2026-08-08 14:25:37 -05:00
parent a81e2f251c
commit 9eb3ecd942
2 changed files with 36 additions and 26 deletions
+15 -16
View File
@@ -303,7 +303,7 @@ func (ScanError) Error() string {
// Parse parses expressions from r. // Parse parses expressions from r.
func Parse(r io.Reader) (e []any, err error) { func Parse(r io.Reader) (e []any, err error) {
r, err = insertDelimiters(r) r = insertDelimiters(r)
var p parser var p parser
p.s.Init(r) p.s.Init(r)
@@ -349,7 +349,7 @@ func isIdentRune(ch rune, i int) bool {
} }
return ch > 0 && ch < rune(len(idents)) && idents[ch] return ch > 0 && ch < rune(len(idents)) && idents[ch]
} }
func insertDelimiters(r io.Reader) (io.Reader, error) { func insertDelimiters(r io.Reader) io.Reader {
var s scanner.Scanner var s scanner.Scanner
s.Init(r) s.Init(r)
s.Mode = scanner.ScanIdents | s.Mode = scanner.ScanIdents |
@@ -361,44 +361,43 @@ func insertDelimiters(r io.Reader) (io.Reader, error) {
s.Whitespace = 0 s.Whitespace = 0
s.IsIdentRune = isIdentRune s.IsIdentRune = isIdentRune
var buf strings.Builder var b strings.Builder
nldelim := false nldelim := false
b := new(runeStack) delim := new(runeStack)
for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() { for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
switch tok { switch tok {
case '{', '[': case '{', '[':
nldelim = false nldelim = false
if tok == '{' { if tok == '{' {
b.Push(';') delim.Push(';')
} else { } else {
b.Push(',') delim.Push(',')
} }
buf.WriteRune(tok) b.WriteRune(tok)
case scanner.String, scanner.RawString, scanner.Int, scanner.Ident: case scanner.String, scanner.RawString, scanner.Int, scanner.Ident:
buf.WriteString(s.TokenText()) b.WriteString(s.TokenText())
nldelim = true nldelim = true
case '+', ':', '=', ',', ';': case '+', ':', '=', ',', ';':
nldelim = false nldelim = false
buf.WriteRune(tok) b.WriteRune(tok)
case '\n': case '\n':
if nldelim { if nldelim {
buf.WriteRune(b.Peek()) b.WriteRune(delim.Peek())
nldelim = false nldelim = false
} }
buf.WriteRune(tok)
case '}', ']': case '}', ']':
if nldelim { if nldelim {
buf.WriteRune(b.Peek()) b.WriteRune(delim.Peek())
} }
b.Pop() delim.Pop()
nldelim = true nldelim = true
buf.WriteRune(tok) b.WriteRune(tok)
default: default:
buf.WriteRune(tok) b.WriteRune(tok)
} }
} }
return strings.NewReader(buf.String()), nil return strings.NewReader(b.String())
} }
type runeStack struct { type runeStack struct {
+21 -10
View File
@@ -64,7 +64,22 @@ func TestParse(t *testing.T) {
{"missing array delimiter", `[ v0 v1 ]`, nil, TokenError{',', scanner.Ident}}, {"missing array delimiter", `[ v0 v1 ]`, nil, TokenError{',', scanner.Ident}},
{"truncated array", `[ "\x00"`, nil, {"truncated array", `[ "\x00"`, nil,
ExprError(scanner.EOF)}, ExprError(scanner.EOF)},
{"array of func", "[\nf {\n v = v\n v2 =\n v2\n }\n g {\n w = w\n w2 = w2\n}\n]\n", []any{Array{
Val{Func{
Ident: Ident("f"),
Args: []Arg{
{K: []Ident{Ident("v")}, V: Val{Ident("v")}},
{K: []Ident{Ident("v2")}, V: Val{Ident("v2")}},
},
}},
Val{Func{
Ident: Ident("g"),
Args: []Arg{
{K: []Ident{Ident("w")}, V: Val{Ident("w")}},
{K: []Ident{Ident("w2")}, V: Val{Ident("w2")}},
},
}},
}}, nil},
{"gcc", gccSample, []any{Func{ {"gcc", gccSample, []any{Func{
Ident: Ident("gcc"), Ident: Ident("gcc"),
Package: true, Package: true,
@@ -153,8 +168,7 @@ func TestParse(t *testing.T) {
{K: []Ident{Ident("version")}, V: Val{String("26.2.0")}, R: true}, {K: []Ident{Ident("version")}, V: Val{String("26.2.0")}, R: true},
{K: []Ident{Ident("source")}, V: Val{Func{ {K: []Ident{Ident("source")}, V: Val{Func{
Ident: Ident("remoteGitLab"), Ident: Ident("remoteGitLab"),
Package: false,
Args: []Arg{ Args: []Arg{
{K: []Ident{Ident("domain")}, V: Val{String("gitlab.freedesktop.org")}}, {K: []Ident{Ident("domain")}, V: Val{String("gitlab.freedesktop.org")}},
{K: []Ident{Ident("suffix")}, V: Val{String("mesa/mesa")}}, {K: []Ident{Ident("suffix")}, V: Val{String("mesa/mesa")}},
@@ -162,7 +176,7 @@ func TestParse(t *testing.T) {
{K: []Ident{Ident("checksum")}, V: Val{String("UPnIdpo5wUsE938GXY-YyYDzfF62enRoEzCYRyLLPvzBhBbP4wZ8nDiKsjivcs5v")}}, {K: []Ident{Ident("checksum")}, V: Val{String("UPnIdpo5wUsE938GXY-YyYDzfF62enRoEzCYRyLLPvzBhBbP4wZ8nDiKsjivcs5v")}},
}, },
}}}, }}},
{K: []Ident{Ident("exec")}, V: Val{Func{Ident: Ident("meson"), Package: false, Args: []Arg{ {K: []Ident{Ident("exec")}, V: Val{Func{Ident: Ident("meson"), Args: []Arg{
{K: []Ident{Ident("setup")}, V: Val{[]KV{ {K: []Ident{Ident("setup")}, V: Val{[]KV{
{K: String("platforms"), V: Val{String("x11,wayland")}}, {K: String("platforms"), V: Val{String("x11,wayland")}},
{K: String("video-codecs"), V: Val{String("all")}}, {K: String("video-codecs"), V: Val{String("all")}},
@@ -170,8 +184,7 @@ func TestParse(t *testing.T) {
{K: String("gbm"), V: Val{String("enabled")}}, {K: String("gbm"), V: Val{String("enabled")}},
{K: String("egl"), V: Val{String("enabled")}}, {K: String("egl"), V: Val{String("enabled")}},
{K: String("gallium-drivers"), V: Val{Func{ {K: String("gallium-drivers"), V: Val{Func{
Ident: Ident("join"), Ident: Ident("join"),
Package: false,
Args: []Arg{ Args: []Arg{
{K: []Ident{Ident("elems")}, V: Val{Array{ {K: []Ident{Ident("elems")}, V: Val{Array{
Val{String("asahi")}, Val{String("asahi")},
@@ -198,8 +211,7 @@ func TestParse(t *testing.T) {
}, },
}}}, }}},
{K: String("vulkan-drivers"), V: Val{Func{ {K: String("vulkan-drivers"), V: Val{Func{
Ident: Ident("join"), Ident: Ident("join"),
Package: false,
Args: []Arg{ Args: []Arg{
{K: []Ident{Ident("elems")}, V: Val{Array{ {K: []Ident{Ident("elems")}, V: Val{Array{
Val{String("amd")}, Val{String("amd")},
@@ -217,8 +229,7 @@ func TestParse(t *testing.T) {
{K: []Ident{Ident("sep")}, V: Val{String(",")}}}, {K: []Ident{Ident("sep")}, V: Val{String(",")}}},
}}}, }}},
{K: String("vulkan-layers"), V: Val{Func{ {K: String("vulkan-layers"), V: Val{Func{
Ident: Ident("join"), Ident: Ident("join"),
Package: false,
Args: []Arg{ Args: []Arg{
{K: []Ident{Ident("elems")}, V: Val{Array{ {K: []Ident{Ident("elems")}, V: Val{Array{
Val{String("device-select")}, Val{String("device-select")},