8#ifndef INCLUDED_ORCUS_YAML_PARSER_HPP
9#define INCLUDED_ORCUS_YAML_PARSER_HPP
11#include "orcus/yaml_parser_base.hpp"
12#include "orcus/parser_global.hpp"
106template<
typename _Handler>
110 typedef _Handler handler_type;
112 yaml_parser(
const char* p,
size_t n, handler_type& hdl);
118 void check_or_begin_document();
119 void check_or_begin_map();
120 void check_or_begin_sequence();
121 void parse_value(
const char* p,
size_t len);
122 void push_value(
const char* p,
size_t len);
123 void parse_line(
const char* p,
size_t len);
124 void parse_map_key(
const char* p,
size_t len);
126 void handler_begin_parse();
127 void handler_end_parse();
128 void handler_begin_document();
129 void handler_end_document();
130 void handler_begin_sequence();
131 void handler_end_sequence();
132 void handler_begin_map();
133 void handler_end_map();
134 void handler_begin_map_key();
135 void handler_end_map_key();
136 void handler_string(
const char* p,
size_t n);
137 void handler_number(
double val);
138 void handler_boolean_true();
139 void handler_boolean_false();
143 handler_type& m_handler;
146template<
typename _Handler>
149 push_parse_token(yaml::detail::parse_token_t::begin_parse);
150 m_handler.begin_parse();
153template<
typename _Handler>
154void yaml_parser<_Handler>::handler_end_parse()
156 push_parse_token(yaml::detail::parse_token_t::end_parse);
157 m_handler.end_parse();
160template<
typename _Handler>
161void yaml_parser<_Handler>::handler_begin_document()
163 push_parse_token(yaml::detail::parse_token_t::begin_document);
164 m_handler.begin_document();
167template<
typename _Handler>
168void yaml_parser<_Handler>::handler_end_document()
170 push_parse_token(yaml::detail::parse_token_t::end_document);
171 m_handler.end_document();
174template<
typename _Handler>
175void yaml_parser<_Handler>::handler_begin_sequence()
177 push_parse_token(yaml::detail::parse_token_t::begin_sequence);
178 m_handler.begin_sequence();
181template<
typename _Handler>
182void yaml_parser<_Handler>::handler_end_sequence()
184 push_parse_token(yaml::detail::parse_token_t::end_sequence);
185 m_handler.end_sequence();
188template<
typename _Handler>
189void yaml_parser<_Handler>::handler_begin_map()
191 push_parse_token(yaml::detail::parse_token_t::begin_map);
192 m_handler.begin_map();
195template<
typename _Handler>
196void yaml_parser<_Handler>::handler_end_map()
198 push_parse_token(yaml::detail::parse_token_t::end_map);
202template<
typename _Handler>
203void yaml_parser<_Handler>::handler_begin_map_key()
205 push_parse_token(yaml::detail::parse_token_t::begin_map_key);
206 m_handler.begin_map_key();
209template<
typename _Handler>
210void yaml_parser<_Handler>::handler_end_map_key()
212 push_parse_token(yaml::detail::parse_token_t::end_map_key);
213 m_handler.end_map_key();
216template<
typename _Handler>
217void yaml_parser<_Handler>::handler_string(
const char* p,
size_t n)
219 push_parse_token(yaml::detail::parse_token_t::string);
220 m_handler.string(p, n);
223template<
typename _Handler>
224void yaml_parser<_Handler>::handler_number(
double val)
226 push_parse_token(yaml::detail::parse_token_t::number);
227 m_handler.number(val);
230template<
typename _Handler>
231void yaml_parser<_Handler>::handler_boolean_true()
233 push_parse_token(yaml::detail::parse_token_t::boolean_true);
234 m_handler.boolean_true();
237template<
typename _Handler>
238void yaml_parser<_Handler>::handler_boolean_false()
240 push_parse_token(yaml::detail::parse_token_t::boolean_false);
241 m_handler.boolean_false();
244template<
typename _Handler>
245void yaml_parser<_Handler>::handler_null()
247 push_parse_token(yaml::detail::parse_token_t::null);
251template<
typename _Handler>
252yaml_parser<_Handler>::yaml_parser(
const char* p,
size_t n, handler_type& hdl) :
253 yaml::parser_base(p, n), m_handler(hdl) {}
255template<
typename _Handler>
256void yaml_parser<_Handler>::parse()
258 handler_begin_parse();
264 size_t indent = parse_indent();
265 if (indent == parse_indent_end_of_stream)
268 if (indent == parse_indent_blank_line)
271 size_t cur_scope = get_scope();
273 if (cur_scope <= indent)
275 if (in_literal_block())
277 handle_line_in_literal(indent);
281 if (has_line_buffer())
285 handle_line_in_multi_line_string();
290 if (cur_scope == scope_empty)
293 throw yaml::parse_error(
294 "first node of the document should not be indented.", offset());
298 else if (indent > cur_scope)
302 else if (indent < cur_scope)
307 cur_scope = end_scope();
308 if (cur_scope < indent)
309 throw yaml::parse_error(
"parse: invalid indent level.", offset());
311 while (indent < cur_scope);
315 std::string_view line = parse_to_end_of_line();
318 assert(!line.empty());
319 parse_line(line.data(), line.size());
323 size_t cur_scope = get_scope();
324 while (cur_scope != scope_empty)
325 cur_scope = end_scope();
328 handler_end_document();
333template<
typename _Handler>
334size_t yaml_parser<_Handler>::end_scope()
336 switch (get_scope_type())
338 case yaml::detail::scope_t::map:
340 if (get_last_parse_token() == yaml::detail::parse_token_t::end_map_key)
346 case yaml::detail::scope_t::sequence:
348 if (get_last_parse_token() == yaml::detail::parse_token_t::begin_sequence_element)
351 handler_end_sequence();
354 case yaml::detail::scope_t::multi_line_string:
356 std::string_view merged = merge_line_buffer();
357 handler_string(merged.data(), merged.size());
362 if (has_line_buffer())
364 assert(get_line_buffer_count() == 1);
365 std::string_view line = pop_line_front();
366 parse_value(line.data(), line.size());
373template<
typename _Handler>
374void yaml_parser<_Handler>::check_or_begin_document()
378 set_doc_hash(mp_char);
379 handler_begin_document();
383template<
typename _Handler>
384void yaml_parser<_Handler>::check_or_begin_map()
386 switch (get_scope_type())
388 case yaml::detail::scope_t::unset:
390 check_or_begin_document();
391 set_scope_type(yaml::detail::scope_t::map);
395 case yaml::detail::scope_t::map:
397 if (get_last_parse_token() == yaml::detail::parse_token_t::end_map_key)
406template<
typename _Handler>
407void yaml_parser<_Handler>::check_or_begin_sequence()
409 switch (get_scope_type())
411 case yaml::detail::scope_t::unset:
413 check_or_begin_document();
414 set_scope_type(yaml::detail::scope_t::sequence);
415 handler_begin_sequence();
418 case yaml::detail::scope_t::sequence:
420 if (get_last_parse_token() == yaml::detail::parse_token_t::begin_sequence_element)
428 push_parse_token(yaml::detail::parse_token_t::begin_sequence_element);
431template<
typename _Handler>
432void yaml_parser<_Handler>::parse_value(
const char* p,
size_t len)
434 check_or_begin_document();
437 const char* p_end = p + len;
438 double val = parse_numeric(p, len);
445 yaml::detail::keyword_t kw = parse_keyword(p0, len);
447 if (kw != yaml::detail::keyword_t::unknown)
451 case yaml::detail::keyword_t::null:
454 case yaml::detail::keyword_t::boolean_true:
455 handler_boolean_true();
457 case yaml::detail::keyword_t::boolean_false:
458 handler_boolean_false();
468 handler_string(p0, len);
471template<
typename _Handler>
472void yaml_parser<_Handler>::push_value(
const char* p,
size_t len)
474 check_or_begin_document();
476 if (has_line_buffer() && get_scope_type() == yaml::detail::scope_t::unset)
477 set_scope_type(yaml::detail::scope_t::multi_line_string);
479 push_line_back(p, len);
482template<
typename _Handler>
483void yaml_parser<_Handler>::parse_line(
const char* p,
size_t len)
485 const char* p_end = p + len;
494 check_or_begin_sequence();
505 throw yaml::parse_error(
"parse_line: line ended with '--'.", offset_last_char_of_line());
508 yaml::parse_error::throw_with(
509 "parse_line: '-' expected but '", *p,
"' found.",
510 offset_last_char_of_line() - std::ptrdiff_t(p_end-p));
514 handler_begin_document();
519 skip_blanks(p, p_end-p);
524 parse_line(p, p_end-p);
530 check_or_begin_sequence();
535 throw yaml::parse_error(
536 "parse_line: list item expected, but the line ended prematurely.",
537 offset_last_char_of_line() - std::ptrdiff_t(p_end-p));
539 skip_blanks(p, p_end-p);
541 size_t scope_width = get_scope() + (p-p0);
542 push_scope(scope_width);
543 parse_line(p, p_end-p);
553 if (get_scope_type() == yaml::detail::scope_t::sequence)
554 yaml::parse_error::throw_with(
555 "'-' was expected for a sequence element, but '", *p,
"' was found.",
556 offset_last_char_of_line()-len+1);
559 parse_map_key(p, len);
562template<
typename _Handler>
563void yaml_parser<_Handler>::parse_map_key(
const char* p,
size_t len)
565 const char* p_end = p + len;
572 std::string_view quoted_str = parse_double_quoted_string_value(p, len);
576 handler_string(quoted_str.data(), quoted_str.size());
580 skip_blanks(p, p_end-p);
583 throw yaml::parse_error(
584 "parse_map_key: ':' is expected after the quoted string key.",
585 offset() - std::ptrdiff_t(p_end-p+1));
587 check_or_begin_map();
588 handler_begin_map_key();
589 handler_string(quoted_str.data(), quoted_str.size());
590 handler_end_map_key();
597 skip_blanks(p, p_end-p);
602 std::string_view quoted_str = parse_single_quoted_string_value(p, len);
606 handler_string(quoted_str.data(), quoted_str.size());
610 skip_blanks(p, p_end-p);
613 throw yaml::parse_error(
614 "parse_map_key: ':' is expected after the quoted string key.",
615 offset() - std::ptrdiff_t(p_end-p+1));
617 check_or_begin_map();
618 handler_begin_map_key();
619 handler_string(quoted_str.data(), quoted_str.size());
620 handler_end_map_key();
626 skip_blanks(p, p_end-p);
631 key_value kv = parse_key_value(p, p_end-p);
638 start_literal_block();
646 check_or_begin_map();
647 handler_begin_map_key();
648 parse_value(kv.key.data(), kv.key.size());
649 handler_end_map_key();
651 if (kv.value.empty())
660 start_literal_block();
666 throw yaml::parse_error(
667 "parse_map_key: sequence entry is not allowed as an inline map item.",
668 offset() - std::ptrdiff_t(p_end-p+1));
670 size_t scope_width = get_scope() + (p-p0);
671 push_scope(scope_width);
672 parse_line(p, p_end-p);
Definition: yaml_parser_base.hpp:75
Definition: yaml_parser.hpp:17
void end_map()
Definition: yaml_parser.hpp:67
void begin_parse()
Definition: yaml_parser.hpp:22
void end_sequence()
Definition: yaml_parser.hpp:47
void end_parse()
Definition: yaml_parser.hpp:27
void string(const char *p, size_t n)
Definition: yaml_parser.hpp:75
void boolean_true()
Definition: yaml_parser.hpp:93
void begin_map_key()
Definition: yaml_parser.hpp:57
void boolean_false()
Definition: yaml_parser.hpp:98
void begin_map()
Definition: yaml_parser.hpp:52
void number(double val)
Definition: yaml_parser.hpp:85
void end_document()
Definition: yaml_parser.hpp:37
void begin_document()
Definition: yaml_parser.hpp:32
void begin_sequence()
Definition: yaml_parser.hpp:42
void end_map_key()
Definition: yaml_parser.hpp:62
Definition: yaml_parser.hpp:108