// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gccgoimporter

import (
	
	
	
	
	
	
	
	
	
	
)

type parser struct {
	scanner  *scanner.Scanner
	version  string                    // format version
	tok      rune                      // current token
	lit      string                    // literal string; only valid for Ident, Int, String tokens
	pkgpath  string                    // package path of imported package
	pkgname  string                    // name of imported package
	pkg      *types.Package            // reference to imported package
	imports  map[string]*types.Package // package path -> package object
	typeList []types.Type              // type number -> type
	typeData []string                  // unparsed type data (v3 and later)
	fixups   []fixupRecord             // fixups to apply at end of parsing
	initdata InitData                  // package init priority data
	aliases  map[int]string            // maps saved type number to alias name
}

// When reading export data it's possible to encounter a defined type
// N1 with an underlying defined type N2 while we are still reading in
// that defined type N2; see issues #29006 and #29198 for instances
// of this. Example:
//
//   type N1 N2
//   type N2 struct {
//      ...
//      p *N1
//   }
//
// To handle such cases, the parser generates a fixup record (below) and
// delays setting of N1's underlying type until parsing is complete, at
// which point fixups are applied.

type fixupRecord struct {
	toUpdate *types.Named // type to modify when fixup is processed
	target   types.Type   // type that was incomplete when fixup was created
}

func ( *parser) ( string,  io.Reader,  map[string]*types.Package) {
	.scanner = new(scanner.Scanner)
	.initScanner(, )
	.imports = 
	.aliases = make(map[int]string)
	.typeList = make([]types.Type, 1 /* type numbers start at 1 */, 16)
}

func ( *parser) ( string,  io.Reader) {
	.scanner.Init()
	.scanner.Error = func( *scanner.Scanner,  string) { .error() }
	.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings
	.scanner.Whitespace = 1<<'\t' | 1<<' '
	.scanner.Filename =  // for good error messages
	.next()
}

type importError struct {
	pos scanner.Position
	err error
}

func ( importError) () string {
	return fmt.Sprintf("import error %s (byte offset = %d): %s", .pos, .pos.Offset, .err)
}

func ( *parser) ( any) {
	if ,  := .(string);  {
		 = errors.New()
	}
	// panic with a runtime.Error if err is not an error
	panic(importError{.scanner.Pos(), .(error)})
}

func ( *parser) ( string,  ...any) {
	.error(fmt.Errorf(, ...))
}

func ( *parser) ( rune) string {
	 := .lit
	if .tok !=  {
		.errorf("expected %s, got %s (%s)", scanner.TokenString(), scanner.TokenString(.tok), )
	}
	.next()
	return 
}

func ( *parser) () {
	if .version == "v1" || .version == "v2" {
		.expect(';')
	}
	.expect('\n')
}

func ( *parser) ( string) {
	 := .expect(scanner.Ident)
	if  !=  {
		.errorf("expected keyword %s, got %q", , )
	}
}

func ( *parser) () string {
	,  := strconv.Unquote(.expect(scanner.String))
	if  != nil {
		.error()
	}
	return 
}

// unquotedString     = { unquotedStringChar } .
// unquotedStringChar = <neither a whitespace nor a ';' char> .
func ( *parser) () string {
	if .tok == scanner.EOF {
		.error("unexpected EOF")
	}
	var  strings.Builder
	.WriteString(.scanner.TokenText())
	// This loop needs to examine each character before deciding whether to consume it. If we see a semicolon,
	// we need to let it be consumed by p.next().
	for  := .scanner.Peek();  != '\n' &&  != ';' &&  != scanner.EOF && .scanner.Whitespace&(1<<uint()) == 0;  = .scanner.Peek() {
		.WriteRune()
		.scanner.Next()
	}
	.next()
	return .String()
}

func ( *parser) () {
	.tok = .scanner.Scan()
	switch .tok {
	case scanner.Ident, scanner.Int, scanner.Float, scanner.String, 'ยท':
		.lit = .scanner.TokenText()
	default:
		.lit = ""
	}
}

func ( *parser) () (,  string) {
	return .parseQualifiedNameStr(.parseString())
}

func ( *parser) () (,  string) {
	return .parseQualifiedNameStr(.parseUnquotedString())
}

