2013-09-01 4 views
7

私はPerlにとって非常に新しいので、新しいPerl 6文法機能を使用して優先順位を持つ演算子でドメイン固有の言語を作成したい。たとえば、 "1 + 2 * 6"を正しい方法で解析する。演算子の優先順位規則を持つPerl 6文法の例

これまでに見つかったドキュメント(例:this)には、優先順位の宣言がある演算子の文法規則の例はありません。

私はこの非常に単純な例を持って

use v6; 

#use Grammar::Tracer; 

grammar TestGrammar { 

    token TOP { 
     <digit> <infix> <digit> 
    } 

    token infix:sym<times> is equiv(&infix:<*>) { <sym> } 

} 

sub MAIN() { 
    my $text = "1 times 2" ; 
    say $text ; 

    my $match = TestGrammar.parse($text); 
    say $match; 
} 

これは私がちょうど抽象構文木を構築したい私に

No such method 'infix' for invocant of type 'TestGrammar' 

を与えます。

答えて

5

AFAIKでは、中置演算子を設定したり、文法で優先順位などを定義することはできません。これらは現在、Perl 6の拡張にのみ適用されます。

ここでは可能なアプローチです。加算の前に乗法項を解析し、単語や記号も許可する。 timesまたは*

use v6; 

grammar TestGrammar { 

    rule TOP  { <expr=.add> } 

    rule add  { <expr=.multiply> +% [ <add-op> ] } 
    rule multiply { <digit> +% [ <mult-op> ] } 

    proto token mult-op {*} 
    token mult-op:sym<times> { <sym>|'*' } 
    token mult-op:sym<divided> { <sym>|'/' } 

    proto token add-op {*} 
    token add-op:sym<plus>  { <sym>|'+' } 
    token add-op:sym<minus> { <sym>|'-' } 

} 

sub MAIN() { 
    for ("2+2", "2 + 2", "1 * 2", "1 + 2 * 6", "4 times 7 minus 3") { 
     say $_; 
     my $match = TestGrammar.parse($_); 
     say $match; 
    } 
} 

%セパレータオペレータであることに留意されたいです。 <digit> +% [ <mult-op> ]は、乗法演算子(times*dividedまたは/)で区切られた数字のリストを意味します。

代替ソリューション2014年9月:

S05ルールやトークンは特別な方法があるが、両方がマルチとして宣言し、ちょうど通常の方法のように引数を取ることができることを言及しません。

このアプローチでは、オペレータの優先レベルを実装するために、再帰とマルチディスパッチの両方を利用します。

use v6; 

grammar TestGrammar { 

    rule TOP    { <expr(3)> } 

    # operator multi-dispatch, loosest to tightest 
    multi token op(3) {'+'|'-'|add|minus} 
    multi token op(2) {'*'|'/'|times|divided} 
    multi token op(1) {'**'} 

    # expression multi-dispatch (recursive) 
    multi rule expr(0)  { <digit> | '(' ~ ')' <expr(3)> } 
    multi rule expr($pred) { <expr($pred-1)> +% [ <op($pred)> ] } 

} 

sub MAIN() { 
    for ("2+2", "2 + 2", "1 * 2", "1 + 2**3 * 6", "4 times (7 minus 3) * 3") { 
     say $_; 
     my $match = TestGrammar.parse($_); 
     say $match; 
    } 
} 
+0

これは私が避けたいと考えていた標準的なアプローチです。最後に、私自身の演算子(postcircumfix、listなど)の多くを定義したいと思っていました。そして、perlがこれを処理すると思っていました。 [Parrot Grammar Engine](http://docs.parrot.org/parrot/latest/html/docs/book/pct/ch04_pge.pod.html)についても同じことが分かりますか? – user2660278

+0

Perl6はnqpのHLL :: Grammarを継承しています。また、Perl 6 irc - http://perl6.org/community/irc – dwarring

+1

アップデートに関する質問をすることもできます:NQPツールチェーンを使ってHLLやドメイン固有の言語を実装するためのドキュメントと実例がいくつかあります。 http://edumentab.github.io/rakudo-and-nqp-internals-course/slides-day1.pdfを参照してください。作業例はpp 118 – dwarring

関連する問題