Skip to content

Commit

Permalink
Merge pull request #3662 from RZhang05/expression-string-template
Browse files Browse the repository at this point in the history
Support expressions in string template
  • Loading branch information
SupunS authored Nov 14, 2024
2 parents 33c0ded + 7e35480 commit d155b01
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 123 deletions.
49 changes: 49 additions & 0 deletions interpreter/misc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12509,4 +12509,53 @@ func TestInterpretStringTemplates(t *testing.T) {
inter.Globals.Get("x").GetValue(inter),
)
})

t.Run("func", func(t *testing.T) {
t.Parallel()

inter := parseCheckAndInterpret(t, `
let add = fun(): Int {
return 2+2
}
let x: String = "\(add())"
`)

AssertValuesEqual(
t,
inter,
interpreter.NewUnmeteredStringValue("4"),
inter.Globals.Get("x").GetValue(inter),
)
})

t.Run("ternary", func(t *testing.T) {
t.Parallel()

inter := parseCheckAndInterpret(t, `
let z = false
let x: String = "\(z ? "foo" : "bar" )"
`)

AssertValuesEqual(
t,
inter,
interpreter.NewUnmeteredStringValue("bar"),
inter.Globals.Get("x").GetValue(inter),
)
})

t.Run("nested", func(t *testing.T) {
t.Parallel()

inter := parseCheckAndInterpret(t, `
let x: String = "\(2*(4-2) + 1 == 5)"
`)

AssertValuesEqual(
t,
inter,
interpreter.NewUnmeteredStringValue("true"),
inter.Globals.Get("x").GetValue(inter),
)
})
}
4 changes: 0 additions & 4 deletions parser/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -1191,10 +1191,6 @@ func defineStringExpression() {
if err != nil {
return nil, err
}
// limit string templates to identifiers only
if _, ok := value.(*ast.IdentifierExpression); !ok {
return nil, p.syntaxError("expected identifier got: %s", value.String())
}
_, err = p.mustOne(lexer.TokenParenClose)
if err != nil {
return nil, err
Expand Down
181 changes: 62 additions & 119 deletions parser/expression_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6054,14 +6054,7 @@ func TestParseStringTemplate(t *testing.T) {
"\(test)"
`)

var err error
if len(errs) > 0 {
err = Error{
Errors: errs,
}
}

require.NoError(t, err)
require.Empty(t, errs)

expected := &ast.StringTemplateExpression{
Values: []string{
Expand Down Expand Up @@ -6093,14 +6086,7 @@ func TestParseStringTemplate(t *testing.T) {
"this is a test \(abc)\(def) test"
`)

var err error
if len(errs) > 0 {
err = Error{
Errors: errs,
}
}

require.NoError(t, err)
require.Empty(t, errs)

expected := &ast.StringTemplateExpression{
Values: []string{
Expand Down Expand Up @@ -6139,14 +6125,7 @@ func TestParseStringTemplate(t *testing.T) {
"this is a test \(FOO)
`)

var err error
if len(errs) > 0 {
err = Error{
Errors: errs,
}
}

require.Error(t, err)
require.NotEmpty(t, errs)
AssertEqualWithDiff(t,
[]error{
&SyntaxError{
Expand All @@ -6166,14 +6145,7 @@ func TestParseStringTemplate(t *testing.T) {
"\(.)"
`)

var err error
if len(errs) > 0 {
err = Error{
Errors: errs,
}
}

require.Error(t, err)
require.NotEmpty(t, errs)
AssertEqualWithDiff(t,
[]error{
&SyntaxError{
Expand All @@ -6185,31 +6157,15 @@ func TestParseStringTemplate(t *testing.T) {
)
})

t.Run("invalid, num", func(t *testing.T) {
t.Run("valid, num", func(t *testing.T) {

t.Parallel()

_, errs := testParseExpression(`
"\(2 + 2) is a"
`)

var err error
if len(errs) > 0 {
err = Error{
Errors: errs,
}
}

require.Error(t, err)
AssertEqualWithDiff(t,
[]error{
&SyntaxError{
Message: "expected identifier got: 2 + 2",
Pos: ast.Position{Offset: 13, Line: 2, Column: 12},
},
},
errs,
)
require.Empty(t, errs)
})

t.Run("valid, nested identifier", func(t *testing.T) {
Expand All @@ -6220,14 +6176,7 @@ func TestParseStringTemplate(t *testing.T) {
"\((a))"
`)

var err error
if len(errs) > 0 {
err = Error{
Errors: errs,
}
}

require.NoError(t, err)
require.Empty(t, errs)

expected := &ast.StringTemplateExpression{
Values: []string{
Expand Down Expand Up @@ -6259,14 +6208,7 @@ func TestParseStringTemplate(t *testing.T) {
"\()"
`)

var err error
if len(errs) > 0 {
err = Error{
Errors: errs,
}
}

require.Error(t, err)
require.NotEmpty(t, errs)
AssertEqualWithDiff(t,
[]error{
&SyntaxError{
Expand All @@ -6278,54 +6220,51 @@ func TestParseStringTemplate(t *testing.T) {
)
})

t.Run("invalid, function identifier", func(t *testing.T) {
t.Run("valid, function identifier", func(t *testing.T) {

t.Parallel()

_, errs := testParseExpression(`
"\(add())"
`)

var err error
if len(errs) > 0 {
err = Error{
Errors: errs,
}
}
require.Empty(t, errs)
})

require.Error(t, err)
t.Run("invalid, missing paren", func(t *testing.T) {

t.Parallel()

_, errs := testParseExpression(`
"\(add"
`)

require.NotEmpty(t, errs)
AssertEqualWithDiff(t,
[]error{
&SyntaxError{
Message: "expected identifier got: add()",
Pos: ast.Position{Offset: 12, Line: 2, Column: 11},
Message: "expected token ')'",
Pos: ast.Position{Offset: 10, Line: 2, Column: 9},
},
},
errs,
)
})

t.Run("invalid, unbalanced paren", func(t *testing.T) {
t.Run("invalid, nested expression paren", func(t *testing.T) {

t.Parallel()

_, errs := testParseExpression(`
"\(add"
"\((2+2)/2()"
`)

var err error
if len(errs) > 0 {
err = Error{
Errors: errs,
}
}

require.Error(t, err)
require.NotEmpty(t, errs)
AssertEqualWithDiff(t,
[]error{
&SyntaxError{
Message: "expected token ')'",
Pos: ast.Position{Offset: 10, Line: 2, Column: 9},
Pos: ast.Position{Offset: 16, Line: 2, Column: 15},
},
},
errs,
Expand All @@ -6340,14 +6279,7 @@ func TestParseStringTemplate(t *testing.T) {
"outer string \( "\(inner template)" )"
`)

var err error
if len(errs) > 0 {
err = Error{
Errors: errs,
}
}

require.Error(t, err)
require.NotEmpty(t, errs)
AssertEqualWithDiff(t,
[]error{
&SyntaxError{
Expand All @@ -6367,14 +6299,7 @@ func TestParseStringTemplate(t *testing.T) {
"a\(b)c"
`)

var err error
if len(errs) > 0 {
err = Error{
Errors: errs,
}
}

require.NoError(t, err)
require.Empty(t, errs)

expected := &ast.StringTemplateExpression{
Values: []string{
Expand Down Expand Up @@ -6406,14 +6331,7 @@ func TestParseStringTemplate(t *testing.T) {
"\(a)b\(c)"
`)

var err error
if len(errs) > 0 {
err = Error{
Errors: errs,
}
}

require.NoError(t, err)
require.Empty(t, errs)

expected := &ast.StringTemplateExpression{
Values: []string{
Expand Down Expand Up @@ -6452,14 +6370,7 @@ func TestParseStringTemplate(t *testing.T) {
"\(a)\(b)\(c)"
`)

var err error
if len(errs) > 0 {
err = Error{
Errors: errs,
}
}

require.NoError(t, err)
require.Empty(t, errs)

expected := &ast.StringTemplateExpression{
Values: []string{
Expand Down Expand Up @@ -6496,6 +6407,38 @@ func TestParseStringTemplate(t *testing.T) {

AssertEqualWithDiff(t, expected, actual)
})

t.Run("valid, extra closing paren", func(t *testing.T) {

t.Parallel()

actual, errs := testParseExpression(`
"\(a))"
`)

require.Empty(t, errs)

expected := &ast.StringTemplateExpression{
Values: []string{
"",
")",
},
Expressions: []ast.Expression{
&ast.IdentifierExpression{
Identifier: ast.Identifier{
Identifier: "a",
Pos: ast.Position{Offset: 7, Line: 2, Column: 6},
},
},
},
Range: ast.Range{
StartPos: ast.Position{Offset: 4, Line: 2, Column: 3},
EndPos: ast.Position{Offset: 10, Line: 2, Column: 9},
},
}

AssertEqualWithDiff(t, expected, actual)
})
}

func TestParseNilCoalescing(t *testing.T) {
Expand Down
Loading

0 comments on commit d155b01

Please sign in to comment.