4 Stimmen

Manuelles Ausgeben eines Tokens mit ANTLR

Ich habe ein bisschen Mühe, manuell ein Token mit einer Lexer-Regel in ANTLR zu emittieren. Ich weiß, dass die emit()-Funktion verwendet werden muss, aber es scheint ein deutlicher Mangel an Dokumentation über diese zu sein. Hat jemand ein gutes Beispiel dafür, wie man das macht?

Das ANTLR-Buch gibt ein gutes Beispiel dafür, wie Sie dies tun müssen, um Pythons Verschachtelung zu analysieren. Wenn Sie zum Beispiel eine bestimmte Menge an Leerzeichen sehen, die größer ist als die Leerzeichen in der vorherigen Zeile, geben Sie ein INDENT-Token aus, aber wenn es weniger ist, geben Sie ein DEDENT-Token aus. Leider geht das Buch nicht auf die eigentliche Syntax ein, die erforderlich ist.

EDIT: Hier ist ein Beispiel für das, was ich zu analysieren versuche. Es sind die verschachtelten Blockquotes von Markdown:

before blockquote

> text1
>
> > text2
>
> text3

outside blockquote

Mein bisheriger Ansatz besteht im Wesentlichen darin, die > Symbole pro Zeile zu zählen. Zum Beispiel scheint die obige Zeile (ungefähr...) PARAGRAPH_START, CDATA, PARAGRAPH_END, BQUOTE_START, CDATA, BQUOTE_START, CDATA, BQUOTE_END, CDATA, BQUOTE_END, PARAGRAPH_START, CDATA, PARAGRAPH_END auszugeben. Die Schwierigkeit hier ist das abschließende BQUOTE_END, das meiner Meinung nach ein imaginäres Token sein sollte, das ausgegeben wird, sobald ein Nicht-Blockquote-Element gefunden wird (und die Verschachtelungsebene >= 1 ist)

2voto

chollida Punkte 7656

Nun, wenn das Token, das Sie ausgeben möchten, nicht durch eine Lexer-Regel definiert ist, müssen Sie einen Token-Abschnitt wie folgt hinzufügen:

tokens
{
    MYFAKETOKEN
}

In Ihrem Lexer brauchen Sie noch eine Regel, die dem Lexer sagt, wann er dieses Token erzeugen soll. Ein häufiges Beispiel ist die Bestimmung, ob etwas ein Integer, ein Bereich oder ein realer Wert ist.

NUMBERS_OR_RANGE
: INT 
        ( { LA(1) == '.' && LA(2) == '.' }? { _ttype = INT; }
    | { LA(1) == '.' || LA(1) == 'e' || LA(1) == 'E' }? { _ttype = REAL; }
    )
| PERIOD 
    ( PERIOD { _ttype = RANGE; }
    INT (( 'e' | 'E' ) ( '-' | '+' )? INT )? { _ttype = REAL; }
)
;

Hier sehen Sie, dass wir entweder eine INT abgleichen und dann nachschauen, ob wir einen doppelten Punkt finden, dann wissen wir, dass die INT wirklich eine int und nicht eine real ist. In diesem Fall setzen wir die Variable _ttype auf INT. Wenn wir einen PERIOD und dann ein 'e' finden, wissen wir, dass es ein Real ist.

Im zweiten Fall, in dem wir einen Punkt finden, wissen wir, dass wir einen Bereich haben, wenn das nächste Zeichen ein Punkt ist, ansonsten haben wir einen Real.

Wir könnten die MYFAKETOKEN Typ, den wir oben definiert haben, um _ttype zuzuweisen, wenn dies angemessen war.

0voto

Scott Punkte 9757

Okay, ich habe etwas recherchiert und das hier gefunden: http://www.cforcoding.com/2010/01/markdown-and-introduction-to-parsing.html

Ich glaube nicht, dass ANTLR wirklich für diese Art von Aufgabe geeignet ist und versuche

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X