OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [exp/] [types/] [gcimporter.go] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2011 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
// This file implements an ast.Importer for gc generated object files.
6
// TODO(gri) Eventually move this into a separate package outside types.
7
 
8
package types
9
 
10
import (
11
        "errors"
12
        "fmt"
13
        "go/ast"
14
        "go/token"
15
        "io"
16
        "math/big"
17
        "os"
18
        "path/filepath"
19
        "runtime"
20
        "strconv"
21
        "text/scanner"
22
)
23
 
24
const trace = false // set to true for debugging
25
 
26
var (
27
        pkgRoot = filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH)
28
        pkgExts = [...]string{".a", ".5", ".6", ".8"}
29
)
30
 
31
// findPkg returns the filename and package id for an import path.
32
// If no file was found, an empty filename is returned.
33
func findPkg(path string) (filename, id string) {
34
        if len(path) == 0 {
35
                return
36
        }
37
 
38
        id = path
39
        var noext string
40
        switch path[0] {
41
        default:
42
                // "x" -> "$GOROOT/pkg/$GOOS_$GOARCH/x.ext", "x"
43
                noext = filepath.Join(pkgRoot, path)
44
 
45
        case '.':
46
                // "./x" -> "/this/directory/x.ext", "/this/directory/x"
47
                cwd, err := os.Getwd()
48
                if err != nil {
49
                        return
50
                }
51
                noext = filepath.Join(cwd, path)
52
                id = noext
53
 
54
        case '/':
55
                // "/x" -> "/x.ext", "/x"
56
                noext = path
57
        }
58
 
59
        // try extensions
60
        for _, ext := range pkgExts {
61
                filename = noext + ext
62
                if f, err := os.Stat(filename); err == nil && !f.IsDir() {
63
                        return
64
                }
65
        }
66
 
67
        filename = "" // not found
68
        return
69
}
70
 
71
// gcParser parses the exports inside a gc compiler-produced
72
// object/archive file and populates its scope with the results.
73
type gcParser struct {
74
        scanner scanner.Scanner
75
        tok     rune                   // current token
76
        lit     string                 // literal string; only valid for Ident, Int, String tokens
77
        id      string                 // package id of imported package
78
        imports map[string]*ast.Object // package id -> package object
79
}
80
 
81
func (p *gcParser) init(filename, id string, src io.Reader, imports map[string]*ast.Object) {
82
        p.scanner.Init(src)
83
        p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
84
        p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
85
        p.scanner.Whitespace = 1<<'\t' | 1<<' '
86
        p.scanner.Filename = filename // for good error messages
87
        p.next()
88
        p.id = id
89
        p.imports = imports
90
}
91
 
92
func (p *gcParser) next() {
93
        p.tok = p.scanner.Scan()
94
        switch p.tok {
95
        case scanner.Ident, scanner.Int, scanner.String:
96
                p.lit = p.scanner.TokenText()
97
        default:
98
                p.lit = ""
99
        }
100
        if trace {
101
                fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit)
102
        }
103
}
104
 
105
// GcImporter implements the ast.Importer signature.
106
func GcImporter(imports map[string]*ast.Object, path string) (pkg *ast.Object, err error) {
107
        if path == "unsafe" {
108
                return Unsafe, nil
109
        }
110
 
111
        defer func() {
112
                if r := recover(); r != nil {
113
                        err = r.(importError) // will re-panic if r is not an importError
114
                        if trace {
115
                                panic(err) // force a stack trace
116
                        }
117
                }
118
        }()
119
 
120
        filename, id := findPkg(path)
121
        if filename == "" {
122
                err = errors.New("can't find import: " + id)
123
                return
124
        }
125
 
126
        if pkg = imports[id]; pkg != nil {
127
                return // package was imported before
128
        }
129
 
130
        buf, err := ExportData(filename)
131
        if err != nil {
132
                return
133
        }
134
        defer buf.Close()
135
 
136
        if trace {
137
                fmt.Printf("importing %s (%s)\n", id, filename)
138
        }
139
 
140
        var p gcParser
141
        p.init(filename, id, buf, imports)
142
        pkg = p.parseExport()
143
        return
144
}
145
 
