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

前端之家收集整理的这篇文章主要介绍了perl – 在Marpa语法中制作0长度列表的简明方法?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我是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/perl

use 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相关文章