Repository: goplus/gop
Pull request #1513 (2023-11-02 12:22:22)

parser: fix parsePrimaryExpr check literal value


Patch:
diff --git a/parser/_instance/instance5/cmd.gop b/parser/_instance/instance5/cmd.gop
index b693b560..e185d378 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 1dc92068..fb6a2d13 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 2fc8a509..ef1d8a64 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) {


Test patch:
diff --git a/parser/parser_test.go b/parser/parser_test.go
index bb6c4bb1..a387edc4 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`, ``)
+}
+
 // -----------------------------------------------------------------------------