1
2
3
4
5
6
7 package parser
8
9 import (
10 "bytes"
11 "go/ast"
12 "go/scanner"
13 "go/token"
14 "io"
15 "io/ioutil"
16 "os"
17 "path/filepath"
18 )
19
20
21
22
23
24 func readSource(filename string, src interface{}) ([]byte, os.Error) {
25 if src != nil {
26 switch s := src.(type) {
27 case string:
28 return []byte(s), nil
29 case []byte:
30 return s, nil
31 case *bytes.Buffer:
32
33 if s != nil {
34 return s.Bytes(), nil
35 }
36 case io.Reader:
37 var buf bytes.Buffer
38 _, err := io.Copy(&buf, s)
39 if err != nil {
40 return nil, err
41 }
42 return buf.Bytes(), nil
43 default:
44 return nil, os.NewError("invalid source")
45 }
46 }
47
48 return ioutil.ReadFile(filename)
49 }
50
51 func (p *parser) errors() os.Error {
52 mode := scanner.Sorted
53 if p.mode&SpuriousErrors == 0 {
54 mode = scanner.NoMultiples
55 }
56 return p.GetError(mode)
57 }
58
59
60
61
62
63
64 func ParseExpr(fset *token.FileSet, filename string, src interface{}) (ast.Expr, os.Error) {
65 data, err := readSource(filename, src)
66 if err != nil {
67 return nil, err
68 }
69
70 var p parser
71 p.init(fset, filename, data, 0)
72 x := p.parseRhs()
73 if p.tok == token.SEMICOLON {
74 p.next()
75 }
76 p.expect(token.EOF)
77
78 return x, p.errors()
79 }
80
81
82
83
84
85
86 func ParseStmtList(fset *token.FileSet, filename string, src interface{}) ([]ast.Stmt, os.Error) {
87 data, err := readSource(filename, src)
88 if err != nil {
89 return nil, err
90 }
91
92 var p parser
93 p.init(fset, filename, data, 0)
94 list := p.parseStmtList()
95 p.expect(token.EOF)
96
97 return list, p.errors()
98 }
99
100
101
102
103
104
105 func ParseDeclList(fset *token.FileSet, filename string, src interface{}) ([]ast.Decl, os.Error) {
106 data, err := readSource(filename, src)
107 if err != nil {
108 return nil, err
109 }
110
111 var p parser
112 p.init(fset, filename, data, 0)
113 list := p.parseDeclList()
114 p.expect(token.EOF)
115
116 return list, p.errors()
117 }
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 func ParseFile(fset *token.FileSet, filename string, src interface{}, mode uint) (*ast.File, os.Error) {
140 data, err := readSource(filename, src)
141 if err != nil {
142 return nil, err
143 }
144
145 var p parser
146 p.init(fset, filename, data, mode)
147 file := p.parseFile()
148
149 return file, p.errors()
150 }
151
152
153
154
155
156
157
158
159
160
161 func ParseFiles(fset *token.FileSet, filenames []string, mode uint) (pkgs map[string]*ast.Package, first os.Error) {
162 pkgs = make(map[string]*ast.Package)
163 for _, filename := range filenames {
164 if src, err := ParseFile(fset, filename, nil, mode); err == nil {
165 name := src.Name.Name
166 pkg, found := pkgs[name]
167 if !found {
168
169 pkg = &ast.Package{name, nil, nil, make(map[string]*ast.File)}
170 pkgs[name] = pkg
171 }
172 pkg.Files[filename] = src
173 } else if first == nil {
174 first = err
175 }
176 }
177 return
178 }
179
180
181
182
183
184
185
186
187
188
189
190 func ParseDir(fset *token.FileSet, path string, filter func(*os.FileInfo) bool, mode uint) (map[string]*ast.Package, os.Error) {
191 fd, err := os.Open(path)
192 if err != nil {
193 return nil, err
194 }
195 defer fd.Close()
196
197 list, err := fd.Readdir(-1)
198 if err != nil {
199 return nil, err
200 }
201
202 filenames := make([]string, len(list))
203 n := 0
204 for i := 0; i < len(list); i++ {
205 d := &list[i]
206 if filter == nil || filter(d) {
207 filenames[n] = filepath.Join(path, d.Name)
208 n++
209 }
210 }
211 filenames = filenames[0:n]
212
213 return ParseFiles(fset, filenames, mode)
214 }