146
// Declare inserts a named object of the given kind in scope.
147
func (p *gcParser) declare(scope *ast.Scope, kind ast.ObjKind, name string) *ast.Object {
148
        // the object may have been imported before - if it exists
149
        // already in the respective package scope, return that object
150
        if obj := scope.Lookup(name); obj != nil {
151
                assert(obj.Kind == kind)
152
                return obj
153
        }
154
 
155
        // otherwise create a new object and insert it into the package scope
156
        obj := ast.NewObj(kind, name)
157
        if scope.Insert(obj) != nil {
158
                p.errorf("already declared: %v %s", kind, obj.Name)
159
        }
160
 
161
        // a new type object is a named type and may be referred
162
        // to before the underlying type is known - set it up
163
        if kind == ast.Typ {
164
                obj.Type = &Name{Obj: obj}
165
        }
166
 
167
        return obj
168
}
169
 
170
// ----------------------------------------------------------------------------
171
// Error handling
172
 
173
// Internal errors are boxed as importErrors.
174
type importError struct {
175
        pos scanner.Position
176
        err error
177
}
178
 
179
func (e importError) Error() string {
180
        return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
181
}
182
 
183
func (p *gcParser) error(err interface{}) {
184
        if s, ok := err.(string); ok {
185
                err = errors.New(s)
186
        }
187
        // panic with a runtime.Error if err is not an error
188
        panic(importError{p.scanner.Pos(), err.(error)})
189
}
190
 
191
func (p *gcParser) errorf(format string, args ...interface{}) {
192
        p.error(fmt.Sprintf(format, args...))
193
}
194
 
195
func (p *gcParser) expect(tok rune) string {
196
        lit := p.lit
197
        if p.tok != tok {
198
                panic(1)
199
                p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
200
        }
201
        p.next()
202
        return lit
203
}
204
 
205
func (p *gcParser) expectSpecial(tok string) {
206
        sep := 'x' // not white space
207
        i := 0
208
        for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' {
209
                sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
210
                p.next()
211
                i++
212
        }
213
        if i < len(tok) {
214
                p.errorf("expected %q, got %q", tok, tok[0:i])
215
        }
216
}
217
 
218
func (p *gcParser) expectKeyword(keyword string) {
219
        lit := p.expect(scanner.Ident)
220
        if lit != keyword {
221
                p.errorf("expected keyword %s, got %q", keyword, lit)
222
        }
223
}
224
 
225
// ----------------------------------------------------------------------------
226
// Import declarations
227
 
228
// ImportPath = string_lit .
229
//
230
func (p *gcParser) parsePkgId() *ast.Object {
231
        id, err := strconv.Unquote(p.expect(scanner.String))
232
        if err != nil {
233
                p.error(err)
234
        }
235
 
236
        switch id {
237
        case "":
238
                // id == "" stands for the imported package id
239
                // (only known at time of package installation)
240
                id = p.id
241
        case "unsafe":
242
                // package unsafe is not in the imports map - handle explicitly
243
                return Unsafe
244
        }
245
 
246
        pkg := p.imports[id]
247
        if pkg == nil {
248
                scope = ast.NewScope(nil)
249
                pkg = ast.NewObj(ast.Pkg, "")
250
                pkg.Data = scope
251
                p.imports[id] = pkg
252
        }
253
 
254
        return pkg
255
}
256
 
257
// dotIdentifier = ( ident | '·' ) { ident | int | '·' } .
258
func (p *gcParser) parseDotIdent() string {
259
        ident := ""
260
        if p.tok != scanner.Int {
261
                sep := 'x' // not white space
262
                for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' {
263
                        ident += p.lit
264
                        sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
265
                        p.next()
266
                }
267
        }
268
        if ident == "" {
269
                p.expect(scanner.Ident) // use expect() for error handling
270
        }
271
        return ident
272
}
273
 
274
// ExportedName = "@" ImportPath "." dotIdentifier .
275
//
276
func (p *gcParser) parseExportedName() (*ast.Object, string) {
277
        p.expect('@')
278
        pkg := p.parsePkgId()
279
        p.expect('.')
280
        name := p.parseDotIdent()
281
        return pkg, name
282
}
283
 
284
// ----------------------------------------------------------------------------
285
// Types
286
 
287
// BasicType = identifier .
288
//
289
func (p *gcParser) parseBasicType() Type {
290
        id := p.expect(scanner.Ident)
291
        obj := Universe.Lookup(id)
292
        if obj == nil || obj.Kind != ast.Typ {
293
                p.errorf("not a basic type: %s", id)
294
        }
295
        return obj.Type.(Type)
296
}
297
 
