我的语言将只有1个组件,后跟0个子组件:
package => component-rule [subcomponent-rule ...]
我首先尝试的是这样的:
{ lhs => 'Package',rhs => [qw/component-rule subcomponents/] },{ lhs => 'subcomponents',rhs => [qw/subcomponent-List/] },{ lhs => 'subcomponent-List',rhs => [qw/subcomponent-rule/],action => 'do_subcomponent_List' },rhs => [qw/subcomponent-List subcomponent-rule/],rhs => [qw//],action => 'do_subcomponent_empty_List' },{ lhs => 'subcomponent-rule',rhs => [qw/subcomponent subcomponent-name/],action => 'do_subcomponent' },
(帖子末尾的完整代码.)
这是我的意见:
$recce->read( 'component',);$recce->read( 'String','MO Factory');$recce->read( 'subcomponent','Memory Wipe Station');$recce->read( 'subcomponent','DMO Tour Robot');
我得到两个解析树,第一个是不受欢迎的undef,第二个是我喜欢的.两者都将列表作为固有的树提供回来.
$VAR1 = [ { 'Component' => 'MO Factory' },[ [ { 'Subcomponent' => undef },{ 'Subcomponent' => 'Memory Wipe Station' } ],{ 'Subcomponent' => 'DMO Tour Robot' } ] ];$VAR2 = [ { 'Component' => 'MO Factory' },[ { 'Subcomponent' => 'Memory Wipe Station' },{ 'Subcomponent' => 'DMO Tour Robot' } ] ];
subcomponent-List的可空规则是允许0个子组件的情况,但它在1个子组件列表的前面引入了null元素,这是一个备用解析. (Marpa只下载了一次周期,谢天谢地.)
我的另一个想法是使子组件列表不可为空,并引入一个0或1个子组件列表的中间规则:
{ lhs => 'subcomponents',rhs => [qw//] },
这至少消除了多重解析,但我仍然有一个循环,一个凌乱的嵌套树来压缩.
是否有更直接的方法来制作0长度列表或以其他方式使符号可选?
完整示例代码:
#!/usr/bin/perluse Marpa::R2;use Data::Dumper;my $grammar = Marpa::R2::Grammar->new( { start => 'Package',actions => 'My_Actions',default_action => 'do_what_I_mean',rules => [ { lhs => 'Package',{ lhs => 'component-name',rhs => [qw/String/] },{ lhs => 'component-rule',rhs => [qw/component component-name/],action => 'do_component' },{ lhs => 'subcomponent-name',# { lhs => 'subcomponent-List',},],});$grammar->precompute();my $recce = Marpa::R2::Recognizer->new( { grammar => $grammar } );$recce->read( 'component','MO Factory');if (1) {$recce->read( 'subcomponent','DMO Tour Robot');$recce->read( 'subcomponent','SMO Break Room');}my @values = ();while ( defined( my $value_ref = $recce->value() ) ) { push @values,${$value_ref};}print "result is ",Dumper(@values),"\n";sub My_Actions::do_what_I_mean { print STDERR "do_what_I_mean\n"; # The first argument is the per-parse variable. # At this stage,just throw it away shift; # Throw away any undef's my @children = grep { defined } @_; # Return what's left return scalar @children > 1 ? \@children : shift @children;}sub My_Actions::do_component { my ( undef,$t1 ) = @_; print STDERR "do_component $t1\n"; my $href = { 'Component' => $t1 }; return $href;}sub My_Actions::do_subcomponent{ my ( undef,$t1 ) = @_; print STDERR "do_subcomponent $t1\n"; my $href = { 'Subcomponent' => $t1 }; return $href;}sub My_Actions::do_subcomponent_empty_List{ print STDERR "do_subcomponent_empty_List\n"; my $href = { 'Subcomponent' => undef }; return $href;}sub My_Actions::do_subcomponent_List{ # The first argument is the per-parse variable. # At this stage,just throw it away shift; # Throw away any undef's my @children = grep { defined } @_; print STDERR "do_subcomponent_List size ",scalar(@children),"\n";# Do this to collapse recursive trees to a List:# @children = map { ref $_ eq "ARRAY" ? @{$_} : $_; } @children; return scalar @children > 1 ? \@children : shift @children;}解决方法 使用min参数指定 sequence rule.该值可以是0(也就是正则表达式中的*量词)或1(也就是量词).您可以通过删除子组件和子组件列表规则来完成此 *** 作.而是添加:
{ lhs => 'subcomponents',rhs => ['subcomponent-rule'],min => 0,action => 'do_subcomponent_List',}
然后您的语法无需进一步修改即可运行.
使用序列规则是优选的:不必进行展平,语法应该更有效.
请注意,建议您使用“无扫描接口”. DSL在这个问题上很好地抽象:
subcomponents ::= <subcomponent rule>* action => do_subcomponent_List总结
以上是内存溢出为你收集整理的perl – 在Marpa语法中制作0长度列表的简明方法?全部内容,希望文章能够帮你解决perl – 在Marpa语法中制作0长度列表的简明方法?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)