func readIdentifier(r *kmgGoReader.Reader) []byte { buf := &bytes.Buffer{} if r.IsEof() { panic(r.GetFileLineInfo() + " unexcept EOF") } b := r.ReadRune() if b == '_' || unicode.IsLetter(b) { buf.WriteRune(b) } else { r.UnreadRune() return nil } for { if r.IsEof() { return buf.Bytes() } b := r.ReadRune() if b == '_' || unicode.IsLetter(b) || unicode.IsDigit(b) { buf.WriteRune(b) } else { r.UnreadRune() return buf.Bytes() // 不是Identifier的东西留个调用者处理 } } }
// 可以读 '"' 这种,返回这个东西实际占的字节数据 func mustReadGoChar(r *kmgGoReader.Reader) []byte { b := r.ReadByte() if b != '\'' { panic(r.GetFileLineInfo() + " unexcept byte " + strconv.Itoa(int(b))) } buf := &bytes.Buffer{} run := r.ReadRune() if run == '\\' { handleSlashInGoChar(r, buf) } else { buf.WriteRune(run) } b = r.ReadByte() if b != '\'' { panic(r.GetFileLineInfo() + " unexcept byte " + strconv.Itoa(int(b))) } return buf.Bytes() }
/* 第一个字符可能为 letter -> identifier(单独的类型名,带package的类型的package部分) "struct" struct类型开头 "func" func类型开头 "interface" interface类型开头 "*" 指针开头 "[" (数组,slice) 开头 "map[" map开头 "chan " chan开头 "chan<- " chan<- 开头 "<-chan" chan<- 开头 */ func (gofile *File) readType(r *kmgGoReader.Reader) Type { id := readIdentifier(r) if len(id) == 0 { if r.IsMatchAfter([]byte("<-chan")) { r.MustReadMatch([]byte("<-chan")) r.ReadAllSpace() return ChanType{ Dir: RecvDir, Elem: gofile.readType(r), } } b := r.ReadByte() if b == '*' { return PointerType{ Elem: gofile.readType(r), } } else if b == '[' { content := readMatchMiddleParantheses(r) if len(content) == 1 { return SliceType{ Elem: gofile.readType(r), } } else { // 仅跳过 return ArrayType{ Elem: gofile.readType(r), } } } else if b == '(' { typ := gofile.readType(r) r.MustReadMatch([]byte(")")) return typ } else { panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) } } if bytes.Equal(id, []byte("struct")) { return gofile.readStruct(r) } else if bytes.Equal(id, []byte("interface")) { // 仅跳过 r.ReadAllSpace() b := r.ReadByte() if b != '{' { panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) } readMatchBigParantheses(r) return InterfaceType{} } else if bytes.Equal(id, []byte("map")) { b := r.ReadByte() m := MapType{} if b != '[' { panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) } m.Key = gofile.readType(r) r.MustReadMatch([]byte("]")) m.Value = gofile.readType(r) return m } else if bytes.Equal(id, []byte("func")) { // 仅跳过 r.ReadAllSpace() b := r.ReadByte() if b != '(' { panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) } readMatchSmallParantheses(r) //跳过输入参数 r.ReadAllSpaceWithoutLineBreak() run := r.ReadRune() //跳过输出参数 if run == '(' { readMatchSmallParantheses(r) } else if run == '\n' { //换行符可以标识这个函数定义结束了. return FuncType{} } else if unicode.IsLetter(run) || run == '[' || run == '*' || run == '<' { r.UnreadRune() //输出参数只有一个类型 gofile.readType(r) } else { r.UnreadRune() //读到了其他东西,退回. } return FuncType{} } else if bytes.Equal(id, []byte("chan")) { if r.IsMatchAfter([]byte("<-")) { r.MustReadMatch([]byte("<-")) r.ReadAllSpace() return ChanType{ Dir: SendDir, Elem: gofile.readType(r), } } else { r.ReadAllSpace() return ChanType{ Dir: BothDir, Elem: gofile.readType(r), } } } else { b := r.ReadByte() if b == '.' { pkgPath := string(id) pkgPath, err := gofile.LookupFullPackagePath(pkgPath) if err != nil { fmt.Println(r.GetFileLineInfo(), err.Error()) //TODO 以目前的复杂度暂时无解.需要把所有相关的package都看一遍才能正确. } id2 := readIdentifier(r) return &NamedType{ PackagePath: pkgPath, Name: string(id2), Pkg: gofile.Pkg, } } else { r.UnreadByte() name := string(id) if builtinTypeMap[BuiltinType(name)] != Invalid { return BuiltinType(name) } else { return &NamedType{ PackagePath: gofile.PackagePath, Name: string(id), Pkg: gofile.Pkg, } } } } /* }else if r.IsMatchAfter([]byte("struct")) { //TODO 解决struct后面必须有一个空格的问题. r.ReadAllSpace() b := r.ReadByte() if b!='{' { panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) } readMatchBigParantheses(r) return StructType{} }else if r.IsMatchAfter([]byte("interface")) { r.ReadAllSpace() b := r.ReadByte() if b!='{' { panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) } readMatchBigParantheses(r) return InterfaceType{} }else if r.IsMatchAfter([]byte("map[")){ }else if r.IsMatchAfter([]byte("func")){ //TODO finish it. } */ }