2012-11-15 3 views
1

좋아, 이틀 동안 세 번째 ANTLR 질문에 대한 :재귀 처리 규칙 ANTLR에서

내 문법은 부울 문이 같은 분석을 의미한다

:이 비교적 간단한 문법이기 때문에

AGE > 21 AND AGE < 35 

을 , 나는 AST를 사용하기보다는 코드를 임베드했다. 규칙은 다음과 같습니다 : 더 악화

AGE >= 21 AND (DEPARTMENT=1000 OR DEPARTMENT=1001) 

나 :

AGE >= 21 AND (DEPARTMENT=1000 OR (EMPID=1000 OR EMPID=1001)) 

수있는 사람

: a=singleEvaluation { $evalResult = $a.evalResult;} 
(('AND') b=singleEvaluation {$evalResult = $evalResult && $b.evalResult;})+ 
{ 
// code 
} 
; 

지금 내가 이런 일을 구문 분석 괄호를 사용하여 작업의 순서를 구현해야 필요한 재귀를 구현하는 방법을 제안 하시겠습니까? 차라리이 후기 단계에서 대서양 표준으로 전환하지 않을 것입니다. 그리고 저는 여전히이 점에서 상대적인 멍청한 입장입니다.

제이슨

답변

1

, 그리고 다른 사람 (또는 정수만 비교), 가장 할 것 귀하의 규칙은 일반 Object를 반환하고 그에 따라 캐스트합니다.

grammar T; 

@parser::members { 
    private java.util.Map<String, Integer> memory = new java.util.HashMap<String, Integer>(); 
} 

parse 
@init{ 
    // initialize some test values 
    memory.put("AGE", 42); 
    memory.put("DEPARTMENT", 999); 
    memory.put("EMPID", 1001); 
} 
: expression EOF {System.out.println($text + " -> " + $expression.value);} 
; 

expression returns [Object value] 
: logical {$value = $logical.value;} 
; 

logical returns [Object value] 
: e1=equality {$value = $e1.value;} ('AND' e2=equality {$value = (Boolean)$value && (Boolean)$e2.value;} 
            | 'OR' e2=equality {$value = (Boolean)$value || (Boolean)$e2.value;} 
            )* 
; 

equality returns [Object value] 
: r1=relational {$value = $r1.value;} ('=' r2=relational {$value = $value.equals($r2.value);} 
             | '!=' r2=relational {$value = !$value.equals($r2.value);} 
             )* 
; 

relational returns [Object value] 
: a1=atom {$value = $a1.value;} ('>=' a2=atom {$value = (Integer)$a1.value >= (Integer)$a2.value;} 
           | '>' a2=atom {$value = (Integer)$a1.value > (Integer)$a2.value;} 
           | '<=' a2=atom {$value = (Integer)$a1.value <= (Integer)$a2.value;} 
           | '<' a2=atom {$value = (Integer)$a1.value < (Integer)$a2.value;} 
           )? 
; 

atom returns [Object value] 
: INTEGER   {$value = Integer.valueOf($INTEGER.text);} 
| ID     {$value = memory.get($ID.text);} 
| '(' expression ')' {$value = $expression.value;} 
; 

INTEGER : '0'..'9'+; 
ID  : ('a'..'z' | 'A'..'Z')+; 
SPACE : ' ' {$channel=HIDDEN;}; 

다음과 같은 출력 초래 입력 "AGE >= 21 AND (DEPARTMENT=1000 OR (EMPID=1000 OR EMPID=1001))" 구문 분석 :

AGE >= 21 AND (DEPARTMENT=1000 OR (EMPID=1000 OR EMPID=1001)) -> true 
+0

좀했습니다 여기

는 (괄호 표현의 경우에는 재귀 호출을 포함) 빠른 데모입니다 조정, 특히 원자 규칙에서. 아파치 코 몬즈 BeanUtils를 사용하여 Java POJO에 대해 유효성을 검사하고 문자열/날짜/등의 문법에 대한 정의를 가지고 있습니다. 그러나 일반적으로 이것은 굉장했습니다. 다시 한번 감사드립니다. – Jason

1

나는 이런 식으로 할 것입니다 : 정수로

규칙 중 일부는 부울로 평가하기 때문에
program : a=logicalExpression {System.out.println($a.evalResult);} 
     ; 

logicalExpression returns [boolean evalResult] : a=andExpression { $evalResult = $a.evalResult;} (('OR') b=andExpression {$evalResult = $evalResult || $b.evalResult;})* 
               ; 

andExpression returns [boolean evalResult]  : a=atomicExpression { $evalResult = $a.evalResult;} (('AND') b=atomicExpression {$evalResult = $evalResult && $b.evalResult;})* 
               ; 

atomicExpression returns [boolean evalResult] : a=singleEvaluation {$evalResult = $a.evalResult;} 
               | '(' b=logicalExpression ')' {$evalResult = $b.evalResult;} 
               ; 

singleEvaluation returns [boolean evalResult ] : 'TRUE' {$evalResult = true;} 
               | 'FALSE' {$evalResult = false;} 
               ; 
관련 문제