github.com/yunabe/lgo@v0.0.0-20190709125917-42c42d410fdf/parser/custom.go (about) 1 package parser 2 3 import ( 4 "go/ast" 5 "go/token" 6 ) 7 8 type LGOBlock struct { 9 Scope *ast.Scope // package scope (this file only) 10 Imports []*ast.ImportSpec // imports in this file 11 Unresolved []*ast.Ident // unresolved identifiers in this file 12 Comments []*ast.CommentGroup // list of all comments in the source file 13 Stmts []ast.Stmt 14 } 15 16 func (p *parser) parseLgoStmtList() (list []ast.Stmt) { 17 if p.trace { 18 defer un(trace(p, "LgoStatementList")) 19 } 20 21 for p.tok != token.CASE && p.tok != token.DEFAULT && p.tok != token.RBRACE && p.tok != token.EOF { 22 list = append(list, p.parseStmtWithFuncDeclImport(true, true)) 23 } 24 25 return 26 } 27 28 func (p *parser) parseLesserGoSrc() *LGOBlock { 29 // Extended from parseFile 30 if p.trace { 31 defer un(trace(p, "File")) 32 } 33 34 // Don't bother parsing the rest if we had errors scanning the first token. 35 // Likely not a Go source file at all. 36 if p.errors.Len() != 0 { 37 return nil 38 } 39 40 p.openScope() 41 // We need to open/close a label-scope to support label in the top-level scope. 42 p.openLabelScope() 43 p.pkgScope = p.topScope 44 // rest of package body 45 stmts := p.parseLgoStmtList() 46 p.closeLabelScope() 47 p.closeScope() 48 assert(p.topScope == nil, "unbalanced scopes") 49 assert(p.labelScope == nil, "unbalanced label scopes") 50 51 // resolve global identifiers within the same file 52 i := 0 53 for _, ident := range p.unresolved { 54 // i <= index for current ident 55 assert(ident.Obj == unresolved, "object already resolved") 56 ident.Obj = p.pkgScope.Lookup(ident.Name) // also removes unresolved sentinel 57 if ident.Obj == nil { 58 p.unresolved[i] = ident 59 i++ 60 } 61 } 62 63 return &LGOBlock{ 64 // Package: pos, 65 // Name: ident, 66 // Decls: decls, 67 Stmts: stmts, 68 Scope: p.pkgScope, 69 Imports: p.imports, 70 Unresolved: p.unresolved[0:i], 71 Comments: p.comments, 72 } 73 } 74 75 func ParseLesserGoFile(fset *token.FileSet, filename string, src interface{}, mode Mode) (f *LGOBlock, err error) { 76 if fset == nil { 77 panic("parser.ParseFile: no token.FileSet provided (fset == nil)") 78 } 79 80 // get source 81 text, err := readSource(filename, src) 82 if err != nil { 83 return nil, err 84 } 85 86 var p parser 87 defer func() { 88 if e := recover(); e != nil { 89 // resume same panic if it's not a bailout 90 if _, ok := e.(bailout); !ok { 91 panic(e) 92 } 93 } 94 95 // set result values 96 if f == nil { 97 // source is not a valid Go source file - satisfy 98 // ParseFile API and return a valid (but) empty 99 // *ast.File 100 f = &LGOBlock{ 101 // Name: new(ast.Ident), 102 Scope: ast.NewScope(nil), 103 } 104 } 105 106 p.errors.Sort() 107 err = p.errors.Err() 108 }() 109 110 // parse source 111 p.init(fset, filename, text, mode) 112 f = p.parseLesserGoSrc() 113 114 return 115 }