// Roots
RootA = { SOI ~ RootHeader? ~ RootBlock* ~ EOI }
RootB = { SOI ~ RootHeader? ~ RootBlockB* ~ EOI } // variant b supports four-space root block
// Blocks
Control = _{ &(BLOCK_START ~ (ShortBlock_ | LongBlocks_)) ~ Block }
ControlB = _{ Block }
Content = _{ ("\\" ~ &STOP | !STOP) ~ (Ellipsis | Line) ~ NEWLINE | (EllipsisEOI | LineEOI) }
Block = {
(BLOCK_START_B ~ !(NEWLINE | EOI) ~ (ShortBlock_ | LongBlocksB_)) |
(PUSH(BLOCK_START) ~ !(NEWLINE | EOI) ~ (ShortBlock_ | LongBlocks_) ~ DROP)
}
LongBlocks_ = _{ (BlockHeader ~ (NEWLINE | EOI) ~ CONTROL_INDENT?)? ~ LongBlock? ~ (CONTROL_INDENT ~ LongBlock )* }
LongBlocksB_ = _{ (BlockHeader ~ (NEWLINE | EOI) ~ " " )? ~ LongBlockB ~ (" " ~ LongBlockB)* }
ShortBlock_ = _{ BlockHeader ~ ShortBlock }
RootBlock = { ( SectHeader | Control | Content) ~ (CONTROL_INDENT ~ Control | CONTENT_INDENT ~ Content)* }
RootBlockB = { ( SectHeader | ControlB | Content) ~ (CONTROL_INDENT ~ ControlB | CONTENT_INDENT ~ Content)* }
LongBlock = { (SPACE ~ SectHeader | Control | SPACE ~ Content) ~ (CONTROL_INDENT ~ Control | CONTENT_INDENT ~ Content)* }
LongBlockB = { (SPACE ~ SectHeader | SPACE ~ Content) ~ ( " " ~ SPACE ~ Content)* }
ShortBlock = { ( SPACE ~ Content) }
Line = { ANY_LETTER* }
LineEOI = { ANY_LETTER+ ~ &EOI }
Ellipsis = { "..." }
EllipsisEOI = { "..." ~ &EOI }
BlockHeader = _{ SPACE ~ BlockHeader_ }
RootHeader = _{ BlockHeader_ ~ (NEWLINE | &EOI) }
SectHeader = _{ SectHeader_ ~ NEWLINE }
BlockHeader_ = _{ "[!" ~ BLOCK_HEADER ~ "]" ~ ("(" ~ BLOCK_PROPS ~ ")")? }
SectHeader_ = _{ "[~" ~ SECT_HEADER ~ "]" ~ ("(" ~ BLOCK_PROPS ~ ")")? }
BLOCK_START = { "|" | ">" | "*" | "+" | "-" | "#" }
BLOCK_START_B = { " " }
BLOCK_HEADER = { (!"]" ~ ANY_LETTER)* }
SECT_HEADER = { (!"]" ~ ANY_LETTER)* }
BLOCK_PROPS = { ("\\)" | !")" ~ ANY_LETTER)* }
BLOCK_INDENT = _{ PEEK[..-1] ~ &BLOCK_START ~ PEEK } // prefix for block control
CONTROL_INDENT = _{ BLOCK_INDENT | NO_INDENT } // prefix for block control or root control
CONTENT_INDENT = _{ BLOCK_INDENT ~ SPACE? | NO_INDENT } // prefix for block content or root content
NO_INDENT = _{ &PEEK_ALL ~ "" }
STOP = _{ SectHeader }
ANY_LETTER = _{ LETTER | NUMBER | MARK | PUNCTUATION | SYMBOL | SEPARATOR }
SPACE = _{ " " | "\t" }
// Block props
BlockProps = _{ Attribute* }
Attribute = { WHITE_SPACE* ~ Key ~ WHITE_SPACE* ~ "=" ~ WHITE_SPACE* ~ Value_ ~ WHITE_SPACE* }
Value_ = _{ PUSH("\"") ~ Value ~ POP }
Key = { ("\\=" | !("=" | WHITE_SPACE) ~ ANY_LETTER)* }
Value = { ("\\\"" | !"\"" ~ ANY_LETTER)* }
// Misc
Pointer = _{ "dummy" }
Paragraph = _{ "dummy" }
Section = _{ "dummy" }