aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Le Brun <laurentlb@gmail.com>2018-02-26 15:01:53 +0100
committeralandonovan <adonovan@google.com>2018-02-26 09:01:53 -0500
commit28ceca7fdc8d88c4b6a4a64453b2251e00f73f56 (patch)
tree3706e5e34d8cb7fc9426166d626ed9b185172496
parent689fc22ccbdf8623bfa12ec5bcaf3484861f9bd5 (diff)
downloadstarlark-go-28ceca7fdc8d88c4b6a4a64453b2251e00f73f56.tar.gz
Add new node ParenExpr (#65)
This is a no-op for the interpreter, but it adds more information to the AST.
-rw-r--r--eval.go6
-rw-r--r--resolve/resolve.go6
-rw-r--r--syntax/parse.go8
-rw-r--r--syntax/parse_test.go14
-rw-r--r--syntax/syntax.go13
-rw-r--r--syntax/walk.go3
6 files changed, 41 insertions, 9 deletions
diff --git a/eval.go b/eval.go
index de0192e..922ea5a 100644
--- a/eval.go
+++ b/eval.go
@@ -675,6 +675,9 @@ func assign(fr *Frame, pos syntax.Position, lhs syntax.Expr, rhs Value) error {
}
return setField(fr, x, lhs, rhs)
+ case *syntax.ParenExpr:
+ return assign(fr, pos, lhs.X, rhs)
+
default:
return fr.errorf(pos, "ill-formed assignment: %T", lhs)
}
@@ -879,6 +882,9 @@ func eval(fr *Frame, e syntax.Expr) (Value, error) {
case *syntax.LambdaExpr:
return evalFunction(fr, e.Lambda, "lambda", &e.Function)
+
+ case *syntax.ParenExpr:
+ return eval(fr, e.X)
}
start, _ := e.Span()
diff --git a/resolve/resolve.go b/resolve/resolve.go
index 14fdcdd..2d84e2a 100644
--- a/resolve/resolve.go
+++ b/resolve/resolve.go
@@ -491,6 +491,9 @@ func (r *resolver) assign(lhs syntax.Expr, isAugmented bool) {
r.assign(elem, isAugmented)
}
+ case *syntax.ParenExpr:
+ r.assign(lhs.X, isAugmented)
+
default:
name := strings.ToLower(strings.TrimPrefix(fmt.Sprintf("%T", lhs), "*syntax."))
r.errorf(syntax.Start(lhs), "can't assign to %s", name)
@@ -630,6 +633,9 @@ func (r *resolver) expr(e syntax.Expr) {
}
r.function(e.Lambda, "lambda", &e.Function)
+ case *syntax.ParenExpr:
+ r.expr(e.X)
+
default:
log.Fatalf("unexpected expr %T", e)
}
diff --git a/syntax/parse.go b/syntax/parse.go
index 42c8656..e7d3106 100644
--- a/syntax/parse.go
+++ b/syntax/parse.go
@@ -814,8 +814,12 @@ func (p *parser) parsePrimary() Expr {
return &TupleExpr{Lparen: lparen, Rparen: rparen}
}
e := p.parseExpr(true) // allow trailing comma
- p.consume(RPAREN)
- return e
+ rparen := p.consume(RPAREN)
+ return &ParenExpr{
+ Lparen: lparen,
+ X: e,
+ Rparen: rparen,
+ }
case MINUS, PLUS:
// unary minus/plus:
diff --git a/syntax/parse_test.go b/syntax/parse_test.go
index 13286dc..d511d3f 100644
--- a/syntax/parse_test.go
+++ b/syntax/parse_test.go
@@ -29,7 +29,7 @@ func TestExprParseTrees(t *testing.T) {
{`[x for x in y]`,
`(Comprehension Body=x Clauses=((ForClause Vars=x X=y)))`},
{`[x for x in (a if b else c)]`,
- `(Comprehension Body=x Clauses=((ForClause Vars=x X=(CondExpr Cond=b True=a False=c))))`},
+ `(Comprehension Body=x Clauses=((ForClause Vars=x X=(ParenExpr X=(CondExpr Cond=b True=a False=c)))))`},
{`x[i].f(42)`,
`(CallExpr Fn=(DotExpr X=(IndexExpr X=x Y=i) Name=f) Args=(42))`},
{`x.f()`,
@@ -65,11 +65,11 @@ func TestExprParseTrees(t *testing.T) {
{`()`,
`(TupleExpr)`},
{`(4,)`,
- `(TupleExpr List=(4))`},
+ `(ParenExpr X=(TupleExpr List=(4)))`},
{`(4)`,
- `4`},
+ `(ParenExpr X=4)`},
{`(4, 5)`,
- `(TupleExpr List=(4 5))`},
+ `(ParenExpr X=(TupleExpr List=(4 5)))`},
{`{}`,
`(DictExpr)`},
{`{"a": 1}`,
@@ -79,7 +79,7 @@ func TestExprParseTrees(t *testing.T) {
{`{"a": 1, "b": 2}`,
`(DictExpr List=((DictEntry Key="a" Value=1) (DictEntry Key="b" Value=2)))`},
{`{x: y for (x, y) in z}`,
- `(Comprehension Curly Body=(DictEntry Key=x Value=y) Clauses=((ForClause Vars=(TupleExpr List=(x y)) X=z)))`},
+ `(Comprehension Curly Body=(DictEntry Key=x Value=y) Clauses=((ForClause Vars=(ParenExpr X=(TupleExpr List=(x y))) X=z)))`},
{`{x: y for a in b if c}`,
`(Comprehension Curly Body=(DictEntry Key=x Value=y) Clauses=((ForClause Vars=a X=b) (IfClause Cond=c)))`},
{`-1 + +2`,
@@ -154,7 +154,7 @@ else:
{`x.f = 1`,
`(AssignStmt Op== LHS=(DotExpr X=x Name=f) RHS=1)`},
{`(x, y) = 1`,
- `(AssignStmt Op== LHS=(TupleExpr List=(x y)) RHS=1)`},
+ `(AssignStmt Op== LHS=(ParenExpr X=(TupleExpr List=(x y))) RHS=1)`},
{`load("", "a", b="c")`,
`(LoadStmt Module="" From=(a c) To=(a b))`},
{`if True: load("", "a", b="c")`, // load needn't be at toplevel
@@ -220,7 +220,7 @@ pass`,
(BranchStmt Token=pass)`},
{`x = (1 +
2)`,
- `(AssignStmt Op== LHS=x RHS=(BinaryExpr X=1 Op=+ Y=2))`},
+ `(AssignStmt Op== LHS=x RHS=(ParenExpr X=(BinaryExpr X=1 Op=+ Y=2)))`},
{`x = 1 \
+ 2`,
`(AssignStmt Op== LHS=x RHS=(BinaryExpr X=1 Op=+ Y=2))`},
diff --git a/syntax/syntax.go b/syntax/syntax.go
index 113c9c4..ba5e730 100644
--- a/syntax/syntax.go
+++ b/syntax/syntax.go
@@ -243,6 +243,7 @@ func (*IndexExpr) expr() {}
func (*LambdaExpr) expr() {}
func (*ListExpr) expr() {}
func (*Literal) expr() {}
+func (*ParenExpr) expr() {}
func (*SliceExpr) expr() {}
func (*TupleExpr) expr() {}
func (*UnaryExpr) expr() {}
@@ -276,6 +277,18 @@ func (x *Literal) Span() (start, end Position) {
return x.TokenPos, x.TokenPos.add(x.Raw)
}
+// A ParenExpr represents a parenthesized expression: (X).
+type ParenExpr struct {
+ commentsRef
+ Lparen Position
+ X Expr
+ Rparen Position
+}
+
+func (x *ParenExpr) Span() (start, end Position) {
+ return x.Lparen, x.Rparen.add(")")
+}
+
// A CallExpr represents a function call expression: Fn(Args).
type CallExpr struct {
commentsRef
diff --git a/syntax/walk.go b/syntax/walk.go
index aeda473..8f20509 100644
--- a/syntax/walk.go
+++ b/syntax/walk.go
@@ -68,6 +68,9 @@ func Walk(n Node, f func(Node) bool) {
Walk(x, f)
}
+ case *ParenExpr:
+ Walk(n.X, f)
+
case *CondExpr:
Walk(n.Cond, f)
Walk(n.True, f)