Package Go of Go

The standard library of Go contains a package named go, which
contains sub-packages that are capable of parsing and manipulating Go
source files. The well-known tool fmt in Go toolchain is
implemented using this pacakge. This makes me thinking about
libclang which was developed for parsing C source files. This
article is my learning note about these Go packages.

go/token

As the very basic elements in source code files are tokens, I started
from learning the package go/token. The very important
concepts/types in this package include FileSet, which contains a
sequence of Files in the order that they were added to the fileset.
An empty FileSet has base offset 1. After adding a file with size
100, the base offset becomes 1+100+1=102. The following program shows
how to add a file into a fileset.

package main

import (
    "fmt"
    "go/token"
    "os"
)

const (
    FILE = "learn-ast.go"
)

func main() {
    fset := token.NewFileSet()
    fmt.Println("The initial base of an fset is ", fset.Base())

    if f, e := os.Open(FILE); e == nil {
        if fi, e := f.Stat(); e == nil {
            fset.AddFile("learn-ast.go", fset.Base(), int(fi.Size()))
            fmt.Println("After adding file ", FILE,
                ", the base becomes ", fset.Base())
        }
    }
}

go/parser and go/ast

The following sample program shows how to invoke package go/parser
to parse itself to generate the Abstract Semantic Tree (AST):

package main

import (
    "fmt"
    "go/parser"
    "go/token"
    "go/ast"
)

const (
    FILE = "learn-parser.go"
)

func main() {
    fset := token.NewFileSet()
    if f, err := parser.ParseFile(fset, FILE, nil, 0); err == nil {
        ast.Print(fset, f)
    } else {
        fmt.Println(err)
    }
}