diff options
Diffstat (limited to 'libgo/go')
-rw-r--r-- | libgo/go/go/internal/gccgoimporter/parser.go | 63 |
1 files changed, 57 insertions, 6 deletions
diff --git a/libgo/go/go/internal/gccgoimporter/parser.go b/libgo/go/go/internal/gccgoimporter/parser.go index dc61e4c..c23002f 100644 --- a/libgo/go/go/internal/gccgoimporter/parser.go +++ b/libgo/go/go/internal/gccgoimporter/parser.go @@ -15,6 +15,7 @@ import ( "strconv" "strings" "text/scanner" + "unicode/utf8" ) type parser struct { @@ -41,7 +42,7 @@ func (p *parser) init(filename string, src io.Reader, imports map[string]*types. func (p *parser) initScanner(filename string, src io.Reader) { p.scanner.Init(src) p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) } - p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments + p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings p.scanner.Whitespace = 1<<'\t' | 1<<' ' p.scanner.Filename = filename // for good error messages p.next() @@ -393,7 +394,7 @@ func (p *parser) parseConst(pkg *types.Package) *types.Const { // NamedType = TypeName [ "=" ] Type { Method } . // TypeName = ExportedName . -// Method = "func" "(" Param ")" Name ParamList ResultList ";" . +// Method = "func" "(" Param ")" Name ParamList ResultList [InlineBody] ";" . func (p *parser) parseNamedType(n int) types.Type { pkg, name := p.parseExportedName() scope := pkg.Scope() @@ -455,6 +456,7 @@ func (p *parser) parseNamedType(n int) types.Type { name := p.parseName() params, isVariadic := p.parseParamList(pkg) results := p.parseResultList(pkg) + p.skipInlineBody() p.expectEOL() sig := types.NewSignature(receiver, params, results, isVariadic) @@ -566,7 +568,11 @@ func (p *parser) parseParamList(pkg *types.Package) (*types.Tuple, bool) { func (p *parser) parseResultList(pkg *types.Package) *types.Tuple { switch p.tok { case '<': - return types.NewTuple(types.NewParam(token.NoPos, pkg, "", p.parseType(pkg))) + p.next() + if p.tok == scanner.Ident && p.lit == "inl" { + return nil + } + return types.NewTuple(types.NewParam(token.NoPos, pkg, "", p.parseTypeAfterAngle(pkg))) case '(': params, _ := p.parseParamList(pkg) @@ -584,7 +590,7 @@ func (p *parser) parseFunctionType(pkg *types.Package) *types.Signature { return types.NewSignature(nil, params, results, isVariadic) } -// Func = Name FunctionType . +// Func = Name FunctionType [InlineBody] . func (p *parser) parseFunc(pkg *types.Package) *types.Func { name := p.parseName() if strings.ContainsRune(name, '$') { @@ -593,7 +599,9 @@ func (p *parser) parseFunc(pkg *types.Package) *types.Func { p.discardDirectiveWhileParsingTypes(pkg) return nil } - return types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg)) + f := types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg)) + p.skipInlineBody() + return f } // InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" . @@ -717,8 +725,13 @@ func lookupBuiltinType(typ int) types.Type { } // Type = "<" "type" ( "-" int | int [ TypeDefinition ] ) ">" . -func (p *parser) parseType(pkg *types.Package) (t types.Type) { +func (p *parser) parseType(pkg *types.Package) types.Type { p.expect('<') + return p.parseTypeAfterAngle(pkg) +} + +// (*parser).Type after reading the "<". +func (p *parser) parseTypeAfterAngle(pkg *types.Package) (t types.Type) { p.expectKeyword("type") switch p.tok { @@ -748,6 +761,39 @@ func (p *parser) parseType(pkg *types.Package) (t types.Type) { return } +// InlineBody = "<inl:NN>" .{NN} +// Reports whether a body was skipped. +func (p *parser) skipInlineBody() { + // We may or may not have seen the '<' already, depending on + // whether the function had a result type or not. + if p.tok == '<' { + p.next() + p.expectKeyword("inl") + } else if p.tok != scanner.Ident || p.lit != "inl" { + return + } else { + p.next() + } + + p.expect(':') + want := p.parseInt() + p.expect('>') + + defer func(w uint64) { + p.scanner.Whitespace = w + }(p.scanner.Whitespace) + p.scanner.Whitespace = 0 + + got := int64(0) + for got < want { + r := p.scanner.Next() + if r == scanner.EOF { + p.error("unexpected EOF") + } + got += int64(utf8.RuneLen(r)) + } +} + // Types = "types" maxp1 exportedp1 (offset length)* . func (p *parser) parseTypes(pkg *types.Package) { maxp1 := p.parseInt() @@ -766,6 +812,11 @@ func (p *parser) parseTypes(pkg *types.Package) { total += len } + defer func(w uint64) { + p.scanner.Whitespace = w + }(p.scanner.Whitespace) + p.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. |