; dmc grammar
; UPPER = lexer token (TokenKind variant)
; lower = parser production
; ?  optional   *  zero+   +  one+   |  alternative   (...)  group

document     = block*

block        = frontmatter
             | import_stmt
             | export_stmt
             | heading
             | code_block
             | indented_code
             | jsx_element
             | jsx_expression
             | md_comment
             | unordered_list
             | ordered_list
             | blockquote
             | thematic_break
             | table
             | paragraph
             | SOFT_BREAK
             | HARD_BREAK

frontmatter  = FRONTMATTER_START FRONTMATTER_CONTENT? FRONTMATTER_END

import_stmt  = IMPORT
export_stmt  = EXPORT

heading      = atx_heading | setext_heading
atx_heading  = HEADING(n) inline*
setext_heading
             = paragraph SOFT_BREAK setext_underline
setext_underline
             = EQ+              (SOFT_BREAK | HARD_BREAK | EOF)
             | THEMATIC_BREAK   (SOFT_BREAK | HARD_BREAK | EOF)

code_block   = CODE_START(n) TEXT? token* CODE_END(n)?
indented_code
             = (WHITESPACE_4 line_remainder (SOFT_BREAK indented_continuation)?)+
line_remainder
             = token* (SOFT_BREAK | HARD_BREAK | EOF)

unordered_list
             = unordered_item ((SOFT_BREAK | HARD_BREAK)? unordered_item)*
ordered_list = ordered_item   ((SOFT_BREAK | HARD_BREAK)? ordered_item)*
unordered_item
             = UNORDERED_LIST_ITEM (task_marker? inline*)
ordered_item = ORDERED_LIST_ITEM   inline*
task_marker  = WHITESPACE? BRACKET TEXT(" "|"x"|"X") BRACKET

blockquote   = (BLOCK_QUOTE inline* (SOFT_BREAK | HARD_BREAK)?)+

thematic_break
             = THEMATIC_BREAK

table        = pipe_line break alignment_line break (pipe_line break)*
pipe_line    = "|" (cell "|")+
alignment_line
             = "|" (":"? "-"+ ":"? "|")+
break        = SOFT_BREAK | HARD_BREAK

paragraph    = inline+

inline       = TEXT
             | WHITESPACE
             | AUTOLINK
             | bold
             | italic
             | strike
             | inline_code
             | link
             | image
             | jsx_element
             | jsx_expression
             | md_comment

bold         = BOLD(n)   inline* BOLD(n)?
italic       = ITALIC(n) inline* ITALIC(n)?
strike       = STRIKE(n) inline* STRIKE(n)?
inline_code  = CODE_START(n) token* CODE_END(n)?
link         = BRACKET inline* BRACKET (PAREN_OPEN token* PAREN_CLOSE)?
image        = BANG BRACKET token* BRACKET (PAREN_OPEN token* PAREN_CLOSE)?
md_comment   = MARKDOWN_COMMENT_START token* MARKDOWN_COMMENT_END?

jsx_element  = JSX_OPEN_TAG_START
               JSX_TAG_NAME?
               jsx_attr*
               ( JSX_SELF_CLOSING_END
               | JSX_OPEN_TAG_END block*
                 JSX_CLOSE_TAG_START JSX_TAG_NAME? JSX_CLOSE_TAG_END )

jsx_attr     = JSX_ATTRIBUTE_NAME (EQ (STRING | jsx_expression))?

jsx_expression
             = EXPRESSION_START token* EXPRESSION_END?
