= Formal definition of command syntax
:encoding: UTF-8
:lang: en
//:title: Yash manual - Formal definition of command syntax
:description: This page gives the formal definition of yash command syntax.

This chapter defines the syntax of shell commands as a parsing expression
grammar.

The set of terminals of the grammar is the set of characters that can
be handled on the environment in which the shell is run (a.k.a. execution
character set), with the exception that the set does not contain the null
character (`'\0'`).

Below is a list of nonterminals of the grammar with corresponding parsing
expressions.
The list does not include rules for parsing contents and ends of
link:redir.html#here[here documents].
In the link:posix.html[POSIXly-correct mode], the grammar varies from the list
below to disable non-POSIX functionalities.

[[d-complete-command]]CompleteCommand::
<<d-sequence,Sequence>> <<d-eof,EOF>>

[[d-sequence]]Sequence::
<<d-n,N>>* <<d-list,List>>*

[[d-list]]List::
<<d-pipeline,Pipeline>> ((+&&+ / +||+) <<d-n,N>>* Pipeline)*
<<d-list-separator,ListSeparator>>

[[d-pipeline]]Pipeline::
<<d-bang,Bang>>? <<d-command,Command>> (+|+ <<d-n,N>>* Command)*

[[d-command]]Command::
<<d-compound-command,CompoundCommand>> <<d-redirection,Redirection>>* / +
!<<d-r,R>> <<d-function-definition,FunctionDefinition>> / +
!R <<d-simple-command,SimpleCommand>>

[[d-compound-command]]CompoundCommand::
<<d-subshell,Subshell>> / +
<<d-grouping,Grouping>> / +
<<d-if-command,IfCommand>> / +
<<d-for-command,ForCommand>> / +
<<d-while-command,WhileCommand>> / +
<<d-case-command,CaseCommand>> / +
<<d-function-command,FunctionCommand>>

[[d-subshell]]Subshell::
+(+ <<d-sequence,Sequence>> +)+ <<d-s,S>>*

[[d-grouping]]Grouping::
<<d-left-brace,LeftBrace>> <<d-sequence,Sequence>>
<<d-right-brace,RightBrace>>

[[d-if-command]]IfCommand::
<<d-if,If>> <<d-sequence,Sequence>> <<d-then,Then>> Sequence
(<<d-elif,Elif>> Sequence <<d-then,Then>> Sequence)*
(<<d-else,Else>> Sequence)? <<d-fi,Fi>>

[[d-for-command]]ForCommand::
<<d-for,For>> <<d-name,Name>> <<d-s,S>>* <<d-separator,Separator>>?
(<<d-in,In>> <<d-word,Word>>* <<d-separator,Separator>>)?
<<d-do,Do>> <<d-sequence,Sequence>> <<d-done,Done>>

[[d-while-command]]WhileCommand::
(<<d-while,While>> / <<d-until,Until>>)
<<d-sequence,Sequence>> <<d-do,Do>> Sequence <<d-done,Done>>

[[d-case-command]]CaseCommand::
<<d-case,Case>> <<d-word,Word>> <<d-n,N>>* <<d-in,In>> N*
<<d-case-item,CaseItem>>* <<d-esac,Esac>>

[[d-case-item]]CaseItem::
!<<d-esac,Esac>> (+(+ <<d-s,S>>*)? <<d-word,Word>> (+|+ S* Word)* +)+
<<d-sequence,Sequence>> (+;;+ / &amp;Esac)

[[d-function-command]]FunctionCommand::
<<d-function,Function>> <<d-word,Word>> (+(+ <<d-s,S>>* +)+)? <<d-n,N>>*
<<d-compound-command,CompoundCommand>> <<d-redirection,Redirection>>*

[[d-function-definition]]FunctionDefinition::
<<d-name,Name>> <<d-s,S>>* +(+ S* +)+ <<d-n,N>>*
<<d-compound-command,CompoundCommand>> <<d-redirection,Redirection>>*

[[d-simple-command]]SimpleCommand::
&(<<d-word,Word>> / <<d-redirection,Redirection>>)
(<<d-assignment,Assignment>> / Redirection)* (Word / Redirection)*

[[d-assignment]]Assignment::
<<d-name,Name>> +=+ <<d-word,Word>> / +
Name +=(+ <<d-n,N>>* (Word N*)* +)+

[[d-name]]Name::
!\[[:digit:]] [[:alnum:] +_+]+

[[d-portable-name]]PortableName::
![++0++-++9++] [++0++-++9++ ++ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_++]+

[[d-word]]Word::
(<<d-word-element,WordElement>> / !<<d-special-char,SpecialChar>> .)+
<<d-s,S>>*

[[d-word-element]]WordElement::
+\+ . / +
`'` (!`'` .)* `'` / +
+"+ <<d-quote-element,QuoteElement>>* +"+ / +
<<d-parameter,Parameter>> / +
<<d-arithmetic,Arithmetic>> / +
<<d-command-substitution,CommandSubstitution>>

