2012-01-01 3 views
3

나는 templl 언어를 구문 분석하기위한 antlr 문법을 구성하려고합니다. 해당 언어는 모든 텍스트에 포함될 수 있으며 경계는 열기/닫기 태그 ({{/}})로 표시됩니다.antlr3 문법의 렉서 상태 전환

foo {{ someVariable }} bar 

하는 foobar이 무시해야하는 경우, 그리고 {{}} 태그 내부의 부분은 해석되어야한다 그래서 유효한 템플릿은 다음과 같습니다. 나는 {}이라는 태그를 제외하고 기본적으로 문제에 대한 해답을 가지고있는 this question을 찾았다. 2 개의 여는/닫는 문자와 일치하도록 문법을 수정하려고 시도했지만이 작업을 수행하자마자 BUFFER 규칙은 모든 문자와 여는 괄호 및 닫는 괄호를 사용합니다. LD 규칙이 호출되지 않습니다.

구분 기호에 2자를 사용할 때 antlr 렉서가 Buffer 규칙에서 모든 토큰을 사용하지만 한 문자 만있는 경우 구분 기호를 사용하지 않는 이유는 누구에게 있습니까? 당신은 괄호 (...)+ (데모의 BUFFER 규칙 참조) 내부 술어를 포함하여 앞서 {{이 나타날 때까지

grammar Test; 

    options { 
     output=AST; 
     ASTLabelType=CommonTree; 
    } 

    @lexer::members { 
     private boolean insideTag = false; 
    } 

    start 
     : (tag | BUFFER)* 
     ; 

    tag 
     : LD IDENT^ RD 
     ; 

    LD @after { 
     // flip lexer the state 
     insideTag=true; 
     System.err.println("FLIPPING TAG"); 
    } : '{{'; 

    RD @after { 
     // flip the state back 
     insideTag=false; 
    } : '}}'; 

    SPACE : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;}; 
    IDENT : (LETTER)*; 
    BUFFER : { !insideTag }?=> ~(LD | RD)+; 

    fragment LETTER : ('a'..'z' | 'A'..'Z'); 
+0

'IDENT : (LETTER) *;'(아마도)하면 렉서가 무한 루프에 빠질 수 있습니다. 렉서 규칙 _ 반드시 _ 적어도 하나의 문자와 일치해야합니다. –

답변

2

는 한 번 이상의 모든 문자를 일치시킬 수 있습니다.

데모 : 그것은 문법의 첫 번째 렉서 규칙과 BUFFER 규칙을 유지하기 위해 최선의 것을

grammar Test; 

options { 
    output=AST; 
    ASTLabelType=CommonTree; 
} 

@lexer::members { 
    private boolean insideTag = false; 
} 

start 
    : tag EOF 
    ; 

tag 
    : LD IDENT^ RD 
    ; 

LD 
@after {insideTag=true;} 
: '{{' 
; 

RD 
@after {insideTag=false;} 
: '}}' 
; 

BUFFER 
: ({!insideTag && !(input.LA(1)=='{' && input.LA(2)=='{')}?=> .)+ {$channel=HIDDEN;} 
; 

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

IDENT 
: ('a'..'z' | 'A'..'Z')+ 
; 

참고 : 그런 식으로, 그것은 시도되는 첫 번째 토큰 될 것입니다.

지금 "foo {{ someVariable }} bar"을 구문 분석하는 경우는, 다음과 같은 AST가 만들어집니다 :

enter image description here

+0

당신의 explantation에 대한 감사합니다. 그것은 지금 완벽하게 작동합니다. – pulse00

+0

@ RobertGruendler를 환영합니다. –

0

이 같은 문법이 당신의 요구에 맞게하지 않을까요? 나는 왜 BUFFER가 그렇게 복잡 할 필요가 있는지 알지 못한다.

grammar test; 

options { 
    output=AST; 
    ASTLabelType=CommonTree; 
} 

@lexer::members { 
    private boolean inTag=false; 
} 

start 
    : tag* EOF 
    ; 

tag 
    : LD IDENT RD -> IDENT 
    ; 

LD 
@after { inTag=true; } 
: '{{' 
; 

RD 
@after { inTag=false; } 
: '}}' 
; 

IDENT : {inTag}?=> ('a'..'z'|'A'..'Z'|'_') 'a'..'z'|'A'..'Z'|'0'..'9'|'_')* 
    ; 

BUFFER 
: . {$channel=HIDDEN;} 
;