diff options
author | Alexandre Garand <alexandre.garand@fretlink.com> | 2019-08-09 15:59:15 +0200 |
---|---|---|
committer | Alexandre Garand <alexandre.garand@fretlink.com> | 2019-08-09 16:39:21 +0200 |
commit | 863486a6b71ed0e562a3965bed56465d007b1418 (patch) | |
tree | e93f6a687695af86d54237ec9f575d4ef104222d /vendor/github.com/zclconf/go-cty-yaml/scannerc.go | |
parent | 49c1c7b4dc69ffb9ab52330e6dc52ccdd6351087 (diff) | |
download | terraform-provider-statuscake-863486a6b71ed0e562a3965bed56465d007b1418.tar.gz terraform-provider-statuscake-863486a6b71ed0e562a3965bed56465d007b1418.tar.zst terraform-provider-statuscake-863486a6b71ed0e562a3965bed56465d007b1418.zip |
update vendor and go.modadd_contact_groups
Diffstat (limited to 'vendor/github.com/zclconf/go-cty-yaml/scannerc.go')
-rw-r--r-- | vendor/github.com/zclconf/go-cty-yaml/scannerc.go | 2696 |
1 files changed, 2696 insertions, 0 deletions
diff --git a/vendor/github.com/zclconf/go-cty-yaml/scannerc.go b/vendor/github.com/zclconf/go-cty-yaml/scannerc.go new file mode 100644 index 0000000..077fd1d --- /dev/null +++ b/vendor/github.com/zclconf/go-cty-yaml/scannerc.go | |||
@@ -0,0 +1,2696 @@ | |||
1 | package yaml | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "fmt" | ||
6 | ) | ||
7 | |||
8 | // Introduction | ||
9 | // ************ | ||
10 | // | ||
11 | // The following notes assume that you are familiar with the YAML specification | ||
12 | // (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in | ||
13 | // some cases we are less restrictive that it requires. | ||
14 | // | ||
15 | // The process of transforming a YAML stream into a sequence of events is | ||
16 | // divided on two steps: Scanning and Parsing. | ||
17 | // | ||
18 | // The Scanner transforms the input stream into a sequence of tokens, while the | ||
19 | // parser transform the sequence of tokens produced by the Scanner into a | ||
20 | // sequence of parsing events. | ||
21 | // | ||
22 | // The Scanner is rather clever and complicated. The Parser, on the contrary, | ||
23 | // is a straightforward implementation of a recursive-descendant parser (or, | ||
24 | // LL(1) parser, as it is usually called). | ||
25 | // | ||
26 | // Actually there are two issues of Scanning that might be called "clever", the | ||
27 | // rest is quite straightforward. The issues are "block collection start" and | ||
28 | // "simple keys". Both issues are explained below in details. | ||
29 | // | ||
30 | // Here the Scanning step is explained and implemented. We start with the list | ||
31 | // of all the tokens produced by the Scanner together with short descriptions. | ||
32 | // | ||
33 | // Now, tokens: | ||
34 | // | ||
35 | // STREAM-START(encoding) # The stream start. | ||
36 | // STREAM-END # The stream end. | ||
37 | // VERSION-DIRECTIVE(major,minor) # The '%YAML' directive. | ||
38 | // TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive. | ||
39 | // DOCUMENT-START # '---' | ||
40 | // DOCUMENT-END # '...' | ||
41 | // BLOCK-SEQUENCE-START # Indentation increase denoting a block | ||
42 | // BLOCK-MAPPING-START # sequence or a block mapping. | ||
43 | // BLOCK-END # Indentation decrease. | ||
44 | // FLOW-SEQUENCE-START # '[' | ||
45 | // FLOW-SEQUENCE-END # ']' | ||
46 | // BLOCK-SEQUENCE-START # '{' | ||
47 | // BLOCK-SEQUENCE-END # '}' | ||
48 | // BLOCK-ENTRY # '-' | ||
49 | // FLOW-ENTRY # ',' | ||
50 | // KEY # '?' or nothing (simple keys). | ||
51 | // VALUE # ':' | ||
52 | // ALIAS(anchor) # '*anchor' | ||
53 | // ANCHOR(anchor) # '&anchor' | ||
54 | // TAG(handle,suffix) # '!handle!suffix' | ||
55 | // SCALAR(value,style) # A scalar. | ||
56 | // | ||
57 | // The following two tokens are "virtual" tokens denoting the beginning and the | ||
58 | // end of the stream: | ||
59 | // | ||
60 | // STREAM-START(encoding) | ||
61 | // STREAM-END | ||
62 | // | ||
63 | // We pass the information about the input stream encoding with the | ||
64 | // STREAM-START token. | ||
65 | // | ||
66 | // The next two tokens are responsible for tags: | ||
67 | // | ||
68 | // VERSION-DIRECTIVE(major,minor) | ||
69 | // TAG-DIRECTIVE(handle,prefix) | ||
70 | // | ||
71 | // Example: | ||
72 | // | ||
73 | // %YAML 1.1 | ||
74 | // %TAG ! !foo | ||
75 | // %TAG !yaml! tag:yaml.org,2002: | ||
76 | // --- | ||
77 | // | ||
78 | // The correspoding sequence of tokens: | ||
79 | // | ||
80 | // STREAM-START(utf-8) | ||
81 | // VERSION-DIRECTIVE(1,1) | ||
82 | // TAG-DIRECTIVE("!","!foo") | ||
83 | // TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:") | ||
84 | // DOCUMENT-START | ||
85 | // STREAM-END | ||
86 | // | ||
87 | // Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole | ||
88 | // line. | ||
89 | // | ||
90 | // The document start and end indicators are represented by: | ||
91 | // | ||
92 | // DOCUMENT-START | ||
93 | // DOCUMENT-END | ||
94 | // | ||
95 | // Note that if a YAML stream contains an implicit document (without '---' | ||
96 | // and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be | ||
97 | // produced. | ||
98 | // | ||
99 | // In the following examples, we present whole documents together with the | ||
100 | // produced tokens. | ||
101 | // | ||
102 | // 1. An implicit document: | ||
103 | // | ||
104 | // 'a scalar' | ||
105 | // | ||
106 | // Tokens: | ||
107 | // | ||
108 | // STREAM-START(utf-8) | ||
109 | // SCALAR("a scalar",single-quoted) | ||
110 | // STREAM-END | ||
111 | // | ||
112 | // 2. An explicit document: | ||
113 | // | ||
114 | // --- | ||
115 | // 'a scalar' | ||
116 | // ... | ||
117 | // | ||
118 | // Tokens: | ||
119 | // | ||
120 | // STREAM-START(utf-8) | ||
121 | // DOCUMENT-START | ||
122 | // SCALAR("a scalar",single-quoted) | ||
123 | // DOCUMENT-END | ||
124 | // STREAM-END | ||
125 | // | ||
126 | // 3. Several documents in a stream: | ||
127 | // | ||
128 | // 'a scalar' | ||
129 | // --- | ||
130 | // 'another scalar' | ||
131 | // --- | ||
132 | // 'yet another scalar' | ||
133 | // | ||
134 | // Tokens: | ||
135 | // | ||
136 | // STREAM-START(utf-8) | ||
137 | // SCALAR("a scalar",single-quoted) | ||
138 | // DOCUMENT-START | ||
139 | // SCALAR("another scalar",single-quoted) | ||
140 | // DOCUMENT-START | ||
141 | // SCALAR("yet another scalar",single-quoted) | ||
142 | // STREAM-END | ||
143 | // | ||
144 | // We have already introduced the SCALAR token above. The following tokens are | ||
145 | // used to describe aliases, anchors, tag, and scalars: | ||
146 | // | ||
147 | // ALIAS(anchor) | ||
148 | // ANCHOR(anchor) | ||
149 | // TAG(handle,suffix) | ||
150 | // SCALAR(value,style) | ||
151 | // | ||
152 | // The following series of examples illustrate the usage of these tokens: | ||
153 | // | ||
154 | // 1. A recursive sequence: | ||
155 | // | ||
156 | // &A [ *A ] | ||
157 | // | ||
158 | // Tokens: | ||
159 | // | ||
160 | // STREAM-START(utf-8) | ||
161 | // ANCHOR("A") | ||
162 | // FLOW-SEQUENCE-START | ||
163 | // ALIAS("A") | ||
164 | // FLOW-SEQUENCE-END | ||
165 | // STREAM-END | ||
166 | // | ||
167 | // 2. A tagged scalar: | ||
168 | // | ||
169 | // !!float "3.14" # A good approximation. | ||
170 | // | ||
171 | // Tokens: | ||
172 | // | ||
173 | // STREAM-START(utf-8) | ||
174 | // TAG("!!","float") | ||
175 | // SCALAR("3.14",double-quoted) | ||
176 | // STREAM-END | ||
177 | // | ||
178 | // 3. Various scalar styles: | ||
179 | // | ||
180 | // --- # Implicit empty plain scalars do not produce tokens. | ||
181 | // --- a plain scalar | ||
182 | // --- 'a single-quoted scalar' | ||
183 | // --- "a double-quoted scalar" | ||
184 | // --- |- | ||
185 | // a literal scalar | ||
186 | // --- >- | ||
187 | // a folded | ||
188 | // scalar | ||
189 | // | ||
190 | // Tokens: | ||
191 | // | ||
192 | // STREAM-START(utf-8) | ||
193 | // DOCUMENT-START | ||
194 | // DOCUMENT-START | ||
195 | // SCALAR("a plain scalar",plain) | ||
196 | // DOCUMENT-START | ||
197 | // SCALAR("a single-quoted scalar",single-quoted) | ||
198 | // DOCUMENT-START | ||
199 | // SCALAR("a double-quoted scalar",double-quoted) | ||
200 | // DOCUMENT-START | ||
201 | // SCALAR("a literal scalar",literal) | ||
202 | // DOCUMENT-START | ||
203 | // SCALAR("a folded scalar",folded) | ||
204 | // STREAM-END | ||
205 | // | ||
206 | // Now it's time to review collection-related tokens. We will start with | ||
207 | // flow collections: | ||
208 | // | ||
209 | // FLOW-SEQUENCE-START | ||
210 | // FLOW-SEQUENCE-END | ||
211 | // FLOW-MAPPING-START | ||
212 | // FLOW-MAPPING-END | ||
213 | // FLOW-ENTRY | ||
214 | // KEY | ||
215 | // VALUE | ||
216 | // | ||
217 | // The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and | ||
218 | // FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}' | ||
219 | // correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the | ||
220 | // indicators '?' and ':', which are used for denoting mapping keys and values, | ||
221 | // are represented by the KEY and VALUE tokens. | ||
222 | // | ||
223 | // The following examples show flow collections: | ||
224 | // | ||
225 | // 1. A flow sequence: | ||
226 | // | ||
227 | // [item 1, item 2, item 3] | ||
228 | // | ||
229 | // Tokens: | ||
230 | // | ||
231 | // STREAM-START(utf-8) | ||
232 | // FLOW-SEQUENCE-START | ||
233 | // SCALAR("item 1",plain) | ||
234 | // FLOW-ENTRY | ||
235 | // SCALAR("item 2",plain) | ||
236 | // FLOW-ENTRY | ||
237 | // SCALAR("item 3",plain) | ||
238 | // FLOW-SEQUENCE-END | ||
239 | // STREAM-END | ||
240 | // | ||
241 | // 2. A flow mapping: | ||
242 | // | ||
243 | // { | ||
244 | // a simple key: a value, # Note that the KEY token is produced. | ||
245 | // ? a complex key: another value, | ||
246 | // } | ||
247 | // | ||
248 | // Tokens: | ||
249 | // | ||
250 | // STREAM-START(utf-8) | ||
251 | // FLOW-MAPPING-START | ||
252 | // KEY | ||
253 | // SCALAR("a simple key",plain) | ||
254 | // VALUE | ||
255 | // SCALAR("a value",plain) | ||
256 | // FLOW-ENTRY | ||
257 | // KEY | ||
258 | // SCALAR("a complex key",plain) | ||
259 | // VALUE | ||
260 | // SCALAR("another value",plain) | ||
261 | // FLOW-ENTRY | ||
262 | // FLOW-MAPPING-END | ||
263 | // STREAM-END | ||
264 | // | ||
265 | // A simple key is a key which is not denoted by the '?' indicator. Note that | ||
266 | // the Scanner still produce the KEY token whenever it encounters a simple key. | ||
267 | // | ||
268 | // For scanning block collections, the following tokens are used (note that we | ||
269 | // repeat KEY and VALUE here): | ||
270 | // | ||
271 | // BLOCK-SEQUENCE-START | ||
272 | // BLOCK-MAPPING-START | ||
273 | // BLOCK-END | ||
274 | // BLOCK-ENTRY | ||
275 | // KEY | ||
276 | // VALUE | ||
277 | // | ||
278 | // The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation | ||
279 | // increase that precedes a block collection (cf. the INDENT token in Python). | ||
280 | // The token BLOCK-END denote indentation decrease that ends a block collection | ||
281 | // (cf. the DEDENT token in Python). However YAML has some syntax pecularities | ||
282 | // that makes detections of these tokens more complex. | ||
283 | // | ||
284 | // The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators | ||
285 | // '-', '?', and ':' correspondingly. | ||
286 | // | ||
287 | // The following examples show how the tokens BLOCK-SEQUENCE-START, | ||
288 | // BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner: | ||
289 | // | ||
290 | // 1. Block sequences: | ||
291 | // | ||
292 | // - item 1 | ||
293 | // - item 2 | ||
294 | // - | ||
295 | // - item 3.1 | ||
296 | // - item 3.2 | ||
297 | // - | ||
298 | // key 1: value 1 | ||
299 | // key 2: value 2 | ||
300 | // | ||
301 | // Tokens: | ||
302 | // | ||
303 | // STREAM-START(utf-8) | ||
304 | // BLOCK-SEQUENCE-START | ||
305 | // BLOCK-ENTRY | ||
306 | // SCALAR("item 1",plain) | ||
307 | // BLOCK-ENTRY | ||
308 | // SCALAR("item 2",plain) | ||
309 | // BLOCK-ENTRY | ||
310 | // BLOCK-SEQUENCE-START | ||
311 | // BLOCK-ENTRY | ||
312 | // SCALAR("item 3.1",plain) | ||
313 | // BLOCK-ENTRY | ||
314 | // SCALAR("item 3.2",plain) | ||
315 | // BLOCK-END | ||
316 | // BLOCK-ENTRY | ||
317 | // BLOCK-MAPPING-START | ||
318 | // KEY | ||
319 | // SCALAR("key 1",plain) | ||
320 | // VALUE | ||
321 | // SCALAR("value 1",plain) | ||
322 | // KEY | ||
323 | // SCALAR("key 2",plain) | ||
324 | // VALUE | ||
325 | // SCALAR("value 2",plain) | ||
326 | // BLOCK-END | ||
327 | // BLOCK-END | ||
328 | // STREAM-END | ||
329 | // | ||
330 | // 2. Block mappings: | ||
331 | // | ||
332 | // a simple key: a value # The KEY token is produced here. | ||
333 | // ? a complex key | ||
334 | // : another value | ||
335 | // a mapping: | ||
336 | // key 1: value 1 | ||
337 | // key 2: value 2 | ||
338 | // a sequence: | ||
339 | // - item 1 | ||
340 | // - item 2 | ||
341 | // | ||
342 | // Tokens: | ||
343 | // | ||
344 | // STREAM-START(utf-8) | ||
345 | // BLOCK-MAPPING-START | ||
346 | // KEY | ||
347 | // SCALAR("a simple key",plain) | ||
348 | // VALUE | ||
349 | // SCALAR("a value",plain) | ||
350 | // KEY | ||
351 | // SCALAR("a complex key",plain) | ||
352 | // VALUE | ||
353 | // SCALAR("another value",plain) | ||
354 | // KEY | ||
355 | // SCALAR("a mapping",plain) | ||
356 | // BLOCK-MAPPING-START | ||
357 | // KEY | ||
358 | // SCALAR("key 1",plain) | ||
359 | // VALUE | ||
360 | // SCALAR("value 1",plain) | ||
361 | // KEY | ||
362 | // SCALAR("key 2",plain) | ||
363 | // VALUE | ||
364 | // SCALAR("value 2",plain) | ||
365 | // BLOCK-END | ||
366 | // KEY | ||
367 | // SCALAR("a sequence",plain) | ||
368 | // VALUE | ||
369 | // BLOCK-SEQUENCE-START | ||
370 | // BLOCK-ENTRY | ||
371 | // SCALAR("item 1",plain) | ||
372 | // BLOCK-ENTRY | ||
373 | // SCALAR("item 2",plain) | ||
374 | // BLOCK-END | ||
375 | // BLOCK-END | ||
376 | // STREAM-END | ||
377 | // | ||
378 | // YAML does not always require to start a new block collection from a new | ||
379 | // line. If the current line contains only '-', '?', and ':' indicators, a new | ||
380 | // block collection may start at the current line. The following examples | ||
381 | // illustrate this case: | ||
382 | // | ||
383 | // 1. Collections in a sequence: | ||
384 | // | ||
385 | // - - item 1 | ||
386 | // - item 2 | ||
387 | // - key 1: value 1 | ||
388 | // key 2: value 2 | ||
389 | // - ? complex key | ||
390 | // : complex value | ||
391 | // | ||
392 | // Tokens: | ||
393 | // | ||
394 | // STREAM-START(utf-8) | ||
395 | // BLOCK-SEQUENCE-START | ||
396 | // BLOCK-ENTRY | ||
397 | // BLOCK-SEQUENCE-START | ||
398 | // BLOCK-ENTRY | ||
399 | // SCALAR("item 1",plain) | ||
400 | // BLOCK-ENTRY | ||
401 | // SCALAR("item 2",plain) | ||
402 | // BLOCK-END | ||
403 | // BLOCK-ENTRY | ||
404 | // BLOCK-MAPPING-START | ||
405 | // KEY | ||
406 | // SCALAR("key 1",plain) | ||
407 | // VALUE | ||
408 | // SCALAR("value 1",plain) | ||
409 | // KEY | ||
410 | // SCALAR("key 2",plain) | ||
411 | // VALUE | ||
412 | // SCALAR("value 2",plain) | ||
413 | // BLOCK-END | ||
414 | // BLOCK-ENTRY | ||
415 | // BLOCK-MAPPING-START | ||
416 | // KEY | ||
417 | // SCALAR("complex key") | ||
418 | // VALUE | ||
419 | // SCALAR("complex value") | ||
420 | // BLOCK-END | ||
421 | // BLOCK-END | ||
422 | // STREAM-END | ||
423 | // | ||
424 | // 2. Collections in a mapping: | ||
425 | // | ||
426 | // ? a sequence | ||
427 | // : - item 1 | ||
428 | // - item 2 | ||
429 | // ? a mapping | ||
430 | // : key 1: value 1 | ||
431 | // key 2: value 2 | ||
432 | // | ||
433 | // Tokens: | ||
434 | // | ||
435 | // STREAM-START(utf-8) | ||
436 | // BLOCK-MAPPING-START | ||
437 | // KEY | ||
438 | // SCALAR("a sequence",plain) | ||
439 | // VALUE | ||
440 | // BLOCK-SEQUENCE-START | ||
441 | // BLOCK-ENTRY | ||
442 | // SCALAR("item 1",plain) | ||
443 | // BLOCK-ENTRY | ||
444 | // SCALAR("item 2",plain) | ||
445 | // BLOCK-END | ||
446 | // KEY | ||
447 | // SCALAR("a mapping",plain) | ||
448 | // VALUE | ||
449 | // BLOCK-MAPPING-START | ||
450 | // KEY | ||
451 | // SCALAR("key 1",plain) | ||
452 | // VALUE | ||
453 | // SCALAR("value 1",plain) | ||
454 | // KEY | ||
455 | // SCALAR("key 2",plain) | ||
456 | // VALUE | ||
457 | // SCALAR("value 2",plain) | ||
458 | // BLOCK-END | ||
459 | // BLOCK-END | ||
460 | // STREAM-END | ||
461 | // | ||
462 | // YAML also permits non-indented sequences if they are included into a block | ||
463 | // mapping. In this case, the token BLOCK-SEQUENCE-START is not produced: | ||
464 | // | ||
465 | // key: | ||
466 | // - item 1 # BLOCK-SEQUENCE-START is NOT produced here. | ||
467 | // - item 2 | ||
468 | // | ||
469 | // Tokens: | ||
470 | // | ||
471 | // STREAM-START(utf-8) | ||
472 | // BLOCK-MAPPING-START | ||
473 | // KEY | ||
474 | // SCALAR("key",plain) | ||
475 | // VALUE | ||
476 | // BLOCK-ENTRY | ||
477 | // SCALAR("item 1",plain) | ||
478 | // BLOCK-ENTRY | ||
479 | // SCALAR("item 2",plain) | ||
480 | // BLOCK-END | ||
481 | // | ||
482 | |||
483 | // Ensure that the buffer contains the required number of characters. | ||
484 | // Return true on success, false on failure (reader error or memory error). | ||
485 | func cache(parser *yaml_parser_t, length int) bool { | ||
486 | // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B) | ||
487 | return parser.unread >= length || yaml_parser_update_buffer(parser, length) | ||
488 | } | ||
489 | |||
490 | // Advance the buffer pointer. | ||
491 | func skip(parser *yaml_parser_t) { | ||
492 | parser.mark.index++ | ||
493 | parser.mark.column++ | ||
494 | parser.unread-- | ||
495 | parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) | ||
496 | } | ||
497 | |||
498 | func skip_line(parser *yaml_parser_t) { | ||
499 | if is_crlf(parser.buffer, parser.buffer_pos) { | ||
500 | parser.mark.index += 2 | ||
501 | parser.mark.column = 0 | ||
502 | parser.mark.line++ | ||
503 | parser.unread -= 2 | ||
504 | parser.buffer_pos += 2 | ||
505 | } else if is_break(parser.buffer, parser.buffer_pos) { | ||
506 | parser.mark.index++ | ||
507 | parser.mark.column = 0 | ||
508 | parser.mark.line++ | ||
509 | parser.unread-- | ||
510 | parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) | ||
511 | } | ||
512 | } | ||
513 | |||
514 | // Copy a character to a string buffer and advance pointers. | ||
515 | func read(parser *yaml_parser_t, s []byte) []byte { | ||
516 | w := width(parser.buffer[parser.buffer_pos]) | ||
517 | if w == 0 { | ||
518 | panic("invalid character sequence") | ||
519 | } | ||
520 | if len(s) == 0 { | ||
521 | s = make([]byte, 0, 32) | ||
522 | } | ||
523 | if w == 1 && len(s)+w <= cap(s) { | ||
524 | s = s[:len(s)+1] | ||
525 | s[len(s)-1] = parser.buffer[parser.buffer_pos] | ||
526 | parser.buffer_pos++ | ||
527 | } else { | ||
528 | s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...) | ||
529 | parser.buffer_pos += w | ||
530 | } | ||
531 | parser.mark.index++ | ||
532 | parser.mark.column++ | ||
533 | parser.unread-- | ||
534 | return s | ||
535 | } | ||
536 | |||
537 | // Copy a line break character to a string buffer and advance pointers. | ||
538 | func read_line(parser *yaml_parser_t, s []byte) []byte { | ||
539 | buf := parser.buffer | ||
540 | pos := parser.buffer_pos | ||
541 | switch { | ||
542 | case buf[pos] == '\r' && buf[pos+1] == '\n': | ||
543 | // CR LF . LF | ||
544 | s = append(s, '\n') | ||
545 | parser.buffer_pos += 2 | ||
546 | parser.mark.index++ | ||
547 | parser.unread-- | ||
548 | case buf[pos] == '\r' || buf[pos] == '\n': | ||
549 | // CR|LF . LF | ||
550 | s = append(s, '\n') | ||
551 | parser.buffer_pos += 1 | ||
552 | case buf[pos] == '\xC2' && buf[pos+1] == '\x85': | ||
553 | // NEL . LF | ||
554 | s = append(s, '\n') | ||
555 | parser.buffer_pos += 2 | ||
556 | case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'): | ||
557 | // LS|PS . LS|PS | ||
558 | s = append(s, buf[parser.buffer_pos:pos+3]...) | ||
559 | parser.buffer_pos += 3 | ||
560 | default: | ||
561 | return s | ||
562 | } | ||
563 | parser.mark.index++ | ||
564 | parser.mark.column = 0 | ||
565 | parser.mark.line++ | ||
566 | parser.unread-- | ||
567 | return s | ||
568 | } | ||
569 | |||
570 | // Get the next token. | ||
571 | func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool { | ||
572 | // Erase the token object. | ||
573 | *token = yaml_token_t{} // [Go] Is this necessary? | ||
574 | |||
575 | // No tokens after STREAM-END or error. | ||
576 | if parser.stream_end_produced || parser.error != yaml_NO_ERROR { | ||
577 | return true | ||
578 | } | ||
579 | |||
580 | // Ensure that the tokens queue contains enough tokens. | ||
581 | if !parser.token_available { | ||
582 | if !yaml_parser_fetch_more_tokens(parser) { | ||
583 | return false | ||
584 | } | ||
585 | } | ||
586 | |||
587 | // Fetch the next token from the queue. | ||
588 | *token = parser.tokens[parser.tokens_head] | ||
589 | parser.tokens_head++ | ||
590 | parser.tokens_parsed++ | ||
591 | parser.token_available = false | ||
592 | |||
593 | if token.typ == yaml_STREAM_END_TOKEN { | ||
594 | parser.stream_end_produced = true | ||
595 | } | ||
596 | return true | ||
597 | } | ||
598 | |||
599 | // Set the scanner error and return false. | ||
600 | func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool { | ||
601 | parser.error = yaml_SCANNER_ERROR | ||
602 | parser.context = context | ||
603 | parser.context_mark = context_mark | ||
604 | parser.problem = problem | ||
605 | parser.problem_mark = parser.mark | ||
606 | return false | ||
607 | } | ||
608 | |||
609 | func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool { | ||
610 | context := "while parsing a tag" | ||
611 | if directive { | ||
612 | context = "while parsing a %TAG directive" | ||
613 | } | ||
614 | return yaml_parser_set_scanner_error(parser, context, context_mark, problem) | ||
615 | } | ||
616 | |||
617 | func trace(args ...interface{}) func() { | ||
618 | pargs := append([]interface{}{"+++"}, args...) | ||
619 | fmt.Println(pargs...) | ||
620 | pargs = append([]interface{}{"---"}, args...) | ||
621 | return func() { fmt.Println(pargs...) } | ||
622 | } | ||
623 | |||
624 | // Ensure that the tokens queue contains at least one token which can be | ||
625 | // returned to the Parser. | ||
626 | func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool { | ||
627 | // While we need more tokens to fetch, do it. | ||
628 | for { | ||
629 | // Check if we really need to fetch more tokens. | ||
630 | need_more_tokens := false | ||
631 | |||
632 | if parser.tokens_head == len(parser.tokens) { | ||
633 | // Queue is empty. | ||
634 | need_more_tokens = true | ||
635 | } else { | ||
636 | // Check if any potential simple key may occupy the head position. | ||
637 | if !yaml_parser_stale_simple_keys(parser) { | ||
638 | return false | ||
639 | } | ||
640 | |||
641 | for i := range parser.simple_keys { | ||
642 | simple_key := &parser.simple_keys[i] | ||
643 | if simple_key.possible && simple_key.token_number == parser.tokens_parsed { | ||
644 | need_more_tokens = true | ||
645 | break | ||
646 | } | ||
647 | } | ||
648 | } | ||
649 | |||
650 | // We are finished. | ||
651 | if !need_more_tokens { | ||
652 | break | ||
653 | } | ||
654 | // Fetch the next token. | ||
655 | if !yaml_parser_fetch_next_token(parser) { | ||
656 | return false | ||
657 | } | ||
658 | } | ||
659 | |||
660 | parser.token_available = true | ||
661 | return true | ||
662 | } | ||
663 | |||
664 | // The dispatcher for token fetchers. | ||
665 | func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool { | ||
666 | // Ensure that the buffer is initialized. | ||
667 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
668 | return false | ||
669 | } | ||
670 | |||
671 | // Check if we just started scanning. Fetch STREAM-START then. | ||
672 | if !parser.stream_start_produced { | ||
673 | return yaml_parser_fetch_stream_start(parser) | ||
674 | } | ||
675 | |||
676 | // Eat whitespaces and comments until we reach the next token. | ||
677 | if !yaml_parser_scan_to_next_token(parser) { | ||
678 | return false | ||
679 | } | ||
680 | |||
681 | // Remove obsolete potential simple keys. | ||
682 | if !yaml_parser_stale_simple_keys(parser) { | ||
683 | return false | ||
684 | } | ||
685 | |||
686 | // Check the indentation level against the current column. | ||
687 | if !yaml_parser_unroll_indent(parser, parser.mark.column) { | ||
688 | return false | ||
689 | } | ||
690 | |||
691 | // Ensure that the buffer contains at least 4 characters. 4 is the length | ||
692 | // of the longest indicators ('--- ' and '... '). | ||
693 | if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { | ||
694 | return false | ||
695 | } | ||
696 | |||
697 | // Is it the end of the stream? | ||
698 | if is_z(parser.buffer, parser.buffer_pos) { | ||
699 | return yaml_parser_fetch_stream_end(parser) | ||
700 | } | ||
701 | |||
702 | // Is it a directive? | ||
703 | if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' { | ||
704 | return yaml_parser_fetch_directive(parser) | ||
705 | } | ||
706 | |||
707 | buf := parser.buffer | ||
708 | pos := parser.buffer_pos | ||
709 | |||
710 | // Is it the document start indicator? | ||
711 | if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) { | ||
712 | return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN) | ||
713 | } | ||
714 | |||
715 | // Is it the document end indicator? | ||
716 | if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) { | ||
717 | return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN) | ||
718 | } | ||
719 | |||
720 | // Is it the flow sequence start indicator? | ||
721 | if buf[pos] == '[' { | ||
722 | return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN) | ||
723 | } | ||
724 | |||
725 | // Is it the flow mapping start indicator? | ||
726 | if parser.buffer[parser.buffer_pos] == '{' { | ||
727 | return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN) | ||
728 | } | ||
729 | |||
730 | // Is it the flow sequence end indicator? | ||
731 | if parser.buffer[parser.buffer_pos] == ']' { | ||
732 | return yaml_parser_fetch_flow_collection_end(parser, | ||
733 | yaml_FLOW_SEQUENCE_END_TOKEN) | ||
734 | } | ||
735 | |||
736 | // Is it the flow mapping end indicator? | ||
737 | if parser.buffer[parser.buffer_pos] == '}' { | ||
738 | return yaml_parser_fetch_flow_collection_end(parser, | ||
739 | yaml_FLOW_MAPPING_END_TOKEN) | ||
740 | } | ||
741 | |||
742 | // Is it the flow entry indicator? | ||
743 | if parser.buffer[parser.buffer_pos] == ',' { | ||
744 | return yaml_parser_fetch_flow_entry(parser) | ||
745 | } | ||
746 | |||
747 | // Is it the block entry indicator? | ||
748 | if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) { | ||
749 | return yaml_parser_fetch_block_entry(parser) | ||
750 | } | ||
751 | |||
752 | // Is it the key indicator? | ||
753 | if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { | ||
754 | return yaml_parser_fetch_key(parser) | ||
755 | } | ||
756 | |||
757 | // Is it the value indicator? | ||
758 | if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { | ||
759 | return yaml_parser_fetch_value(parser) | ||
760 | } | ||
761 | |||
762 | // Is it an alias? | ||
763 | if parser.buffer[parser.buffer_pos] == '*' { | ||
764 | return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN) | ||
765 | } | ||
766 | |||
767 | // Is it an anchor? | ||
768 | if parser.buffer[parser.buffer_pos] == '&' { | ||
769 | return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN) | ||
770 | } | ||
771 | |||
772 | // Is it a tag? | ||
773 | if parser.buffer[parser.buffer_pos] == '!' { | ||
774 | return yaml_parser_fetch_tag(parser) | ||
775 | } | ||
776 | |||
777 | // Is it a literal scalar? | ||
778 | if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 { | ||
779 | return yaml_parser_fetch_block_scalar(parser, true) | ||
780 | } | ||
781 | |||
782 | // Is it a folded scalar? | ||
783 | if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 { | ||
784 | return yaml_parser_fetch_block_scalar(parser, false) | ||
785 | } | ||
786 | |||
787 | // Is it a single-quoted scalar? | ||
788 | if parser.buffer[parser.buffer_pos] == '\'' { | ||
789 | return yaml_parser_fetch_flow_scalar(parser, true) | ||
790 | } | ||
791 | |||
792 | // Is it a double-quoted scalar? | ||
793 | if parser.buffer[parser.buffer_pos] == '"' { | ||
794 | return yaml_parser_fetch_flow_scalar(parser, false) | ||
795 | } | ||
796 | |||
797 | // Is it a plain scalar? | ||
798 | // | ||
799 | // A plain scalar may start with any non-blank characters except | ||
800 | // | ||
801 | // '-', '?', ':', ',', '[', ']', '{', '}', | ||
802 | // '#', '&', '*', '!', '|', '>', '\'', '\"', | ||
803 | // '%', '@', '`'. | ||
804 | // | ||
805 | // In the block context (and, for the '-' indicator, in the flow context | ||
806 | // too), it may also start with the characters | ||
807 | // | ||
808 | // '-', '?', ':' | ||
809 | // | ||
810 | // if it is followed by a non-space character. | ||
811 | // | ||
812 | // The last rule is more restrictive than the specification requires. | ||
813 | // [Go] Make this logic more reasonable. | ||
814 | //switch parser.buffer[parser.buffer_pos] { | ||
815 | //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`': | ||
816 | //} | ||
817 | if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' || | ||
818 | parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' || | ||
819 | parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' || | ||
820 | parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || | ||
821 | parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' || | ||
822 | parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' || | ||
823 | parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' || | ||
824 | parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' || | ||
825 | parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' || | ||
826 | parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') || | ||
827 | (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) || | ||
828 | (parser.flow_level == 0 && | ||
829 | (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') && | ||
830 | !is_blankz(parser.buffer, parser.buffer_pos+1)) { | ||
831 | return yaml_parser_fetch_plain_scalar(parser) | ||
832 | } | ||
833 | |||
834 | // If we don't determine the token type so far, it is an error. | ||
835 | return yaml_parser_set_scanner_error(parser, | ||
836 | "while scanning for the next token", parser.mark, | ||
837 | "found character that cannot start any token") | ||
838 | } | ||
839 | |||
840 | // Check the list of potential simple keys and remove the positions that | ||
841 | // cannot contain simple keys anymore. | ||
842 | func yaml_parser_stale_simple_keys(parser *yaml_parser_t) bool { | ||
843 | // Check for a potential simple key for each flow level. | ||
844 | for i := range parser.simple_keys { | ||
845 | simple_key := &parser.simple_keys[i] | ||
846 | |||
847 | // The specification requires that a simple key | ||
848 | // | ||
849 | // - is limited to a single line, | ||
850 | // - is shorter than 1024 characters. | ||
851 | if simple_key.possible && (simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index) { | ||
852 | |||
853 | // Check if the potential simple key to be removed is required. | ||
854 | if simple_key.required { | ||
855 | return yaml_parser_set_scanner_error(parser, | ||
856 | "while scanning a simple key", simple_key.mark, | ||
857 | "could not find expected ':'") | ||
858 | } | ||
859 | simple_key.possible = false | ||
860 | } | ||
861 | } | ||
862 | return true | ||
863 | } | ||
864 | |||
865 | // Check if a simple key may start at the current position and add it if | ||
866 | // needed. | ||
867 | func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { | ||
868 | // A simple key is required at the current position if the scanner is in | ||
869 | // the block context and the current column coincides with the indentation | ||
870 | // level. | ||
871 | |||
872 | required := parser.flow_level == 0 && parser.indent == parser.mark.column | ||
873 | |||
874 | // | ||
875 | // If the current position may start a simple key, save it. | ||
876 | // | ||
877 | if parser.simple_key_allowed { | ||
878 | simple_key := yaml_simple_key_t{ | ||
879 | possible: true, | ||
880 | required: required, | ||
881 | token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), | ||
882 | } | ||
883 | simple_key.mark = parser.mark | ||
884 | |||
885 | if !yaml_parser_remove_simple_key(parser) { | ||
886 | return false | ||
887 | } | ||
888 | parser.simple_keys[len(parser.simple_keys)-1] = simple_key | ||
889 | } | ||
890 | return true | ||
891 | } | ||
892 | |||
893 | // Remove a potential simple key at the current flow level. | ||
894 | func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { | ||
895 | i := len(parser.simple_keys) - 1 | ||
896 | if parser.simple_keys[i].possible { | ||
897 | // If the key is required, it is an error. | ||
898 | if parser.simple_keys[i].required { | ||
899 | return yaml_parser_set_scanner_error(parser, | ||
900 | "while scanning a simple key", parser.simple_keys[i].mark, | ||
901 | "could not find expected ':'") | ||
902 | } | ||
903 | } | ||
904 | // Remove the key from the stack. | ||
905 | parser.simple_keys[i].possible = false | ||
906 | return true | ||
907 | } | ||
908 | |||
909 | // Increase the flow level and resize the simple key list if needed. | ||
910 | func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { | ||
911 | // Reset the simple key on the next level. | ||
912 | parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) | ||
913 | |||
914 | // Increase the flow level. | ||
915 | parser.flow_level++ | ||
916 | return true | ||
917 | } | ||
918 | |||
919 | // Decrease the flow level. | ||
920 | func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { | ||
921 | if parser.flow_level > 0 { | ||
922 | parser.flow_level-- | ||
923 | parser.simple_keys = parser.simple_keys[:len(parser.simple_keys)-1] | ||
924 | } | ||
925 | return true | ||
926 | } | ||
927 | |||
928 | // Push the current indentation level to the stack and set the new level | ||
929 | // the current column is greater than the indentation level. In this case, | ||
930 | // append or insert the specified token into the token queue. | ||
931 | func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool { | ||
932 | // In the flow context, do nothing. | ||
933 | if parser.flow_level > 0 { | ||
934 | return true | ||
935 | } | ||
936 | |||
937 | if parser.indent < column { | ||
938 | // Push the current indentation level to the stack and set the new | ||
939 | // indentation level. | ||
940 | parser.indents = append(parser.indents, parser.indent) | ||
941 | parser.indent = column | ||
942 | |||
943 | // Create a token and insert it into the queue. | ||
944 | token := yaml_token_t{ | ||
945 | typ: typ, | ||
946 | start_mark: mark, | ||
947 | end_mark: mark, | ||
948 | } | ||
949 | if number > -1 { | ||
950 | number -= parser.tokens_parsed | ||
951 | } | ||
952 | yaml_insert_token(parser, number, &token) | ||
953 | } | ||
954 | return true | ||
955 | } | ||
956 | |||
957 | // Pop indentation levels from the indents stack until the current level | ||
958 | // becomes less or equal to the column. For each indentation level, append | ||
959 | // the BLOCK-END token. | ||
960 | func yaml_parser_unroll_indent(parser *yaml_parser_t, column int) bool { | ||
961 | // In the flow context, do nothing. | ||
962 | if parser.flow_level > 0 { | ||
963 | return true | ||
964 | } | ||
965 | |||
966 | // Loop through the indentation levels in the stack. | ||
967 | for parser.indent > column { | ||
968 | // Create a token and append it to the queue. | ||
969 | token := yaml_token_t{ | ||
970 | typ: yaml_BLOCK_END_TOKEN, | ||
971 | start_mark: parser.mark, | ||
972 | end_mark: parser.mark, | ||
973 | } | ||
974 | yaml_insert_token(parser, -1, &token) | ||
975 | |||
976 | // Pop the indentation level. | ||
977 | parser.indent = parser.indents[len(parser.indents)-1] | ||
978 | parser.indents = parser.indents[:len(parser.indents)-1] | ||
979 | } | ||
980 | return true | ||
981 | } | ||
982 | |||
983 | // Initialize the scanner and produce the STREAM-START token. | ||
984 | func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool { | ||
985 | |||
986 | // Set the initial indentation. | ||
987 | parser.indent = -1 | ||
988 | |||
989 | // Initialize the simple key stack. | ||
990 | parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) | ||
991 | |||
992 | // A simple key is allowed at the beginning of the stream. | ||
993 | parser.simple_key_allowed = true | ||
994 | |||
995 | // We have started. | ||
996 | parser.stream_start_produced = true | ||
997 | |||
998 | // Create the STREAM-START token and append it to the queue. | ||
999 | token := yaml_token_t{ | ||
1000 | typ: yaml_STREAM_START_TOKEN, | ||
1001 | start_mark: parser.mark, | ||
1002 | end_mark: parser.mark, | ||
1003 | encoding: parser.encoding, | ||
1004 | } | ||
1005 | yaml_insert_token(parser, -1, &token) | ||
1006 | return true | ||
1007 | } | ||
1008 | |||
1009 | // Produce the STREAM-END token and shut down the scanner. | ||
1010 | func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool { | ||
1011 | |||
1012 | // Force new line. | ||
1013 | if parser.mark.column != 0 { | ||
1014 | parser.mark.column = 0 | ||
1015 | parser.mark.line++ | ||
1016 | } | ||
1017 | |||
1018 | // Reset the indentation level. | ||
1019 | if !yaml_parser_unroll_indent(parser, -1) { | ||
1020 | return false | ||
1021 | } | ||
1022 | |||
1023 | // Reset simple keys. | ||
1024 | if !yaml_parser_remove_simple_key(parser) { | ||
1025 | return false | ||
1026 | } | ||
1027 | |||
1028 | parser.simple_key_allowed = false | ||
1029 | |||
1030 | // Create the STREAM-END token and append it to the queue. | ||
1031 | token := yaml_token_t{ | ||
1032 | typ: yaml_STREAM_END_TOKEN, | ||
1033 | start_mark: parser.mark, | ||
1034 | end_mark: parser.mark, | ||
1035 | } | ||
1036 | yaml_insert_token(parser, -1, &token) | ||
1037 | return true | ||
1038 | } | ||
1039 | |||
1040 | // Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token. | ||
1041 | func yaml_parser_fetch_directive(parser *yaml_parser_t) bool { | ||
1042 | // Reset the indentation level. | ||
1043 | if !yaml_parser_unroll_indent(parser, -1) { | ||
1044 | return false | ||
1045 | } | ||
1046 | |||
1047 | // Reset simple keys. | ||
1048 | if !yaml_parser_remove_simple_key(parser) { | ||
1049 | return false | ||
1050 | } | ||
1051 | |||
1052 | parser.simple_key_allowed = false | ||
1053 | |||
1054 | // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. | ||
1055 | token := yaml_token_t{} | ||
1056 | if !yaml_parser_scan_directive(parser, &token) { | ||
1057 | return false | ||
1058 | } | ||
1059 | // Append the token to the queue. | ||
1060 | yaml_insert_token(parser, -1, &token) | ||
1061 | return true | ||
1062 | } | ||
1063 | |||
1064 | // Produce the DOCUMENT-START or DOCUMENT-END token. | ||
1065 | func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool { | ||
1066 | // Reset the indentation level. | ||
1067 | if !yaml_parser_unroll_indent(parser, -1) { | ||
1068 | return false | ||
1069 | } | ||
1070 | |||
1071 | // Reset simple keys. | ||
1072 | if !yaml_parser_remove_simple_key(parser) { | ||
1073 | return false | ||
1074 | } | ||
1075 | |||
1076 | parser.simple_key_allowed = false | ||
1077 | |||
1078 | // Consume the token. | ||
1079 | start_mark := parser.mark | ||
1080 | |||
1081 | skip(parser) | ||
1082 | skip(parser) | ||
1083 | skip(parser) | ||
1084 | |||
1085 | end_mark := parser.mark | ||
1086 | |||
1087 | // Create the DOCUMENT-START or DOCUMENT-END token. | ||
1088 | token := yaml_token_t{ | ||
1089 | typ: typ, | ||
1090 | start_mark: start_mark, | ||
1091 | end_mark: end_mark, | ||
1092 | } | ||
1093 | // Append the token to the queue. | ||
1094 | yaml_insert_token(parser, -1, &token) | ||
1095 | return true | ||
1096 | } | ||
1097 | |||
1098 | // Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token. | ||
1099 | func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool { | ||
1100 | // The indicators '[' and '{' may start a simple key. | ||
1101 | if !yaml_parser_save_simple_key(parser) { | ||
1102 | return false | ||
1103 | } | ||
1104 | |||
1105 | // Increase the flow level. | ||
1106 | if !yaml_parser_increase_flow_level(parser) { | ||
1107 | return false | ||
1108 | } | ||
1109 | |||
1110 | // A simple key may follow the indicators '[' and '{'. | ||
1111 | parser.simple_key_allowed = true | ||
1112 | |||
1113 | // Consume the token. | ||
1114 | start_mark := parser.mark | ||
1115 | skip(parser) | ||
1116 | end_mark := parser.mark | ||
1117 | |||
1118 | // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. | ||
1119 | token := yaml_token_t{ | ||
1120 | typ: typ, | ||
1121 | start_mark: start_mark, | ||
1122 | end_mark: end_mark, | ||
1123 | } | ||
1124 | // Append the token to the queue. | ||
1125 | yaml_insert_token(parser, -1, &token) | ||
1126 | return true | ||
1127 | } | ||
1128 | |||
1129 | // Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token. | ||
1130 | func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool { | ||
1131 | // Reset any potential simple key on the current flow level. | ||
1132 | if !yaml_parser_remove_simple_key(parser) { | ||
1133 | return false | ||
1134 | } | ||
1135 | |||
1136 | // Decrease the flow level. | ||
1137 | if !yaml_parser_decrease_flow_level(parser) { | ||
1138 | return false | ||
1139 | } | ||
1140 | |||
1141 | // No simple keys after the indicators ']' and '}'. | ||
1142 | parser.simple_key_allowed = false | ||
1143 | |||
1144 | // Consume the token. | ||
1145 | |||
1146 | start_mark := parser.mark | ||
1147 | skip(parser) | ||
1148 | end_mark := parser.mark | ||
1149 | |||
1150 | // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. | ||
1151 | token := yaml_token_t{ | ||
1152 | typ: typ, | ||
1153 | start_mark: start_mark, | ||
1154 | end_mark: end_mark, | ||
1155 | } | ||
1156 | // Append the token to the queue. | ||
1157 | yaml_insert_token(parser, -1, &token) | ||
1158 | return true | ||
1159 | } | ||
1160 | |||
1161 | // Produce the FLOW-ENTRY token. | ||
1162 | func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool { | ||
1163 | // Reset any potential simple keys on the current flow level. | ||
1164 | if !yaml_parser_remove_simple_key(parser) { | ||
1165 | return false | ||
1166 | } | ||
1167 | |||
1168 | // Simple keys are allowed after ','. | ||
1169 | parser.simple_key_allowed = true | ||
1170 | |||
1171 | // Consume the token. | ||
1172 | start_mark := parser.mark | ||
1173 | skip(parser) | ||
1174 | end_mark := parser.mark | ||
1175 | |||
1176 | // Create the FLOW-ENTRY token and append it to the queue. | ||
1177 | token := yaml_token_t{ | ||
1178 | typ: yaml_FLOW_ENTRY_TOKEN, | ||
1179 | start_mark: start_mark, | ||
1180 | end_mark: end_mark, | ||
1181 | } | ||
1182 | yaml_insert_token(parser, -1, &token) | ||
1183 | return true | ||
1184 | } | ||
1185 | |||
1186 | // Produce the BLOCK-ENTRY token. | ||
1187 | func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool { | ||
1188 | // Check if the scanner is in the block context. | ||
1189 | if parser.flow_level == 0 { | ||
1190 | // Check if we are allowed to start a new entry. | ||
1191 | if !parser.simple_key_allowed { | ||
1192 | return yaml_parser_set_scanner_error(parser, "", parser.mark, | ||
1193 | "block sequence entries are not allowed in this context") | ||
1194 | } | ||
1195 | // Add the BLOCK-SEQUENCE-START token if needed. | ||
1196 | if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) { | ||
1197 | return false | ||
1198 | } | ||
1199 | } else { | ||
1200 | // It is an error for the '-' indicator to occur in the flow context, | ||
1201 | // but we let the Parser detect and report about it because the Parser | ||
1202 | // is able to point to the context. | ||
1203 | } | ||
1204 | |||
1205 | // Reset any potential simple keys on the current flow level. | ||
1206 | if !yaml_parser_remove_simple_key(parser) { | ||
1207 | return false | ||
1208 | } | ||
1209 | |||
1210 | // Simple keys are allowed after '-'. | ||
1211 | parser.simple_key_allowed = true | ||
1212 | |||
1213 | // Consume the token. | ||
1214 | start_mark := parser.mark | ||
1215 | skip(parser) | ||
1216 | end_mark := parser.mark | ||
1217 | |||
1218 | // Create the BLOCK-ENTRY token and append it to the queue. | ||
1219 | token := yaml_token_t{ | ||
1220 | typ: yaml_BLOCK_ENTRY_TOKEN, | ||
1221 | start_mark: start_mark, | ||
1222 | end_mark: end_mark, | ||
1223 | } | ||
1224 | yaml_insert_token(parser, -1, &token) | ||
1225 | return true | ||
1226 | } | ||
1227 | |||
1228 | // Produce the KEY token. | ||
1229 | func yaml_parser_fetch_key(parser *yaml_parser_t) bool { | ||
1230 | |||
1231 | // In the block context, additional checks are required. | ||
1232 | if parser.flow_level == 0 { | ||
1233 | // Check if we are allowed to start a new key (not nessesary simple). | ||
1234 | if !parser.simple_key_allowed { | ||
1235 | return yaml_parser_set_scanner_error(parser, "", parser.mark, | ||
1236 | "mapping keys are not allowed in this context") | ||
1237 | } | ||
1238 | // Add the BLOCK-MAPPING-START token if needed. | ||
1239 | if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { | ||
1240 | return false | ||
1241 | } | ||
1242 | } | ||
1243 | |||
1244 | // Reset any potential simple keys on the current flow level. | ||
1245 | if !yaml_parser_remove_simple_key(parser) { | ||
1246 | return false | ||
1247 | } | ||
1248 | |||
1249 | // Simple keys are allowed after '?' in the block context. | ||
1250 | parser.simple_key_allowed = parser.flow_level == 0 | ||
1251 | |||
1252 | // Consume the token. | ||
1253 | start_mark := parser.mark | ||
1254 | skip(parser) | ||
1255 | end_mark := parser.mark | ||
1256 | |||
1257 | // Create the KEY token and append it to the queue. | ||
1258 | token := yaml_token_t{ | ||
1259 | typ: yaml_KEY_TOKEN, | ||
1260 | start_mark: start_mark, | ||
1261 | end_mark: end_mark, | ||
1262 | } | ||
1263 | yaml_insert_token(parser, -1, &token) | ||
1264 | return true | ||
1265 | } | ||
1266 | |||
1267 | // Produce the VALUE token. | ||
1268 | func yaml_parser_fetch_value(parser *yaml_parser_t) bool { | ||
1269 | |||
1270 | simple_key := &parser.simple_keys[len(parser.simple_keys)-1] | ||
1271 | |||
1272 | // Have we found a simple key? | ||
1273 | if simple_key.possible { | ||
1274 | // Create the KEY token and insert it into the queue. | ||
1275 | token := yaml_token_t{ | ||
1276 | typ: yaml_KEY_TOKEN, | ||
1277 | start_mark: simple_key.mark, | ||
1278 | end_mark: simple_key.mark, | ||
1279 | } | ||
1280 | yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token) | ||
1281 | |||
1282 | // In the block context, we may need to add the BLOCK-MAPPING-START token. | ||
1283 | if !yaml_parser_roll_indent(parser, simple_key.mark.column, | ||
1284 | simple_key.token_number, | ||
1285 | yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) { | ||
1286 | return false | ||
1287 | } | ||
1288 | |||
1289 | // Remove the simple key. | ||
1290 | simple_key.possible = false | ||
1291 | |||
1292 | // A simple key cannot follow another simple key. | ||
1293 | parser.simple_key_allowed = false | ||
1294 | |||
1295 | } else { | ||
1296 | // The ':' indicator follows a complex key. | ||
1297 | |||
1298 | // In the block context, extra checks are required. | ||
1299 | if parser.flow_level == 0 { | ||
1300 | |||
1301 | // Check if we are allowed to start a complex value. | ||
1302 | if !parser.simple_key_allowed { | ||
1303 | return yaml_parser_set_scanner_error(parser, "", parser.mark, | ||
1304 | "mapping values are not allowed in this context") | ||
1305 | } | ||
1306 | |||
1307 | // Add the BLOCK-MAPPING-START token if needed. | ||
1308 | if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { | ||
1309 | return false | ||
1310 | } | ||
1311 | } | ||
1312 | |||
1313 | // Simple keys after ':' are allowed in the block context. | ||
1314 | parser.simple_key_allowed = parser.flow_level == 0 | ||
1315 | } | ||
1316 | |||
1317 | // Consume the token. | ||
1318 | start_mark := parser.mark | ||
1319 | skip(parser) | ||
1320 | end_mark := parser.mark | ||
1321 | |||
1322 | // Create the VALUE token and append it to the queue. | ||
1323 | token := yaml_token_t{ | ||
1324 | typ: yaml_VALUE_TOKEN, | ||
1325 | start_mark: start_mark, | ||
1326 | end_mark: end_mark, | ||
1327 | } | ||
1328 | yaml_insert_token(parser, -1, &token) | ||
1329 | return true | ||
1330 | } | ||
1331 | |||
1332 | // Produce the ALIAS or ANCHOR token. | ||
1333 | func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool { | ||
1334 | // An anchor or an alias could be a simple key. | ||
1335 | if !yaml_parser_save_simple_key(parser) { | ||
1336 | return false | ||
1337 | } | ||
1338 | |||
1339 | // A simple key cannot follow an anchor or an alias. | ||
1340 | parser.simple_key_allowed = false | ||
1341 | |||
1342 | // Create the ALIAS or ANCHOR token and append it to the queue. | ||
1343 | var token yaml_token_t | ||
1344 | if !yaml_parser_scan_anchor(parser, &token, typ) { | ||
1345 | return false | ||
1346 | } | ||
1347 | yaml_insert_token(parser, -1, &token) | ||
1348 | return true | ||
1349 | } | ||
1350 | |||
1351 | // Produce the TAG token. | ||
1352 | func yaml_parser_fetch_tag(parser *yaml_parser_t) bool { | ||
1353 | // A tag could be a simple key. | ||
1354 | if !yaml_parser_save_simple_key(parser) { | ||
1355 | return false | ||
1356 | } | ||
1357 | |||
1358 | // A simple key cannot follow a tag. | ||
1359 | parser.simple_key_allowed = false | ||
1360 | |||
1361 | // Create the TAG token and append it to the queue. | ||
1362 | var token yaml_token_t | ||
1363 | if !yaml_parser_scan_tag(parser, &token) { | ||
1364 | return false | ||
1365 | } | ||
1366 | yaml_insert_token(parser, -1, &token) | ||
1367 | return true | ||
1368 | } | ||
1369 | |||
1370 | // Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens. | ||
1371 | func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool { | ||
1372 | // Remove any potential simple keys. | ||
1373 | if !yaml_parser_remove_simple_key(parser) { | ||
1374 | return false | ||
1375 | } | ||
1376 | |||
1377 | // A simple key may follow a block scalar. | ||
1378 | parser.simple_key_allowed = true | ||
1379 | |||
1380 | // Create the SCALAR token and append it to the queue. | ||
1381 | var token yaml_token_t | ||
1382 | if !yaml_parser_scan_block_scalar(parser, &token, literal) { | ||
1383 | return false | ||
1384 | } | ||
1385 | yaml_insert_token(parser, -1, &token) | ||
1386 | return true | ||
1387 | } | ||
1388 | |||
1389 | // Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens. | ||
1390 | func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool { | ||
1391 | // A plain scalar could be a simple key. | ||
1392 | if !yaml_parser_save_simple_key(parser) { | ||
1393 | return false | ||
1394 | } | ||
1395 | |||
1396 | // A simple key cannot follow a flow scalar. | ||
1397 | parser.simple_key_allowed = false | ||
1398 | |||
1399 | // Create the SCALAR token and append it to the queue. | ||
1400 | var token yaml_token_t | ||
1401 | if !yaml_parser_scan_flow_scalar(parser, &token, single) { | ||
1402 | return false | ||
1403 | } | ||
1404 | yaml_insert_token(parser, -1, &token) | ||
1405 | return true | ||
1406 | } | ||
1407 | |||
1408 | // Produce the SCALAR(...,plain) token. | ||
1409 | func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool { | ||
1410 | // A plain scalar could be a simple key. | ||
1411 | if !yaml_parser_save_simple_key(parser) { | ||
1412 | return false | ||
1413 | } | ||
1414 | |||
1415 | // A simple key cannot follow a flow scalar. | ||
1416 | parser.simple_key_allowed = false | ||
1417 | |||
1418 | // Create the SCALAR token and append it to the queue. | ||
1419 | var token yaml_token_t | ||
1420 | if !yaml_parser_scan_plain_scalar(parser, &token) { | ||
1421 | return false | ||
1422 | } | ||
1423 | yaml_insert_token(parser, -1, &token) | ||
1424 | return true | ||
1425 | } | ||
1426 | |||
1427 | // Eat whitespaces and comments until the next token is found. | ||
1428 | func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool { | ||
1429 | |||
1430 | // Until the next token is not found. | ||
1431 | for { | ||
1432 | // Allow the BOM mark to start a line. | ||
1433 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1434 | return false | ||
1435 | } | ||
1436 | if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) { | ||
1437 | skip(parser) | ||
1438 | } | ||
1439 | |||
1440 | // Eat whitespaces. | ||
1441 | // Tabs are allowed: | ||
1442 | // - in the flow context | ||
1443 | // - in the block context, but not at the beginning of the line or | ||
1444 | // after '-', '?', or ':' (complex value). | ||
1445 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1446 | return false | ||
1447 | } | ||
1448 | |||
1449 | for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') { | ||
1450 | skip(parser) | ||
1451 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1452 | return false | ||
1453 | } | ||
1454 | } | ||
1455 | |||
1456 | // Eat a comment until a line break. | ||
1457 | if parser.buffer[parser.buffer_pos] == '#' { | ||
1458 | for !is_breakz(parser.buffer, parser.buffer_pos) { | ||
1459 | skip(parser) | ||
1460 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1461 | return false | ||
1462 | } | ||
1463 | } | ||
1464 | } | ||
1465 | |||
1466 | // If it is a line break, eat it. | ||
1467 | if is_break(parser.buffer, parser.buffer_pos) { | ||
1468 | if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { | ||
1469 | return false | ||
1470 | } | ||
1471 | skip_line(parser) | ||
1472 | |||
1473 | // In the block context, a new line may start a simple key. | ||
1474 | if parser.flow_level == 0 { | ||
1475 | parser.simple_key_allowed = true | ||
1476 | } | ||
1477 | } else { | ||
1478 | break // We have found a token. | ||
1479 | } | ||
1480 | } | ||
1481 | |||
1482 | return true | ||
1483 | } | ||
1484 | |||
1485 | // Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token. | ||
1486 | // | ||
1487 | // Scope: | ||
1488 | // %YAML 1.1 # a comment \n | ||
1489 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
1490 | // %TAG !yaml! tag:yaml.org,2002: \n | ||
1491 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
1492 | // | ||
1493 | func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool { | ||
1494 | // Eat '%'. | ||
1495 | start_mark := parser.mark | ||
1496 | skip(parser) | ||
1497 | |||
1498 | // Scan the directive name. | ||
1499 | var name []byte | ||
1500 | if !yaml_parser_scan_directive_name(parser, start_mark, &name) { | ||
1501 | return false | ||
1502 | } | ||
1503 | |||
1504 | // Is it a YAML directive? | ||
1505 | if bytes.Equal(name, []byte("YAML")) { | ||
1506 | // Scan the VERSION directive value. | ||
1507 | var major, minor int8 | ||
1508 | if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) { | ||
1509 | return false | ||
1510 | } | ||
1511 | end_mark := parser.mark | ||
1512 | |||
1513 | // Create a VERSION-DIRECTIVE token. | ||
1514 | *token = yaml_token_t{ | ||
1515 | typ: yaml_VERSION_DIRECTIVE_TOKEN, | ||
1516 | start_mark: start_mark, | ||
1517 | end_mark: end_mark, | ||
1518 | major: major, | ||
1519 | minor: minor, | ||
1520 | } | ||
1521 | |||
1522 | // Is it a TAG directive? | ||
1523 | } else if bytes.Equal(name, []byte("TAG")) { | ||
1524 | // Scan the TAG directive value. | ||
1525 | var handle, prefix []byte | ||
1526 | if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) { | ||
1527 | return false | ||
1528 | } | ||
1529 | end_mark := parser.mark | ||
1530 | |||
1531 | // Create a TAG-DIRECTIVE token. | ||
1532 | *token = yaml_token_t{ | ||
1533 | typ: yaml_TAG_DIRECTIVE_TOKEN, | ||
1534 | start_mark: start_mark, | ||
1535 | end_mark: end_mark, | ||
1536 | value: handle, | ||
1537 | prefix: prefix, | ||
1538 | } | ||
1539 | |||
1540 | // Unknown directive. | ||
1541 | } else { | ||
1542 | yaml_parser_set_scanner_error(parser, "while scanning a directive", | ||
1543 | start_mark, "found unknown directive name") | ||
1544 | return false | ||
1545 | } | ||
1546 | |||
1547 | // Eat the rest of the line including any comments. | ||
1548 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1549 | return false | ||
1550 | } | ||
1551 | |||
1552 | for is_blank(parser.buffer, parser.buffer_pos) { | ||
1553 | skip(parser) | ||
1554 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1555 | return false | ||
1556 | } | ||
1557 | } | ||
1558 | |||
1559 | if parser.buffer[parser.buffer_pos] == '#' { | ||
1560 | for !is_breakz(parser.buffer, parser.buffer_pos) { | ||
1561 | skip(parser) | ||
1562 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1563 | return false | ||
1564 | } | ||
1565 | } | ||
1566 | } | ||
1567 | |||
1568 | // Check if we are at the end of the line. | ||
1569 | if !is_breakz(parser.buffer, parser.buffer_pos) { | ||
1570 | yaml_parser_set_scanner_error(parser, "while scanning a directive", | ||
1571 | start_mark, "did not find expected comment or line break") | ||
1572 | return false | ||
1573 | } | ||
1574 | |||
1575 | // Eat a line break. | ||
1576 | if is_break(parser.buffer, parser.buffer_pos) { | ||
1577 | if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { | ||
1578 | return false | ||
1579 | } | ||
1580 | skip_line(parser) | ||
1581 | } | ||
1582 | |||
1583 | return true | ||
1584 | } | ||
1585 | |||
1586 | // Scan the directive name. | ||
1587 | // | ||
1588 | // Scope: | ||
1589 | // %YAML 1.1 # a comment \n | ||
1590 | // ^^^^ | ||
1591 | // %TAG !yaml! tag:yaml.org,2002: \n | ||
1592 | // ^^^ | ||
1593 | // | ||
1594 | func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool { | ||
1595 | // Consume the directive name. | ||
1596 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1597 | return false | ||
1598 | } | ||
1599 | |||
1600 | var s []byte | ||
1601 | for is_alpha(parser.buffer, parser.buffer_pos) { | ||
1602 | s = read(parser, s) | ||
1603 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1604 | return false | ||
1605 | } | ||
1606 | } | ||
1607 | |||
1608 | // Check if the name is empty. | ||
1609 | if len(s) == 0 { | ||
1610 | yaml_parser_set_scanner_error(parser, "while scanning a directive", | ||
1611 | start_mark, "could not find expected directive name") | ||
1612 | return false | ||
1613 | } | ||
1614 | |||
1615 | // Check for an blank character after the name. | ||
1616 | if !is_blankz(parser.buffer, parser.buffer_pos) { | ||
1617 | yaml_parser_set_scanner_error(parser, "while scanning a directive", | ||
1618 | start_mark, "found unexpected non-alphabetical character") | ||
1619 | return false | ||
1620 | } | ||
1621 | *name = s | ||
1622 | return true | ||
1623 | } | ||
1624 | |||
1625 | // Scan the value of VERSION-DIRECTIVE. | ||
1626 | // | ||
1627 | // Scope: | ||
1628 | // %YAML 1.1 # a comment \n | ||
1629 | // ^^^^^^ | ||
1630 | func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool { | ||
1631 | // Eat whitespaces. | ||
1632 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1633 | return false | ||
1634 | } | ||
1635 | for is_blank(parser.buffer, parser.buffer_pos) { | ||
1636 | skip(parser) | ||
1637 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1638 | return false | ||
1639 | } | ||
1640 | } | ||
1641 | |||
1642 | // Consume the major version number. | ||
1643 | if !yaml_parser_scan_version_directive_number(parser, start_mark, major) { | ||
1644 | return false | ||
1645 | } | ||
1646 | |||
1647 | // Eat '.'. | ||
1648 | if parser.buffer[parser.buffer_pos] != '.' { | ||
1649 | return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", | ||
1650 | start_mark, "did not find expected digit or '.' character") | ||
1651 | } | ||
1652 | |||
1653 | skip(parser) | ||
1654 | |||
1655 | // Consume the minor version number. | ||
1656 | if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) { | ||
1657 | return false | ||
1658 | } | ||
1659 | return true | ||
1660 | } | ||
1661 | |||
1662 | const max_number_length = 2 | ||
1663 | |||
1664 | // Scan the version number of VERSION-DIRECTIVE. | ||
1665 | // | ||
1666 | // Scope: | ||
1667 | // %YAML 1.1 # a comment \n | ||
1668 | // ^ | ||
1669 | // %YAML 1.1 # a comment \n | ||
1670 | // ^ | ||
1671 | func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool { | ||
1672 | |||
1673 | // Repeat while the next character is digit. | ||
1674 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1675 | return false | ||
1676 | } | ||
1677 | var value, length int8 | ||
1678 | for is_digit(parser.buffer, parser.buffer_pos) { | ||
1679 | // Check if the number is too long. | ||
1680 | length++ | ||
1681 | if length > max_number_length { | ||
1682 | return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", | ||
1683 | start_mark, "found extremely long version number") | ||
1684 | } | ||
1685 | value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos)) | ||
1686 | skip(parser) | ||
1687 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1688 | return false | ||
1689 | } | ||
1690 | } | ||
1691 | |||
1692 | // Check if the number was present. | ||
1693 | if length == 0 { | ||
1694 | return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", | ||
1695 | start_mark, "did not find expected version number") | ||
1696 | } | ||
1697 | *number = value | ||
1698 | return true | ||
1699 | } | ||
1700 | |||
1701 | // Scan the value of a TAG-DIRECTIVE token. | ||
1702 | // | ||
1703 | // Scope: | ||
1704 | // %TAG !yaml! tag:yaml.org,2002: \n | ||
1705 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
1706 | // | ||
1707 | func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool { | ||
1708 | var handle_value, prefix_value []byte | ||
1709 | |||
1710 | // Eat whitespaces. | ||
1711 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1712 | return false | ||
1713 | } | ||
1714 | |||
1715 | for is_blank(parser.buffer, parser.buffer_pos) { | ||
1716 | skip(parser) | ||
1717 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1718 | return false | ||
1719 | } | ||
1720 | } | ||
1721 | |||
1722 | // Scan a handle. | ||
1723 | if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) { | ||
1724 | return false | ||
1725 | } | ||
1726 | |||
1727 | // Expect a whitespace. | ||
1728 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1729 | return false | ||
1730 | } | ||
1731 | if !is_blank(parser.buffer, parser.buffer_pos) { | ||
1732 | yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", | ||
1733 | start_mark, "did not find expected whitespace") | ||
1734 | return false | ||
1735 | } | ||
1736 | |||
1737 | // Eat whitespaces. | ||
1738 | for is_blank(parser.buffer, parser.buffer_pos) { | ||
1739 | skip(parser) | ||
1740 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1741 | return false | ||
1742 | } | ||
1743 | } | ||
1744 | |||
1745 | // Scan a prefix. | ||
1746 | if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) { | ||
1747 | return false | ||
1748 | } | ||
1749 | |||
1750 | // Expect a whitespace or line break. | ||
1751 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1752 | return false | ||
1753 | } | ||
1754 | if !is_blankz(parser.buffer, parser.buffer_pos) { | ||
1755 | yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", | ||
1756 | start_mark, "did not find expected whitespace or line break") | ||
1757 | return false | ||
1758 | } | ||
1759 | |||
1760 | *handle = handle_value | ||
1761 | *prefix = prefix_value | ||
1762 | return true | ||
1763 | } | ||
1764 | |||
1765 | func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool { | ||
1766 | var s []byte | ||
1767 | |||
1768 | // Eat the indicator character. | ||
1769 | start_mark := parser.mark | ||
1770 | skip(parser) | ||
1771 | |||
1772 | // Consume the value. | ||
1773 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1774 | return false | ||
1775 | } | ||
1776 | |||
1777 | for is_alpha(parser.buffer, parser.buffer_pos) { | ||
1778 | s = read(parser, s) | ||
1779 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1780 | return false | ||
1781 | } | ||
1782 | } | ||
1783 | |||
1784 | end_mark := parser.mark | ||
1785 | |||
1786 | /* | ||
1787 | * Check if length of the anchor is greater than 0 and it is followed by | ||
1788 | * a whitespace character or one of the indicators: | ||
1789 | * | ||
1790 | * '?', ':', ',', ']', '}', '%', '@', '`'. | ||
1791 | */ | ||
1792 | |||
1793 | if len(s) == 0 || | ||
1794 | !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' || | ||
1795 | parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' || | ||
1796 | parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' || | ||
1797 | parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' || | ||
1798 | parser.buffer[parser.buffer_pos] == '`') { | ||
1799 | context := "while scanning an alias" | ||
1800 | if typ == yaml_ANCHOR_TOKEN { | ||
1801 | context = "while scanning an anchor" | ||
1802 | } | ||
1803 | yaml_parser_set_scanner_error(parser, context, start_mark, | ||
1804 | "did not find expected alphabetic or numeric character") | ||
1805 | return false | ||
1806 | } | ||
1807 | |||
1808 | // Create a token. | ||
1809 | *token = yaml_token_t{ | ||
1810 | typ: typ, | ||
1811 | start_mark: start_mark, | ||
1812 | end_mark: end_mark, | ||
1813 | value: s, | ||
1814 | } | ||
1815 | |||
1816 | return true | ||
1817 | } | ||
1818 | |||
1819 | /* | ||
1820 | * Scan a TAG token. | ||
1821 | */ | ||
1822 | |||
1823 | func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool { | ||
1824 | var handle, suffix []byte | ||
1825 | |||
1826 | start_mark := parser.mark | ||
1827 | |||
1828 | // Check if the tag is in the canonical form. | ||
1829 | if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { | ||
1830 | return false | ||
1831 | } | ||
1832 | |||
1833 | if parser.buffer[parser.buffer_pos+1] == '<' { | ||
1834 | // Keep the handle as '' | ||
1835 | |||
1836 | // Eat '!<' | ||
1837 | skip(parser) | ||
1838 | skip(parser) | ||
1839 | |||
1840 | // Consume the tag value. | ||
1841 | if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { | ||
1842 | return false | ||
1843 | } | ||
1844 | |||
1845 | // Check for '>' and eat it. | ||
1846 | if parser.buffer[parser.buffer_pos] != '>' { | ||
1847 | yaml_parser_set_scanner_error(parser, "while scanning a tag", | ||
1848 | start_mark, "did not find the expected '>'") | ||
1849 | return false | ||
1850 | } | ||
1851 | |||
1852 | skip(parser) | ||
1853 | } else { | ||
1854 | // The tag has either the '!suffix' or the '!handle!suffix' form. | ||
1855 | |||
1856 | // First, try to scan a handle. | ||
1857 | if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) { | ||
1858 | return false | ||
1859 | } | ||
1860 | |||
1861 | // Check if it is, indeed, handle. | ||
1862 | if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' { | ||
1863 | // Scan the suffix now. | ||
1864 | if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { | ||
1865 | return false | ||
1866 | } | ||
1867 | } else { | ||
1868 | // It wasn't a handle after all. Scan the rest of the tag. | ||
1869 | if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) { | ||
1870 | return false | ||
1871 | } | ||
1872 | |||
1873 | // Set the handle to '!'. | ||
1874 | handle = []byte{'!'} | ||
1875 | |||
1876 | // A special case: the '!' tag. Set the handle to '' and the | ||
1877 | // suffix to '!'. | ||
1878 | if len(suffix) == 0 { | ||
1879 | handle, suffix = suffix, handle | ||
1880 | } | ||
1881 | } | ||
1882 | } | ||
1883 | |||
1884 | // Check the character which ends the tag. | ||
1885 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1886 | return false | ||
1887 | } | ||
1888 | if !is_blankz(parser.buffer, parser.buffer_pos) { | ||
1889 | yaml_parser_set_scanner_error(parser, "while scanning a tag", | ||
1890 | start_mark, "did not find expected whitespace or line break") | ||
1891 | return false | ||
1892 | } | ||
1893 | |||
1894 | end_mark := parser.mark | ||
1895 | |||
1896 | // Create a token. | ||
1897 | *token = yaml_token_t{ | ||
1898 | typ: yaml_TAG_TOKEN, | ||
1899 | start_mark: start_mark, | ||
1900 | end_mark: end_mark, | ||
1901 | value: handle, | ||
1902 | suffix: suffix, | ||
1903 | } | ||
1904 | return true | ||
1905 | } | ||
1906 | |||
1907 | // Scan a tag handle. | ||
1908 | func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool { | ||
1909 | // Check the initial '!' character. | ||
1910 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1911 | return false | ||
1912 | } | ||
1913 | if parser.buffer[parser.buffer_pos] != '!' { | ||
1914 | yaml_parser_set_scanner_tag_error(parser, directive, | ||
1915 | start_mark, "did not find expected '!'") | ||
1916 | return false | ||
1917 | } | ||
1918 | |||
1919 | var s []byte | ||
1920 | |||
1921 | // Copy the '!' character. | ||
1922 | s = read(parser, s) | ||
1923 | |||
1924 | // Copy all subsequent alphabetical and numerical characters. | ||
1925 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1926 | return false | ||
1927 | } | ||
1928 | for is_alpha(parser.buffer, parser.buffer_pos) { | ||
1929 | s = read(parser, s) | ||
1930 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1931 | return false | ||
1932 | } | ||
1933 | } | ||
1934 | |||
1935 | // Check if the trailing character is '!' and copy it. | ||
1936 | if parser.buffer[parser.buffer_pos] == '!' { | ||
1937 | s = read(parser, s) | ||
1938 | } else { | ||
1939 | // It's either the '!' tag or not really a tag handle. If it's a %TAG | ||
1940 | // directive, it's an error. If it's a tag token, it must be a part of URI. | ||
1941 | if directive && string(s) != "!" { | ||
1942 | yaml_parser_set_scanner_tag_error(parser, directive, | ||
1943 | start_mark, "did not find expected '!'") | ||
1944 | return false | ||
1945 | } | ||
1946 | } | ||
1947 | |||
1948 | *handle = s | ||
1949 | return true | ||
1950 | } | ||
1951 | |||
1952 | // Scan a tag. | ||
1953 | func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool { | ||
1954 | //size_t length = head ? strlen((char *)head) : 0 | ||
1955 | var s []byte | ||
1956 | hasTag := len(head) > 0 | ||
1957 | |||
1958 | // Copy the head if needed. | ||
1959 | // | ||
1960 | // Note that we don't copy the leading '!' character. | ||
1961 | if len(head) > 1 { | ||
1962 | s = append(s, head[1:]...) | ||
1963 | } | ||
1964 | |||
1965 | // Scan the tag. | ||
1966 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1967 | return false | ||
1968 | } | ||
1969 | |||
1970 | // The set of characters that may appear in URI is as follows: | ||
1971 | // | ||
1972 | // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', | ||
1973 | // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', | ||
1974 | // '%'. | ||
1975 | // [Go] Convert this into more reasonable logic. | ||
1976 | for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' || | ||
1977 | parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' || | ||
1978 | parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' || | ||
1979 | parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' || | ||
1980 | parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' || | ||
1981 | parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' || | ||
1982 | parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' || | ||
1983 | parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' || | ||
1984 | parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' || | ||
1985 | parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' || | ||
1986 | parser.buffer[parser.buffer_pos] == '%' { | ||
1987 | // Check if it is a URI-escape sequence. | ||
1988 | if parser.buffer[parser.buffer_pos] == '%' { | ||
1989 | if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) { | ||
1990 | return false | ||
1991 | } | ||
1992 | } else { | ||
1993 | s = read(parser, s) | ||
1994 | } | ||
1995 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
1996 | return false | ||
1997 | } | ||
1998 | hasTag = true | ||
1999 | } | ||
2000 | |||
2001 | if !hasTag { | ||
2002 | yaml_parser_set_scanner_tag_error(parser, directive, | ||
2003 | start_mark, "did not find expected tag URI") | ||
2004 | return false | ||
2005 | } | ||
2006 | *uri = s | ||
2007 | return true | ||
2008 | } | ||
2009 | |||
2010 | // Decode an URI-escape sequence corresponding to a single UTF-8 character. | ||
2011 | func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool { | ||
2012 | |||
2013 | // Decode the required number of characters. | ||
2014 | w := 1024 | ||
2015 | for w > 0 { | ||
2016 | // Check for a URI-escaped octet. | ||
2017 | if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { | ||
2018 | return false | ||
2019 | } | ||
2020 | |||
2021 | if !(parser.buffer[parser.buffer_pos] == '%' && | ||
2022 | is_hex(parser.buffer, parser.buffer_pos+1) && | ||
2023 | is_hex(parser.buffer, parser.buffer_pos+2)) { | ||
2024 | return yaml_parser_set_scanner_tag_error(parser, directive, | ||
2025 | start_mark, "did not find URI escaped octet") | ||
2026 | } | ||
2027 | |||
2028 | // Get the octet. | ||
2029 | octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2)) | ||
2030 | |||
2031 | // If it is the leading octet, determine the length of the UTF-8 sequence. | ||
2032 | if w == 1024 { | ||
2033 | w = width(octet) | ||
2034 | if w == 0 { | ||
2035 | return yaml_parser_set_scanner_tag_error(parser, directive, | ||
2036 | start_mark, "found an incorrect leading UTF-8 octet") | ||
2037 | } | ||
2038 | } else { | ||
2039 | // Check if the trailing octet is correct. | ||
2040 | if octet&0xC0 != 0x80 { | ||
2041 | return yaml_parser_set_scanner_tag_error(parser, directive, | ||
2042 | start_mark, "found an incorrect trailing UTF-8 octet") | ||
2043 | } | ||
2044 | } | ||
2045 | |||
2046 | // Copy the octet and move the pointers. | ||
2047 | *s = append(*s, octet) | ||
2048 | skip(parser) | ||
2049 | skip(parser) | ||
2050 | skip(parser) | ||
2051 | w-- | ||
2052 | } | ||
2053 | return true | ||
2054 | } | ||
2055 | |||
2056 | // Scan a block scalar. | ||
2057 | func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool { | ||
2058 | // Eat the indicator '|' or '>'. | ||
2059 | start_mark := parser.mark | ||
2060 | skip(parser) | ||
2061 | |||
2062 | // Scan the additional block scalar indicators. | ||
2063 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
2064 | return false | ||
2065 | } | ||
2066 | |||
2067 | // Check for a chomping indicator. | ||
2068 | var chomping, increment int | ||
2069 | if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { | ||
2070 | // Set the chomping method and eat the indicator. | ||
2071 | if parser.buffer[parser.buffer_pos] == '+' { | ||
2072 | chomping = +1 | ||
2073 | } else { | ||
2074 | chomping = -1 | ||
2075 | } | ||
2076 | skip(parser) | ||
2077 | |||
2078 | // Check for an indentation indicator. | ||
2079 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
2080 | return false | ||
2081 | } | ||
2082 | if is_digit(parser.buffer, parser.buffer_pos) { | ||
2083 | // Check that the indentation is greater than 0. | ||
2084 | if parser.buffer[parser.buffer_pos] == '0' { | ||
2085 | yaml_parser_set_scanner_error(parser, "while scanning a block scalar", | ||
2086 | start_mark, "found an indentation indicator equal to 0") | ||
2087 | return false | ||
2088 | } | ||
2089 | |||
2090 | // Get the indentation level and eat the indicator. | ||
2091 | increment = as_digit(parser.buffer, parser.buffer_pos) | ||
2092 | skip(parser) | ||
2093 | } | ||
2094 | |||
2095 | } else if is_digit(parser.buffer, parser.buffer_pos) { | ||
2096 | // Do the same as above, but in the opposite order. | ||
2097 | |||
2098 | if parser.buffer[parser.buffer_pos] == '0' { | ||
2099 | yaml_parser_set_scanner_error(parser, "while scanning a block scalar", | ||
2100 | start_mark, "found an indentation indicator equal to 0") | ||
2101 | return false | ||
2102 | } | ||
2103 | increment = as_digit(parser.buffer, parser.buffer_pos) | ||
2104 | skip(parser) | ||
2105 | |||
2106 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
2107 | return false | ||
2108 | } | ||
2109 | if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { | ||
2110 | if parser.buffer[parser.buffer_pos] == '+' { | ||
2111 | chomping = +1 | ||
2112 | } else { | ||
2113 | chomping = -1 | ||
2114 | } | ||
2115 | skip(parser) | ||
2116 | } | ||
2117 | } | ||
2118 | |||
2119 | // Eat whitespaces and comments to the end of the line. | ||
2120 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
2121 | return false | ||
2122 | } | ||
2123 | for is_blank(parser.buffer, parser.buffer_pos) { | ||
2124 | skip(parser) | ||
2125 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
2126 | return false | ||
2127 | } | ||
2128 | } | ||
2129 | if parser.buffer[parser.buffer_pos] == '#' { | ||
2130 | for !is_breakz(parser.buffer, parser.buffer_pos) { | ||
2131 | skip(parser) | ||
2132 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
2133 | return false | ||
2134 | } | ||
2135 | } | ||
2136 | } | ||
2137 | |||
2138 | // Check if we are at the end of the line. | ||
2139 | if !is_breakz(parser.buffer, parser.buffer_pos) { | ||
2140 | yaml_parser_set_scanner_error(parser, "while scanning a block scalar", | ||
2141 | start_mark, "did not find expected comment or line break") | ||
2142 | return false | ||
2143 | } | ||
2144 | |||
2145 | // Eat a line break. | ||
2146 | if is_break(parser.buffer, parser.buffer_pos) { | ||
2147 | if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { | ||
2148 | return false | ||
2149 | } | ||
2150 | skip_line(parser) | ||
2151 | } | ||
2152 | |||
2153 | end_mark := parser.mark | ||
2154 | |||
2155 | // Set the indentation level if it was specified. | ||
2156 | var indent int | ||
2157 | if increment > 0 { | ||
2158 | if parser.indent >= 0 { | ||
2159 | indent = parser.indent + increment | ||
2160 | } else { | ||
2161 | indent = increment | ||
2162 | } | ||
2163 | } | ||
2164 | |||
2165 | // Scan the leading line breaks and determine the indentation level if needed. | ||
2166 | var s, leading_break, trailing_breaks []byte | ||
2167 | if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { | ||
2168 | return false | ||
2169 | } | ||
2170 | |||
2171 | // Scan the block scalar content. | ||
2172 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
2173 | return false | ||
2174 | } | ||
2175 | var leading_blank, trailing_blank bool | ||
2176 | for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) { | ||
2177 | // We are at the beginning of a non-empty line. | ||
2178 | |||
2179 | // Is it a trailing whitespace? | ||
2180 | trailing_blank = is_blank(parser.buffer, parser.buffer_pos) | ||
2181 | |||
2182 | // Check if we need to fold the leading line break. | ||
2183 | if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' { | ||
2184 | // Do we need to join the lines by space? | ||
2185 | if len(trailing_breaks) == 0 { | ||
2186 | s = append(s, ' ') | ||
2187 | } | ||
2188 | } else { | ||
2189 | s = append(s, leading_break...) | ||
2190 | } | ||
2191 | leading_break = leading_break[:0] | ||
2192 | |||
2193 | // Append the remaining line breaks. | ||
2194 | s = append(s, trailing_breaks...) | ||
2195 | trailing_breaks = trailing_breaks[:0] | ||
2196 | |||
2197 | // Is it a leading whitespace? | ||
2198 | leading_blank = is_blank(parser.buffer, parser.buffer_pos) | ||
2199 | |||
2200 | // Consume the current line. | ||
2201 | for !is_breakz(parser.buffer, parser.buffer_pos) { | ||
2202 | s = read(parser, s) | ||
2203 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
2204 | return false | ||
2205 | } | ||
2206 | } | ||
2207 | |||
2208 | // Consume the line break. | ||
2209 | if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { | ||
2210 | return false | ||
2211 | } | ||
2212 | |||
2213 | leading_break = read_line(parser, leading_break) | ||
2214 | |||
2215 | // Eat the following indentation spaces and line breaks. | ||
2216 | if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { | ||
2217 | return false | ||
2218 | } | ||
2219 | } | ||
2220 | |||
2221 | // Chomp the tail. | ||
2222 | if chomping != -1 { | ||
2223 | s = append(s, leading_break...) | ||
2224 | } | ||
2225 | if chomping == 1 { | ||
2226 | s = append(s, trailing_breaks...) | ||
2227 | } | ||
2228 | |||
2229 | // Create a token. | ||
2230 | *token = yaml_token_t{ | ||
2231 | typ: yaml_SCALAR_TOKEN, | ||
2232 | start_mark: start_mark, | ||
2233 | end_mark: end_mark, | ||
2234 | value: s, | ||
2235 | style: yaml_LITERAL_SCALAR_STYLE, | ||
2236 | } | ||
2237 | if !literal { | ||
2238 | token.style = yaml_FOLDED_SCALAR_STYLE | ||
2239 | } | ||
2240 | return true | ||
2241 | } | ||
2242 | |||
2243 | // Scan indentation spaces and line breaks for a block scalar. Determine the | ||
2244 | // indentation level if needed. | ||
2245 | func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool { | ||
2246 | *end_mark = parser.mark | ||
2247 | |||
2248 | // Eat the indentation spaces and line breaks. | ||
2249 | max_indent := 0 | ||
2250 | for { | ||
2251 | // Eat the indentation spaces. | ||
2252 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
2253 | return false | ||
2254 | } | ||
2255 | for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) { | ||
2256 | skip(parser) | ||
2257 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
2258 | return false | ||
2259 | } | ||
2260 | } | ||
2261 | if parser.mark.column > max_indent { | ||
2262 | max_indent = parser.mark.column | ||
2263 | } | ||
2264 | |||
2265 | // Check for a tab character messing the indentation. | ||
2266 | if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) { | ||
2267 | return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", | ||
2268 | start_mark, "found a tab character where an indentation space is expected") | ||
2269 | } | ||
2270 | |||
2271 | // Have we found a non-empty line? | ||
2272 | if !is_break(parser.buffer, parser.buffer_pos) { | ||
2273 | break | ||
2274 | } | ||
2275 | |||
2276 | // Consume the line break. | ||
2277 | if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { | ||
2278 | return false | ||
2279 | } | ||
2280 | // [Go] Should really be returning breaks instead. | ||
2281 | *breaks = read_line(parser, *breaks) | ||
2282 | *end_mark = parser.mark | ||
2283 | } | ||
2284 | |||
2285 | // Determine the indentation level if needed. | ||
2286 | if *indent == 0 { | ||
2287 | *indent = max_indent | ||
2288 | if *indent < parser.indent+1 { | ||
2289 | *indent = parser.indent + 1 | ||
2290 | } | ||
2291 | if *indent < 1 { | ||
2292 | *indent = 1 | ||
2293 | } | ||
2294 | } | ||
2295 | return true | ||
2296 | } | ||
2297 | |||
2298 | // Scan a quoted scalar. | ||
2299 | func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool { | ||
2300 | // Eat the left quote. | ||
2301 | start_mark := parser.mark | ||
2302 | skip(parser) | ||
2303 | |||
2304 | // Consume the content of the quoted scalar. | ||
2305 | var s, leading_break, trailing_breaks, whitespaces []byte | ||
2306 | for { | ||
2307 | // Check that there are no document indicators at the beginning of the line. | ||
2308 | if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { | ||
2309 | return false | ||
2310 | } | ||
2311 | |||
2312 | if parser.mark.column == 0 && | ||
2313 | ((parser.buffer[parser.buffer_pos+0] == '-' && | ||
2314 | parser.buffer[parser.buffer_pos+1] == '-' && | ||
2315 | parser.buffer[parser.buffer_pos+2] == '-') || | ||
2316 | (parser.buffer[parser.buffer_pos+0] == '.' && | ||
2317 | parser.buffer[parser.buffer_pos+1] == '.' && | ||
2318 | parser.buffer[parser.buffer_pos+2] == '.')) && | ||
2319 | is_blankz(parser.buffer, parser.buffer_pos+3) { | ||
2320 | yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", | ||
2321 | start_mark, "found unexpected document indicator") | ||
2322 | return false | ||
2323 | } | ||
2324 | |||
2325 | // Check for EOF. | ||
2326 | if is_z(parser.buffer, parser.buffer_pos) { | ||
2327 | yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", | ||
2328 | start_mark, "found unexpected end of stream") | ||
2329 | return false | ||
2330 | } | ||
2331 | |||
2332 | // Consume non-blank characters. | ||
2333 | leading_blanks := false | ||
2334 | for !is_blankz(parser.buffer, parser.buffer_pos) { | ||
2335 | if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' { | ||
2336 | // Is is an escaped single quote. | ||
2337 | s = append(s, '\'') | ||
2338 | skip(parser) | ||
2339 | skip(parser) | ||
2340 | |||
2341 | } else if single && parser.buffer[parser.buffer_pos] == '\'' { | ||
2342 | // It is a right single quote. | ||
2343 | break | ||
2344 | } else if !single && parser.buffer[parser.buffer_pos] == '"' { | ||
2345 | // It is a right double quote. | ||
2346 | break | ||
2347 | |||
2348 | } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) { | ||
2349 | // It is an escaped line break. | ||
2350 | if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { | ||
2351 | return false | ||
2352 | } | ||
2353 | skip(parser) | ||
2354 | skip_line(parser) | ||
2355 | leading_blanks = true | ||
2356 | break | ||
2357 | |||
2358 | } else if !single && parser.buffer[parser.buffer_pos] == '\\' { | ||
2359 | // It is an escape sequence. | ||
2360 | code_length := 0 | ||
2361 | |||
2362 | // Check the escape character. | ||
2363 | switch parser.buffer[parser.buffer_pos+1] { | ||
2364 | case '0': | ||
2365 | s = append(s, 0) | ||
2366 | case 'a': | ||
2367 | s = append(s, '\x07') | ||
2368 | case 'b': | ||
2369 | s = append(s, '\x08') | ||
2370 | case 't', '\t': | ||
2371 | s = append(s, '\x09') | ||
2372 | case 'n': | ||
2373 | s = append(s, '\x0A') | ||
2374 | case 'v': | ||
2375 | s = append(s, '\x0B') | ||
2376 | case 'f': | ||
2377 | s = append(s, '\x0C') | ||
2378 | case 'r': | ||
2379 | s = append(s, '\x0D') | ||
2380 | case 'e': | ||
2381 | s = append(s, '\x1B') | ||
2382 | case ' ': | ||
2383 | s = append(s, '\x20') | ||
2384 | case '"': | ||
2385 | s = append(s, '"') | ||
2386 | case '\'': | ||
2387 | s = append(s, '\'') | ||
2388 | case '\\': | ||
2389 | s = append(s, '\\') | ||
2390 | case 'N': // NEL (#x85) | ||
2391 | s = append(s, '\xC2') | ||
2392 | s = append(s, '\x85') | ||
2393 | case '_': // #xA0 | ||
2394 | s = append(s, '\xC2') | ||
2395 | s = append(s, '\xA0') | ||
2396 | case 'L': // LS (#x2028) | ||
2397 | s = append(s, '\xE2') | ||
2398 | s = append(s, '\x80') | ||
2399 | s = append(s, '\xA8') | ||
2400 | case 'P': // PS (#x2029) | ||
2401 | s = append(s, '\xE2') | ||
2402 | s = append(s, '\x80') | ||
2403 | s = append(s, '\xA9') | ||
2404 | case 'x': | ||
2405 | code_length = 2 | ||
2406 | case 'u': | ||
2407 | code_length = 4 | ||
2408 | case 'U': | ||
2409 | code_length = 8 | ||
2410 | default: | ||
2411 | yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", | ||
2412 | start_mark, "found unknown escape character") | ||
2413 | return false | ||
2414 | } | ||
2415 | |||
2416 | skip(parser) | ||
2417 | skip(parser) | ||
2418 | |||
2419 | // Consume an arbitrary escape code. | ||
2420 | if code_length > 0 { | ||
2421 | var value int | ||
2422 | |||
2423 | // Scan the character value. | ||
2424 | if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) { | ||
2425 | return false | ||
2426 | } | ||
2427 | for k := 0; k < code_length; k++ { | ||
2428 | if !is_hex(parser.buffer, parser.buffer_pos+k) { | ||
2429 | yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", | ||
2430 | start_mark, "did not find expected hexdecimal number") | ||
2431 | return false | ||
2432 | } | ||
2433 | value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k) | ||
2434 | } | ||
2435 | |||
2436 | // Check the value and write the character. | ||
2437 | if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF { | ||
2438 | yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", | ||
2439 | start_mark, "found invalid Unicode character escape code") | ||
2440 | return false | ||
2441 | } | ||
2442 | if value <= 0x7F { | ||
2443 | s = append(s, byte(value)) | ||
2444 | } else if value <= 0x7FF { | ||
2445 | s = append(s, byte(0xC0+(value>>6))) | ||
2446 | s = append(s, byte(0x80+(value&0x3F))) | ||
2447 | } else if value <= 0xFFFF { | ||
2448 | s = append(s, byte(0xE0+(value>>12))) | ||
2449 | s = append(s, byte(0x80+((value>>6)&0x3F))) | ||
2450 | s = append(s, byte(0x80+(value&0x3F))) | ||
2451 | } else { | ||
2452 | s = append(s, byte(0xF0+(value>>18))) | ||
2453 | s = append(s, byte(0x80+((value>>12)&0x3F))) | ||
2454 | s = append(s, byte(0x80+((value>>6)&0x3F))) | ||
2455 | s = append(s, byte(0x80+(value&0x3F))) | ||
2456 | } | ||
2457 | |||
2458 | // Advance the pointer. | ||
2459 | for k := 0; k < code_length; k++ { | ||
2460 | skip(parser) | ||
2461 | } | ||
2462 | } | ||
2463 | } else { | ||
2464 | // It is a non-escaped non-blank character. | ||
2465 | s = read(parser, s) | ||
2466 | } | ||
2467 | if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { | ||
2468 | return false | ||
2469 | } | ||
2470 | } | ||
2471 | |||
2472 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
2473 | return false | ||
2474 | } | ||
2475 | |||
2476 | // Check if we are at the end of the scalar. | ||
2477 | if single { | ||
2478 | if parser.buffer[parser.buffer_pos] == '\'' { | ||
2479 | break | ||
2480 | } | ||
2481 | } else { | ||
2482 | if parser.buffer[parser.buffer_pos] == '"' { | ||
2483 | break | ||
2484 | } | ||
2485 | } | ||
2486 | |||
2487 | // Consume blank characters. | ||
2488 | for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { | ||
2489 | if is_blank(parser.buffer, parser.buffer_pos) { | ||
2490 | // Consume a space or a tab character. | ||
2491 | if !leading_blanks { | ||
2492 | whitespaces = read(parser, whitespaces) | ||
2493 | } else { | ||
2494 | skip(parser) | ||
2495 | } | ||
2496 | } else { | ||
2497 | if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { | ||
2498 | return false | ||
2499 | } | ||
2500 | |||
2501 | // Check if it is a first line break. | ||
2502 | if !leading_blanks { | ||
2503 | whitespaces = whitespaces[:0] | ||
2504 | leading_break = read_line(parser, leading_break) | ||
2505 | leading_blanks = true | ||
2506 | } else { | ||
2507 | trailing_breaks = read_line(parser, trailing_breaks) | ||
2508 | } | ||
2509 | } | ||
2510 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
2511 | return false | ||
2512 | } | ||
2513 | } | ||
2514 | |||
2515 | // Join the whitespaces or fold line breaks. | ||
2516 | if leading_blanks { | ||
2517 | // Do we need to fold line breaks? | ||
2518 | if len(leading_break) > 0 && leading_break[0] == '\n' { | ||
2519 | if len(trailing_breaks) == 0 { | ||
2520 | s = append(s, ' ') | ||
2521 | } else { | ||
2522 | s = append(s, trailing_breaks...) | ||
2523 | } | ||
2524 | } else { | ||
2525 | s = append(s, leading_break...) | ||
2526 | s = append(s, trailing_breaks...) | ||
2527 | } | ||
2528 | trailing_breaks = trailing_breaks[:0] | ||
2529 | leading_break = leading_break[:0] | ||
2530 | } else { | ||
2531 | s = append(s, whitespaces...) | ||
2532 | whitespaces = whitespaces[:0] | ||
2533 | } | ||
2534 | } | ||
2535 | |||
2536 | // Eat the right quote. | ||
2537 | skip(parser) | ||
2538 | end_mark := parser.mark | ||
2539 | |||
2540 | // Create a token. | ||
2541 | *token = yaml_token_t{ | ||
2542 | typ: yaml_SCALAR_TOKEN, | ||
2543 | start_mark: start_mark, | ||
2544 | end_mark: end_mark, | ||
2545 | value: s, | ||
2546 | style: yaml_SINGLE_QUOTED_SCALAR_STYLE, | ||
2547 | } | ||
2548 | if !single { | ||
2549 | token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE | ||
2550 | } | ||
2551 | return true | ||
2552 | } | ||
2553 | |||
2554 | // Scan a plain scalar. | ||
2555 | func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool { | ||
2556 | |||
2557 | var s, leading_break, trailing_breaks, whitespaces []byte | ||
2558 | var leading_blanks bool | ||
2559 | var indent = parser.indent + 1 | ||
2560 | |||
2561 | start_mark := parser.mark | ||
2562 | end_mark := parser.mark | ||
2563 | |||
2564 | // Consume the content of the plain scalar. | ||
2565 | for { | ||
2566 | // Check for a document indicator. | ||
2567 | if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { | ||
2568 | return false | ||
2569 | } | ||
2570 | if parser.mark.column == 0 && | ||
2571 | ((parser.buffer[parser.buffer_pos+0] == '-' && | ||
2572 | parser.buffer[parser.buffer_pos+1] == '-' && | ||
2573 | parser.buffer[parser.buffer_pos+2] == '-') || | ||
2574 | (parser.buffer[parser.buffer_pos+0] == '.' && | ||
2575 | parser.buffer[parser.buffer_pos+1] == '.' && | ||
2576 | parser.buffer[parser.buffer_pos+2] == '.')) && | ||
2577 | is_blankz(parser.buffer, parser.buffer_pos+3) { | ||
2578 | break | ||
2579 | } | ||
2580 | |||
2581 | // Check for a comment. | ||
2582 | if parser.buffer[parser.buffer_pos] == '#' { | ||
2583 | break | ||
2584 | } | ||
2585 | |||
2586 | // Consume non-blank characters. | ||
2587 | for !is_blankz(parser.buffer, parser.buffer_pos) { | ||
2588 | |||
2589 | // Check for indicators that may end a plain scalar. | ||
2590 | if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) || | ||
2591 | (parser.flow_level > 0 && | ||
2592 | (parser.buffer[parser.buffer_pos] == ',' || | ||
2593 | parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' || | ||
2594 | parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || | ||
2595 | parser.buffer[parser.buffer_pos] == '}')) { | ||
2596 | break | ||
2597 | } | ||
2598 | |||
2599 | // Check if we need to join whitespaces and breaks. | ||
2600 | if leading_blanks || len(whitespaces) > 0 { | ||
2601 | if leading_blanks { | ||
2602 | // Do we need to fold line breaks? | ||
2603 | if leading_break[0] == '\n' { | ||
2604 | if len(trailing_breaks) == 0 { | ||
2605 | s = append(s, ' ') | ||
2606 | } else { | ||
2607 | s = append(s, trailing_breaks...) | ||
2608 | } | ||
2609 | } else { | ||
2610 | s = append(s, leading_break...) | ||
2611 | s = append(s, trailing_breaks...) | ||
2612 | } | ||
2613 | trailing_breaks = trailing_breaks[:0] | ||
2614 | leading_break = leading_break[:0] | ||
2615 | leading_blanks = false | ||
2616 | } else { | ||
2617 | s = append(s, whitespaces...) | ||
2618 | whitespaces = whitespaces[:0] | ||
2619 | } | ||
2620 | } | ||
2621 | |||
2622 | // Copy the character. | ||
2623 | s = read(parser, s) | ||
2624 | |||
2625 | end_mark = parser.mark | ||
2626 | if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { | ||
2627 | return false | ||
2628 | } | ||
2629 | } | ||
2630 | |||
2631 | // Is it the end? | ||
2632 | if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) { | ||
2633 | break | ||
2634 | } | ||
2635 | |||
2636 | // Consume blank characters. | ||
2637 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
2638 | return false | ||
2639 | } | ||
2640 | |||
2641 | for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { | ||
2642 | if is_blank(parser.buffer, parser.buffer_pos) { | ||
2643 | |||
2644 | // Check for tab characters that abuse indentation. | ||
2645 | if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) { | ||
2646 | yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", | ||
2647 | start_mark, "found a tab character that violates indentation") | ||
2648 | return false | ||
2649 | } | ||
2650 | |||
2651 | // Consume a space or a tab character. | ||
2652 | if !leading_blanks { | ||
2653 | whitespaces = read(parser, whitespaces) | ||
2654 | } else { | ||
2655 | skip(parser) | ||
2656 | } | ||
2657 | } else { | ||
2658 | if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { | ||
2659 | return false | ||
2660 | } | ||
2661 | |||
2662 | // Check if it is a first line break. | ||
2663 | if !leading_blanks { | ||
2664 | whitespaces = whitespaces[:0] | ||
2665 | leading_break = read_line(parser, leading_break) | ||
2666 | leading_blanks = true | ||
2667 | } else { | ||
2668 | trailing_breaks = read_line(parser, trailing_breaks) | ||
2669 | } | ||
2670 | } | ||
2671 | if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { | ||
2672 | return false | ||
2673 | } | ||
2674 | } | ||
2675 | |||
2676 | // Check indentation level. | ||
2677 | if parser.flow_level == 0 && parser.mark.column < indent { | ||
2678 | break | ||
2679 | } | ||
2680 | } | ||
2681 | |||
2682 | // Create a token. | ||
2683 | *token = yaml_token_t{ | ||
2684 | typ: yaml_SCALAR_TOKEN, | ||
2685 | start_mark: start_mark, | ||
2686 | end_mark: end_mark, | ||
2687 | value: s, | ||
2688 | style: yaml_PLAIN_SCALAR_STYLE, | ||
2689 | } | ||
2690 | |||
2691 | // Note that we change the 'simple_key_allowed' flag. | ||
2692 | if leading_blanks { | ||
2693 | parser.simple_key_allowed = true | ||
2694 | } | ||
2695 | return true | ||
2696 | } | ||