2009-06-04 3 views
1

그것에서 얻는 정보, 그리고 내가 가장 끔찍한 시간 그것으로부터 정보를 얻는 것 같다. 온라인에서 쉽게 구할 수있는 정보는 단순한 예제가없는 것처럼 보입니다. 여기서 입력 파일이 제대로 파싱 출력는 구문 분석 :: RecDescent - 나는 펄의 <a href="http://search.cpan.org/perldoc?Parse::RecDescent" rel="nofollow noreferrer">Parse::RecDescent</a> 파서 함께 일하고 있어요

PS W:\developers\paulnathan\rd_dir> perl parser.pl testfile 
$VAR1 = 4; 
$VAR1 = 8; 
PS W:\developers\paulnathan\rd_dir> 

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}; 

"재료", "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

당신은 당신이 는 HASH 심판으로 ("1") 문자열을 사용할 수 없습니다 치명적인 오류가 발생합니다 스크립트에 use strict를 추가하면 동안 [상기 사용 "엄격한 심판" merge_hash_refs]으로 전화하십시오. <defer> 지시문에 의해 생성 된 클로저는 @item의 내용을 결과적으로 하위 규칙에 의해 반환 된 hashrefs 대신에 일치시킬 때 발생합니다. 이것은 높은 수준의 규칙 (역 추적 포함) 실패 할 경우에도 $ :: 개체가 성공적으로 object 프로덕션에 의해 업데이트되는 부작용이, 물론

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

다음 <defer> 지시를 제거하면 나에게이 출력을 제공합니다.

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
아마

하지 질문에 대한 답변,하지만 당신은 해시를 통해 각() 루프를 시작할 때 (각각의 경우)는 이전에 해시 함수가 가리킨 해시에서 시작된 해시에 사용되었습니다. 안전하게하려면 while 루프 앞에 void-context keys() (예 : keys (% $ ref1);)를 넣어 반복기를 재설정하십시오. 데이터 :: 덤퍼의 이전 버전 (각 ...) 루프 :

+0

그게 답이 아니었지만 당신이 나에게 말했기 때문에 기쁩니다. :-) –