YamlReference-0.2: Text/Yaml/Reference.bnf
-- ** Spec productions
--
-- These are copied directly from the spec, with the addition of the occasional
-- decision point and commitment.
c_printable = '\x9'
/ '\xA'
/ '\xD'
/ ('\x20', '\x7E')
/ '\x85'
/ ('\xA0', '\xD7FF')
/ ('\xE000', '\xFFFD')
/ ('\x10000', '\x10FFFF')
c_byte_order_mark = '\xFEFF' & detect_utf_encoding
-- Indicators:
c_sequence_entry = indicator '-'
c_mapping_key = indicator '?'
c_mapping_value = indicator ':'
c_collect_entry = indicator ','
c_sequence_start = indicator '['
c_sequence_end = indicator ']'
c_mapping_start = indicator '{'
c_mapping_end = indicator '}'
c_comment = indicator '#'
c_anchor = indicator '&'
c_alias = indicator '*'
c_tag = indicator '!'
c_literal = indicator '|'
c_folded = indicator '>'
c_single_quote = indicator '\''
c_double_quote = indicator '"'
c_directive = indicator '%'
c_reserved = indicator ( '@' / '`' )
c_indicator = c_sequence_entry
/ c_mapping_key
/ c_mapping_value
/ c_collect_entry
/ c_sequence_start
/ c_sequence_end
/ c_mapping_start
/ c_mapping_end
/ c_comment
/ c_anchor
/ c_alias
/ c_tag
/ c_literal
/ c_folded
/ c_single_quote
/ c_double_quote
/ c_directive
/ c_reserved
c_flow_indicator = c_collect_entry
/ c_sequence_start / c_sequence_end
/ c_mapping_start / c_mapping_end
-- Line breaks:
b_line_feed = '\xA'
b_carriage_return = '\xD'
b_next_line = '\x85'
b_line_separator = '\x2028'
b_paragraph_separator = '\x2029'
b_char = b_line_feed
/ b_carriage_return
/ b_next_line
/ b_line_separator
/ b_paragraph_separator
b_specific = ( b_line_separator / b_paragraph_separator )
& nextLine
b_generic = ( b_carriage_return & b_line_feed
/ b_carriage_return
/ b_line_feed
/ b_next_line )
& nextLine
b_as_line_feed = token LineFeed b_generic
b_normalized = b_as_line_feed / token Break b_specific
b_ignored_generic = token Continue b_generic
b_ignored_any = b_ignored_generic / token Continue b_specific
-- Chars:
nb_char = c_printable - b_char
s_space = '\x20'
s_tab = '\x9'
s_white = s_space / s_tab
ns_char = nb_char - s_white
ns_dec_digit = ('\x30', '\x39')
ns_hex_digit = ns_dec_digit / ('\x41', '\x46') / ('\x61', '\x66')
ns_ascii_letter = ('\x41', '\x5A') / ('\x61', '\x7A')
ns_word_char = ns_dec_digit / ns_ascii_letter / '-'
ns_uri_char = "escape"
^ ( ns_word_char
/ '%' ! "escape" & ns_hex_digit & ns_hex_digit
/ ';' / '/' / '?' / ':' / '@' / '&' / '=' / '+' / '$' / ','
/ '_' / '.' / '!' / '~' / '*' / '\'' / '(' / ')' / '[' / ']' )
ns_tag_char = ns_uri_char - c_tag
-- Escape:
c_escape = indicator '\\'
ns_esc_null = meta '0'
ns_esc_bell = meta 'a'
ns_esc_backspace = meta 'b'
ns_esc_horizontal_tab = meta ( 't' / '\x9' )
ns_esc_line_feed = meta 'n'
ns_esc_vertical_tab = meta 'v'
ns_esc_form_feed = meta 'f'
ns_esc_carriage_return = meta 'r'
ns_esc_escape = meta 'e'
ns_esc_space = meta '\x20'
ns_esc_double_quote = meta '"'
ns_esc_backslash = meta '\\'
ns_esc_next_line = meta 'N'
ns_esc_non_breaking_space = meta '_'
ns_esc_line_separator = meta 'L'
ns_esc_paragraph_separator = meta 'P'
ns_esc_8_bit = indicator 'x' ! "escaped" & meta ( ns_hex_digit % 2 )
ns_esc_16_bit = indicator 'u' ! "escaped" & meta ( ns_hex_digit % 4 )
ns_esc_32_bit = indicator 'U' ! "escaped" & meta ( ns_hex_digit % 8 )
ns_esc_char = nest BeginEscape
& c_escape ! "escape"
& "escaped"
^ ( ns_esc_null
/ ns_esc_bell
/ ns_esc_backspace
/ ns_esc_horizontal_tab
/ ns_esc_line_feed
/ ns_esc_vertical_tab
/ ns_esc_form_feed
/ ns_esc_carriage_return
/ ns_esc_escape
/ ns_esc_space
/ ns_esc_double_quote
/ ns_esc_backslash
/ ns_esc_next_line
/ ns_esc_non_breaking_space
/ ns_esc_line_separator
/ ns_esc_paragraph_separator
/ ns_esc_8_bit
/ ns_esc_16_bit
/ ns_esc_32_bit )
& nest EndEscape
-- Spaces:
s_indent n = token Indent ( s_space % n )
s_indent_lt n = token Indent ( s_space <% n )
s_indent_le n = token Indent ( s_space <% (n .+ 1) )
s_separate_in_line = token White ( s_white +) / sol
-- Empty lines
s_ignored_prefix n s = case s of
Plain -> s_ignored_prefix_flow n
Double -> s_ignored_prefix_flow n
Single -> s_ignored_prefix_flow n
Literal -> s_ignored_prefix_block n
Folded -> s_ignored_prefix_block n
s_ignored_prefix_flow n = s_indent n & ( s_separate_in_line ?)
s_ignored_prefix_block n = s_indent n
l_empty n s = ( s_ignored_prefix n s / s_indent_lt n ) & b_normalized
-- Comments: TODO
c_nb_comment_text = nest BeginComment
& c_comment & meta ( nb_char *)
& nest EndComment
s_b_comment = ( s_separate_in_line & ( c_nb_comment_text ?) ?) & b_ignored_any
s_l_comments = ( s_b_comment / sol ) & ( l_comment *)
l_comment = s_separate_in_line & ( c_nb_comment_text ?) & b_ignored_any
-- Folding:
b_l_folded_specific n s = token Break b_specific & ( l_empty n s *)
b_l_folded_as_space = token LineFold b_generic
b_l_folded_trimmed n s = b_ignored_generic & ( l_empty n s +)
b_l_folded_any n s = b_l_folded_specific n s / b_l_folded_trimmed n s / b_l_folded_as_space
s_l_flow_folded n = ( s_separate_in_line ?) & b_l_folded_any n Plain
-- Directives:
l_directive = nest BeginDirective
& c_directive
& "directive" ^ ( ns_yaml_directive / ns_tag_directive / ns_reserved_directive )
& nest EndDirective
& s_l_comments
ns_reserved_directive = ns_directive_name & ( s_separate_in_line & ns_directive_parameter *)
ns_directive_name = meta ( ns_char +)
ns_directive_parameter = meta ( ns_char +)
-- Yaml directive:
ns_yaml_directive = meta [ 'Y', 'A', 'M', 'L' ] ! "directive"
& s_separate_in_line & ns_yaml_version
ns_yaml_version = meta ( ( ns_dec_digit +) & '.' & ( ns_dec_digit +) )
-- Tag directive:
ns_tag_directive = meta [ 'T', 'A', 'G' ] ! "directive"
& s_separate_in_line & c_tag_handle
& s_separate_in_line & ns_tag_prefix
c_tag_handle = c_named_tag_handle
/ c_secondary_tag_handle
/ c_primary_tag_handle
c_primary_tag_handle = nest BeginHandle
& c_tag
& nest EndHandle
c_secondary_tag_handle = nest BeginHandle
& c_tag & c_tag
& nest EndHandle
c_named_tag_handle = nest BeginHandle
& c_tag & meta ( ns_word_char +) & c_tag
& nest EndHandle
ns_tag_prefix = nest BeginTag
& ( c_ns_local_tag_prefix / ns_global_tag_prefix )
& nest EndTag
c_ns_local_tag_prefix = c_tag & meta ( ns_uri_char *)
ns_global_tag_prefix = meta ( ns_tag_char & ( ns_uri_char *) )
-- Properties:
c_ns_properties = nest BeginProperties
& c_ns_property & ( s_separate_in_line & c_ns_property *)
& nest EndProperties
c_ns_property = c_ns_anchor_property / c_ns_tag_property
-- Tag:
c_ns_tag_property = nest BeginTag
& ( c_verbatim_tag / c_ns_shorthand_tag / c_non_specific_tag )
& nest EndTag
c_verbatim_tag = c_tag & indicator '<' & meta ( ns_uri_char +) & indicator '>'
c_ns_shorthand_tag = c_named_tag_handle & meta ( ns_uri_char +)
/ c_secondary_tag_handle & meta ( ns_uri_char +)
/ c_primary_tag_handle & meta ( ns_tag_char +)
c_non_specific_tag = c_tag
-- Anchor:
c_ns_anchor_property = nest BeginAnchor
& c_anchor & ns_anchor_name
& nest EndAnchor
ns_anchor_char = ns_char - c_flow_indicator
ns_anchor_name = meta ( ns_anchor_char +)
-- Double:
nb_double_char = "escape" ^ ( ns_esc_char / nb_char - c_escape - c_double_quote )
ns_double_char = nb_double_char - s_white
c_double_quoted n c = nest BeginScalar
& c_double_quote ! "node" & text ( nb_double_text n c ) & c_double_quote
& nest EndScalar
nb_double_text n c = case c of
FlowOut -> s_double_multi n
FlowIn -> s_double_multi n
FlowKey -> ( nb_double_char *)
s_double_multi n = ( s_ns_double_chars *)
& ( s_ns_double_next n *)
& ( s_white *)
s_ns_double_chars = ( s_white *) & ns_double_char
s_ns_double_next n = s_l_double_any n
& s_ignored_prefix n Double
& ( ns_double_char & ( s_ns_double_chars *) ?)
s_l_double_any n = "escape" ^ ( s_b_double_escaped / s_l_flow_folded n )
s_b_double_escaped = ( s_white *)
& nest BeginEscape
& c_escape ! "escape"
& b_ignored_any
& nest EndEscape
-- Single:
c_quoted_quote = nest BeginEscape
& c_single_quote ! "escape" & meta '\''
& nest EndEscape
nb_single_char = "escape" ^ ( c_quoted_quote / nb_char - c_single_quote )
ns_single_char = nb_single_char - s_white
c_single_quoted n c = nest BeginScalar
& c_single_quote & text ( nb_single_text n c ) & c_single_quote
& nest EndScalar
nb_single_text n c = case c of
FlowOut -> s_single_multi n
FlowIn -> s_single_multi n
FlowKey -> ( nb_single_char *)
s_ns_single_chars = ( s_white *) & ns_single_char
s_single_multi n = ( s_ns_single_chars *)
& ( s_ns_single_next n *)
& ( s_white *)
s_ns_single_next n = s_l_flow_folded n
& s_ignored_prefix n Double
& ( ns_single_char & ( s_ns_single_chars *) ?)
-- Plain:
ns_plain_safe c = case c of
FlowOut -> ns_plain_safe_out
FlowIn -> ns_plain_safe_in
FlowKey -> ns_plain_safe_in
ns_plain_safe_out = ns_char - c_mapping_value - c_comment
ns_plain_safe_in = ns_plain_safe_out - c_flow_indicator
ns_plain_char c = ( ':' +) & ( '#' / ns_plain_safe c ) & ( '#' *)
/ ns_plain_safe c & ( '#' *)
nb_plain_char c = s_white / ns_plain_char c
ns_plain_first c = ( '-' / '?' / ':' ) & ( ( '#' +) / ns_plain_char c )
/ ns_plain_char c - c_indicator
ns_plain n c = nest BeginScalar
& text (case c of
FlowOut -> ns_plain_multi n c
FlowIn -> ns_plain_multi n c
FlowKey -> ns_plain_single c)
& nest EndScalar
ns_plain_single c = ns_plain_first c ! "node" & ( s_ns_plain_chars c *)
s_ns_plain_chars c = ( s_white *) & ns_plain_char c
ns_plain_multi n c = ns_plain_single c & ( s_ns_plain_next n c *)
s_ns_plain_next n c = s_l_flow_folded n
& s_ignored_prefix n Plain
& ns_plain_char c
& ( s_ns_plain_chars c *)
-- Separation: TODO
s_separate_in_flow n c = case c of
FlowOut -> s_separate_lines n
FlowIn -> s_separate_lines n
FlowKey -> s_separate_in_line
s_separate_lines n = s_l_comments & s_ignored_prefix_flow n
/ s_separate_in_line
-- Flow collection:
in_flow c = case c of
FlowOut -> FlowIn
FlowIn -> FlowIn
FlowKey -> FlowKey
-- Flow sequence:
c_flow_sequence n c = nest BeginSequence
& c_sequence_start ! "node"
& ( s_separate_in_flow n c ?)
& ( ns_s_flow_seq_entries n (in_flow c) ?)
& c_sequence_end
& nest EndSequence
ns_s_flow_seq_entries n c = ns_flow_seq_entry n c
& ( s_separate_in_flow n c ?)
& ( c_collect_entry
& ( s_separate_in_flow n c ?)
& ( ns_s_flow_seq_entries n c ?) ?)
ns_flow_seq_entry n c = "pair" ^ ( ns_flow_map_single_pair n c / "node" ^ ns_flow_node n c )
-- Flow mapping:
c_flow_mapping n c = nest BeginMapping
& c_mapping_start ! "node"
& ( s_separate_in_flow n c ?)
& ( ns_s_flow_map_entries n (in_flow c) ?)
& c_mapping_end
& nest EndMapping
ns_s_flow_map_entries n c = ns_flow_map_entry n c
& ( s_separate_in_flow n c ?)
& ( c_collect_entry
& ( s_separate_in_flow n c ?)
& ( ns_s_flow_map_entries n c ?) ?)
ns_flow_map_entry n c = nest BeginPair
& "pair"
^ ( c_mapping_key ! "pair" & s_ns_flow_map_explicit_entry n c
/ ns_flow_map_implicit_entry n c )
& nest EndPair
s_ns_flow_map_explicit_entry n c = "entry"
^ ( s_ns_flow_map_explicit_json n c
/ s_ns_flow_map_explicit_yaml n c
/ s_ns_flow_map_explicit_empty n c
/ e_node & e_node )
s_ns_flow_map_explicit_json n c = s_separate_in_flow n c
& ( "node" ^ c_flow_json_node n c ) ! "entry"
& ( ( s_separate_in_flow n c ?) & c_ns_flow_map_adjacent_value n c
/ e_node )
s_ns_flow_map_explicit_yaml n c = s_separate_in_flow n c
& ( "node" ^ ns_flow_yaml_node n c ) ! "entry"
& ( ( s_separate_in_flow n c ?) & c_ns_flow_map_separate_value n c
/ e_node )
s_ns_flow_map_explicit_empty n c = s_separate_in_flow n c & e_node & c_ns_flow_map_separate_value n c
c_ns_flow_map_separate_value n c = c_mapping_value ! "pair"
& ( s_separate_in_flow n c & ns_flow_node n c
/ e_node )
c_ns_flow_map_adjacent_value n c = c_mapping_value ! "pair"
& ( ( s_separate_in_flow n c ?) & ns_flow_node n c
/ e_node )
ns_flow_map_implicit_entry n c = c_ns_flow_map_implicit_json n c
/ ns_flow_map_implicit_yaml n c
/ ns_flow_map_implicit_empty n c
c_ns_flow_map_implicit_json n c = c_s_simple_json_key & ( c_ns_flow_map_adjacent_value n c / e_node )
ns_flow_map_implicit_yaml n c = ns_s_simple_yaml_key & ( c_ns_flow_map_separate_value n c / e_node )
ns_flow_map_implicit_empty n c = e_node & c_ns_flow_map_separate_value n c
c_s_simple_json_key = ( "node" ^ ( c_flow_json_node na FlowKey ) & ( s_separate_in_line ?) ) `limitedTo` 1024
ns_s_simple_yaml_key = ( "node" ^ ( ns_flow_yaml_node na FlowKey ) & ( s_separate_in_line ?) ) `limitedTo` 1024
ns_flow_map_single_pair n c = nest BeginMapping
& nest BeginPair
& ( c_mapping_key ! "pair" & s_ns_flow_map_explicit_entry n c
/ ns_flow_map_single_entry n c )
& nest EndPair
& nest EndMapping
ns_flow_map_single_entry n c = "entry"
^ ( c_ns_flow_map_single_json n c
/ ns_flow_map_single_yaml n c
/ ns_flow_map_implicit_empty n c )
c_ns_flow_map_single_json n c = c_s_simple_json_key & c_ns_flow_map_adjacent_value n c
ns_flow_map_single_yaml n c = ns_s_simple_yaml_key & c_ns_flow_map_separate_value n c
-- Alias:
c_ns_alias = nest BeginAlias
& c_alias ! "node" & ns_anchor_name
& nest EndAlias
-- Empty:
e_scalar = nest BeginScalar & nest EndScalar
e_node = nest BeginNode & e_scalar & nest EndNode
-- Flow node:
ns_flow_content n c = c_flow_json_content n c
/ ns_flow_yaml_content n c
c_flow_json_content n c = c_flow_sequence n c
/ c_flow_mapping n c
/ c_single_quoted n c
/ c_double_quoted n c
ns_flow_yaml_content n c = ns_plain n c
c_flow_json_node n c = nest BeginNode
& ( c_ns_properties & s_separate_in_line ?)
& c_flow_json_content n c
& nest EndNode
ns_flow_yaml_node n c = nest BeginNode
& ( c_ns_alias
/ ( c_ns_properties
& ( s_separate_in_line & ns_flow_yaml_content n c
/ e_scalar ) )
/ ns_flow_yaml_content n c )
& nest EndNode
ns_flow_node n c = nest BeginNode
& ( c_ns_alias
/ ( c_ns_properties
& ( s_separate_in_line & ns_flow_content n c
/ e_scalar ) )
/ ns_flow_content n c )
& nest EndNode
-- Block scalar:
c_indentation_indicator n = indicator ( ns_dec_digit - '0' ) & asInteger
/ detect_scalar_indentation n
detect_scalar_indentation n = peek $ ( nb_char *)
& ( b_ignored_any & ( l_empty n Literal *) ?)
& count_spaces (-n)
count_spaces n = (s_space & count_spaces (n .+ 1))
/ result (max 1 n)
c_style_indicator s = case s of
Literal -> indicator '|'
Folded -> indicator '>'
c_chomping_indicator = indicator '-' & result Strip
/ indicator '+' ! "header" & result Keep
/ result Clip
c_b__block_header n s = c_style_indicator s ! "node"
& "header"
^ ( do t <- c_chomping_indicator
m <- c_indentation_indicator n
( s_white / b_char ) ?! "header"
s_b_comment
result (m, t)
/ do m <- c_indentation_indicator n
t <- c_chomping_indicator
s_b_comment
result (m, t) )
-- Chomping:
b_chomped_last t = case t of
Strip -> nest EndScalar & b_ignored_any
Clip -> b_normalized & nest EndScalar
Keep -> b_normalized
l_chomped_empty n t = case t of
Strip -> l_strip_empty n
Clip -> l_strip_empty n
Keep -> l_keep_empty n
l_strip_empty n = ( s_indent_le n & b_ignored_any *)
& ( l_trail_comments n ?)
l_keep_empty n = ( s_indent_le n & b_normalized *)
& nest EndScalar
& ( l_trail_comments n ?)
l_trail_comments n = s_indent_lt n & c_nb_comment_text & b_ignored_any
& ( l_comment *)
-- Literal:
c_l__literal n = do nest BeginScalar
(m, t) <- c_b__block_header n Literal
text ( l_literal_content (n .+ m) t )
l_nb_literal_chars n = ( l_empty n Literal *) & s_indent n & ( nb_char +)
b_l_literal_next n = b_normalized & l_nb_literal_chars n
l_literal_content n t = ( l_nb_literal_chars n & ( b_l_literal_next n *) & b_chomped_last t ?)
& l_chomped_empty n t
-- Folded:
c_l__folded n = do nest BeginScalar
(m, t) <- c_b__block_header n Folded
text ( l_folded_content (n .+ m) t )
s_nb_folded_text n = s_indent n & ns_char ! "fold" & ( nb_char *)
l_nb_folded_lines n = s_nb_folded_text n
& ( b_l_folded_any n Folded & s_nb_folded_text n *)
l_nb_start_with_folded n = ( l_empty n Folded *)
& l_nb_folded_lines n
& ( b_normalized & l_nb_start_with_spaced n ?)
s_nb_spaced_text n = s_indent n & s_white ! "fold" & ( nb_char *)
b_l_spaced n = b_normalized & ( l_empty n Folded *)
l_nb_spaced_lines n = s_nb_spaced_text n
& ( b_l_spaced n & s_nb_spaced_text n *)
l_nb_start_with_spaced n = ( l_empty n Folded *)
& l_nb_spaced_lines n
& ( b_normalized & l_nb_start_with_folded n ?)
l_nb_start_with_any n = "fold" ^ ( l_nb_start_with_folded n / l_nb_start_with_spaced n )
l_folded_content n t = ( l_nb_start_with_any n & b_chomped_last t ?)
& l_chomped_empty n t
-- Block sequence:
seq_spaces n c = case c of
BlockOut -> n
BlockIn -> n .- 1
l__block_sequence n = do m <- detect_collection_indentation n
( nest BeginSequence
& ( s_indent (n .+ m) & c_l_block_seq_entry (n .+ m) +)
& nest EndSequence )
detect_collection_indentation n = peek $ ( l_comment* ) & count_spaces (-n)
c_l_block_seq_entry n = c_sequence_entry ! "node" & s_l__block_indented n BlockOut
s_l__block_indented n c = do m <- detect_inline_indentation
( s_indent m
& "node"
^ ( ns_l_in_line_sequence (n .+ 1 .+ m)
/ ns_l_in_line_mapping (n .+ 1 .+ m) ) )
/ s_l__block_node n c
/ e_node & s_l_comments
detect_inline_indentation = peek $ count_spaces 0
ns_l_in_line_sequence n = nest BeginNode
& nest BeginSequence
& c_l_block_seq_entry n
& ( s_indent n & c_l_block_seq_entry n *)
& nest EndSequence
& nest EndNode
-- Block mapping:
l__block_mapping n = do m <- detect_collection_indentation n
( nest BeginMapping
& ( s_indent (n .+ m) & ns_l_block_map_entry (n .+ m) +)
& nest EndMapping )
ns_l_block_map_entry n = nest BeginPair
& ( c_l_block_map_explicit_entry n
/ ns_l_block_map_implicit_entry n )
& nest EndPair
c_l_block_map_explicit_entry n = c_l_block_map_explicit_key n
& ( l_block_map_explicit_value n / e_node )
c_l_block_map_explicit_key n = c_mapping_key ! "node" & s_l__block_indented n BlockIn
l_block_map_explicit_value n = s_indent n & c_mapping_value & s_l__block_indented n BlockIn
ns_l_block_map_implicit_entry n = ns_s_block_map_implicit_key & c_l_block_map_implicit_value n
/ e_node & c_l_block_map_implicit_value n
ns_s_block_map_implicit_key = c_s_simple_json_key / ns_s_simple_yaml_key
c_l_block_map_implicit_value n = c_mapping_value ! "node"
& ( s_l__block_node n BlockIn
/ e_node & s_l_comments )
ns_l_in_line_mapping n = nest BeginNode
& nest BeginMapping
& ns_l_block_map_entry n
& ( s_indent n & ns_l_block_map_entry n *)
& nest EndMapping
& nest EndNode
-- Block node:
s_l__block_node n c = s_l__block_in_block n c
/ s_l__flow_in_block n
s_l__flow_in_block n = s_separate_in_line & ns_flow_node (n .+ 1) FlowOut & s_l_comments
s_l__block_in_block n c = nest BeginNode
& ( s_separate_in_line & c_ns_properties ?)
& s_l__block_content n c
& nest EndNode
s_l__block_content n c = s_separate_in_line & c_l__literal n
/ s_separate_in_line & c_l__folded n
/ s_l_comments & l__block_sequence (seq_spaces n c)
/ s_l_comments & l__block_mapping n
-- Document:
c_document_start = token DocumentStart [ '-', '-', '-' ]
c_document_end = token DocumentEnd [ '.', '.', '.' ]
l_document_prefix = ( c_byte_order_mark ?) & ( l_comment *)
l_document_suffix = c_document_end & s_l_comments
l_forbidden = sol
& ( c_document_start / c_document_end )
& ( b_char / s_white / eof )
l_implicit_document = nest BeginDocument
& s_l__block_node (-1) BlockOut `forbidding` l_forbidden
& nest EndDocument
l_explicit_document = nest BeginDocument
& ( l_directive ! "doc" *)
& c_document_start ! "doc"
& "node" ^ ( l_implicit_document / e_node & s_l_comments )
& nest EndDocument
e_no_document = empty
-- Stream:
l_yaml_stream = nest BeginStream
& l_documents
& ( l_document_suffix & l_documents *)
& nest EndStream
l_documents = l_leading_document & ( l_following_document *)
l_leading_document = l_document_prefix & "doc" ^ ( l_explicit_document / "node" ^ ( l_implicit_document / e_no_document ) )
l_following_document = l_document_prefix & "doc" ^ ( l_explicit_document / e_no_document )