sounds about right -- finding the appropriate mux point to pinch is indeed the first step towards sanity. if you get funding, give me a buzz. otherwise, i will continue to work w/ (old) librx and approach the problem from the guile perspective. (e.g., below is lex.test w/ a simple shell-lexer spec. probably guile will be able to do a busybox-like sumo move on the auto* tools by end of 1.4.x.)
the broader social hack is going to be difficult, if anything. people don't like to reflect because the image they see (initially) is one of incompetence and foolishness. it takes fortitude to synthesize that stark realization into actions that support their ideals (and self-image). much easier to deny the proper place of reflection entirely, along w/ its past implication and future consequence. ah, children w/ magic wands... given this, probably the best you can do is to write analysis tools that help people migrate from the pre- to the fully-muxed state. (i see "autoupdate" is a step in this direction.) M-x refactor-build-flow, you know. thi __________________________________________________ #!/bin/sh exec ${GUILE-guile} -s $0 "$@" # -*- scheme -*- !# ;;; Commentary: ;; Usage: $(INST_TESTS_ENVIRONMENT) $(srcdir)/lex.test ;; ;; Basically, we construct a lexer on ourselves; do not modify ;; anything above the commentary line w/o also modifying the ;; associated values in `expected' below! ;;; Code: (use-modules (lang lex)) ;; simple references lexeme-reader lexer-regexp-and-handler make-lexer eof-token? ;; from comment (define r (regcomp "if[[:cut 1:]]\\|else[[:cut 2:]]")) (or (equal? (regexec r "if" '(#\c 0)) '(1 "if")) (error "'(#\c 0) on \"if\" failed")) (or (equal? (regexec r "else" '(#\c 0)) '(2 "else")) (error "'(#\c 0) on \"else\" failed")) ;; from comment using make-lexer (define ifelse-lexer (make-lexer '(("if" if) ("else" else)))) ;; self lexing -- incomplete spec for testing purposes only (define (token->number token . port) (list 'number (string->number token))) (define (token->id token . port) (list 'identifier (string->symbol token))) (define shell-script-lexer-spec `(("[0-9]\\+" ,token->number) ("/\\([a-zA-Z0-9,=_-]\\+/*\\)*" filename) ("\"\\$@\"" ,(lambda ignored '(dollar-at))) ("\\$" ,(lambda ignored '(dollar))) ("{" ,(lambda ignored '(left-curly))) ("}" ,(lambda ignored '(right-curly))) ("exec" ,(lambda ignored '(exec))) ("#!" ,(lambda ignored '(hash-bang))) ("!#" ,(lambda ignored '(bang-hash))) ("[A-Za-z0-9_][A-Za-z0-9_]*" identifier) ("-" ,(lambda ignored '(dash))) ("\n" ,(lambda ignored '(newline))) ("#[^!][^\n]*" comment) ("." ignored))) (define shell-script-lexer (make-lexer shell-script-lexer-spec)) (or (procedure? shell-script-lexer) (error (format #f "not a procedure: ~S" shell-script-lexer))) (use-modules (ice-9 lineio)) (define p (make-line-buffering-input-port (open-input-file (car (command-line))))) (or (lineio-port? p) (error (format #f "not a lineio port: ~S" p))) (define expected '((hash-bang) (filename "/bin/sh") (newline) (exec) (dollar) (left-curly) (identifier "GUILE") (dash) (identifier "guile") (right-curly) (dash) (identifier "s") (dollar) (number 0) (dollar-at) (comment "# -*- scheme -*-") (newline) (bang-hash) (newline))) (define expected-length (length expected)) (define (next) (shell-script-lexer p)) (let loop ((lexeme (next)) (check 0)) ;;(format #t "~S\n" lexeme) (cond ((eq? '<eoi> (car lexeme))) ((eq? 'ignored (car lexeme)) (loop (next) check)) ((and (< check expected-length) (not (equal? (list-ref expected check) lexeme))) (error (format #f "expected ~S but got ~S !!!\n" (list-ref expected check) lexeme))) (else (loop (next) (1+ check))))) ;;; lex.test ends here