Ci sono due casi diversi da considerare, a seconda della sintassi della tua lingua. Se la tua lingua usa la parentesi per indicare l'applicazione della funzione (ad esempio f(2+1)
), la precedenza è irrilevante. La funzione dovrebbe essere inserita nello stack e rilasciata dopo (per l'esempio sopra, il risultato è 2 1 + f
). In alternativa puoi considerare la funzione come un valore e inviarla immediatamente, ed eseguire un'operazione di chiamata di funzione dopo la parentesi chiusa (che dovrebbe altrimenti essere trattata come qualsiasi altra parentesi), ad esempio f 2 1 + $
, dove $
è la funzione operazione di chiamata.
Se la tua lingua, tuttavia, non usa la parentesi per indicare la funzione di invocazione, ma pone l'argomento direttamente dopo la funzione senza alcuna punteggiatura speciale (es. f 2 + 1
), come evidentemente è il caso dell'esempio di Wikipedia, quindi le cose sono un po 'più complicato. Nota che l'espressione che ho appena dato ad un esempio è ambigua: è f applicato a 2 e 1 aggiunto al risultato, oppure aggiungiamo 2 e 1 insieme e poi chiamiamo f con il risultato?
Ancora una volta, ci sono due approcci. Puoi semplicemente spingere la funzione sulla pila dell'operatore quando la incontri e assegnarla a qualunque precedenza tu voglia. Questo è l'approccio più semplice ed è apparentemente quello che l'esempio citato ha fatto. Ci sono comunque problemi pratici. In primo luogo, come si identifica una funzione? Se si dispone di un set finito è facile, ma se si dispone di funzioni definite dall'utente, ciò significa che il parser ha bisogno di essere reindirizzato nel proprio ambiente, che può diventare disordinato rapidamente. E come gestisci le funzioni con più argomenti?
La mia sensazione è che per questo stile di sintassi, usare le funzioni come valori più utili da un operatore di applicazioni di funzione ha molto più senso. Quindi, puoi semplicemente iniettare l'operatore dell'applicazione ogni volta che leggi un valore e anche l'ultima cosa che hai letto era un valore, quindi non hai bisogno di alcun modo speciale per dire quali identificatori sono funzioni. Puoi anche lavorare con espressioni che restituiscono funzioni (che è difficile o impossibile con lo stile di funzione-come-operazione). Questo significa che puoi usare currying per gestire più funzioni di argomenti, il che è una grande semplificazione nel tentativo di gestirli direttamente.
L'unica cosa che devi decidere è quale sia la precedenza dell'applicazione della funzione. La scelta spetta a te, ma in tutte le lingue che ho usato funziona così, è stato l'operatore più vincolante nella lingua e ha avuto ragione associativa. (L'unica variazione interessante è Haskell, che oltre ad avere la versione strongmente vincolante descritta, ha anche un sinonimo per esso con il simbolo $
, che è l'operatore più debole nella lingua, permettendo espressioni come f 2 + 1
da applicare f a 2 e f $ 2 + 1
per applicarlo all'intero resto dell'espressione)