// qualifiedName = [ ["."] unquotedString "." ] unquotedString .
//
// The above production uses greedy matching.
func ( *parser) ( string) (,  string) {
	 := strings.Split(, ".")
	if [0] == "" {
		 = [1:]
	}

	switch len() {
	case 0:
		.errorf("malformed qualified name: %q", )
	case 1:
		// unqualified name
		 = .pkgpath
		 = [0]
	default:
		// qualified name, which may contain periods
		 = strings.Join([0:len()-1], ".")
		 = [len()-1]
	}

	return
}

// getPkg returns the package for a given path. If the package is
// not found but we have a package name, create the package and
// add it to the p.imports map.
func ( *parser) (,  string) *types.Package {
	// package unsafe is not in the imports map - handle explicitly
	if  == "unsafe" {
		return types.Unsafe
	}
	 := .imports[]
	if  == nil &&  != "" {
		 = types.NewPackage(, )
		.imports[] = 
	}
	return 
}

// parseExportedName is like parseQualifiedName, but
// the package path is resolved to an imported *types.Package.
//
// ExportedName = string [string] .
func ( *parser) () ( *types.Package,  string) {
	,  := .parseQualifiedName()
	var  string
	if .tok == scanner.String {
		 = .parseString()
	}
	 = .getPkg(, )
	if  == nil {
		.errorf("package %s (path = %q) not found", , )
	}
	return
}

// Name = QualifiedName | "?" .
func ( *parser) () string {
	if .tok == '?' {
		// Anonymous.
		.next()
		return ""
	}
	// The package path is redundant for us. Don't try to parse it.
	,  := .parseUnquotedQualifiedName()
	return 
}

func deref( types.Type) types.Type {
	if ,  := .(*types.Pointer);  != nil {
		 = .Elem()
	}
	return 
}

// Field = Name Type [string] .
func ( *parser) ( *types.Package) ( *types.Var,  string) {
	 := .parseName()
	,  := .parseTypeExtended()
	 := false
	if  == "" {
		 = true
		// Alias?
		if ,  := .aliases[];  {
			 = 
		} else {
			switch typ := deref().(type) {
			case *types.Basic:
				 = .Name()
			case *types.Named:
				 = .Obj().Name()
			default:
				.error("embedded field expected")
			}
		}
	}
	 = types.NewField(token.NoPos, , , , )
	if .tok == scanner.String {
		 = .parseString()
	}
	return
}

// Param = Name ["..."] Type .
func ( *parser) ( *types.Package) ( *types.Var,  bool) {
	 := .parseName()
	// Ignore names invented for inlinable functions.
	if strings.HasPrefix(, "p.") || strings.HasPrefix(, "r.") || strings.HasPrefix(, "$ret") {
		 = ""
	}
	if .tok == '<' && .scanner.Peek() == 'e' {
		// EscInfo = "<esc:" int ">" . (optional and ignored)
		.next()
		.expectKeyword("esc")
		.expect(':')
		.expect(scanner.Int)
		.expect('>')
	}
	if .tok == '.' {
		.next()
		.expect('.')
		.expect('.')
		 = true
	}
	 := .parseType()
	if  {
		 = types.NewSlice()
	}
	 = types.NewParam(token.NoPos, , , )
	return
}

// Var = Name Type .
func ( *parser) ( *types.Package) *types.Var {
	 := .parseName()
	 := types.NewVar(token.NoPos, , , .parseType())
	if [0] == '.' || [0] == '<' {
		// This is an unexported variable,
		// or a variable defined in a different package.
		// We only want to record exported variables.
		return nil
	}
	return 
}

// Conversion = "convert" "(" Type "," ConstValue ")" .
func ( *parser) ( *types.Package) ( constant.Value,  types.Type) {
	.expectKeyword("convert")
	.expect('(')
	 = .parseType()
	.expect(',')
	, _ = .parseConstValue()
	.expect(')')
	return
}

