...
Run Format

Source file src/go/internal/gccgoimporter/parser.go

Documentation: go/internal/gccgoimporter

     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 == '<' && p.scanner.Peek() == 'e' {
   230  		// EscInfo = "<esc:" int ">" . (optional and ignored)
   231  		p.next()
   232  		p.expectKeyword("esc")
   233  		p.expect(':')
   234  		p.expect(scanner.Int)
   235  		p.expect('>')
   236  	}
   237  	if p.tok == '.' {
   238  		p.next()
   239  		p.expect('.')
   240  		p.expect('.')
   241  		isVariadic = true
   242  	}
   243  	typ := p.parseType(pkg)
   244  	if isVariadic {
   245  		typ = types.NewSlice(typ)
   246  	}
   247  	param = types.NewParam(token.NoPos, pkg, name, typ)
   248  	return
   249  }
   250  
   251  // Var = Name Type .
   252  func (p *parser) parseVar(pkg *types.Package) *types.Var {
   253  	name := p.parseName()
   254  	return types.NewVar(token.NoPos, pkg, name, p.parseType(pkg))
   255  }
   256  
   257  // Conversion = "convert" "(" Type "," ConstValue ")" .
   258  func (p *parser) parseConversion(pkg *types.Package) (val constant.Value, typ types.Type) {
   259  	p.expectKeyword("convert")
   260  	p.expect('(')
   261  	typ = p.parseType(pkg)
   262  	p.expect(',')
   263  	val, _ = p.parseConstValue(pkg)
   264  	p.expect(')')
   265  	return
   266  }
   267  
   268  // ConstValue     = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) | Conversion .
   269  // FloatOrComplex = float ["i" | ("+"|"-") float "i"] .
   270  func (p *parser) parseConstValue(pkg *types.Package) (val constant.Value, typ types.Type) {
   271  	switch p.tok {
   272  	case scanner.String:
   273  		str := p.parseString()
   274  		val = constant.MakeString(str)
   275  		typ = types.Typ[types.UntypedString]
   276  		return
   277  
   278  	case scanner.Ident:
   279  		b := false
   280  		switch p.lit {
   281  		case "false":
   282  		case "true":
   283  			b = true
   284  
   285  		case "convert":
   286  			return p.parseConversion(pkg)
   287  
   288  		default:
   289  			p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit)
   290  		}
   291  
   292  		p.next()
   293  		val = constant.MakeBool(b)
   294  		typ = types.Typ[types.UntypedBool]
   295  		return
   296  	}
   297  
   298  	sign := ""
   299  	if p.tok == '-' {
   300  		p.next()
   301  		sign = "-"
   302  	}
   303  
   304  	switch p.tok {
   305  	case scanner.Int:
   306  		val = constant.MakeFromLiteral(sign+p.lit, token.INT, 0)
   307  		if val == nil {
   308  			p.error("could not parse integer literal")
   309  		}
   310  
   311  		p.next()
   312  		if p.tok == '\'' {
   313  			p.next()
   314  			typ = types.Typ[types.UntypedRune]
   315  		} else {
   316  			typ = types.Typ[types.UntypedInt]
   317  		}
   318  
   319  	case scanner.Float:
   320  		re := sign + p.lit
   321  		p.next()
   322  
   323  		var im string
   324  		switch p.tok {
   325  		case '+':
   326  			p.next()
   327  			im = p.expect(scanner.Float)
   328  
   329  		case '-':
   330  			p.next()
   331  			im = "-" + p.expect(scanner.Float)
   332  
   333  		case scanner.Ident:
   334  			// re is in fact the imaginary component. Expect "i" below.
   335  			im = re
   336  			re = "0"
   337  
   338  		default:
   339  			val = constant.MakeFromLiteral(re, token.FLOAT, 0)
   340  			if val == nil {
   341  				p.error("could not parse float literal")
   342  			}
   343  			typ = types.Typ[types.UntypedFloat]
   344  			return
   345  		}
   346  
   347  		p.expectKeyword("i")
   348  		reval := constant.MakeFromLiteral(re, token.FLOAT, 0)
   349  		if reval == nil {
   350  			p.error("could not parse real component of complex literal")
   351  		}
   352  		imval := constant.MakeFromLiteral(im+"i", token.IMAG, 0)
   353  		if imval == nil {
   354  			p.error("could not parse imag component of complex literal")
   355  		}
   356  		val = constant.BinaryOp(reval, token.ADD, imval)
   357  		typ = types.Typ[types.UntypedComplex]
   358  
   359  	default:
   360  		p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit)
   361  	}
   362  
   363  	return
   364  }
   365  
   366  // Const = Name [Type] "=" ConstValue .
   367  func (p *parser) parseConst(pkg *types.Package) *types.Const {
   368  	name := p.parseName()
   369  	var typ types.Type
   370  	if p.tok == '<' {
   371  		typ = p.parseType(pkg)
   372  	}
   373  	p.expect('=')
   374  	val, vtyp := p.parseConstValue(pkg)
   375  	if typ == nil {
   376  		typ = vtyp
   377  	}
   378  	return types.NewConst(token.NoPos, pkg, name, typ, val)
   379  }
   380  
   381  // NamedType = TypeName [ "=" ] Type { Method } .
   382  // TypeName  = ExportedName .
   383  // Method    = "func" "(" Param ")" Name ParamList ResultList ";" .
   384  func (p *parser) parseNamedType(n int) types.Type {
   385  	pkg, name := p.parseExportedName()
   386  	scope := pkg.Scope()
   387  
   388  	if p.tok == '=' {
   389  		// type alias
   390  		p.next()
   391  		typ := p.parseType(pkg)
   392  		if obj := scope.Lookup(name); obj != nil {
   393  			typ = obj.Type() // use previously imported type
   394  			if typ == nil {
   395  				p.errorf("%v (type alias) used in cycle", obj)
   396  			}
   397  		} else {
   398  			obj = types.NewTypeName(token.NoPos, pkg, name, typ)
   399  			scope.Insert(obj)
   400  		}
   401  		p.typeMap[n] = typ
   402  		return typ
   403  	}
   404  
   405  	// named type
   406  	obj := scope.Lookup(name)
   407  	if obj == nil {
   408  		// a named type may be referred to before the underlying type
   409  		// is known - set it up
   410  		tname := types.NewTypeName(token.NoPos, pkg, name, nil)
   411  		types.NewNamed(tname, nil, nil)
   412  		scope.Insert(tname)
   413  		obj = tname
   414  	}
   415  
   416  	typ := obj.Type()
   417  	p.typeMap[n] = typ
   418  
   419  	nt, ok := typ.(*types.Named)
   420  	if !ok {
   421  		// This can happen for unsafe.Pointer, which is a TypeName holding a Basic type.
   422  		pt := p.parseType(pkg)
   423  		if pt != typ {
   424  			p.error("unexpected underlying type for non-named TypeName")
   425  		}
   426  		return typ
   427  	}
   428  
   429  	underlying := p.parseType(pkg)
   430  	if nt.Underlying() == nil {
   431  		nt.SetUnderlying(underlying.Underlying())
   432  	}
   433  
   434  	// collect associated methods
   435  	for p.tok == scanner.Ident {
   436  		p.expectKeyword("func")
   437  		p.expect('(')
   438  		receiver, _ := p.parseParam(pkg)
   439  		p.expect(')')
   440  		name := p.parseName()
   441  		params, isVariadic := p.parseParamList(pkg)
   442  		results := p.parseResultList(pkg)
   443  		p.expect(';')
   444  
   445  		sig := types.NewSignature(receiver, params, results, isVariadic)
   446  		nt.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig))
   447  	}
   448  
   449  	return nt
   450  }
   451  
   452  func (p *parser) parseInt() int64 {
   453  	lit := p.expect(scanner.Int)
   454  	n, err := strconv.ParseInt(lit, 10, 0)
   455  	if err != nil {
   456  		p.error(err)
   457  	}
   458  	return n
   459  }
   460  
   461  // ArrayOrSliceType = "[" [ int ] "]" Type .
   462  func (p *parser) parseArrayOrSliceType(pkg *types.Package) types.Type {
   463  	p.expect('[')
   464  	if p.tok == ']' {
   465  		p.next()
   466  		return types.NewSlice(p.parseType(pkg))
   467  	}
   468  
   469  	n := p.parseInt()
   470  	p.expect(']')
   471  	return types.NewArray(p.parseType(pkg), n)
   472  }
   473  
   474  // MapType = "map" "[" Type "]" Type .
   475  func (p *parser) parseMapType(pkg *types.Package) types.Type {
   476  	p.expectKeyword("map")
   477  	p.expect('[')
   478  	key := p.parseType(pkg)
   479  	p.expect(']')
   480  	elem := p.parseType(pkg)
   481  	return types.NewMap(key, elem)
   482  }
   483  
   484  // ChanType = "chan" ["<-" | "-<"] Type .
   485  func (p *parser) parseChanType(pkg *types.Package) types.Type {
   486  	p.expectKeyword("chan")
   487  	dir := types.SendRecv
   488  	switch p.tok {
   489  	case '-':
   490  		p.next()
   491  		p.expect('<')
   492  		dir = types.SendOnly
   493  
   494  	case '<':
   495  		// don't consume '<' if it belongs to Type
   496  		if p.scanner.Peek() == '-' {
   497  			p.next()
   498  			p.expect('-')
   499  			dir = types.RecvOnly
   500  		}
   501  	}
   502  
   503  	return types.NewChan(dir, p.parseType(pkg))
   504  }
   505  
   506  // StructType = "struct" "{" { Field } "}" .
   507  func (p *parser) parseStructType(pkg *types.Package) types.Type {
   508  	p.expectKeyword("struct")
   509  
   510  	var fields []*types.Var
   511  	var tags []string
   512  
   513  	p.expect('{')
   514  	for p.tok != '}' && p.tok != scanner.EOF {
   515  		field, tag := p.parseField(pkg)
   516  		p.expect(';')
   517  		fields = append(fields, field)
   518  		tags = append(tags, tag)
   519  	}
   520  	p.expect('}')
   521  
   522  	return types.NewStruct(fields, tags)
   523  }
   524  
   525  // ParamList = "(" [ { Parameter "," } Parameter ] ")" .
   526  func (p *parser) parseParamList(pkg *types.Package) (*types.Tuple, bool) {
   527  	var list []*types.Var
   528  	isVariadic := false
   529  
   530  	p.expect('(')
   531  	for p.tok != ')' && p.tok != scanner.EOF {
   532  		if len(list) > 0 {
   533  			p.expect(',')
   534  		}
   535  		par, variadic := p.parseParam(pkg)
   536  		list = append(list, par)
   537  		if variadic {
   538  			if isVariadic {
   539  				p.error("... not on final argument")
   540  			}
   541  			isVariadic = true
   542  		}
   543  	}
   544  	p.expect(')')
   545  
   546  	return types.NewTuple(list...), isVariadic
   547  }
   548  
   549  // ResultList = Type | ParamList .
   550  func (p *parser) parseResultList(pkg *types.Package) *types.Tuple {
   551  	switch p.tok {
   552  	case '<':
   553  		return types.NewTuple(types.NewParam(token.NoPos, pkg, "", p.parseType(pkg)))
   554  
   555  	case '(':
   556  		params, _ := p.parseParamList(pkg)
   557  		return params
   558  
   559  	default:
   560  		return nil
   561  	}
   562  }
   563  
   564  // FunctionType = ParamList ResultList .
   565  func (p *parser) parseFunctionType(pkg *types.Package) *types.Signature {
   566  	params, isVariadic := p.parseParamList(pkg)
   567  	results := p.parseResultList(pkg)
   568  	return types.NewSignature(nil, params, results, isVariadic)
   569  }
   570  
   571  // Func = Name FunctionType .
   572  func (p *parser) parseFunc(pkg *types.Package) *types.Func {
   573  	name := p.parseName()
   574  	if strings.ContainsRune(name, '$') {
   575  		// This is a Type$equal or Type$hash function, which we don't want to parse,
   576  		// except for the types.
   577  		p.discardDirectiveWhileParsingTypes(pkg)
   578  		return nil
   579  	}
   580  	return types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg))
   581  }
   582  
   583  // InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" .
   584  func (p *parser) parseInterfaceType(pkg *types.Package) types.Type {
   585  	p.expectKeyword("interface")
   586  
   587  	var methods []*types.Func
   588  	var embeddeds []types.Type
   589  
   590  	p.expect('{')
   591  	for p.tok != '}' && p.tok != scanner.EOF {
   592  		if p.tok == '?' {
   593  			p.next()
   594  			embeddeds = append(embeddeds, p.parseType(pkg))
   595  		} else {
   596  			method := p.parseFunc(pkg)
   597  			methods = append(methods, method)
   598  		}
   599  		p.expect(';')
   600  	}
   601  	p.expect('}')
   602  
   603  	return types.NewInterfaceType(methods, embeddeds)
   604  }
   605  
   606  // PointerType = "*" ("any" | Type) .
   607  func (p *parser) parsePointerType(pkg *types.Package) types.Type {
   608  	p.expect('*')
   609  	if p.tok == scanner.Ident {
   610  		p.expectKeyword("any")
   611  		return types.Typ[types.UnsafePointer]
   612  	}
   613  	return types.NewPointer(p.parseType(pkg))
   614  }
   615  
   616  // TypeDefinition = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType .
   617  func (p *parser) parseTypeDefinition(pkg *types.Package, n int) types.Type {
   618  	var t types.Type
   619  	switch p.tok {
   620  	case scanner.String:
   621  		t = p.parseNamedType(n)
   622  
   623  	case scanner.Ident:
   624  		switch p.lit {
   625  		case "map":
   626  			t = p.parseMapType(pkg)
   627  
   628  		case "chan":
   629  			t = p.parseChanType(pkg)
   630  
   631  		case "struct":
   632  			t = p.parseStructType(pkg)
   633  
   634  		case "interface":
   635  			t = p.parseInterfaceType(pkg)
   636  		}
   637  
   638  	case '*':
   639  		t = p.parsePointerType(pkg)
   640  
   641  	case '[':
   642  		t = p.parseArrayOrSliceType(pkg)
   643  
   644  	case '(':
   645  		t = p.parseFunctionType(pkg)
   646  	}
   647  
   648  	p.typeMap[n] = t
   649  	return t
   650  }
   651  
   652  const (
   653  	// From gofrontend/go/export.h
   654  	// Note that these values are negative in the gofrontend and have been made positive
   655  	// in the gccgoimporter.
   656  	gccgoBuiltinINT8       = 1
   657  	gccgoBuiltinINT16      = 2
   658  	gccgoBuiltinINT32      = 3
   659  	gccgoBuiltinINT64      = 4
   660  	gccgoBuiltinUINT8      = 5
   661  	gccgoBuiltinUINT16     = 6
   662  	gccgoBuiltinUINT32     = 7
   663  	gccgoBuiltinUINT64     = 8
   664  	gccgoBuiltinFLOAT32    = 9
   665  	gccgoBuiltinFLOAT64    = 10
   666  	gccgoBuiltinINT        = 11
   667  	gccgoBuiltinUINT       = 12
   668  	gccgoBuiltinUINTPTR    = 13
   669  	gccgoBuiltinBOOL       = 15
   670  	gccgoBuiltinSTRING     = 16
   671  	gccgoBuiltinCOMPLEX64  = 17
   672  	gccgoBuiltinCOMPLEX128 = 18
   673  	gccgoBuiltinERROR      = 19
   674  	gccgoBuiltinBYTE       = 20
   675  	gccgoBuiltinRUNE       = 21
   676  )
   677  
   678  func lookupBuiltinType(typ int) types.Type {
   679  	return [...]types.Type{
   680  		gccgoBuiltinINT8:       types.Typ[types.Int8],
   681  		gccgoBuiltinINT16:      types.Typ[types.Int16],
   682  		gccgoBuiltinINT32:      types.Typ[types.Int32],
   683  		gccgoBuiltinINT64:      types.Typ[types.Int64],
   684  		gccgoBuiltinUINT8:      types.Typ[types.Uint8],
   685  		gccgoBuiltinUINT16:     types.Typ[types.Uint16],
   686  		gccgoBuiltinUINT32:     types.Typ[types.Uint32],
   687  		gccgoBuiltinUINT64:     types.Typ[types.Uint64],
   688  		gccgoBuiltinFLOAT32:    types.Typ[types.Float32],
   689  		gccgoBuiltinFLOAT64:    types.Typ[types.Float64],
   690  		gccgoBuiltinINT:        types.Typ[types.Int],
   691  		gccgoBuiltinUINT:       types.Typ[types.Uint],
   692  		gccgoBuiltinUINTPTR:    types.Typ[types.Uintptr],
   693  		gccgoBuiltinBOOL:       types.Typ[types.Bool],
   694  		gccgoBuiltinSTRING:     types.Typ[types.String],
   695  		gccgoBuiltinCOMPLEX64:  types.Typ[types.Complex64],
   696  		gccgoBuiltinCOMPLEX128: types.Typ[types.Complex128],
   697  		gccgoBuiltinERROR:      types.Universe.Lookup("error").Type(),
   698  		gccgoBuiltinBYTE:       types.Universe.Lookup("byte").Type(),
   699  		gccgoBuiltinRUNE:       types.Universe.Lookup("rune").Type(),
   700  	}[typ]
   701  }
   702  
   703  // Type = "<" "type" ( "-" int | int [ TypeDefinition ] ) ">" .
   704  func (p *parser) parseType(pkg *types.Package) (t types.Type) {
   705  	p.expect('<')
   706  	p.expectKeyword("type")
   707  
   708  	switch p.tok {
   709  	case scanner.Int:
   710  		n := p.parseInt()
   711  
   712  		if p.tok == '>' {
   713  			t = p.typeMap[int(n)]
   714  		} else {
   715  			t = p.parseTypeDefinition(pkg, int(n))
   716  		}
   717  
   718  	case '-':
   719  		p.next()
   720  		n := p.parseInt()
   721  		t = lookupBuiltinType(int(n))
   722  
   723  	default:
   724  		p.errorf("expected type number, got %s (%q)", scanner.TokenString(p.tok), p.lit)
   725  		return nil
   726  	}
   727  
   728  	p.expect('>')
   729  	return
   730  }
   731  
   732  // PackageInit = unquotedString unquotedString int .
   733  func (p *parser) parsePackageInit() PackageInit {
   734  	name := p.parseUnquotedString()
   735  	initfunc := p.parseUnquotedString()
   736  	priority := -1
   737  	if p.version == "v1" {
   738  		priority = int(p.parseInt())
   739  	}
   740  	return PackageInit{Name: name, InitFunc: initfunc, Priority: priority}
   741  }
   742  
   743  // Throw away tokens until we see a ';'. If we see a '<', attempt to parse as a type.
   744  func (p *parser) discardDirectiveWhileParsingTypes(pkg *types.Package) {
   745  	for {
   746  		switch p.tok {
   747  		case ';':
   748  			return
   749  		case '<':
   750  			p.parseType(pkg)
   751  		case scanner.EOF:
   752  			p.error("unexpected EOF")
   753  		default:
   754  			p.next()
   755  		}
   756  	}
   757  }
   758  
   759  // Create the package if we have parsed both the package path and package name.
   760  func (p *parser) maybeCreatePackage() {
   761  	if p.pkgname != "" && p.pkgpath != "" {
   762  		p.pkg = p.getPkg(p.pkgpath, p.pkgname)
   763  	}
   764  }
   765  
   766  // InitDataDirective = ( "v1" | "v2" ) ";" |
   767  //                     "priority" int ";" |
   768  //                     "init" { PackageInit } ";" |
   769  //                     "checksum" unquotedString ";" .
   770  func (p *parser) parseInitDataDirective() {
   771  	if p.tok != scanner.Ident {
   772  		// unexpected token kind; panic
   773  		p.expect(scanner.Ident)
   774  	}
   775  
   776  	switch p.lit {
   777  	case "v1", "v2":
   778  		p.version = p.lit
   779  		p.next()
   780  		p.expect(';')
   781  
   782  	case "priority":
   783  		p.next()
   784  		p.initdata.Priority = int(p.parseInt())
   785  		p.expect(';')
   786  
   787  	case "init":
   788  		p.next()
   789  		for p.tok != ';' && p.tok != scanner.EOF {
   790  			p.initdata.Inits = append(p.initdata.Inits, p.parsePackageInit())
   791  		}
   792  		p.expect(';')
   793  
   794  	case "init_graph":
   795  		p.next()
   796  		// The graph data is thrown away for now.
   797  		for p.tok != ';' && p.tok != scanner.EOF {
   798  			p.parseInt()
   799  			p.parseInt()
   800  		}
   801  		p.expect(';')
   802  
   803  	case "checksum":
   804  		// Don't let the scanner try to parse the checksum as a number.
   805  		defer func(mode uint) {
   806  			p.scanner.Mode = mode
   807  		}(p.scanner.Mode)
   808  		p.scanner.Mode &^= scanner.ScanInts | scanner.ScanFloats
   809  		p.next()
   810  		p.parseUnquotedString()
   811  		p.expect(';')
   812  
   813  	default:
   814  		p.errorf("unexpected identifier: %q", p.lit)
   815  	}
   816  }
   817  
   818  // Directive = InitDataDirective |
   819  //             "package" unquotedString [ unquotedString ] [ unquotedString ] ";" |
   820  //             "pkgpath" unquotedString ";" |
   821  //             "prefix" unquotedString ";" |
   822  //             "import" unquotedString unquotedString string ";" |
   823  //             "func" Func ";" |
   824  //             "type" Type ";" |
   825  //             "var" Var ";" |
   826  //             "const" Const ";" .
   827  func (p *parser) parseDirective() {
   828  	if p.tok != scanner.Ident {
   829  		// unexpected token kind; panic
   830  		p.expect(scanner.Ident)
   831  	}
   832  
   833  	switch p.lit {
   834  	case "v1", "v2", "priority", "init", "init_graph", "checksum":
   835  		p.parseInitDataDirective()
   836  
   837  	case "package":
   838  		p.next()
   839  		p.pkgname = p.parseUnquotedString()
   840  		p.maybeCreatePackage()
   841  		if p.version == "v2" && p.tok != ';' {
   842  			p.parseUnquotedString()
   843  			p.parseUnquotedString()
   844  		}
   845  		p.expect(';')
   846  
   847  	case "pkgpath":
   848  		p.next()
   849  		p.pkgpath = p.parseUnquotedString()
   850  		p.maybeCreatePackage()
   851  		p.expect(';')
   852  
   853  	case "prefix":
   854  		p.next()
   855  		p.pkgpath = p.parseUnquotedString()
   856  		p.expect(';')
   857  
   858  	case "import":
   859  		p.next()
   860  		pkgname := p.parseUnquotedString()
   861  		pkgpath := p.parseUnquotedString()
   862  		p.getPkg(pkgpath, pkgname)
   863  		p.parseString()
   864  		p.expect(';')
   865  
   866  	case "func":
   867  		p.next()
   868  		fun := p.parseFunc(p.pkg)
   869  		if fun != nil {
   870  			p.pkg.Scope().Insert(fun)
   871  		}
   872  		p.expect(';')
   873  
   874  	case "type":
   875  		p.next()
   876  		p.parseType(p.pkg)
   877  		p.expect(';')
   878  
   879  	case "var":
   880  		p.next()
   881  		v := p.parseVar(p.pkg)
   882  		p.pkg.Scope().Insert(v)
   883  		p.expect(';')
   884  
   885  	case "const":
   886  		p.next()
   887  		c := p.parseConst(p.pkg)
   888  		p.pkg.Scope().Insert(c)
   889  		p.expect(';')
   890  
   891  	default:
   892  		p.errorf("unexpected identifier: %q", p.lit)
   893  	}
   894  }
   895  
   896  // Package = { Directive } .
   897  func (p *parser) parsePackage() *types.Package {
   898  	for p.tok != scanner.EOF {
   899  		p.parseDirective()
   900  	}
   901  	for _, typ := range p.typeMap {
   902  		if it, ok := typ.(*types.Interface); ok {
   903  			it.Complete()
   904  		}
   905  	}
   906  	p.pkg.MarkComplete()
   907  	return p.pkg
   908  }
   909  

View as plain text