diff --git a/check.sh b/check.sh index 0f03704..389ca4b 100755 --- a/check.sh +++ b/check.sh @@ -48,6 +48,8 @@ tests=" 11-for-split-sequence 20-semi.sh +20-or.sh +20-and.sh 20-pipe-exit-0 20-pipe-exit-1 20-pipe-sed diff --git a/gash/peg.scm b/gash/peg.scm index 56e6fb5..413fa2b 100644 --- a/gash/peg.scm +++ b/gash/peg.scm @@ -152,9 +152,9 @@ (define-peg-string-patterns "script <-- ws* (term (separator term)* separator?)? - term <- pipeline (sp* (and / or) ws* pipeline)* - and <-- '&&' - or <-- '||' + term <- (and / or / pipeline) (sp* (and / or /pipeline))* + and <-- pipeline sp* amp-amp ws* pipeline + or <-- pipeline sp* pipe-pipe ws* pipeline pipe < '|' pipeline <-- negate? pipeline-head pipeline-tail* pipeline-head <- sp* command @@ -223,7 +223,7 @@ rhs <- (substitution / word)* assign < '=' dollar < '$' - literal <-- backslash? (!ws !tick !dollar !pipe !semi !par !nl !sp !rbrace .)+ + literal <-- backslash? (!ws !amp !tick !dollar !pipe !semi !par !nl !sp !rbrace .)+ variable <-- dollar ('$' / '*' / '?' / '@' / [0-9] / identifier / lbrace identifier rbrace) variable-and-or <- dollar lbrace (variable-or / variable-and ) rbrace variable-and <-- identifier plus rhs @@ -238,6 +238,8 @@ separator <- (sp* break ws*) / ws+ sequential-sep <- (semi !semi ws*) / ws+ amp <- '&' + amp-amp < '&&' + pipe-pipe < '||' backslash <- '\\' semi < ';' lpar < '(' @@ -326,6 +328,9 @@ (('sequence o ...) `(sequence (quote ,(map transform o)))) + (('and l r) `(and-terms ,(transform l) ,(transform r))) + (('or l r) `(or-terms ,(transform l) ,(transform r))) + (('substitution o) `(substitution ,(transform o))) (('if-clause expr then) `(if-clause ,(transform expr) ,(transform then))) (('if-clause expr then else) `(if-clause ,(transform expr) ,(transform then) ,(transform else))) diff --git a/gash/script.scm b/gash/script.scm index 44a951c..166149b 100644 --- a/gash/script.scm +++ b/gash/script.scm @@ -39,6 +39,7 @@ #:use-module (gash util) #:export ( + and-terms background builtin command @@ -48,6 +49,7 @@ if-clause ignore-error literal + or-terms pipeline run script @@ -177,6 +179,22 @@ #'(let ((it (ignore-error expr))) (if (zero? it) then else))))))) +(define-syntax and-terms + (lambda (x) + (syntax-case x () + ((_ left right) + (with-syntax ((it (datum->syntax x 'it))) + #'(let ((it left)) + (if (zero? it) right it))))))) + +(define-syntax or-terms + (lambda (x) + (syntax-case x () + ((_ left right) + (with-syntax ((it (datum->syntax x 'it))) + #'(let ((it (ignore-error left))) + (if (zero? it) it right))))))) + (define (pipeline . commands) (define (handle job) (when (> %debug-level 1) diff --git a/test/20-and.exit b/test/20-and.exit new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/test/20-and.exit @@ -0,0 +1 @@ +2 diff --git a/test/20-and.sh b/test/20-and.sh new file mode 100644 index 0000000..495cfe4 --- /dev/null +++ b/test/20-and.sh @@ -0,0 +1 @@ +true && exit 2 diff --git a/test/20-or.sh b/test/20-or.sh new file mode 100644 index 0000000..84ffdd6 --- /dev/null +++ b/test/20-or.sh @@ -0,0 +1 @@ +false || true