// ConstValue     = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) | Conversion .
// FloatOrComplex = float ["i" | ("+"|"-") float "i"] .
func ( *parser) ( *types.Package) ( constant.Value,  types.Type) {
	// v3 changed to $false, $true, $convert, to avoid confusion
	// with variable names in inline function bodies.
	if .tok == '$' {
		.next()
		if .tok != scanner.Ident {
			.errorf("expected identifier after '$', got %s (%q)", scanner.TokenString(.tok), .lit)
		}
	}

	switch .tok {
	case scanner.String:
		 := .parseString()
		 = constant.MakeString()
		 = types.Typ[types.UntypedString]
		return

	case scanner.Ident:
		 := false
		switch .lit {
		case "false":
		case "true":
			 = true

		case "convert":
			return .parseConversion()

		default:
			.errorf("expected const value, got %s (%q)", scanner.TokenString(.tok), .lit)
		}

		.next()
		 = constant.MakeBool()
		 = types.Typ[types.UntypedBool]
		return
	}

	 := ""
	if .tok == '-' {
		.next()
		 = "-"
	}

	switch .tok {
	case scanner.Int:
		 = constant.MakeFromLiteral(+.lit, token.INT, 0)
		if  == nil {
			.error("could not parse integer literal")
		}

		.next()
		if .tok == '\'' {
			.next()
			 = types.Typ[types.UntypedRune]
		} else {
			 = types.Typ[types.UntypedInt]
		}

	case scanner.Float:
		 :=  + .lit
		.next()

		var  string
		switch .tok {
		case '+':
			.next()
			 = .expect(scanner.Float)

		case '-':
			.next()
			 = "-" + .expect(scanner.Float)

		case scanner.Ident:
			// re is in fact the imaginary component. Expect "i" below.
			 = 
			 = "0"

		default:
			 = constant.MakeFromLiteral(, token.FLOAT, 0)
			if  == nil {
				.error("could not parse float literal")
			}
			 = types.Typ[types.UntypedFloat]
			return
		}

		.expectKeyword("i")
		 := constant.MakeFromLiteral(, token.FLOAT, 0)
		if  == nil {
			.error("could not parse real component of complex literal")
		}
		 := constant.MakeFromLiteral(+"i", token.IMAG, 0)
		if  == nil {
			.error("could not parse imag component of complex literal")
		}
		 = constant.BinaryOp(, token.ADD, )
		 = types.Typ[types.UntypedComplex]

	default:
		.errorf("expected const value, got %s (%q)", scanner.TokenString(.tok), .lit)
	}

	return
}

// Const = Name [Type] "=" ConstValue .
func ( *parser) ( *types.Package) *types.Const {
	 := .parseName()
	var  types.Type
	if .tok == '<' {
		 = .parseType()
	}
	.expect('=')
	,  := .parseConstValue()
	if  == nil {
		 = 
	}
	return types.NewConst(token.NoPos, , , , )
}

// reserved is a singleton type used to fill type map slots that have
// been reserved (i.e., for which a type number has been parsed) but
// which don't have their actual type yet. When the type map is updated,
// the actual type must replace a reserved entry (or we have an internal
// error). Used for self-verification only - not required for correctness.
var reserved = new(struct{ types.Type })

// reserve reserves the type map entry n for future use.
func ( *parser) ( int) {
	// Notes:
	// - for pre-V3 export data, the type numbers we see are
	//   guaranteed to be in increasing order, so we append a
	//   reserved entry onto the list.
	// - for V3+ export data, type numbers can appear in
	//   any order, however the 'types' section tells us the
	//   total number of types, hence typeList is pre-allocated.
	if len(.typeData) == 0 {
		if  != len(.typeList) {
			.errorf("invalid type number %d (out of sync)", )
		}
		.typeList = append(.typeList, reserved)
	} else {
		if .typeList[] != nil {
			.errorf("previously visited type number %d", )
		}
		.typeList[] = reserved
	}
}

