github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgGoSource/kmgGoParser/kmgGoParser.go (about) 1 package kmgGoParser 2 3 import ( 4 "bytes" 5 "github.com/bronze1man/kmg/kmgFile" 6 "github.com/bronze1man/kmg/kmgGoSource/kmgGoReader" 7 "unicode" 8 ) 9 10 // 暂时忽略任何测试包. 此处不做编译检查,认为所有输入的go文件都是正常的. 11 func MustParsePackage(gopath string, pkgPath string) *Package { 12 return NewProgram([]string{gopath}).GetPackage(pkgPath) 13 } 14 15 //再多解析一个文件,path 是绝对路径 16 func (pkg *Package) mustAddFile(path string) { 17 //fmt.Println(path) 18 file := parseFile(pkg.PkgPath, path, pkg) 19 for imp := range file.ImportMap { 20 pkg.AddImport(imp) 21 } 22 for _, funcDecl := range file.FuncList { 23 pkg.FuncList = append(pkg.FuncList, funcDecl) 24 } 25 for _, funcDecl := range file.MethodList { 26 pkg.MethodList = append(pkg.MethodList, funcDecl) 27 } 28 for _, namedType := range file.NamedTypeList { 29 pkg.NamedTypeList = append(pkg.NamedTypeList, namedType) 30 } 31 } 32 33 func (pkg *Package) LookupNamedType(name string) *NamedType { 34 for i := range pkg.NamedTypeList { 35 if pkg.NamedTypeList[i].Name == name { 36 return pkg.NamedTypeList[i] 37 } 38 } 39 return nil 40 } 41 42 func parseFile(pkgPath string, path string, pkg *Package) *File { 43 gofile := &File{ 44 PackagePath: pkgPath, 45 ImportMap: map[string]bool{}, 46 AliasImportMap: map[string]string{}, 47 Pkg: pkg, 48 } 49 content := kmgFile.MustReadFile(path) 50 posFile := kmgGoReader.NewPosFile(path, content) 51 content = goSourceRemoveComment(content, posFile) 52 r := kmgGoReader.NewReader(content, posFile) 53 54 r.ReadAllSpace() 55 r.MustReadMatch(tokenPackage) 56 r.ReadUntilByte('\n') 57 for { 58 if r.IsEof() { 59 return gofile //没有 import 正确情况 60 } 61 r.ReadAllSpace() 62 if r.IsMatchAfter(tokenImport) { 63 gofile.readImport(r) 64 continue 65 } 66 break 67 } 68 for { 69 switch { 70 case r.IsEof(): 71 return gofile 72 case r.IsMatchAfter(tokenFunc): 73 funcDecl := gofile.readGoFunc(r) 74 if funcDecl.GetKind() == Func { 75 gofile.FuncList = append(gofile.FuncList, funcDecl) 76 } else { 77 gofile.MethodList = append(gofile.MethodList, funcDecl) 78 } 79 case r.IsMatchAfter(tokenType): 80 //r.ReadUntilByte('\n') 81 gofile.readGoType(r) 82 case r.IsMatchAfter(tokenVar): 83 gofile.readGoVar(r) 84 case r.IsMatchAfter(tokenConst): 85 gofile.readGoConst(r) 86 // 有一些没有分析的代码,里面可能包含import,此处先简单绕过. 87 case r.IsMatchAfter(tokenDoubleQuate) || r.IsMatchAfter(tokenGraveAccent): 88 MustReadGoString(r) 89 //fmt.Println(string(ret)) 90 case r.IsMatchAfter(tokenSingleQuate): 91 mustReadGoChar(r) 92 default: 93 r.ReadByte() 94 } 95 } 96 } 97 98 func readIdentifier(r *kmgGoReader.Reader) []byte { 99 buf := &bytes.Buffer{} 100 if r.IsEof() { 101 panic(r.GetFileLineInfo() + " unexcept EOF") 102 } 103 b := r.ReadRune() 104 if b == '_' || unicode.IsLetter(b) { 105 buf.WriteRune(b) 106 } else { 107 r.UnreadRune() 108 return nil 109 } 110 for { 111 if r.IsEof() { 112 return buf.Bytes() 113 } 114 b := r.ReadRune() 115 if b == '_' || unicode.IsLetter(b) || unicode.IsDigit(b) { 116 buf.WriteRune(b) 117 } else { 118 r.UnreadRune() 119 return buf.Bytes() // 不是Identifier的东西留个调用者处理 120 } 121 } 122 } 123 124 // 跳过 "{" "}",默认当前已经有第一层了(已经读入一个"{"了) 125 func readMatchBigParantheses(r *kmgGoReader.Reader) []byte { 126 return readMatchChar(r, '{', '}') 127 } 128 129 // 跳过 "[" "]",默认当前已经有第一层了(已经读入一个"["了) 130 func readMatchMiddleParantheses(r *kmgGoReader.Reader) []byte { 131 return readMatchChar(r, '[', ']') 132 } 133 134 // 跳过 "(" ")",默认当前已经有第一层了(已经读入一个"("了) 135 func readMatchSmallParantheses(r *kmgGoReader.Reader) []byte { 136 return readMatchChar(r, '(', ')') 137 } 138 139 func readMatchChar(r *kmgGoReader.Reader, starter byte, ender byte) []byte { 140 startPos := r.Pos() 141 level := 1 142 for { 143 if r.IsEof() { 144 panic(r.GetFileLineInfo() + " unexcept EOF") 145 } 146 b := r.ReadByte() 147 if b == '"' || b == '`' { 148 r.UnreadByte() 149 MustReadGoString(r) 150 } else if b == '\'' { 151 r.UnreadByte() 152 mustReadGoChar(r) 153 } else if b == starter { 154 level++ 155 } else if b == ender { 156 level-- 157 if level == 0 { 158 return r.BufToCurrent(startPos) 159 } 160 } 161 } 162 }