diff options
Diffstat (limited to 'src/pkg/go/parser/parser.go')
-rw-r--r-- | src/pkg/go/parser/parser.go | 50 |
1 files changed, 27 insertions, 23 deletions
diff --git a/src/pkg/go/parser/parser.go b/src/pkg/go/parser/parser.go index f4a690a6f..c4523318f 100644 --- a/src/pkg/go/parser/parser.go +++ b/src/pkg/go/parser/parser.go @@ -64,7 +64,7 @@ type parser struct { } func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mode) { - p.file = fset.AddFile(filename, fset.Base(), len(src)) + p.file = fset.AddFile(filename, -1, len(src)) var m scanner.Mode if mode&ParseComments != 0 { m = scanner.ScanComments @@ -1150,7 +1150,7 @@ func (p *parser) parseTypeAssertion(x ast.Expr) ast.Expr { defer un(trace(p, "TypeAssertion")) } - p.expect(token.LPAREN) + lparen := p.expect(token.LPAREN) var typ ast.Expr if p.tok == token.TYPE { // type switch: typ == nil @@ -1158,9 +1158,9 @@ func (p *parser) parseTypeAssertion(x ast.Expr) ast.Expr { } else { typ = p.parseType() } - p.expect(token.RPAREN) + rparen := p.expect(token.RPAREN) - return &ast.TypeAssertExpr{X: x, Type: typ} + return &ast.TypeAssertExpr{X: x, Type: typ, Lparen: lparen, Rparen: rparen} } func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr { @@ -1170,25 +1170,27 @@ func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr { lbrack := p.expect(token.LBRACK) p.exprLev++ - var low, high ast.Expr - isSlice := false + var index [3]ast.Expr // change the 3 to 2 to disable slice expressions w/ cap if p.tok != token.COLON { - low = p.parseRhs() + index[0] = p.parseRhs() } - if p.tok == token.COLON { - isSlice = true + ncolons := 0 + for p.tok == token.COLON && ncolons < len(index)-1 { p.next() - if p.tok != token.RBRACK { - high = p.parseRhs() + ncolons++ + if p.tok != token.COLON && p.tok != token.RBRACK && p.tok != token.EOF { + index[ncolons] = p.parseRhs() } } p.exprLev-- rbrack := p.expect(token.RBRACK) - if isSlice { - return &ast.SliceExpr{X: x, Lbrack: lbrack, Low: low, High: high, Rbrack: rbrack} + if ncolons > 0 { + // slice expression + return &ast.SliceExpr{X: x, Lbrack: lbrack, Low: index[0], High: index[1], Max: index[2], Slice3: ncolons == 2, Rbrack: rbrack} } - return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: low, Rbrack: rbrack} + + return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: index[0], Rbrack: rbrack} } func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr { @@ -1406,7 +1408,7 @@ L: } switch p.tok { case token.IDENT: - x = p.parseSelector(p.checkExpr(x)) + x = p.parseSelector(p.checkExprOrType(x)) case token.LPAREN: x = p.parseTypeAssertion(p.checkExpr(x)) default: @@ -2145,12 +2147,13 @@ func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) as ident = p.parseIdent() } - var path *ast.BasicLit + pos := p.pos + var path string if p.tok == token.STRING { - if !isValidImport(p.lit) { - p.error(p.pos, "invalid import path: "+p.lit) + path = p.lit + if !isValidImport(path) { + p.error(pos, "invalid import path: "+path) } - path = &ast.BasicLit{ValuePos: p.pos, Kind: p.tok, Value: p.lit} p.next() } else { p.expect(token.STRING) // use expect() error handling @@ -2161,7 +2164,7 @@ func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) as spec := &ast.ImportSpec{ Doc: doc, Name: ident, - Path: path, + Path: &ast.BasicLit{ValuePos: pos, Kind: token.STRING, Value: path}, Comment: p.lineComment, } p.imports = append(p.imports, spec) @@ -2177,8 +2180,9 @@ func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota idents := p.parseIdentList() typ := p.tryType() var values []ast.Expr - if p.tok == token.ASSIGN || keyword == token.CONST && (typ != nil || iota == 0) || keyword == token.VAR && typ == nil { - p.expect(token.ASSIGN) + // always permit optional initialization for more tolerant parsing + if p.tok == token.ASSIGN { + p.next() values = p.parseRhsList() } p.expectSemi() // call before accessing p.linecomment @@ -2381,7 +2385,7 @@ func (p *parser) parseFile() *ast.File { // Go spec: The package clause is not a declaration; // the package name does not appear in any scope. ident := p.parseIdent() - if ident.Name == "_" { + if ident.Name == "_" && p.mode&DeclarationErrors != 0 { p.error(p.pos, "invalid package name _") } p.expectSemi() |