// update sets the type map entries for the entries in nlist to t.
// An entry in nlist can be a type number in p.typeList,
// used to resolve named types, or it can be a *types.Pointer,
// used to resolve pointers to named types in case they are referenced
// by embedded fields.
func ( *parser) ( types.Type,  []any) {
	if  == reserved {
		.errorf("internal error: update(%v) invoked on reserved", )
	}
	if  == nil {
		.errorf("internal error: update(%v) invoked on nil", )
	}
	for ,  := range  {
		switch n := .(type) {
		case int:
			if .typeList[] ==  {
				continue
			}
			if .typeList[] != reserved {
				.errorf("internal error: update(%v): %d not reserved", , )
			}
			.typeList[] = 
		case *types.Pointer:
			if * != (types.Pointer{}) {
				 := .Elem()
				if  ==  {
					continue
				}
				.errorf("internal error: update: pointer already set to %v, expected %v", , )
			}
			* = *types.NewPointer()
		default:
			.errorf("internal error: %T on nlist", )
		}
	}
}

// NamedType = TypeName [ "=" ] Type { Method } .
// TypeName  = ExportedName .
// Method    = "func" "(" Param ")" Name ParamList ResultList [InlineBody] ";" .
func ( *parser) ( []any) types.Type {
	,  := .parseExportedName()
	 := .Scope()
	 := .Lookup()
	if  != nil && .Type() == nil {
		.errorf("%v has nil type", )
	}

	if .tok == scanner.Ident && .lit == "notinheap" {
		.next()
		// The go/types package has no way of recording that
		// this type is marked notinheap. Presumably no user
		// of this package actually cares.
	}

	// type alias
	if .tok == '=' {
		.next()
		.aliases[[len()-1].(int)] = 
		if  != nil {
			// use the previously imported (canonical) type
			 := .Type()
			.update(, )
			.parseType() // discard
			return 
		}
		 := .parseType(, ...)
		 = types.NewTypeName(token.NoPos, , , )
		.Insert()
		return 
	}

	// defined type
	if  == nil {
		// A named type may be referred to before the underlying type
		// is known - set it up.
		 := types.NewTypeName(token.NoPos, , , nil)
		types.NewNamed(, nil, nil)
		.Insert()
		 = 
	}

	// use the previously imported (canonical), or newly created type
	 := .Type()
	.update(, )

	,  := .(*types.Named)
	if ! {
		// This can happen for unsafe.Pointer, which is a TypeName holding a Basic type.
		 := .parseType()
		if  !=  {
			.error("unexpected underlying type for non-named TypeName")
		}
		return 
	}

	 := .parseType()
	if .Underlying() == nil {
		if .Underlying() == nil {
			 := fixupRecord{toUpdate: , target: }
			.fixups = append(.fixups, )
		} else {
			.SetUnderlying(.Underlying())
		}
	}

	if .tok == '\n' {
		.next()
		// collect associated methods
		for .tok == scanner.Ident {
			.expectKeyword("func")
			if .tok == '/' {
				// Skip a /*nointerface*/ or /*asm ID */ comment.
				.expect('/')
				.expect('*')
				if .expect(scanner.Ident) == "asm" {
					.parseUnquotedString()
				}
				.expect('*')
				.expect('/')
			}
			.expect('(')
			,  := .parseParam()
			.expect(')')
			 := .parseName()
			,  := .parseParamList()
			 := .parseResultList()
			.skipInlineBody()
			.expectEOL()

			 := types.NewSignatureType(, nil, nil, , , )
			.AddMethod(types.NewFunc(token.NoPos, , , ))
		}
	}

	return 
}

func ( *parser) () int64 {
	 := .expect(scanner.Int)
	,  := strconv.ParseInt(, 10, 64)
	if  != nil {
		.error()
	}
	return 
}

func ( *parser) () int {
	 := .expect(scanner.Int)
	,  := strconv.ParseInt(, 10, 0 /* int */)
	if  != nil {
		.error()
	}
	return int()
}

// ArrayOrSliceType = "[" [ int ] "]" Type .
func ( *parser) ( *types.Package,  []any) types.Type {
	.expect('[')
	if .tok == ']' {
		.next()

		 := new(types.Slice)
		.update(, )

		* = *types.NewSlice(.parseType())
		return 
	}

	 := new(types.Array)
	.update(, )

	 := .parseInt64()
	.expect(']')

	* = *types.NewArray(.parseType(), )
	return 
}

// MapType = "map" "[" Type "]" Type .
func ( *parser) ( *types.Package,  []any) types.Type {
	.expectKeyword("map")

	 := new(types.Map)
	.update(, )

	.expect('[')
	 := .parseType()
	.expect(']')
	 := .parseType()

	* = *types.NewMap(, )
	return 
}

