1package main 2 3import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "go/ast" 8 "go/token" 9 "strconv" 10 "text/scanner" 11) 12 13//------------------------------------------------------------------------- 14// gc_parser 15// 16// The following part of the code may contain portions of the code from the Go 17// standard library, which tells me to retain their copyright notice: 18// 19// Copyright (c) 2009 The Go Authors. All rights reserved. 20// 21// Redistribution and use in source and binary forms, with or without 22// modification, are permitted provided that the following conditions are 23// met: 24// 25// * Redistributions of source code must retain the above copyright 26// notice, this list of conditions and the following disclaimer. 27// * Redistributions in binary form must reproduce the above 28// copyright notice, this list of conditions and the following disclaimer 29// in the documentation and/or other materials provided with the 30// distribution. 31// * Neither the name of Google Inc. nor the names of its 32// contributors may be used to endorse or promote products derived from 33// this software without specific prior written permission. 34// 35// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 36// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 37// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 38// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 39// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 41// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 42// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 43// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 44// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 45// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 46//------------------------------------------------------------------------- 47 48type gc_parser struct { 49 scanner scanner.Scanner 50 tok rune 51 lit string 52 path_to_name map[string]string 53 beautify bool 54 pfc *package_file_cache 55} 56 57func (p *gc_parser) init(data []byte, pfc *package_file_cache) { 58 p.scanner.Init(bytes.NewReader(data)) 59 p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) } 60 p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanStrings | 61 scanner.ScanComments | scanner.ScanChars | scanner.SkipComments 62 p.scanner.Whitespace = 1<<'\t' | 1<<' ' | 1<<'\r' | 1<<'\v' | 1<<'\f' 63 p.scanner.Filename = "package.go" 64 p.next() 65 // and the built-in "unsafe" package to the path_to_name map 66 p.path_to_name = map[string]string{"unsafe": "unsafe"} 67 p.pfc = pfc 68} 69 70func (p *gc_parser) next() { 71 p.tok = p.scanner.Scan() 72 switch p.tok { 73 case scanner.Ident, scanner.Int, scanner.String: 74 p.lit = p.scanner.TokenText() 75 default: 76 p.lit = "" 77 } 78} 79 80func (p *gc_parser) error(msg string) { 81 panic(errors.New(msg)) 82} 83 84func (p *gc_parser) errorf(format string, args ...interface{}) { 85 p.error(fmt.Sprintf(format, args...)) 86} 87 88func (p *gc_parser) expect(tok rune) string { 89 lit := p.lit 90 if p.tok != tok { 91 p.errorf("expected %s, got %s (%q)", scanner.TokenString(tok), 92 scanner.TokenString(p.tok), lit) 93 } 94 p.next() 95 return lit 96} 97 98func (p *gc_parser) expect_keyword(keyword string) { 99 lit := p.expect(scanner.Ident) 100 if lit != keyword { 101 p.errorf("expected keyword: %s, got: %q", keyword, lit) 102 } 103} 104 105func (p *gc_parser) expect_special(what string) { 106 i := 0 107 for i < len(what) { 108 if p.tok != rune(what[i]) { 109 break 110 } 111 112 nc := p.scanner.Peek() 113 if i != len(what)-1 && nc <= ' ' { 114 break 115 } 116 117 p.next() 118 i++ 119 } 120 121 if i < len(what) { 122 p.errorf("expected: %q, got: %q", what, what[0:i]) 123 } 124} 125 126// dotIdentifier = "?" | ( ident | '·' ) { ident | int | '·' } . 127// we're doing lexer job here, kind of 128func (p *gc_parser) parse_dot_ident() string { 129 if p.tok == '?' { 130 p.next() 131 return "?" 132 } 133 134 ident := "" 135 sep := 'x' 136 i, j := 0, -1 137 for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' { 138 ident += p.lit 139 if p.tok == '·' { 140 ident += "·" 141 j = i 142 i++ 143 } 144 i += len(p.lit) 145 sep = p.scanner.Peek() 146 p.next() 147 } 148 // middot = \xc2\xb7 149 if j != -1 && i > j+1 { 150 c := ident[j+2] 151 if c >= '0' && c <= '9' { 152 ident = ident[0:j] 153 } 154 } 155 return ident 156} 157 158// ImportPath = string_lit . 159// quoted name of the path, but we return it as an identifier, taking an alias 160// from 'pathToAlias' map, it is filled by import statements 161func (p *gc_parser) parse_package() *ast.Ident { 162 path, err := strconv.Unquote(p.expect(scanner.String)) 163 if err != nil { 164 panic(err) 165 } 166 167 return ast.NewIdent(path) 168} 169 170// ExportedName = "@" ImportPath "." dotIdentifier . 171func (p *gc_parser) parse_exported_name() *ast.SelectorExpr { 172 p.expect('@') 173 pkg := p.parse_package() 174 if pkg.Name == "" { 175 pkg.Name = "!" + p.pfc.name + "!" + p.pfc.defalias 176 } else { 177 pkg.Name = p.path_to_name[pkg.Name] 178 } 179 p.expect('.') 180 name := ast.NewIdent(p.parse_dot_ident()) 181 return &ast.SelectorExpr{X: pkg, Sel: name} 182} 183 184// Name = identifier | "?" | ExportedName . 185func (p *gc_parser) parse_name() (string, ast.Expr) { 186 switch p.tok { 187 case scanner.Ident: 188 name := p.lit 189 p.next() 190 return name, ast.NewIdent(name) 191 case '?': 192 p.next() 193 return "?", ast.NewIdent("?") 194 case '@': 195 en := p.parse_exported_name() 196 return en.Sel.Name, en 197 } 198 p.error("name expected") 199 return "", nil 200} 201 202// Field = Name Type [ string_lit ] . 203func (p *gc_parser) parse_field() *ast.Field { 204 var tag string 205 name, _ := p.parse_name() 206 typ := p.parse_type() 207 if p.tok == scanner.String { 208 tag = p.expect(scanner.String) 209 } 210 211 var names []*ast.Ident 212 if name != "?" { 213 names = []*ast.Ident{ast.NewIdent(name)} 214 } 215 216 return &ast.Field{ 217 Names: names, 218 Type: typ, 219 Tag: &ast.BasicLit{Kind: token.STRING, Value: tag}, 220 } 221} 222 223// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] . 224func (p *gc_parser) parse_parameter() *ast.Field { 225 // name 226 name, _ := p.parse_name() 227 228 // type 229 var typ ast.Expr 230 if p.tok == '.' { 231 p.expect_special("...") 232 typ = &ast.Ellipsis{Elt: p.parse_type()} 233 } else { 234 typ = p.parse_type() 235 } 236 237 var tag string 238 if p.tok == scanner.String { 239 tag = p.expect(scanner.String) 240 } 241 242 return &ast.Field{ 243 Names: []*ast.Ident{ast.NewIdent(name)}, 244 Type: typ, 245 Tag: &ast.BasicLit{Kind: token.STRING, Value: tag}, 246 } 247} 248 249// Parameters = "(" [ ParameterList ] ")" . 250// ParameterList = { Parameter "," } Parameter . 251func (p *gc_parser) parse_parameters() *ast.FieldList { 252 flds := []*ast.Field{} 253 parse_parameter := func() { 254 par := p.parse_parameter() 255 flds = append(flds, par) 256 } 257 258 p.expect('(') 259 if p.tok != ')' { 260 parse_parameter() 261 for p.tok == ',' { 262 p.next() 263 parse_parameter() 264 } 265 } 266 p.expect(')') 267 return &ast.FieldList{List: flds} 268} 269 270// Signature = Parameters [ Result ] . 271// Result = Type | Parameters . 272func (p *gc_parser) parse_signature() *ast.FuncType { 273 var params *ast.FieldList 274 var results *ast.FieldList 275 276 params = p.parse_parameters() 277 switch p.tok { 278 case scanner.Ident, '[', '*', '<', '@': 279 fld := &ast.Field{Type: p.parse_type()} 280 results = &ast.FieldList{List: []*ast.Field{fld}} 281 case '(': 282 results = p.parse_parameters() 283 } 284 return &ast.FuncType{Params: params, Results: results} 285} 286 287// MethodOrEmbedSpec = Name [ Signature ] . 288func (p *gc_parser) parse_method_or_embed_spec() *ast.Field { 289 name, nameexpr := p.parse_name() 290 if p.tok == '(' { 291 typ := p.parse_signature() 292 return &ast.Field{ 293 Names: []*ast.Ident{ast.NewIdent(name)}, 294 Type: typ, 295 } 296 } 297 298 return &ast.Field{ 299 Type: nameexpr, 300 } 301} 302 303// int_lit = [ "-" | "+" ] { "0" ... "9" } . 304func (p *gc_parser) parse_int() { 305 switch p.tok { 306 case '-', '+': 307 p.next() 308 } 309 p.expect(scanner.Int) 310} 311 312// number = int_lit [ "p" int_lit ] . 313func (p *gc_parser) parse_number() { 314 p.parse_int() 315 if p.lit == "p" { 316 p.next() 317 p.parse_int() 318 } 319} 320 321//------------------------------------------------------------------------------- 322// gc_parser.types 323//------------------------------------------------------------------------------- 324 325// InterfaceType = "interface" "{" [ MethodOrEmbedList ] "}" . 326// MethodOrEmbedList = MethodOrEmbedSpec { ";" MethodOrEmbedSpec } . 327func (p *gc_parser) parse_interface_type() ast.Expr { 328 var methods []*ast.Field 329 parse_method := func() { 330 meth := p.parse_method_or_embed_spec() 331 methods = append(methods, meth) 332 } 333 334 p.expect_keyword("interface") 335 p.expect('{') 336 if p.tok != '}' { 337 parse_method() 338 for p.tok == ';' { 339 p.next() 340 parse_method() 341 } 342 } 343 p.expect('}') 344 return &ast.InterfaceType{Methods: &ast.FieldList{List: methods}} 345} 346 347// StructType = "struct" "{" [ FieldList ] "}" . 348// FieldList = Field { ";" Field } . 349func (p *gc_parser) parse_struct_type() ast.Expr { 350 var fields []*ast.Field 351 parse_field := func() { 352 fld := p.parse_field() 353 fields = append(fields, fld) 354 } 355 356 p.expect_keyword("struct") 357 p.expect('{') 358 if p.tok != '}' { 359 parse_field() 360 for p.tok == ';' { 361 p.next() 362 parse_field() 363 } 364 } 365 p.expect('}') 366 return &ast.StructType{Fields: &ast.FieldList{List: fields}} 367} 368 369// MapType = "map" "[" Type "]" Type . 370func (p *gc_parser) parse_map_type() ast.Expr { 371 p.expect_keyword("map") 372 p.expect('[') 373 key := p.parse_type() 374 p.expect(']') 375 elt := p.parse_type() 376 return &ast.MapType{Key: key, Value: elt} 377} 378 379// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type . 380func (p *gc_parser) parse_chan_type() ast.Expr { 381 dir := ast.SEND | ast.RECV 382 if p.tok == scanner.Ident { 383 p.expect_keyword("chan") 384 if p.tok == '<' { 385 p.expect_special("<-") 386 dir = ast.SEND 387 } 388 } else { 389 p.expect_special("<-") 390 p.expect_keyword("chan") 391 dir = ast.RECV 392 } 393 394 elt := p.parse_type() 395 return &ast.ChanType{Dir: dir, Value: elt} 396} 397 398// ArrayOrSliceType = ArrayType | SliceType . 399// ArrayType = "[" int_lit "]" Type . 400// SliceType = "[" "]" Type . 401func (p *gc_parser) parse_array_or_slice_type() ast.Expr { 402 p.expect('[') 403 if p.tok == ']' { 404 // SliceType 405 p.next() // skip ']' 406 return &ast.ArrayType{Len: nil, Elt: p.parse_type()} 407 } 408 409 // ArrayType 410 lit := p.expect(scanner.Int) 411 p.expect(']') 412 return &ast.ArrayType{ 413 Len: &ast.BasicLit{Kind: token.INT, Value: lit}, 414 Elt: p.parse_type(), 415 } 416} 417 418// Type = 419// BasicType | TypeName | ArrayType | SliceType | StructType | 420// PointerType | FuncType | InterfaceType | MapType | ChanType | 421// "(" Type ")" . 422// BasicType = ident . 423// TypeName = ExportedName . 424// SliceType = "[" "]" Type . 425// PointerType = "*" Type . 426// FuncType = "func" Signature . 427func (p *gc_parser) parse_type() ast.Expr { 428 switch p.tok { 429 case scanner.Ident: 430 switch p.lit { 431 case "struct": 432 return p.parse_struct_type() 433 case "func": 434 p.next() 435 return p.parse_signature() 436 case "interface": 437 return p.parse_interface_type() 438 case "map": 439 return p.parse_map_type() 440 case "chan": 441 return p.parse_chan_type() 442 default: 443 lit := p.lit 444 p.next() 445 return ast.NewIdent(lit) 446 } 447 case '@': 448 return p.parse_exported_name() 449 case '[': 450 return p.parse_array_or_slice_type() 451 case '*': 452 p.next() 453 return &ast.StarExpr{X: p.parse_type()} 454 case '<': 455 return p.parse_chan_type() 456 case '(': 457 p.next() 458 typ := p.parse_type() 459 p.expect(')') 460 return typ 461 } 462 p.errorf("unexpected token: %s", scanner.TokenString(p.tok)) 463 return nil 464} 465 466//------------------------------------------------------------------------------- 467// gc_parser.declarations 468//------------------------------------------------------------------------------- 469 470// ImportDecl = "import" identifier string_lit . 471func (p *gc_parser) parse_import_decl() { 472 p.expect_keyword("import") 473 alias := p.expect(scanner.Ident) 474 path := p.parse_package() 475 fullName := "!" + path.Name + "!" + alias 476 p.path_to_name[path.Name] = fullName 477 p.pfc.add_package_to_scope(fullName, path.Name) 478} 479 480// ConstDecl = "const" ExportedName [ Type ] "=" Literal . 481// Literal = bool_lit | int_lit | float_lit | complex_lit | string_lit . 482// bool_lit = "true" | "false" . 483// complex_lit = "(" float_lit "+" float_lit ")" . 484// rune_lit = "(" int_lit "+" int_lit ")" . 485// string_lit = `"` { unicode_char } `"` . 486func (p *gc_parser) parse_const_decl() (string, *ast.GenDecl) { 487 // TODO: do we really need actual const value? gocode doesn't use this 488 p.expect_keyword("const") 489 name := p.parse_exported_name() 490 491 var typ ast.Expr 492 if p.tok != '=' { 493 typ = p.parse_type() 494 } 495 496 p.expect('=') 497 498 // skip the value 499 switch p.tok { 500 case scanner.Ident: 501 // must be bool, true or false 502 p.next() 503 case '-', '+', scanner.Int: 504 // number 505 p.parse_number() 506 case '(': 507 // complex_lit or rune_lit 508 p.next() // skip '(' 509 if p.tok == scanner.Char { 510 p.next() 511 } else { 512 p.parse_number() 513 } 514 p.expect('+') 515 p.parse_number() 516 p.expect(')') 517 case scanner.Char: 518 p.next() 519 case scanner.String: 520 p.next() 521 default: 522 p.error("expected literal") 523 } 524 525 return name.X.(*ast.Ident).Name, &ast.GenDecl{ 526 Tok: token.CONST, 527 Specs: []ast.Spec{ 528 &ast.ValueSpec{ 529 Names: []*ast.Ident{name.Sel}, 530 Type: typ, 531 Values: []ast.Expr{&ast.BasicLit{Kind: token.INT, Value: "0"}}, 532 }, 533 }, 534 } 535} 536 537// TypeDecl = "type" ExportedName Type . 538func (p *gc_parser) parse_type_decl() (string, *ast.GenDecl) { 539 p.expect_keyword("type") 540 name := p.parse_exported_name() 541 typ := p.parse_type() 542 return name.X.(*ast.Ident).Name, &ast.GenDecl{ 543 Tok: token.TYPE, 544 Specs: []ast.Spec{ 545 &ast.TypeSpec{ 546 Name: name.Sel, 547 Type: typ, 548 }, 549 }, 550 } 551} 552 553// VarDecl = "var" ExportedName Type . 554func (p *gc_parser) parse_var_decl() (string, *ast.GenDecl) { 555 p.expect_keyword("var") 556 name := p.parse_exported_name() 557 typ := p.parse_type() 558 return name.X.(*ast.Ident).Name, &ast.GenDecl{ 559 Tok: token.VAR, 560 Specs: []ast.Spec{ 561 &ast.ValueSpec{ 562 Names: []*ast.Ident{name.Sel}, 563 Type: typ, 564 }, 565 }, 566 } 567} 568 569// FuncBody = "{" ... "}" . 570func (p *gc_parser) parse_func_body() { 571 p.expect('{') 572 for i := 1; i > 0; p.next() { 573 switch p.tok { 574 case '{': 575 i++ 576 case '}': 577 i-- 578 } 579 } 580} 581 582// FuncDecl = "func" ExportedName Signature [ FuncBody ] . 583func (p *gc_parser) parse_func_decl() (string, *ast.FuncDecl) { 584 // "func" was already consumed by lookahead 585 name := p.parse_exported_name() 586 typ := p.parse_signature() 587 if p.tok == '{' { 588 p.parse_func_body() 589 } 590 return name.X.(*ast.Ident).Name, &ast.FuncDecl{ 591 Name: name.Sel, 592 Type: typ, 593 } 594} 595 596func strip_method_receiver(recv *ast.FieldList) string { 597 var sel *ast.SelectorExpr 598 599 // find selector expression 600 typ := recv.List[0].Type 601 switch t := typ.(type) { 602 case *ast.StarExpr: 603 sel = t.X.(*ast.SelectorExpr) 604 case *ast.SelectorExpr: 605 sel = t 606 } 607 608 // extract package path 609 pkg := sel.X.(*ast.Ident).Name 610 611 // write back stripped type 612 switch t := typ.(type) { 613 case *ast.StarExpr: 614 t.X = sel.Sel 615 case *ast.SelectorExpr: 616 recv.List[0].Type = sel.Sel 617 } 618 619 return pkg 620} 621 622// MethodDecl = "func" Receiver Name Signature . 623// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" [ FuncBody ] . 624func (p *gc_parser) parse_method_decl() (string, *ast.FuncDecl) { 625 recv := p.parse_parameters() 626 pkg := strip_method_receiver(recv) 627 name, _ := p.parse_name() 628 typ := p.parse_signature() 629 if p.tok == '{' { 630 p.parse_func_body() 631 } 632 return pkg, &ast.FuncDecl{ 633 Recv: recv, 634 Name: ast.NewIdent(name), 635 Type: typ, 636 } 637} 638 639// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" . 640func (p *gc_parser) parse_decl() (pkg string, decl ast.Decl) { 641 switch p.lit { 642 case "import": 643 p.parse_import_decl() 644 case "const": 645 pkg, decl = p.parse_const_decl() 646 case "type": 647 pkg, decl = p.parse_type_decl() 648 case "var": 649 pkg, decl = p.parse_var_decl() 650 case "func": 651 p.next() 652 if p.tok == '(' { 653 pkg, decl = p.parse_method_decl() 654 } else { 655 pkg, decl = p.parse_func_decl() 656 } 657 } 658 p.expect('\n') 659 return 660} 661 662// Export = PackageClause { Decl } "$$" . 663// PackageClause = "package" identifier [ "safe" ] "\n" . 664func (p *gc_parser) parse_export(callback func(string, ast.Decl)) { 665 p.expect_keyword("package") 666 p.pfc.defalias = p.expect(scanner.Ident) 667 if p.tok != '\n' { 668 p.expect_keyword("safe") 669 } 670 p.expect('\n') 671 672 for p.tok != '$' && p.tok != scanner.EOF { 673 pkg, decl := p.parse_decl() 674 if decl != nil { 675 callback(pkg, decl) 676 } 677 } 678} 679