github.com/ltltlt/go-source-code@v0.0.0-20190830023027-95be009773aa/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 == '<' && 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 typs []*types.Named 589 590 p.expect('{') 591 for p.tok != '}' && p.tok != scanner.EOF { 592 if p.tok == '?' { 593 p.next() 594 typs = append(typs, p.parseType(pkg).(*types.Named)) 595 } else { 596 method := p.parseFunc(pkg) 597 methods = append(methods, method) 598 } 599 p.expect(';') 600 } 601 p.expect('}') 602 603 return types.NewInterface(methods, typs) 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 910 // InitData = { InitDataDirective } . 911 func (p *parser) parseInitData() { 912 for p.tok != scanner.EOF { 913 p.parseInitDataDirective() 914 } 915 }