// ChanType = "chan" ["<-" | "-<"] Type .
func ( *parser) ( *types.Package,  []any) types.Type {
	.expectKeyword("chan")

	 := new(types.Chan)
	.update(, )

	 := types.SendRecv
	switch .tok {
	case '-':
		.next()
		.expect('<')
		 = types.SendOnly

	case '<':
		// don't consume '<' if it belongs to Type
		if .scanner.Peek() == '-' {
			.next()
			.expect('-')
			 = types.RecvOnly
		}
	}

	* = *types.NewChan(, .parseType())
	return 
}

// StructType = "struct" "{" { Field } "}" .
func ( *parser) ( *types.Package,  []any) types.Type {
	.expectKeyword("struct")

	 := new(types.Struct)
	.update(, )

	var  []*types.Var
	var  []string

	.expect('{')
	for .tok != '}' && .tok != scanner.EOF {
		,  := .parseField()
		.expect(';')
		 = append(, )
		 = append(, )
	}
	.expect('}')

	* = *types.NewStruct(, )
	return 
}

// ParamList = "(" [ { Parameter "," } Parameter ] ")" .
func ( *parser) ( *types.Package) (*types.Tuple, bool) {
	var  []*types.Var
	 := false

	.expect('(')
	for .tok != ')' && .tok != scanner.EOF {
		if len() > 0 {
			.expect(',')
		}
		,  := .parseParam()
		 = append(, )
		if  {
			if  {
				.error("... not on final argument")
			}
			 = true
		}
	}
	.expect(')')

	return types.NewTuple(...), 
}

// ResultList = Type | ParamList .
func ( *parser) ( *types.Package) *types.Tuple {
	switch .tok {
	case '<':
		.next()
		if .tok == scanner.Ident && .lit == "inl" {
			return nil
		}
		,  := .parseTypeAfterAngle()
		return types.NewTuple(types.NewParam(token.NoPos, , "", ))

	case '(':
		,  := .parseParamList()
		return 

	default:
		return nil
	}
}

// FunctionType = ParamList ResultList .
func ( *parser) ( *types.Package,  []any) *types.Signature {
	 := new(types.Signature)
	.update(, )

	,  := .parseParamList()
	 := .parseResultList()

	* = *types.NewSignatureType(nil, nil, nil, , , )
	return 
}

// Func = Name FunctionType [InlineBody] .
func ( *parser) ( *types.Package) *types.Func {
	if .tok == '/' {
		// Skip an /*asm ID */ comment.
		.expect('/')
		.expect('*')
		if .expect(scanner.Ident) == "asm" {
			.parseUnquotedString()
		}
		.expect('*')
		.expect('/')
	}

	 := .parseName()
	 := types.NewFunc(token.NoPos, , , .parseFunctionType(, nil))
	.skipInlineBody()

	if [0] == '.' || [0] == '<' || strings.ContainsRune(, '$') {
		// This is an unexported function,
		// or a function defined in a different package,
		// or a type$equal or type$hash function.
		// We only want to record exported functions.
		return nil
	}

	return 
}

// InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" .
func ( *parser) ( *types.Package,  []any) types.Type {
	.expectKeyword("interface")

	 := new(types.Interface)
	.update(, )

	var  []*types.Func
	var  []types.Type

	.expect('{')
	for .tok != '}' && .tok != scanner.EOF {
		if .tok == '?' {
			.next()
			 = append(, .parseType())
		} else {
			 := .parseFunc()
			if  != nil {
				 = append(, )
			}
		}
		.expect(';')
	}
	.expect('}')

	* = *types.NewInterfaceType(, )
	return 
}

// PointerType = "*" ("any" | Type) .
func ( *parser) ( *types.Package,  []any) types.Type {
	.expect('*')
	if .tok == scanner.Ident {
		.expectKeyword("any")
		 := types.Typ[types.UnsafePointer]
		.update(, )
		return 
	}

	 := new(types.Pointer)
	.update(, )

	* = *types.NewPointer(.parseType(, ))

	return 
}

