我目前正在接触一些Perl6。具体来说,我正在尝试编写基于语法的Fortran解析器(Fortran::Grammar模块)
出于测试目的,我希望有可能将Match
对象转换为JSON可序列化Hash
。
谷歌搜索/ official Perl6 documentation没有帮助。如果我忽略了某些事情,我很抱歉。
到目前为止我的尝试:
Match $m
将Hash
转换为$m.hash
。但这会保留嵌套的Match
个对象。Match
个对象的内容显然最好通过make
/ made
完成。我希望有一个超级简单的Actions
对象可以用{strong>默认方法传递给.parse
,所有匹配基本上只需要make $/.hash
或类似的东西。我根本不知道如何指定默认方法。答案 0 :(得分: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>
或<foo=bar>
)来构建哈希树。它可以修改为处理它们,具体取决于你想用它们做什么。请记住:
$/.hash
以Map
。$/.list
提供位置捕获,为List
。$/.caps
(或$/.pairs
)同时提供命名和位置捕获,作为name=>submatch
和/或index=>submatch
对的序列。{ make ... }
块来覆盖特定规则的AST生成(假设您从未故意想要make
未定义的值),或者通过向操作类添加带有规则名称的方法。答案 1 :(得分:3)
我根本不知道如何指定默认方法。
方法名称FALLBACK
保留用于此目的。
添加类似这样的内容
method FALLBACK($name, $/) {
make $/.pairs.map(-> (:key($k), :value($v)) {
$k => $v ~~ Match ?? $v.made !! $v>>.made
}).hash || ~$/;
}
你的行动课应该有效。
对于没有显式操作方法的每个命名规则,它将make
包含其子规则(命名的或位置捕获)的哈希,或者如果规则是“原子”的话。并且没有匹配字符串的这样的子规则。