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"
117template<
typename HandlerT>
121 typedef HandlerT handler_type;
123 yaml_parser(std::string_view content, handler_type& hdl);
129 void check_or_begin_document();
130 void check_or_begin_map();
131 void check_or_begin_sequence();
132 void parse_value(
const char* p,
size_t len);
133 void push_value(
const char* p,
size_t len);
134 void parse_line(
const char* p,
size_t len);
135 void parse_map_key(
const char* p,
size_t len);
137 void handler_begin_parse();
138 void handler_end_parse();
139 void handler_begin_document();
140 void handler_end_document();
141 void handler_begin_sequence();
142 void handler_end_sequence();
143 void handler_begin_map();
144 void handler_end_map();
145 void handler_begin_map_key();
146 void handler_end_map_key();
147 void handler_string(
const char* p,
size_t n);
148 void handler_number(
double val);
149 void handler_boolean_true();
150 void handler_boolean_false();
154 handler_type& m_handler;
157template<
typename _Handler>
160 push_parse_token(yaml::detail::parse_token_t::begin_parse);
161 m_handler.begin_parse();
164template<
typename _Handler>
165void yaml_parser<_Handler>::handler_end_parse()
167 push_parse_token(yaml::detail::parse_token_t::end_parse);
168 m_handler.end_parse();
171template<
typename _Handler>
172void yaml_parser<_Handler>::handler_begin_document()
174 push_parse_token(yaml::detail::parse_token_t::begin_document);
175 m_handler.begin_document();
178template<
typename _Handler>
179void yaml_parser<_Handler>::handler_end_document()
181 push_parse_token(yaml::detail::parse_token_t::end_document);
182 m_handler.end_document();
185template<
typename _Handler>
186void yaml_parser<_Handler>::handler_begin_sequence()
188 push_parse_token(yaml::detail::parse_token_t::begin_sequence);
189 m_handler.begin_sequence();
192template<
typename _Handler>
193void yaml_parser<_Handler>::handler_end_sequence()
195 push_parse_token(yaml::detail::parse_token_t::end_sequence);
196 m_handler.end_sequence();
199template<
typename _Handler>
200void yaml_parser<_Handler>::handler_begin_map()
202 push_parse_token(yaml::detail::parse_token_t::begin_map);
203 m_handler.begin_map();
206template<
typename _Handler>
207void yaml_parser<_Handler>::handler_end_map()
209 push_parse_token(yaml::detail::parse_token_t::end_map);
213template<
typename _Handler>
214void yaml_parser<_Handler>::handler_begin_map_key()
216 push_parse_token(yaml::detail::parse_token_t::begin_map_key);
217 m_handler.begin_map_key();
220template<
typename _Handler>
221void yaml_parser<_Handler>::handler_end_map_key()
223 push_parse_token(yaml::detail::parse_token_t::end_map_key);
224 m_handler.end_map_key();
227template<
typename _Handler>
228void yaml_parser<_Handler>::handler_string(
const char* p,
size_t n)
230 push_parse_token(yaml::detail::parse_token_t::string);
231 m_handler.string({p, n});
234template<
typename _Handler>
235void yaml_parser<_Handler>::handler_number(
double val)
237 push_parse_token(yaml::detail::parse_token_t::number);
238 m_handler.number(val);
241template<
typename _Handler>
242void yaml_parser<_Handler>::handler_boolean_true()
244 push_parse_token(yaml::detail::parse_token_t::boolean_true);
245 m_handler.boolean_true();
248template<
typename _Handler>
249void yaml_parser<_Handler>::handler_boolean_false()
251 push_parse_token(yaml::detail::parse_token_t::boolean_false);
252 m_handler.boolean_false();
255template<
typename _Handler>
256void yaml_parser<_Handler>::handler_null()
258 push_parse_token(yaml::detail::parse_token_t::null);
262template<
typename _Handler>
263yaml_parser<_Handler>::yaml_parser(std::string_view content, handler_type& hdl) :
264 yaml::parser_base(content), m_handler(hdl) {}
266template<
typename _Handler>
267void yaml_parser<_Handler>::parse()
269 handler_begin_parse();
275 size_t indent = parse_indent();
276 if (indent == parse_indent_end_of_stream)
279 if (indent == parse_indent_blank_line)
282 size_t cur_scope = get_scope();
284 if (cur_scope <= indent)
286 if (in_literal_block())
288 handle_line_in_literal(indent);
292 if (has_line_buffer())
296 handle_line_in_multi_line_string();
301 if (cur_scope == scope_empty)
305 "first node of the document should not be indented.", offset());
309 else if (indent > cur_scope)
313 else if (indent < cur_scope)
318 cur_scope = end_scope();
319 if (cur_scope < indent)
320 throw parse_error(
"parse: invalid indent level.", offset());
322 while (indent < cur_scope);
326 std::string_view line = parse_to_end_of_line();
329 assert(!line.empty());
330 parse_line(line.data(), line.size());
334 size_t cur_scope = get_scope();
335 while (cur_scope != scope_empty)
336 cur_scope = end_scope();
339 handler_end_document();
344template<
typename _Handler>
345size_t yaml_parser<_Handler>::end_scope()
347 switch (get_scope_type())
349 case yaml::detail::scope_t::map:
351 if (get_last_parse_token() == yaml::detail::parse_token_t::end_map_key)
357 case yaml::detail::scope_t::sequence:
359 if (get_last_parse_token() == yaml::detail::parse_token_t::begin_sequence_element)
362 handler_end_sequence();
365 case yaml::detail::scope_t::multi_line_string:
367 std::string_view merged = merge_line_buffer();
368 handler_string(merged.data(), merged.size());
373 if (has_line_buffer())
375 assert(get_line_buffer_count() == 1);
376 std::string_view line = pop_line_front();
377 parse_value(line.data(), line.size());
384template<
typename _Handler>
385void yaml_parser<_Handler>::check_or_begin_document()
389 set_doc_hash(mp_char);
390 handler_begin_document();
394template<
typename _Handler>
395void yaml_parser<_Handler>::check_or_begin_map()
397 switch (get_scope_type())
399 case yaml::detail::scope_t::unset:
401 check_or_begin_document();
402 set_scope_type(yaml::detail::scope_t::map);
406 case yaml::detail::scope_t::map:
408 if (get_last_parse_token() == yaml::detail::parse_token_t::end_map_key)
417template<
typename _Handler>
418void yaml_parser<_Handler>::check_or_begin_sequence()
420 switch (get_scope_type())
422 case yaml::detail::scope_t::unset:
424 check_or_begin_document();
425 set_scope_type(yaml::detail::scope_t::sequence);
426 handler_begin_sequence();
429 case yaml::detail::scope_t::sequence:
431 if (get_last_parse_token() == yaml::detail::parse_token_t::begin_sequence_element)
439 push_parse_token(yaml::detail::parse_token_t::begin_sequence_element);
442template<
typename _Handler>
443void yaml_parser<_Handler>::parse_value(
const char* p,
size_t len)
445 check_or_begin_document();
448 const char* p_end = p + len;
450 p = parse_numeric(p, p_end, val);
457 yaml::detail::keyword_t kw = parse_keyword(p0, len);
459 if (kw != yaml::detail::keyword_t::unknown)
463 case yaml::detail::keyword_t::null:
466 case yaml::detail::keyword_t::boolean_true:
467 handler_boolean_true();
469 case yaml::detail::keyword_t::boolean_false:
470 handler_boolean_false();
480 handler_string(p0, len);
483template<
typename _Handler>
484void yaml_parser<_Handler>::push_value(
const char* p,
size_t len)
486 check_or_begin_document();
488 if (has_line_buffer() && get_scope_type() == yaml::detail::scope_t::unset)
489 set_scope_type(yaml::detail::scope_t::multi_line_string);
491 push_line_back(p, len);
494template<
typename _Handler>
495void yaml_parser<_Handler>::parse_line(
const char* p,
size_t len)
497 const char* p_end = p + len;
506 check_or_begin_sequence();
517 throw parse_error(
"parse_line: line ended with '--'.", offset_last_char_of_line());
520 parse_error::throw_with(
521 "parse_line: '-' expected but '", *p,
"' found.",
522 offset_last_char_of_line() - std::ptrdiff_t(p_end-p));
526 handler_begin_document();
531 skip_blanks(p, p_end-p);
536 parse_line(p, p_end-p);
542 check_or_begin_sequence();
548 "parse_line: list item expected, but the line ended prematurely.",
549 offset_last_char_of_line() - std::ptrdiff_t(p_end-p));
551 skip_blanks(p, p_end-p);
553 size_t scope_width = get_scope() + (p-p0);
554 push_scope(scope_width);
555 parse_line(p, p_end-p);
565 if (get_scope_type() == yaml::detail::scope_t::sequence)
566 parse_error::throw_with(
567 "'-' was expected for a sequence element, but '", *p,
"' was found.",
568 offset_last_char_of_line()-len+1);
571 parse_map_key(p, len);
574template<
typename _Handler>
575void yaml_parser<_Handler>::parse_map_key(
const char* p,
size_t len)
577 const char* p_end = p + len;
584 std::string_view quoted_str = parse_double_quoted_string_value(p, len);
588 handler_string(quoted_str.data(), quoted_str.size());
592 skip_blanks(p, p_end-p);
596 "parse_map_key: ':' is expected after the quoted string key.",
597 offset() - std::ptrdiff_t(p_end-p+1));
599 check_or_begin_map();
600 handler_begin_map_key();
601 handler_string(quoted_str.data(), quoted_str.size());
602 handler_end_map_key();
609 skip_blanks(p, p_end-p);
614 std::string_view quoted_str = parse_single_quoted_string_value(p, len);
618 handler_string(quoted_str.data(), quoted_str.size());
622 skip_blanks(p, p_end-p);
626 "parse_map_key: ':' is expected after the quoted string key.",
627 offset() - std::ptrdiff_t(p_end-p+1));
629 check_or_begin_map();
630 handler_begin_map_key();
631 handler_string(quoted_str.data(), quoted_str.size());
632 handler_end_map_key();
638 skip_blanks(p, p_end-p);
643 key_value kv = parse_key_value(p, p_end-p);
650 start_literal_block();
658 check_or_begin_map();
659 handler_begin_map_key();
660 parse_value(kv.key.data(), kv.key.size());
661 handler_end_map_key();
663 if (kv.value.empty())
672 start_literal_block();
679 "parse_map_key: sequence entry is not allowed as an inline map item.",
680 offset() - std::ptrdiff_t(p_end-p+1));
682 size_t scope_width = get_scope() + (p-p0);
683 push_scope(scope_width);
684 parse_line(p, p_end-p);
Definition yaml_parser_base.hpp:66
Definition yaml_parser.hpp:21
void end_map()
Definition yaml_parser.hpp:71
void begin_parse()
Definition yaml_parser.hpp:26
void end_sequence()
Definition yaml_parser.hpp:51
void end_parse()
Definition yaml_parser.hpp:31
void null()
Definition yaml_parser.hpp:106
void boolean_true()
Definition yaml_parser.hpp:96
void begin_map_key()
Definition yaml_parser.hpp:61
void boolean_false()
Definition yaml_parser.hpp:101
void begin_map()
Definition yaml_parser.hpp:56
void number(double val)
Definition yaml_parser.hpp:88
void end_document()
Definition yaml_parser.hpp:41
void begin_document()
Definition yaml_parser.hpp:36
void string(std::string_view value)
Definition yaml_parser.hpp:78
void begin_sequence()
Definition yaml_parser.hpp:46
void end_map_key()
Definition yaml_parser.hpp:66
Definition yaml_parser.hpp:119