file = _{ SOI ~ NEWLINE* ~ (block ~ NEWLINE*)* ~ EOI } block = { code_block | latex_block | header | unordered_list | ordered_list | table | paragraph } header = { "#"{1,6} ~ span } unordered_list = { unordered_list_item+ } unordered_list_item = { "- " ~ span ~ NEWLINE } ordered_list = { ordered_list_item+ } ordered_list_item = { ASCII_DIGIT+ ~ ". " ~ span ~ NEWLINE } paragraph = { span } code_block = { "```" ~ code_block_lang ~ NEWLINE ~ code_block_inner ~ "```" } code_block_lang = { ASCII_ALPHANUMERIC* } code_block_inner = { (!"```" ~ ANY)* } latex_block = { "$$" ~ latex_block_inner ~ "$$" } latex_block_inner = { (!"$$" ~ ANY)* } table = { (table_row ~ NEWLINE)+ } table_row = { "|"? ~ table_cell ~ ("|" ~ table_cell)+ ~ "|"? } table_cell = { span } span = { (style_bold | style_italic | style_code | inline_latex | hyperlink | text)+ } style_bold = { "**" ~ span ~ "**" } style_italic = { "_" ~ span ~ "_" } style_code = { "`" ~ code_inner ~ "`" } code_inner = { (!"`" ~ ANY)+ } inline_latex = { "$" ~ latex_inner ~ "$" } latex_inner = { (!"$" ~ ANY)+ } hyperlink = { "[" ~ hyperlink_label ~ "](" ~ hyperlink_location ~ ")" } hyperlink_label = { span } hyperlink_location = { (!")" ~ANY)+ } text = { (!("[" | "]" | "*" | "_" | "`" | "|" | "$" | ("\n" ~ forbidden_span_wrap)) ~ ANY)+ } forbidden_span_wrap = _{ "\n" | "|" | "- " | ASCII_DIGIT+ ~ ". " }