github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/compiler/compiler.go (about)

     1  package compiler
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  
     9  	"github.com/hirochachacha/plua/compiler/codegen"
    10  	"github.com/hirochachacha/plua/compiler/parser"
    11  	"github.com/hirochachacha/plua/compiler/scanner"
    12  	"github.com/hirochachacha/plua/compiler/undump"
    13  	"github.com/hirochachacha/plua/internal/version"
    14  	"github.com/hirochachacha/plua/object"
    15  )
    16  
    17  type FormatType uint
    18  
    19  const (
    20  	Either FormatType = iota
    21  	Text
    22  	Binary
    23  )
    24  
    25  func (typ FormatType) String() string {
    26  	switch typ {
    27  	case Either:
    28  		return "either"
    29  	case Text:
    30  		return "text"
    31  	case Binary:
    32  		return "binary"
    33  	default:
    34  		return "unexpected"
    35  	}
    36  }
    37  
    38  type Compiler struct {
    39  	s *scanner.ScanState
    40  	r *bufio.Reader
    41  }
    42  
    43  func NewCompiler() *Compiler {
    44  	return new(Compiler)
    45  }
    46  
    47  func (c *Compiler) Compile(r io.Reader, srcname string, typ FormatType) (*object.Proto, error) {
    48  
    49  	if c.r == nil {
    50  		c.r = bufio.NewReader(r)
    51  	} else {
    52  		c.r.Reset(r)
    53  	}
    54  
    55  	b, err := c.r.Peek(1)
    56  
    57  	switch {
    58  	case err == io.EOF, err == nil && b[0] != version.LUA_SIGNATURE[0]:
    59  		if typ != Either && typ != Text {
    60  			return nil, &Error{fmt.Errorf("compiler: attempt to load a %s chunk (mode is '%s')", "text", typ)}
    61  		}
    62  
    63  		if c.s == nil {
    64  			c.s = scanner.Scan(c.r, srcname, 0)
    65  		} else {
    66  			c.s.Reset(c.r, srcname, 0)
    67  		}
    68  
    69  		ast, err := parser.Parse(c.s, 0)
    70  		if err != nil {
    71  			return nil, err
    72  		}
    73  
    74  		return codegen.Generate(ast)
    75  	case err == nil && b[0] == version.LUA_SIGNATURE[0]:
    76  		if typ != Either && typ != Binary {
    77  			return nil, &Error{fmt.Errorf("compiler: attempt to load a %s chunk (mode is '%s')", "binary", typ)}
    78  		}
    79  
    80  		return undump.Undump(c.r, 0)
    81  	default:
    82  		return nil, err
    83  	}
    84  }
    85  
    86  func (c *Compiler) CompileFile(path string, typ FormatType) (*object.Proto, error) {
    87  	f, err := os.Open(path)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  	defer f.Close()
    92  
    93  	return c.Compile(f, "@"+f.Name(), typ)
    94  }