2009-05-08 8 views
3

Verzeihen Sie mir, ich bin völlig neu zu Parsing und lex/yacc, und ich wahrscheinlich über meinen Kopf in Art und Weise bin, aber dennoch:Tokenizing links über Daten mit lex/yacc

ich eine ziemlich ich schreibe einfacher Rechner mit PLY, aber seine Eingabe ist möglicherweise nicht immer eine Gleichung, und ich muss feststellen, ob es beim Parsen ist oder nicht. Die Extreme der Eingabe würden etwas sein, das perfekt zu einer Gleichung auswertet, die es gut parst und berechnet, oder etwas, das nichts wie eine Gleichung ist, die nicht parsen kann und auch in Ordnung ist.

Der graue Bereich ist ein Eingang, der gleichungsähnliche Teile hat, von denen der Parser greifen und arbeiten wird. Das ist nicht was ich will - ich muss in der Lage sein zu sagen, ob Teile der Zeichenkette nicht aufgenommen und in Token umgewandelt wurden, so dass ich einen Fehler zurückwerfen kann, aber ich habe keine Ahnung, wie das geht.

Weiß jemand, wie ich im Grunde ein Token "alles, was noch übrig ist" definieren kann? Oder gibt es einen besseren Weg, damit umzugehen?

Antwort

1

In yacc ist ein Token error integriert. Normalerweise würden Sie so etwas wie:

line: goodline | badline ;

badline : error '\n' /* Error-handling action, if needed */

goodline : equation '\n' ;

Jede Zeile, die nicht equation von badline behandelt werden überein.

Möglicherweise möchten Sie in der Fehlerbehandlungsaktion yyerrok verwenden, um sicherzustellen, dass die Fehlerverarbeitung für die nächste Zeile zurückgesetzt wird.

+0

Das war der Trick. Ich fügte ein t_error token hinzu, das gerade falsch zurückgab, und alles geschieht tadellos. Vielen Dank! – bck

0

Normalerweise benutze ich einen separaten 'Befehlsleser', um einen vollständigen Befehl - wahrscheinlich eine Zeile in Ihrem Fall - in eine Hostvariablen-Zeichenfolge zu bekommen und arrangiere dann den lexikalischen Analysator, um den String zu analysieren und mir zu sagen, wann er es getan hat geh nicht ans Ende. Dies ist schwer einzurichten, erleichtert jedoch die Fehlerberichterstattung. Einer der Orte, an denen ich diese Technik routinemäßig verwendet habe, hat mehrzeilige Befehle mit 3 Kommentarkonventionen, zwei Sätze von Strings in Anführungszeichen und einige andere Schädlinge, um meine Zähne auf den Rand zu stellen (kontextsensitive Tokenisierung - yuck!).

Ansonsten ist Dons Rat mit dem Yacc "Fehler" Token gut.

1

Definieren Sie ein Token (Ende der Eingabe), und machen Sie Ihren Lexer es am Ende der Eingabe ausgeben.

also vor, wenn Sie diese Token hatte:

'1' 'PLUS' '1' 

Sie werden jetzt haben:

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

Jetzt können Sie Ihre Top-Level-Regel in Ihrem Parser definieren. Anstelle von (zum Beispiel):

Equation ::= EXPRESSION 

Sie

Equation ::= EXPRESSION END_OF_INPUT 

haben, würden Offensichtlich musst du diese in PLY Syntax neu zu schreiben, aber das sollte man die meisten die Quere kommen.

+0

Dies ist auch, wie der Standard Yacc funktioniert - er akzeptiert nur, wenn keine Token mehr übrig sind. – Ingo

0

Es sieht so aus, als ob Sie bereits eine Lösung gefunden haben, aber ich werde einen weiteren Vorschlag hinzufügen, falls Sie oder andere an einem alternativen Ansatz interessiert sind.

Sie sagen, dass Sie PLY verwenden, aber weil der Compiler in einer Python-Umgebung ausgeführt werden soll?Wenn ja, könnten Sie auch andere Tools in Betracht ziehen. Für solche Jobs verwende ich oft ANTLR (http://www.antlr.org), die einen Python-Code-Generator hat. ANTLR hat viele Tricks, um Dinge wie lexer zu essen, so dass der Parser es nie sieht (zB Kommentare), die Fähigkeit, eine Unterregel (zB eine Gleichung) innerhalb einer größeren Grammatik aufzurufen (die einmal enden sollte) Regel wurde angepasst, ohne weitere Eingaben zu verarbeiten ... klingt etwas wie das, was Sie tun möchten) und ein sehr schöner Links-Factoring-Algorithmus.

ANTLRs Parsing-Fähigkeit kombiniert mit der Verwendung der StringTemplate (http://www.stringtemplate.org) Engine macht eine nette Kombination und beide unterstützen Python (neben vielen anderen).