dsc56927
2015-02-24 00:04
浏览 34
已采纳

如何打印手写AST?

I have a set of XML description of network protocol that I'm trying to generate Go code from, therefore I don't have any existing Go code to work with. All of the examples that make use of go/ast (such as go fmt) take existing code, do some transformation on the AST, then write them back out. Since all I have are XML files, the AST that I'm working with have to be written by hand. The problem is that I cannot get my hand-written AST to output.

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)
}

Expected output:

package foo

type Bar uint32

Actual output: nothing

How do I get the AST to print?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dongshuang0011 2015-02-24 03:38
    已采纳

    Don't ignore errors!

    Adding:

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

    Gives: "go/printer: unsupported node type ast.File" which should have been enough to point you in the right direction.

    printer.Fprint's last argument is interface{} so the compiler accepts anything. However, just as parser.ParseFile returns an *ast.File (rather than ast.File) it expects a pointer to a node.

    Passing a pointer gives the output you want (note the &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

    点赞 打赏 评论

相关推荐 更多相似问题