2008-09-26 36 views
5

什麼是最簡單(最短,最少規則,沒有警告)的方式來解析同一語法中的有效日期和數字?我的問題是,匹配有效月份(1-12)的詞法分析規則將匹配任何1-12的匹配項。所以,如果我只是想匹配一個數字,我需要一個像解析規則:Antlr:最簡單的方法來識別日期和數字?

number: (MONTH|INT); 

它只有當我添加詞法規則一天和一年變得更加複雜。我想這樣的日期解析規則:

date: month '/' day ('/' year)? -> ^('DATE' year month day); 

我不在乎月,日&年是解析或詞法規則,只是只要我結束了同一個樹形結構。我還需要能夠在其他地方認識數字,例如:

foo: STRING OP number -> ^(OP STRING number); 
STRING: ('a'..'z')+; 
OP: ('<'|'>'); 

回答

5

的問題是,你似乎想在你的詞法分析器和/或解析器執行兩個句法和語義檢查。這是一個常見的錯誤,只有在非常簡單的語言中才有可能。

你真正需要做的是更廣泛地接受詞法分析器和解析器,然後執行語義檢查。取決於你是否需要在每個月的日子之前接受零:1)真正接受你的INT,2)將DATENUM定義爲只接受那些有效天數的令牌,但不接受有效的INT。我推薦第二種方法,因爲代碼稍後會需要較少的語義檢查(因爲INT會在語法級別進行驗證,並且您只需對日期執行語義檢查。第一種方法:

INT: '0'..'9'+; 

第二種方法:

DATENUM: '0' '1'..'9'; 
INT: '0' | SIGN? '1'..'9' '0'..'9'*; 

使用的詞法規則接受邀請後,您的日期字段將之一:

date: INT '/' INT ('/' INT)? 

或:

date: (INT | DATENUM) '/' (INT | DATENUM) ('/' (INT | DATENUM))? 

之後,你會執行語義運行你的AST,以確保你的日期是有效的。

如果你在你的語法進行語義檢查死心塌地,然而,ANTLR允許解析器語義斷言,所以你可以做一個檢查這樣的值的日期字段:

date: month=INT '/' day=INT (year='/' INT)? { year==null ? (/* First check /*) : (/* Second check */)} 

當你這樣做,但是,你是在語法中嵌入語言特定的代碼,並且它不能跨目標移植。

0

使用ANTLR4,這裏是我使用的一個簡單的組合語法。它使用詞法分析器僅匹配簡單的標記,而使解析器規則解釋日期與數字。

// parser rules 

date 
    : INT SEPARATOR month SEPARATOR INT 
    | INT SEPARATOR month SEPARATOR INT4 
    | INT SEPARATOR INT SEPARATOR INT4; 

month : JAN | FEB | MAR | APR | MAY | JUN | JUL | AUG | SEP | OCT | NOV | DEC ; 

number : FLOAT | INT | INT4 ; 

// lexer rules 

FLOAT : DIGIT+ '.' DIGIT+ ; 

INT4 : DIGIT DIGIT DIGIT DIGIT; 
INT : DIGIT+; 

JAN : [Jj][Aa][Nn] ; 
FEB : [Ff][Ee][Bb] ; 
MAR : [Mm][Aa][Rr] ; 
APR : [Aa][Pp][Rr] ; 
MAY : [Mm][Aa][Yy] ; 
JUN : [Jj][Uu][Nn] ; 
JUL : [Jj][Uu][Ll] ; 
AUG : [Aa][Uu][Gg] ; 
SEP : [Ss][Ee][Pp] ; 
OCT : [Oo][Cc][Tt] ; 
NOV : [Nn][Oo][Vv] ; 
DEC : [Dd][Ee][Cc] ; 

SEPARATOR : [/\\\-] ; 

fragment DIGIT : [0-9];