Skip to content

Commit

Permalink
cmd/compile/internal/syntax: don't panic if no error handler is provided
Browse files Browse the repository at this point in the history
If no error handler is provided, terminate parsing with first error
and report that error.

Fixes #17697.

Change-Id: I9070faf7239bd53725de141507912b92ded3474b
Reviewed-on: https://go-review.googlesource.com/32456
Run-TryBot: Robert Griesemer <[email protected]>
Reviewed-by: Matthew Dempsky <[email protected]>
  • Loading branch information
griesemer committed Nov 1, 2016
1 parent 53fc330 commit 7a26d9f
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 6 deletions.
4 changes: 3 additions & 1 deletion src/cmd/compile/internal/syntax/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ type parser struct {
nerrors int // error count
}

type parserError string // for error recovery if no error handler was installed

func (p *parser) init(src io.Reader, errh ErrorHandler, pragh PragmaHandler) {
p.scanner.init(src, func(pos, line int, msg string) {
p.nerrors++
if !debug && errh != nil {
errh(pos, line, msg)
return
}
panic(fmt.Sprintf("%d: %s\n", line, msg))
panic(parserError(fmt.Sprintf("%d: %s\n", line, msg)))
}, pragh)

p.fnest = 0
Expand Down
7 changes: 7 additions & 0 deletions src/cmd/compile/internal/syntax/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,10 @@ func verifyPrint(filename string, ast1 *File) {
panic("not equal")
}
}

func TestIssue17697(t *testing.T) {
_, err := ReadBytes(nil, nil, nil, 0) // return with parser error, don't panic
if err == nil {
t.Errorf("no error reported")
}
}
24 changes: 19 additions & 5 deletions src/cmd/compile/internal/syntax/syntax.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package syntax

import (
"errors"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -52,18 +53,31 @@ func ReadBytes(src []byte, errh ErrorHandler, pragh PragmaHandler, mode Mode) (*
return Read(&bytesReader{src}, errh, pragh, mode)
}

func Read(src io.Reader, errh ErrorHandler, pragh PragmaHandler, mode Mode) (*File, error) {
func Read(src io.Reader, errh ErrorHandler, pragh PragmaHandler, mode Mode) (ast *File, err error) {
defer func() {
if p := recover(); p != nil {
if msg, ok := p.(parserError); ok {
err = errors.New(string(msg))
return
}
panic(p)
}
}()

var p parser
p.init(src, errh, pragh)

p.next()
ast := p.file()
ast = p.file()

// TODO(gri) This isn't quite right: Even if there's an error handler installed
// we should report an error if parsing found syntax errors. This also
// requires updating the noder's ReadFile call.
if errh == nil && p.nerrors > 0 {
return nil, fmt.Errorf("%d syntax errors", p.nerrors)
ast = nil
err = fmt.Errorf("%d syntax errors", p.nerrors)
}

return ast, nil
return
}

func Write(w io.Writer, n *File) error {
Expand Down

0 comments on commit 7a26d9f

Please sign in to comment.