2017-02-14 89 views
3

在針對Java解析的Antlr 3.5語法上工作時注意到'IDENTIFIER'規則在ANTLR Lexer語法中消耗少量關鍵字。詞法語法'IDENTIFIER'規則也消耗ANTLR Lexer語法中的關鍵字

lexer grammar JavaLexer; 

options { 
    //k=8; 
    language=Java; 
    filter=true; 
    //backtrack=true; 
} 

@lexer::header { 
package java; 
} 

@lexer::members { 
public ArrayList<String> keywordsList = new ArrayList<String>(); 
} 

V_DECLARATION 
: 
(((MODIFIERS)=>tok1=MODIFIERS WS+)? tok2=TYPE WS+ var=V_DECLARATOR WS*) 
{...}; 

fragment 
V_DECLARATOR 
    : 
    (
    tok=IDENTIFIER WS* (',' | ';' | ASSIGN WS* V_VALUE) 
) 
    {...}; 

fragment 
V_VALUE 
: (IDENTIFIER (DOT WS* IDENTIFIER WS* '(' | ',' | ';')) 
; 

MODIFIERS 
    : 
    (PUBLIC | PRIVATE | FINAL)+ 
; 

PRIVATE 
    : tok = 'private' 
    { keywordsList.add($tok.getText()); } 
    ; 

PUBLIC 
    : tok = 'public' 
    { keywordsList.add($tok.getText()); } 
    ; 

DOT 
    : '.' 
    { keywordsList.add("."); } 
    ; 

THIS 
    : tok = 'this' 
    { keywordsList.add($tok.getText()); } 
    ; 

ASSIGN 
    : '=' 
     { keywordsList.add("="); } 
    ;  

IDENTIFIER: 
    tok =Identifier 
    { 
    //System.out.println("Identifier: " + $tok.text); 
    } 
    ; 

fragment 
Identifier 
    : (Letter (Letter|JavaIDDigit)*); 

fragment 
Letter 
    : '\u0024' | 
     '\u0041'..'\u005a' | 
     '\u005f' | 
     '\u0061'..'\u007a' | 
     '\u00c0'..'\u00d6' | 
     '\u00d8'..'\u00f6' | 
     '\u00f8'..'\u00ff' | 
     '\u0100'..'\u1fff' | 
     '\u3040'..'\u318f' | 
     '\u3300'..'\u337f' | 
     '\u3400'..'\u3d2d' | 
     '\u4e00'..'\u9fff' | 
     '\uf900'..'\ufaff' 
    ; 

fragment 
JavaIDDigit 
    : '\u0030'..'\u0039' | 
     '\u0660'..'\u0669' | 
     '\u06f0'..'\u06f9' | 
     '\u0966'..'\u096f' | 
     '\u09e6'..'\u09ef' | 
     '\u0a66'..'\u0a6f' | 
     '\u0ae6'..'\u0aef' | 
     '\u0b66'..'\u0b6f' | 
     '\u0be7'..'\u0bef' | 
     '\u0c66'..'\u0c6f' | 
     '\u0ce6'..'\u0cef' | 
     '\u0d66'..'\u0d6f' | 
     '\u0e50'..'\u0e59' | 
     '\u0ed0'..'\u0ed9' | 
     '\u1040'..'\u1049' 
    ; 

WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN; skip();} 
    ; 

當我嘗試分析行:

public final int inch = this.getValue(); 

那麼規則「VAR_VALUE - >標識符」,也消耗了「這個」關鍵字,這是不可取的,因爲關鍵字也被收集到一個單獨的列表中。

Antlr語法中是否有任何技巧/規定將關鍵字本身與規則進行匹配而不影響「IDENTIFIER」等其他功能?

+0

也嘗試了**'{backtrack = true;} ** **選項,但沒有結果。 – Kishore

+2

它與我有關,規則V_DECLARATION,V_DECLARATOR和V_VALUE屬於解析器而不是詞法分析器。 –

+0

否@Maurice Perry,這些是非常基本的詞法分析器規則,用於匹配特定的標記,然後觸發包含各種規則中的完整Java語法的解析器。 – Kishore

回答

3

你的問題確實是在詞法分析器屬於什麼誤解造成的,在解析器屬於什麼:

  • 詞法分析的任務是確定哪些單詞字符流代表
    • 例如這thisTHIS0是一個NUMBERthatIDENTIFIER
  • 解析器的任務是確定從詞法分析器發出字序列是否符合給定的語言,也就是「一句話」是否由這些詞很有意義
    • eg該聲明由可能的修飾符,類型和標識符的列表

由於詞法分析的任務是確定哪些話是對輸入的,它處理輸入和查找最長有效期匹配(在ANTLR中,如果兩個或更多規則接受相同的輸入,源語法中最高的那個輸入獲勝)。不適用於任何「最具體」,但只是最長的一個。

實施例:

  • 輸入t
    • 可以是THISIDENTIFIER
  • 輸入h
    • 仍可THISIDENTIFIER
  • 輸入a
    • 可以不再THIS,只有IDENTIFIER可能
  • 輸入t
    • IDENTIFIER肯定
  • 輸入.
    • 不再匹配IDENTIFIER,所以that將被匹配爲IDENTIFIER和最後輸入.將匹配作爲下一個標記

一個新的開始和另一個例子:

  • 輸入t,h,i, s
    • 可以匹配的任何THISIDENTIFIER整個時間
  • 輸入.
    • 不能再被任何東西所匹配,所以this將被匹配爲THIS(最上面的匹配規則),而不是IDENTIFIER.將啓動新令牌

現在重要的部分 - 只要從另一個詞法分析規則引用詞法分析規則,它被認爲僅僅是引用詞法分析規則的一個片段。這意味着匹配它不會發出新的標記,並且它不會觸發片段匹配結束時多個匹配標記之間的任何決定。由於this確實可以通過IDENTIFIER規則匹配,整個聲明符合V_DECLARATION詞法規則 - 因此,除非有另一個詞法規則,可以匹配至少輸入長度相同早在語法比這個規則,這條規則將適用。

你沒有提供任何規則引用THIS,所以我們不知道究竟怎麼了這起出你的語法,但顯而易見的原因是,詞法分析器可以匹配更長的輸入或比使用THIS規則前面的任何規則。