internal/rosa/azalea: implement semicolon and comma insertion

This commit is contained in:
2026-08-08 11:58:30 -05:00
parent d236c9eaf7
commit 052ec33a04
2 changed files with 126 additions and 41 deletions
+91 -6
View File
@@ -4,8 +4,11 @@ package azalea
import (
"errors"
"fmt"
"io"
"os"
"strconv"
"strings"
"text/scanner"
)
@@ -302,6 +305,7 @@ func (ScanError) Error() string {
// Parse parses expressions from r.
func Parse(r io.Reader) (e []any, err error) {
r, err = insertSemicolons(r)
var p parser
p.s.Init(r)
@@ -311,12 +315,7 @@ func Parse(r io.Reader) (e []any, err error) {
scanner.ScanRawStrings |
scanner.ScanComments |
scanner.SkipComments
p.s.IsIdentRune = func(ch rune, i int) bool {
if i == 0 && ch >= '0' && ch <= '9' {
return false
}
return ch > 0 && ch < rune(len(idents)) && idents[ch]
}
p.s.IsIdentRune = isIdentRune
defer func() {
v := recover()
@@ -346,3 +345,89 @@ func Parse(r io.Reader) (e []any, err error) {
}
return
}
func isIdentRune(ch rune, i int) bool {
if i == 0 && ch >= '0' && ch <= '9' {
return false
}
return ch > 0 && ch < rune(len(idents)) && idents[ch]
}
func insertSemicolons(r io.Reader) (io.Reader, error) {
var s scanner.Scanner
s.Init(r)
s.Mode = scanner.ScanIdents |
scanner.ScanInts |
scanner.ScanStrings |
scanner.ScanRawStrings |
scanner.ScanComments |
scanner.SkipComments
s.Whitespace = 0
s.IsIdentRune = isIdentRune
var buf strings.Builder
nlsemi := false
nlcomma := false
b := ""
tok := s.Scan()
for tok != scanner.EOF {
switch tok {
case '\n':
if b[len(b)-1] == '{' && nlsemi {
buf.WriteRune(';')
nlsemi = false
}
if b[len(b)-1] == '[' && nlcomma {
buf.WriteRune(',')
nlcomma = false
}
case ';':
buf.WriteRune(tok)
nlsemi = false
case ',':
buf.WriteRune(tok)
nlcomma = false
case '{', '[':
nlsemi = false
buf.WriteRune(tok)
b += string(tok)
case '}', ']':
if len(b) > 0 && b[len(b)-1] == '{' && nlsemi {
buf.WriteRune(';')
nlsemi = false
}
if len(b) > 0 && b[len(b)-1] == '[' && nlcomma {
buf.WriteRune(',')
nlcomma = false
}
if len(b) > 1 && b[len(b)-1] == '{' {
nlsemi = true
}
if len(b) > 1 && b[len(b)-1] == '[' {
nlcomma = true
nlsemi = true
}
if len(b) > 1 {
b = b[:len(b)-1]
}
buf.WriteRune(tok)
case '+', ':', '=':
buf.WriteRune(tok)
nlsemi = false
nlcomma = false
case scanner.String, scanner.RawString, scanner.Int, scanner.Ident:
buf.WriteString(s.TokenText())
if len(b) > 0 && b[len(b)-1] == '{' {
nlsemi = true
} else if len(b) > 0 && b[len(b)-1] == '[' {
nlcomma = true
}
default:
buf.WriteString(s.TokenText())
}
tok = s.Scan()
}
fmt.Fprintln(os.Stderr, buf.String())
return strings.NewReader(buf.String()), nil
}