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 }