I am currently gettin' my hands dirty on some Perl6. Specifically I am trying to write a Fortran parser based on grammars (the Fortran::Grammar module)
For testing purposes, I would like to have the possiblity to convert a Match
object into a JSON-serializable Hash
.
Googling / official Perl6 documentation didn't help. My apologies if I overlooked something.
My attempts so far:
Match $m
to a Hash
via $m.hash
. But this keeps nested Match
objects.Match
objects' contents is obviously best accomplished via make
/made
. I would love to have a super simple Actions
object to hand to .parse
with a default method for all matches that basically just does a make $/.hash
or something the like. I just have no idea on how to specify a default method.Here's an action class method from one of my Perl 6 projects, which does what you describe.
It does almost the same as what Christoph posted, but is written more verbosely (and I've added copious amounts of comments to make it easier to understand):
#| Fallback action method that produces a Hash tree from named captures.
method FALLBACK ($name, $/) {
# Unless an embedded { } block in the grammar already called make()...
unless $/.made.defined {
# If the Match has named captures, produce a hash with one entry
# per capture:
if $/.hash -> %captures {
make hash do for %captures.kv -> $k, $v {
# The key of the hash entry is the capture's name.
$k => $v ~~ Array
# If the capture was repeated by a quantifier, the
# value becomes a list of what each repetition of the
# sub-rule produced:
?? $v.map(*.made).cache
# If the capture wasn't quantified, the value becomes
# what the sub-rule produced:
!! $v.made
}
}
# If the Match has no named captures, produce the string it matched:
else { make ~$/ }
}
}
Notes:
( )
inside the grammar) - only named captures (e.g. <foo>
or <foo=bar>
) are used to build the Hash tree. It could be amended to handle them too, depending on what you want to do with them. Keep in mind that:
$/.hash
gives the named captures, as a Map
.$/.list
gives the positional captures, as a List
.$/.caps
(or $/.pairs
) gives both the named and positional captures, as a sequence of name=>submatch
and/or index=>submatch
pairs.{ make ... }
block inside the rule in the grammar (assuming that you never intentionally want to make
an undefined value), or by adding a method with the rule's name to the action class.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With