2012-12-03 5 views
3

입력이 "term >1" 인 경우 숫자 (1)와 비교 연산자 (>)는 AST에서 별도의 노드를 생성해야합니다. 어떻게 이것을 달성 할 수 있습니까?공백이없는 토큰 Antlr3 일치

내 테스트에서 "term < 1"과 같은 공백으로 구분되는 "c"및 "1"인 경우에만 일치가 발생했습니다.

현재 문법 :

startExpression : orEx; 

expressionLevel4  
: LPARENTHESIS! orEx RPARENTHESIS! | atomicExpression; 
expressionLevel3  
: (fieldExpression) | expressionLevel4 ; 
expressionLevel2  
: (nearExpression) | expressionLevel3 ; 
expressionLevel1  
: (countExpression) | expressionLevel2 ; 
notEx : (NOT^)? expressionLevel1; 
andEx : (notEx  -> notEx) 
(AND? a=notEx -> ^(ANDNODE $andEx $a))*; 
orEx : andEx (OR^ andEx)*; 

countExpression : COUNT LPARENTHESIS WORD RPARENTHESIS RELATION NUMBERS -> ^(COUNT WORD RELATION NUMBERS); 

nearExpression : NEAR LPARENTHESIS (WORD|PHRASE) MULTIPLESEPERATOR (WORD|PHRASE) MULTIPLESEPERATOR NUMBERS RPARENTHESIS -> ^(NEAR WORD* PHRASE* ^(NEARDISTANCE NUMBERS)); 

fieldExpression : WORD PROPERTYSEPERATOR WORD -> ^(FIELDSEARCH ^(TARGETFIELD WORD) WORD); 

atomicExpression 
: WORD 
| PHRASE 
; 

fragment NUMBER : ('0'..'9'); 
fragment CHARACTER : ('a'..'z'|'A'..'Z'|'0'..'9'|'*'|'?'); 
fragment QUOTE  : ('"'); 
fragment LESSTHEN : '<'; 
fragment MORETHEN: '>'; 
fragment EQUAL: '='; 
fragment SPACE  : ('\u0009'|'\u0020'|'\u000C'|'\u00A0'); 
fragment UNICODENOSPACES: ('\u0021'..'\u0027'|'\u0030'..'\u0039'|'\u003B'..'\u007E'|'\u00A1'..'\uFFFF'); 
//fragment UNICODENOSPACES : ('\u0021'..'\u0039'|'\u003B'..'\u007E'|'\u00A1'..'\uFFFF'); 

LPARENTHESIS : '('; 
RPARENTHESIS : ')'; 

AND : ('A'|'a')('N'|'n')('D'|'d'); 
OR  : ('O'|'o')('R'|'r'); 
ANDNOT : ('A'|'a')('N'|'n')('D'|'d')('N'|'n')('O'|'o')('T'|'t'); 
NOT : ('N'|'n')('O'|'o')('T'|'t'); 
COUNT:('C'|'c')('O'|'o')('U'|'u')('N'|'n')('T'|'t'); 
NEAR:('N'|'n')('E'|'e')('A'|'a')('R'|'r'); 
PROPERTYSEPERATOR : ':'; 
MULTIPLESEPERATOR : ','; 

WS  : (SPACE) { $channel=HIDDEN; }; 
RELATION : LESSTHEN? MORETHEN? EQUAL?; 
NUMBERS : (NUMBER)+; 
PHRASE : (QUOTE)(CHARACTER)+((SPACE)+(CHARACTER)+)+(QUOTE); 
WORD : (UNICODENOSPACES)+; 

답변

4

당신의 WORD 규칙이 너무 많이 일치하기 때문에 즉 : 그것은 또한 ">1" 함께 기록 된 때,이 2 개 개의 문자가 하나의 WORD -token로 토큰 화되어 ">" 일치합니다. 내 렉서가 무엇을하고 있는지 확실 해요 때마다

, 나는 간단한 파서 일치 어떤 유형의 0 개 이상의 토큰을하자, 모든 토큰의 유형 및 텍스트 인쇄 : 당신이를 할 때

parse 
: (t=. {System.out.printf("\%-15s '\%s'\n", tokenNames[$t.type], $t.text);})* EOF 
; 

WORD   'term' 
RELATION  '>' 
WORD   '1'

및 입력의 "term" >1

WORD   'term' 
WORD   '>1'
: 귀하의 의견 "term > 1" 일치 위의 지배, 다음 인쇄됩니다

룰러가 2 (또는 그 이상) 문자 (WORD 규칙)와 일치 할 수있는 경우 이전에 정의 된 규칙 (단일 문자 (RELATION 규칙) 만 일치하는 경로를 선택합니다.

RELATION : LESSTHEN? MORETHEN? EQUAL?; 

잠재적으로 빈 문자열과 일치 :

또한 RELATION 규칙이 있습니다. 모든 렉서 규칙이 적어도 하나의 문자와 일치하는지 확인하십시오. 그렇지 않으면 렉서가 무한 루프에 빠질 수 있습니다.

더 나은은 같은 것을 할 :

RELATION 
: (LESSTHEN | MORETHEN)? EQUAL // '<=', '>=', or '=' 
| (LESSTHEN | MORETHEN)  // '<' or '>' 
; 
+0

감사합니다! 다시 한번 WORD를 조정해야합니다. AntlrWorks가 한 마디로 단계를 파싱 한 다음 RELATION (내 pov에있는)을 찾지 못하는 것은 실제로 내 마음 속에 그 과정을 묘사하는 것에 어긋나게됩니다. 이게 (WORD의 모든 문자를 제외하고) 실제로 어떻게 올바르게 수행 되었습니까? 그렇지 않으면 문자가 사용되기 때문에 단어는 제외 된 단어와 일치하지 않습니다. –

+1

@ThomAS, 나는 당신의 요구 사항을 정확하게 알고 있지는 않지만 가능한 한'WORD'는 문자로 시작해야합니다 ('>'또는''''등이 아닙니다.) 그러면이 문제가 해결 될 것입니다. (그리고 당신이 가지고있는 다른 이슈들도 있습니다.) –

+0

모든 정규 표현식 규칙을 적어도 1 문자 이상 일치시키고 두 단어의 시작 부분을 보호하는 것이 아주 좋은 두 가지 팁입니다! (다시) 나를 도와 줘서 고마워! –