2014-05-22 5 views
0

ANTLR에 새로운 오류입니다. ANTLRv4와 함께 DXF files의 파서를 작성하려고합니다. DXF 파일은 소위 그룹 코드를 사용하여 다음 데이터의 유형을 지정합니다. 일부 DXF 파일로부터ANTLR DXF 그룹 코드와 정수를 구별하십시오.

예 발췌 예 :

0 
SECTION 
    2 
HEADER 
    9 
$ORTHOMODE 
70 
    0 
    9 
    0 
ENDSEC 

0 다음 행의 문자열은 다음을 의미한다. 그룹 코드 70은 예를 들어 0 인 16Bit 정수가 이어짐을 의미합니다. 내 문제는 다음과 같습니다. 그룹 코드 0과 정수 0을 어떻게 구별 할 수 있습니까? 예제 스 니펫에서는 정수 값에 약간의 들여 쓰기가있는 것 같지만 DXF 참조에서이 값에 대해 아무 것도 찾을 수 없습니다.

지금까지 ANTLR 문법 다음 한 내 생각 :

grammar SimpleDXF; 

start  : HEADER variable* ENDSEC ; 
variable : varstart (groupcode NL value NL)+ ; 
varstart : VAR ; 
groupcode : INT ; 
value  : INT | ANYCHARSEQ ; 

WS   : [ \t]+ -> skip ; 
NL   : '\r'? '\n' ; 
HEADER  : '0' NL 'SECTION' NL '2' NL 'HEADER' NL ; 
ENDSEC  : '0' NL 'ENDSEC' NL ; 
VAR   : '9' NL VARNAME NL ; 
VARNAME  : '$' LETTER (LETTER | DIGIT)* NL ; 
INT   : DIGIT+ NL ; 
ANYCHARSEQ : ANYCHAR+ NL ; 

fragment ANYCHAR : [\u0021-\u00FF] ; 
fragment LETTER  : [A-Za-z_] ; 
fragment DIGIT  : [0-9] ; 

그러나이 렉서하여 그룹 코드 0로 간주되기 때문에, 정수 0을 구문 분석 header 규칙의 원인을 시도 할 때 분명히 이것은 실패 .

그래서 지금 내 문제를 해결하는 방법을 알 수 없습니다. 어떤 도움을 주셔서 감사합니다.

편집

변경된 ANTLR 문법은 더 렉서 규칙을 포함합니다. 이제 문제는 렉서가 완전히 실패한다는 것입니다. 첫 번째 입력 문자는 HEADER 토큰의 일부가 아닌 INT 토큰입니다. 그 이유는 -> skip으로 공백을 제거하는 것이 단일 토큰 안에있는 경우 작동하지 않습니다 (다음 예 참조).

start : 'A' 'B' ; 
WS  : [ \t\r\n]+ -> skip ; 

을하지만이 문법이 작동하지 않습니다 : 입력 A B (두 문자 사이의 공간)에 대한

은이 문법이 작동

start : AB ; 
AB  : 'A' 'B' ; 
WS  : [ \t\r\n]+ -> skip ; 

답변

1

나는 모든 그룹 코드와 해당 값이 같은 줄에있는 사전 처리를 수행하여 문제를 해결했습니다. 전처리는 또한 @UweAllner가 제안한 바와 같이 앞뒤 공백을 제거합니다. 전처리 후 질문에서 예제 입력 파일은 다음과 같습니다 : 이것처럼

0 SECTION 
2 HEADER 
9 $ORTHOMODE 
70 0 
0 ENDSEC 

의 그룹 코드와 간단한 정수, 정수가에있는 동안 원인 그룹 코드는, 행의 시작에 항상 구별하기 쉽게 가능 줄의 끝. 다음 예제 문법 문제를 해결한다 :

grammar SimpleDXF; 

start   : HEADER variable* ENDSEC ; 
variable  : varstart groupcodevalue+ ; 
varstart  : VAR ; 
groupcodevalue : GROUPCODE value ; 
value   : (INT | ANYCHARSEQ) NL ; 

NL    : '\r'? '\n' ; 
HEADER   : '0 SECTION' NL '2 HEADER' NL ; 
ENDSEC   : '0 ENDSEC' NL ; 
VAR    : '9 ' VARNAME NL ; 
GROUPCODE  : INT ' ' ; 
VARNAME   : '$' LETTER (LETTER | DIGIT)* ; 
INT    : '-'? DIGIT+ ; 
ANYCHARSEQ  : ANYCHAR+ ; 

fragment ANYCHAR: [\u0021-\u00FF] ; 
fragment LETTER : [A-Za-z_] ; 
fragment DIGIT : [0-9] ; 
0

당신은 (당신이 말한대로) 구분과 같은 groupcodes와 값 사이에 가능하지 그렇지 않으면

group: groupcode NL value; 

같은 규칙이 없습니다. 하나 groupcode 여러 값으로 올 수 있습니다 경우 는 또는 :

group: groupcode (NL value)+; 

그리고 당신이 렉서는 "단지 숫자"와 "구별 할 수 있도록 HEADER 및 ENDSEC 같은 헤더와 endsec을 정의해야합니다은의 시작 순서". 변수 규칙의 시작 부분 (고정 된 문장으로 구성된 모든 항목)에 대해서도 마찬가지 일 수 있습니다.

편집 : 매우 우아없는 동안

HEADER  : '0' WS* NL WS* 'SECTION' WS* NL WS* '2' WS* NL WS* 'HEADER' WS* NL ; 

, 내 마음에 자발적으로 제공

같은 뭔가. 그러나 이상한 파일 형식은 이국적인 조치가 필요합니다.

이것을 조금 더 정리하려면, 앞과 뒤 공백이 렉 스팅되고 파싱되기 전에 줄 바꿈을 할 수 있습니까?

+0

나는 암시 적으로 하위 규칙으로'variable' 규칙이있다 :'(groupcode NL 값 NL) +'나는 또한 당신의 제안에이 하위 규칙을 교환했지만, 예상대로 나는 여전히 같은 결과를 얻는다. – schauk11erd

+0

당신이 준 예제는 실제로이 규칙으로 분석 할 수 없다. groupcode 70 및 0으로 소비 된 값은 0과 NL ENDSEC으로 구성된 예상 엔드 포인트 사이에 0을 유지합니다. 그룹 코드 당 하나 이상의 값이 있습니까? –

+0

그룹 코드 당 하나의 값만 가능하지만 헤더 섹션의 변수에는 여러 매개 변수 (그룹 코드 + 값)가있을 수 있습니다. IMO 문제는 'header'규칙 때문에 '0'값이 잘못된 토큰 클래스에 있다는 것인데, ''0 '...'은 렉서에게 0을위한 토큰을 생성하게한다. – schauk11erd