From 99aa56a437be4f72da2eefd2cce1c09fe8d7c201 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 17 Sep 2019 16:32:11 -0700 Subject: [PATCH] go/parser: return partial result from ParseExpr in case of error Remove redundant code and improve documentation in the process. Fixes #34211. Change-Id: I9a6d1467f1a2c98a163f41f9df147fc6500c6fad Reviewed-on: https://go-review.googlesource.com/c/go/+/196077 Reviewed-by: Ian Lance Taylor --- src/go/parser/interface.go | 21 +++++++++++++-------- src/go/parser/parser_test.go | 9 ++++++++- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/go/parser/interface.go b/src/go/parser/interface.go index 0c3f824c98..500c98d496 100644 --- a/src/go/parser/interface.go +++ b/src/go/parser/interface.go @@ -75,7 +75,7 @@ const ( // indicates the specific failure. If the source was read but syntax // errors were found, the result is a partial AST (with ast.Bad* nodes // representing the fragments of erroneous source code). Multiple errors -// are returned via a scanner.ErrorList which is sorted by file position. +// are returned via a scanner.ErrorList which is sorted by source position. // func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) (f *ast.File, err error) { if fset == nil { @@ -173,6 +173,12 @@ func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, m // be a valid Go (type or value) expression. Specifically, fset must not // be nil. // +// If the source couldn't be read, the returned AST is nil and the error +// indicates the specific failure. If the source was read but syntax +// errors were found, the result is a partial AST (with ast.Bad* nodes +// representing the fragments of erroneous source code). Multiple errors +// are returned via a scanner.ErrorList which is sorted by source position. +// func ParseExprFrom(fset *token.FileSet, filename string, src interface{}, mode Mode) (expr ast.Expr, err error) { if fset == nil { panic("parser.ParseExprFrom: no token.FileSet provided (fset == nil)") @@ -204,7 +210,7 @@ func ParseExprFrom(fset *token.FileSet, filename string, src interface{}, mode M // in case of an erroneous x. p.openScope() p.pkgScope = p.topScope - e := p.parseRhsOrType() + expr = p.parseRhsOrType() p.closeScope() assert(p.topScope == nil, "unbalanced scopes") @@ -215,18 +221,17 @@ func ParseExprFrom(fset *token.FileSet, filename string, src interface{}, mode M } p.expect(token.EOF) - if p.errors.Len() > 0 { - p.errors.Sort() - return nil, p.errors.Err() - } - - return e, nil + return } // ParseExpr is a convenience function for obtaining the AST of an expression x. // The position information recorded in the AST is undefined. The filename used // in error messages is the empty string. // +// If syntax errors were found, the result is a partial AST (with ast.Bad* nodes +// representing the fragments of erroneous source code). Multiple errors are +// returned via a scanner.ErrorList which is sorted by source position. +// func ParseExpr(x string) (ast.Expr, error) { return ParseExprFrom(token.NewFileSet(), "", []byte(x), 0) } diff --git a/src/go/parser/parser_test.go b/src/go/parser/parser_test.go index 18c05bce20..25a374eeef 100644 --- a/src/go/parser/parser_test.go +++ b/src/go/parser/parser_test.go @@ -108,9 +108,16 @@ func TestParseExpr(t *testing.T) { // an invalid expression src = "a + *" - if _, err := ParseExpr(src); err == nil { + x, err = ParseExpr(src) + if err == nil { t.Errorf("ParseExpr(%q): got no error", src) } + if x == nil { + t.Errorf("ParseExpr(%q): got no (partial) result", src) + } + if _, ok := x.(*ast.BinaryExpr); !ok { + t.Errorf("ParseExpr(%q): got %T, want *ast.BinaryExpr", src, x) + } // a valid expression followed by extra tokens is invalid src = "a[i] := x" -- 2.50.0