如何打印手写AST?

时间:2015-02-24 00:04:46

标签: go code-generation abstract-syntax-tree

我有一组网络协议的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?

1 个答案:

答案 0 :(得分:4)

不要忽视错误!

添加:

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

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

printer.Fprint的最后一个参数是interface{},所以编译器接受任何东西。但是,就像parser.ParseFile返回*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