checkpoint
This commit is contained in:
parent
e31829a757
commit
6e556508f5
10
TODO
10
TODO
|
@ -3,11 +3,11 @@
|
|||
* parsing posix shell: nested "'""'": done
|
||||
* globbing: done
|
||||
* job control: done
|
||||
* readline: prompt2: done?
|
||||
* pipe: almost done: mix built-in with process
|
||||
* substitution: done
|
||||
* readline: prompt2: in progress
|
||||
* pipe: in progress: mix built-in with process
|
||||
* compound: case, while, until
|
||||
* expansion
|
||||
* substitution
|
||||
* alias
|
||||
* expansion: done
|
||||
* alias:
|
||||
* redirection:
|
||||
* posix compliance:
|
||||
|
|
|
@ -20,11 +20,27 @@
|
|||
|
||||
:export (main))
|
||||
|
||||
(define (remove-shell-comments s)
|
||||
(string-join (map
|
||||
(lambda (s)
|
||||
(let* ((n (string-index s #\#)))
|
||||
(if n (string-pad-right s (string-length s) #\space 0 n)
|
||||
s)))
|
||||
(string-split s #\newline)) "\n"))
|
||||
|
||||
(define (remove-escaped-newlines s)
|
||||
(reduce (lambda (next prev)
|
||||
(let* ((escaped? (string-suffix? "\\" next))
|
||||
(next (if escaped? (string-drop-right next 1) next))
|
||||
(sep (if escaped? "" "\n")))
|
||||
(string-append prev sep next)))
|
||||
"" (string-split s #\newline)))
|
||||
|
||||
(define (file-to-string filename)
|
||||
((compose read-string open-input-file) filename))
|
||||
((compose read-string open-input-file) filename))
|
||||
|
||||
(define (string-to-ast string)
|
||||
((compose parse remove-shell-comments) string))
|
||||
((compose parse remove-escaped-newlines remove-shell-comments) string))
|
||||
|
||||
(define (file-to-ast filename)
|
||||
((compose string-to-ast file-to-string) filename))
|
||||
|
@ -48,8 +64,16 @@ the GNU Public License, see COPYING for the copyleft.
|
|||
|
||||
"))
|
||||
|
||||
(define global-variables '())
|
||||
|
||||
(define (main args)
|
||||
(setenv "PATH" "/bin:/usr/bin:/sbin:/usr/sbin:.")
|
||||
(map (lambda (key-value)
|
||||
(let* ((key-value (string-split key-value #\=))
|
||||
(key (car key-value))
|
||||
(value (cadr key-value)))
|
||||
(set! global-variables (assoc-set! global-variables key value))))
|
||||
(environ))
|
||||
(let ((thunk
|
||||
(lambda ()
|
||||
(job-control-init)
|
||||
|
@ -99,14 +123,6 @@ the GNU Public License, see COPYING for the copyleft.
|
|||
(newline)))))))
|
||||
(thunk)))
|
||||
|
||||
(define (remove-shell-comments s)
|
||||
(string-join (map
|
||||
(lambda (s)
|
||||
(let* ((n (string-index s #\#)))
|
||||
(if n (string-pad-right s (string-length s) #\space 0 n)
|
||||
s)))
|
||||
(string-split s #\newline)) "\n"))
|
||||
|
||||
(define (expand identifier o) ;;identifier-string -> symbol
|
||||
(define (expand- o)
|
||||
(let ((dollar-identifier (string-append "$" identifier)))
|
||||
|
@ -199,10 +215,12 @@ the GNU Public License, see COPYING for the copyleft.
|
|||
(('do-group "do" (command "done")) (transform command))
|
||||
(('pipeline command) (let* ((command (transform command))) (or (builtin command) `(pipeline #t ,@command))))
|
||||
(('pipeline command piped-commands) `(pipeline #t ,@(transform command) ,@(transform piped-commands)))
|
||||
(('simple-command ('word (assignment name value))) (set! global-variables (assoc-set! global-variables (transform name) (transform value))) #t)
|
||||
(('simple-command ('word s)) `((glob ,(transform s))))
|
||||
(('simple-command ('word s1) ('io-redirect "<<" ('here-document s2))) `((append (glob "echo") (cons "-n" (glob ,s2))) (glob ,(transform s1))))
|
||||
(('simple-command ('word s1) ('word s2)) `((append (glob ,(transform s1)) (glob ,(transform s2)))))
|
||||
(('simple-command ('word s1) (('word s2) ...)) `((append (glob ,(transform s1)) (append-map glob (list ,@(map transform s2))))))
|
||||
(('variable s) (assoc-ref global-variables (string-drop s 1)))
|
||||
(('literal s) (transform s))
|
||||
(('singlequotes s) (string-concatenate `("'" ,s "'")))
|
||||
(('doublequotes s) (string-concatenate `("\"" ,s "\"")))
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
:export (stdout stderr))
|
||||
|
||||
(define (output port . o)
|
||||
(define (output port o)
|
||||
(map (lambda (o) (display o port)) o)
|
||||
(newline port)
|
||||
(force-output port))
|
||||
|
|
|
@ -54,8 +54,8 @@
|
|||
for-clause <-- 'for' (sp+ identifier (ws+ 'in' expression sequential-sep / sp* sequential-sep) do-group / error)
|
||||
expression <-- sp+ substitution sp* / (sp+ word)* sp*
|
||||
do-group <-- 'do' ws* (ne-compound-list 'done' / error)
|
||||
if-clause <-- 'if' (ne-compound-list 'then' ne-compound-list else-part? 'fi' / error)
|
||||
else-part <-- 'elif' (ne-compound-list 'then' ne-compound-list else-part? / error) / 'else' (ne-compound-list / error)
|
||||
if-clause <-- 'if' (ne-compound-list 'then' ws* ne-compound-list else-part? 'fi' / error)
|
||||
else-part <-- 'elif' (ne-compound-list 'then' ws* ne-compound-list else-part? / error) / 'else' (ne-compound-list / error)
|
||||
while-clause <-- 'while' (ne-compound-list do-group / error)
|
||||
until-clause <-- 'until' (ne-compound-list do-group / error)
|
||||
function-def <-- name sp* '(' sp* ')' ws* (function-body / error)
|
||||
|
@ -78,7 +78,7 @@
|
|||
ltest < '[ '
|
||||
rtest < ' ]'
|
||||
substitution <-- ('$(' (script ')' / error)) / ('`' (script '`' / error))
|
||||
assignment <-- name assign word?
|
||||
assignment <-- name assign (substitution / word)?
|
||||
assign < '='
|
||||
literal <-- (variable / delim / (![0-9] (![()] !io-op !sp !nl !break !pipe !assign .)+) / ([0-9]+ &separator)) literal*
|
||||
variable <-- '$' ('$' / '*' / '@' / [0-9] / identifier / ([{] (![}] .)+ [}]))
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
SHELL=/bin/bash
|
2
test/for
2
test/for
|
@ -1 +1 @@
|
|||
for f in *; do echo $f | grep c; done
|
||||
for f in *; do echo "$f:" | grep c; done
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
foo=bar
|
||||
bar=foo
|
||||
if [ "${foo}" != "foo" -a "${bar}" != "bar" ]; then echo foobar; fi
|
Loading…
Reference in New Issue