diff options
Diffstat (limited to 'src/cmd/compile/internal/syntax/syntax.go')
-rw-r--r-- | src/cmd/compile/internal/syntax/syntax.go | 99 |
1 files changed, 57 insertions, 42 deletions
diff --git a/src/cmd/compile/internal/syntax/syntax.go b/src/cmd/compile/internal/syntax/syntax.go index 71fc097c3b..b1e56ee946 100644 --- a/src/cmd/compile/internal/syntax/syntax.go +++ b/src/cmd/compile/internal/syntax/syntax.go @@ -5,35 +5,72 @@ package syntax import ( - "errors" "fmt" "io" "os" ) +// Mode describes the parser mode. type Mode uint +// Error describes a syntax error. Error implements the error interface. +type Error struct { + // TODO(gri) decide what we really need here + Pos int // byte offset from file start + Line int // line (starting with 1) + Msg string +} + +func (err Error) Error() string { + return fmt.Sprintf("%d: %s", err.Line, err.Msg) +} + +var _ error = Error{} // verify that Error implements error + +// An ErrorHandler is called for each error encountered reading a .go file. +type ErrorHandler func(err error) + // A Pragma value is a set of flags that augment a function or // type declaration. Callers may assign meaning to the flags as // appropriate. type Pragma uint16 -type ErrorHandler func(pos, line int, msg string) - // A PragmaHandler is used to process //line and //go: directives as // they're scanned. The returned Pragma value will be unioned into the // next FuncDecl node. type PragmaHandler func(pos, line int, text string) Pragma -// TODO(gri) These need a lot more work. +// Parse parses a single Go source file from src and returns the corresponding +// syntax tree. If there are syntax errors, Parse will return the first error +// encountered. +// +// If errh != nil, it is called with each error encountered, and Parse will +// process as much source as possible. If errh is nil, Parse will terminate +// immediately upon encountering an error. +// +// If a PragmaHandler is provided, it is called with each pragma encountered. +// +// The Mode argument is currently ignored. +func Parse(src io.Reader, errh ErrorHandler, pragh PragmaHandler, mode Mode) (_ *File, err error) { + defer func() { + if p := recover(); p != nil { + var ok bool + if err, ok = p.(Error); ok { + return + } + panic(p) + } + }() -func ReadFile(filename string, errh ErrorHandler, pragh PragmaHandler, mode Mode) (*File, error) { - src, err := os.Open(filename) - if err != nil { - return nil, err - } - defer src.Close() - return Read(src, errh, pragh, mode) + var p parser + p.init(src, errh, pragh) + p.next() + return p.file(), p.first +} + +// ParseBytes behaves like Parse but it reads the source from the []byte slice provided. +func ParseBytes(src []byte, errh ErrorHandler, pragh PragmaHandler, mode Mode) (*File, error) { + return Parse(&bytesReader{src}, errh, pragh, mode) } type bytesReader struct { @@ -49,37 +86,15 @@ func (r *bytesReader) Read(p []byte) (int, error) { return 0, io.EOF } -func ReadBytes(src []byte, errh ErrorHandler, pragh PragmaHandler, mode Mode) (*File, error) { - return Read(&bytesReader{src}, errh, pragh, mode) -} - -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) +// ParseFile behaves like Parse but it reads the source from the named file. +func ParseFile(filename string, errh ErrorHandler, pragh PragmaHandler, mode Mode) (*File, error) { + src, err := os.Open(filename) + if err != nil { + if errh != nil { + errh(err) } - }() - - var p parser - p.init(src, errh, pragh) - p.next() - 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 { - ast = nil - err = fmt.Errorf("%d syntax errors", p.nerrors) + return nil, err } - - return -} - -func Write(w io.Writer, n *File) error { - panic("unimplemented") + defer src.Close() + return Parse(src, errh, pragh, mode) } |