2013-09-01 6 views
7

저는 Perl을 처음 접했고 새로운 Perl 6 문법 기능을 사용하여 우선 순위가있는 연산자로 도메인 특정 언어를 만들고 싶습니다. 예를 들어 "1 + 2 * 6"을 올바른 방식으로 구문 분석합니다.연산자 우선 순위 규칙이 적용된 Perl 6 문법의 예

지금까지 발견 한 문서 (예 : this)에는 우선 순위 선언이있는 연산자에 대한 문법 규칙의 예가 없습니다.

내가

이 나에게 난 그냥 추상 구문 트리를 구성 할

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

을 제공

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

이 매우 간단한 예제를 가지고있다.

답변

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