2017-01-20 16 views
6

두 문법이 있습니다. 하나는 proto token을 사용하지만 하나는 사용하지 않습니다. 그들은 둘 다 똑같이합니다. 이것은 기본적으로 S05 under "Variable (non-)interpolation"의 예입니다. 이 간단한 예에서, 그들은 모두 같은 일을 할 수 있습니다.Perl 6 문법에서 proto 규칙을 사용하는 이유는 무엇입니까?

추가 입력을 모두 합리화하는 경우가 있습니까? proto 토큰에는 액션 클래스에서 고유 한 메소드가 있으며, 거기에 작은 이점이있을 수 있습니다. 그러나 그 혜택을 얻으려면 몇 가지 추가 사항을 입력해야합니다.

proto의 일부 기능으로 문법의 다른 부분을 쉽게 만들 수 있습니까? 당신이 스스로를 지정하지 않은 경우

------No proto parsing 
found sigil: $ 
found identifier: butterfuly 
found variable: $butterfuly 
------Yes proto parsing 
found sym sigil: $ 
found identifier: butterfuly 
found variable: $butterfuly 

답변

7

기술적으로는하는 proto 당신을 위해 할 것입니다 :

grammar NoProto { 
    token variable { <sigil> <identifier> } 

    token identifier { <ident>+ } 
    token sigil  { < $ @ % & :: > } 
    } 

grammar YesProto { 
      token variable  { <sigil> <identifier> } 

      token identifier { <ident>+ } 
    proto token sigil   { *  } 
      token sigil:sym<$> { <sym> } 
      token sigil:sym<@> { <sym> } 
      token sigil:sym<%> { <sym> } 
      token sigil:sym<&> { <sym> } 
      token sigil:sym<::> { <sym> } 
    } 

class Proto::Actions { 
    method variable ($/) { 
     say "found variable: " ~ $/; 
     } 
    method identifier ($/) { 
     say "found identifier: " ~ $/; 
     } 
    method sigil ($/) { 
     say "found sigil: " ~ $/; 
     } 
    method sigil:sym<$> ($/) { 
     say "found sym sigil: " ~ $/; 
     } 
    } 

my $variable = '$butterfuly'; 

say "------No proto parsing"; 
my $no_proto_match = NoProto.parse(
    $variable, 
    :rule<variable>, 
    :actions(Proto::Actions), 
    ); 

say "------Yes proto parsing"; 
my $yes_proto_match = YesProto.parse(
    $variable, 
    :rule<variable>, 
    :actions(Proto::Actions), 
    ); 

출력은 proto 액션 클래스의 다른 메소드를 호출 보여줍니다. 기본적으로 해당 token에 대한 다중 메서드 디스패치 처리기를 만듭니다 (submethod과 동일). 당신은 보통 걱정할 필요가 없습니다.

proto을 지정 하시겠습니까? 당신이 이전 또는 파견

예 후 일부 코드를 실행하려는 때문에 token의 몇 가지 특성

  • 을 공유하려는 때문에 { * }

    1. : 나는 여러 가지 이유를 생각할 수 실행 코드가 포함될 수 있습니다. 벌거숭이 인 Whatever은 해당 후보자에게 파견을 지시합니다. sub와 간단한 상황이 표시 :

      proto a(|) { say "before"; {*}; say "after" } 
      multi a(Int) { say "Int" } 
      multi a(Str) { say "Str" } 
      a 42; a "42" 
      

      쇼 :

      before 
      Int 
      after 
      before 
      Str 
      after 
      

      희망이 그것이 유용 할 수있는 행동 클래스에서 호출하는 방법을 갖는 :-)

  • +0

    아, 알겠습니다. 하지만 왜 액션 클래스의'sigil' 메소드가 호출되지 않았을까요? 저는 문법 밖에서 이것을 사용할 수 있습니다.하지만 저는 문법 안에서 그 문법을 생각해 보려고합니다. 내가 본 예는 복잡하지 않았거나화물 숭배였습니다. –

    6

    하는 데 도움이 논리를 분리. 이것은 기본적으로 문법을 제외하고는 다중 방법과 같은 생각입니다.

    서브 클래스 문법은 이미 존재하는 것들의 측면을 따라 자사의 토큰을 추가 할 수 있도록 그것은 또한 그것을 만드는

    grammar Mathemania { 
        token TOP    { <cmd-list>   } 
    
        token cmd-list   { <cmd>+    } 
    
        token cmd    { <op> <argument>? } 
    
        proto token op   { * } 
        token op:sym<exp>  { e } # notice that the name doesn't have to match 
        token op:sym<factorial> { f } 
        token op:sym<root>  { r } 
        token op:sym<ceil>  { c } 
        token op:sym<floor>  { l } 
    
        token argument   { '(' ~ ')' <cmd-list> } 
    } 
    
    class Calculate { 
        method TOP  ($/) { make $<cmd-list>.made } 
        method argument ($/) { make $<cmd-list>.made } 
    
        method cmd-list ($/) { 
        my $result = 2; 
    
        $result = .made.($result).narrow for @<cmd>; 
    
        make $result; 
        } 
    
        method cmd ($/) { 
        if $<argument> { 
         make $<op>.made.assuming(*, $<argument>.made); 
        } else { 
         make $<op>.made; 
        } 
        } 
    
        method op:sym<exp>  ($/) { make -> \n, \e = 2 { n ** e     } } 
        method op:sym<factorial> ($/) { make -> \n, \k = 2 { [*] n, n - k + 1 ...^ 0 } } 
        method op:sym<root>  ($/) { make -> \n, \r = 2 { n ** (1/r)    } } 
        method op:sym<ceil>  ($/) { make &ceiling } 
        method op:sym<floor>  ($/) { make &floor } 
    
    } 
    

    (A Code Golf에 대한 답변을 평가하기위한 I wrote this)

    및 하위 클래스 작업 클래스는 작업을 수행 할 수 있습니다 같은. 프로토과 멀티로 대안을 분할하는 (try it)

    grammar Mathmania-Plus is Mathemania { 
        token op:sym<negate> { n } 
        token op:sym<abs> { a } 
    } 
    
    class Calculate-Plus is Calculate { 
        method op:sym<negate> ($/) { make &prefix:<-> } 
        method op:sym<abs> ($/) { make &abs } 
    } 
    
    +1

    따라서 하위 (문법 | 클래스)의 경우 메서드를 재정의하거나 확장 할 필요가 없습니다. 그게 좋은 물건이야. –

    5

    이점 중 하나는 당신이 더 안정적으로 확장 할 수 있다는 것입니다. proto를 선언하는 문법을 상속하는 문법으로 기존의 proto에 multis를 추가 할 수 있으며 모든 가능한 대안을 나열 할 필요가 없습니다 (단일 규칙의 경우 수행해야 할).

    즉, 동일한 문법에 여러 개의 독립적 인 확장을 적용 할 수도 있습니다. 예를 들어 일치시킬 다른 기호에 대해 multis를 제공하는 몇 가지 규칙을 혼합하여 사용할 수 있습니다.

    이것은 기본적으로 Perl 6이 사용자 지정 연산자를 정의 할 때 사용하는 메커니즘입니다. 서로 다른 종류의 연산자 (예 : 접미사, 접두사, 후위 ...)를 일치시키는 규칙이 있으며 새 연산자를 선언하면 새로운 연산자에 대해 다중 후보가 추가 된 현재 활성 문법입니다. 스크립트는 프로토 토큰 메커니즘의 확장 성 덕분에 서로를 모르는 여러 모듈에서 연산자를 가져올 수 있습니다.