2014-04-14 1 views
0

에 모호한 문법에 과부하 기호로 취급. 하나의 확장자는 예를 들어 확장입니다. 즉 fact(1..3).fact(1). fact(2). fact(3).으로 확장됩니다. 언어는 INTFLOAT 숫자를 인식하며 종료 자로도 .을 사용합니다.나는, 문법의 측면에서, 일부 확장과 프롤로그</em><em>과 같은 <em>대답 설정 프로그래밍 (ASP)</em>의 방언에 대한 파서를 작성하는 것을 시도하고있다 ANTLR4

구문 분석기가 정수, 부동 소수점, 확장자 및 구분 기호를 구별하지 못하는 이유는 언어가 명확하지 않기 때문입니다. 이 경우 명시 적으로 토큰을 공백으로 구분해야합니다. 그러나 프롤로그 또는 ASP 파서는 이러한 제작을 올바르게 처리합니다. 나는 그것을 읽었다 ANTLR4는 문제가있는 작품을 자율적으로 모호하게 할 수 있지만 아마도 도움이 필요 하겠지만 어떻게해야할지 모르겠다! ;-) 나는 herehere과 같은 것을 읽었지만 분명히 그들은 나를 도와주지 않았다.

누군가가이 모호성을 극복하기 위해해야 ​​할 일을 말해 줄 수 있습니까? 언어는 매우 표준적인 언어이므로 변경할 수 없습니다. 전문가의 작업을 단순화하기 위해 필자는 최소한의 작업 예제를 작성했습니다.

grammar Test; 

program: 
    statement* ; 

statement: // DOT is the statement terminator 
    range DOT | 
    intNum DOT | 
    floatNum DOT ; 

intNum: // not needed, but helps in TestRig 
    INT; 

floatNum: // not needed, but helps in TestRig 
    FLOAT; 

range: // defines an expansion 
    INT DOTS INT ; 

DOTS: '..'; 
DOT: '.'; 

FLOAT: DIGIT+ '.' DIGIT* | '.' DIGIT+ ; 
INT: DIGIT+ ; 

WS: [ \t\r\n]+ -> skip ; 

fragment NONZERO  : [1-9] ; 
fragment DIGIT  : [0] | NONZERO ; 

나는 다음과 같은 입력 사용 :

1 . 
1. . 
1.5 . 
.5 . 
1 .. 5 . 

1. 
1.. 
1.5. 
.5. 
1..5. 

을 그리고 다른 도구 대신 수정 구문 분석 다음과 같은 오류를 얻을 :

line 8:0 extraneous input '1.' expecting '.' 
line 11:2 extraneous input '.5' expecting '.' 

많은 감사를 사전에!

+0

이 언어는 _ 부동 _1로 부동을 허용합니까? 프롤로그는 그렇지 않으며, 이로 인해 언어의 모호성이 상당히 높아집니다. –

+0

@Daniel Lyons Prolog가'1'을 float으로 받아들이지 않는다는 것을 깨닫지 못했습니다 ... 나는 방금 수레에 대한 다소 표준적인 정의를했습니다. 당신의 제안은 다음 프로덕션을 float에 사용하는 것입니다 :'float : DIGIT + '.' DIGIT +; –

+0

나는 그것이 도움이 될 것이고 그것이 상처를 받으면 나는 충격을받을 것이라고 생각한다. –

답변

0

프롤로그는 float로 1.을 허용하지 않습니다. 이 기능을 사용하면 문법이 훨씬 모호해질 수 있으므로 해당 기능을 제거해보십시오.

+0

그리고 지금 그것이 받아 들여지는 대답입니다! 당신의 도움에 많은 감사드립니다! –

1

는 DOTS 규칙 전에 문 단말기 점에 대해 고유 한 규칙을 추가하고 DOTS 규칙을 명확하게 (그리고 터미널 사용하는 다른 규칙을 변경) : 술어 방법은 간단에 앞서 보인다 곳

TERMINAL: DOT { isTerminal(1) }? ; 
DOTS: DOT DOT { !isTerminal(2) }? ; 
DOT: '.'; 

을 _input 문자 스트림. 현재 토큰 색인에서 다음 문자가 공백인지 여부를 확인합니다. 문법에 @member 블록에 이런 식으로 뭔가를 넣어 : 공백이 점과 후행 INT 사이에 유효한 경우

public boolean isTerminal(int la) { 
    int offset = _tokenStartCharIndex + 1 + la; 
    String s = _input.getText(Interval.of(offset, offset)); 
    if (Character.isWhitespace(s.charAt(0))) { 
     return true; 
    } 
    return false; 
} 

조금 더 많은 작업을 수행 할 수 있습니다.

+0

나는 내가 당신이 제안한 것에 대한 직감을 가지고 있다고 생각한다. 그러나 나는 그것이 올바르게되었는지보기 위해 내일 몇 가지 테스트를해야한다! 지금 고마워! –

1

작업을 파서로 옮기는 것이 좋습니다.

1..21..2 또는 1 .. 2 인 경우 렉서가 결정할 수없는 경우 파서의 지시에 따라야합니다.

아마도 첫 번째 대안으로 해석 될 수있는 컨텍스트가 있고 두 번째 대안으로 해석 될 수있는 다른 컨텍스트가있을 수 있습니다.

은 Btw는 : 1..2.1 .. 2 . (range) 또는 1. . 2 . (floatNum, intNum)로 해석 될 수있다. 이걸 어떻게 처리하고 싶니?

다음 문법은 모든 것을 구문 분석해야합니다. 그러나 . .dots으로 취급되며 1 . 23floatNum입니다. 파싱하는 동안 또는 파싱하는 동안 (파싱에 영향을 주는지 여부에 따라) 이러한 힘든 부분을 확인할 수 있습니다.

grammar Test; 

program: 
    statement* ; 

statement: // DOT is the statement terminator 
    range DOT | 
    intNum DOT | 
    floatNum DOT ; 

intNum: // not needed, but helps in TestRig 
    INT; 

floatNum: 
    INT DOT INT? | DOT INT ; 

range: // defines an expansion 
    INT dots INT ; 

dots : DOT DOT; 

DOT: '.'; 

INT: DIGIT+ ; 

WS: [ \t\r\n]+ -> skip ; 

fragment NONZERO  : [1-9] ; 
fragment DIGIT  : [0] | NONZERO ;