298
// ArrayType = "[" int_lit "]" Type .
299
//
300
func (p *gcParser) parseArrayType() Type {
301
        // "[" already consumed and lookahead known not to be "]"
302
        lit := p.expect(scanner.Int)
303
        p.expect(']')
304
        elt := p.parseType()
305
        n, err := strconv.ParseUint(lit, 10, 64)
306
        if err != nil {
307
                p.error(err)
308
        }
309
        return &Array{Len: n, Elt: elt}
310
}
311
 
312
// MapType = "map" "[" Type "]" Type .
313
//
314
func (p *gcParser) parseMapType() Type {
315
        p.expectKeyword("map")
316
        p.expect('[')
317
        key := p.parseType()
318
        p.expect(']')
319
        elt := p.parseType()
320
        return &Map{Key: key, Elt: elt}
321
}
322
 
323
// Name = identifier | "?" | ExportedName  .
324
//
325
func (p *gcParser) parseName() (name string) {
326
        switch p.tok {
327
        case scanner.Ident:
328
                name = p.lit
329
                p.next()
330
        case '?':
331
                // anonymous
332
                p.next()
333
        case '@':
334
                // exported name prefixed with package path
335
                _, name = p.parseExportedName()
336
        default:
337
                p.error("name expected")
338
        }
339
        return
340
}
341
 
342
// Field = Name Type [ string_lit ] .
343
//
344
func (p *gcParser) parseField() (fld *ast.Object, tag string) {
345
        name := p.parseName()
346
        ftyp := p.parseType()
347
        if name == "" {
348
                // anonymous field - ftyp must be T or *T and T must be a type name
349
                if _, ok := Deref(ftyp).(*Name); !ok {
350
                        p.errorf("anonymous field expected")
351
                }
352
        }
353
        if p.tok == scanner.String {
354
                tag = p.expect(scanner.String)
355
        }
356
        fld = ast.NewObj(ast.Var, name)
357
        fld.Type = ftyp
358
        return
359
}
360
 
361
// StructType = "struct" "{" [ FieldList ] "}" .
362
// FieldList  = Field { ";" Field } .
363
//
364
func (p *gcParser) parseStructType() Type {
365
        var fields []*ast.Object
366
        var tags []string
367
 
368
        parseField := func() {
369
                fld, tag := p.parseField()
370
                fields = append(fields, fld)
371
                tags = append(tags, tag)
372
        }
373
 
374
        p.expectKeyword("struct")
375
        p.expect('{')
376
        if p.tok != '}' {
377
                parseField()
378
                for p.tok == ';' {
379
                        p.next()
380
                        parseField()
381
                }
382
        }
383
        p.expect('}')
384
 
385
        return &Struct{Fields: fields, Tags: tags}
386
}
387
 
388
// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] .
389
//
390
func (p *gcParser) parseParameter() (par *ast.Object, isVariadic bool) {
391
        name := p.parseName()
392
        if name == "" {
393
                name = "_" // cannot access unnamed identifiers
394
        }
395
        if p.tok == '.' {
396
                p.expectSpecial("...")
397
                isVariadic = true
398
        }
399
        ptyp := p.parseType()
400
        // ignore argument tag
401
        if p.tok == scanner.String {
402
                p.expect(scanner.String)
403
        }
404
        par = ast.NewObj(ast.Var, name)
405
        par.Type = ptyp
406
        return
407
}
408
 
409
// Parameters    = "(" [ ParameterList ] ")" .
410
// ParameterList = { Parameter "," } Parameter .
411
//
412
func (p *gcParser) parseParameters() (list []*ast.Object, isVariadic bool) {
413
        parseParameter := func() {
414
                par, variadic := p.parseParameter()
415
                list = append(list, par)
416
                if variadic {
417
                        if isVariadic {
418
                                p.error("... not on final argument")
419
                        }
420
                        isVariadic = true
421
                }
422
        }
423
 
424
        p.expect('(')
425
        if p.tok != ')' {
426
                parseParameter()
427
                for p.tok == ',' {
428
                        p.next()
429
                        parseParameter()
430
                }
431
        }
432
        p.expect(')')
433
 
434
        return
435
}
436
 
