2013-09-01 9 views
7

Sono molto nuovo in Perl e voglio creare un linguaggio specifico per il dominio con operatori che hanno la precedenza usando le nuove caratteristiche grammaticali di Perl 6. Ad esempio per analizzare "1 + 2 * 6" nel modo corretto.Esempio di grammatica Perl 6 con regole di precedenza per l'operatore

La documentazione che ho trovato fino ad ora (ad esempio this) non ha esempi con regole grammaticali per gli operatori con dichiarazioni di precedenza.

ho questo esempio molto semplice

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

Questo mi dà

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

Voglio solo di costruire un albero di sintassi astratta.

risposta

5

AFAIK non è possibile impostare gli operatori di infisso e definire la precedenza ecc. Nelle grammatiche. Questi sono solo attualmente applicabili all'estensione di Perl 6.

Qui un possibile approccio. Analizza i termini moltiplicativi prima delle aggiunte e consente anche parole o simboli, ad es. times o *.

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

noti che % è l'operatore separatore. <digit> +% [ <mult-op> ] indica un elenco di cifre separate da operatori moltiplicativi (times, *, divided o /).

soluzione alternativa settembre 2014:

S05 fa menzione che, sebbene le regole e gettoni sono metodi speciali, entrambi possono essere dichiarati come multi e prendere argomenti, proprio come i metodi normali.

Questo approccio sfrutta sia la ricorsione che il multi-dispatch per implementare i livelli di precedenza degli operatori.

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

Sì, questo è l'approccio standard che speravo di evitare. Alla fine volevo definire molti dei miei operatori (postcircumfix, list, ecc.) E pensavo che perl potesse gestirlo. Sai se lo stesso vale per [Parrot Grammar Engine] (http://docs.parrot.org/parrot/latest/html/docs/book/pct/ch04_pge.pod.html)? – user2660278

+0

Da ciò che Perl6 eredita HLL :: Grammar da nqp, che potrebbe essere adatto anche a te. Puoi anche provare a chiedere sull'aggiornamento Perl 6 irc - http://perl6.org/community/irc – dwarring

+1

: ora ci sono alcuni documenti e esempi pratici per implementare gli HLL e le lingue specifiche del dominio usando la catena di strumenti NQP! Vedi http://edumentab.github.io/rakudo-and-nqp-internals-course/slides-day1.pdf. Gli esempi di lavoro iniziano intorno a pp 118 – dwarring

Problemi correlati