Files
llgo/chore/_xtool/llcppsymg/parse/parse.go

154 lines
3.5 KiB
Go
Raw Normal View History

package parse
2024-07-26 13:45:08 +08:00
import (
"errors"
2024-07-26 13:45:08 +08:00
"strconv"
"unsafe"
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/c/clang"
"github.com/goplus/llgo/chore/llcppg/types"
2024-07-26 13:45:08 +08:00
)
type Context struct {
namespaceName string
className string
2024-07-29 11:21:36 +08:00
astInfo []types.ASTInformation
currentFile string
2024-07-26 13:45:08 +08:00
}
func newContext() *Context {
return &Context{
2024-07-29 11:21:36 +08:00
astInfo: make([]types.ASTInformation, 0),
2024-07-26 13:45:08 +08:00
}
}
func (c *Context) setNamespaceName(name string) {
c.namespaceName = name
}
func (c *Context) setClassName(name string) {
c.className = name
}
func (c *Context) setCurrentFile(filename string) {
2024-07-26 17:09:26 +08:00
c.currentFile = filename
2024-07-26 15:56:47 +08:00
}
2024-07-26 13:45:08 +08:00
var context = newContext()
2024-07-29 11:21:36 +08:00
func collectFuncInfo(cursor clang.Cursor) types.ASTInformation {
2024-07-26 15:56:47 +08:00
2024-07-29 11:21:36 +08:00
info := types.ASTInformation{
2024-07-26 13:45:08 +08:00
Namespace: context.namespaceName,
Class: context.className,
}
cursorStr := cursor.String()
symbol := cursor.Mangling()
info.Name = c.GoString(cursorStr.CStr())
2024-07-26 14:37:26 +08:00
2024-07-26 13:45:08 +08:00
info.Symbol = c.GoString(symbol.CStr())
2024-07-26 14:37:26 +08:00
if len(info.Symbol) >= 1 {
if info.Symbol[0] == '_' {
info.Symbol = info.Symbol[1:]
}
}
2024-07-26 13:45:08 +08:00
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())
2024-07-29 11:21:36 +08:00
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()
2024-07-29 11:21:36 +08:00
info.Parameters[i] = types.Parameter{
Name: c.GoString(argName.CStr()),
Type: c.GoString(argType.CStr()),
2024-07-26 13:45:08 +08:00
}
argType.Dispose()
argName.Dispose()
2024-07-26 13:45:08 +08:00
}
return info
}
func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitResult {
if cursor.Kind == clang.Namespace {
nameStr := cursor.String()
context.setNamespaceName(c.GoString(nameStr.CStr()))
clang.VisitChildren(cursor, visit, nil)
context.setNamespaceName("")
} else if cursor.Kind == clang.ClassDecl {
nameStr := cursor.String()
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 {
2024-07-26 15:56:47 +08:00
loc := cursor.Location()
var file clang.File
var line, column c.Uint
loc.SpellingLocation(&file, &line, &column, nil)
filename := file.FileName()
if c.Strcmp(filename.CStr(), c.AllocaCStr(context.currentFile)) == 0 {
2024-07-26 15:56:47 +08:00
info := collectFuncInfo(cursor)
info.Location = c.GoString(filename.CStr()) + ":" + strconv.Itoa(int(line)) + ":" + strconv.Itoa(int(column))
context.astInfo = append(context.astInfo, info)
}
defer filename.Dispose()
2024-07-26 13:45:08 +08:00
}
return clang.ChildVisit_Continue
}
func ParseHeaderFile(filepaths []string) ([]types.ASTInformation, error) {
2024-07-26 13:45:08 +08:00
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()
2024-07-26 13:45:08 +08:00
for _, filename := range filepaths {
2024-07-26 17:09:26 +08:00
unit := index.ParseTranslationUnit(
c.AllocaCStr(filename),
2024-07-26 17:09:26 +08:00
unsafe.SliceData(args), 3,
nil, 0,
clang.TranslationUnit_None,
)
if unit == nil {
return nil, errors.New("Unable to parse translation unit for file " + filename)
2024-07-26 17:09:26 +08:00
}
2024-07-26 13:45:08 +08:00
2024-07-26 17:09:26 +08:00
cursor := unit.Cursor()
context.setCurrentFile(filename)
clang.VisitChildren(cursor, visit, nil)
unit.Dispose()
}
2024-07-26 13:45:08 +08:00
index.Dispose()
return context.astInfo, nil
2024-07-26 13:45:08 +08:00
}