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