checkpoint

This commit is contained in:
Rutger van Beusekom 2017-04-08 21:39:43 +02:00
parent e31829a757
commit 6e556508f5
8 changed files with 43 additions and 20 deletions

10
TODO
View File

@ -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:

View File

@ -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 "\"")))

View File

@ -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))

View File

@ -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 / ([{] (![}] .)+ [}]))

1
test/assignment Normal file
View File

@ -0,0 +1 @@
SHELL=/bin/bash

View File

@ -1 +1 @@
for f in *; do echo $f | grep c; done
for f in *; do echo "$f:" | grep c; done

3
test/test Normal file
View File

@ -0,0 +1,3 @@
foo=bar
bar=foo
if [ "${foo}" != "foo" -a "${bar}" != "bar" ]; then echo foobar; fi

1
test/var Normal file
View File

@ -0,0 +1 @@
echo $SHELL