[[d-quote-element]]QuoteElement::
+\+ ([+$&#96;"&#92;+] / <<d-nl,NL>>) / +
<<d-parameter,Parameter>> / +
<<d-arithmetic,Arithmetic>> / +
<<d-command-substitution,CommandSubstitution>> / +
![+&#96;"&#92;+] .

[[d-parameter]]Parameter::
+$+ [+@*#?-$!+ [:digit:]] / +
+$+ <<d-portable-name,PortableName>> / +
+$+ <<d-parameter-body,ParameterBody>>

[[d-parameter-body]]ParameterBody::
+{+ <<d-parameter-number,ParameterNumber>>?
(<<d-parameter-name,ParameterName>> / ParameterBody /
<<d-parameter,Parameter>>)
<<d-parameter-index,ParameterIndex>>? <<d-parameter-match,ParameterMatch>>?
+}+

[[d-parameter-number]]ParameterNumber::
`#` ![`+=:/%`] !([`-?#`] `}`)

[[d-parameter-name]]ParameterName::
[+@*#?-$!+] / +
[[:alnum:] +_+]+

[[d-parameter-index]]ParameterIndex::
+[+ <<d-parameter-index-word,ParameterIndexWord>> (+,+ ParameterIndexWord)?
+]+

[[d-parameter-index-word]]ParameterIndexWord::
(<<d-word-element,WordElement>> / ![+"'],+] .)+

[[d-parameter-match]]ParameterMatch::
`:`? [`-+=?`] <<d-parameter-match-word,ParameterMatchWord>> / +
(`#` / `##` / `%` / `%%`) ParameterMatchWord / +
(`:/` / `/` [`#%/`]?)
<<d-parameter-match-word-no-slash,ParameterMatchWordNoSlash>>
(+/+ ParameterMatchWord)?

[[d-parameter-match-word]]ParameterMatchWord::
(<<d-word-element,WordElement>> / ![+"'}+] .)*

[[d-parameter-match-word-no-slash]]ParameterMatchWordNoSlash::
(<<d-word-element,WordElement>> / ![+"'/}+] .)*

[[d-arithmetic]]Arithmetic::
`$((` <<d-arithmetic-body,ArithmeticBody>>* `))`

[[d-arithmetic-body]]ArithmeticBody::
+\+ . / +
<<d-parameter,Parameter>> / +
<<d-arithmetic,Arithmetic>> / +
<<d-command-substitution,CommandSubstitution>> / +
+(+ ArithmeticBody +)+ / +
![+`()+] .

[[d-command-substitution]]CommandSubstitution::
+$(+ <<d-sequence,Sequence>> +)+ / +
+&#96;+ <<d-command-substitution-body,CommandSubstitutionBody>>* +&#96;+

[[d-command-substitution-body]]CommandSubstitutionBody::
+\+ [+$&#96;\+] / +
!++&#96;++ .

[[d-redirection]]Redirection::
<<d-redirection-fd,RedirectionFD>>
<<d-redirection-operator,RedirectionOperator>> <<d-s,S>>* <<d-word,Word>> / +
RedirectionFD +<(+ <<d-sequence,Sequence>> +)+ / +
RedirectionFD +>(+ Sequence +)+

[[d-redirection-fd]]RedirectionFD::
\[[:digit:]]*

[[d-redirection-operator]]RedirectionOperator::
`<` / `<>` / `>` / `>|` / `>>` / `>>|` / `<&` / `>&` / `<<` / `<<-` / `<<<`

[[d-list-separator]]ListSeparator::
<<d-separator,Separator>> / +
+&amp;+ <<d-n,N>>* / +
&++)++ / +
&++;;++

[[d-separator]]Separator::
+;+ <<d-n,N>>* / +
<<d-n,N>>+ / +
<<d-eof,EOF>>

[[d-n]]N::
<<d-s,S>>* <<d-nl,NL>>

[[d-s]]S::
\[[:blank:]] / +
<<d-comment,Comment>>

[[d-comment]]Comment::
+#+ (!<<d-nl,NL>> .)*

[[d-r]]R::
<<d-bang,Bang>> / <<d-left-brace,LeftBrace>> / <<d-right-brace,RightBrace>> /
<<d-case,Case>> / <<d-do,Do>> / <<d-done,Done>> / <<d-elif,Elif>> /
<<d-else,Else>> / <<d-esac,Esac>> / <<d-fi,Fi>> / <<d-for,For>> /
<<d-if,If>> / <<d-in,In>> / <<d-then,Then>> / <<d-until,Until>> /
<<d-while,While>>

[[d-bang]]Bang::
+!+ <<d-d,D>>

[[d-left-brace]]LeftBrace::
+{+ <<d-d,D>>

[[d-right-brace]]RightBrace::
+}+ <<d-d,D>>

[[d-case]]Case::
+case+ <<d-d,D>>

[[d-do]]Do::
+do+ <<d-d,D>>

[[d-done]]Done::
+done+ <<d-d,D>>

[[d-elif]]Elif::
+elif+ <<d-d,D>>

[[d-else]]Else::
+else+ <<d-d,D>>

[[d-esac]]Esac::
+esac+ <<d-d,D>>

[[d-fi]]Fi::
+fi+ <<d-d,D>>

[[d-for]]For::
+for+ <<d-d,D>>

[[d-function]]Function::
+function+ <<d-d,D>>

[[d-if]]If::
+if+ <<d-d,D>>

[[d-in]]In::
+in+ <<d-d,D>>

[[d-then]]Then::
+then+ <<d-d,D>>

[[d-until]]Until::
+until+ <<d-d,D>>

[[d-while]]While::
+while+ <<d-d,D>>

[[d-d]]D::
!<<d-word,Word>> <<d-s,S>>*

[[d-special-char]]SpecialChar::
[+|&amp;;&lt;&gt;()&#96;&#92;"'+ [:blank:]] / <<d-nl,NL>>

[[d-nl]]NL::
<newline>

[[d-eof]]EOF::
!.

// vim: set filetype=asciidoc textwidth=78 expandtab:
