Perl6:将 Match 对象转换为 JSON-serializable Hash

Perl6: Convert Match object to JSON-serializable Hash

我目前正忙于研究 Perl6。具体来说,我正在尝试编写一个基于语法的 Fortran 解析器(Fortran::Grammar 模块)

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

谷歌搜索/official Perl6 documentation 没有帮助。如果我忽略了什么,我深表歉意。

我目前的尝试:

I just have no idea on how to specify a default method.

方法名称 FALLBACK 已为此保留。

添加这样的内容

method FALLBACK($name, $/) {
    make $/.pairs.map(-> (:key($k), :value($v)) {
        $k => $v ~~ Match ?? $v.made !! $v>>.made
    }).hash || ~$/;
}

您的操作 class 应该有效。

对于每个没有显式操作方法的命名规则,它将 make 包含其子规则(命名规则或位置捕获)的散列,或者如果规则是 'atomic' 并且没有这样子规则匹配的字符串。

这是我的一个 Perl 6 项目中的一个动作 class 方法,它执行您描述的操作。

它与 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.
    • $/.caps(或$/.pairs)同时给出命名和位置捕获,作为name=>submatch and/or index=>submatch对的序列。
  • 它允许您覆盖特定规则的 AST 生成,方法是在语法中的规则内添加一个 { make ... } 块(假设您从不想 make 一个未定义的值) ,或者通过将具有规则名称的方法添加到操作 class.