# (value) indicates an optional terminal or non-terminal
#
# Not specified in the grammer is comments, which are
#
# '#' /[^\n]*/
#
# This may appear anywhere outside of a quoted string and should be removed by
# the lexer.
#
# Continuations are also not specified, i.e. '\' LF
#
# TODO:
# - foo=bar command
# - rework numeric tokens
script commands (ALLWS)
commands (ALLWS) command
commands (ALLWS) separator command
separator LF
';'
command compound-command
assign
if-command
for-command
while-command
switch-command
func
'{' commands '}'
'@' '{' commands '}'
WS command (WS)
simple-command value-list (redirections)
compound-command
simple-command
builtin-command
'!' (WS) compound-command
compound-command (WS) pipe (WS) compound-command
compound-command (WS) '&&' (WS) compound-command
compound-command (WS) '||' (WS) compound-command
builtin-command
builtin value-list (redirections)
builtin 'cd'
'break'
'continue'
'eval'
'exit'
'echo'
'shift'
'unset'
assign word (WS) '=' (WS) value
for-command 'for' (WS) '(' (WS) word (WS) ')' command
'for' (WS) '(' word (WS) 'in' (WS) value-list ')' command
if-command 'if' (WS) condition command
if-command 'else' command
while-command 'while' (WS) condition command
switch-command 'switch' (WS) '(' (WS) value (WS) ')' (WS) '{' switch-cases '}'
switch-cases switch-case
switch-cases switch-case
switch-case (WS) 'case' WS value ALLWS command
(WS) 'default' WS value ALLWS command
condition '(' command ')'
func 'fn' WS word (params) WS command
params '(' param-list ')'
param-list word
param-list WS word
pipe '|' (file)
redirections redirection
redirections redirection
redirection '<' (file) (WS) value
'>' (file) (WS) value
'>' '>' (file) (WS) value
'<' '>' (file) (WS) value
'>' '>' heredoc
heredoc
(-) word [...] word
(-) string-literal [...] string-literal
file '[' (WS) integer (WS) ']'
'[' (WS) integer (WS) '=' (WS) ']'
'[' (WS) integer (WS) '=' (WS) integer (WS) ']'
value literal
access
subscript
pipescript
'(' (WS) value-list (WS) ')'
value-list value
value WS value-list
literal argument
string-literal
literal argument
literal string-literal
string-literal
'"' nondquote '"'
"'" nonsquote "'"
access '$' varname
'$' '#' varname
'$' '"' varname
'$' varname '(' (WS) access-list (WS) ')'
varname word
numeric
'*'
access-list index
'-' (WS) index
index (WS) '-'
index (WS) '-' (WS) index
index numeric
access
subscript '`' '{' script '}'
'`' string-literal '{' script '}'
pipescript '<' '{' script '}'
'>' '{' script '}'
word /[A-Za-z_][A-Za-z0-9_.]*/
argument /[^\[\](){}<>'"&|!;=$#@`\\ \t\n]+/
nondquote /[^"\n]+/
nonsquote /[^'\n]+/
numeric integer
integer /[0-9]+/
linefeeds LF (WS)
LF (WS) linefeeds
WS SP
TS
WS SP
WS TS
ALLWS
SP
TS
LF
WS SP
WS TS
WS LF
SP ' '
TS '\t'
LF '\n'