WHITESPACE = _{ " " | "\t" }
KW_IF = _{ "if " }
KW_FI = _{ "fi" ~ (NEWLINE | EOI) }
KW_FOR = _{ "for " }
KW_ELSE = { "else" ~ NEWLINE }
KW_ELSEIF = _{ "else if " }
KW_WHILE = _{ "while " }
KW_DONE = _{ "done" ~ (NEWLINE | EOI) }
KW_LIST = _{ KW_IF | KW_FOR | KW_ELSEIF | KW_ELSE | KW_FI | KW_WHILE | KW_DONE }
DUMMY_DO = _{ ";" ~ "do" ~ NEWLINE }
DUMMY_THEN = _{ ";" ~ "then" ~ NEWLINE }
TEST = {(!(NEWLINE|DUMMY_THEN|DUMMY_DO) ~ ANY)+}
CMD_END = _{ !KW_LIST ~ (!NEWLINE ~ ANY)+ ~ EOI}
CMD_NORMAL = _{ !KW_LIST ~ (!NEWLINE ~ ANY)* ~ NEWLINE}
CMD = { CMD_NORMAL | CMD_END }
IF_HEAD = { KW_IF ~ TEST ~ (DUMMY_THEN|NEWLINE) }
EXP_BODY = { (CMD | EXP_IF | EXP_WHILE | EXP_FOR)+ }
IF_ELSEIF_HEAD = { KW_ELSEIF ~ TEST ~ (DUMMY_THEN|NEWLINE) }
IF_IF_BR = { IF_HEAD ~ EXP_BODY }
IF_ELSEIF_BR = { IF_ELSEIF_HEAD ~ EXP_BODY }
IF_ELSE_BR = { KW_ELSE ~ EXP_BODY }
EXP_IF = {
(SOI)? ~
IF_IF_BR ~
IF_ELSEIF_BR* ~
IF_ELSE_BR? ~
KW_FI
}
FOR_VAR = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* }
FOR_INIT = { FOR_VAR ~ "in" ~ TEST ~ (DUMMY_DO|NEWLINE) }
FOR_HEAD = { KW_FOR ~ FOR_INIT }
EXP_FOR = {
(SOI)? ~
FOR_HEAD ~
EXP_BODY ~
KW_DONE
}
WHILE_HEAD = { KW_WHILE ~ TEST ~ (DUMMY_DO|NEWLINE) }
EXP_WHILE = {
(SOI)? ~
WHILE_HEAD ~
EXP_BODY ~
KW_DONE
}
EXP = { (EXP_IF | EXP_FOR | EXP_WHILE | CMD)* }