1 #ifndef C4_YML_PARSE_ENGINE_HPP_
2 #define C4_YML_PARSE_ENGINE_HPP_
4 #ifndef C4_YML_PARSER_STATE_HPP_
7 #ifndef C4_YML_PARSE_OPTIONS_HPP_
10 #ifndef C4_YML_FWD_HPP_
16 # pragma warning(push)
17 # pragma warning(disable: 4251)
231 struct FilterResultExtending;
232 typedef enum BlockChomp_ {
258 Entry annotations[2];
289 template<
class EventHandler>
335 RYML_ASSERT_BASIC_(m_evt_handler);
336 m_evt_handler->m_stack.reserve(capacity);
343 _resize_locations(num_source_lines);
357 Callbacks const&
callbacks()
const { RYML_ASSERT_BASIC_(m_evt_handler);
return m_evt_handler->m_stack.m_callbacks; }
440 bool _scan_scalar_plain_blck(ScannedScalar *C4_RESTRICT sc,
size_t indentation);
441 bool _scan_scalar_plain_seq_flow(ScannedScalar *C4_RESTRICT sc);
442 bool _scan_scalar_plain_seq_blck(ScannedScalar *C4_RESTRICT sc);
443 bool _scan_scalar_plain_map_flow(ScannedScalar *C4_RESTRICT sc);
444 bool _scan_scalar_plain_map_blck(ScannedScalar *C4_RESTRICT sc);
445 bool _scan_scalar_map_json(ScannedScalar *C4_RESTRICT sc);
446 bool _scan_scalar_seq_json(ScannedScalar *C4_RESTRICT sc);
447 bool _scan_scalar_plain_unk(ScannedScalar *C4_RESTRICT sc);
448 bool _is_valid_start_scalar_plain_flow(
csubstr s);
449 bool _is_valid_start_scalar_plain_flow_check_block_token(
csubstr s);
450 bool _is_valid_start_scalar_plain_flow_check_qmrk(
csubstr s);
451 bool _scan_scalar_plain_handle_newline(
csubstr s,
size_t offs);
452 void _check_valid_newline_in_quoted_scalar();
454 ScannedScalar _scan_scalar_squot();
455 ScannedScalar _scan_scalar_dquot();
457 void _scan_block(ScannedBlock *C4_RESTRICT sb,
size_t indref);
470 csubstr _filter_scalar_literal(
substr s,
size_t indentation, BlockChomp_e chomp);
471 csubstr _filter_scalar_folded(
substr s,
size_t indentation, BlockChomp_e chomp);
474 csubstr _maybe_filter_key_scalar_plain(ScannedScalar
const& sc,
size_t indendation);
475 csubstr _maybe_filter_val_scalar_plain(ScannedScalar
const& sc,
size_t indendation);
476 csubstr _maybe_filter_key_scalar_squot(ScannedScalar
const& sc);
477 csubstr _maybe_filter_val_scalar_squot(ScannedScalar
const& sc);
478 csubstr _maybe_filter_key_scalar_dquot(ScannedScalar
const& sc);
479 csubstr _maybe_filter_val_scalar_dquot(ScannedScalar
const& sc);
480 csubstr _maybe_filter_key_scalar_literal(ScannedBlock
const& sb);
481 csubstr _maybe_filter_val_scalar_literal(ScannedBlock
const& sb);
482 csubstr _maybe_filter_key_scalar_folded(ScannedBlock
const& sb);
483 csubstr _maybe_filter_val_scalar_folded(ScannedBlock
const& sb);
488 void _handle_map_block();
489 bool _handle_map_block_qmrk();
490 bool _handle_map_block_rkcl();
491 void _handle_seq_block();
492 void _handle_map_flow();
493 void _handle_seq_flow();
494 void _handle_seq_imap();
495 void _handle_map_json();
496 void _handle_seq_json();
499 void _handle_unk_json();
503 void _handle_flow_skip_whitespace();
504 void _handle_flow_line_beginning();
506 size_t _handle_unk_check_left_tokens(
size_t realindent,
size_t col,
bool skip_annotations=
true);
507 void _handle_unk_get_first_non_pending_token_pos(
csubstr s,
size_t *indent,
size_t *first_non_token_pos);
508 void _handle_unk_begin_doc();
510 size_t _handle_block_skip_leading_whitespace();
512 size_t _handle_block_get_whitespace_mark() const noexcept {
return m_evt_handler->m_curr->pos.offset; }
513 void _handle_block_check_leading_tabs(
size_t prev_mark) {
return _handle_block_check_leading_tabs(prev_mark, m_evt_handler->m_curr->pos.offset); }
514 void _handle_block_check_leading_tabs(
size_t start_mark,
size_t end_mark);
516 void _end_map_flow();
517 void _end_seq_flow();
518 void _end_map_blck();
519 void _end_seq_blck();
522 void _end_flow_container(
size_t orig_indent,
bool multiline);
523 void _flow_container_was_a_key(
size_t orig_indent);
526 void _begin2_doc_expl();
528 void _end2_doc_expl();
529 void _check_doc_end_tokens()
const;
531 void _maybe_begin_doc();
532 void _maybe_end_doc();
534 void _start_doc_suddenly();
535 void _end_doc_suddenly();
536 void _end_doc_suddenly__pop();
537 void _check_trailing_doc_token();
540 void _set_indentation(
size_t indentation) noexcept;
541 void _save_indentation();
542 void _mark_seqflow_val_end() noexcept;
543 void _handle_indentation_pop_from_block_seq();
544 void _handle_indentation_pop_from_block_map();
545 void _handle_indentation_pop(ParserState const* dst);
547 void _maybe_skip_comment();
548 void _maybe_skip_comment_strict();
549 void _skip_comment();
550 void _maybe_skip_whitespace_tokens();
551 void _maybe_skipchars(
char c);
553 void _skipchars(const
char (&chars)[N]);
554 bool _maybe_scan_following_colon() noexcept;
559 template<class FilterProcessor> auto _filter_plain(FilterProcessor &C4_RESTRICT proc,
size_t indentation) -> decltype(proc.result());
560 template<class FilterProcessor> auto _filter_squoted(FilterProcessor &C4_RESTRICT proc) -> decltype(proc.result());
561 template<class FilterProcessor> auto _filter_dquoted(FilterProcessor &C4_RESTRICT proc) -> decltype(proc.result());
562 template<class FilterProcessor> auto _filter_block_literal(FilterProcessor &C4_RESTRICT proc,
size_t indentation, BlockChomp_e chomp) -> decltype(proc.result());
563 template<class FilterProcessor> auto _filter_block_folded(FilterProcessor &C4_RESTRICT proc,
size_t indentation, BlockChomp_e chomp) -> decltype(proc.result());
569 template<class FilterProcessor>
void _filter_nl_plain(FilterProcessor &C4_RESTRICT proc,
size_t indentation);
570 template<class FilterProcessor>
void _filter_nl_squoted(FilterProcessor &C4_RESTRICT proc);
571 template<class FilterProcessor>
void _filter_nl_dquoted(FilterProcessor &C4_RESTRICT proc);
573 template<class FilterProcessor>
bool _filter_ws_handle_to_first_non_space(FilterProcessor &C4_RESTRICT proc);
574 template<class FilterProcessor>
void _filter_ws_copy_trailing(FilterProcessor &C4_RESTRICT proc);
575 template<class FilterProcessor>
void _filter_ws_skip_trailing(FilterProcessor &C4_RESTRICT proc);
577 template<class FilterProcessor>
void _filter_dquoted_backslash(FilterProcessor &C4_RESTRICT proc);
578 template<class FilterProcessor>
void _filter_dquoted_backslash_decode(FilterProcessor &C4_RESTRICT proc,
size_t sz);
580 template<class FilterProcessor>
void _filter_chomp(FilterProcessor &C4_RESTRICT proc, BlockChomp_e chomp,
size_t indentation);
581 template<class FilterProcessor>
size_t _handle_all_whitespace(FilterProcessor &C4_RESTRICT proc, BlockChomp_e chomp);
582 template<class FilterProcessor>
size_t _extend_to_chomp(FilterProcessor &C4_RESTRICT proc,
size_t contents_len);
583 template<class FilterProcessor>
void _filter_block_indentation(FilterProcessor &C4_RESTRICT proc,
size_t indentation);
584 template<class FilterProcessor>
void _filter_block_folded_newlines(FilterProcessor &C4_RESTRICT proc,
size_t indentation,
size_t len);
585 template<class FilterProcessor>
size_t _filter_block_folded_newlines_compress(FilterProcessor &C4_RESTRICT proc,
size_t num_newl,
size_t wpos_at_first_newl);
586 template<class FilterProcessor>
void _filter_block_folded_newlines_leading(FilterProcessor &C4_RESTRICT proc,
size_t indentation,
size_t len);
587 template<class FilterProcessor>
void _filter_block_folded_indented_block(FilterProcessor &C4_RESTRICT proc,
size_t indentation,
size_t len,
size_t curr_indentation) noexcept;
589 substr _alloc_arena(
size_t len,
substr *relocated=
nullptr);
590 substr _alloc_arena(
size_t len,
csubstr *relocated) {
return _alloc_arena(len, reinterpret_cast<substr*>(relocated)); }
596 void _line_progressed(
size_t ahead);
598 void _line_ended_undo();
600 bool _finished_file()
const;
601 bool _finished_line()
const;
604 substr _peek_next_line(
size_t pos=
npos)
const;
610 C4_ALWAYS_INLINE
substr _buf() const noexcept {
return m_evt_handler->m_src; }
612 C4_ALWAYS_INLINE
bool has_all(
ParserFlag_t f)
const noexcept {
return (m_evt_handler->m_curr->flags & f) == f; }
613 C4_ALWAYS_INLINE
bool has_any(
ParserFlag_t f)
const noexcept {
return (m_evt_handler->m_curr->flags & f) != 0; }
614 C4_ALWAYS_INLINE
bool has_none(
ParserFlag_t f)
const noexcept {
return (m_evt_handler->m_curr->flags & f) == 0; }
615 static C4_ALWAYS_INLINE
bool has_all(
ParserFlag_t f, ParserState
const* C4_RESTRICT s) noexcept {
return (s->flags & f) == f; }
616 static C4_ALWAYS_INLINE
bool has_any(
ParserFlag_t f, ParserState
const* C4_RESTRICT s) noexcept {
return (s->flags & f) != 0; }
617 static C4_ALWAYS_INLINE
bool has_none(
ParserFlag_t f, ParserState
const* C4_RESTRICT s) noexcept {
return (s->flags & f) == 0; }
620 C4_ALWAYS_INLINE
void add_flags(
ParserFlag_t on) noexcept { m_evt_handler->m_curr->flags |= on; }
621 C4_ALWAYS_INLINE
void addrem_flags(
ParserFlag_t on,
ParserFlag_t off) noexcept { m_evt_handler->m_curr->flags &= ~off; m_evt_handler->m_curr->flags |= on; }
622 C4_ALWAYS_INLINE
void rem_flags(
ParserFlag_t off) noexcept { m_evt_handler->m_curr->flags &= ~off; }
631 void _prepare_locations();
632 void _resize_locations(
size_t sz);
633 bool _locations_dirty()
const;
641 template<
class ...Args> C4_NORETURN C4_NO_INLINE
void _err(Location
const& cpploc,
const char *fmt,
Args const& ...args)
const;
642 template<
class ...Args> C4_NORETURN C4_NO_INLINE
void _err(Location
const& cpploc, Location
const& ymlloc,
const char *fmt,
Args const& ...args)
const;
644 template<
class ...Args> C4_NO_INLINE
void _dbg(
csubstr fmt,
Args const& ...args)
const;
645 template<
class DumpFn> C4_NO_INLINE
void _fmt_msg(DumpFn &&dumpfn)
const;
646 C4_NO_INLINE
void _print_state_stack()
const;
647 C4_NO_INLINE
void _print_state_stack(
substr buf)
const;
652 void _handle_colon();
653 void _add_annotation(Annotation *C4_RESTRICT dst,
csubstr str,
size_t indentation,
size_t line);
654 void _add_annotation(Annotation *C4_RESTRICT dst,
csubstr str,
size_t indentation,
size_t line,
csubstr orig);
655 void _add_annotation(Annotation *C4_RESTRICT dst,
csubstr str);
656 C4_ALWAYS_INLINE
void _clear_annotations(Annotation *C4_RESTRICT dst) noexcept { dst->num_entries = 0; }
657 bool _annotations_require_key_container()
const;
658 bool _handle_annotations_before_unexpected_flow_token_rkey();
659 void _handle_annotations_before_blck_key_scalar();
660 void _handle_annotations_before_blck_val_scalar();
661 void _handle_annotations_before_start_mapblck(
size_t current_line);
662 void _handle_annotations_before_start_mapblck_as_key();
663 void _handle_annotations_and_indentation_after_start_mapblck(
size_t key_indentation,
size_t key_line);
664 size_t _select_indentation_from_annotations(
size_t val_indentation,
size_t val_line);
666 void _handle_keyref(
csubstr alias);
667 void _handle_valref(
csubstr alias);
669 void _handle_directive(
csubstr rem);
671 bool _validate_directive_tag(
csubstr *C4_RESTRICT directive,
csubstr *C4_RESTRICT handle,
csubstr *C4_RESTRICT prefix)
const;
677 ParserOptions m_options;
682 EventHandler *C4_RESTRICT m_evt_handler;
687 Annotation m_pending_anchors;
688 Annotation m_pending_tags;
690 bool m_has_directives_yaml;
691 bool m_has_directives;
694 size_t m_prev_val_end;
704 size_t *m_newline_offsets;
705 size_t m_newline_offsets_size;
706 size_t m_newline_offsets_capacity;
713 RYML_DEPRECATED(
"filter arena no longer needed") size_t filter_arena_capacity()
const {
return 0u; }
714 RYML_DEPRECATED(
"filter arena no longer needed") void reserve_filter_arena(
size_t) {}
716 template<
class U=EventHandler> RYML_DEPRECATED(
"removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_place(
csubstr filename,
substr yaml, Tree *t,
size_t node_id);
717 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_place(
substr yaml, Tree *t,
size_t node_id);
718 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_place(
csubstr filename,
substr yaml, Tree *t );
719 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_place(
substr yaml, Tree *t );
720 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_place(
csubstr filename,
substr yaml, NodeRef node );
721 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_place(
substr yaml, NodeRef node );
722 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree, Tree>::type
parse_in_place(
csubstr filename,
substr yaml );
723 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree, Tree>::type
parse_in_place(
substr yaml );
724 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_arena(
csubstr filename,
csubstr yaml, Tree *t,
size_t node_id);
725 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_arena(
csubstr yaml, Tree *t,
size_t node_id);
726 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_arena(
csubstr filename,
csubstr yaml, Tree *t );
727 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_arena(
csubstr yaml, Tree *t );
728 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_arena(
csubstr filename,
csubstr yaml, NodeRef node );
729 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_arena(
csubstr yaml, NodeRef node );
730 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree, Tree>::type
parse_in_arena(
csubstr filename,
csubstr yaml );
731 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the function in parse.hpp.") typename std::enable_if<U::is_wtree, Tree>::type
parse_in_arena(
csubstr yaml );
732 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the
csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_arena(
csubstr filename,
substr yaml, Tree *t,
size_t node_id);
733 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the
csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_arena(
substr yaml, Tree *t,
size_t node_id);
734 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the
csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_arena(
csubstr filename,
substr yaml, Tree *t );
735 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the
csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_arena(
substr yaml, Tree *t );
736 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the
csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_arena(
csubstr filename,
substr yaml, NodeRef node );
737 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the
csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree,
void>::type
parse_in_arena(
substr yaml, NodeRef node );
738 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the
csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree, Tree>::type
parse_in_arena(
csubstr filename,
substr yaml );
739 template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the
csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree, Tree>::type
parse_in_arena(
substr yaml );
742 RYML_DEPRECATED("moved to Tree::location(
Parser const&). deliberately undefined here.")
743 auto location(Tree const&,
id_type node) const -> typename std::enable_if<U::is_wtree, Location>::type;
746 RYML_DEPRECATED("moved to ConstNodeRef::location(
Parser const&), deliberately undefined here.")
747 auto location(ConstNodeRef const&) const -> typename std::enable_if<U::is_wtree, Location>::type;
755 C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wattributes")
756 C4_NO_INLINE inline
size_t _find_last_newline_and_larger_indentation(
csubstr s,
size_t indentation) noexcept
758 if(indentation + 1 > s.len)
760 for(
size_t i = s.len-indentation-1; i !=
size_t(-1); --i)
766 first = (first !=
npos) ? first : rem.len;
767 if(first > indentation)
773 C4_SUPPRESS_WARNING_GCC_POP
781 #if defined(_MSC_VER)
782 # pragma warning(pop)
size_t locations_capacity() const
enum c4::yml::Encoding_ Encoding_e
FilterResult filter_scalar_block_literal(csubstr scalar, substr dst, size_t indentation, BlockChomp_e chomp)
filter a block-literal scalar
FilterResult filter_scalar_block_folded(csubstr scalar, substr dst, size_t indentation, BlockChomp_e chomp)
filter a block-folded scalar
Location val_location(const char *val) const
Given a pointer to a buffer position, get the location.
FilterResult filter_scalar_block_folded_in_place(substr scalar, size_t cap, size_t indentation, BlockChomp_e chomp)
filter a block-folded scalar in place
void reserve_stack(id_type capacity)
Reserve a certain capacity for the parsing stack.
id_type stack_capacity() const
A c-style callbacks class to customize behavior on errors or allocation.
A parser event handler that creates a compact representation of the YAML tree in a contiguous buffer ...
FilterResult filter_scalar_plain_in_place(substr scalar, size_t cap, size_t indentation)
filter a plain scalar in place
FilterResult filter_scalar_squoted_in_place(substr scalar, size_t cap)
filter a single-quoted scalar in place
ParseEngine< EventHandlerTree > Parser
This is the main ryml parser, where the parser events are handled to create a ryml tree (see Event Ha...
FilterResultExtending filter_scalar_dquoted_in_place(substr scalar, size_t cap)
filter a double-quoted scalar in place
void parse_in_place_ev(csubstr filename, substr src)
parse YAML in place, emitting events to the current handler
void parse_json_in_place_ev(csubstr filename, substr src)
parse JSON in place, emitting events to the current handler
void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, Tree *tree, id_type node_id)
(1) parse YAML into an existing tree node. The filename will be used in any error messages arising du...
csubstr source() const
Get the latest YAML buffer parsed by this object.
ParserOptions const & options() const
Get the options used to build this parser object.
RYML_ID_TYPE id_type
The type of a node id in the YAML tree; to override the default type, define the macro RYML_ID_TYPE t...
Options to give to the ParseEngine to control its behavior.
void reserve_locations(size_t num_source_lines)
Reserve a certain capacity for the array used to track node locations in the source buffer...
basic_substring sub(size_t first) const noexcept
return [first,len[
FilterResult filter_scalar_block_literal_in_place(substr scalar, size_t cap, size_t indentation, BlockChomp_e chomp)
filter a block-literal scalar in place
basic_substring< char > substr
a mutable string view
basic_substring< const char > csubstr
an immutable string view
holds a source or yaml file position, for example when an error is detected; See also location_format...
No Byte Order Mark was found.
Encoding_e encoding() const
Get the encoding of the latest YAML buffer parsed by this object.
id_type estimate_tree_capacity(csubstr src)
Quickly inspect the source to estimate the number of nodes the resulting tree is likely to have...
This is the main driver of parsing logic: it scans the YAML or JSON source for tokens, and emits the appropriate sequence of parsing events to its event handler.
csubstr filename() const
Get the name of the latest file parsed by this object.
csubstr location_contents(Location const &loc) const
Get the string starting at a particular location, to the end of the parsed source buffer...
Callbacks const & callbacks() const
Get the current callbacks in the parser.
Result for filtering a scalar which not fit in the intended memory.
void parse_in_place(Parser *parser, csubstr filename, substr yaml, Tree *tree, id_type node_id)
(1) parse YAML into an existing tree node.
Result for filtering a scalar which not fit in the intended memory.
size_t first_not_of(const C c) const
FilterResult filter_scalar_squoted(csubstr scalar, substr dst)
filter a single-quoted scalar
FilterResult filter_scalar_plain(csubstr scalar, substr dst, size_t indentation)
filter a plain scalar
FilterResult filter_scalar_dquoted(csubstr scalar, substr dst)
filter a double-quoted scalar
int ParserFlag_t
data type for ParserState_e
ParseEngine(EventHandler *evt_handler, ParserOptions const &opts={})