2012-07-09 5 views
1

나는 Antlr 문법에 관한 질문의 양으로 다소 편안함을 느낀 반면 (단지이 야크 모양의 물건을 면도하려고하는 것이 아닙니다), 도움이되는 질문/답변을 찾지 못했습니다. 내 문제.간단한 Antlr3 토큰 파싱

Antlr3.3을 혼합 토큰/파서 렉서와 함께 사용하고 있습니다.

gUnit을 사용하여 문법 및 일부 jUnit 테스트를 증명합니다. 이것은 재미가 시작되는 곳입니다. 나는 문제가 "식별자"를 파싱 (이 예제는 foobar) 데

identifier foobar { 
port=8080 
stub plusone.google.com { 
     status-code = 206 
     header = [] 
     body = [] 
    } 
} 

: 나는 간단한 설정 파일이

내가 구문 분석 할 내가 허용 할 유효한 이름은 다음과 같습니다

foobar 
foo-bar 
foo_bar 
foobar2 
foo-bar2 
foo_bar2 
3foobar 
_foo-bar3 

등, 따라서 유효한 이름이 문자를 'a..z'|'A..Z', '0..9' '_' and '-'

난에 도착했습니다 문법을 사용할 수 있습니다이 (이 전체 g 밤은주의입니다 이 질문에 관련 rammar 단지 부)

fragment HYPHEN : '-' ; 

fragment UNDERSCORE : '_' ; 

fragment DIGIT : '0'..'9' ; 

fragment LETTER : 'a'..'z' |'A'..'Z' ; 

fragment NUMBER : DIGIT+ ; 

fragment WORD : LETTER+ ; 

IDENTIFIER : DIGIT | LETTER (LETTER | DIGIT | HYPHEN | UNDERSCORE)*; 

및 gUnit 테스트를 실행하는 해당 시험 gUnit

IDENTIFIER: 
"foobar" OK 
"foo_bar" OK 
"foo-bar" OK 
"foobar1" OK 
"foobar12" OK 
"foo-bar2" OK 
"foo_bar2" OK 
"foo-bar-2" OK 
"foo-bar_2" OK 
"5foobar" OK 
"f_2-a" OK 
"aA0_" OK 
// no "funny chars" 
"foo[email protected]" FAIL 
// not with whitepsace 
"foo bar" FAIL 

은 "5foobar"실패. 나는 어려운 것들을 파싱 할 수 있었지만, 식별자를 파싱하는 겉으로는 간단한 작업이 나를 때렸다.

누군가 내가 잘못 가고있는 부분을 지적 할 수 있습니까? 탐욕스럽지 않고 나는 어떻게 맞습니까?

미리 감사드립니다.

- UPDATE - 나는 바트의 대답에 따라,이에 대한 문법 변화

:

IDENTIFIER : ('0'..'9'| 'a'..'z'|'A'..'Z' | '_'|'-') ('_'|'-'|'a'..'z'|'A'..'Z'|'0'..'9')* ;

을하고 이것이 실패 gUnit 테스트를 고정하지만, unreleated JUnit 테스트를 파산, 그 "port"매개 변수를 테스트합니다. 위의 설정 스 니펫 (snippet)의 다음은과 문법 거래를 다음 "포트 = 8080"요소 :

configurationStatement[MiddlemanConfiguration config] 
     : PORT EQ port=NUMBER { 
config.setConfigurationPort(Integer.parseInt(port.getText())); } 
      | def=proxyDefinition { config.add(def); } 
; 

내가 얻는 메시지는 다음과 같습니다 번호가 NUMBER : ('0'..'9')+ ;

으로 정의된다

mismatched input '8080' expecting NUMBER

IDENTIFIER 블록 위에 NUMBER에 대한 규칙을 이동하면이 문제가 해결되었습니다.

IDENTIFIER 
: DIGIT 
| LETTER (LETTER | DIGIT | HYPHEN | UNDERSCORE)* 
; 

그래서 IDENTIFIER 단일 DIGIT eiter거나 (LETTER | DIGIT | HYPHEN | UNDERSCORE)* 뒤에 LETTER로 시작

답변

1
IDENTIFIER : DIGIT | LETTER (LETTER | DIGIT | HYPHEN | UNDERSCORE)*; 

는 동일하다.

당신은 아마 의미 :

IDENTIFIER 
: (DIGIT | LETTER | UNDERSCORE) (LETTER | DIGIT | HYPHEN | UNDERSCORE)* 
; 

을하지만, 또한 유효한 IDENTIFIER 인 것으로 3---3을 허용하는 올바른 것입니다?

+1

그는'_foo-bar3'이 유효한 식별자이므로 밑줄을 허용 가능한 첫 번째 문자로 추가해야한다고 지시했습니다. 또한 ANTLR 4는 규칙을 조각으로 분리하는 성능상의 문제가 없지만 ANTLR 3은 단순히 "HYPHEN", "0"... "9"대신에 "-"를 사용하면 훨씬 효율적으로 작동합니다 'DIGIT' 등 –

+0

@ 280Z28, 네, 맞아요. OP가 언급 한 gUnit 테스트 사례를 살펴 보았습니다. 'IDENTIFIER' 규칙의 시작 부분에'UNDERSCORE'를 추가했습니다. –

+0

안녕하세요 @Bart @ 280Z28, 문법을 다음과 같이 변경했습니다 : 'IDENTIFIER : ('0 '..'9 '|'a '..'z '|'A '..'Z '|'_ ' '' '' '' '' '' '' '' '' '' '' '0'.. '9') *; ' ' '(' '' '' , 그러나 그것의 "포트 = 8080"깨진, 그 테스트는 지금 실패합니다. 나는 그 질문을 편집 할 것이다. – user1512122