Perl6:将 Match 对象转换为 JSON-serializable Hash
Perl6: Convert Match object to JSON-serializable Hash
我目前正忙于研究 Perl6。具体来说,我正在尝试编写一个基于语法的 Fortran 解析器(Fortran::Grammar 模块)
出于测试目的,我希望能够将 Match
对象转换为 JSON-可序列化 Hash
.
谷歌搜索/official Perl6 documentation 没有帮助。如果我忽略了什么,我深表歉意。
我目前的尝试:
- 我知道可以通过
$m.hash
将 Match $m
转换为 Hash
。但这会保留嵌套的 Match
个对象。
- 因为这 有 可以通过递归解决,我尝试了但放弃了首先在这里询问 simpler/existing 解决方案的存在性
- 处理
Match
对象的内容显然最好通过 make
/made
完成。我很想有一个超级简单的 Actions
对象交给 .parse
与 default 方法基本上只是做一个 make $/.hash
或之类的东西。我只是不知道如何指定默认方法。
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.
我目前正忙于研究 Perl6。具体来说,我正在尝试编写一个基于语法的 Fortran 解析器(Fortran::Grammar 模块)
出于测试目的,我希望能够将 Match
对象转换为 JSON-可序列化 Hash
.
谷歌搜索/official Perl6 documentation 没有帮助。如果我忽略了什么,我深表歉意。
我目前的尝试:
- 我知道可以通过
$m.hash
将Match $m
转换为Hash
。但这会保留嵌套的Match
个对象。 - 因为这 有 可以通过递归解决,我尝试了但放弃了首先在这里询问 simpler/existing 解决方案的存在性
- 处理
Match
对象的内容显然最好通过make
/made
完成。我很想有一个超级简单的Actions
对象交给.parse
与 default 方法基本上只是做一个make $/.hash
或之类的东西。我只是不知道如何指定默认方法。
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/orindex=>submatch
对的序列。
- 它允许您覆盖特定规则的 AST 生成,方法是在语法中的规则内添加一个
{ make ... }
块(假设您从不想make
一个未定义的值) ,或者通过将具有规则名称的方法添加到操作 class.