2017-02-14 2 views
3

Java 구문 분석을 위해 Antlr 3.5 문법을 사용하는 동안 'IDENTIFIER'규칙은 ANTLR Lexer 문법에서 키워드를 거의 사용하지 않습니다. 또한 "이" 키워드를 소비, 바람직하지 않다 -'IDENTIFIER'규칙도 ANTLR Lexer 문법에서 키워드를 사용합니다.

public final int inch = this.getValue(); 

그런 규칙 '> 식별자가 VAR_VALUE'내가 선을 구문 분석 할 때 렉서 문법은

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();} 
    ; 

입니다 키워드는 별도의 목록으로도 수집되기 때문에

"IDENTIFIER"와 같은 다른 기능에 영향을 미치지 않고 Antlr 문법에 키워드 자체 규칙을 일치시키는 트릭/조항이 있습니까?

+0

옵션''{backtrack = true;}'**을 시도했지만 결과가 없습니다. – Kishore

+2

규칙 V_DECLARATION, V_DECLARATOR 및 V_VALUE는 렉서가 아닌 파서에 속합니다. –

+0

@Maurice Perry는 특정 토큰을 일치시키는 매우 기본적인 렉서 규칙이며 다양한 규칙으로 전체 Java 문법을 포함하는 파서를 트리거합니다. – Kishore

답변

3

귀하의 문제는 실제로 렉서에 속한 것을의 오해로 인해 발생하고 무엇을 파서에 속하는 :

  • 렉서의 작업이 문자의 스트림을 표현하는 단어를 결정하는 것입니다
    • 예를 들어, thisTHIS 즉, 0NUMBERthatIDENTIFIER
  • 파서의 작업이 "문장"으로 만든 여부 렉서에서 방출 단어의 순서, 즉, 주어진 언어에 적합 여부를 결정하는 것입니다입니다 그 말은 의미가 있습니다.
    • 예. 그 선언이 가능 수정, 유형 및 렉서의 작업이 입력에있는 단어를 확인하는 것입니다

때문에 식별자의 목록으로 구성, 입력을 처리하고 긴 유효을 찾습니다 match (ANTLR에서 두 개 이상의 규칙이 동일한 입력을 허용하면 소스 문법의 최상위 규칙이 우선합니다). 어떤 "가장 구체적인"것이 아니라 단순히 가장 긴 것입니다.

예 :

  • 입력 t
    • 이 될 수 THIS 또는 IDENTIFIER
  • 입력 h
    • 정지 될 수 있습니다 THIS 또는 IDENTIFIER
  • 입력 a
    • 는 더 이상 THIS 수 없다, 단지 IDENTIFIER이 가능합니다
  • 확인
  • 입력에 대한 입력 t
    • IDENTIFIER.
      • 는 더 이상 IDENTIFIER 일치하지 않기 때문에 thatIDENTIFIER로 일치하고 마지막 입력 . 다음 토큰

    의 새로운 시작과 또 다른 예로서 일치됩니다

    • 입력 t, h, i, s
      • THIS 또는 IDENTIFIER 중 전체 시간으로 일치 할 수
    • 입력 .
      • 더 이상 아무것도 일치 할 수 없습니다, 그래서 this이 일치하게 될 THIS (맨 위의 일치 규칙) 등보다는 IDENTIFIER.은 새로운 토큰을 시작합니다.

    그리고 이제는 중요한 부분 인 에 대해서도 렉서 규칙이 다른 렉서 규칙에서 참조되는 한, 이는 참조 렉서 규칙의 단편으로 간주됩니다. 즉, 일치하는 경우 새 토큰을 방출하지 않으며 조각 일치의 끝에서 여러 일치 토큰간에 어떤 결정도 트리거하지 않습니다. this가 실제로 IDENTIFIER 규칙에 일치시킬 수 있기 때문에, 전체 선언은 V_DECLARATION 렉서 규칙을 준수 - 그래서 입력 적어도 같은 길이와 일치 할 수있는 또 다른 렉서 규칙이 아니라면입니다 이전에 문법이 규칙보다 이 규칙이 적용됩니다.

    THIS을 참조하는 규칙을 제공하지 않았으므로 문법에서이 문이 얼마나 정확하게 작동하는지 알 수 없지만 렉서가 THIS 규칙을 사용하는 것보다 긴 입력 또는 이전 규칙과 일치 할 수 있습니다.

  • 관련 문제