2009-06-04 2 views
1

Я работаю с парсером 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}; 

Это должно быть вывод хэша заклиненного на "материал", "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; 
      } 
      > 

edit2: 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; 
} 
+0

Можете ли вы показать содержимое правил object_list и event_list? –

+0

Event_list ничего не возвращает; добавлен object_list. –

ответ

6

Если добавить use strict в скрипт вы получите фатальную ошибку не может использовать строку («1») в качестве хэша реф, а «строгие рефов» в использовании на [ позвоните по номеру merge_hash_refs]. Похоже, что замыкания, созданные директивами <defer>, вызывают содержимое @item, если они совпадают с производством, а не с хэш-файлами, которые в конечном итоге возвращаются субстратами. Удаление <defer> директивы дает мне этот выход:

$VAR1 = { 
      'stuff2' => 'stuff', 
      'stuff' => 'stuff' 
     }; 

Конечно, это имеет побочный эффект, что $ :: объект обновляется успешными object производств, даже если правила более высокого уровня потерпеть неудачу (в том числе и возвратов). Я бы написать так:

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' 
     }; 
+0

Это делает вид злого смысла. Вздох. Спасибо. –

1

Вероятно, не ответ на ваш вопрос, но при запуске каждого() цикл через хэш, если каждый () ранее использовались в хеше, который он только начинал с того места, где указывал итератор. Чтобы быть в безопасности, поместите ключи void-context() (например, ключи (% $ ref1);) перед циклом while, чтобы сбросить итератор. В старых версиях Data :: Dumper была небольшая ошибка, заключающаяся в том, что итератор указывал сразу после последнего элемента, делая хэш, кажется, пустым до небезопасного while (... each ...) loop :)

+0

Это был не ответ, но я рад, что ты сказал мне. :-) –

 Смежные вопросы

  • Нет связанных вопросов^_^