func (p *gcParser) expect(tok int) string { lit := p.lit if p.tok != tok { p.errorf("expected %q, got %q (%q)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit) } p.next() return lit }
// Export = "PackageClause { Decl } "$$" . // PackageClause = "package" identifier [ "safe" ] "\n" . // func (p *gcParser) parseExport() *ast.Object { p.expectKeyword("package") name := p.expect(scanner.Ident) if p.tok != '\n' { // A package is safe if it was compiled with the -u flag, // which disables the unsafe package. // TODO(gri) remember "safe" package p.expectKeyword("safe") } p.expect('\n') assert(p.imports[p.id] == nil) pkg := ast.NewObj(ast.Pkg, name) pkg.Data = ast.NewScope(nil) p.imports[p.id] = pkg for p.tok != '$' && p.tok != scanner.EOF { p.parseDecl() } if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' { // don't call next()/expect() since reading past the // export data may cause scanner errors (e.g. NUL chars) p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch) } if n := p.scanner.ErrorCount; n != 0 { p.errorf("expected no scanner errors, got %d", n) } return pkg }
func (p *parser) expect(tok rune) scanner.Position { pos := p.pos if p.tok != tok { p.errorExpected(pos, scanner.TokenString(tok)) } p.next() // make progress in any case return pos }
func (p *gcParser) next() { p.tok = p.scanner.Scan() switch p.tok { case scanner.Ident, scanner.Int, scanner.String: p.lit = p.scanner.TokenText() default: p.lit = "" } if trace { fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit) } }
func (p *parser) errorExpected(pos scanner.Position, msg string) { msg = `expected "` + msg + `"` if pos.Offset == p.pos.Offset { // the error happened at the current position; // make the error message more specific msg += ", found " + scanner.TokenString(p.tok) if p.tok < 0 { msg += " " + p.lit } } p.error(pos, msg) }
// Type = // BasicType | TypeName | ArrayType | SliceType | StructType | // PointerType | FuncType | InterfaceType | MapType | ChanType | // "(" Type ")" . // BasicType = ident . // TypeName = ExportedName . // SliceType = "[" "]" Type . // PointerType = "*" Type . // FuncType = "func" Signature . // func (p *gcParser) parseType() Type { switch p.tok { case scanner.Ident: switch p.lit { default: return p.parseBasicType() case "struct": return p.parseStructType() case "func": // FuncType p.next() return p.parseSignature() case "interface": return p.parseInterfaceType() case "map": return p.parseMapType() case "chan": return p.parseChanType() } case '@': // TypeName pkg, name := p.parseExportedName() return p.declare(pkg.Data.(*ast.Scope), ast.Typ, name).Type.(Type) case '[': p.next() // look ahead if p.tok == ']' { // SliceType p.next() return &Slice{Elt: p.parseType()} } return p.parseArrayType() case '*': // PointerType p.next() return &Pointer{Base: p.parseType()} case '<': return p.parseChanType() case '(': // "(" Type ")" p.next() typ := p.parseType() p.expect(')') return typ } p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit) return nil }
// Type = // BasicType | TypeName | ArrayType | SliceType | StructType | // PointerType | FuncType | InterfaceType | MapType | ChanType | // "(" Type ")" . // BasicType = ident . // TypeName = ExportedName . // SliceType = "[" "]" Type . // PointerType = "*" Type . // func (p *gcParser) parseType() Type { switch p.tok { case scanner.Ident: switch p.lit { default: return p.parseBasicType() case "struct": return p.parseStructType() case "func": p.next() // parseFuncType assumes "func" is already consumed return p.parseFuncType() case "interface": return p.parseInterfaceType() case "map": return p.parseMapType() case "chan": return p.parseChanType() } case scanner.String: // TypeName return p.parseExportedName(ast.Typ).Type.(Type) case '[': p.next() // look ahead if p.tok == ']' { // SliceType p.next() return &Slice{Elt: p.parseType()} } return p.parseArrayType() case '*': // PointerType p.next() return &Pointer{Base: p.parseType()} case '<': return p.parseChanType() case '(': // "(" Type ")" p.next() typ := p.parseType() p.expect(')') return typ } p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit) return nil }
// Type = // BasicType | TypeName | ArrayType | SliceType | StructType | // PointerType | FuncType | InterfaceType | MapType | ChanType | // "(" Type ")" . // BasicType = ident . // TypeName = ExportedName . // SliceType = "[" "]" Type . // PointerType = "*" Type . // FuncType = "func" Signature . func (p *gcParser) parseType() ast.Expr { switch p.tok { case scanner.Ident: switch p.lit { case "struct": return p.parseStrucType() case "func": p.next() return p.parseSignature() case "interface": return p.parseInterfaceType() case "map": return p.parseMapType() case "chan": return p.parseChanType() default: lit := p.lit p.next() return ast.NewIdent(lit) } case '@': return p.parseExportedName() case '[': return p.parseArrayOrSliceType() case '*': p.next() return &ast.StarExpr{X: p.parseType()} case '<': return p.parseChanType() case '(': p.next() typ := p.parseType() p.expect(')') return typ } p.errorf("unexpected token: %s", scanner.TokenString(p.tok)) return nil }
/*func (d *Decoder) decode(src io.Reader) { } */ func main() { flag.Parse() if flag.NArg() != 1 { fmt.Println("wrong number of arguments") os.Exit(1) } file, err := os.Open(flag.Arg(0), os.O_RDONLY, 0) if file == nil { fmt.Printf("can't open file; err=%s\n", err.String()) os.Exit(1) } var s scanner.Scanner s.Init(file) tok := s.Scan() for tok != scanner.EOF { fmt.Println(scanner.TokenString(tok)) tok = s.Scan() } fmt.Println() file.Close() }