437
// Signature = Parameters [ Result ] .
438
// Result    = Type | Parameters .
439
//
440
func (p *gcParser) parseSignature() *Func {
441
        params, isVariadic := p.parseParameters()
442
 
443
        // optional result type
444
        var results []*ast.Object
445
        switch p.tok {
446
        case scanner.Ident, '[', '*', '<', '@':
447
                // single, unnamed result
448
                result := ast.NewObj(ast.Var, "_")
449
                result.Type = p.parseType()
450
                results = []*ast.Object{result}
451
        case '(':
452
                // named or multiple result(s)
453
                var variadic bool
454
                results, variadic = p.parseParameters()
455
                if variadic {
456
                        p.error("... not permitted on result type")
457
                }
458
        }
459
 
460
        return &Func{Params: params, Results: results, IsVariadic: isVariadic}
461
}
462
 
463
// MethodOrEmbedSpec = Name [ Signature ] .
464
//
465
func (p *gcParser) parseMethodOrEmbedSpec() *ast.Object {
466
        p.parseName()
467
        if p.tok == '(' {
468
                p.parseSignature()
469
                // TODO(gri) compute method object
470
                return ast.NewObj(ast.Fun, "_")
471
        }
472
        // TODO lookup name and return that type
473
        return ast.NewObj(ast.Typ, "_")
474
}
475
 
476
// InterfaceType = "interface" "{" [ MethodOrEmbedList ] "}" .
477
// MethodOrEmbedList = MethodOrEmbedSpec { ";" MethodOrEmbedSpec } .
478
//
479
func (p *gcParser) parseInterfaceType() Type {
480
        var methods ObjList
481
 
482
        parseMethod := func() {
483
                switch m := p.parseMethodOrEmbedSpec(); m.Kind {
484
                case ast.Typ:
485
                        // TODO expand embedded methods
486
                case ast.Fun:
487
                        methods = append(methods, m)
488
                }
489
        }
490
 
491
        p.expectKeyword("interface")
492
        p.expect('{')
493
        if p.tok != '}' {
494
                parseMethod()
495
                for p.tok == ';' {
496
                        p.next()
497
                        parseMethod()
498
                }
499
        }
500
        p.expect('}')
501
 
502
        methods.Sort()
503
        return &Interface{Methods: methods}
504
}
505
 
506
// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
507
//
508
func (p *gcParser) parseChanType() Type {
509
        dir := ast.SEND | ast.RECV
510
        if p.tok == scanner.Ident {
511
                p.expectKeyword("chan")
512
                if p.tok == '<' {
513
                        p.expectSpecial("<-")
514
                        dir = ast.SEND
515
                }
516
        } else {
517
                p.expectSpecial("<-")
518
                p.expectKeyword("chan")
519
                dir = ast.RECV
520
        }
521
        elt := p.parseType()
522
        return &Chan{Dir: dir, Elt: elt}
523
}
524
 
525
// Type =
526
//      BasicType | TypeName | ArrayType | SliceType | StructType |
527
//      PointerType | FuncType | InterfaceType | MapType | ChanType |
528
//      "(" Type ")" .
529
// BasicType = ident .
530
// TypeName = ExportedName .
531
// SliceType = "[" "]" Type .
532
// PointerType = "*" Type .
533
// FuncType = "func" Signature .
534
//
535
func (p *gcParser) parseType() Type {
536
        switch p.tok {
537
        case scanner.Ident:
538
                switch p.lit {
539
                default:
540
                        return p.parseBasicType()
541
                case "struct":
542
                        return p.parseStructType()
543
                case "func":
544
                        // FuncType
545
                        p.next()
546
                        return p.parseSignature()
547
                case "interface":
548
                        return p.parseInterfaceType()
549
                case "map":
550
                        return p.parseMapType()
551
                case "chan":
552
                        return p.parseChanType()
553
                }
554
        case '@':
555
                // TypeName
556
                pkg, name := p.parseExportedName()
557
                return p.declare(pkg.Data.(*ast.Scope), ast.Typ, name).Type.(Type)
558
        case '[':
559
                p.next() // look ahead
560
                if p.tok == ']' {
561
                        // SliceType
562
                        p.next()
563
                        return &Slice{Elt: p.parseType()}
564
                }
565
                return p.parseArrayType()
566
        case '*':
567
                // PointerType
568
                p.next()
569
                return &Pointer{Base: p.parseType()}
570
        case '<':
571
                return p.parseChanType()
572
        case '(':
573
                // "(" Type ")"
574
                p.next()
575
                typ := p.parseType()
576
                p.expect(')')
577
                return typ
578
        }
579
        p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit)
580
        return nil
581
}
582
 