// TypeSpec = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType .
func ( *parser) ( *types.Package,  []any) types.Type {
	switch .tok {
	case scanner.String:
		return .parseNamedType()

	case scanner.Ident:
		switch .lit {
		case "map":
			return .parseMapType(, )

		case "chan":
			return .parseChanType(, )

		case "struct":
			return .parseStructType(, )

		case "interface":
			return .parseInterfaceType(, )
		}

	case '*':
		return .parsePointerType(, )

	case '[':
		return .parseArrayOrSliceType(, )

	case '(':
		return .parseFunctionType(, )
	}

	.errorf("expected type name or literal, got %s", scanner.TokenString(.tok))
	return nil
}

const (
	// From gofrontend/go/export.h
	// Note that these values are negative in the gofrontend and have been made positive
	// in the gccgoimporter.
	gccgoBuiltinINT8       = 1
	gccgoBuiltinINT16      = 2
	gccgoBuiltinINT32      = 3
	gccgoBuiltinINT64      = 4
	gccgoBuiltinUINT8      = 5
	gccgoBuiltinUINT16     = 6
	gccgoBuiltinUINT32     = 7
	gccgoBuiltinUINT64     = 8
	gccgoBuiltinFLOAT32    = 9
	gccgoBuiltinFLOAT64    = 10
	gccgoBuiltinINT        = 11
	gccgoBuiltinUINT       = 12
	gccgoBuiltinUINTPTR    = 13
	gccgoBuiltinBOOL       = 15
	gccgoBuiltinSTRING     = 16
	gccgoBuiltinCOMPLEX64  = 17
	gccgoBuiltinCOMPLEX128 = 18
	gccgoBuiltinERROR      = 19
	gccgoBuiltinBYTE       = 20
	gccgoBuiltinRUNE       = 21
	gccgoBuiltinANY        = 22
)

func lookupBuiltinType( int) types.Type {
	return [...]types.Type{
		gccgoBuiltinINT8:       types.Typ[types.Int8],
		gccgoBuiltinINT16:      types.Typ[types.Int16],
		gccgoBuiltinINT32:      types.Typ[types.Int32],
		gccgoBuiltinINT64:      types.Typ[types.Int64],
		gccgoBuiltinUINT8:      types.Typ[types.Uint8],
		gccgoBuiltinUINT16:     types.Typ[types.Uint16],
		gccgoBuiltinUINT32:     types.Typ[types.Uint32],
		gccgoBuiltinUINT64:     types.Typ[types.Uint64],
		gccgoBuiltinFLOAT32:    types.Typ[types.Float32],
		gccgoBuiltinFLOAT64:    types.Typ[types.Float64],
		gccgoBuiltinINT:        types.Typ[types.Int],
		gccgoBuiltinUINT:       types.Typ[types.Uint],
		gccgoBuiltinUINTPTR:    types.Typ[types.Uintptr],
		gccgoBuiltinBOOL:       types.Typ[types.Bool],
		gccgoBuiltinSTRING:     types.Typ[types.String],
		gccgoBuiltinCOMPLEX64:  types.Typ[types.Complex64],
		gccgoBuiltinCOMPLEX128: types.Typ[types.Complex128],
		gccgoBuiltinERROR:      types.Universe.Lookup("error").Type(),
		gccgoBuiltinBYTE:       types.Universe.Lookup("byte").Type(),
		gccgoBuiltinRUNE:       types.Universe.Lookup("rune").Type(),
		gccgoBuiltinANY:        types.Universe.Lookup("any").Type(),
	}[]
}

// Type = "<" "type" ( "-" int | int [ TypeSpec ] ) ">" .
//
// parseType updates the type map to t for all type numbers n.
func ( *parser) ( *types.Package,  ...any) types.Type {
	.expect('<')
	,  := .parseTypeAfterAngle(, ...)
	return 
}

