Commit 305d7ada authored by Robert Griesemer's avatar Robert Griesemer

go/parser: permit [...]T where array types are permitted

More lenient parsing with better error recovery.
It's easier for the type check to pick up the slack.

R=iant
CC=golang-dev
https://golang.org/cl/6856108
parent 5b650235
...@@ -578,14 +578,15 @@ func (p *parser) parseTypeName() ast.Expr { ...@@ -578,14 +578,15 @@ func (p *parser) parseTypeName() ast.Expr {
return ident return ident
} }
func (p *parser) parseArrayType(ellipsisOk bool) ast.Expr { func (p *parser) parseArrayType() ast.Expr {
if p.trace { if p.trace {
defer un(trace(p, "ArrayType")) defer un(trace(p, "ArrayType"))
} }
lbrack := p.expect(token.LBRACK) lbrack := p.expect(token.LBRACK)
var len ast.Expr var len ast.Expr
if ellipsisOk && p.tok == token.ELLIPSIS { // always permit ellipsis for more fault-tolerant parsing
if p.tok == token.ELLIPSIS {
len = &ast.Ellipsis{Ellipsis: p.pos} len = &ast.Ellipsis{Ellipsis: p.pos}
p.next() p.next()
} else if p.tok != token.RBRACK { } else if p.tok != token.RBRACK {
...@@ -697,7 +698,7 @@ func (p *parser) tryVarType(isParam bool) ast.Expr { ...@@ -697,7 +698,7 @@ func (p *parser) tryVarType(isParam bool) ast.Expr {
if isParam && p.tok == token.ELLIPSIS { if isParam && p.tok == token.ELLIPSIS {
pos := p.pos pos := p.pos
p.next() p.next()
typ := p.tryIdentOrType(isParam) // don't use parseType so we can provide better error message typ := p.tryIdentOrType() // don't use parseType so we can provide better error message
if typ != nil { if typ != nil {
p.resolve(typ) p.resolve(typ)
} else { } else {
...@@ -706,7 +707,7 @@ func (p *parser) tryVarType(isParam bool) ast.Expr { ...@@ -706,7 +707,7 @@ func (p *parser) tryVarType(isParam bool) ast.Expr {
} }
return &ast.Ellipsis{Ellipsis: pos, Elt: typ} return &ast.Ellipsis{Ellipsis: pos, Elt: typ}
} }
return p.tryIdentOrType(false) return p.tryIdentOrType()
} }
// If the result is an identifier, it is not resolved. // If the result is an identifier, it is not resolved.
...@@ -943,12 +944,12 @@ func (p *parser) parseChanType() *ast.ChanType { ...@@ -943,12 +944,12 @@ func (p *parser) parseChanType() *ast.ChanType {
} }
// If the result is an identifier, it is not resolved. // If the result is an identifier, it is not resolved.
func (p *parser) tryIdentOrType(ellipsisOk bool) ast.Expr { func (p *parser) tryIdentOrType() ast.Expr {
switch p.tok { switch p.tok {
case token.IDENT: case token.IDENT:
return p.parseTypeName() return p.parseTypeName()
case token.LBRACK: case token.LBRACK:
return p.parseArrayType(ellipsisOk) return p.parseArrayType()
case token.STRUCT: case token.STRUCT:
return p.parseStructType() return p.parseStructType()
case token.MUL: case token.MUL:
...@@ -975,7 +976,7 @@ func (p *parser) tryIdentOrType(ellipsisOk bool) ast.Expr { ...@@ -975,7 +976,7 @@ func (p *parser) tryIdentOrType(ellipsisOk bool) ast.Expr {
} }
func (p *parser) tryType() ast.Expr { func (p *parser) tryType() ast.Expr {
typ := p.tryIdentOrType(false) typ := p.tryIdentOrType()
if typ != nil { if typ != nil {
p.resolve(typ) p.resolve(typ)
} }
...@@ -1083,7 +1084,7 @@ func (p *parser) parseOperand(lhs bool) ast.Expr { ...@@ -1083,7 +1084,7 @@ func (p *parser) parseOperand(lhs bool) ast.Expr {
return p.parseFuncTypeOrLit() return p.parseFuncTypeOrLit()
} }
if typ := p.tryIdentOrType(true); typ != nil { if typ := p.tryIdentOrType(); typ != nil {
// could be type for composite literal or conversion // could be type for composite literal or conversion
_, isIdent := typ.(*ast.Ident) _, isIdent := typ.(*ast.Ident)
assert(!isIdent, "type cannot be identifier") assert(!isIdent, "type cannot be identifier")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment