/
main.go
109 lines (101 loc) · 2.84 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// goparse parses Go source code. You may independently enable parser
// tracing, which yields a trace of parsed productions; and AST
// printing, which gives a lower-level view of the resultant AST. Both
// are ideal for programmer consumption and debugging, aiding in
// understanding the structure of Go programs as well as the behavior of
// the built-in parser library.
//
// If a positional argument is specified, it will be used as the input
// file. If no positional arguments are specified, the input will be
// read from standard in.
//
// There are other options as well that enable other parser
// functionality.
//
// usage: goparse [-h] [options] [file]
// -all-errors=false: report all errors (not just the first 10
// on different lines)
// -ast-print=false: print AST with ast.Fprint and no field filter
// -declaration-errors=false: report declaration errors
// -imports-only=false: stop parsing after import declarations
// -parse-comments=false: parse comments and add them to AST
// -trace=false: print a trace of parsed productions
//
// If both tracing and AST printing are enabled, the trace will precede
// AST output.
package main
import (
"flag"
"fmt"
"io"
"log"
"os"
"path"
"go/ast"
"go/parser"
"go/token"
)
var mode parser.Mode
var astPrint *bool
func init() {
log.SetFlags(0)
importsOnly := flag.Bool("imports-only", false,
"stop parsing after import declarations")
parseComments := flag.Bool("parse-comments", false,
"parse comments and add them to AST")
trace := flag.Bool("trace", false,
"print a trace of parsed productions")
declarationErrors := flag.Bool("declaration-errors", false,
"report declaration errors")
allErrors := flag.Bool("all-errors", false,
"report all errors (not just the first 10 on different lines)")
astPrint = flag.Bool("ast-print", false,
"print AST with ast.Fprint and no field filter")
flag.Parse()
if (*importsOnly) {
mode |= parser.ImportsOnly
}
if (*parseComments) {
mode |= parser.ParseComments
}
if (*trace) {
mode |= parser.Trace
}
if (*declarationErrors) {
mode |= parser.DeclarationErrors
}
if (*allErrors) {
mode |= parser.AllErrors
}
}
func main() {
var filename string
var src io.Reader
var err error
var astfile *ast.File
fargs := flag.Args()
if len(fargs) == 0 {
filename = "-"
src = os.Stdin
} else if len(fargs) == 1 {
filename = fargs[0]
src, err = os.Open(filename)
if err != nil {
log.Fatal(err)
}
} else {
fmt.Printf("usage: %s [-h] [options] [file]\n", path.Base(os.Args[0]))
os.Exit(2)
}
fset := token.NewFileSet()
astfile, err = parser.ParseFile(fset, filename, src, mode)
if err != nil {
log.Fatal(err)
}
if *astPrint {
err = ast.Fprint(os.Stdout, fset, astfile, nil)
if err != nil {
log.Fatal(err)
}
}
}