如何打印手写的AST?

How to print hand-written AST?

我有一组 XML 网络协议描述,我试图从中生成 Go 代码,因此我没有任何现有的 Go 代码可以使用。所有使用 go/ast 的示例(例如 go fmt)都采用现有代码,对 AST 进行一些转换,然后将它们写回。因为我只有 XML 个文件,所以我正在使用的 AST 必须手写。问题是我手写的AST无法输出。

Example

package main

import (
    "go/ast"
    "go/printer"
    "go/token"
    "os"
)

func main() {
    f := ast.File{
        Name: ast.NewIdent("foo"),
        Decls: []ast.Decl{
            &ast.GenDecl{
                Tok: token.TYPE,
                Specs: []ast.Spec{
                    &ast.TypeSpec{
                        Name: ast.NewIdent("Bar"),
                        Type: ast.NewIdent("uint32"),
                    },
                },
            },
        },
    }
    fset := token.NewFileSet()
    printer.Fprint(os.Stdout, fset, f)
}

预期输出:

package foo

type Bar uint32

实际输出:无

如何打印 AST?

不要忽略错误!

添加:

err := printer.Fprint(os.Stdout, fset, f)
if err != nil {
    log.Fatal(err)
}

给出:“go/printer:不支持的节点类型 ast.File”这应该足以为您指明正确的方向。

printer.Fprint's last argument is interface{} so the compiler accepts anything. However, just as parser.ParseFile returns 一个 *ast.File (而不是 ast.File)它需要一个指向节点的指针。

传递一个指针给出你想要的输出(注意&ast.File):

package main

import (
    "go/ast"
    "go/printer"
    "go/token"
    "log"
    "os"
)

func main() {
    f := &ast.File{
        Name: ast.NewIdent("foo"),
        Decls: []ast.Decl{
            &ast.GenDecl{
                Tok: token.TYPE,
                Specs: []ast.Spec{
                    &ast.TypeSpec{
                        Name: ast.NewIdent("Bar"),
                        Type: ast.NewIdent("uint32"),
                    },
                },
            },
        },
    }
    fset := token.NewFileSet()
    err := printer.Fprint(os.Stdout, fset, f)
    if err != nil {
        log.Fatal(err)
    }
}

playground