Fixed the issue with colons in ident

This commit is contained in:
Leon Mika 2024-05-04 11:35:31 +10:00
parent 78720eeb5b
commit 0dc9fd3c32
5 changed files with 35 additions and 27 deletions

View file

@ -2,6 +2,7 @@ package ucl
import ( import (
"io" "io"
"strings"
"github.com/alecthomas/participle/v2" "github.com/alecthomas/participle/v2"
"github.com/alecthomas/participle/v2/lexer" "github.com/alecthomas/participle/v2/lexer"
@ -12,11 +13,19 @@ type astLiteral struct {
Int *int `parser:"| @Int"` Int *int `parser:"| @Int"`
} }
type astHashKey struct { type astIdentNames struct {
Literal *astLiteral `parser:"@@"` Ident string `parser:"@Ident"`
Ident *string `parser:"| @Ident"` ColonParts []string `parser:"( COLON @Ident )*"`
Var *string `parser:"| DOLLAR @Ident"` }
Sub *astPipeline `parser:"| LP @@ RP"`
func (ai *astIdentNames) String() string {
sb := strings.Builder{}
sb.WriteString(ai.Ident)
for _, p := range ai.ColonParts {
sb.WriteRune(':')
sb.WriteString(p)
}
return sb.String()
} }
type astElementPair struct { type astElementPair struct {
@ -41,7 +50,7 @@ type astMaybeSub struct {
type astCmdArg struct { type astCmdArg struct {
Literal *astLiteral `parser:"@@"` Literal *astLiteral `parser:"@@"`
Ident *string `parser:"| @Ident"` Ident *astIdentNames `parser:"| @@"`
Var *string `parser:"| DOLLAR @Ident"` Var *string `parser:"| DOLLAR @Ident"`
MaybeSub *astMaybeSub `parser:"| LP @@ RP"` MaybeSub *astMaybeSub `parser:"| LP @@ RP"`
ListOrHash *astListOrHash `parser:"| @@"` ListOrHash *astListOrHash `parser:"| @@"`
@ -83,7 +92,7 @@ var scanner = lexer.MustStateful(lexer.Rules{
{"RC", `\}`, nil}, {"RC", `\}`, nil},
{"NL", `[;\n][; \n\t]*`, nil}, {"NL", `[;\n][; \n\t]*`, nil},
{"PIPE", `\|`, nil}, {"PIPE", `\|`, nil},
{"Ident", `[-]*[a-zA-Z_:][\w-:]*`, nil}, {"Ident", `[-]*[a-zA-Z_][\w-]*`, nil},
}, },
}) })
var parser = participle.MustBuild[astScript](participle.Lexer(scanner), var parser = participle.MustBuild[astScript](participle.Lexer(scanner),

View file

@ -334,18 +334,17 @@ func foreachBuiltin(ctx context.Context, args macroArgs) (object, error) {
} }
} }
} }
case hashObject: case hashable:
for k, v := range t { err := t.Each(func(k string, v object) error {
last, err = args.evalBlock(ctx, blockIdx, []object{strObject(k), v}, true) last, err = args.evalBlock(ctx, blockIdx, []object{strObject(k), v}, true)
if err != nil { return err
if errors.As(err, &breakErr) { })
if !breakErr.isCont { if errors.As(err, &breakErr) {
return breakErr.ret, nil if !breakErr.isCont {
} return breakErr.ret, nil
} else {
return nil, err
}
} }
} else {
return nil, err
} }
} }

View file

