diff --git a/parser/_instance/instance5/cmd.gop b/parser/_instance/instance5/cmd.gop index b693b560a..e185d378c 100644 --- a/parser/_instance/instance5/cmd.gop +++ b/parser/_instance/instance5/cmd.gop @@ -1,6 +1,11 @@ var a [2]int + if 0 < a[0] { println a - println T[int]{1} - println (T[int]){a:1,b:2} + println M[int]{1} + println T[int]{a: 1, b: 2} +} + +for _, i := range []int{7, 42} { + println i } diff --git a/parser/_instance/instance5/parser.expect b/parser/_instance/instance5/parser.expect index 1dc92068c..fb6a2d13e 100644 --- a/parser/_instance/instance5/parser.expect +++ b/parser/_instance/instance5/parser.expect @@ -70,7 +70,7 @@ ast.FuncDecl: ast.IndexExpr: X: ast.Ident: - Name: T + Name: M Index: ast.Ident: Name: int @@ -87,15 +87,13 @@ ast.FuncDecl: Args: ast.CompositeLit: Type: - ast.ParenExpr: + ast.IndexExpr: X: - ast.IndexExpr: - X: - ast.Ident: - Name: T - Index: - ast.Ident: - Name: int + ast.Ident: + Name: T + Index: + ast.Ident: + Name: int Elts: ast.KeyValueExpr: Key: @@ -113,3 +111,37 @@ ast.FuncDecl: ast.BasicLit: Kind: INT Value: 2 + ast.RangeStmt: + Key: + ast.Ident: + Name: _ + Value: + ast.Ident: + Name: i + Tok: := + X: + ast.CompositeLit: + Type: + ast.ArrayType: + Elt: + ast.Ident: + Name: int + Elts: + ast.BasicLit: + Kind: INT + Value: 7 + ast.BasicLit: + Kind: INT + Value: 42 + Body: + ast.BlockStmt: + List: + ast.ExprStmt: + X: + ast.CallExpr: + Fun: + ast.Ident: + Name: println + Args: + ast.Ident: + Name: i diff --git a/parser/parser.go b/parser/parser.go index 2fc8a509c..ef1d8a646 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -2068,29 +2068,6 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr { return x } -// isLiteralType reports whether x is a legal composite literal type. -func isLiteralType(x ast.Expr) bool { - switch t := unparen(x).(type) { - case *ast.BadExpr: - case *ast.Ident: - case *ast.IndexExpr: - _, isIdent := t.X.(*ast.Ident) - return isIdent - case *ast.IndexListExpr: - _, isIdent := t.X.(*ast.Ident) - return isIdent - case *ast.SelectorExpr: - _, isIdent := t.X.(*ast.Ident) - return isIdent - case *ast.ArrayType: - case *ast.StructType: - case *ast.MapType: - default: - return false // all other nodes are not legal composite literal types - } - return true -} - /* // If x is of the form *T, deref returns T, otherwise it returns x. func deref(x ast.Expr) ast.Expr { @@ -2174,13 +2151,30 @@ L: case token.LBRACE: // { if allowCmd && p.isCmd(x) { // println {...} x = p.parseCallOrConversion(p.checkExprOrType(x), true) - } else if isLiteralType(x) && p.exprLev >= 0 { - if lhs { - p.resolve(x) + } else { + t := unparen(x) + // determine if '{' belongs to a composite literal or a block statement + switch t.(type) { + case *ast.BadExpr, *ast.Ident, *ast.SelectorExpr: + if p.exprLev < 0 { + break L + } + // x is possibly a composite literal type + case *ast.IndexExpr, *ast.IndexListExpr: + if p.exprLev < 0 { + break L + } + // x is possibly a composite literal type + case *ast.ArrayType, *ast.StructType, *ast.MapType: + // x is a composite literal type + default: + break L + } + if t != x { + p.error(t.Pos(), "cannot parenthesize type in composite literal") + // already progressed, no need to advance } x = p.parseLiteralValue(x) - } else { - break L } case token.NOT: if allowCmd && p.isCmd(x) { diff --git a/parser/parser_test.go b/parser/parser_test.go index bb6c4bb13..a387edc41 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -513,4 +513,9 @@ func TestErrGlobal(t *testing.T) { }`, `/foo/bar.gop:2:1: expected statement, found '}'`, ``) } +func TestErrCompositeLiteral(t *testing.T) { + testErrCode(t, `println (T[int]){a: 1, b: 2} +`, `/foo/bar.gop:1:10: cannot parenthesize type in composite literal`, ``) +} + // -----------------------------------------------------------------------------