tl; dr Quale sarebbe un modo semplice per incorporare le funzioni in un'implementazione dell'algoritmo di Shunting-Yard?
Se fossero consentite solo espressioni come function(arg1, arg2, arg3)
(dove function
è una funzione incorporata), sarebbe davvero facile, dato che potrei semplicemente trattare function
come un operatore. Ma considera un caso in cui l'utente definisce la propria funzione come f = function
, quindi chiama f(arg1, arg2, arg3)
. In questo caso avrei bisogno di un AST strongmente tipizzato per rilevare al momento della compilazione quale tipo di f
è per vedere che i token procedenti ( (arg1, arg2, arg3)
) sono in realtà una chiamata di funzione, e non solo una costruzione di un tuple.
Peggio ancora, considera (f)()
dove f
è una funzione nulla definita dall'utente. Quindi quando arrivo a f
, anche se so che è una funzione, il token successivo sarà )
, che non è l'inizio di una chiamata di funzione valida. Che dire di (l[i])()
, dove l
è una lista di funzioni?
Al livello più generale, capisco grammaticalmente che quando abbiamo un'istruzione come [expression], "(", [expression], ")"
, allora sappiamo che stiamo chiamando una funzione. Tuttavia, non sono abbastanza sicuro di come controllare questo senza l'implementazione di un AST (che, per semplicità, preferirei non farlo).
Potrei memorizzare un elenco di tutti i token operatore e "parentesi", e poi quando raggiungo il "(" in una supposta chiamata di funzione, controllo solo se l'ultimo token non-bracket fosse un operatore. quindi "(" rappresenta una sottoespressione, come in 5 * (3 - 8)
. Se non era un operatore, quindi "(" rappresenta una chiamata di funzione, tuttavia questo metodo si sente facilmente infranto. Per esempio, cosa succede se là dove qualche operatore $
che era "unary left-associative", quindi (expression $)(args)
era valido? Quindi l'algoritmo non avrebbe funzionato, a meno che non avessi un controllo speciale per $
. Cosa accadrebbe se ci fosse un commento tra la funzione e la chiamata di funzione, come function \* comment *\ (args)
? O ancora peggio, qualcosa come
function \ lol the last token in this comment is an operator +
(args)
Ciò richiederebbe agli addetti all'implementazione molti casi speciali e mi chiedo se c'è un modo migliore per farlo.