2013-09-01 98 views
7

Tôi rất mới đối với Perl và muốn tạo một ngôn ngữ cụ thể cho miền với các toán tử có ưu tiên sử dụng các tính năng ngữ pháp Perl 6 mới. Ví dụ để phân tích cú pháp "1 + 2 * 6" theo cách chính xác.Ví dụ về ngữ pháp Perl 6 với các quy tắc ưu tiên toán tử

Tài liệu tôi đã tìm thấy cho đến bây giờ (ví dụ: this) chưa có ví dụ về quy tắc ngữ pháp cho nhà khai thác có tuyên bố ưu tiên.

Tôi có ví dụ này rất đơn giản

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

này mang lại cho tôi

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

Tôi chỉ muốn xây dựng một cây cú pháp trừu tượng.

Trả lời

5

AFAIK bạn không thể thiết lập các toán tử infix và xác định quyền ưu tiên vv trong ngữ pháp. Đây chỉ hiện áp dụng cho việc mở rộng Perl 6.

Đây là cách tiếp cận có thể có. Nó phân tích các cụm từ nhân trước khi bổ sung và cũng cho phép các từ hoặc ký hiệu, ví dụ: times hoặc *.

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

Lưu ý rằng % là các nhà điều hành tách. <digit> +% [ <mult-op> ] là danh sách các chữ số được phân cách bởi toán tử nhân (times, *, divided hoặc /).

Giải pháp thay thế tháng 9 năm 2014:

S05 không đề cập rằng mặc dù các quy tắc và thẻ là phương pháp đặc biệt, cả hai có thể được khai báo là đa và một vài tham số giống như các phương pháp thông thường.

Cách tiếp cận này tận dụng lợi thế của cả đệ quy và đa công văn để thực hiện các mức ưu tiên của toán tử.

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

Vâng, đây là cách tiếp cận tiêu chuẩn mà tôi đã hy vọng tránh. Cuối cùng tôi muốn định nghĩa nhiều toán tử của riêng mình (postcircumfix, list, etc) và perl nghĩ sẽ xử lý điều này. Bạn có biết điều tương tự có đúng với [Parrot Grammar Engine] không (http://docs.parrot.org/parrot/latest/html/docs/book/pct/ch04_pge.pod.html)? – user2660278

+0

Từ những gì Perl6 kế thừa HLL :: Grammar từ nqp, có thể phù hợp với bạn. Bạn cũng có thể thử hỏi về bản cập nhật Perl 6 irc - http://perl6.org/community/irc – dwarring

+1

: hiện có một số tài liệu và ví dụ đã được thực hiện để triển khai HLL và các ngôn ngữ cụ thể của miền bằng cách sử dụng chuỗi công cụ NQP! Xem http://edumentab.github.io/rakudo-and-nqp-internals-course/slides-day1.pdf. Ví dụ làm việc bắt đầu xung quanh trang 118 – dwarring