2017-01-20 3 views
6

ここには2つの文法があります。 1つはproto tokenを使用し、1つは使用しません。彼らはどちらも同じことをします。これらは基本的にS05 under "Variable (non-)interpolation"の例です。この単純な例では、どちらも同じことをすることができます。Perl 6の文法でprotoルールを使用するのはなぜですか?

追加の入力をすべて正当化する状況はありますか? 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

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 sが、いくつかの特徴

  • を共有したいので、{ * }

    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

    を支援ロジックを分離する。基本的に文法以外のマルチメソッドと同じ考えです。

    (I Code Golfへの回答を評価するためのwrote this

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

    サブクラス化文法が既に存在するものの側面に沿ってそのトークンを追加できるようにそれはまたそれを行い、サブクラスのアクションクラスを行うことができます同じ。プロトとのマルチにあなたの選択肢を分割する(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

    1つの利点は、あなたがより確実にそれを拡張することができるということです。 protoを宣言する文法を継承する文法で既存のprotoにmultisを追加することができます。可能なすべての選択肢をリストする必要はありません(単一の規則の場合に行う必要があります)。

    これは、同じ文法に複数の独立した拡張子を設定することもできます。

    これは基本的に、カスタム演算子を定義するときにPerl 6自身が使用するメカニズムです。異なる種類の演算子(infix、prefix、postfixなど)を一致させるルールがあり、新しい演算子のために複数の候補が追加された、現在アクティブな文法。スクリプトは、プロトトークンメカニズムの拡張性のおかげで、互いに知り合わない複数のモジュールからオペレータをインポートすることができます。

    関連する問題