github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/src/go/internal/gccgoimporter/parser.go (about)

     1  // Copyright 2013 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 gccgoimporter
     6  
     7  import (
     8  	"bytes"
     9  	"errors"
    10  	"fmt"
    11  	"go/constant"
    12  	"go/token"
    13  	"go/types"
    14  	"io"
    15  	"strconv"
    16  	"strings"
    17  	"text/scanner"
    18  )
    19  
    20  type parser struct {
    21  	scanner  scanner.Scanner
    22  	version  string                    // format version
    23  	tok      rune                      // current token
    24  	lit      string                    // literal string; only valid for Ident, Int, String tokens
    25  	pkgpath  string                    // package path of imported package
    26  	pkgname  string                    // name of imported package
    27  	pkg      *types.Package            // reference to imported package
    28  	imports  map[string]*types.Package // package path -> package object
    29  	typeMap  map[int]types.Type        // type number -> type
    30  	initdata InitData                  // package init priority data
    31  }
    32  
    33  func (p *parser) init(filename string, src io.Reader, imports map[string]*types.Package) {
    34  	p.scanner.Init(src)
    35  	p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
    36  	p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
    37  	p.scanner.Whitespace = 1<<'\t' | 1<<'\n' | 1<<' '
    38  	p.scanner.Filename = filename // for good error messages
    39  	p.next()
    40  	p.imports = imports
    41  	p.typeMap = make(map[int]types.Type)
    42  }
    43  
    44  type importError struct {
    45  	pos scanner.Position
    46  	err error
    47  }
    48  
    49  func (e importError) Error() string {
    50  	return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
    51  }
    52  
    53  func (p *parser) error(err interface{}) {
    54  	if s, ok := err.(string); ok {
    55  		err = errors.New(s)
    56  	}
    57  	// panic with a runtime.Error if err is not an error
    58  	panic(importError{p.scanner.Pos(), err.(error)})
    59  }
    60  
    61  func (p *parser) errorf(format string, args ...interface{}) {
    62  	p.error(fmt.Errorf(format, args...))
    63  }
    64  
    65  func (p *parser) expect(tok rune) string {
    66  	lit := p.lit
    67  	if p.tok != tok {
    68  		p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
    69  	}
    70  	p.next()
    71  	return lit
    72  }
    73  
    74  func (p *parser) expectKeyword(keyword string) {
    75  	lit := p.expect(scanner.Ident)
    76  	if lit != keyword {
    77  		p.errorf("expected keyword %s, got %q", keyword, lit)
    78  	}
    79  }
    80  
    81  func (p *parser) parseString() string {
    82  	str, err := strconv.Unquote(p.expect(scanner.String))
    83  	if err != nil {
    84  		p.error(err)
    85  	}
    86  	return str
    87  }
    88  
    89  // unquotedString     = { unquotedStringChar } .
    90  // unquotedStringChar = <neither a whitespace nor a ';' char> .
    91  func (p *parser) parseUnquotedString() string {
    92  	if p.tok == scanner.EOF {
    93  		p.error("unexpected EOF")
    94  	}
    95  	var buf bytes.Buffer
    96  	buf.WriteString(p.scanner.TokenText())
    97  	// This loop needs to examine each character before deciding whether to consume it. If we see a semicolon,
    98  	// we need to let it be consumed by p.next().
    99  	for ch := p.scanner.Peek(); ch != ';' && ch != scanner.EOF && p.scanner.Whitespace&(1<<uint(ch)) == 0; ch = p.scanner.Peek() {
   100  		buf.WriteRune(ch)
   101  		p.scanner.Next()
   102  	}
   103  	p.next()
   104  	return buf.String()
   105  }
   106  
   107  func (p *parser) next() {
   108  	p.tok = p.scanner.Scan()
   109  	switch p.tok {
   110  	case scanner.Ident, scanner.Int, scanner.Float, scanner.String, 'ยท':
   111  		p.lit = p.scanner.TokenText()
   112  	default:
   113  		p.lit = ""
   114  	}
   115  }
   116  
   117  func (p *parser) parseQualifiedName() (path, name string) {
   118  	return p.parseQualifiedNameStr(p.parseString())
   119  }
   120  
   121  func (p *parser) parseUnquotedQualifiedName() (path, name string) {
   122  	return p.parseQualifiedNameStr(p.parseUnquotedString())
   123  }
   124  
   125  // qualifiedName = [ ["."] unquotedString "." ] unquotedString .
   126  //
   127  // The above production uses greedy matching.
   128  func (p *parser) parseQualifiedNameStr(unquotedName string) (pkgpath, name string) {
   129  	parts := strings.Split(unquotedName, ".")
   130  	if parts[0] == "" {
   131  		parts = parts[1:]
   132  	}
   133  
   134  	switch len(parts) {
   135  	case 0:
   136  		p.errorf("malformed qualified name: %q", unquotedName)
   137  	case 1:
   138  		// unqualified name
   139  		pkgpath = p.pkgpath
   140  		name = parts[0]
   141  	default:
   142  		// qualified name, which may contain periods
   143  		pkgpath = strings.Join(parts[0:len(parts)-1], ".")
   144  		name = parts[len(parts)-1]
   145  	}
   146  
   147  	return
   148  }
   149  
   150  // getPkg returns the package for a given path. If the package is
   151  // not found but we have a package name, create the package and
   152  // add it to the p.imports map.
   153  //
   154  func (p *parser) getPkg(pkgpath, name string) *types.Package {
   155  	// package unsafe is not in the imports map - handle explicitly
   156  	if pkgpath == "unsafe" {
   157  		return types.Unsafe
   158  	}
   159  	pkg := p.imports[pkgpath]
   160  	if pkg == nil && name != "" {
   161  		pkg = types.NewPackage(pkgpath, name)
   162  		p.imports[pkgpath] = pkg
   163  	}
   164  	return pkg
   165  }
   166  
   167  // parseExportedName is like parseQualifiedName, but
   168  // the package path is resolved to an imported *types.Package.
   169  //
   170  // ExportedName = string [string] .
   171  func (p *parser) parseExportedName() (pkg *types.Package, name string) {
   172  	path, name := p.parseQualifiedName()
   173  	var pkgname string
   174  	if p.tok == scanner.String {
   175  		pkgname = p.parseString()
   176  	}
   177  	pkg = p.getPkg(path, pkgname)
   178  	if pkg == nil {
   179  		p.errorf("package %s (path = %q) not found", name, path)
   180  	}
   181  	return
   182  }
   183  
   184  // Name = QualifiedName | "?" .
   185  func (p *parser) parseName() string {
   186  	if p.tok == '?' {
   187  		// Anonymous.
   188  		p.next()
   189  		return ""
   190  	}
   191  	// The package path is redundant for us. Don't try to parse it.
   192  	_, name := p.parseUnquotedQualifiedName()
   193  	return name
   194  }
   195  
   196  func deref(typ types.Type) types.Type {
   197  	if p, _ := typ.(*types.Pointer); p != nil {
   198  		typ = p.Elem()
   199  	}
   200  	return typ
   201  }
   202  
   203  // Field = Name Type [string] .
   204  func (p *parser) parseField(pkg *types.Package) (field *types.Var, tag string) {
   205  	name := p.parseName()
   206  	typ := p.parseType(pkg)
   207  	anon := false
   208  	if name == "" {
   209  		anon = true
   210  		switch typ := deref(typ).(type) {
   211  		case *types.Basic:
   212  			name = typ.Name()
   213  		case *types.Named:
   214  			name = typ.Obj().Name()
   215  		default:
   216  			p.error("anonymous field expected")
   217  		}
   218  	}
   219  	field = types.NewField(token.NoPos, pkg, name, typ, anon)
   220  	if p.tok == scanner.String {
   221  		tag = p.parseString()
   222  	}
   223  	return
   224  }
   225  
   226  // Param = Name ["..."] Type .
   227  func (p *parser) parseParam(pkg *types.Package) (param *types.Var, isVariadic bool) {
   228  	name := p.parseName()
   229  	if p.tok == '.' {
   230  		p.next()
   231  		p.expect('.')
   232  		p.expect('.')
   233  		isVariadic = true
   234  	}
   235  	typ := p.parseType(pkg)
   236  	if isVariadic {
   237  		typ = types.NewSlice(typ)
   238  	}
   239  	param = types.NewParam(token.NoPos, pkg, name, typ)
   240  	return
   241  }
   242  
   243  // Var = Name Type .
   244  func (p *parser) parseVar(pkg *types.Package) *types.Var {
   245  	name := p.parseName()
   246  	return types.NewVar(token.NoPos, pkg, name, p.parseType(pkg))
   247  }
   248  
   249  // Conversion = "convert" "(" Type "," ConstValue ")" .
   250  func (p *parser) parseConversion(pkg *types.Package) (val constant.Value, typ types.Type) {
   251  	p.expectKeyword("convert")
   252  	p.expect('(')
   253  	typ = p.parseType(pkg)
   254  	p.expect(',')
   255  	val, _ = p.parseConstValue(pkg)
   256  	p.expect(')')
   257  	return
   258  }
   259  
   260  // ConstValue     = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) | Conversion .
   261  // FloatOrComplex = float ["i" | ("+"|"-") float "i"] .
   262  func (p *parser) parseConstValue(pkg *types.Package) (val constant.Value, typ types.Type) {
   263  	switch p.tok {
   264  	case scanner.String:
   265  		str := p.parseString()
   266  		val = constant.MakeString(str)
   267  		typ = types.Typ[types.UntypedString]
   268  		return
   269  
   270  	case scanner.Ident:
   271  		b := false
   272  		switch p.lit {
   273  		case "false":
   274  		case "true":
   275  			b = true
   276  
   277  		case "convert":
   278  			return p.parseConversion(pkg)
   279  
   280  		default:
   281  			p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit)
   282  		}
   283  
   284  		p.next()
   285  		val = constant.MakeBool(b)
   286  		typ = types.Typ[types.UntypedBool]
   287  		return
   288  	}
   289  
   290  	sign := ""
   291  	if p.tok == '-' {
   292  		p.next()
   293  		sign = "-"
   294  	}
   295  
   296  	switch p.tok {
   297  	case scanner.Int:
   298  		val = constant.MakeFromLiteral(sign+p.lit, token.INT, 0)
   299  		if val == nil {
   300  			p.error("could not parse integer literal")
   301  		}
   302  
   303  		p.next()
   304  		if p.tok == '\'' {
   305  			p.next()
   306  			typ = types.Typ[types.UntypedRune]
   307  		} else {
   308  			typ = types.Typ[types.UntypedInt]
   309  		}
   310  
   311  	case scanner.Float:
   312  		re := sign + p.lit
   313  		p.next()
   314  
   315  		var im string
   316  		switch p.tok {
   317  		case '+':
   318  			p.next()
   319  			im = p.expect(scanner.Float)
   320  
   321  		case '-':
   322  			p.next()
   323  			im = "-" + p.expect(scanner.Float)
   324  
   325  		case scanner.Ident:
   326  			// re is in fact the imaginary component. Expect "i" below.
   327  			im = re
   328  			re = "0"
   329  
   330  		default:
   331  			val = constant.MakeFromLiteral(re, token.FLOAT, 0)
   332  			if val == nil {
   333  				p.error("could not parse float literal")
   334  			}
   335  			typ = types.Typ[types.UntypedFloat]
   336  			return
   337  		}
   338  
   339  		p.expectKeyword("i")
   340  		reval := constant.MakeFromLiteral(re, token.FLOAT, 0)
   341  		if reval == nil {
   342  			p.error("could not parse real component of complex literal")
   343  		}
   344  		imval := constant.MakeFromLiteral(im+"i", token.IMAG, 0)
   345  		if imval == nil {
   346  			p.error("could not parse imag component of complex literal")
   347  		}
   348  		val = constant.BinaryOp(reval, token.ADD, imval)
   349  		typ = types.Typ[types.UntypedComplex]
   350  
   351  	default:
   352  		p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit)
   353  	}
   354  
   355  	return
   356  }
   357  
   358  // Const = Name [Type] "=" ConstValue .
   359  func (p *parser) parseConst(pkg *types.Package) *types.Const {
   360  	name := p.parseName()
   361  	var typ types.Type
   362  	if p.tok == '<' {
   363  		typ = p.parseType(pkg)
   364  	}
   365  	p.expect('=')
   366  	val, vtyp := p.parseConstValue(pkg)
   367  	if typ == nil {
   368  		typ = vtyp
   369  	}
   370  	return types.NewConst(token.NoPos, pkg, name, typ, val)
   371  }
   372  
   373  // NamedType = TypeName [ "=" ] Type { Method } .
   374  // TypeName  = ExportedName .
   375  // Method    = "func" "(" Param ")" Name ParamList ResultList ";" .
   376  func (p *parser) parseNamedType(n int) types.Type {
   377  	pkg, name := p.parseExportedName()
   378  	scope := pkg.Scope()
   379  
   380  	if p.tok == '=' {
   381  		// type alias
   382  		p.next()
   383  		typ := p.parseType(pkg)
   384  		if obj := scope.Lookup(name); obj != nil {
   385  			typ = obj.Type() // use previously imported type
   386  			if typ == nil {
   387  				p.errorf("%v (type alias) used in cycle", obj)
   388  			}
   389  		} else {
   390  			obj = types.NewTypeName(token.NoPos, pkg, name, typ)
   391  			scope.Insert(obj)
   392  		}
   393  		p.typeMap[n] = typ
   394  		return typ
   395  	}
   396  
   397  	// named type
   398  	obj := scope.Lookup(name)
   399  	if obj == nil {
   400  		// a named type may be referred to before the underlying type
   401  		// is known - set it up
   402  		tname := types.NewTypeName(token.NoPos, pkg, name, nil)
   403  		types.NewNamed(tname, nil, nil)
   404  		scope.Insert(tname)
   405  		obj = tname
   406  	}
   407  
   408  	typ := obj.Type()
   409  	p.typeMap[n] = typ
   410  
   411  	nt, ok := typ.(*types.Named)
   412  	if !ok {
   413  		// This can happen for unsafe.Pointer, which is a TypeName holding a Basic type.
   414  		pt := p.parseType(pkg)
   415  		if pt != typ {
   416  			p.error("unexpected underlying type for non-named TypeName")
   417  		}
   418  		return typ
   419  	}
   420  
   421  	underlying := p.parseType(pkg)
   422  	if nt.Underlying() == nil {
   423  		nt.SetUnderlying(underlying.Underlying())
   424  	}
   425  
   426  	// collect associated methods
   427  	for p.tok == scanner.Ident {
   428  		p.expectKeyword("func")
   429  		p.expect('(')
   430  		receiver, _ := p.parseParam(pkg)
   431  		p.expect(')')
   432  		name := p.parseName()
   433  		params, isVariadic := p.parseParamList(pkg)
   434  		results := p.parseResultList(pkg)
   435  		p.expect(';')
   436  
   437  		sig := types.NewSignature(receiver, params, results, isVariadic)
   438  		nt.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig))
   439  	}
   440  
   441  	return nt
   442  }
   443  
   444  func (p *parser) parseInt() int64 {
   445  	lit := p.expect(scanner.Int)
   446  	n, err := strconv.ParseInt(lit, 10, 0)
   447  	if err != nil {
   448  		p.error(err)
   449  	}
   450  	return n
   451  }
   452  
   453  // ArrayOrSliceType = "[" [ int ] "]" Type .
   454  func (p *parser) parseArrayOrSliceType(pkg *types.Package) types.Type {
   455  	p.expect('[')
   456  	if p.tok == ']' {
   457  		p.next()
   458  		return types.NewSlice(p.parseType(pkg))
   459  	}
   460  
   461  	n := p.parseInt()
   462  	p.expect(']')
   463  	return types.NewArray(p.parseType(pkg), n)
   464  }
   465  
   466  // MapType = "map" "[" Type "]" Type .
   467  func (p *parser) parseMapType(pkg *types.Package) types.Type {
   468  	p.expectKeyword("map")
   469  	p.expect('[')
   470  	key := p.parseType(pkg)
   471  	p.expect(']')
   472  	elem := p.parseType(pkg)
   473  	return types.NewMap(key, elem)
   474  }
   475  
   476  // ChanType = "chan" ["<-" | "-<"] Type .
   477  func (p *parser) parseChanType(pkg *types.Package) types.Type {
   478  	p.expectKeyword("chan")
   479  	dir := types.SendRecv
   480  	switch p.tok {
   481  	case '-':
   482  		p.next()
   483  		p.expect('<')
   484  		dir = types.SendOnly
   485  
   486  	case '<':
   487  		// don't consume '<' if it belongs to Type
   488  		if p.scanner.Peek() == '-' {
   489  			p.next()
   490  			p.expect('-')
   491  			dir = types.RecvOnly
   492  		}
   493  	}
   494  
   495  	return types.NewChan(dir, p.parseType(pkg))
   496  }
   497  
   498  // StructType = "struct" "{" { Field } "}" .
   499  func (p *parser) parseStructType(pkg *types.Package) types.Type {
   500  	p.expectKeyword("struct")
   501  
   502  	var fields []*types.Var
   503  	var tags []string
   504  
   505  	p.expect('{')
   506  	for p.tok != '}' && p.tok != scanner.EOF {
   507  		field, tag := p.parseField(pkg)
   508  		p.expect(';')
   509  		fields = append(fields, field)
   510  		tags = append(tags, tag)
   511  	}
   512  	p.expect('}')
   513  
   514  	return types.NewStruct(fields, tags)
   515  }
   516  
   517  // ParamList = "(" [ { Parameter "," } Parameter ] ")" .
   518  func (p *parser) parseParamList(pkg *types.Package) (*types.Tuple, bool) {
   519  	var list []*types.Var
   520  	isVariadic := false
   521  
   522  	p.expect('(')
   523  	for p.tok != ')' && p.tok != scanner.EOF {
   524  		if len(list) > 0 {
   525  			p.expect(',')
   526  		}
   527  		par, variadic := p.parseParam(pkg)
   528  		list = append(list, par)
   529  		if variadic {
   530  			if isVariadic {
   531  				p.error("... not on final argument")
   532  			}
   533  			isVariadic = true
   534  		}
   535  	}
   536  	p.expect(')')
   537  
   538  	return types.NewTuple(list...), isVariadic
   539  }
   540  
   541  // ResultList = Type | ParamList .
   542  func (p *parser) parseResultList(pkg *types.Package) *types.Tuple {
   543  	switch p.tok {
   544  	case '<':
   545  		return types.NewTuple(types.NewParam(token.NoPos, pkg, "", p.parseType(pkg)))
   546  
   547  	case '(':
   548  		params, _ := p.parseParamList(pkg)
   549  		return params
   550  
   551  	default:
   552  		return nil
   553  	}
   554  }
   555  
   556  // FunctionType = ParamList ResultList .
   557  func (p *parser) parseFunctionType(pkg *types.Package) *types.Signature {
   558  	params, isVariadic := p.parseParamList(pkg)
   559  	results := p.parseResultList(pkg)
   560  	return types.NewSignature(nil, params, results, isVariadic)
   561  }
   562  
   563  // Func = Name FunctionType .
   564  func (p *parser) parseFunc(pkg *types.Package) *types.Func {
   565  	name := p.parseName()
   566  	if strings.ContainsRune(name, '$') {
   567  		// This is a Type$equal or Type$hash function, which we don't want to parse,
   568  		// except for the types.
   569  		p.discardDirectiveWhileParsingTypes(pkg)
   570  		return nil
   571  	}
   572  	return types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg))
   573  }
   574  
   575  // InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" .
   576  func (p *parser) parseInterfaceType(pkg *types.Package) types.Type {
   577  	p.expectKeyword("interface")
   578  
   579  	var methods []*types.Func
   580  	var typs []*types.Named
   581  
   582  	p.expect('{')
   583  	for p.tok != '}' && p.tok != scanner.EOF {
   584  		if p.tok == '?' {
   585  			p.next()
   586  			typs = append(typs, p.parseType(pkg).(*types.Named))
   587  		} else {
   588  			method := p.parseFunc(pkg)
   589  			methods = append(methods, method)
   590  		}
   591  		p.expect(';')
   592  	}
   593  	p.expect('}')
   594  
   595  	return types.NewInterface(methods, typs)
   596  }
   597  
   598  // PointerType = "*" ("any" | Type) .
   599  func (p *parser) parsePointerType(pkg *types.Package) types.Type {
   600  	p.expect('*')
   601  	if p.tok == scanner.Ident {
   602  		p.expectKeyword("any")
   603  		return types.Typ[types.UnsafePointer]
   604  	}
   605  	return types.NewPointer(p.parseType(pkg))
   606  }
   607  
   608  // TypeDefinition = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType .
   609  func (p *parser) parseTypeDefinition(pkg *types.Package, n int) types.Type {
   610  	var t types.Type
   611  	switch p.tok {
   612  	case scanner.String:
   613  		t = p.parseNamedType(n)
   614  
   615  	case scanner.Ident:
   616  		switch p.lit {
   617  		case "map":
   618  			t = p.parseMapType(pkg)
   619  
   620  		case "chan":
   621  			t = p.parseChanType(pkg)
   622  
   623  		case "struct":
   624  			t = p.parseStructType(pkg)
   625  
   626  		case "interface":
   627  			t = p.parseInterfaceType(pkg)
   628  		}
   629  
   630  	case '*':
   631  		t = p.parsePointerType(pkg)
   632  
   633  	case '[':
   634  		t = p.parseArrayOrSliceType(pkg)
   635  
   636  	case '(':
   637  		t = p.parseFunctionType(pkg)
   638  	}
   639  
   640  	p.typeMap[n] = t
   641  	return t
   642  }
   643  
   644  const (
   645  	// From gofrontend/go/export.h
   646  	// Note that these values are negative in the gofrontend and have been made positive
   647  	// in the gccgoimporter.
   648  	gccgoBuiltinINT8       = 1
   649  	gccgoBuiltinINT16      = 2
   650  	gccgoBuiltinINT32      = 3
   651  	gccgoBuiltinINT64      = 4
   652  	gccgoBuiltinUINT8      = 5
   653  	gccgoBuiltinUINT16     = 6
   654  	gccgoBuiltinUINT32     = 7
   655  	gccgoBuiltinUINT64     = 8
   656  	gccgoBuiltinFLOAT32    = 9
   657  	gccgoBuiltinFLOAT64    = 10
   658  	gccgoBuiltinINT        = 11
   659  	gccgoBuiltinUINT       = 12
   660  	gccgoBuiltinUINTPTR    = 13
   661  	gccgoBuiltinBOOL       = 15
   662  	gccgoBuiltinSTRING     = 16
   663  	gccgoBuiltinCOMPLEX64  = 17
   664  	gccgoBuiltinCOMPLEX128 = 18
   665  	gccgoBuiltinERROR      = 19
   666  	gccgoBuiltinBYTE       = 20
   667  	gccgoBuiltinRUNE       = 21
   668  )
   669  
   670  func lookupBuiltinType(typ int) types.Type {
   671  	return [...]types.Type{
   672  		gccgoBuiltinINT8:       types.Typ[types.Int8],
   673  		gccgoBuiltinINT16:      types.Typ[types.Int16],
   674  		gccgoBuiltinINT32:      types.Typ[types.Int32],
   675  		gccgoBuiltinINT64:      types.Typ[types.Int64],
   676  		gccgoBuiltinUINT8:      types.Typ[types.Uint8],
   677  		gccgoBuiltinUINT16:     types.Typ[types.Uint16],
   678  		gccgoBuiltinUINT32:     types.Typ[types.Uint32],
   679  		gccgoBuiltinUINT64:     types.Typ[types.Uint64],
   680  		gccgoBuiltinFLOAT32:    types.Typ[types.Float32],
   681  		gccgoBuiltinFLOAT64:    types.Typ[types.Float64],
   682  		gccgoBuiltinINT:        types.Typ[types.Int],
   683  		gccgoBuiltinUINT:       types.Typ[types.Uint],
   684  		gccgoBuiltinUINTPTR:    types.Typ[types.Uintptr],
   685  		gccgoBuiltinBOOL:       types.Typ[types.Bool],
   686  		gccgoBuiltinSTRING:     types.Typ[types.String],
   687  		gccgoBuiltinCOMPLEX64:  types.Typ[types.Complex64],
   688  		gccgoBuiltinCOMPLEX128: types.Typ[types.Complex128],
   689  		gccgoBuiltinERROR:      types.Universe.Lookup("error").Type(),
   690  		gccgoBuiltinBYTE:       types.Universe.Lookup("byte").Type(),
   691  		gccgoBuiltinRUNE:       types.Universe.Lookup("rune").Type(),
   692  	}[typ]
   693  }
   694  
   695  // Type = "<" "type" ( "-" int | int [ TypeDefinition ] ) ">" .
   696  func (p *parser) parseType(pkg *types.Package) (t types.Type) {
   697  	p.expect('<')
   698  	p.expectKeyword("type")
   699  
   700  	switch p.tok {
   701  	case scanner.Int:
   702  		n := p.parseInt()
   703  
   704  		if p.tok == '>' {
   705  			t = p.typeMap[int(n)]
   706  		} else {
   707  			t = p.parseTypeDefinition(pkg, int(n))
   708  		}
   709  
   710  	case '-':
   711  		p.next()
   712  		n := p.parseInt()
   713  		t = lookupBuiltinType(int(n))
   714  
   715  	default:
   716  		p.errorf("expected type number, got %s (%q)", scanner.TokenString(p.tok), p.lit)
   717  		return nil
   718  	}
   719  
   720  	p.expect('>')
   721  	return
   722  }
   723  
   724  // PackageInit = unquotedString unquotedString int .
   725  func (p *parser) parsePackageInit() PackageInit {
   726  	name := p.parseUnquotedString()
   727  	initfunc := p.parseUnquotedString()
   728  	priority := -1
   729  	if p.version == "v1" {
   730  		priority = int(p.parseInt())
   731  	}
   732  	return PackageInit{Name: name, InitFunc: initfunc, Priority: priority}
   733  }
   734  
   735  // Throw away tokens until we see a ';'. If we see a '<', attempt to parse as a type.
   736  func (p *parser) discardDirectiveWhileParsingTypes(pkg *types.Package) {
   737  	for {
   738  		switch p.tok {
   739  		case ';':
   740  			return
   741  		case '<':
   742  			p.parseType(pkg)
   743  		case scanner.EOF:
   744  			p.error("unexpected EOF")
   745  		default:
   746  			p.next()
   747  		}
   748  	}
   749  }
   750  
   751  // Create the package if we have parsed both the package path and package name.
   752  func (p *parser) maybeCreatePackage() {
   753  	if p.pkgname != "" && p.pkgpath != "" {
   754  		p.pkg = p.getPkg(p.pkgpath, p.pkgname)
   755  	}
   756  }
   757  
   758  // InitDataDirective = ( "v1" | "v2" ) ";" |
   759  //                     "priority" int ";" |
   760  //                     "init" { PackageInit } ";" |
   761  //                     "checksum" unquotedString ";" .
   762  func (p *parser) parseInitDataDirective() {
   763  	if p.tok != scanner.Ident {
   764  		// unexpected token kind; panic
   765  		p.expect(scanner.Ident)
   766  	}
   767  
   768  	switch p.lit {
   769  	case "v1", "v2":
   770  		p.version = p.lit
   771  		p.next()
   772  		p.expect(';')
   773  
   774  	case "priority":
   775  		p.next()
   776  		p.initdata.Priority = int(p.parseInt())
   777  		p.expect(';')
   778  
   779  	case "init":
   780  		p.next()
   781  		for p.tok != ';' && p.tok != scanner.EOF {
   782  			p.initdata.Inits = append(p.initdata.Inits, p.parsePackageInit())
   783  		}
   784  		p.expect(';')
   785  
   786  	case "init_graph":
   787  		p.next()
   788  		// The graph data is thrown away for now.
   789  		for p.tok != ';' && p.tok != scanner.EOF {
   790  			p.parseInt()
   791  			p.parseInt()
   792  		}
   793  		p.expect(';')
   794  
   795  	case "checksum":
   796  		// Don't let the scanner try to parse the checksum as a number.
   797  		defer func(mode uint) {
   798  			p.scanner.Mode = mode
   799  		}(p.scanner.Mode)
   800  		p.scanner.Mode &^= scanner.ScanInts | scanner.ScanFloats
   801  		p.next()
   802  		p.parseUnquotedString()
   803  		p.expect(';')
   804  
   805  	default:
   806  		p.errorf("unexpected identifier: %q", p.lit)
   807  	}
   808  }
   809  
   810  // Directive = InitDataDirective |
   811  //             "package" unquotedString [ unquotedString ] [ unquotedString ] ";" |
   812  //             "pkgpath" unquotedString ";" |
   813  //             "prefix" unquotedString ";" |
   814  //             "import" unquotedString unquotedString string ";" |
   815  //             "func" Func ";" |
   816  //             "type" Type ";" |
   817  //             "var" Var ";" |
   818  //             "const" Const ";" .
   819  func (p *parser) parseDirective() {
   820  	if p.tok != scanner.Ident {
   821  		// unexpected token kind; panic
   822  		p.expect(scanner.Ident)
   823  	}
   824  
   825  	switch p.lit {
   826  	case "v1", "v2", "priority", "init", "init_graph", "checksum":
   827  		p.parseInitDataDirective()
   828  
   829  	case "package":
   830  		p.next()
   831  		p.pkgname = p.parseUnquotedString()
   832  		p.maybeCreatePackage()
   833  		if p.version == "v2" && p.tok != ';' {
   834  			p.parseUnquotedString()
   835  			p.parseUnquotedString()
   836  		}
   837  		p.expect(';')
   838  
   839  	case "pkgpath":
   840  		p.next()
   841  		p.pkgpath = p.parseUnquotedString()
   842  		p.maybeCreatePackage()
   843  		p.expect(';')
   844  
   845  	case "prefix":
   846  		p.next()
   847  		p.pkgpath = p.parseUnquotedString()
   848  		p.expect(';')
   849  
   850  	case "import":
   851  		p.next()
   852  		pkgname := p.parseUnquotedString()
   853  		pkgpath := p.parseUnquotedString()
   854  		p.getPkg(pkgpath, pkgname)
   855  		p.parseString()
   856  		p.expect(';')
   857  
   858  	case "func":
   859  		p.next()
   860  		fun := p.parseFunc(p.pkg)
   861  		if fun != nil {
   862  			p.pkg.Scope().Insert(fun)
   863  		}
   864  		p.expect(';')
   865  
   866  	case "type":
   867  		p.next()
   868  		p.parseType(p.pkg)
   869  		p.expect(';')
   870  
   871  	case "var":
   872  		p.next()
   873  		v := p.parseVar(p.pkg)
   874  		p.pkg.Scope().Insert(v)
   875  		p.expect(';')
   876  
   877  	case "const":
   878  		p.next()
   879  		c := p.parseConst(p.pkg)
   880  		p.pkg.Scope().Insert(c)
   881  		p.expect(';')
   882  
   883  	default:
   884  		p.errorf("unexpected identifier: %q", p.lit)
   885  	}
   886  }
   887  
   888  // Package = { Directive } .
   889  func (p *parser) parsePackage() *types.Package {
   890  	for p.tok != scanner.EOF {
   891  		p.parseDirective()
   892  	}
   893  	for _, typ := range p.typeMap {
   894  		if it, ok := typ.(*types.Interface); ok {
   895  			it.Complete()
   896  		}
   897  	}
   898  	p.pkg.MarkComplete()
   899  	return p.pkg
   900  }
   901  
   902  // InitData = { InitDataDirective } .
   903  func (p *parser) parseInitData() {
   904  	for p.tok != scanner.EOF {
   905  		p.parseInitDataDirective()
   906  	}
   907  }