ANTLR4: parsing an email header, lookahead not working, Python target

51 views
Skip to first unread message

Roger Costello

unread,
Aug 31, 2015, 3:36:12 PM8/31/15
to antlr-discussion

I am trying to parse this portion of an email header:


Received: from server.mymailhost.com (mail.mymailhost.com [126.43.75.123]) by pilot01.cl.msu.edu (8.10.2/8.10.2) with ESMTP id NAA23597;Fri, 12 Jul 2002 16:11:20 -0400 (EDT)


I want the lexer to tokenize it into these pieces:


Received: 

from  server.mymailhost.com (mail.mymailhost.com [126.43.75.123]) 

by pilot01.cl.msu.edu (8.10.2/8.10.2) 

with ESMTP 

id NAA23597

;

Fri, 12 Jul 2002 16:11:20 -0400 (EDT)

<EOF>

Here's my parser grammar:


parser grammar MyParser;                

options { tokenVocab=MyLexer; }         

received : Received fromToken byToken withToken idToken SemiColon date EOF ;

fromToken : FromText ;

byToken: ByText ;

withToken : WithText ;

idToken : IdText ;

date : DateContents+ ;

Below is my lexer grammar. This is the error that I get when I run ANTLR:


token recognition error at: 'from server.mymailhost.com (mail.mymailhost.com [126.43.75.123]) by pilot01.cl.msu.edu (8.10.2/8.10.2) with ESMTP id NAA23597;Fri, 12 Jul 2002 16:11:20 -0400 (EDT)'

mismatched input '<EOF>' expecting FromText

Apparently the lexer is successfully getting the first token (Received: ) but then is not getting the next token (From: ). Note that in the lexer grammar I am using lookahead; am I using it correctly? Any thoughts on what the problem is?


lexer grammar MyLexer;                  

Received : 'Received: ' ;
SemiColon : ';' ;

FromText : 'from ' .+? 
      {  
        (self.input.LA(1) == 'b') and (self.input.LA(2) == 'y')
      }? ;

ByText : 'by '.+? 
      {
        (self.input.LA(1) == 'w') and (self.input.LA(2) == 'i') and (self.input.LA(3) == 't') and (self.input.LA(4) == 'h')
      }? ;

WithText : 'with ' .+? 
      {
        (self.input.LA(1) == 'i') and (self.input.LA(2) == 'd')
      }? ;

IdText : 'id ' .+? 
      {
        (self.input.LA(1) == ';')
      }? ;

DateContents : ('Mon' | 'Tue' | 'Wed' | 'Thu' | 'Fri' | 'Sat' | 'Sun') (Letter | Number | Special)+ ;

fragment Letter :  'A'..'Z' | 'a'..'z' ;

fragment Number : '0'..'9' ;

fragment Special : ' ' | '_' | '-' | '.' | ',' | '~' | ':' | '+' | '$' | '=' | '(' | ')' | '[' | ']' | '/' ;

Whitespace : [\t\r\n]+ -> skip ;

Roger Costello

unread,
Aug 31, 2015, 5:29:50 PM8/31/15
to antlr-discussion

After much effort I figured out the answer. Here is the working lexer:


lexer grammar MyLexer;                  

Received : 'Received: ' ;
SemiColon : ';' ;

FromText : 'from ' .+?
 
      {(self._input.LA(1) == ord('b')) and (self._input.LA(2) == ord('y'))}?
      ;

ByText : 'by '.+? 
      {(self._input.LA(1) == ord('w')) and (self._input.LA(2) == ord('i')) and (self._input.LA(3) == ord('t')) and (self._input.LA(4) == ord('h'))}? 
      ;

WithText : 'with ' .+? 
      {(self._input.LA(1) == ord('i')) and (self._input.LA(2) == ord('d'))}? 
      ;

IdText : 'id ' .+? 
      {(self._input.LA(1) == ord(';'))}? 
      
;

DateContents : ('Mon' | 'Tue' | 'Wed' | 'Thu' | 'Fri' | 'Sat' | 'Sun') (Letter | Number | Special)+ ;

fragment Letter :  'A'..'Z' | 'a'..'z' ;

fragment Number : '0'..'9' ;

fragment Special : ' ' | '_' | '-' | '.' | ',' | '~' | ':' | '+' | '$' | '=' | '(' | ')' | '[' | ']' | '/' ;

Whitespace : [\t\r\n]+ -> skip ;
Reply all
Reply to author
Forward
0 new messages