2014-07-21 4 views
0

내가 구문 분석하는 데 노력하고있어 파일에서 발췌 한 것입니다. 따라서 이들을 처리 할 규칙은 다음과 같습니다.ANTLR4 파서 규칙 충돌

//Start rule, left out the other sections because they work 
program : typesymbolssection signaturesection; 

//The rules below are for handling the Type Symbols section 
typesymbolssection : 'section typeSymbols:' typelist; 

typelist : type (',' type)*; 

type : if_type | if_operator '(' typelist ')' | '{' constantnatlist '}'; 
//only the first alternative should matter here. 
//the rest are only used elsewhere 

if_type : Const_ident; 

Const_ident : [a-z][A-Za-z0-9_]*; 

//The rules below are for handling the Signature Section 
signaturesection : 'section signature:' signaturesection0; 

signaturesection0 : supertypedeclaration* functiondeclaration* predicatedeclaration*; 

supertypedeclaration : if_type '>' if_type; 

functiondeclaration : if_operator ':' typestar '->' type; 

predicatedeclaration : if_operator ':' typestar '->' 'fact'; 

typestar : type | type '*' typestar; 

이 문법은 하나의 작은 오류를 제외하고는 대부분 파일을 올바르게 구문 분석합니다. 그것은 오류를 준다 : "입력 '실용적인 대안'사실" ". 이것은 유형 기호 섹션의 사실에 대한 첫 번째 인스턴스를 나타냅니다.

typesymbolssection 
    | 
    |----> "section typeSymbols:" 
    | 
    |----> typelist 
      | 
      |---> type ---> if_type ---> agent 
      |---> type ---> if_type ---> message 
      |---> type ---> fact //Highlighted in red because of parsing error 
      |---> type ---> if_type ---> nat 
      |---> type ---> if_type ---> protocol_id 
      |---> type ---> if_type ---> set 

를 내가 제대로 구문 분석하도록 오류를 해결하는 한 가지 방법을 알고 있지만,이 수정은 훨씬 더 큰 오류를 소개합니다 : 그것은 다음과 같은 구문 분석 트리를 얻을 수 있습니다. 오류를 던지고없이 다음

predicatedeclaration : if_operator ':' typestar '->' type; 

가 실행하지만 제대로 나는 때문에 모든 술어 선언 뭘하는지 설명하지 않습니다

predicatedeclaration : if_operator ':' typestar '->' 'fact'; 

에 : 나는에서

을 변경하는 경우 함수 선언으로 읽혀지고 (이 시점에서 함수와 술어에 대한 정의가 같기 때문에) 술어 정의가 잘못되었다고 잘못 생각합니다. 함수가 아니라 술어가되는 것은 그것이 사실로가는 것입니다. 그러나 인용문에 'fact'가 있어야한다는 것을 명시함으로써 typeSymbols 섹션으로 올라간다는 것을 분명히한다면. 이것은 심지어 관련이 없기 때문에 이것은 나에게 이해가되지 않습니다. 그것은 형식 규칙에있는 것이고 다른 것들처럼 Const_ident에 전달하는 대신 '사실'입력을 포기한다는 것을 알 수 있습니다.

내 질문에 차이가 있으며 왜 이것을 수정하여 두 오류를 피할 수 있습니까? "유형"에서 "사실"로 변경하는 것이 왜 첫 번째 섹션에서 차이를 만들어야하는지 이해할 수 없습니다. 지금까지 나는 한 가지 오류 또는 다른 오류가있는 곳에서 붙어 있었고 3 일 동안 내 머리를 두드리는 소리를 쳤다. 어떤 도움이라도 대단히 감사합니다 ...

답변

1

규칙의 순서 (우선 순위)에 문제가 있습니다. 일치 할 수있는 첫 번째 렉서 규칙이 일치합니다. 문법 유사한 다른 경우에도

predicatedeclaration : if_operator ':' typestar '->' Fact ; 


Fact : 'fact'; // now 'fact' will be a Fact not a Const_ident 
Const_ident : [a-z][A-Za-z0-9_]*; 

확인 :

Const_ident : [a-z][A-Za-z0-9_]*; // will match the token 'fact'! 

//... 

predicatedeclaration : if_operator ':' typestar '->' 'fact'; // implicitly creates the token 'fact', which will NEVER match since it's always matched by Const_ident rule! 

는 다음과 같이하십시오.

조언 : 당신이 우선 순위를 명확하게 볼 수 있습니다, 그래서 한 곳에서 모든 렉서 규칙을 넣어

  • . 가장 전문화 된 것을 먼저 써서보다 일반적인 규칙에 "이길"수 있습니다.
  • 암시 적 토큰을 사용하지 마십시오 (예 : 파서 ​​규칙에서 '무언가')
  • 파서와 렉서 문법을 두 개의 파일로 분리하는 것이 가장 좋습니다. 이렇게하면 암시 적 토큰을 만들 수 없습니다.

편집 :

// use parser rules for `Const_ident` now. I.e. in all parser rules only use the parser rule, not the token directly. 
const_ident : Const_ident | Fact; // will match `Const_ident`s and `fact`s 


Fact : 'fact'; 
Const_ident : [a-z][A-Za-z0-9_]*; // don't use this directly in parser rules but `const_ident` instead! 
+0

불행하게도이 나를 위해 문제가 해결되지 않은 : 때때로 Fact 때로는 'Const_ident'을한다

fact 경우, 다음과 같은 방법을 사용할 수 있습니다. 여러 주문에서 규칙을 이미 시도했지만 여전히 문제가 있습니다. 또한 나는 ANTLR4 참고 서적에서 렉서가 가장 긴 글자를 취할 것임을 (즉, 대부분의 글자를 소비하는 것을 의미하며 넥타이를 쓴다면 가장 먼저 나온 것을 고를 것임을 의미한다) 글을 읽었다 고 생각한다. 문제는 문자열 fact가 입력에 두 번 나타나고 매번 다르게 취급되기를 바랍니다. – user3380049

+0

그러나 "사실"은 항상 "Const_ident"에 의해 매치 될 수 있으므로,이 규칙에 따라 항상 먼저 나온다. – Onur

+0

죄송합니다. 무슨 말을해야할지 모르겠군요. 나는 그것을 시도하고 그것은 문제를 해결하지 않았다. 문제는 처음으로 '사실'이 입력에 나타나고, 이후에 항상 Const_ident가되어야한다는 것입니다. 지금 당장 가장 좋은 해결책은 입력 파일에 물건을 추가하여 문제를 전처리하여 함수와 술어가 다르게 형성되도록하는 것입니다 ... – user3380049