Beispiel #1
0
// 可以读 '"' 这种,返回这个东西实际占的字节数据
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()
}
Beispiel #2
0
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的东西留个调用者处理
		}
	}
}
Beispiel #3
0
func readMatchChar(r *kmgGoReader.Reader, starter byte, ender byte) []byte {
	startPos := r.Pos()
	level := 1
	for {
		if r.IsEof() {
			panic(r.GetFileLineInfo() + " unexcept EOF")
		}
		b := r.ReadByte()
		if b == '"' || b == '`' {
			r.UnreadByte()
			MustReadGoString(r)
		} else if b == '\'' {
			r.UnreadByte()
			mustReadGoChar(r)
		} else if b == starter {
			level++
		} else if b == ender {
			level--
			if level == 0 {
				return r.BufToCurrent(startPos)
			}
		}
	}
}
Beispiel #4
0
// 此处已经读过了 /
func handleSlashInGoChar(r *kmgGoReader.Reader, buf *bytes.Buffer) {
	if r.IsEof() {
		panic(r.GetFileLineInfo() + " unexcept EOF")
	}
	b := r.ReadByte()
	switch b {
	case '0', '1', '2', '3', '4', '5', '6', '7':
		r.UnreadByte()
		octal := r.MustReadWithSize(3)
		b64, err := strconv.ParseUint(string(octal), 8, 8)
		if err != nil {
			panic(r.GetFileLineInfo() + " " + err.Error())
		}
		buf.WriteByte(byte(b64))
	case 'x':
		octal := r.MustReadWithSize(2)
		b64, err := strconv.ParseUint(string(octal), 16, 8)
		if err != nil {
			panic(r.GetFileLineInfo() + " " + err.Error())
		}
		buf.WriteByte(byte(b64))
	case 'u':
		octal := r.MustReadWithSize(4)
		b64, err := strconv.ParseUint(string(octal), 16, 16)
		if err != nil {
			panic(r.GetFileLineInfo() + " " + err.Error())
		}
		buf.WriteRune(rune(b64))
	case 'U':
		octal := r.MustReadWithSize(8)
		b64, err := strconv.ParseUint(string(octal), 16, 32)
		if err != nil {
			panic(r.GetFileLineInfo() + " " + err.Error())
		}
		buf.WriteRune(rune(b64))
	case 'a':
		buf.WriteByte('\a')
	case 'b':
		buf.WriteByte('\b')
	case 'f':
		buf.WriteByte('\f')
	case 'n':
		buf.WriteByte('\n')
	case 'r':
		buf.WriteByte('\r')
	case 't':
		buf.WriteByte('\t')
	case 'v':
		buf.WriteByte('\v')
	case '\\':
		buf.WriteByte('\\')
	case '\'':
		buf.WriteByte('\'')
	case '"':
		buf.WriteByte('"')
	default:
		panic(r.GetFileLineInfo() + " unexcept byte " + strconv.Itoa(int(b)))
	}
}
Beispiel #5
0
// 可以读这两种 "abc" `abc` ,返回这个东西实际存放的信息.
func MustReadGoString(r *kmgGoReader.Reader) (output []byte) {
	b := r.ReadByte()
	if b == '"' {
		buf := &bytes.Buffer{}
		for {
			if r.IsEof() {
				panic(r.GetFileLineInfo() + " unexcept EOF " + buf.String())
			}
			b := r.ReadByte()
			switch b {
			case '"':
				return buf.Bytes()
			case '\\':
				handleSlashInGoChar(r, buf)
			default:
				buf.WriteByte(b)
			}
		}
	} else if b == '`' {
		return r.ReadUntilByte('`')
	} else {
		panic(fmt.Errorf("%s unexcept byte %d '%s'", r.GetFileLineInfo(), b, string(rune(b))))
	}
}
Beispiel #6
0
func (gofile *File) readParameters(r *kmgGoReader.Reader) (output []FuncParameter) {

	b := r.ReadByte()
	if b != '(' {
		// 处理 int 这种类型
		r.UnreadByte()
		return []FuncParameter{
			{
				Type: gofile.readType(r),
			},
		}
	}
	parameterPartList := []*astParameterPart{}
	lastPart := &astParameterPart{}
	for {
		r.ReadAllSpace()
		b := r.ReadByte()
		if b == ')' || b == ',' {
			if lastPart.partList[0].originByte != nil {
				parameterPartList = append(parameterPartList, lastPart)
				lastPart = &astParameterPart{}
			}
			if b == ')' {
				break
			}
			if b == ',' {
				continue
			}
		}

		r.UnreadByte()
		if r.IsMatchAfter([]byte("...")) {
			r.MustReadMatch([]byte("..."))
			lastPart.isVariadic = true
		}
		startPos := r.Pos()
		typ := gofile.readType(r)
		buf := r.BufToCurrent(startPos)
		//fmt.Println(string(buf))
		hasSet := false
		for i := range lastPart.partList {
			if lastPart.partList[i].originByte == nil {
				lastPart.partList[i].originByte = buf
				lastPart.partList[i].typ = typ
				hasSet = true
				break
			}
		}
		if !hasSet {
			panic(r.GetFileLineInfo() + " unexcept func parameterList.")
		}
	}

	output = make([]FuncParameter, len(parameterPartList))
	onlyHavePart1Num := 0
	for i := range parameterPartList {
		if parameterPartList[i].partList[1].originByte == nil {
			onlyHavePart1Num++
		}
	}
	//重新分析出函数参数来. 处理(int,int) 这种类型.
	if onlyHavePart1Num == len(parameterPartList) {
		for i := range parameterPartList {
			output[i].Type = parameterPartList[i].partList[0].typ
			output[i].IsVariadic = parameterPartList[i].isVariadic
		}
		return output
	}
	// 处理 (x,y int) (x int,y int) 这种类型.
	for i, parameterPart := range parameterPartList {
		output[i].Name = string(parameterPart.partList[0].originByte)
		if parameterPart.partList[1].typ != nil {
			output[i].Type = parameterPart.partList[1].typ
		}
		output[i].IsVariadic = parameterPart.isVariadic
	}
	// 补全 (x,y int) 里面 x的类型.
	for i := range parameterPartList {
		if output[i].Type == nil {
			for j := i + 1; j < len(parameterPartList); j++ {
				if output[j].Type != nil {
					output[i].Type = output[j].Type
				}
			}
		}
	}
	return output
}
Beispiel #7
0
// 此处仅跳过函数
func (gofile *File) readGoFunc(r *kmgGoReader.Reader) *FuncOrMethodDeclaration {
	funcDecl := &FuncOrMethodDeclaration{}
	r.MustReadMatch([]byte("func"))
	// 读函数头,至少要有括号
	r.ReadAllSpace()
	b := r.ReadByte()
	if b == '(' {
		r.UnreadByte()
		receiver := gofile.readParameters(r)
		if len(receiver) != 1 {
			panic(fmt.Errorf("%s receiver must have one parameter", r.GetFileLineInfo()))
		}
		funcDecl.ReceiverType = receiver[0].Type
		r.ReadAllSpace()
		// 暂不处理方法
	} else {
		r.UnreadByte()
	}
	id := readIdentifier(r)
	funcDecl.Name = string(id)
	if funcDecl.Name == "" {
		panic(fmt.Errorf("%s need function name", r.GetFileLineInfo()))
	}
	r.ReadAllSpace()
	b = r.ReadByte()
	if b != '(' {
		panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b))))
	}
	r.UnreadByte()
	funcDecl.InParameter = gofile.readParameters(r)
	r.ReadAllSpaceWithoutLineBreak()
	b = r.ReadByte()
	if b == '\n' { //没有body
		return funcDecl
	} else if b != '{' {
		r.UnreadByte()
		funcDecl.OutParameter = gofile.readParameters(r)
		r.ReadAllSpaceWithoutLineBreak()
		b = r.ReadByte()
	}
	if b == '\n' { //没有body
		return funcDecl
	}
	if b != '{' {
		panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b))))
	}

	//跳过函数体
	readMatchBigParantheses(r)
	return funcDecl
}
Beispiel #8
0
/*
第一个字符可能为
	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.
		}
	*/
}
Beispiel #9
0
func (gofile *File) readStruct(r *kmgGoReader.Reader) StructType {
	// 仅跳过
	r.ReadAllSpace()
	b := r.ReadByte()
	if b != '{' {
		panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b))))
	}
	lastReadBuf := []bytesAndType{}
	var lastTag []byte
	out := StructType{}
	for {
		r.ReadAllSpaceWithoutLineBreak()
		b := r.ReadByte()
		if b == '}' {
			return out
		} else if b == '"' || b == '\'' || b == '`' {
			r.UnreadByte()
			lastTag = MustReadGoString(r)
		} else if b == ',' {
			continue
		} else if b == '\n' {
			if len(lastReadBuf) == 0 {
				continue
			} else if len(lastReadBuf) == 1 {
				typ := lastReadBuf[0].typ
				name := getTypeStructAnonymousName(typ)
				out.Field = append(out.Field, StructField{
					Name:             name,
					Elem:             typ,
					IsAnonymousField: true,
					Tag:              string(lastTag),
				})
				lastReadBuf = []bytesAndType{}
			} else if len(lastReadBuf) >= 2 {
				typ := lastReadBuf[len(lastReadBuf)-1].typ
				for i := range lastReadBuf[:len(lastReadBuf)-1] {
					out.Field = append(out.Field, StructField{
						Name:             string(lastReadBuf[i].originByte),
						Elem:             typ,
						IsAnonymousField: false,
						Tag:              string(lastTag),
					})
				}
				lastReadBuf = []bytesAndType{}
			}
		} else {
			r.UnreadByte()
			startPos := r.Pos()
			typ := gofile.readType(r)
			lastReadBuf = append(lastReadBuf, bytesAndType{
				originByte: r.BufToCurrent(startPos),
				typ:        typ,
			})
		}
	}
}
Beispiel #10
0
// 此处暂时仅跳过该部分
func (gofile *File) readGoType(r *kmgGoReader.Reader) {
	r.MustReadMatch([]byte("type"))
	r.ReadAllSpace()
	b := r.ReadByte()
	if b == '(' {
		for {
			r.ReadAllSpace()
			b = r.ReadByte()
			if b == ')' {
				return
			}
			r.UnreadByte()
			name := readIdentifier(r)
			r.ReadAllSpace()
			typ := gofile.readType(r)
			gofile.NamedTypeList = append(gofile.NamedTypeList, &NamedType{
				PackagePath: gofile.PackagePath,
				Name:        string(name),
				underType:   typ,
			})
		}
		return
	} else {
		r.UnreadByte()
		name := readIdentifier(r)
		r.ReadAllSpace()
		typ := gofile.readType(r)
		gofile.NamedTypeList = append(gofile.NamedTypeList, &NamedType{
			PackagePath: gofile.PackagePath,
			Name:        string(name),
			underType:   typ,
		})
		return
	}
}
Beispiel #11
0
// 正确跳过该部分.
func (gofile *File) readGoVar(r *kmgGoReader.Reader) {
	r.MustReadMatch([]byte("var"))
	r.ReadAllSpace()
	b := r.ReadByte()
	if b == '(' {
		readMatchSmallParantheses(r)
		return
	}
	r.UnreadByte()
	readIdentifier(r)
	r.ReadAllSpace()
	b = r.ReadByte()
	if b == '=' {
		r.ReadAllSpace()
	}
	for {
		if b == '"' || b == '`' {
			r.UnreadByte()
			MustReadGoString(r)
		}
		if b == '\'' {
			r.UnreadByte()
			mustReadGoChar(r)
		}
		if b == '\n' {
			return
		}
		if b == '{' { //里面可以字面写东西.
			readMatchBigParantheses(r)
			//TODO 正确跳过该部分
			/*
							简单解决下列情况
							var UnreadRuneErrorTests = []struct {
					name string
					f    func(*Reader)
				}{
					{"Read", func(r *Reader) { r.Read([]byte{0}) }},
					{"ReadByte", func(r *Reader) { r.ReadByte() }},
					{"UnreadRune", func(r *Reader) { r.UnreadRune() }},
					{"Seek", func(r *Reader) { r.Seek(0, 1) }},
					{"WriteTo", func(r *Reader) { r.WriteTo(&Buffer{}) }},
				}

			*/
		}
		if b == '(' { //里面可以调用函数
			readMatchSmallParantheses(r)
		}
		if r.IsEof() {
			return
		}
		b = r.ReadByte()
	}
}
Beispiel #12
0
// 正确跳过该部分.
func (gofile *File) readGoConst(r *kmgGoReader.Reader) {
	r.MustReadMatch([]byte("const"))
	r.ReadAllSpace()
	b := r.ReadByte()
	if b == '(' {
		readMatchSmallParantheses(r)
		return
	}
	for {
		if b == '"' || b == '`' {
			r.UnreadByte()
			MustReadGoString(r)
		}
		if b == '\'' {
			r.UnreadByte()
			mustReadGoChar(r)
		}
		if b == '\n' {
			return
		}
		b = r.ReadByte()
	}
}
Beispiel #13
0
// 读取一个import语法里面的数据,此处从import关键词开始
func (gofile *File) readImport(r *kmgGoReader.Reader) {
	r.MustReadMatch([]byte("import"))
	r.ReadAllSpace()
	if r.IsEof() {
		panic(r.GetFileLineInfo() + " unexcept EOF ")
	}
	b := r.ReadByte()
	if b == '(' {
		for {
			r.ReadAllSpace()
			b := r.ReadByte()
			if b == ')' {
				return
			} else {
				r.UnreadByte()
				gofile.readImportSpec(r)
			}
		}
	} else {
		r.UnreadByte()
		gofile.readImportSpec(r)
	}
}
Beispiel #14
0
// 此处暂时只保留路径,其他数据抛弃.
func (gofile *File) readImportSpec(r *kmgGoReader.Reader) {
	r.ReadAllSpace()
	b := r.ReadByte()
	//fmt.Println(b,string(rune(b)))
	if b == '"' || b == '`' {
		r.UnreadByte()
		gofile.AddImport(string(MustReadGoString(r)), "")
	} else if b == '.' {
		r.ReadAllSpace()
		gofile.AddImport(string(MustReadGoString(r)), ".")
	} else {
		r.UnreadByte()
		alias := readIdentifier(r)
		r.ReadAllSpace()
		gofile.AddImport(string(MustReadGoString(r)), string(alias))
	}
}