2010-04-12 1 views
1

AST로 작업 할 때 모범 사례가 있습니까? 구문 분석 AST가 있습니다. ConstantExpression, BinaryExpression 등 AST의 정보로 GUI 대화 상자를 채우고 싶습니다. 내 코드가 꽤 복잡해지기 때문에 다소 혼란 스럽습니다.표현식 AST로 작업하기

예 :

나는 값 10 RESP 두 개의 텍스트 상자를 채우려
expression = "Var1 > 10 AND Var2 < 20" 

. 20에서 대서양 표준시. 내가 지금하고있는 것은 올바른 자식 표현 유형 (.Net Is-operator 사용)을 확인하고 그에 따라 작동하며 코드가 실제로 "smelly"인 재귀 적 방법입니다. :)

어떤 디자인 패턴이 있습니까? 방문객이나 그와 같은 사람이 이것을 좀 더 쉽게/더 읽기 쉽고 유지할 수있게합니까?

+0

의견에 관해서. 당신이 설명하는 어려움을 이해하고 있는지 확신 할 수 없습니다. 어떤 종류의 표현이 허용되지 않습니까? 어쨌든, 요점은 설명하는 두 개의 apporaches가 나무에서 수행하려는 모든 종류의 조작/유효성 검사에 사용될 수 있다는 것입니다. 첫 번째 접근 방식에서 적절한 매개 변수를 사용하여 새 메소드를 추가하거나 적절한 필드를 사용하여 두 번째 접근 방식에서 방문자의 새 하위 클래스를 정의하면됩니다. –

+0

다음은 무슨 뜻입니까. exp1 = "1 + 1" exp2 = "Var1> 10 및 Var2 <20" 해결책으로 두 표현식에서 두 개의 정수를 얻을 수 있지만 첫 번째 표현식이 내 응용 프로그램에 올바른 유형이 아닙니다. GUI가 채워 넣는 GUI는 두 가지 정수가 포함 된 모든 유형의 표현식 (트리의 일부분)이 아닌 특정 유형의 표현식에서만 작동합니다. – Marcus

+0

구체적으로 달성하고자하는 것이 분명하지 않습니다. –

답변

0

대부분의 컴파일러는 사용하여이 문제를 해결하거나

  • 방법
다음

입니다 당신이 나타납니다 모든 상수 값 (리터럴) 수집에 대해 가고 싶어하는 방법이다

  • 방문자를 무시하여 표현식은 List의 정수로 나타납니다. 그런 다음 코드를 호출하면이 목록의 값으로 텍스트 상자를 채울 수 있습니다.

    방법 오버라이드

    최상위 가장 AST 클래스는 서브 클래스에서 오버라이드 (override)하는 추상적 인 방법을 정의합니다.

    class AstNode { 
        .. // Some stuff 
        public abstract void collectValues(List<Integer> ints); 
    } 
    
    class ConstantExpression : AstNode { 
        private int value; 
        .. // Some stuff 
        public override void collectValues(List<Integer> ints) { ints.Add(value); } 
    } 
    
    class BinaryExpression : AstNode { 
        private AstNode left; 
        private AstNode right; 
        .. // Some stuff 
        public override void collectValues(List<Integer> ints) { 
         left.collectValues(ints); 
         right.collectValues(ints); 
        } 
    } 
    
    class Identifier : AstNode { 
        .. // Some stuff 
        public override void collectValues(List<Integer> ints) { 
        // do nothing! 
        } 
    } 
    

    방문자

    같은 프로그램 만 방문자를 사용하여 작성. 하는 AST 작업을위한

    class Visitor { 
        public abstract void visit(ConstantExpression e); 
        public abstract void visit(BinaryExpression e); 
        public abstract void visit(Identifier e); 
    } 
    
    class AstNode { 
        .. // Some stuff 
        public abstract void accept(Visitor v); 
    } 
    
    class ConstantExpression : AstNode { 
        public int value; 
        .. // Some stuff 
        public override void accept(Visitor v) { v.visit(this); } 
    } 
    
    class BinaryExpression : AstNode { 
        private AstNode left; 
        private AstNode right; 
        .. // Some stuff 
        public override void accept(Visitor v) { 
        left.accept(v); 
        right.accept(v); 
        v.visit(this); 
        } 
    } 
    
    class Identifier : AstNode { 
        .. // Some stuff 
        public override void accept(Visitor v) { v.visit(this); } 
    } 
    
    
    class ValueCollector : Visitor { 
        public List<Integer> ints = ...; 
    
        public void visit(ConstantExpression e) { ints.Add(e.value); } 
        public void visit(BinaryExpression e) { } 
        public void visit(Identifier e) { } 
    } 
    
  • +0

    그것은 좋은 솔루션이지만, 내가 원하는 "안전"은 아닙니다. 이 솔루션은 값만 수집합니다. 예 : "표현식 : 1 + 1"은 당신의 해답으로 작동 할 것이지만 그 종류의 표현은 허용되지 않습니다. – Marcus

    1

    모범 사례는 다음과 같습니다

    • 당신이에 AST를 걸어 도움을 받기 문법 설명
    • 의 어떤 종류에서 좋은 라이브러리를하는 AST를 구축 할 수 있도록 좋은 파서 받기 AST 수집/수정

    AST를 심각하게 사용하려면 AST를 생성하고 조작하도록 설계된 패키지를 사용하는 것이 가장 좋습니다. 흔히 이러한 패키지에는 소스와 소스 간의 변환을 사용하는 패턴 일치 및/또는 AST 재 작성과 같은 많은 추가 지원이 포함됩니다.

    여기에 몇 가지 있습니다 :

    This example은 BNF, 패턴 및 소스 -를 사용하는 AST를 구축하고 조작하는 방법을 보여줍니다 투 - 소스 변환.