帮助解析日志文件(ANTLR3)

Unk*_*own 5 parsing antlr text-parsing antlr3

我需要一点指导来编写语法来解析游戏永恒之塔的日志文件.我决定使用Antlr3(因为它似乎是一个可以完成工作的工具,我认为学会使用它对我有好处).但是,由于日志文件的结构不完整,我遇到了问题.

我需要解析的日志文件如下所示:

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.
Run Code Online (Sandbox Code Playgroud)

如您所见,大多数行以时间戳开头,但也有例外.我想在Antlr3中做的是编写一个解析器,它只使用以时间戳开头的行,同时静默地丢弃其他行.

这就是我到目前为止所写的内容(我是这些东西的初学者所以请不要笑: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'; 
Run Code Online (Sandbox Code Playgroud)

所以我需要的是一个如何解析它而不会为没有时间戳的行生成错误的示例.

谢谢!

Bar*_*ers 5

没有人会笑.事实上,你第一次尝试做得很好.当然,还有改进的余地!:)

首先是一些评论:你只能否定单个字符.由于您的NL规则可能包含两个字符,因此您无法否定它.此外,当你在解析器规则中否定时,你不会否定单个字符,但是你否定了词法规则.这可能听起来有点令人困惑,所以让我用一个例子来澄清.采用组合(解析器和词法分析器)语法T:

grammar T;

// parser rule
foo
  :  ~A
  ;

// lexer rules
A
  :  'a'
  ;

B
  :  'b'
  ;

C
  :  'c'
  ;
Run Code Online (Sandbox Code Playgroud)

如您所见,我正在否定解析器A规则中的词法foo规则.该foo规则现在匹配任何字符,除了'a',但它匹配任何词法分析规则,除了A.换句话说,它只匹配一个'b'或一个'c'字符.

此外,您不需要:

options {
  language = Java;
}
Run Code Online (Sandbox Code Playgroud)

在你的语法中:默认目标是Java(当然,将它留在那里并没有什么坏处).

现在,在你的语法中,你已经可以区分你的词法分析器中的data- 和 - text行.这是一种可行的方法:

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'
  ;
Run Code Online (Sandbox Code Playgroud)

请注意,fragment词法分析器规则中的部分意味着没有从这些规则创建令牌:它们仅用于其他词法分析器规则.因此词法分析器只会创建两种不同类型的标记:DataLine's TextLine' 和's'.