Hi :) I recently discovered the (ice-9 peg) module, and it seems really useful. However I have to admit I struggle a bit with processing the tree produced by it.
Let me put forward an example: --8<---------------cut here---------------start------------->8--- (use-modules (ice-9 peg)) (define-peg-pattern Opt body (and Name Space (+ (and Enum Space)) Default)) (define-peg-pattern Name all (+ Alpha)) (define-peg-pattern Enum all (+ Alpha)) (define-peg-pattern Default all (and (ignore "(default: ") (* Alpha) (ignore ")"))) (define-peg-pattern Alpha body (range #\a #\z)) (define-peg-pattern Space none " ") --8<---------------cut here---------------end--------------->8--- Now I can feed it few strings to get the parsed trees: --8<---------------cut here---------------start------------->8--- scheme@(guile-user)> (peg:tree (match-pattern Opt "name a b c (default: a)")) $11 = ((Name "name") ((Enum "a") (Enum "b") (Enum "c")) (Default "a")) scheme@(guile-user)> (peg:tree (match-pattern Opt "name a b c (default: )")) $12 = ((Name "name") ((Enum "a") (Enum "b") (Enum "c")) Default) scheme@(guile-user)> (peg:tree (match-pattern Opt "name a (default: a)")) $13 = ((Name "name") (Enum "a") (Default "a")) scheme@(guile-user)> (peg:tree (match-pattern Opt "name a (default: )")) $14 = ((Name "name") (Enum "a") Default) --8<---------------cut here---------------end--------------->8--- What we see here is that it produces trees in 4 different "shapes", depending on the input string. And I am unsure how to reasonably process them. My current approach looks like: --8<---------------cut here---------------start------------->8--- (define process-tree (match-lambda ((('Name name) (('Enum enum) ...) ('Default def)) (pk name enum def)) ((('Name name) ('Enum enum) ... ('Default def)) (pk name enum def)) ((('Name name) (('Enum enum) ...) 'Default) (pk name enum #f)) ((('Name name) ('Enum enum) ... 'Default) (pk name enum #f)))) --8<---------------cut here---------------end--------------->8--- Which *does* work: --8<---------------cut here---------------start------------->8--- scheme@(guile-user)> (for-each process-tree (list $11 $12 $13 $14)) ;;; ("name" ("a" "b" "c") "a") ;;; ("name" ("a" "b" "c") #f) ;;; ("name" ("a") "a") ;;; ("name" ("a") #f) --8<---------------cut here---------------end--------------->8--- However it is very repetitive and the code is pretty hard to work with. (Real code even has few more branches.) And I am not sure how to do a better job at this. It would really simplify things if I would be able to *always* have a list of 'Enum, even when there is just a single one. Same for default. I tried keyword-flatten, but probably I just do not understand how to use it. Or maybe (ice-9 match) is just a wrong tool here? Would someone be able to provide general guidance how to approach this, or at least recommend some projects using (ice-9 peg) that I could study? Thanks and have a nice day, Tomas -- There are only two hard things in Computer Science: cache invalidation, naming things and off-by-one errors.
signature.asc
Description: PGP signature