list ::= sync | (' sync ...) sync ::= exp | (' exp) exp ::= pipe | (' exp_1 exp_2) | (' exp_1 exp_2) | (' pipe) pipe ::= cmd* | (' cmd* ...) cmd* ::= cmd | (' name sync ...) cmd ::= (' word ...) | (' ((var var-word) ...) word ...) | (' (redir ...) [cmd]) | (' (var word) ...) | (' sync ...) | (' (name (word ...)) sync ...) | (' word ((pattern-word ...) sync ...) ...) | (' (list sync ...) ... [(' sync ...)]) | (' list sync ...) | (' list sync ...) redir ::= ('> fdes word) | ('< fdes word) | ('>& fdes word) | ('<& fdes word) | ('>> fdes word) | ('<> fdes word) | ('>! fdes word) | ('<< fdes word) ;; Internally, the parser also uses these two forms. | ('<< fdes (' qword)) | ('<<- fdes (' qword)) word ::= string | (word ...) | (' word) | (' [list] ...) | (' var) | (' var [word]) | (' var [word]) | (' var [word]) | (' var [word]) | (' var [word]) | (' var [word]) | (' var [word]) | (' var [word]) | (' var [word]) | (' var [word]) | (' var [word]) | (' var [word]) | (' var) ;; The parser never returns a qword, but it is a useful notion. It ;; gets used internally by the parser and by the `word' module. qword ::= string | (qword ...) | (' qword)