2013-06-18 4 views
0

일부 왼쪽 재귀 구문 분석 규칙을 사용하는 C# 대상 ANTLR v4에 대한 문법을 ​​작성한 및 이러한 규칙을 사용해야하는 일부 샘플 코드를 구문 분석 할 때마다 구문 분석 엔진은 잘못된 규칙.ANTLR4 왼쪽 재귀 문제

구문 분석 규칙 :

expr 
    : expr COR term 
    | expr CAND term 
    | term 
    ; 

코드는 내가 구문 분석하려고 해요 :

... 
print("Testing Program p00csx\n"); 
... 

구문 분석 엔진에서 정보를 사용하여 방문자이에서

public override Int32 VisitExpr(CSXParser.ExprContext context) 
    { 
     if (context == null) return 0; 
     switch (context.altNum) 
     { 
      case 1: //expr COR term 
       VisitExpr(context.expr()); 
       Console.Write(context.COR()); 
       VisitTerm(context.term()); 
       break; 
      case 2: //expr CAND term 
       VisitExpr(context.expr()); 
       Console.Write(context.CAND()); 
       VisitTerm(context.term()); 
       break; 
      case 3: //term 
       VisitTerm(context.term()); 
       break; 
     } 
     return 0; 
    } 

을 예를 들어, print() 호출의 문자열 리터럴은 '용어'등으로 해석되는 'expr'을 해결해야합니다. c, 'stringLit'이 생길 때까지. 위의 예에서 사례 3입니다. 그러나 대신 파서가 사례 1을 선택하고 심지어 프로그램 텍스트에 COR ('||')이 없다고 생각합니다.

ANTLR 사이트에서는 v4가 이러한 왼쪽 반복 표현을 처리 할 수 ​​있다고 말합니다. 이로 인해 내가 뭔가 잘못하고 있다고 생각하게됩니다. 나는 ANTLR을 처음 접했고, 아마도 문제는 내가 간과 한 단순한 것이었다. 어떤 도움이라도 대단히 감사 할 것입니다. 필자는 문서를 읽고 며칠 동안 디버거를 실행하고 있었고이를 파악하려고 노력했습니다.

감사합니다.

expr 
scope 
{ 
    LogicOperator op; 
} 
     : expr ((COR {expr.op = LogicOperator.Or;} | CAND {expr.op = LogicOperator.And;}) exp)* 
     | term 
     ; 

추신 :

답변

2

다음과 같은 이유로 ParserRuleContext.altNum 필드를 사용하지 마십시오.

  • 왼쪽 재귀 규칙에는 초기화되지 않으므로 신뢰할 수 없습니다.
  • 엄청난 메모리 낭비이고 그것을 제거하기를 바라고 있습니다.
  • 다른 어떤 시나리오에서도 정확성이나 유용성을 확인하기 위해 테스트를 수행하지 않았습니다.

대신, 다음 중 하나를 수행하십시오 대안에 대한

  1. 테스트를 처음 context.expr() 경우는 null를 돌려줍니다 확인하여. 그렇다면 term이 있습니다. expr()이 null이 아닌 경우, context.COR() 또는 context.CAND() 중 null이 아닌 것을 리턴하여 사용 된 실제 운영자를 판별 할 수 있습니다. 이

    expr 
        : expr COR term # orExpr 
        | expr CAND term # andExpr 
        | term   # termExpr 
        ; 
    
+0

그 각도에서 접근하는 것이 흥미 롭습니다. 그런 식으로 실제로 방문자를 작성하기 시작했는데, 코드는 "check this, then check that"로직을 사용하여 상당히 엉망이되어 가고있었습니다.이 로직은'ParserRuleContext.altNum'을 발견했을 때입니다. 'ParserRuleContext.altNum'을 사용하지 않고 구문 분석 규칙의 수를 얻는 방법이 있습니까? –

+0

그게 내가 해결할 두 가지 옵션을 준 이유입니다. :) 두 번째 옵션은'VisitOrExpr','VisitAndExpr' 및'VisitTermExpr'의 3 가지 메소드로 당신을 떠날 것입니다. 'VisitExpr'은 여전히 ​​인터페이스에 존재하지만 기본 방문자는 호출하지 않습니다. –

+0

하하, 죄송합니다. 두 번째 것을 보지 못했습니다. 이전에는 레이블을 사용하지 않았지만 한 번만 알려줍니다. 감사! –

-1

나는 전혀 왼쪽 재귀를 제거 제안 논리 연산자와 우선 순위가있는 ANTLR3 grammar

+0

-1처럼 바깥 쪽 대안,

  • 레이블 : 이것은 내가 ANTLR3와 함께 일 ANTLR 4. –

  • +0

    심지어 유효하지 않은, 그래서 어쩌면 내가 뭔가 ... –

    +1

    을 놓친' scope {}'구문이 ANTLR 4에서 제거되었습니다.또한 ANTLR 4의 자동 왼쪽 재귀 제거는 여기에서 작성한 것과 마찬가지로 수행되지만이 예와 달리 연산자 우선 순위와 연관성을 적절하게 고려하여 구문 분석 트리를 작성합니다. –