WIP FOO => rewrite me harder
This commit is contained in:
parent
859a95efe2
commit
745757cfd0
106
gash/gash.scm
106
gash/gash.scm
|
@ -92,7 +92,6 @@ copyleft.
|
|||
(debug (single-char #\d))
|
||||
(errexit (single-char #\e))
|
||||
(help (single-char #\h))
|
||||
(parse (single-char #\p))
|
||||
(prefer-builtins)
|
||||
(version (single-char #\v))
|
||||
(xtrace (single-char #\x))))
|
||||
|
@ -100,19 +99,13 @@ copyleft.
|
|||
(command? (option-ref options 'command #f))
|
||||
(opt? (lambda (name) (lambda (o) (and (eq? (car o) name) (cdr o)))))
|
||||
(debug (length (filter-map (opt? 'debug) options)))
|
||||
(debug? (option-ref options 'debug #f))
|
||||
(help? (option-ref options 'help #f))
|
||||
(parse? (option-ref options 'parse #f))
|
||||
(version? (option-ref options 'version #f))
|
||||
(files (option-ref options '() '()))
|
||||
(run
|
||||
(lambda (ast)
|
||||
(cond (parse?
|
||||
(let ((ast- (transform ast)))
|
||||
(stdout "parsed: " ast)
|
||||
(stdout "prepared: " ast-)
|
||||
#t))
|
||||
(#t
|
||||
(sh-exec ast))))))
|
||||
(run (compose sh-exec
|
||||
(if #t (cut stdout "transformed: " <>) identity) (cut transform <>)
|
||||
(if #t (cut stdout "parsed: " <>) identity))))
|
||||
(set! %prefer-builtins? (option-ref options 'prefer-builtins #f))
|
||||
(set-shell-opt! "errexit" (option-ref options 'errexit #f))
|
||||
(set-shell-opt! "xtrace" (option-ref options 'xtrace #f))
|
||||
|
@ -185,7 +178,7 @@ copyleft.
|
|||
paths)))
|
||||
(cond
|
||||
((not pattern) '(""))
|
||||
((string=? "$?" pattern) (list (assoc-ref global-variables "?")))
|
||||
((string-prefix? "$" pattern) (list (pk "get " pattern " => " (assoc-ref global-variables (string-drop pattern 1))))) ;; TODO: REMOVE ME
|
||||
((glob? pattern) (let ((absolute? (string-prefix? "/" pattern)))
|
||||
(let loop ((patterns (filter (negate string-null?) (string-split pattern #\/)))
|
||||
(paths (if absolute? '("/") '("."))))
|
||||
|
@ -320,52 +313,57 @@ mostly works, pipes work, some redirections work.
|
|||
(#t #t)
|
||||
(_ #f)))))))
|
||||
|
||||
(define (tostring . args)
|
||||
(with-output-to-string (cut map display args)))
|
||||
|
||||
;; transform ast -> list of expr
|
||||
;; such that (map eval expr)
|
||||
|
||||
(define (transform ast)
|
||||
(match ast
|
||||
(('script term "&") (list (background (transform term))))
|
||||
(('script term) `(,(transform term)))
|
||||
(('script terms ...) (transform terms))
|
||||
(('substitution "$(" script ")") (local-eval (cons 'substitute (cddr (car (transform script)))) (the-environment)))
|
||||
(('substitution "`" script "`") (local-eval (cons 'substitute (cddr (car (transform script)))) (the-environment)))
|
||||
((('term command)) `(,(transform command)))
|
||||
((('term command) ...) (map transform command))
|
||||
((('term command) (('term commands) ...)) (map transform (cons command commands)))
|
||||
(('compound-list terms ...) (transform terms))
|
||||
(('if-clause "if" (expression "then" consequent "fi"))
|
||||
`(if (equal? 0 (status:exit-val ,@(transform expression)))
|
||||
(begin ,@(transform consequent))))
|
||||
(('if-clause "if" (expression "then" consequent ('else-part "else" alternative) "fi"))
|
||||
`(if (equal? 0 (status:exit-val ,@(transform expression)))
|
||||
(begin ,@(transform consequent))
|
||||
(begin ,@(transform alternative))))
|
||||
(('for-clause ("for" identifier sep do-group)) #t)
|
||||
(('for-clause "for" ((identifier "in" lst sep) do-group))
|
||||
`(for-each (lambda (,(string->symbol identifier))
|
||||
(begin ,@(expand identifier (transform do-group))))
|
||||
(glob ,(transform lst))))
|
||||
(('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 "\"")))
|
||||
(('backticks s) (string-concatenate `("`" ,s "`")))
|
||||
(('delim ('singlequotes s ...)) (string-concatenate (map transform s)))
|
||||
(('delim ('doublequotes s ...)) (string-concatenate (map transform s)))
|
||||
(('delim ('backticks s ...)) (string-concatenate (map transform s)))
|
||||
((('pipe _) command) (transform command))
|
||||
(((('pipe _) command) ...) (map (compose car transform) command))
|
||||
((_ o) (transform o)) ;; peel the onion: (symbol (...)) -> (...)
|
||||
(_ ast))) ;; done
|
||||
(('script term "&") (list (background (transform term))))
|
||||
(('script term) `(,(transform term)))
|
||||
(('script terms ...) (transform terms))
|
||||
(('substitution "$(" script ")") (local-eval (cons 'substitute (cddr (car (transform script)))) (the-environment)))
|
||||
(('substitution "`" script "`") (local-eval (cons 'substitute (cddr (car (transform script)))) (the-environment)))
|
||||
((('term command)) `(,(transform command)))
|
||||
((('term command) ...) (map transform command))
|
||||
((('term command) (('term commands) ...)) (map transform (cons command commands)))
|
||||
(('compound-list terms ...) (transform terms))
|
||||
(('if-clause "if" (expression "then" consequent "fi"))
|
||||
`(if (equal? 0 (status:exit-val ,@(transform expression)))
|
||||
(begin ,@(transform consequent))))
|
||||
(('if-clause "if" (expression "then" consequent ('else-part "else" alternative) "fi"))
|
||||
`(if (equal? 0 (status:exit-val ,@(transform expression)))
|
||||
(begin ,@(transform consequent))
|
||||
(begin ,@(transform alternative))))
|
||||
(('for-clause ("for" identifier sep do-group)) #t)
|
||||
(('for-clause "for" ((identifier "in" lst sep) do-group))
|
||||
`(for-each (lambda (,(string->symbol identifier))
|
||||
(begin ,@(expand identifier (transform do-group))))
|
||||
(glob ,(transform lst))))
|
||||
(('do-group "do" (command "done")) (transform command))
|
||||
(('pipeline command) (pk 1) (let* ((command (transform command))) (or (builtin command) `(pipeline #t ,@command))))
|
||||
(('pipeline command piped-commands) (pk 2) `(pipeline #t ,@(transform command) ,@(transform piped-commands)))
|
||||
(('simple-command ('word (assignment name value))) `((lambda _ (let ((name ,(tostring (transform name)))
|
||||
(value ,(tostring (transform value))))
|
||||
(stderr "assignment: " name "=" value)
|
||||
(set! global-variables (assoc-set! global-variables name (glob value)))))))
|
||||
(('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) s)
|
||||
(('literal s) (transform s))
|
||||
(('singlequotes s) (string-concatenate `("'" ,s "'")))
|
||||
(('doublequotes s) (string-concatenate `("\"" ,s "\"")))
|
||||
(('backticks s) (string-concatenate `("`" ,s "`")))
|
||||
(('delim ('singlequotes s ...)) (string-concatenate (map transform s)))
|
||||
(('delim ('doublequotes s ...)) (string-concatenate (map transform s)))
|
||||
(('delim ('backticks s ...)) (string-concatenate (map transform s)))
|
||||
((('pipe _) command) (transform command))
|
||||
(((('pipe _) command) ...) (map (compose car transform) command))
|
||||
((_ o) (transform o)) ;; peel the onion: (symbol (...)) -> (...)
|
||||
(_ ast))) ;; done
|
||||
|
||||
(define (sh-exec ast)
|
||||
(define (exec cmd)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
(define-module (gash io)
|
||||
|
||||
#:use-module (srfi srfi-1)
|
||||
|
||||
#:export (stdout stderr))
|
||||
|
||||
(define (output port o)
|
||||
|
@ -9,8 +11,8 @@
|
|||
|
||||
(define (stdout . o)
|
||||
(output (current-output-port) o)
|
||||
o)
|
||||
(last o))
|
||||
|
||||
(define (stderr . o)
|
||||
(output (current-error-port) o)
|
||||
o)
|
||||
(last o))
|
||||
|
|
42
gash/peg.scm
42
gash/peg.scm
|
@ -5,6 +5,42 @@
|
|||
|
||||
#:export (parse peg-trace?))
|
||||
|
||||
(define (wrap-parser-for-users for-syntax parser accumsym s-syn)
|
||||
#`(lambda (str strlen pos)
|
||||
(when (> (@ (gash gash) %debug-level) 0)
|
||||
(format (current-error-port) "~a ~a : ~s\n"
|
||||
(make-string (- pos (or (string-rindex str #\newline 0 pos) 0)) #\space)
|
||||
'#,s-syn
|
||||
(substring str pos (min (+ pos 40) strlen))))
|
||||
|
||||
(let* ((res (#,parser str strlen pos)))
|
||||
;; Try to match the nonterminal.
|
||||
(if res
|
||||
;; If we matched, do some post-processing to figure out
|
||||
;; what data to propagate upward.
|
||||
(let ((at (car res))
|
||||
(body (cadr res)))
|
||||
#,(cond
|
||||
((eq? accumsym 'name)
|
||||
#`(list at '#,s-syn))
|
||||
((eq? accumsym 'all)
|
||||
#`(list (car res)
|
||||
(cond
|
||||
((not (list? body))
|
||||
(list '#,s-syn body))
|
||||
((null? body) '#,s-syn)
|
||||
((symbol? (car body))
|
||||
(list '#,s-syn body))
|
||||
(else (cons '#,s-syn body)))))
|
||||
((eq? accumsym 'none) #`(list (car res) '()))
|
||||
(else #`(begin res))))
|
||||
;; If we didn't match, just return false.
|
||||
#f))))
|
||||
|
||||
(module-define! (resolve-module '(ice-9 peg codegen))
|
||||
'wrap-parser-for-users
|
||||
wrap-parser-for-users)
|
||||
|
||||
(define (error? x)
|
||||
(let loop ((x x))
|
||||
(if (null? x) #f
|
||||
|
@ -83,13 +119,13 @@
|
|||
assignment <-- name assign (substitution / word)?
|
||||
assign < '='
|
||||
literal <-- (variable / delim / (![0-9] (![()] !io-op !sp !nl !break !pipe !assign !bt !sq !dq .)+) / ([0-9]+ &separator)) literal*
|
||||
variable <-- '$' ('$' / '*' / '@' / [0-9] / identifier / ([{] (![}] .)+ [}]))
|
||||
variable <-- '$' ('$' / '*' / '?' / '@' / [0-9] / identifier / ([{] (![}] .)+ [}]))
|
||||
delim <-- singlequotes / doublequotes / substitution
|
||||
sq < [']
|
||||
dq < [\"]
|
||||
bt < [`]
|
||||
singlequotes <-- sq (doublequotes / substitution / (!sq .))* sq
|
||||
doublequotes <-- dq (singlequotes / substitution / (!dq .))* dq
|
||||
singlequotes <-- sq (doublequotes / (!sq .))* sq
|
||||
doublequotes <-- dq (singlequotes / substitution / variable / (!dq .))* dq
|
||||
separator <- (sp* break ws*) / ws+
|
||||
break <- amp / semi !semi
|
||||
sequential-sep <-- (semi !semi ws*) / ws+
|
||||
|
|
Loading…
Reference in New Issue