diff options
Diffstat (limited to 'src/shell.pest')
-rw-r--r-- | src/shell.pest | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/src/shell.pest b/src/shell.pest new file mode 100644 index 0000000..92b173a --- /dev/null +++ b/src/shell.pest @@ -0,0 +1,72 @@ +basic_escape_char = @{ "\\\\" | "\\'" } +escape_char = @{ "\\" ~ ANY } + +bareword_char = @{ + escape_char | + !("|" | ";" | "\"" | "'" | "$" | "{" | "(" | ")" | WHITESPACE | COMMENT) + ~ ANY +} +single_string_char = @{ basic_escape_char | (!"'" ~ ANY) } +double_string_char = @{ escape_char | (!("\"" | "$") ~ ANY) } + +var = @{ + ("$" ~ XID_START ~ XID_CONTINUE*) | + ("$" ~ ("?" | "$" | "*" | ASCII_DIGIT)) | + ("${" ~ (!"}" ~ ANY)+ ~ "}") +} +bareword = @{ bareword_char+ } +single_string = @{ single_string_char+ } +double_string = @{ double_string_char+ } + +alternation_bareword_char = @{ !("," | "}") ~ bareword_char } +alternation_bareword = @{ alternation_bareword_char+ } +alternation_word_part = ${ + var | + alternation_bareword | + "'" ~ single_string? ~ "'" | + "\"" ~ (var | double_string)* ~ "\"" +} +alternation_word = ${ alternation_word_part* } +alternation = ${ "{" ~ alternation_word ~ ("," ~ alternation_word)* ~ "}" } + +substitution = ${ "$(" ~ w? ~ commands ~ w? ~ ")"} + +word_part = ${ + alternation | + substitution | + var | + bareword | + "'" ~ single_string? ~ "'" | + "\"" ~ (substitution | var | double_string)* ~ "\"" +} +word = ${ word_part+ } + +redir_prefix = @{ + ("in" | "out" | "err" | ASCII_DIGIT*) ~ (">>" | ">" | "<") +} +redirect = ${ redir_prefix ~ w? ~ word } + +exe = ${ (redirect | word) ~ (w ~ (redirect | word))* } +subshell = ${ + "(" ~ w? ~ commands ~ w? ~ ")" ~ (w? ~ redirect ~ (w ~ redirect)*)? +} +list = ${ word ~ (w ~ word)* } +pipeline = ${ (subshell | exe) ~ (w? ~ "|" ~ w? ~ (subshell | exe))* } + +control_if = ${ "if" ~ w ~ pipeline } +control_while = ${ "while" ~ w ~ pipeline } +control_for = ${ "for" ~ w ~ bareword ~ w ~ "in" ~ w ~ list } +control_else = ${ "else" ~ (w ~ "if" ~ w ~ pipeline)? } +control_end = ${ "end" } +control = ${ + control_if | control_while | control_for | control_else | control_end +} + +command = ${ control | pipeline } +commands = ${ command ~ (w? ~ ";" ~ w? ~ command)* } + +line = ${ SOI ~ w? ~ commands ~ w? ~ EOI } + +w = _{ (WHITESPACE | COMMENT)+ } +WHITESPACE = _{ (" " | "\t" | "\n") } +COMMENT = _{ "#" ~ ANY* } |