2015-03-09 31 views
6

Il linguaggio di comando della shell POSIX non è facile da analizzare, in gran parte a causa dello stretto accoppiamento tra lexing e parsing.Le grammatiche di espressione di parsing sono adatte all'analisi del linguaggio di comando della shell?

Tuttavia, le grammature di espressioni parsing (PEG) sono spesso senza scanner. Combinando il lexing e l'analisi, sembra che potrei evitare questi problemi. Il linguaggio che sto usando (Rust) ha una libreria PEG ben mantenuta. Tuttavia, sono a conoscenza di tre difficoltà che potrebbero rendere poco pratico l'utilizzo di questa libreria:

  • I serbatoi devono essere in grado di analizzare riga per riga, senza leggere i caratteri oltre la fine della riga.
  • alias sono puramente lessicale, e può causare un token per essere sostituito da qualsiasi sequenza di altri token in determinate situazioni
  • Shell riservata parole sono riconosciuti solo in determinate situazioni

è un PEG adatta per l'analisi del linguaggio di comando della shell dati questi requisiti, o è un parser ricorsivo-discendente scritto a mano più adatto?

+0

FWIW, bash utilizza un parser generato da bisonte abbastanza semplice, combinato con un lexer scritto a mano estremamente complicato. Non ho idea di quanto bene PEG avrebbe funzionato, ma se ci provi, faccelo sapere. – rici

+5

Tre motivi: è GPL mentre la mia shell è sotto MIT/Apache 2, è in C mentre la mia shell è in Rust, e non imparerei nulla da essa. – Demi

+0

Sì. I parser PEG eseguono la scansione. Il linguaggio grammaticale è più potente delle espressioni regolari e altrettanto compatto e conveniente. Ho tradotto diverse grammatiche ANTLR in Grako (PEG) e la parte lessicale è stata tradotta facilmente. Tuttavia, il PEG sarà meno efficiente di un lexer basato sullo stato macchina. – Apalala

risposta

3

Sì, è possibile utilizzare un PEG e nessuno dei problemi noti potrebbe essere un problema. In particolare:

1) analisi riga per riga: la maggior parte degli strumenti PEG non presenta salti di spazio bianco incorporati. Tutto lo spazio bianco incluso i newline deve essere gestito esplicitamente da te, il che significa che puoi gestire newline come preferisci.

2) Non utilizzare l'albero di analisi da PEG come AST. Invece dovresti scendere l'albero di analisi e costruire un AST. Per gli alias, quindi, dopo che l'analisi è stata completata e stai creando il tuo AST, puoi rilevare l'alias e inserire invece l'espansione appropriata per l'alias.

3) Le parole riservate non sono riservate a meno che non le prenotiate. Cioè, se hai un contesto in cui può verificarsi una parola riservata o un altro simbolo alfanumerico, devi prima controllare esplicitamente le parole riservate, quindi il simbolo alfanumerico arbitrario, perché una volta che il PEG decide che ha una corrispondenza, ciò non tornerà -traccia. Ovunque una parola riservata non è permessa, semplicemente non controllarla e la tua regola generica alfanumerica sostituirà la regola.

+0

Sono un po 'fuori dal mio campo, ma ho letto la parola "alias" come "macro senza parametri". Chi dice che una macro espansione deve formare una frase nella grammatica che fornisci? In caso contrario, non puoi semplicemente "sostituire un albero". (Francamente, questi sono facilmente gestibili semplicemente espandendoli quando il lexer li incontra). –

+0

@Ira: gli alias di shell tradizionali sono fondamentalmente sostituzioni testuali: qualsiasi testo successivo nell'invocazione viene analizzato come parte dell'espansione. Quindi, mentre quello che dici può essere vero per gli alias in altre lingue, o in shell più avanzate, una sostituzione testuale sarà quasi sempre corretta. Inoltre: l'AST non è un albero di analisi, come ho già detto.Fai qualunque sostituzione crei la semantica dell'alias giusto. – cliffordheath

+0

"Quasi sempre?" data la stringa "if (pqr abc" con pqr che è un alias di "a> b)", come si può analizzare la stringa e poi sostituire l'alias in un secondo momento? –