Parse::RecDescent - 从中获取信息
我正在 Perl 中使用 Parse::RecDescent 解析器,我似乎从中获取信息是最糟糕的。 网上现成的信息似乎没有重要的例子。
这是代码:
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];
}
>
这是输出
PS W:\developers\paulnathan\rd_dir> perl parser.pl testfile
$VAR1 = 4;
$VAR1 = 8;
PS W:\developers\paulnathan\rd_dir>
输入文件解析正确。
stuff, stuff2: pre-operation event = {foo1, foo2};
它应该输出一个以“stuff”、“stuff2”为键的哈希值。
想法?
编辑:
object_list :
object ',' object_list
<defer:
{
my $retval = ();
$retval = ::merge_hash_refs($item[1], $item[3]);
$return = $retval;
}
>
| object
<defer:
{
#print Dumper($item{object});
$return = $item{object};
}
>
object :
'/' /[a-z0-9_][a-z0-9_]*/ '/' '...'
<defer:
{
$::objects->{$item[2]} = "stuff";
$return = $::objects;
}
>
| /[a-z0-9_][a-z0-9_]*/
<defer:
{
$::objects->{$item[1]} = "stuff";
$return = $::objects;
}
>
编辑2: Merge_hash_refs,以防万一。 :-)
#takes two hash references.
sub merge_hash_refs {
my($ref1, $ref2) = @_;
my $retref = ();
while( my ($k, $v) = each %$ref1 ) {
$retref->{$k} = $v;
}
while( my ($k, $v) = each %$ref2 ) {
$retref->{$k} = $v;
}
return $retref;
}
I'm working with the Parse::RecDescent parser in Perl, and I seem to have the most terrible time getting information from it. The information readily available online does not seem to have non-trivial examples.
Here is the code:
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];
}
>
Here is the output
PS W:\developers\paulnathan\rd_dir> perl parser.pl testfile
$VAR1 = 4;
$VAR1 = 8;
PS W:\developers\paulnathan\rd_dir>
The input file parses correctly.
stuff, stuff2: pre-operation event = {foo1, foo2};
It should be outputting a hash keyed by "stuff", "stuff2".
Thoughts?
edit:
object_list :
object ',' object_list
<defer:
{
my $retval = ();
$retval = ::merge_hash_refs($item[1], $item[3]);
$return = $retval;
}
>
| object
<defer:
{
#print Dumper($item{object});
$return = $item{object};
}
>
object :
'/' /[a-z0-9_][a-z0-9_]*/ '/' '...'
<defer:
{
$::objects->{$item[2]} = "stuff";
$return = $::objects;
}
>
| /[a-z0-9_][a-z0-9_]*/
<defer:
{
$::objects->{$item[1]} = "stuff";
$return = $::objects;
}
>
edit2:
Merge_hash_refs, just in case. :-)
#takes two hash references.
sub merge_hash_refs {
my($ref1, $ref2) = @_;
my $retref = ();
while( my ($k, $v) = each %$ref1 ) {
$retref->{$k} = $v;
}
while( my ($k, $v) = each %$ref2 ) {
$retref->{$k} = $v;
}
return $retref;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您在脚本中添加
use strict
,您将收到致命错误 Can't use string ("1") as a HASH ref while "strict refs" in use at [the调用merge_hash_refs
]。 看来由
指令创建的闭包导致@item
的内容成为产生式匹配时的内容,而不是最终由子规则。 删除
指令会给出以下输出:当然,这会产生副作用,即 $::object 会被成功的
object
生成更新,即使更高级别也是如此规则失败(包括回溯)。 我会这样写:输出是:
If you add a
use strict
to your script you'll get the fatal error Can't use string ("1") as a HASH ref while "strict refs" in use at [the call tomerge_hash_refs
]. It appears that the closures created by the<defer>
directives are causing the contents of@item
to be the ones when the production matched instead of the hashrefs eventually returned by the subrules. Removing the<defer>
directives gives me this output:Of course, this has the side effect that $::object is updated by successful
object
productions even if the higher level rules fail (including backtracking). I'd write it this way:The output is:
可能不是您问题的答案,但是当您通过哈希启动each()循环时,如果之前在哈希上使用过each(),那么它只会从迭代器指向的位置开始。 为了安全起见,请在 while 循环之前放置一个 void-contextkeys()(例如,keys(%$ref1);)以重置迭代器。 旧版本的 Data::Dumper 有一个可爱的小错误,有时让迭代器指向最后一个元素之后,使得散列对于不安全的 while(...each...) 循环来说似乎是空的:)
Probably not an answer to your question, but when you start an each() loop through a hash, if each() had previously been used on the hash it just starts from wherever the iterator was pointing. To be safe, put a void-context keys() (e.g. keys(%$ref1);) before the while loop to reset the iterator. Older versions of Data::Dumper had a cute little bug of leaving the iterator pointing just after the last element sometimes, making the hash appear to be empty to an unsafe while(...each...) loop :)