我现在开始在一些Perl6上弄脏手.具体来说,我正在尝试编写基于语法的Fortran解析器(
Fortran::Grammar模块)
出于测试目的,我希望有可能将Match对象转换为JSON可序列化的Hash.
谷歌/ official Perl6 documentation没有帮助.如果我忽视某些事情,我道歉.
到目前为止我的尝试:
>我知道可以通过$m.hash将Match $m转换为Hash.但这会保留嵌套的Match对象.
>因为这只需要通过递归来解决,我试过但是放弃了先请求在这里提出一个更简单/现有的解决方案
>处理Match对象的内容显然最好通过make / made来完成.我希望有一个超级简单的Actions对象可以使用默认方法传递给.parse所有匹配,基本上只需要make $/ .hash或类似的东西.我根本不知道如何指定默认方法.
解决方法
这是我的一个Perl 6项目中的一个动作类方法,它可以完成您所描述的内容.
它与Christoph发布的内容几乎相同,但写得更加冗长(并且我添加了大量的注释以使其更容易理解):
#| 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 ~$/ } } }
笔记:
>这完全忽略了位置捕获(即在语法内用()进行的捕获) – 仅使用命名捕获(例如< foo>或< foo = bar>)来构建哈希树.它可以修改为处理它们,具体取决于你想用它们做什么.请记住:
> $/.hash给出命名的捕获,作为Map.
> $/ .list给出位置捕获,作为List.
> $/.cap(或$/.对)给出命名和位置捕获,作为name => submatch和/或index =>子匹配对的序列.
>它允许您覆盖特定规则的AST生成,方法是在语法规则中添加{make …}块(假设您从不故意想要创建未定义的值),或者添加方法动作类的规则名称.