@ -72,7 +72,7 @@ func (e evaluator) evalPipeline(ctx context.Context, ec *evalCtx, n *astPipeline
func (e evaluator) evalCmd(ctx context.Context, ec *evalCtx, currentPipe object, ast *astCmd) (object, error) { func (e evaluator) evalCmd(ctx context.Context, ec *evalCtx, currentPipe object, ast *astCmd) (object, error) {
switch { switch {
case ast.Name.Ident != nil: case ast.Name.Ident != nil:
name := *ast.Name.Ident name := ast.Name.Ident.String()
// Regular command // Regular command
if cmd := ec.lookupInvokable(name); cmd != nil { if cmd := ec.lookupInvokable(name); cmd != nil {
@ -117,14 +117,14 @@ func (e evaluator) evalInvokable(ctx context.Context, ec *evalCtx, currentPipe o
argsPtr.Append(currentPipe) argsPtr.Append(currentPipe)
} }
for _, arg := range ast.Args { for _, arg := range ast.Args {
if ident := arg.Ident; ident != nil && (*ident)[0] == '-' { if ident := arg.Ident; ident != nil && ident.String()[0] == '-' {
// Arg switch // Arg switch
if kwargs == nil { if kwargs == nil {
kwargs = make(map[string]*listObject) kwargs = make(map[string]*listObject)
} }
argsPtr = &listObject{} argsPtr = &listObject{}
kwargs[(*ident)[1:]] = argsPtr kwargs[ident.String()[1:]] = argsPtr
} else { } else {
ae, err := e.evalArg(ctx, ec, arg) ae, err := e.evalArg(ctx, ec, arg)
if err != nil { if err != nil {
@ -153,7 +153,7 @@ func (e evaluator) evalArg(ctx context.Context, ec *evalCtx, n astCmdArg) (objec
case n.Literal != nil: case n.Literal != nil:
return e.evalLiteral(ctx, ec, n.Literal) return e.evalLiteral(ctx, ec, n.Literal)
case n.Ident != nil: case n.Ident != nil:
return strObject(*n.Ident), nil return strObject(n.Ident.String()), nil
case n.Var != nil: case n.Var != nil:
if v, ok := ec.getVar(*n.Var); ok { if v, ok := ec.getVar(*n.Var); ok {
return v, nil return v, nil

View file

@ -194,7 +194,7 @@ func (ma macroArgs) identIs(ctx context.Context, n int, expectedIdent string) bo
return false return false
} }
return *lit == expectedIdent return lit.String() == expectedIdent
} }
func (ma *macroArgs) shiftIdent(ctx context.Context) (string, bool) { func (ma *macroArgs) shiftIdent(ctx context.Context) (string, bool) {
@ -205,7 +205,7 @@ func (ma *macroArgs) shiftIdent(ctx context.Context) (string, bool) {
lit := ma.ast.Args[ma.argShift].Ident lit := ma.ast.Args[ma.argShift].Ident
if lit != nil { if lit != nil {
ma.argShift += 1 ma.argShift += 1
return *lit, true return lit.String(), true
} }
return "", false return "", false
} }

View file

@ -465,20 +465,20 @@ func TestBuiltins_Map(t *testing.T) {
proc makeUpper { |x| $x | toUpper } proc makeUpper { |x| $x | toUpper }
map ["a" "b" "c"] (proc { |x| makeUpper $x }) map ["a" "b" "c"] (proc { |x| makeUpper $x })
`, want: "[A B C]\n"}, `, want: "A\nB\nC\n"},
{desc: "map list 2", expr: ` {desc: "map list 2", expr: `
set makeUpper (proc { |x| $x | toUpper }) set makeUpper (proc { |x| $x | toUpper })
map ["a" "b" "c"] $makeUpper map ["a" "b" "c"] $makeUpper
`, want: "[A B C]\n"}, `, want: "A\nB\nC\n"},
{desc: "map list with pipe", expr: ` {desc: "map list with pipe", expr: `
set makeUpper (proc { |x| $x | toUpper }) set makeUpper (proc { |x| $x | toUpper })
["a" "b" "c"] | map $makeUpper ["a" "b" "c"] | map $makeUpper
`, want: "[A B C]\n"}, `, want: "A\nB\nC\n"},
{desc: "map list with block", expr: ` {desc: "map list with block", expr: `
map ["a" "b" "c"] { |x| toUpper $x } map ["a" "b" "c"] { |x| toUpper $x }
`, want: "[A B C]\n"}, `, want: "A\nB\nC\n"},
{desc: "map list with stream", expr: ` {desc: "map list with stream", expr: `
set makeUpper (proc { |x| toUpper $x }) set makeUpper (proc { |x| toUpper $x })