Perl6:将Match对象转换为JSON可序列化Hash

Nob*_*son 4 testing json perl6 regexp-grammars

我现在开始在一些Perl6上弄脏手.具体来说,我正在尝试编写基于语法的Fortran解析器(Fortran :: Grammar模块)

出于测试目的,我希望有可能将Match对象转换为JSON可序列化Hash.

谷歌搜索/ 官方Perl6文档没有帮助.如果我忽视某些事情,我道歉.

到目前为止我的尝试:

  • 我知道可以将a转换Match $mHashvia $m.hash.但这会保留嵌套Match对象.
  • 由于这只是要通过递归解决的,我试过,但有利于给先询问一种更简单的/现有解决方案是否存在等在这里了
  • 处理Match对象的内容显然最好通过make/ 来完成made.我希望有一个超级简单的Actions对象,用于所有匹配.parse默认方法,基本上只是做一个make $/.hash或类似的东西.我根本不知道如何指定默认方法.

sml*_*mls 5

这是我的一个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 ~$/ }
    }
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 这完全忽略了位置捕获(即( )在语法内部进行的捕获) - 仅使用命名捕获(例如<foo><foo=bar>)来构建哈希树.它可以修改为处理它们,具体取决于你想用它们做什么.请记住:
    • $/.hash给出命名的捕获,作为Map.
    • $/.list给出位置捕获,如List.
    • $/.caps(或$/.pairs)给出命名和位置捕获,作为序列name=>submatch和/或index=>submatch对.
  • 它允许您覆盖特定规则的AST生成,方法是{ make ... }在语法中添加规则内的块(假设您从不故意想要make未定义的值),或者通过向操作类添加具有规则名称的方法.

  • 为了完整性,`.caps`和`.pairs`之间的区别在于前者列出了与不同项对应的相同键的子匹配,而后者不重复键,如果需要将子匹配放入数组中 (2认同)