Go高级解析器开发求助:提取核心代码块与函数体
Go代码核心块解析器优化方案
针对你开发Go高级解析器时遇到的导入解析、函数体边界识别、原始格式保留等问题,结合你基于participle的实现,给出以下针对性改进建议:
1. 修复函数体捕获逻辑的边界问题
当前FuncBody.Parse方法存在起始位置未跳过外层{、未处理EOF场景的问题,修改后确保正确识别嵌套{}并完整保留原始格式:
func (f *FuncBody) Parse(lex *lexer.PeekingLexer) error { count := 1 // 初始为1,已匹配到外层{ start := lex.RawCursor() for { tok := lex.Peek() if tok.Kind == lexer.EOF { return fmt.Errorf("unclosed function body") } switch tok.Value { case "{": count++ case "}": count-- if count == 0 { // 截取到当前}之前的内容 end := lex.RawCursor() tokens := lex.Range(start, end) for _, t := range tokens { f.Body += t.Value } lex.Next() // 跳过当前的} return nil } } lex.Next() } }
同时调整FuncDef的解析标签,让外层{由解析器匹配,函数体只捕获内部内容:
type FuncDef struct { Name string `parser:"@Ident '('"` Args []FuncArg `parser:"(@@ (',' @@)* )? ')'"` ReturnDef *FuncReturnDef `parser:"@@?"` Body *FuncBody `parser:"'{' @@"` // 去掉末尾的'}',由FuncBody处理闭合 }
2. 完善导入语句的解析规则
当前解析逻辑无法区分单行导入和块级导入,修改结构支持两种导入形式:
type GoFile struct { PackageName string `parser:"'package' @Ident"` Imports []ImportStmt `parser:"@@*"` // 支持多个单行/块级导入 Decls []Declaration`parser:"@@*"` } type ImportStmt struct { Single *ImportDef `parser:"'import' @@"` Block []ImportDef `parser:"| 'import' '(' @@+ ')'"` } type ImportDef struct { Alias string `parser:"@Ident?"` Path string `parser:"@String"` }
3. 补全类型定义的解析
恢复并扩展TypeDef结构,支持结构体、接口、基本类型等常见类型声明:
type Declaration struct { Func *FuncDef `parser:"'func' @@"` Type *TypeDef `parser:"| 'type' @@"` } type TypeDef struct { Name string `parser:"@Ident"` Def TypeDefinition `parser:"@@"` } type TypeDefinition struct { BasicType string `parser:"@Ident"` Struct *StructDef `parser:"| 'struct' '{' @@* '}'"` Interface *InterfaceDef `parser:"| 'interface' '{' @@* '}'"` // 可扩展指针、切片、映射等复合类型 } type StructDef struct { Fields []StructField `parser:"@@*"` } type StructField struct { Name string `parser:"@Ident"` Type string `parser:"@Ident"` } type InterfaceDef struct { Methods []InterfaceMethod `parser:"@@*"` } type InterfaceMethod struct { Name string `parser:"@Ident '(' ')'"` Ret string `parser:"@Ident?"` }
4. 修复函数参数与返回值的解析缺陷
当前无法处理复合类型和多返回值,调整解析规则支持更复杂的函数签名:
type FuncArg struct { Name string `parser:"@Ident?"` // 支持匿名参数 Type string `parser:"@(Ident | 'chan' '<'? '>'? Ident | '[]' Ident | '*' Ident)"` } type FuncReturnDef struct { SingleType string `parser:"@Ident"` MultiTypes []string `parser:"| '(' (@Ident (',' @Ident)*) ')'"` NamedReturns []NamedReturn `parser:"| '(' (@Ident @Ident (',' @Ident @Ident)*) ')'"` } type NamedReturn struct { Name string `parser:"@Ident"` Type string `parser:"@Ident"` }
5. 保留原始空白符与换行的优化
移除participle.Elide("Whitespace", "EOL")避免丢失格式,在需要忽略空白的解析点手动添加(Whitespace)*规则,例如:
type GoFile struct { PackageName string `parser:"'package' (Whitespace)* @Ident"` Imports []ImportStmt `parser:"@@*"` Decls []Declaration`parser:"@@*"` }
确保词法分析器保留Whitespace和EOL类型,让函数体捕获完整的原始格式内容。
测试补充
针对多返回值、复合类型参数、嵌套函数体等场景补充测试用例,覆盖边界情况:
{ name: "function with named returns", src: `package main func Split(s string) (first, second string) { first = s[:1] second = s[1:] return }`, wantPackage: "main", wantDecls: []Declaration{ { Func: &FuncDef{ Name: "Split", Args: []FuncArg{{Name: "s", Type: "string"}}, ReturnDef: &FuncReturnDef{ NamedReturns: []NamedReturn{{Name: "first", Type: "string"}, {Name: "second", Type: "string"}}, }, Body: &FuncBody{Body: ` first = s[:1] second = s[1:] return `}, }, }, }, }
内容的提问来源于stack exchange,提问作者Julia Carmack
相关产品推荐
相关产品推荐

