To overengineer and test out the framework a simple grep and sed utility has been designed. It knows about scheme and can locate and translate scheme files as well as having traditional grep/sed funcitonality. The main interface is in the module (logic guile-log grep)
.
(grep match code #:key (a 0) (b 0) (c 0))
, this will evaluate code
in a separate thread and capture standard output and only print what the parser function match
matches. a,b,c
defines an interval [min(-b,-c),max(a,c)]
around the matched line which is printed.
(sed match code)
, will print everything but if match matches, it’s output will be printed instead by the matcher, e.g. use the pr versions of the parser combinators for printing matches.
(par-grep match code #:key (str q-false) (com q-false) (a 0) (b 0) (c 0))
, This is a grep funciton that knows about scheme, it works as before but will print the sexp or part of sexp that is matching. The extra fields are, str
, the matcher used inside strings, com
, the matcher used in comments, and d
prints the lines containing the d
level enclosing sexp.
(par-sed match code #:key (str q-false) (com q-false))
, This is a sed utility that knows about scheme.
In order to translate scheme code we have a nice little monster framework to to the grunt work. You may use it by importing (logic guile-log parsing sch-match).
To use this one need to know about how syntax-parse works. We only support a subset of the syntax-parse interface, namlely the directives ~and ~or ~not ~var _)
added to this we make use of ice-9 match notation for symbols.
To define a match abstraction use,
(define-match-class [nm | (nm . args)] (pattern pat l ...) ...)
,
just use this as with define-syntax-class, but with the exception that you will build and match according to some whitespace rules stated below.
(define-splicing-match-class [nm | (nm . args)] (pattern pat l ...) ...)
,
This works just as with define-splicing-syntax-class
in syntax-parse, but again with some extra twarts.
The actual matchers are,
(scm-sed (pat res ...) ...)
, this works just as with syntax-parse, but with the extra build-rules.
(scm-match pat)
, use this as a matcher in par-grep, but with the syntax-parse pattern interface to define a match.
The philosophy is to treat the sed translation as a special syntax transform. A variable x
in the pattern will produce three sub matches, x.l,x.it.x.r
. e.g. left whitespace, sexp, right whitespace. By matching #(l it r)
l will be left whitespace, it the sexp and r the right whitespace, and this is how you define the output as well in order to surround an element with whitespace.
This is an example how one may define a sed translator that swaps the meaning of variable and value in a let form and preserving whitespace as much as possible.
(define-match-class swap (pattern #(l (x y) r) #:with tr #'#(l (x.l y.it x.r y.l x.it y.r) r))) (define-match-class (tr-it oldval newval) (pattern #(l ,oldval r) #:with tr #`#(l #,(datum->syntax #'a newval) r))) (define (test f) (par-sed (scm-sed (#(l ((~var let (tr-it 'let 'tel)) #(a ((~var bind swap) ...) b) body ...) r) #'#(l (let.tr #(a (bind.tr ...) b) body ...) r))) (f)))