// (*parser).Type after reading the "<".
func ( *parser) ( *types.Package,  ...any) ( types.Type,  int) {
	.expectKeyword("type")

	 = 0
	switch .tok {
	case scanner.Int:
		 = .parseInt()
		if .tok == '>' {
			if len(.typeData) > 0 && .typeList[] == nil {
				.parseSavedType(, , )
			}
			 = .typeList[]
			if len(.typeData) == 0 &&  == reserved {
				.errorf("invalid type cycle, type %d not yet defined (nlist=%v)", , )
			}
			.update(, )
		} else {
			.reserve()
			 = .parseTypeSpec(, append(, ))
		}

	case '-':
		.next()
		 := .parseInt()
		 = lookupBuiltinType()
		.update(, )

	default:
		.errorf("expected type number, got %s (%q)", scanner.TokenString(.tok), .lit)
		return nil, 0
	}

	if  == nil ||  == reserved {
		.errorf("internal error: bad return from parseType(%v)", )
	}

	.expect('>')
	return
}

// parseTypeExtended is identical to parseType, but if the type in
// question is a saved type, returns the index as well as the type
// pointer (index returned is zero if we parsed a builtin).
func ( *parser) ( *types.Package,  ...any) ( types.Type,  int) {
	.expect('<')
	,  = .parseTypeAfterAngle(, ...)
	return
}

// InlineBody = "<inl:NN>" .{NN}
// Reports whether a body was skipped.
func ( *parser) () {
	// We may or may not have seen the '<' already, depending on
	// whether the function had a result type or not.
	if .tok == '<' {
		.next()
		.expectKeyword("inl")
	} else if .tok != scanner.Ident || .lit != "inl" {
		return
	} else {
		.next()
	}

	.expect(':')
	 := .parseInt()
	.expect('>')

	defer func( uint64) {
		.scanner.Whitespace = 
	}(.scanner.Whitespace)
	.scanner.Whitespace = 0

	 := 0
	for  <  {
		 := .scanner.Next()
		if  == scanner.EOF {
			.error("unexpected EOF")
		}
		 += utf8.RuneLen()
	}
}

// Types = "types" maxp1 exportedp1 (offset length)* .
func ( *parser) ( *types.Package) {
	 := .parseInt()
	 := .parseInt()
	.typeList = make([]types.Type, , )

	type  struct {
		 int
		 int
	}
	var  []

	 := 0
	for  := 1;  < ; ++ {
		 := .parseInt()
		 = append(, {, })
		 += 
	}

	defer func( uint64) {
		.scanner.Whitespace = 
	}(.scanner.Whitespace)
	.scanner.Whitespace = 0

	// We should now have p.tok pointing to the final newline.
	// The next runes from the scanner should be the type data.

	var  strings.Builder
	for .Len() <  {
		 := .scanner.Next()
		if  == scanner.EOF {
			.error("unexpected EOF")
		}
		.WriteRune()
	}
	 := .String()

	.typeData = []string{""} // type 0, unused
	for ,  := range  {
		.typeData = append(.typeData, [.:.+.])
	}

	for  := 1;  < ; ++ {
		.parseSavedType(, , nil)
	}
}

// parseSavedType parses one saved type definition.
func ( *parser) ( *types.Package,  int,  []any) {
	defer func( *scanner.Scanner,  rune,  string) {
		.scanner = 
		.tok = 
		.lit = 
	}(.scanner, .tok, .lit)

	.scanner = new(scanner.Scanner)
	.initScanner(.scanner.Filename, strings.NewReader(.typeData[]))
	.expectKeyword("type")
	 := .parseInt()
	if  !=  {
		.errorf("type ID mismatch: got %d, want %d", , )
	}
	if .typeList[] == reserved {
		.errorf("internal error: %d already reserved in parseSavedType", )
	}
	if .typeList[] == nil {
		.reserve()
		.parseTypeSpec(, append(, ))
	}
	if .typeList[] == nil || .typeList[] == reserved {
		.errorf("internal error: parseSavedType(%d,%v) reserved/nil", , )
	}
}

// PackageInit = unquotedString unquotedString int .
func ( *parser) () PackageInit {
	 := .parseUnquotedString()
	 := .parseUnquotedString()
	 := -1
	if .version == "v1" {
		 = .parseInt()
	}
	return PackageInit{Name: , InitFunc: , Priority: }
}

// Create the package if we have parsed both the package path and package name.
func ( *parser) () {
	if .pkgname != "" && .pkgpath != "" {
		.pkg = .getPkg(.pkgpath, .pkgname)
	}
}

