2012-12-15 4 views
2

그래서 ANTLR을 사용하여 Java로 컴파일러를 작성하고 있으며 오류를 처리하는 방법에 다소 의문이 생깁니다.ANTLR이 구문 오류를 억제하지 못하게하는 방법은 무엇입니까?

기본 동작은 오류 메시지를 인쇄 한 다음 토큰 삽입 등을 통해 오류를 복구하고 구문 분석을 계속하는 것 같습니다. 나는 원칙적으로 이것을 좋아한다. 즉, 사용자가 둘 이상의 구문 오류를 범하면 (가장 좋은 경우) 오류 당 하나의 메시지가 표시되지만 모든 오류를 다시 컴파일하여 다음 오류를 발견하도록 강요하지는 않습니다. 기본 오류 메시지는 내 용도에 적합합니다. 문제는 모든 토큰을 읽었을 때 발생합니다.

물론 ANTLR의 트리 생성자를 사용하여 추상 구문 트리를 작성합니다. 구문 분석을 계속 진행하여 사용자가 모든 오류를 볼 수 있도록 구문 분석을 계속하는 것은 좋지만 구문 분석이 끝나면 입력이 구문 적으로 유효하지 않다는 표시 또는 예외를 얻고 싶습니다. 그런 식으로 컴파일을 중단하고 사용자에게 "죄송합니다. 구문 오류를 수정 한 다음 다시 시도하십시오"라고 말할 수 있습니다. 내가 원하지 않는 것은 사용자가 말하고자하는 바를 토대로 불완전한 AST를 내뱉고 아무 것도 잘못되었다는 표시없이 컴파일의 다음 단계로 진행하는 것이다. 콘솔과 나는 볼 수 없다). 그러나 기본적으로 정확하게 작동합니다. RecognitionException들 던져 mismatchrecoverFromMismatchedSet 방법을 무시하고, 동일한 작업을 수행 할 수있는 @rulecatch 액션을 추가 :

는 확실한 ANTLR 참조 즉시 구문 오류가 감지되는 구문 분석을 중지하는 기술을 제공합니다. 이것은 구문 분석 오류를 복구하는 이점을 잃어 버리는 것처럼 보일 수 있지만 더 중요한 것은 부분적으로 만 작동한다는 것입니다. 필요한 토큰이 누락 된 경우 (예 : 2 진 연산자가 한쪽에만 표현식이있는 경우) 예상대로 예외가 발생하지만 불필요한 토큰이 추가되면 ANTLR은 거기에 속한다고 생각되는 토큰을 삽입합니다 콘솔 메시지를 제외하고 구문 오류가 표시되지 않은 상태로 AST를 생성합니다. 설상가상으로, 삽입 된 토큰은 EOF이므로 파일의 나머지 부분도 파싱되지 않았습니다.

isValid 필드에 다음을 추가하여 문제를 해결할 수 있습니다. 구문 분석이 끝날 때 오류가 발생하면 예외를 throw하도록 구문 분석기 및 재정의 메서드와 동작을 추가합니다. 그러나 더 좋은 방법이 있습니까? 나는 ANTLR 사용자들 사이에서 내가하려고하는 것이 이상하다는 것을 상상할 수 없다.

답변

2

... [O] nce 구문 분석이 완료되었습니다. 입력이 구문 적으로 유효하지 않다는 표시 또는 예외를 얻고 싶습니다. 내가 컴파일을 중지 할 수 있습니다 그런 식으로 ...

당신은 은밀하게 ANTLR에 의해 수용되었다 에러가 발생했을 경우 결정하기 위해 구문 분석 후 렉서와 파서 모두 getNumberOfSyntaxErrors를 호출 할 수 있습니다. 이 오류는 분명히 무엇인지 알려주지는 않지만,이 메서드는 "일단 구문 분석이 끝나면 ... 컴파일을 중지합니다"라는 질문에 답변합니다. RecognitionExceptions을 던져 불일치 및 recoverFromMismatchedSet 방법을 무시하고, 동일한 작업을 수행 할 수있는 @rulecatch 액션을 추가

확실한 ANTLR 참조

즉시 구문 오류가 감지되는 구문 분석을 중지하는 기술을 제공합니다.

