在cpan的Marpa::R2页面中,我了解了BNF(Backus-Naur表格),但我对动作回调感到很遗憾。
在下面的这个例子中,我理解左右两个成员都被传递给do_multiply
。对于那件事我没有任何疑问。问题是我找不到任何关于这些论点的文档?
my $dsl = <<'END_OF_DSL';
:default ::= action => [name,values]
lexeme default = latm => 1
Calculator ::= Expression action => ::first
...
Term '*' Factor action => do_multiply
...
END_OF_DSL
my $grammar = Marpa::R2::Scanless::G->new( { source => \$dsl } );
sub do_multiply { $_[1] * $_[2] }
什么是$_[0]
甚至$_[3]
?这记录在哪里?即使在official marpa website我也看不到任何文档。
在另一个示例here chobora的答案中,我们看到pair
引用了$_[2]
和$_[3]
:
BNF的片段:
Hash ::= '(' Pairs ')' action => hash
Pairs ::= Pair+ action => pairs
Pair ::= '(' Key Value ')' action => pair
Key ::= String
核心代码:
$recce->read(\$input);
print Dumper $recce->value;
sub hash { $_[2] }
sub pairs { shift; +{ map @$_, @_ } }
sub pair { [ @_[2, 3] ] } # What is 2 and 3?
sub itself { $_[1] }
答案 0 :(得分:4)
Marpe::R2 docs说出以下内容:
sub My_Actions::do_add { my ( undef, $t1, undef, $t2 ) = @_; return $t1 + $t2; }
Perl语义闭包是回调。它们被称为每个节点 在解析树中进行评估。
使用一个或多个参数调用每个Perl语义闭包。该 值action的第一个参数始终是per-parse-tree对象, 回调可以用作暂存器。在这个例子中, 不使用per-parse-tree对象。其余的论据将是 节点的价值&#34;儿童&#34; - 换句话说,计算出的值 对于每个RHS符号,按顺序。如果操作是空的 规则,per-parse-tree对象将是它唯一的参数。
每个值操作都应返回一个值。除了一个例外, 此值作为参数传递给父节点。例外 是起始规则的值。起始规则的返回值 成为解析结果。
因此,这些函数作为第一个参数传递给对象。那是$_[0]
。
对于您的示例,文本似乎意味着以下参数$_[1]
和$_[2]
只是您用来计算内容的值。
添加一些调试输出给了我以下内容:
use Data::Printer;
sub My_Actions::do_add {
my ( undef, $t1, undef, $t2 ) = @_;
say 'do_add';
p @_;
return $t1 + $t2;
}
sub My_Actions::do_multiply {
my ( undef, $t1, undef, $t2 ) = @_;
say 'do_multiply';
p @_;
return $t1 * $t2;
}
__END__
do_multiply
[
[0] {},
[1] 42,
[2] "*",
[3] 1
]
do_add
[
[0] {},
[1] 42,
[2] "+",
[3] 7
]