583
// ----------------------------------------------------------------------------
584
// Declarations
585
 
586
// ImportDecl = "import" identifier string_lit .
587
//
588
func (p *gcParser) parseImportDecl() {
589
        p.expectKeyword("import")
590
        // The identifier has no semantic meaning in the import data.
591
        // It exists so that error messages can print the real package
592
        // name: binary.ByteOrder instead of "encoding/binary".ByteOrder.
593
        name := p.expect(scanner.Ident)
594
        pkg := p.parsePkgId()
595
        assert(pkg.Name == "" || pkg.Name == name)
596
        pkg.Name = name
597
}
598
 
599
// int_lit = [ "+" | "-" ] { "0" ... "9" } .
600
//
601
func (p *gcParser) parseInt() (sign, val string) {
602
        switch p.tok {
603
        case '-':
604
                p.next()
605
                sign = "-"
606
        case '+':
607
                p.next()
608
        }
609
        val = p.expect(scanner.Int)
610
        return
611
}
612
 
613
// number = int_lit [ "p" int_lit ] .
614
//
615
func (p *gcParser) parseNumber() Const {
616
        // mantissa
617
        sign, val := p.parseInt()
618
        mant, ok := new(big.Int).SetString(sign+val, 10)
619
        assert(ok)
620
 
621
        if p.lit == "p" {
622
                // exponent (base 2)
623
                p.next()
624
                sign, val = p.parseInt()
625
                exp64, err := strconv.ParseUint(val, 10, 0)
626
                if err != nil {
627
                        p.error(err)
628
                }
629
                exp := uint(exp64)
630
                if sign == "-" {
631
                        denom := big.NewInt(1)
632
                        denom.Lsh(denom, exp)
633
                        return Const{new(big.Rat).SetFrac(mant, denom)}
634
                }
635
                if exp > 0 {
636
                        mant.Lsh(mant, exp)
637
                }
638
                return Const{new(big.Rat).SetInt(mant)}
639
        }
640
 
641
        return Const{mant}
642
}
643
 
644
// ConstDecl   = "const" ExportedName [ Type ] "=" Literal .
645
// Literal     = bool_lit | int_lit | float_lit | complex_lit | string_lit .
646
// bool_lit    = "true" | "false" .
647
// complex_lit = "(" float_lit "+" float_lit ")" .
648
// rune_lit = "(" int_lit "+" int_lit ")" .
649
// string_lit  = `"` { unicode_char } `"` .
650
//
651
func (p *gcParser) parseConstDecl() {
652
        p.expectKeyword("const")
653
        pkg, name := p.parseExportedName()
654
        obj := p.declare(pkg.Data.(*ast.Scope), ast.Con, name)
655
        var x Const
656
        var typ Type
657
        if p.tok != '=' {
658
                obj.Type = p.parseType()
659
        }
660
        p.expect('=')
661
        switch p.tok {
662
        case scanner.Ident:
663
                // bool_lit
664
                if p.lit != "true" && p.lit != "false" {
665
                        p.error("expected true or false")
666
                }
667
                x = Const{p.lit == "true"}
668
                typ = Bool.Underlying
669
                p.next()
670
        case '-', scanner.Int:
671
                // int_lit
672
                x = p.parseNumber()
673
                typ = Int.Underlying
674
                if _, ok := x.val.(*big.Rat); ok {
675
                        typ = Float64.Underlying
676
                }
677
        case '(':
678
                // complex_lit or rune_lit
679
                p.next()
680
                if p.tok == scanner.Char {
681
                        p.next()
682
                        p.expect('+')
683
                        p.parseNumber()
684
                        p.expect(')')
685
                        // TODO: x = ...
686
                        break
687
                }
688
                re := p.parseNumber()
689
                p.expect('+')
690
                im := p.parseNumber()
691
                p.expect(')')
692
                x = Const{cmplx{re.val.(*big.Rat), im.val.(*big.Rat)}}
693
                typ = Complex128.Underlying
694
        case scanner.Char:
695
                // TODO: x = ...
696
                p.next()
697
        case scanner.String:
698
                // string_lit
699
                x = MakeConst(token.STRING, p.lit)
700
                p.next()
701
                typ = String.Underlying
702
        default:
703
                println(p.tok)
704
                p.errorf("expected literal got %s", scanner.TokenString(p.tok))
705
        }
706
        if obj.Type == nil {
707
                obj.Type = typ
708
        }
709
        obj.Data = x
710
}
711
 