난 당신이 이클립스를 "사용 내역"을 사용하고 있지만 방법 recoverFromMismatchedSet에 대한 ANTLR의 V3.4 코드의 문서는 "현재 사용되지"말한다 및 ANTLR의 버전을 언급 생각하지 않는다 스캔에서 발신자가 없습니다.당신의 주된 문제에 여기도 거기에 없지만, 나는 그 기록에 대해 언급하고 싶었습니다. 버전에 맞게 재정의하는 것이 올바른 방법 일 수 있습니다.

필요한 토큰이없는 경우는 ... [재정의 된 코드] 예상대로 예외가 발생하지만, 외부 토큰이 추가되는 경우, ANTLR은이 속한 생각하는 토큰을 삽입하고 메리에 계속 방법 ... 각각의 방법 및 mismatchIsMissingTokenmismatchIsUnwantedToken에 위임하여 복구 누락 불필요한 토큰

recoverFromMismatchedToken 테스트 방법. 적절한 방법으로 삽입 또는 삭제로 문제가 해결된다고 판단되면 recoverFromMismatchedToken이 적절하게 수정됩니다. 일치하지 않는 토큰 문 제를 해결하는 조작이 없다고 판단되면 은 MismatchedTokenException을 던집니다.

복구 작업이 수행되면 reportError이 호출되며 자세한 내용은 displayRecognitionError입니다.

이것은 ANTLR v3.4 및 이전 버전에 적용됩니다.

  • 무시 recoverFromMismatchedToken과 세밀한 수준에서 오류를 처리 :

    이렇게하면 적어도 두 가지 옵션을 제공합니다. 여기에서 수퍼 구현으로 호출을 위임하거나, 자체 복구 코드를 롤하거나, 예외 상황을 해결할 수 있습니다. 어떤 경우이든 코드가 호출되므로 불일치 오류가 발생했거나 복구 할 수 있는지 여부를 알 수 있습니다. 이 옵션은 아마도 recoverFromMismatchedSet을 무시하는 것과 같습니다.

  • displayRecognitionError을 무시하고 코스 수준에서 오류를 처리하십시오. 방법 reportError는 일부 주 저글링을 수행하므로 무시 구현이 수퍼 구현을 호출하지 않는 한이를 무시하지 않는 것이 좋습니다. 방법 displayRecognitionError은 복구 된 토큰 호출 체인의 마지막 호출 중 하나 인 것으로 보이므로 계속할지 여부를 결정하는 것이 좋습니다. 나는 그것이 그것이 합리적인 장소라고 지적한 이름을 원했지만 오하이오. 이 옵션을 보여주는 Here is an answer. 쉽게 충분한 오류 메시지 텍스트를 제공하기 때문에

나는 최우선 displayRecognitionError 대한 부분이야하고 있기 때문에 나는 토큰 복구 작업 이후에만 호출 및 상태 저글링을해야 할 것 몰라 - 내 파서에 대한 필요성을 자체 복구 방법을 찾아야합니다. 이것은 getNumberOfSyntaxErrors과 결합하여 관련 버전의 ANTLR로 작업 중이며 문제를 완전히 이해했다고 가정 할 때 원하는 옵션을 제공하는 것으로 보입니다.

+0

유용합니다 (ANTLR 3.4를 사용하고 있습니다). 그러나 실제로 RecognitionException을 던질 곳은 어디입니까? 가능한 경우 복구하는 것이 좋지만 AST를 생성하는 대신 구문 분석 끝에 예외를 던지십시오. – Taymon

+0

@Taymon 구문 분석 후 'getNumberOfSyntaxErrors'를 검사하고 파서를 호출 한 코드가 수행 할 작업을 결정하도록하는 것이 좋습니다. 불일치 토큰을 복구하려는 경우 파서 자체에서 던져 볼 때 장점이 없습니다. 파서가 깨끗한 실행을 시도하도록하고 호출자가 충분히 깨끗한 지 결정하도록하십시오. – user1201210

+0

렉서와 파서 모두에서'getNumberOfSyntaxErrors'를 검사하고, 어느 것이 든 0이 아니면 예외를 던집니다. – Apalala

관련 문제