llcppsymg:improve parsing process

This commit is contained in:
luoliwoshang
2024-08-08 14:14:20 +08:00
parent 4b0cfc0751
commit fe5de95008
2 changed files with 90 additions and 148 deletions

View File

@@ -3,23 +3,27 @@ package parse
import (
"errors"
"strconv"
"strings"
"unsafe"
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/c/clang"
"github.com/goplus/llgo/chore/llcppg/types"
)
type Context struct {
namespaceName string
className string
astInfo []types.ASTInformation
prefixes []string
symbolMap map[string]string
currentFile string
nameCounts map[string]int
}
func newContext() *Context {
func newContext(prefixes []string) *Context {
return &Context{
astInfo: make([]types.ASTInformation, 0),
prefixes: prefixes,
symbolMap: make(map[string]string),
nameCounts: make(map[string]int),
}
}
@@ -35,70 +39,83 @@ func (c *Context) setCurrentFile(filename string) {
c.currentFile = filename
}
var context = newContext()
func (c *Context) removePrefix(str string) string {
for _, prefix := range c.prefixes {
if strings.HasPrefix(str, prefix) {
return strings.TrimPrefix(str, prefix)
}
}
return str
}
func collectFuncInfo(cursor clang.Cursor) types.ASTInformation {
func (c *Context) genGoName(name string) string {
class := c.removePrefix(c.className)
name = c.removePrefix(name)
info := types.ASTInformation{
Namespace: context.namespaceName,
Class: context.className,
var baseName string
if class == "" {
baseName = name
} else {
baseName = c.genMethodName(class, name)
}
return c.addSuffix(baseName)
}
func (c *Context) genMethodName(class, name string) string {
prefix := "(*" + class + ")."
if class == name {
return prefix + "Init"
}
if name == "~"+class {
return prefix + "Dispose"
}
return prefix + name
}
func (c *Context) addSuffix(name string) string {
c.nameCounts[name]++
count := c.nameCounts[name]
if count > 1 {
return name + "__" + strconv.Itoa(count-1)
}
return name
}
var context = newContext([]string{})
func collectFuncInfo(cursor clang.Cursor) {
cursorStr := cursor.String()
symbol := cursor.Mangling()
info.Name = c.GoString(cursorStr.CStr())
info.Symbol = c.GoString(symbol.CStr())
if len(info.Symbol) >= 1 {
if info.Symbol[0] == '_' {
info.Symbol = info.Symbol[1:]
}
name := c.GoString(cursorStr.CStr())
symbolName := c.GoString(symbol.CStr())
if len(symbolName) >= 1 && symbolName[0] == '_' {
symbolName = symbolName[1:]
}
defer symbol.Dispose()
defer cursorStr.Dispose()
if context.namespaceName != "" {
info.Namespace = context.namespaceName
}
if context.className != "" {
info.Class = context.className
}
typeStr := cursor.ResultType().String()
defer typeStr.Dispose()
info.ReturnType = c.GoString(typeStr.CStr())
info.Parameters = make([]types.Parameter, cursor.NumArguments())
for i := 0; i < int(cursor.NumArguments()); i++ {
argCurSor := cursor.Argument(c.Uint(i))
argType := argCurSor.Type().String()
argName := argCurSor.String()
info.Parameters[i] = types.Parameter{
Name: c.GoString(argName.CStr()),
Type: c.GoString(argType.CStr()),
}
argType.Dispose()
argName.Dispose()
}
return info
goName := context.genGoName(name)
context.symbolMap[symbolName] = goName
}
func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitResult {
if cursor.Kind == clang.Namespace {
if cursor.Kind == clang.CursorNamespace {
nameStr := cursor.String()
defer nameStr.Dispose()
context.setNamespaceName(c.GoString(nameStr.CStr()))
clang.VisitChildren(cursor, visit, nil)
context.setNamespaceName("")
} else if cursor.Kind == clang.ClassDecl {
} else if cursor.Kind == clang.CursorClassDecl {
nameStr := cursor.String()
defer nameStr.Dispose()
context.setClassName(c.GoString(nameStr.CStr()))
clang.VisitChildren(cursor, visit, nil)
context.setClassName("")
} else if cursor.Kind == clang.CXXMethod || cursor.Kind == clang.FunctionDecl || cursor.Kind == clang.Constructor || cursor.Kind == clang.Destructor {
} else if cursor.Kind == clang.CursorCXXMethod || cursor.Kind == clang.CursorFunctionDecl || cursor.Kind == clang.CursorConstructor || cursor.Kind == clang.CursorDestructor {
loc := cursor.Location()
var file clang.File
var line, column c.Uint
@@ -107,9 +124,7 @@ func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitRe
filename := file.FileName()
if c.Strcmp(filename.CStr(), c.AllocaCStr(context.currentFile)) == 0 {
info := collectFuncInfo(cursor)
info.Location = c.GoString(filename.CStr()) + ":" + strconv.Itoa(int(line)) + ":" + strconv.Itoa(int(column))
context.astInfo = append(context.astInfo, info)
collectFuncInfo(cursor)
}
defer filename.Dispose()
@@ -118,14 +133,13 @@ func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitRe
return clang.ChildVisit_Continue
}
func ParseHeaderFile(filepaths []string) ([]types.ASTInformation, error) {
func ParseHeaderFile(filepaths []string, prefixes []string) (map[string]string, error) {
index := clang.CreateIndex(0, 0)
args := make([]*c.Char, 3)
args[0] = c.Str("-x")
args[1] = c.Str("c++")
args[2] = c.Str("-std=c++11")
context = newContext()
context = newContext(prefixes)
for _, filename := range filepaths {
unit := index.ParseTranslationUnit(
@@ -149,5 +163,5 @@ func ParseHeaderFile(filepaths []string) ([]types.ASTInformation, error) {
index.Dispose()
return context.astInfo, nil
return context.symbolMap, nil
}