...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package load
16
17 import (
18 "bufio"
19 "io"
20 "unicode/utf8"
21
22 "cuelang.org/go/cue/errors"
23 "cuelang.org/go/cue/token"
24 )
25
26 type importReader struct {
27 b *bufio.Reader
28 buf []byte
29 peek byte
30 err errors.Error
31 eof bool
32 nerr int
33 }
34
35 func isIdent(c byte) bool {
36 return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c >= utf8.RuneSelf
37 }
38
39 var (
40 errSyntax = errors.Newf(token.NoPos, "syntax error")
41 errNUL = errors.Newf(token.NoPos, "unexpected NUL in input")
42 )
43
44
45 func (r *importReader) syntaxError() {
46 if r.err == nil {
47 r.err = errSyntax
48 }
49 }
50
51
52
53 func (r *importReader) readByte() byte {
54 c, err := r.b.ReadByte()
55 if err == nil {
56 r.buf = append(r.buf, c)
57 if c == 0 {
58 err = errNUL
59 }
60 }
61 if err != nil {
62 if err == io.EOF {
63 r.eof = true
64 } else if r.err == nil {
65 r.err = errors.Wrapf(err, token.NoPos, "readByte")
66 }
67 c = 0
68 }
69 return c
70 }
71
72
73
74 func (r *importReader) peekByte(skipSpace bool) byte {
75 if r.err != nil {
76 if r.nerr++; r.nerr > 10000 {
77 panic("go/build: import reader looping")
78 }
79 return 0
80 }
81
82
83
84
85 c := r.peek
86 if c == 0 {
87 c = r.readByte()
88 }
89 for r.err == nil && !r.eof {
90 if skipSpace {
91
92
93 switch c {
94 case ' ', '\f', '\t', '\r', '\n', ';':
95 c = r.readByte()
96 continue
97
98 case '/':
99 c = r.readByte()
100 if c == '/' {
101 for c != '\n' && r.err == nil && !r.eof {
102 c = r.readByte()
103 }
104 } else if c == '*' {
105 var c1 byte
106 for (c != '*' || c1 != '/') && r.err == nil {
107 if r.eof {
108 r.syntaxError()
109 }
110 c, c1 = c1, r.readByte()
111 }
112 } else {
113 r.syntaxError()
114 }
115 c = r.readByte()
116 continue
117 }
118 }
119 break
120 }
121 r.peek = c
122 return r.peek
123 }
124
125
126 func (r *importReader) nextByte(skipSpace bool) byte {
127 c := r.peekByte(skipSpace)
128 r.peek = 0
129 return c
130 }
131
132
133
134 func (r *importReader) readKeyword(kw string) {
135 r.peekByte(true)
136 for i := 0; i < len(kw); i++ {
137 if r.nextByte(false) != kw[i] {
138 r.syntaxError()
139 return
140 }
141 }
142 if isIdent(r.peekByte(false)) {
143 r.syntaxError()
144 }
145 }
146
147
148
149 func (r *importReader) readIdent() {
150 c := r.peekByte(true)
151 if !isIdent(c) {
152 r.syntaxError()
153 return
154 }
155 for isIdent(r.peekByte(false)) {
156 r.peek = 0
157 }
158 }
159
160
161
162 func (r *importReader) readString(save *[]string) {
163 switch r.nextByte(true) {
164 case '`':
165 start := len(r.buf) - 1
166 for r.err == nil {
167 if r.nextByte(false) == '`' {
168 if save != nil {
169 *save = append(*save, string(r.buf[start:]))
170 }
171 break
172 }
173 if r.eof {
174 r.syntaxError()
175 }
176 }
177 case '"':
178 start := len(r.buf) - 1
179 for r.err == nil {
180 c := r.nextByte(false)
181 if c == '"' {
182 if save != nil {
183 *save = append(*save, string(r.buf[start:]))
184 }
185 break
186 }
187 if r.eof || c == '\n' {
188 r.syntaxError()
189 }
190 if c == '\\' {
191 r.nextByte(false)
192 }
193 }
194 default:
195 r.syntaxError()
196 }
197 }
198
199
200
201 func (r *importReader) readImport(imports *[]string) {
202 c := r.peekByte(true)
203 if c == '.' {
204 r.peek = 0
205 } else if isIdent(c) {
206 r.readIdent()
207 }
208 r.readString(imports)
209 }
210
211
212
213 func readImports(f io.Reader, reportSyntaxError bool, imports *[]string) ([]byte, errors.Error) {
214 r := &importReader{b: bufio.NewReader(f)}
215
216 r.readKeyword("package")
217 r.readIdent()
218 for r.peekByte(true) == 'i' {
219 r.readKeyword("import")
220 if r.peekByte(true) == '(' {
221 r.nextByte(false)
222 for r.peekByte(true) != ')' && r.err == nil {
223 r.readImport(imports)
224 }
225 r.nextByte(false)
226 } else {
227 r.readImport(imports)
228 }
229 }
230
231
232
233 if r.err == nil && !r.eof {
234 return r.buf[:len(r.buf)-1], nil
235 }
236
237
238
239 if r.err == errSyntax && !reportSyntaxError {
240 r.err = nil
241 for r.err == nil && !r.eof {
242 r.readByte()
243 }
244 }
245
246 return r.buf, r.err
247 }
248
View as plain text