Skip to content

Commit 99aa56a

Browse files
committed
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 <[email protected]>
1 parent d55cf5b commit 99aa56a

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

src/go/parser/interface.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ const (
7575
// indicates the specific failure. If the source was read but syntax
7676
// errors were found, the result is a partial AST (with ast.Bad* nodes
7777
// representing the fragments of erroneous source code). Multiple errors
78-
// are returned via a scanner.ErrorList which is sorted by file position.
78+
// are returned via a scanner.ErrorList which is sorted by source position.
7979
//
8080
func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) (f *ast.File, err error) {
8181
if fset == nil {
@@ -173,6 +173,12 @@ func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, m
173173
// be a valid Go (type or value) expression. Specifically, fset must not
174174
// be nil.
175175
//
176+
// If the source couldn't be read, the returned AST is nil and the error
177+
// indicates the specific failure. If the source was read but syntax
178+
// errors were found, the result is a partial AST (with ast.Bad* nodes
179+
// representing the fragments of erroneous source code). Multiple errors
180+
// are returned via a scanner.ErrorList which is sorted by source position.
181+
//
176182
func ParseExprFrom(fset *token.FileSet, filename string, src interface{}, mode Mode) (expr ast.Expr, err error) {
177183
if fset == nil {
178184
panic("parser.ParseExprFrom: no token.FileSet provided (fset == nil)")
@@ -204,7 +210,7 @@ func ParseExprFrom(fset *token.FileSet, filename string, src interface{}, mode M
204210
// in case of an erroneous x.
205211
p.openScope()
206212
p.pkgScope = p.topScope
207-
e := p.parseRhsOrType()
213+
expr = p.parseRhsOrType()
208214
p.closeScope()
209215
assert(p.topScope == nil, "unbalanced scopes")
210216

@@ -215,18 +221,17 @@ func ParseExprFrom(fset *token.FileSet, filename string, src interface{}, mode M
215221
}
216222
p.expect(token.EOF)
217223

218-
if p.errors.Len() > 0 {
219-
p.errors.Sort()
220-
return nil, p.errors.Err()
221-
}
222-
223-
return e, nil
224+
return
224225
}
225226

226227
// ParseExpr is a convenience function for obtaining the AST of an expression x.
227228
// The position information recorded in the AST is undefined. The filename used
228229
// in error messages is the empty string.
229230
//
231+
// If syntax errors were found, the result is a partial AST (with ast.Bad* nodes
232+
// representing the fragments of erroneous source code). Multiple errors are
233+
// returned via a scanner.ErrorList which is sorted by source position.
234+
//
230235
func ParseExpr(x string) (ast.Expr, error) {
231236
return ParseExprFrom(token.NewFileSet(), "", []byte(x), 0)
232237
}

src/go/parser/parser_test.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,16 @@ func TestParseExpr(t *testing.T) {
108108

109109
// an invalid expression
110110
src = "a + *"
111-
if _, err := ParseExpr(src); err == nil {
111+
x, err = ParseExpr(src)
112+
if err == nil {
112113
t.Errorf("ParseExpr(%q): got no error", src)
113114
}
115+
if x == nil {
116+
t.Errorf("ParseExpr(%q): got no (partial) result", src)
117+
}
118+
if _, ok := x.(*ast.BinaryExpr); !ok {
119+
t.Errorf("ParseExpr(%q): got %T, want *ast.BinaryExpr", src, x)
120+
}
114121

115122
// a valid expression followed by extra tokens is invalid
116123
src = "a[i] := x"

0 commit comments

Comments
 (0)