> On Dec 20, 2016, at 4:35 AM, Alexis King <lexi.lam...@gmail.com> wrote: > > One relatively easy solution would be to just compile patterns to > regular expressions and use Racket’s built-in match form. Writing this > as a match-expander is fairly straightforward: > > #lang racket > > (require (for-syntax racket/string > syntax/parse/experimental/template) > syntax/parse/define) > > (begin-for-syntax > (define-syntax-class svp > #:attributes [id regex-str] > [pattern id:id > #:attr regex-str "(.*)"] > [pattern str:str > #:attr regex-str (regexp-quote (syntax-e #'str)) > #:attr id #f])) > > (define-match-expander str > (syntax-parser > [(_ svp:svp ...) > #:do [(define regex-strs > (string-append* (attribute svp.regex-str)))] > #:with regex (regexp (string-append "^" regex-strs "$")) > (template (regexp 'regex (list _ (?? svp.id) ...)))])) > > This will compile string-match patterns into regular expressions by > converting identifiers into capturing groups, (.*), and converting > string literals into patterns that match themselves using regexp-quote.
Oooh, that's pretty cool. Much better than my super-slow attempt. Should you make this into a package (I would certainly use it a lot) or would it make more sense to add in a pull request to the existing `match-string` package? > This match expander can be used pretty easily as-is, but if you want to > use your string-match syntax directly, that’s just another simple macro > away: > > (define-syntax-parser string-match > #:literals [else] > [(_ input:expr > [(svp:svp ...) body:expr ...] ... > {~optional [else else-body ...]}) > (template (match input > [(str svp ...) body ...] ... > (?? [_ else-body ...])))]) > > This handles your syntax, and ensures an else clause is both optional > and can only occur at the end. For all of the above code, you could > improve syntax-parse’s error reporting by adding some description > annotations, but I’ve left them off for brevity. > > With the above definitions, your sm function is valid syntax, and it > works. However, the output is different from your expected output for > the final case, which matches the first case, producing the following > output: > >> (sm "abc--123--456 bar end") > '(abc--123 456 "bar") > > I think this behavior is correct, since that input does match the > pattern specified without any further information (and I cannot come up > with a useful parsing scheme that would not parse that string given that > pattern). Greediness doesn’t really matter there, either, since a greedy > parser would produce the above result (Racket’s regexps are always > greedy), and a non-greedy parser would still parse, it would just break > the string into the components "abc", "123--456", and "bar" instead. > > Alexis > >> On Dec 20, 2016, at 00:59, Daniel Prager <daniel.a.pra...@gmail.com> wrote: >> >> While working through many of the puzzles in this year's adventofcode.com I >> tend to parse the input with a sequence of string-splits. >> >> This isn't too bad, but What I'd *really* like is a "string-match" form to >> more elegantly process structured data, via a few strings based on a simple >> (and greedy) left-to-right algorithm. >> >> For example: >> >> (define (sm s) >> (string-match s >> [(a "--" b " " c " end") (list (string->symbol a) (string->number b) c)] >> [("the " object " is " adjective) (~a adjective " " object)] >> [("whole-string") 'whole] >> [else 'no-match-found])) >> >> (sm "abc--123 foo end") -> '(abc 123 "foo") >> (sm "the fox is black") -> "black fox" >> (sm "whole-string") -> 'whole >> (sm "abc--123--456 bar end") -> 'no-match-found ; greedy strategy keeps >> things simple and explicit >> >> >> But my macro-fu is too weak. >> >> 1. Can someone show me how to write this style of macro? >> 2. Is this of more general interest? >> >> Dan > > -- > You received this message because you are subscribed to the Google Groups > "Racket Users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to racket-users+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.