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