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