加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

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

发布时间:2020-12-16 06:26:15 所属栏目:大数据 来源:网络整理
导读:我是Marpa的新手.我已经尝试了几种方法来描述我的语法中的0个或更多个术语的列表,我想避免使用多个解析树. 我的语言将只有1个组件,后跟0个子组件: package = component-rule [subcomponent-rule ...] 我首先尝试的是这样的: { lhs = 'Package',rhs = [qw/c
我是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_meann";

    # 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 $t1n";
    my $href = { 'Component' => $t1 };
    return $href;
}
sub My_Actions::do_subcomponent{
    my ( undef,$t1 ) = @_;
    print STDERR "do_subcomponent $t1n";
    my $href = { 'Subcomponent' => $t1 };
    return $href;
}

sub My_Actions::do_subcomponent_empty_list
{
    print STDERR "do_subcomponent_empty_listn";
    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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读