NL = _{ "\n" | "\r" }
MUTANT_MARKER = _{ "!" | "|" }
code = { (mutation | line)* ~ last_line? }
line = { indent? ~ !variation_end ~ single_line_text ~ NL }
last_line = { indent? ~ single_line_text }
indent = { (" " | "\t")+ }
single_line_text = { (!NL ~ !variant_begin_marker ~ ANY)* }
mutation = { variation }
variation = { variation_header ~ NL ~ base ~ variant+ ~ variation_end ~ NL? }
variation_header = { indent? ~ variation_begin_marker ~ WHITE_SPACE ~ (identifier ~ WHITE_SPACE)? ~ (tags ~ WHITE_SPACE)? ~ comment_end }
variation_begin_marker = @{ comment_begin ~ MUTANT_MARKER }
variation_end = @{ indent? ~ comment_begin ~ WHITE_SPACE ~ MUTANT_MARKER ~ comment_end }
base = { variant_body }
variant = { variant_header ~ NL ~ variant_body }
variant_begin_marker = @{ comment_begin ~ MUTANT_MARKER{2} }
variant_header = { indent? ~ variant_begin_marker ~ WHITE_SPACE ~ identifier ~ WHITE_SPACE ~ comment_end }
variant_body = { inactive_multi_line_variant_body | inactive_single_line_variant_body | active_variant_body }
inactive_single_line_variant_body = { indent? ~ variant_body_begin_marker ~ single_line_comment_text ~ comment_end ~ NL }
inactive_multi_line_variant_body = { indent? ~ variant_body_begin_marker ~ NL ~ comment_text ~ indent? ~ comment_end ~ NL }
variant_body_begin_marker = @{ comment_begin ~ MUTANT_MARKER }
active_variant_body = { line+ }
// Tags ::= “[“ (Tag “,”)* Tag “]”
tags = { "[" ~ WHITE_SPACE? ~ tag ~ (WHITE_SPACE? ~ "," ~ WHITE_SPACE? ~ tag)* ~ WHITE_SPACE? ~ "]" }
// Tag ::= Identifier
tag = { identifier }
comment_begin = { "(*" | "/*" | "{-" | "#|" | "//" | "\"\"\"" }
comment_end = { "*)" | "*/" | "-}" | "|#" | "//" | "\"\"\"" }
identifier = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHA | ASCII_DIGIT | "_")* }
comment_text = { comment_line* }
comment_line = { !(indent? ~ comment_end ~ NL) ~ (!NL ~ ANY)* ~ NL }
single_line_comment_text = { (!NL ~ !comment_end ~ ANY)* }
program = { SOI ~ code ~ EOI }