// InitDataDirective = ( "v1" | "v2" | "v3" ) ";" |
//
//	"priority" int ";" |
//	"init" { PackageInit } ";" |
//	"checksum" unquotedString ";" .
func ( *parser) () {
	if .tok != scanner.Ident {
		// unexpected token kind; panic
		.expect(scanner.Ident)
	}

	switch .lit {
	case "v1", "v2", "v3":
		.version = .lit
		.next()
		.expect(';')
		.expect('\n')

	case "priority":
		.next()
		.initdata.Priority = .parseInt()
		.expectEOL()

	case "init":
		.next()
		for .tok != '\n' && .tok != ';' && .tok != scanner.EOF {
			.initdata.Inits = append(.initdata.Inits, .parsePackageInit())
		}
		.expectEOL()

	case "init_graph":
		.next()
		// The graph data is thrown away for now.
		for .tok != '\n' && .tok != ';' && .tok != scanner.EOF {
			.parseInt64()
			.parseInt64()
		}
		.expectEOL()

	case "checksum":
		// Don't let the scanner try to parse the checksum as a number.
		defer func( uint) {
			.scanner.Mode = 
		}(.scanner.Mode)
		.scanner.Mode &^= scanner.ScanInts | scanner.ScanFloats
		.next()
		.parseUnquotedString()
		.expectEOL()

	default:
		.errorf("unexpected identifier: %q", .lit)
	}
}

// Directive = InitDataDirective |
//
//	"package" unquotedString [ unquotedString ] [ unquotedString ] ";" |
//	"pkgpath" unquotedString ";" |
//	"prefix" unquotedString ";" |
//	"import" unquotedString unquotedString string ";" |
//	"indirectimport" unquotedString unquotedstring ";" |
//	"func" Func ";" |
//	"type" Type ";" |
//	"var" Var ";" |
//	"const" Const ";" .
func ( *parser) () {
	if .tok != scanner.Ident {
		// unexpected token kind; panic
		.expect(scanner.Ident)
	}

	switch .lit {
	case "v1", "v2", "v3", "priority", "init", "init_graph", "checksum":
		.parseInitDataDirective()

	case "package":
		.next()
		.pkgname = .parseUnquotedString()
		.maybeCreatePackage()
		if .version != "v1" && .tok != '\n' && .tok != ';' {
			.parseUnquotedString()
			.parseUnquotedString()
		}
		.expectEOL()

	case "pkgpath":
		.next()
		.pkgpath = .parseUnquotedString()
		.maybeCreatePackage()
		.expectEOL()

	case "prefix":
		.next()
		.pkgpath = .parseUnquotedString()
		.expectEOL()

	case "import":
		.next()
		 := .parseUnquotedString()
		 := .parseUnquotedString()
		.getPkg(, )
		.parseString()
		.expectEOL()

	case "indirectimport":
		.next()
		 := .parseUnquotedString()
		 := .parseUnquotedString()
		.getPkg(, )
		.expectEOL()

	case "types":
		.next()
		.parseTypes(.pkg)
		.expectEOL()

	case "func":
		.next()
		 := .parseFunc(.pkg)
		if  != nil {
			.pkg.Scope().Insert()
		}
		.expectEOL()

	case "type":
		.next()
		.parseType(.pkg)
		.expectEOL()

	case "var":
		.next()
		 := .parseVar(.pkg)
		if  != nil {
			.pkg.Scope().Insert()
		}
		.expectEOL()

	case "const":
		.next()
		 := .parseConst(.pkg)
		.pkg.Scope().Insert()
		.expectEOL()

	default:
		.errorf("unexpected identifier: %q", .lit)
	}
}

// Package = { Directive } .
func ( *parser) () *types.Package {
	for .tok != scanner.EOF {
		.parseDirective()
	}
	for ,  := range .fixups {
		if .target.Underlying() == nil {
			.errorf("internal error: fixup can't be applied, loop required")
		}
		.toUpdate.SetUnderlying(.target.Underlying())
	}
	.fixups = nil
	for ,  := range .typeList {
		if ,  := .(*types.Interface);  {
			.Complete()
		}
	}
	.pkg.MarkComplete()
	return .pkg
}