(编辑:下面的pipe函数应该返回一个受祝福的对象,以便重载正常工作。请参阅接受的答案。)
我正在尝试使用perl的overload功能来构建一个简单的解析树。我不需要太多-事实上,我只需要一个左联结运算符。但是,perl解析$x op $y的方式与$x op $y op $z op ...这样的长链解析方式似乎不一致。
这就是我所拥有的:
package foo;
use overload '|' => \&pipe,
"**" => \&pipe,
">>" => \&pipe;
sub pipe { [ $_[0], $_[1] ] }
package main;
my $x = bless ["x"], "foo";
my $y = bless ["y"], "foo";
my $z = bless ["z"], "foo";
my $w = bless ["w"], "foo";
# how perl parses it:
my $p2 = $x | $y; # Cons x y
my $p3 = $x | $y | $z; # Cons z (Cons x y)
my $p4 = $x | $y | $z | $w; # Cons w (Cons z (Cons x y))
my $p5 = $z | ($x | $y); # same as p3???
my $s2 = $x ** $y; # Cons x y
my $s3 = $x ** $y ** $z; # Cons x (Cons y z)
my $s4 = $x ** $y ** $z ** $w; # Cons x (Cons y (Cons z w))
sub d { Dumper(\@_) }
say "p2 = ".d($p2);
say "p3 = ".d($p3);
say "p4 = ".d($p4);
say "p5 = ".d($p5);
say "s2 = ".d($s2);
say "s3 = ".d($s3);
say "s4 = ".d($s4);输出类似于:
p2 = [bless( ['x'], 'foo' ),bless( ['y'], 'foo' )]
p3 = [bless( ['z'], 'foo' ),[bless( ['x'], 'foo' ),bless( ['y'], 'foo' )]]
p4 = [bless( ['w'], 'foo' ),[bless( ['z'], 'foo' ),[bless( ['x'], 'foo' ),bless( ['y'], 'foo' )]]]
p5 = [bless( ['z'], 'foo' ),[bless( ['x'], 'foo' ),bless( ['y'], 'foo' )]]
s2 = [bless( ['x'], 'foo' ),bless( ['y'], 'foo' )]
s3 = [bless( ['x'], 'foo' ),[bless( ['y'], 'foo' ),bless( ['z'], 'foo' )]]
s4 = [bless( ['x'], 'foo' ),[bless( ['y'], 'foo' ),[bless( ['z'], 'foo' ),bless( ['w'], 'foo' )]]]难道p2不应该颠倒x和y来与其他情况保持一致吗?注意,p3和p5产生相同的输出-那么我如何区分它们呢?
对于右关联操作符**,我没有看到同样的问题。
有没有解决这个问题的办法?
发布于 2012-09-07 00:02:48
use feature ":5.14";
use warnings FATAL => qw(all);
use strict;
use Data::Dump qw(dump pp);
sub foo()
{package foo;
use overload '|' => \&p;
sub p {bless [@{$_[0]},@{$_[1]}]}
}
my $x = bless ["x"], "foo";
my $y = bless ["y"], "foo";
my $z = bless ["z"], "foo";
my $p = $x | $y | $z;
pp($p)产生:
bless(["x", "y", "z"], "foo")发布于 2012-09-07 08:12:34
重载运算符处理程序有时会以相反的顺序接收操作数,但是当Perl这样做时,它会通过将交换的参数设置为true来通知处理程序。
overload
将三个参数传递给use overload指令中指定的所有子例程(有一个例外-参见nomethod)。..。当(且仅当)两个操作数被交换时,第三个参数被设置为TRUE。Perl可以这样做,以确保第一个参数($self )是实现重载操作的对象,这符合一般的对象调用约定。...
您忽略了传递给处理程序的第三个参数。潜在的问题是您忘记从pipe返回一个foo对象。
发布于 2012-09-06 15:21:29
你应该检查一下Marpa,我认为它更适合解析这样的东西。
http://blogs.perl.org/users/jeffrey_kegler/2010/05/bnf-parsing-and-linear-time.html
https://metacpan.org/pod/Marpa::PP
我认为这是你的脚本中的一个打字错误:
my $p3 = $x || $y || $z;https://stackoverflow.com/questions/12293640
复制相似问题