2011-08-30 16 views
5

Mi sono appena imbattuto nello this post, è piuttosto elegante.Come convertire infix in postfix in erlang?

Ma non sta prendendo in considerazione la priorità dei diversi operatori.

ad es. * ha priorità più alta di +.

Così 1+2*(3+2) devono essere convertiti in 1 2 3 2 + * +

Come fare in Erlang prendendo la questione prioritaria in considerazione?

risposta

2

Ecco un modo per farlo che abusa del parser integrato per i termini di Erlang. Potresti scrivere il tuo parser tramite yecc o discesa ricorsiva, ma per la semplicità rimarrò con il parser di Erlang.

-module(foo). 
    -compile(export_all). 

Dichiarare un modulo, esportare tutto da esso. Questa è una brutta forma se vuoi usarla. Piuttosto, ridurre l'esportazione a p/1.

parse(Str) ->  
    {ok, Tokens, _} = erl_scan:string(Str ++ "."), 
    {ok, [E]} = erl_parse:parse_exprs(Tokens), 
    E. 

Questa funzione abusi del parser Erlang in modo che possiamo ottenere un albero sintattico di gettoni Erlang.

rpn({op, _, What, LS, RS}) -> 
    rpn(LS), 
    rpn(RS), 
    io:format(" ~s ", [atom_to_list(What)]); 
rpn({integer, _, N}) -> 
    io:format(" ~B ", [N]). 

L'uscita RPN deve eseguire una traversata dell'albero-marcia post-ordine. Quindi, fondamentalmente camminiamo sulla mano sinistra e sul lato destro dell'albero e quindi emettiamo noi stessi come un nodo. L'ordine di "parentesi" è memorizzato in modo astratto nell'albero stesso. La priorità è gestita dal parser di Erlang. Si potrebbe facilmente farlo tramite un parser di discesa ricorsiva, se lo si desidera. Ma questa è una domanda diversa al punto "Come scrivere i parser in Erlang?" La risposta è duplice: o usi leex + yecc o usi un parser basato su combinatori di parser e/o discesa ricorsiva. Soprattutto per una grammatica così semplice.

p(Str) -> 
     Tree = parse(Str), 
     rpn(Tree), 
     io:format("~n"). 

Questa è solo la formattazione.

+0

Non vedo la logica di trattare con priorità lì .. –

+1

Come ho accennato, la priorità è gestita da un parser. È davvero separato dalla domanda "Come faccio a formattare un albero di analisi in notazione RPN", che è ciò che fa sopra. Puoi cercare la discesa ricorsiva che è un modo per farlo per una grammatica LL (1) che sono le tue espressioni. –

+0

Ho bisogno di avere molti operatori aggiuntivi che non esistono in erlang, quindi ho bisogno di specificare la priorità manualmente, non le impostazioni predefinite di erlang. –

0

È possibile ottenere ispirato dal mio Erlang Programming Exercise 3-8 solution. C'è tutto il lexer manoscritto, parser e "compilatore" per il codice postfix.

Modifica: Spiacenti, Vedo che l'Esercizio 3-8 ha un bracketing esplicito in modo che non risolva la priorità dell'operatore. Dovresti modificare il parser per gestirlo.