4

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

出于测试目的,我希望能够将Match对象转换为 JSON-serializable Hash

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

到目前为止我的尝试:

  • 我知道可以将 a 转换Match $mHashvia $m.hash。但这会保留嵌套Match对象。
  • 因为这只能通过递归来解决,所以我尝试但放弃了,而是先在此处询问是否存在更简单/现有的解决方案
  • 处理Match对象的内容显然最好通过make/来完成made。我很想有一个超级简单的Actions对象来处理所有匹配.parse默认方法,基本上只是做一个make $/.hash或类似的事情。我只是不知道如何指定默认方法。
4

2 回答 2

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 ~$/ }
    }
}

笔记:

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

我只是不知道如何指定默认方法。

FALLBACK为此目的保留方法名称。

添加这样的东西

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

到你的行动类应该工作。

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

于 2017-02-03T22:06:29.850 回答