712
// TypeDecl = "type" ExportedName Type .
713
//
714
func (p *gcParser) parseTypeDecl() {
715
        p.expectKeyword("type")
716
        pkg, name := p.parseExportedName()
717
        obj := p.declare(pkg.Data.(*ast.Scope), ast.Typ, name)
718
 
719
        // The type object may have been imported before and thus already
720
        // have a type associated with it. We still need to parse the type
721
        // structure, but throw it away if the object already has a type.
722
        // This ensures that all imports refer to the same type object for
723
        // a given type declaration.
724
        typ := p.parseType()
725
 
726
        if name := obj.Type.(*Name); name.Underlying == nil {
727
                assert(Underlying(typ) == typ)
728
                name.Underlying = typ
729
        }
730
}
731
 
732
// VarDecl = "var" ExportedName Type .
733
//
734
func (p *gcParser) parseVarDecl() {
735
        p.expectKeyword("var")
736
        pkg, name := p.parseExportedName()
737
        obj := p.declare(pkg.Data.(*ast.Scope), ast.Var, name)
738
        obj.Type = p.parseType()
739
}
740
 
741
// FuncBody = "{" ... "}" .
742
//
743
func (p *gcParser) parseFuncBody() {
744
        p.expect('{')
745
        for i := 1; i > 0; p.next() {
746
                switch p.tok {
747
                case '{':
748
                        i++
749
                case '}':
750
                        i--
751
                }
752
        }
753
}
754
 
755
// FuncDecl = "func" ExportedName Signature [ FuncBody ] .
756
//
757
func (p *gcParser) parseFuncDecl() {
758
        // "func" already consumed
759
        pkg, name := p.parseExportedName()
760
        obj := p.declare(pkg.Data.(*ast.Scope), ast.Fun, name)
761
        obj.Type = p.parseSignature()
762
        if p.tok == '{' {
763
                p.parseFuncBody()
764
        }
765
}
766
 
767
// MethodDecl = "func" Receiver Name Signature .
768
// Receiver   = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" [ FuncBody ].
769
//
770
func (p *gcParser) parseMethodDecl() {
771
        // "func" already consumed
772
        p.expect('(')
773
        p.parseParameter() // receiver
774
        p.expect(')')
775
        p.parseName() // unexported method names in imports are qualified with their package.
776
        p.parseSignature()
777
        if p.tok == '{' {
778
                p.parseFuncBody()
779
        }
780
}
781
 
782
// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
783
//
784
func (p *gcParser) parseDecl() {
785
        switch p.lit {
786
        case "import":
787
                p.parseImportDecl()
788
        case "const":
789
                p.parseConstDecl()
790
        case "type":
791
                p.parseTypeDecl()
792
        case "var":
793
                p.parseVarDecl()
794
        case "func":
795
                p.next() // look ahead
796
                if p.tok == '(' {
797
                        p.parseMethodDecl()
798
                } else {
799
                        p.parseFuncDecl()
800
                }
801
        }
802
        p.expect('\n')
803
}
804
 
805
// ----------------------------------------------------------------------------
806
// Export
807
 
808
// Export        = "PackageClause { Decl } "$$" .
809
// PackageClause = "package" identifier [ "safe" ] "\n" .
810
//
811
func (p *gcParser) parseExport() *ast.Object {
812
        p.expectKeyword("package")
813
        name := p.expect(scanner.Ident)
814
        if p.tok != '\n' {
815
                // A package is safe if it was compiled with the -u flag,
816
                // which disables the unsafe package.
817
                // TODO(gri) remember "safe" package
818
                p.expectKeyword("safe")
819
        }
820
        p.expect('\n')
821
 
822
        assert(p.imports[p.id] == nil)
823
        pkg := ast.NewObj(ast.Pkg, name)
824
        pkg.Data = ast.NewScope(nil)
825
        p.imports[p.id] = pkg
826
 
827
        for p.tok != '$' && p.tok != scanner.EOF {
828
                p.parseDecl()
829
        }
830
 
831
        if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' {
832
                // don't call next()/expect() since reading past the
833
                // export data may cause scanner errors (e.g. NUL chars)
834
                p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch)
835
        }
836
 
837
        if n := p.scanner.ErrorCount; n != 0 {
838
                p.errorf("expected no scanner errors, got %d", n)
839
        }
840
 
841
        return pkg
842
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.