Perl Parse::RecDescent-从中获取信息

Perl Parse::RecDescent-从中获取信息,perl,parse-recdescent,Perl,Parse Recdescent,我正在用Perl处理解析器,从中获取信息的时间似乎最糟糕。网上现成的信息似乎没有不寻常的例子 代码如下: event_function: object_list ':' event_list ';' <defer: { #item is a special character with Parse::Recdescent. print Dumper($item{object_list}); $ret

我正在用Perl处理解析器,从中获取信息的时间似乎最糟糕。网上现成的信息似乎没有不寻常的例子

代码如下:

event_function: object_list ':' event_list ';'
        <defer:
        {       #item is a special character with Parse::Recdescent.
            print Dumper($item{object_list});
            $return = $item[1];
        }
        >
        | object_list ':' ';'
        <defer:
        { 
            print Dumper($item{object_list});
            $return = $item[1];
        }
        >
输入文件解析正确

stuff, stuff2: pre-operation event = {foo1, foo2};
它应该输出一个由stuff,stuff2键控的散列

想法

编辑:

如果在脚本中添加use strict,则会出现致命错误[merge_HASH_refs调用]处使用strict refs时,无法将字符串1用作哈希引用。看起来,指令创建的闭包导致@item的内容成为生产匹配时的内容,而不是子规则最终返回的hashref。删除这些指令会产生以下输出:

$VAR1 = {
          'stuff2' => 'stuff',
          'stuff' => 'stuff'
        };
当然,这有一个副作用,即即使较高级别的规则失败(包括回溯),成功的对象生成也会更新$::对象。我会这样写:

use strict;
use warnings;
use Parse::RecDescent;
use Data::Dumper;

my $parser = Parse::RecDescent->new(<<'EOT');
event_function: object_list ':' event_list(?) ';'
    {
        $return = $item[1];
    }

object_list : <leftop: object ',' object>
    {
        $return = { map { %$_ } @{$item[1]} };
    }

object : 
    '/' /[a-z0-9_][a-z0-9_]*/ '/' '...'
        {
            $return = { $item[2] => 'stuff' };
        }
    |  /[a-z0-9_][a-z0-9_]*/
        { 
            $return = { $item[1] => 'stuff' };
        }

# stub, don't know what this should be
event_list : /[^;]+/

EOT

my %object;

while (<DATA>) {
    my $x = $parser->event_function($_);

    next unless $x;

    # merge objects into master list
    while (my ($k, $v) = each %$x) {
        $object{$k} = $v;
    }
}

print Dumper \%object;

__DATA__
stuff, stuff2: pre-operation event = {foo1, foo2};
stuff3, stuff4: ;
如果在脚本中添加use strict,则会出现致命错误[merge_HASH_refs调用]处使用strict refs时,无法将字符串1用作哈希引用。看起来,指令创建的闭包导致@item的内容成为生产匹配时的内容,而不是子规则最终返回的hashref。删除这些指令会产生以下输出:

$VAR1 = {
          'stuff2' => 'stuff',
          'stuff' => 'stuff'
        };
当然,这有一个副作用,即即使较高级别的规则失败(包括回溯),成功的对象生成也会更新$::对象。我会这样写:

use strict;
use warnings;
use Parse::RecDescent;
use Data::Dumper;

my $parser = Parse::RecDescent->new(<<'EOT');
event_function: object_list ':' event_list(?) ';'
    {
        $return = $item[1];
    }

object_list : <leftop: object ',' object>
    {
        $return = { map { %$_ } @{$item[1]} };
    }

object : 
    '/' /[a-z0-9_][a-z0-9_]*/ '/' '...'
        {
            $return = { $item[2] => 'stuff' };
        }
    |  /[a-z0-9_][a-z0-9_]*/
        { 
            $return = { $item[1] => 'stuff' };
        }

# stub, don't know what this should be
event_list : /[^;]+/

EOT

my %object;

while (<DATA>) {
    my $x = $parser->event_function($_);

    next unless $x;

    # merge objects into master list
    while (my ($k, $v) = each %$x) {
        $object{$k} = $v;
    }
}

print Dumper \%object;

__DATA__
stuff, stuff2: pre-operation event = {foo1, foo2};
stuff3, stuff4: ;

可能不是您问题的答案,但是当您通过散列启动each循环时,如果之前在散列上使用过each,那么它只是从迭代器指向的任何地方开始。为安全起见,请放置一个空的上下文键,例如键%$ref1;在while循环之前重置迭代器。旧版本的Data::Dumper有一个可爱的小错误,有时会让迭代器指向最后一个元素之后,使哈希看起来是空的,而不安全的是…每个。。。循环:

可能不是您问题的答案,但当您通过散列启动each循环时,如果先前在散列上使用过each,则它只是从迭代器指向的任何位置开始。为安全起见,请放置一个空的上下文键,例如键%$ref1;在while循环之前重置迭代器。旧版本的Data::Dumper有一个可爱的小错误,有时会让迭代器指向最后一个元素之后,使哈希看起来是空的,而不安全的是…每个。。。循环:

能否显示对象列表和事件列表规则的内容?事件列表不返回任何内容;添加了对象列表。能否显示对象列表和事件列表规则的内容?事件列表不返回任何内容;添加了对象列表。这是一种邪恶的感觉。叹气谢谢你,这是一种邪恶的感觉。叹气谢谢。这不是答案,但我很高兴你告诉我-那不是答案,但我很高兴你告诉我-
use strict;
use warnings;
use Parse::RecDescent;
use Data::Dumper;

my $parser = Parse::RecDescent->new(<<'EOT');
event_function: object_list ':' event_list(?) ';'
    {
        $return = $item[1];
    }

object_list : <leftop: object ',' object>
    {
        $return = { map { %$_ } @{$item[1]} };
    }

object : 
    '/' /[a-z0-9_][a-z0-9_]*/ '/' '...'
        {
            $return = { $item[2] => 'stuff' };
        }
    |  /[a-z0-9_][a-z0-9_]*/
        { 
            $return = { $item[1] => 'stuff' };
        }

# stub, don't know what this should be
event_list : /[^;]+/

EOT

my %object;

while (<DATA>) {
    my $x = $parser->event_function($_);

    next unless $x;

    # merge objects into master list
    while (my ($k, $v) = each %$x) {
        $object{$k} = $v;
    }
}

print Dumper \%object;

__DATA__
stuff, stuff2: pre-operation event = {foo1, foo2};
stuff3, stuff4: ;
$VAR1 = {
          'stuff2' => 'stuff',
          'stuff3' => 'stuff',
          'stuff' => 'stuff',
          'stuff4' => 'stuff'
        };