Domanda

Perdonami, sono completamente nuovo nell'analisi e lex / yacc, e probabilmente sono in qualche modo sopra la mia testa, ma comunque:

Sto scrivendo una calcolatrice piuttosto semplice con PLY, ma il suo input potrebbe non essere sempre un'equazione e devo determinare se lo è o meno durante l'analisi. Gli estremi dell'input sarebbero qualcosa che valuta perfettamente un'equazione, che analizza bene e calcola, o qualcosa che non assomiglia a un'equazione, che non analizza e va anche bene.

L'area grigia è un input che ha parti simili a equazioni, di cui il parser afferrerà e risolverà. Questo non è quello che voglio - devo essere in grado di dire se parti della stringa non sono state raccolte e tokenizzate in modo da poter restituire un errore, ma non ho idea di come farlo.

Qualcuno sa come posso definire, in sostanza, un token 'cattura tutto ciò che è rimasto'? O c'è un modo migliore per gestirlo?

È stato utile?

Soluzione

Esiste un token errore incorporato in yacc. Normalmente faresti qualcosa del tipo:

line: goodline | badline;

badline: errore '\ n' / * Azione di gestione degli errori, se necessario * /

goodline: equazione '\ n';

Qualsiasi riga che non corrisponde all'equazione verrà gestita da badline .

Potresti voler utilizzare yyerrok nell'azione di gestione degli errori per assicurarti che l'elaborazione degli errori sia ripristinata per la riga successiva.

Altri suggerimenti

Definisci un token (fine dell'input) e fai in modo che il tuo lexer lo emetta alla fine dell'input.

Quindi, prima, se avevi questi token:

'1' 'PLUS' '1'

Ora avrai:

'1' 'PLUS' '1' 'END_OF_INPUT'

Ora puoi definire la tua regola di livello superiore nel tuo parser. Invece di (ad esempio):

Equation ::= EXPRESSION

Avrai

Equation ::= EXPRESSION END_OF_INPUT

Ovviamente dovrai riscriverli nella sintassi PLY, ma questo dovrebbe farti arrivare per lo più.

In genere utilizzo un "lettore di comandi" separato per ottenere un comando completo - probabilmente una riga nel tuo caso - in una stringa di variabile host, quindi organizzare che l'analizzatore lessicale analizzi la stringa, includendomi anche quando non lo ha fatto ' raggiungere la fine. È difficile da configurare, ma semplifica alcune classi di segnalazione degli errori. Uno dei posti in cui ho usato questa tecnica di routine ha comandi multilinea con 3 convenzioni di commento, due serie di stringhe tra virgolette e alcuni altri nasties per mettere i denti al limite (tokenizzazione sensibile al contesto - schifo!).

Altrimenti, il consiglio di Don con il token "errore" di Yacc è buono.

Sembra che tu abbia già trovato una soluzione, ma aggiungerò un altro suggerimento nel caso tu o altri foste interessati ad un approccio alternativo.

Dici che stai usando PLY ma è perché vuoi che il compilatore venga eseguito in un ambiente Python? In tal caso, potresti prendere in considerazione anche altri strumenti. Per tali lavori utilizzo spesso ANTLR ( http://www.antlr.org ) che ha un generatore di codice Python . ANTLR ha molti trucchi per fare cose come mangiare un mucchio di input a livello di lexer in modo che il parser non lo veda mai (ad es. Commenti), capacità di chiamare una sotto-regola (ad es. Equazione) all'interno di una grammatica più ampia (che dovrebbe terminare una volta che la regola è stata abbinata senza elaborare ulteriori input ... sembra un po 'come quello che vuoi fare) e un algoritmo di factoring di sinistra molto carino.

Capacità di analisi degli ANTLR combinata con l'uso di StringTemplate ( http://www.stringtemplate.org ) engine crea una bella combinazione ed entrambi supportano Python (tra molti altri).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top