【问题标题】:How to print hand-written AST?如何打印手写的 AST?
【发布时间】:2015-04-25 11:54:45
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

    不要忽略错误!

    添加:

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

    给出:“go/printer: unsupported node type 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

    【讨论】:

    • +1 仅用于第一行。很好,它也回答了这个问题,但是忽略错误是一个坏习惯。
    • 糟糕。并不是我知道printer.Fprint 返回错误并且我故意忽略它,而是我像fmt.Printf 一样使用它,通常不进行错误检查。愚蠢的问题,但感谢您的回答!为什么像打印这样简单的事情不起作用……
    猜你喜欢
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多