dax*_*xim 10 grammar parsing perl6
考虑语法:
TOP ? 'x' Y 'z'
Y ? 'y'
Run Code Online (Sandbox Code Playgroud)
以下是如何["TOP","x",["Y","y"],"z"]使用各种解析器获取精确值(不是手动编写,而是从语法生成):
xyz__Parse-Eyapp.eyp
%strict
%tree
%%
start:
TOP { shift; use JSON::MaybeXS qw(encode_json); print encode_json $_[0] };
TOP:
'x' Y 'z' { shift; ['TOP', (scalar @_) ? @_ : undef] };
Y:
'y' { shift; ['Y', (scalar @_) ? @_ : undef] };
%%
Run Code Online (Sandbox Code Playgroud)
xyz__Regexp-Grammars.pl
use 5.028;
use strictures;
use Regexp::Grammars;
use JSON::MaybeXS qw(encode_json);
print encode_json $/{TOP} if (do { local $/; readline; }) =~ qr{
<nocontext:>
<TOP>
<rule: TOP>
<[anon=(x)]> <[anon=Y]> <[anon=(z)]>
<MATCH=(?{['TOP', $MATCH{anon} ? $MATCH{anon}->@* : undef]})>
<rule: Y>
<[anon=(y)]>
<MATCH=(?{['Y', $MATCH{anon} ? $MATCH{anon}->@* : undef]})>
}msx;
Run Code Online (Sandbox Code Playgroud)
代码省略了接下来的两个解析器.使用Pegex,通过继承Pegex :: Receiver实现功能.使用Marpa-R2,返回值的自定义非常有限,但嵌套数组可以通过配置选项开箱即用.
我已经证明了所需的定制是可能的,尽管它并不总是容易或直接.附加到规则的这些代码段在树组装时运行.
该解析方法返回无非是笨重嵌套的匹配对象.他们没有保留未命名的终端!(只是为了确定我在说什么:这些是TOP规则的RHS中的两个数据,其值是'x'和'z'.)显然,只有从命名声明符弹出的数据才被添加到树中.
分配到匹配变量(类似于它在Regexp-Grammars中的工作方式)似乎没有效果.由于终端没有将它变成匹配变量,因此动作也没有帮助.
总之,这里是语法和普通解析值:
grammar {rule TOP { x <Y> z }; rule Y { y };}.parse('x y z')
Run Code Online (Sandbox Code Playgroud)
你如何从中获得价值["TOP","x",["Y","y"],"z"]?您不能更改规则的形状,因为这可能会破坏用户附加的语义,否则其他任何东西都是公平的游戏.我仍然认为解决方案的关键是匹配变量,但我看不出如何.
不是完整的答案,但Match.chunks方法为您提供了一些标记为捕获和未捕获部分的输入字符串.
但是,它确实无法区分正则表达式中的非捕获文字和隐式匹配的空格.
您可以通过添加位置捕获来避开它,并使用Match.caps
my $m = grammar {rule TOP { (x) <Y> (z) }; rule Y { (y) }}.parse('x y z');
sub transform(Pair $p) {
given $p.key {
when Int { $p.value.Str }
when Str { ($p.key, $p.value.caps.map(&transform)).flat }
}
}
say $m.caps.map(&transform);
Run Code Online (Sandbox Code Playgroud)
这产生了
(x (Y y) z)
Run Code Online (Sandbox Code Playgroud)
这么多你想要的东西,除了顶级TOP缺失(如果你对其进行硬编码,你可能只会在那里进入).
请注意,这并未涵盖所有边缘情况; 例如,当量化捕获时,$p.value是一个数组,而不是一个匹配对象,所以你需要另一个级别.map,但一般的想法应该是清楚的.
| 归档时间: |
|
| 查看次数: |
92 次 |
| 最近记录: |