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" 16 template<
typename _Handler>
20 typedef _Handler handler_type;
22 yaml_parser(
const char* p,
size_t n, handler_type& hdl);
28 void check_or_begin_document();
29 void check_or_begin_map();
30 void check_or_begin_sequence();
31 void parse_value(
const char* p,
size_t len);
32 void push_value(
const char* p,
size_t len);
33 void parse_line(
const char* p,
size_t len);
34 void parse_map_key(
const char* p,
size_t len);
36 void handler_begin_parse();
37 void handler_end_parse();
38 void handler_begin_document();
39 void handler_end_document();
40 void handler_begin_sequence();
41 void handler_end_sequence();
42 void handler_begin_map();
43 void handler_end_map();
44 void handler_begin_map_key();
45 void handler_end_map_key();
46 void handler_string(
const char* p,
size_t n);
47 void handler_number(
double val);
48 void handler_boolean_true();
49 void handler_boolean_false();
53 handler_type& m_handler;
56 template<
typename _Handler>
59 push_parse_token(yaml::detail::parse_token_t::begin_parse);
60 m_handler.begin_parse();
63 template<
typename _Handler>
64 void yaml_parser<_Handler>::handler_end_parse()
66 push_parse_token(yaml::detail::parse_token_t::end_parse);
67 m_handler.end_parse();
70 template<
typename _Handler>
71 void yaml_parser<_Handler>::handler_begin_document()
73 push_parse_token(yaml::detail::parse_token_t::begin_document);
74 m_handler.begin_document();
77 template<
typename _Handler>
78 void yaml_parser<_Handler>::handler_end_document()
80 push_parse_token(yaml::detail::parse_token_t::end_document);
81 m_handler.end_document();
84 template<
typename _Handler>
85 void yaml_parser<_Handler>::handler_begin_sequence()
87 push_parse_token(yaml::detail::parse_token_t::begin_sequence);
88 m_handler.begin_sequence();
91 template<
typename _Handler>
92 void yaml_parser<_Handler>::handler_end_sequence()
94 push_parse_token(yaml::detail::parse_token_t::end_sequence);
95 m_handler.end_sequence();
98 template<
typename _Handler>
99 void yaml_parser<_Handler>::handler_begin_map()
101 push_parse_token(yaml::detail::parse_token_t::begin_map);
102 m_handler.begin_map();
105 template<
typename _Handler>
106 void yaml_parser<_Handler>::handler_end_map()
108 push_parse_token(yaml::detail::parse_token_t::end_map);
112 template<
typename _Handler>
113 void yaml_parser<_Handler>::handler_begin_map_key()
115 push_parse_token(yaml::detail::parse_token_t::begin_map_key);
116 m_handler.begin_map_key();
119 template<
typename _Handler>
120 void yaml_parser<_Handler>::handler_end_map_key()
122 push_parse_token(yaml::detail::parse_token_t::end_map_key);
123 m_handler.end_map_key();
126 template<
typename _Handler>
127 void yaml_parser<_Handler>::handler_string(
const char* p,
size_t n)
129 push_parse_token(yaml::detail::parse_token_t::string);
130 m_handler.string(p, n);
133 template<
typename _Handler>
134 void yaml_parser<_Handler>::handler_number(
double val)
136 push_parse_token(yaml::detail::parse_token_t::number);
137 m_handler.number(val);
140 template<
typename _Handler>
141 void yaml_parser<_Handler>::handler_boolean_true()
143 push_parse_token(yaml::detail::parse_token_t::boolean_true);
144 m_handler.boolean_true();
147 template<
typename _Handler>
148 void yaml_parser<_Handler>::handler_boolean_false()
150 push_parse_token(yaml::detail::parse_token_t::boolean_false);
151 m_handler.boolean_false();
154 template<
typename _Handler>
155 void yaml_parser<_Handler>::handler_null()
157 push_parse_token(yaml::detail::parse_token_t::null);
161 template<
typename _Handler>
162 yaml_parser<_Handler>::yaml_parser(
const char* p,
size_t n, handler_type& hdl) :
163 yaml::parser_base(p, n), m_handler(hdl) {}
165 template<
typename _Handler>
166 void yaml_parser<_Handler>::parse()
168 handler_begin_parse();
174 size_t indent = parse_indent();
175 if (indent == parse_indent_end_of_stream)
178 if (indent == parse_indent_blank_line)
181 size_t cur_scope = get_scope();
183 if (cur_scope <= indent)
185 if (in_literal_block())
187 handle_line_in_literal(indent);
191 if (has_line_buffer())
195 handle_line_in_multi_line_string();
200 if (cur_scope == scope_empty)
203 throw yaml::parse_error(
204 "first node of the document should not be indented.", offset());
208 else if (indent > cur_scope)
212 else if (indent < cur_scope)
217 cur_scope = end_scope();
218 if (cur_scope < indent)
219 throw yaml::parse_error(
"parse: invalid indent level.", offset());
221 while (indent < cur_scope);
225 pstring line = parse_to_end_of_line();
228 assert(!line.empty());
229 parse_line(line.get(), line.size());
233 size_t cur_scope = get_scope();
234 while (cur_scope != scope_empty)
235 cur_scope = end_scope();
238 handler_end_document();
243 template<
typename _Handler>
244 size_t yaml_parser<_Handler>::end_scope()
246 switch (get_scope_type())
248 case yaml::detail::scope_t::map:
250 if (get_last_parse_token() == yaml::detail::parse_token_t::end_map_key)
256 case yaml::detail::scope_t::sequence:
258 if (get_last_parse_token() == yaml::detail::parse_token_t::begin_sequence_element)
261 handler_end_sequence();
264 case yaml::detail::scope_t::multi_line_string:
266 pstring merged = merge_line_buffer();
267 handler_string(merged.get(), merged.size());
272 if (has_line_buffer())
274 assert(get_line_buffer_count() == 1);
275 pstring line = pop_line_front();
276 parse_value(line.get(), line.size());
283 template<
typename _Handler>
284 void yaml_parser<_Handler>::check_or_begin_document()
288 set_doc_hash(mp_char);
289 handler_begin_document();
293 template<
typename _Handler>
294 void yaml_parser<_Handler>::check_or_begin_map()
296 switch (get_scope_type())
298 case yaml::detail::scope_t::unset:
300 check_or_begin_document();
301 set_scope_type(yaml::detail::scope_t::map);
305 case yaml::detail::scope_t::map:
307 if (get_last_parse_token() == yaml::detail::parse_token_t::end_map_key)
316 template<
typename _Handler>
317 void yaml_parser<_Handler>::check_or_begin_sequence()
319 switch (get_scope_type())
321 case yaml::detail::scope_t::unset:
323 check_or_begin_document();
324 set_scope_type(yaml::detail::scope_t::sequence);
325 handler_begin_sequence();
328 case yaml::detail::scope_t::sequence:
330 if (get_last_parse_token() == yaml::detail::parse_token_t::begin_sequence_element)
338 push_parse_token(yaml::detail::parse_token_t::begin_sequence_element);
341 template<
typename _Handler>
342 void yaml_parser<_Handler>::parse_value(
const char* p,
size_t len)
344 check_or_begin_document();
347 const char* p_end = p + len;
348 double val = parse_numeric(p, len);
355 yaml::detail::keyword_t kw = parse_keyword(p0, len);
357 if (kw != yaml::detail::keyword_t::unknown)
361 case yaml::detail::keyword_t::null:
364 case yaml::detail::keyword_t::boolean_true:
365 handler_boolean_true();
367 case yaml::detail::keyword_t::boolean_false:
368 handler_boolean_false();
378 handler_string(p0, len);
381 template<
typename _Handler>
382 void yaml_parser<_Handler>::push_value(
const char* p,
size_t len)
384 check_or_begin_document();
386 if (has_line_buffer() && get_scope_type() == yaml::detail::scope_t::unset)
387 set_scope_type(yaml::detail::scope_t::multi_line_string);
389 push_line_back(p, len);
392 template<
typename _Handler>
393 void yaml_parser<_Handler>::parse_line(
const char* p,
size_t len)
395 const char* p_end = p + len;
404 check_or_begin_sequence();
415 throw yaml::parse_error(
"parse_line: line ended with '--'.", offset_last_char_of_line());
418 yaml::parse_error::throw_with(
419 "parse_line: '-' expected but '", *p,
"' found.",
420 offset_last_char_of_line() - std::ptrdiff_t(p_end-p));
424 handler_begin_document();
429 skip_blanks(p, p_end-p);
434 parse_line(p, p_end-p);
440 check_or_begin_sequence();
445 throw yaml::parse_error(
446 "parse_line: list item expected, but the line ended prematurely.",
447 offset_last_char_of_line() - std::ptrdiff_t(p_end-p));
449 skip_blanks(p, p_end-p);
451 size_t scope_width = get_scope() + (p-p0);
452 push_scope(scope_width);
453 parse_line(p, p_end-p);
463 if (get_scope_type() == yaml::detail::scope_t::sequence)
464 yaml::parse_error::throw_with(
465 "'-' was expected for a sequence element, but '", *p,
"' was found.",
466 offset_last_char_of_line()-len+1);
469 parse_map_key(p, len);
472 template<
typename _Handler>
473 void yaml_parser<_Handler>::parse_map_key(
const char* p,
size_t len)
475 const char* p_end = p + len;
482 pstring quoted_str = parse_double_quoted_string_value(p, len);
486 handler_string(quoted_str.get(), quoted_str.size());
490 skip_blanks(p, p_end-p);
493 throw yaml::parse_error(
494 "parse_map_key: ':' is expected after the quoted string key.",
495 offset() - std::ptrdiff_t(p_end-p+1));
497 check_or_begin_map();
498 handler_begin_map_key();
499 handler_string(quoted_str.get(), quoted_str.size());
500 handler_end_map_key();
507 skip_blanks(p, p_end-p);
512 pstring quoted_str = parse_single_quoted_string_value(p, len);
516 handler_string(quoted_str.get(), quoted_str.size());
520 skip_blanks(p, p_end-p);
523 throw yaml::parse_error(
524 "parse_map_key: ':' is expected after the quoted string key.",
525 offset() - std::ptrdiff_t(p_end-p+1));
527 check_or_begin_map();
528 handler_begin_map_key();
529 handler_string(quoted_str.get(), quoted_str.size());
530 handler_end_map_key();
536 skip_blanks(p, p_end-p);
541 key_value kv = parse_key_value(p, p_end-p);
548 start_literal_block();
556 check_or_begin_map();
557 handler_begin_map_key();
558 parse_value(kv.key.get(), kv.key.size());
559 handler_end_map_key();
561 if (kv.value.empty())
570 start_literal_block();
576 throw yaml::parse_error(
577 "parse_map_key: sequence entry is not allowed as an inline map item.",
578 offset() - std::ptrdiff_t(p_end-p+1));
580 size_t scope_width = get_scope() + (p-p0);
581 push_scope(scope_width);
582 parse_line(p, p_end-p);
Definition: yaml_parser.hpp:17
Definition: base64.hpp:15
Definition: yaml_parser_base.hpp:75