Home | History | Annotate | Download | only in syntax
      1 // Copyright 2016 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package syntax
      6 
      7 import (
      8 	"fmt"
      9 	"io"
     10 	"os"
     11 )
     12 
     13 // Mode describes the parser mode.
     14 type Mode uint
     15 
     16 // Error describes a syntax error. Error implements the error interface.
     17 type Error struct {
     18 	// TODO(gri) decide what we really need here
     19 	Pos  int // byte offset from file start
     20 	Line int // line (starting with 1)
     21 	Msg  string
     22 }
     23 
     24 func (err Error) Error() string {
     25 	return fmt.Sprintf("%d: %s", err.Line, err.Msg)
     26 }
     27 
     28 var _ error = Error{} // verify that Error implements error
     29 
     30 // An ErrorHandler is called for each error encountered reading a .go file.
     31 type ErrorHandler func(err error)
     32 
     33 // A Pragma value is a set of flags that augment a function or
     34 // type declaration. Callers may assign meaning to the flags as
     35 // appropriate.
     36 type Pragma uint16
     37 
     38 // A PragmaHandler is used to process //line and //go: directives as
     39 // they're scanned. The returned Pragma value will be unioned into the
     40 // next FuncDecl node.
     41 type PragmaHandler func(pos, line int, text string) Pragma
     42 
     43 // Parse parses a single Go source file from src and returns the corresponding
     44 // syntax tree. If there are syntax errors, Parse will return the first error
     45 // encountered.
     46 //
     47 // If errh != nil, it is called with each error encountered, and Parse will
     48 // process as much source as possible. If errh is nil, Parse will terminate
     49 // immediately upon encountering an error.
     50 //
     51 // If a PragmaHandler is provided, it is called with each pragma encountered.
     52 //
     53 // The Mode argument is currently ignored.
     54 func Parse(src io.Reader, errh ErrorHandler, pragh PragmaHandler, mode Mode) (_ *File, err error) {
     55 	defer func() {
     56 		if p := recover(); p != nil {
     57 			var ok bool
     58 			if err, ok = p.(Error); ok {
     59 				return
     60 			}
     61 			panic(p)
     62 		}
     63 	}()
     64 
     65 	var p parser
     66 	p.init(src, errh, pragh)
     67 	p.next()
     68 	return p.file(), p.first
     69 }
     70 
     71 // ParseBytes behaves like Parse but it reads the source from the []byte slice provided.
     72 func ParseBytes(src []byte, errh ErrorHandler, pragh PragmaHandler, mode Mode) (*File, error) {
     73 	return Parse(&bytesReader{src}, errh, pragh, mode)
     74 }
     75 
     76 type bytesReader struct {
     77 	data []byte
     78 }
     79 
     80 func (r *bytesReader) Read(p []byte) (int, error) {
     81 	if len(r.data) > 0 {
     82 		n := copy(p, r.data)
     83 		r.data = r.data[n:]
     84 		return n, nil
     85 	}
     86 	return 0, io.EOF
     87 }
     88 
     89 // ParseFile behaves like Parse but it reads the source from the named file.
     90 func ParseFile(filename string, errh ErrorHandler, pragh PragmaHandler, mode Mode) (*File, error) {
     91 	src, err := os.Open(filename)
     92 	if err != nil {
     93 		if errh != nil {
     94 			errh(err)
     95 		}
     96 		return nil, err
     97 	}
     98 	defer src.Close()
     99 	return Parse(src, errh, pragh, mode)
    100 }
    101