perl – 在Marpa语法中制作0长度列表的简明方法?

perl – 在Marpa语法中制作0长度列表的简明方法?,第1张

概述我是Marpa的新手.我已经尝试了几种方法来描述我的语法中的0个或更多个术语的列表,我想避免使用多个解析树. 我的语言将只有1个组件,后跟0个子组件: package => component-rule [subcomponent-rule ...] 我首先尝试的是这样的: { lhs => 'Package', rhs => [qw/component-rule subcomponents/] 我是Marpa的新手.我已经尝试了几种方法来描述我的语法中的0个或更多个术语的列表,我想避免使用多个解析树.

我的语言将只有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长度列表的简明方法?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1255496.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存