diff options
author | Laurent Le Brun <laurentlb@gmail.com> | 2018-02-26 15:01:53 +0100 |
---|---|---|
committer | alandonovan <adonovan@google.com> | 2018-02-26 09:01:53 -0500 |
commit | 28ceca7fdc8d88c4b6a4a64453b2251e00f73f56 (patch) | |
tree | 3706e5e34d8cb7fc9426166d626ed9b185172496 | |
parent | 689fc22ccbdf8623bfa12ec5bcaf3484861f9bd5 (diff) | |
download | starlark-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.go | 6 | ||||
-rw-r--r-- | resolve/resolve.go | 6 | ||||
-rw-r--r-- | syntax/parse.go | 8 | ||||
-rw-r--r-- | syntax/parse_test.go | 14 | ||||
-rw-r--r-- | syntax/syntax.go | 13 | ||||
-rw-r--r-- | syntax/walk.go | 3 |
6 files changed, 41 insertions, 9 deletions
@@ -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) |