From ae1ec83271b8e35e33e2006359b2b10811cf7ec0 Mon Sep 17 00:00:00 2001 From: visualfc Date: Sun, 3 Jul 2022 09:13:02 +0800 Subject: [PATCH 1/8] parser: parseCallOrConversion iscmd check tuple to list --- parser/parser.go | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index aeb337604..ed74768db 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -1412,11 +1412,11 @@ func (p *parser) parseOperand(lhs, allowTuple, allowCmd bool) ast.Expr { x := p.parseRHSOrType() // types may be parenthesized: (some type) if allowTuple && p.tok == token.COMMA { // (x, y, ...) => expr - items := make([]*ast.Ident, 1, 2) - items[0] = p.toIdent(x) + items := make([]ast.Expr, 1, 2) + items[0] = x for p.tok == token.COMMA { p.next() - items = append(items, p.parseIdent()) + items = append(items, p.parseRHSOrType()) } p.exprLev-- p.expect(token.RPAREN) @@ -1568,7 +1568,6 @@ func (p *parser) parseCallOrConversion(fun ast.Expr, isCmd bool) *ast.CallExpr { if p.trace { defer un(trace(p, "CallOrConversion")) } - var lparen, rparen token.Pos var endTok token.Token if isCmd { @@ -1580,7 +1579,12 @@ func (p *parser) parseCallOrConversion(fun ast.Expr, isCmd bool) *ast.CallExpr { var list []ast.Expr var ellipsis token.Pos for p.tok != endTok && p.tok != token.EOF && !ellipsis.IsValid() { - list = append(list, p.parseRHSOrType()) // builtins may expect a type: make(some type, ...) + expr := p.parseRHSOrType() + if tuple, ok := expr.(*tupleExpr); ok && isCmd { + list = tuple.items + break + } + list = append(list, expr) // builtins may expect a type: make(some type, ...) if p.tok == token.ELLIPSIS { ellipsis = p.pos p.next() @@ -2065,7 +2069,7 @@ func (p *parser) parseRangeExpr(allowCmd bool) ast.Expr { type tupleExpr struct { ast.Expr - items []*ast.Ident + items []ast.Expr } func (p *parser) parseLambdaExpr(allowCmd, allowRangeExpr bool) ast.Expr { @@ -2108,7 +2112,11 @@ func (p *parser) parseLambdaExpr(allowCmd, allowRangeExpr bool) ast.Expr { retry: switch v := e.(type) { case *tupleExpr: - lhs, lhsHasParen = v.items, true + items := make([]*ast.Ident, len(v.items), len(v.items)) + for i, item := range v.items { + items[i] = p.toIdent(item) + } + lhs, lhsHasParen = items, true case *ast.ParenExpr: e, lhsHasParen = v.X, true goto retry @@ -2138,9 +2146,9 @@ func (p *parser) parseLambdaExpr(allowCmd, allowRangeExpr bool) ast.Expr { RhsHasParen: rhsHasParen, } } - if _, ok := x.(*tupleExpr); ok { - panic("TODO: tupleExpr") - } + // if _, ok := x.(*tupleExpr); ok { + // panic("TODO: tupleExpr") + // } return x } From ced47e59f0cf4c2199b19575fea0895ff229d63c Mon Sep 17 00:00:00 2001 From: visualfc Date: Sun, 3 Jul 2022 20:30:19 +0800 Subject: [PATCH 2/8] parser: parsePrimaryExpr/parseBinaryExpr check tupleExpr --- parser/parser.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/parser/parser.go b/parser/parser.go index ed74768db..ea9aa2bd2 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -1863,6 +1863,9 @@ func (p *parser) parsePrimaryExpr(lhs, allowTuple, allowCmd bool) ast.Expr { } x := p.parseOperand(lhs, allowTuple, allowCmd) + if _, ok := x.(*tupleExpr); ok { + return x + } L: for { switch p.tok { @@ -2028,6 +2031,9 @@ func (p *parser) parseBinaryExpr(lhs bool, prec1 int, allowTuple, allowCmd bool) } x := p.parseUnaryExpr(lhs, allowTuple, allowCmd) + if _, ok := x.(*tupleExpr); ok { + return x + } for { op, oprec := p.tokPrec() if oprec < prec1 { From a80e87982775a8f7a16c5717b7e49cb34fc10cab Mon Sep 17 00:00:00 2001 From: visualfc Date: Sun, 3 Jul 2022 20:56:38 +0800 Subject: [PATCH 3/8] parser: tupleExpr Pos/End --- parser/parser.go | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index ea9aa2bd2..9af8b0ce1 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -1406,7 +1406,7 @@ func (p *parser) parseOperand(lhs, allowTuple, allowCmd bool) ast.Expr { p.next() if allowTuple && p.tok == token.RPAREN { // () => expr p.next() - return &tupleExpr{} + return &tupleExpr{Opening: lparen, Closing: p.pos} } p.exprLev++ x := p.parseRHSOrType() // types may be parenthesized: (some type) @@ -1420,7 +1420,7 @@ func (p *parser) parseOperand(lhs, allowTuple, allowCmd bool) ast.Expr { } p.exprLev-- p.expect(token.RPAREN) - return &tupleExpr{items: items} + return &tupleExpr{Opening: lparen, Items: items, Closing: p.pos} } p.exprLev-- rparen := p.expect(token.RPAREN) @@ -1580,9 +1580,13 @@ func (p *parser) parseCallOrConversion(fun ast.Expr, isCmd bool) *ast.CallExpr { var ellipsis token.Pos for p.tok != endTok && p.tok != token.EOF && !ellipsis.IsValid() { expr := p.parseRHSOrType() - if tuple, ok := expr.(*tupleExpr); ok && isCmd { - list = tuple.items - break + if tuple, ok := expr.(*tupleExpr); ok { + if isCmd { + list = tuple.Items + break + } else { + p.error(tuple.Pos(), "func param not support tuple") + } } list = append(list, expr) // builtins may expect a type: make(some type, ...) if p.tok == token.ELLIPSIS { @@ -2075,7 +2079,17 @@ func (p *parser) parseRangeExpr(allowCmd bool) ast.Expr { type tupleExpr struct { ast.Expr - items []ast.Expr + Opening token.Pos + Items []ast.Expr + Closing token.Pos +} + +func (p *tupleExpr) Pos() token.Pos { + return p.Opening +} + +func (p *tupleExpr) End() token.Pos { + return p.Closing } func (p *parser) parseLambdaExpr(allowCmd, allowRangeExpr bool) ast.Expr { @@ -2118,8 +2132,8 @@ func (p *parser) parseLambdaExpr(allowCmd, allowRangeExpr bool) ast.Expr { retry: switch v := e.(type) { case *tupleExpr: - items := make([]*ast.Ident, len(v.items), len(v.items)) - for i, item := range v.items { + items := make([]*ast.Ident, len(v.Items), len(v.Items)) + for i, item := range v.Items { items[i] = p.toIdent(item) } lhs, lhsHasParen = items, true From 46e16fd4e3779dc9052496bb696314f44cac0ad3 Mon Sep 17 00:00:00 2001 From: visualfc Date: Sun, 3 Jul 2022 21:41:56 +0800 Subject: [PATCH 4/8] parser: parseRHSOrType/parseExpr/parseLambdaExpr add param allowTuple --- parser/parser.go | 52 +++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index 9af8b0ce1..6dda99ab0 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -688,10 +688,10 @@ func (p *parser) parseExprList(lhs, allowCmd bool) (list []ast.Expr) { defer un(trace(p, "ExpressionList")) } - list = append(list, p.checkExpr(p.parseExpr(lhs, allowCmd, false))) + list = append(list, p.checkExpr(p.parseExpr(lhs, false, allowCmd, false))) for p.tok == token.COMMA { p.next() - list = append(list, p.checkExpr(p.parseExpr(lhs, false, false))) + list = append(list, p.checkExpr(p.parseExpr(lhs, false, false, false))) } return } @@ -1409,14 +1409,14 @@ func (p *parser) parseOperand(lhs, allowTuple, allowCmd bool) ast.Expr { return &tupleExpr{Opening: lparen, Closing: p.pos} } p.exprLev++ - x := p.parseRHSOrType() // types may be parenthesized: (some type) + x := p.parseRHSOrType(false) // types may be parenthesized: (some type) if allowTuple && p.tok == token.COMMA { // (x, y, ...) => expr items := make([]ast.Expr, 1, 2) items[0] = x for p.tok == token.COMMA { p.next() - items = append(items, p.parseRHSOrType()) + items = append(items, p.parseRHSOrType(false)) } p.exprLev-- p.expect(token.RPAREN) @@ -1579,14 +1579,10 @@ func (p *parser) parseCallOrConversion(fun ast.Expr, isCmd bool) *ast.CallExpr { var list []ast.Expr var ellipsis token.Pos for p.tok != endTok && p.tok != token.EOF && !ellipsis.IsValid() { - expr := p.parseRHSOrType() + expr := p.parseRHSOrType(isCmd && len(list) == 0) if tuple, ok := expr.(*tupleExpr); ok { - if isCmd { - list = tuple.Items - break - } else { - p.error(tuple.Pos(), "func param not support tuple") - } + list = tuple.Items + break } list = append(list, expr) // builtins may expect a type: make(some type, ...) if p.tok == token.ELLIPSIS { @@ -1643,7 +1639,7 @@ func (p *parser) parseValue(keyOk bool) ast.Expr { // undeclared; or b) it is a struct field. In the former case, the type // checker can do a top-level lookup, and in the latter case it will do // a separate field lookup. - x := p.checkExpr(p.parseExpr(keyOk, false, false)) + x := p.checkExpr(p.parseExpr(keyOk, false, false, false)) if keyOk { if p.tok == token.COLON { // Try to resolve the key but don't collect it @@ -2092,7 +2088,7 @@ func (p *tupleExpr) End() token.Pos { return p.Closing } -func (p *parser) parseLambdaExpr(allowCmd, allowRangeExpr bool) ast.Expr { +func (p *parser) parseLambdaExpr(allowTuple bool, allowCmd, allowRangeExpr bool) ast.Expr { var x ast.Expr var first = p.pos if p.tok != token.RARROW { @@ -2113,7 +2109,7 @@ func (p *parser) parseLambdaExpr(allowCmd, allowRangeExpr bool) ast.Expr { rhsHasParen = true p.next() for { - item := p.parseExpr(false, false, false) + item := p.parseExpr(false, false, false, false) rhs = append(rhs, item) if p.tok != token.COMMA { break @@ -2124,7 +2120,7 @@ func (p *parser) parseLambdaExpr(allowCmd, allowRangeExpr bool) ast.Expr { case token.LBRACE: // { body = p.parseBlockStmt() default: - rhs = []ast.Expr{p.parseExpr(false, false, false)} + rhs = []ast.Expr{p.parseExpr(false, false, false, false)} } var lhs []*ast.Ident if x != nil { @@ -2166,9 +2162,11 @@ func (p *parser) parseLambdaExpr(allowCmd, allowRangeExpr bool) ast.Expr { RhsHasParen: rhsHasParen, } } - // if _, ok := x.(*tupleExpr); ok { - // panic("TODO: tupleExpr") - // } + if !allowTuple { + if _, ok := x.(*tupleExpr); ok { + p.error(x.Pos(), "not support tuple") + } + } return x } @@ -2176,14 +2174,14 @@ func (p *parser) parseLambdaExpr(allowCmd, allowRangeExpr bool) ast.Expr { // The result may be a type or even a raw type ([...]int). Callers must // check the result (using checkExpr or checkExprOrType), depending on // context. -func (p *parser) parseExpr(lhs, allowCmd, allowRangeExpr bool) ast.Expr { +func (p *parser) parseExpr(lhs, allowTuple, allowCmd, allowRangeExpr bool) ast.Expr { if p.trace { defer un(trace(p, "Expression")) } if lhs { return p.parseBinaryExpr(true, token.LowestPrec+1, false, allowCmd) } - return p.parseLambdaExpr(allowCmd, allowRangeExpr) + return p.parseLambdaExpr(allowTuple, allowCmd, allowRangeExpr) } func (p *parser) parseRHS() ast.Expr { @@ -2193,15 +2191,15 @@ func (p *parser) parseRHS() ast.Expr { func (p *parser) parseRHSEx(allowRangeExpr bool) ast.Expr { old := p.inRHS p.inRHS = true - x := p.checkExpr(p.parseExpr(false, false, allowRangeExpr)) + x := p.checkExpr(p.parseExpr(false, false, false, allowRangeExpr)) p.inRHS = old return x } -func (p *parser) parseRHSOrType() ast.Expr { +func (p *parser) parseRHSOrType(allowTuple bool) ast.Expr { old := p.inRHS p.inRHS = true - x := p.checkExprOrType(p.parseExpr(false, false, false)) + x := p.checkExprOrType(p.parseExpr(false, allowTuple, false, false)) p.inRHS = old return x } @@ -2303,7 +2301,7 @@ func (p *parser) parseSimpleStmt(mode int, allowCmd bool) (ast.Stmt, bool) { } func (p *parser) parseCallExpr(callType string) *ast.CallExpr { - x := p.parseRHSOrType() // could be a conversion: (some type)(x) + x := p.parseRHSOrType(false) // could be a conversion: (some type)(x) if call, isCall := x.(*ast.CallExpr); isCall { return call } @@ -2768,13 +2766,13 @@ func (p *parser) parseForPhrases() (phrases []*ast.ForPhrase) { func (p *parser) parseForPhraseStmtPart(lhs []ast.Expr) *ast.ForPhraseStmt { tokPos := p.expect(token.ARROW) // <- - x := p.parseExpr(false, false, true) + x := p.parseExpr(false, false, false, true) var cond ast.Expr var ifPos token.Pos if p.tok == token.IF || p.tok == token.COMMA { ifPos = p.pos p.next() - cond = p.parseExpr(false, false, false) + cond = p.parseExpr(false, false, false, false) } stmt := &ast.ForPhraseStmt{ForPhrase: &ast.ForPhrase{TokPos: tokPos, X: x, IfPos: ifPos, Cond: cond}} @@ -2818,7 +2816,7 @@ func (p *parser) parseForPhrase() *ast.ForPhrase { // for k, v <- container if c } tokPos := p.expect(token.ARROW) // <- container - x := p.parseExpr(false, false, true) + x := p.parseExpr(false, false, false, true) var init ast.Stmt var cond ast.Expr var ifPos token.Pos From e9f8d00104b51001a6a05dcf6e95d7c99485aa87 Mon Sep 17 00:00:00 2001 From: visualfc Date: Sun, 3 Jul 2022 22:22:27 +0800 Subject: [PATCH 5/8] parser: add _testdata/cmdlinestyle6 --- parser/_testdata/cmdlinestyle6/cmd.gop | 1 + parser/_testdata/cmdlinestyle6/parser.expect | 35 ++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 parser/_testdata/cmdlinestyle6/cmd.gop create mode 100644 parser/_testdata/cmdlinestyle6/parser.expect diff --git a/parser/_testdata/cmdlinestyle6/cmd.gop b/parser/_testdata/cmdlinestyle6/cmd.gop new file mode 100644 index 000000000..126b37c52 --- /dev/null +++ b/parser/_testdata/cmdlinestyle6/cmd.gop @@ -0,0 +1 @@ +println (1+2i,2) diff --git a/parser/_testdata/cmdlinestyle6/parser.expect b/parser/_testdata/cmdlinestyle6/parser.expect new file mode 100644 index 000000000..dcdefb1d8 --- /dev/null +++ b/parser/_testdata/cmdlinestyle6/parser.expect @@ -0,0 +1,35 @@ +package main + +file cmd.gop +noEntrypoint +ast.FuncDecl: + Name: + ast.Ident: + Name: main + Type: + ast.FuncType: + Params: + ast.FieldList: + Body: + ast.BlockStmt: + List: + ast.ExprStmt: + X: + ast.CallExpr: + Fun: + ast.Ident: + Name: println + Args: + ast.BinaryExpr: + X: + ast.BasicLit: + Kind: INT + Value: 1 + Op: + + Y: + ast.BasicLit: + Kind: IMAG + Value: 2i + ast.BasicLit: + Kind: INT + Value: 2 From 5c642112d82dc772d48f8dce3bb1c6d698e73ef9 Mon Sep 17 00:00:00 2001 From: visualfc Date: Sun, 3 Jul 2022 23:07:50 +0800 Subject: [PATCH 6/8] parser: parseCallOrConversion check tuple and reset nocommand --- parser/parser.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/parser/parser.go b/parser/parser.go index 6dda99ab0..42d219dad 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -1578,10 +1578,13 @@ func (p *parser) parseCallOrConversion(fun ast.Expr, isCmd bool) *ast.CallExpr { p.exprLev++ var list []ast.Expr var ellipsis token.Pos + var extractTuple bool for p.tok != endTok && p.tok != token.EOF && !ellipsis.IsValid() { expr := p.parseRHSOrType(isCmd && len(list) == 0) if tuple, ok := expr.(*tupleExpr); ok { list = tuple.Items + extractTuple = true + rparen = tuple.End() break } list = append(list, expr) // builtins may expect a type: make(some type, ...) @@ -1603,7 +1606,9 @@ func (p *parser) parseCallOrConversion(fun ast.Expr, isCmd bool) *ast.CallExpr { p.exprLev-- var noParenEnd token.Pos if isCmd { - noParenEnd = p.pos + if !extractTuple { + noParenEnd = p.pos + } } else { rparen = p.expectClosing(token.RPAREN, "argument list") } @@ -1905,6 +1910,9 @@ L: } isCmd := allowCmd && x.End() != p.pos // println () x = p.parseCallOrConversion(p.checkExprOrType(x), isCmd) + if isCmd && !x.(*ast.CallExpr).IsCommand() { + allowCmd = false + } case token.LBRACE: // { if allowCmd && x.End() != p.pos { // println {} x = p.parseCallOrConversion(p.checkExprOrType(x), true) From c600969a8285b08b06b18ed722dd162c2a5e8021 Mon Sep 17 00:00:00 2001 From: visualfc Date: Mon, 4 Jul 2022 11:28:39 +0800 Subject: [PATCH 7/8] parser: parseCallOrConversion remove extractTuple --- parser/parser.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index 42d219dad..aaba15b26 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -1578,13 +1578,12 @@ func (p *parser) parseCallOrConversion(fun ast.Expr, isCmd bool) *ast.CallExpr { p.exprLev++ var list []ast.Expr var ellipsis token.Pos - var extractTuple bool for p.tok != endTok && p.tok != token.EOF && !ellipsis.IsValid() { expr := p.parseRHSOrType(isCmd && len(list) == 0) if tuple, ok := expr.(*tupleExpr); ok { list = tuple.Items - extractTuple = true rparen = tuple.End() + isCmd = false break } list = append(list, expr) // builtins may expect a type: make(some type, ...) @@ -1606,10 +1605,8 @@ func (p *parser) parseCallOrConversion(fun ast.Expr, isCmd bool) *ast.CallExpr { p.exprLev-- var noParenEnd token.Pos if isCmd { - if !extractTuple { - noParenEnd = p.pos - } - } else { + noParenEnd = p.pos + } else if rparen == token.NoPos { rparen = p.expectClosing(token.RPAREN, "argument list") } if debugParseOutput { From d6c877e3310ce51c39b0ff34eccefbaeeffc080a Mon Sep 17 00:00:00 2001 From: visualfc Date: Mon, 4 Jul 2022 11:37:12 +0800 Subject: [PATCH 8/8] parser: tupleExpr remove Pos/End implement --- parser/parser.go | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index aaba15b26..3ba835749 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -1582,7 +1582,7 @@ func (p *parser) parseCallOrConversion(fun ast.Expr, isCmd bool) *ast.CallExpr { expr := p.parseRHSOrType(isCmd && len(list) == 0) if tuple, ok := expr.(*tupleExpr); ok { list = tuple.Items - rparen = tuple.End() + rparen = tuple.Closing isCmd = false break } @@ -2085,14 +2085,6 @@ type tupleExpr struct { Closing token.Pos } -func (p *tupleExpr) Pos() token.Pos { - return p.Opening -} - -func (p *tupleExpr) End() token.Pos { - return p.Closing -} - func (p *parser) parseLambdaExpr(allowTuple bool, allowCmd, allowRangeExpr bool) ast.Expr { var x ast.Expr var first = p.pos @@ -2168,8 +2160,8 @@ func (p *parser) parseLambdaExpr(allowTuple bool, allowCmd, allowRangeExpr bool) } } if !allowTuple { - if _, ok := x.(*tupleExpr); ok { - p.error(x.Pos(), "not support tuple") + if tuple, ok := x.(*tupleExpr); ok { + p.error(tuple.Opening, "tuple is not supported") } } return x