2010-05-12 11 views
5

Ich brauche ein wenig Anleitung beim Schreiben einer Grammatik, um die Protokolldatei des Spiels Aion zu analysieren. Ich habe mich für die Verwendung von Antlr3 entschieden (weil es ein Werkzeug zu sein scheint, das den Job erledigen kann und ich fand es gut, dass ich es benutze). Ich habe jedoch Probleme festgestellt, weil die Protokolldatei nicht genau strukturiert ist.Hilfe beim Analysieren einer Protokolldatei (ANTLR3)

Die Log-Datei Ich brauche aussieht wie das unten zu analysieren:

2010.04.27 22:32:22 : You changed the connection status to Online. 
2010.04.27 22:32:22 : You changed the group to the Solo state. 
2010.04.27 22:32:22 : You changed the group to the Solo state. 
2010.04.27 22:32:28 : Legion Message: www.xxxxxxxx.com (forum) 



ventrillo: 19x.xxx.xxx.xxx 

Port: 3712 

Pass: xxxx (blabla) 

4/27/2010 7:47 PM 
2010.04.27 22:32:28 : You have item(s) left to settle in the sales agency window. 

Wie Sie sehen können, die meisten Linien mit einem Zeitstempel zu starten, aber es gibt Ausnahmen. In Antlr3 möchte ich einen Parser schreiben, der nur die Zeilen verwendet, die mit dem Zeitstempel beginnen, während die anderen stillschweigend verworfen werden.

Das ist, was ich bisher geschrieben habe (ich bin ein Anfänger mit diesen Dingen so bitte nicht lachen: D)

grammar Antlr; 

options { 
    language = Java; 
} 

logfile: line* EOF; 

line : dataline | textline; 

dataline: timestamp WS ':' WS text NL ; 
textline: ~DIG text NL; 

timestamp: four_dig '.' two_dig '.' two_dig WS two_dig ':' two_dig ':' two_dig ; 

four_dig: DIG DIG DIG DIG; 
two_dig: DIG DIG; 

text: ~NL+; 

/* Whitespace */ 
WS: (' ' | '\t')+; 

/* New line goes to \r\n or EOF */ 
NL: '\r'? '\n' ; 

/* Digits */ 
DIG : '0'..'9'; 

Also, was ich brauche, ist ein Beispiel dafür, wie dies zu analysieren ohne Fehler für Zeilen ohne den Zeitstempel zu erzeugen.

Danke!

Antwort

5

Niemand wird lachen. In der Tat, du hast einen ziemlich guten Job für einen ersten Versuch gemacht. Natürlich gibt es Raum für Verbesserungen! :)

Zuerst einige Anmerkungen: Sie können nur einzelne Zeichen negieren. Da Ihre NL Regel möglicherweise aus zwei Zeichen bestehen kann, können Sie sie nicht negieren. Wenn Sie in Ihren Parser-Regeln negieren, negieren Sie nicht einzelne Zeichen, sondern negieren die Lexer-Regeln. Das mag ein wenig verwirrend klingen, also lassen Sie mich mit einem Beispiel klären. Nehmen Sie die Kombination (Parser & Lexer) Grammatik T:

grammar T; 

// parser rule 
foo 
    : ~A 
    ; 

// lexer rules 
A 
    : 'a' 
    ; 

B 
    : 'b' 
    ; 

C 
    : 'c' 
    ; 

Wie Sie sehen, ich bin negiert die A Lexer-Regel in der foo Parser-Regel. Die foo Regel macht jetzt nicht entspricht ein beliebiges Zeichen mit Ausnahme der 'a', aber es entspricht jeder Lexer-Regel außer A. Mit anderen Worten, es wird nur ein 'b' oder 'c' Zeichen übereinstimmen.

Auch Sie brauchen nicht zu setzen:

options { 
    language = Java; 
} 

in Ihrer Grammatik: das Standardziel Java ist (es tut nicht weh es natürlich in dort zu lassen).

Nun können Sie in Ihrer Grammatik bereits zwischen data - und text - Zeilen in Ihrer Lexer-Grammatik unterscheiden. Hier ist eine Art und Weise, dies zu tun:

logfile 
    : line+ 
    ; 

line 
    : dataline 
    | textline 
    ; 

dataline 
    : DataLine 
    ; 

textline 
    : TextLine 
    ; 

DataLine 
    : TwoDigits TwoDigits '.' TwoDigits '.' TwoDigits Space+ TwoDigits ':' TwoDigits ':' TwoDigits Space+ ':' TextLine 
    ; 

TextLine 
    : ~('\r' | '\n')* (NewLine | EOF) 
    ; 

fragment 
NewLine 
    : '\r'? '\n' 
    | '\r' 
    ; 

fragment 
TwoDigits 
    : '0'..'9' '0'..'9' 
    ; 

fragment 
Space 
    : ' ' 
    | '\t' 
    ; 

Beachten Sie, dass die fragment an den Lexer Regeln bedeuten, dass keine Token von diesen Regeln erstellt werden: sie sind nur in anderen Lexer-Regeln verwendet. Der Lexer erstellt also nur zwei verschiedene Arten von Tokens: DataLine 's und TextLine' s.

+0

Das scheint ziemlich gut zu funktionieren und es ist einfach und klar. Ofcouse, ich werde etwas ändern, um zu tun, was immer ich brauche. Danke! – Unknown

+0

@ user188106, gern geschehen. –

2

Versuchen, Ihre Grammatik so nah wie möglich zu halten, hier ist, wie ich es auf der Grundlage der Beispieleingabe arbeiten konnte. Da Leerzeichen vom Lexer an den Parser übergeben werden, habe ich alle Ihre Token vom Parser in tatsächliche Lexer-Regeln verschoben.Die Hauptänderung besteht eigentlich nur darin, eine weitere Zeilenoption hinzuzufügen und dann zu versuchen, sie mit Ihren Testdaten und nicht mit den anderen guten Daten abzugleichen. Ich nahm auch an, dass eine Leerzeile verworfen werden sollte, wie Sie an der Regel erkennen können. Also hier ist, was ich in der Lage war zu arbeiten:

Hoffentlich hilft das Ihnen, viel Glück.

+0

Danke auch für Ihre Mühe! – Unknown