Re: How to work with the tree produced by (ice-9 peg)'s match-pattern?
Zelphir Kaltstahl <[email protected]>
| Newsgroups | gmane.lisp.guile.user |
|---|---|
| Message-ID | <[email protected]> |
On 04.12.24 13:06, Tomas Volf wrote:
> 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
Hello Tomas,
Without getting into the details, perhaps my peg utils module could be useful
for you:
https://codeberg.org/ZelphirKaltstahl/advent-of-code-2024/src/commit/3f64ee60297ccc89085c9425522bd8b8e83fe99d/utils/peg-tree-utils.scm
Best regards, Zelphir
--
repositories:https://notabug.org/ZelphirKaltstahl,https://codeberg.org/ZelphirKaltstahl