2

Ruby로 작성된 컴파일러에서 작업 중이며 현재 의미 분석 단계 (유형 검사)를 진행 중입니다. 선불 주문과 주문 후 주문 방식으로 방문해야하는 AST가 있습니다. Ruby에서 가장 좋은 방법은 무엇인지 궁금합니다. 블록을 each으로 전달하는 것은 본질적으로 방문자 패턴이지만, 두 가지 방식 (사전, 게시물)으로 방문해야하고 Ruby가 메소드 오버로드를 지원하지 않기 때문에이 방법에 접근 할 방법이 확실하지 않습니다.선주문 및 주문 후 방문객

(참고 : 나는 객체들이 방문하는 방법을 제어 노드를 가지고 노력하고, 그래서 내 방문자가 부풀어되지 않습니다)

다음

내가 노력에 대해 생각하고 무엇인가에 대한

두 동의 방법 각 노드 클래스 accept_pre 다른 노드

class Node 
    def initialize(a, b, c) 
    @a, @b, @c = a, b, c 
    end 

    def accept_pre(visitor) 
    @a.accept_pre visitor 
    @b.accept_pre visitor 
    @c.accept_pre visitor 
    vistor.visit_node(self) 
    end 

    def accept_post(visitor) 
    visitor.visit_node(self) 
    @c.accept_post visitor 
    @b.accept_post visitor 
    @a.accept_post visitor 
    end 
end 

이 작업을 수행 할 수있는 더 나은 방법이 있나요

의 해당 accept_preaccept_post 메소드를 호출 accept_post? 두 번의 정렬이 필요하더라도 .each으로 처리 할 수 ​​있습니까?

어떤 도움

주시면 감사하겠습니다.

답변

3

탐색 옵션 arg를 사용하여 두 순서를 하나의 승인으로 접을 수 있습니다. 노드의 구성원을 통해 각각을 사용하여 어린이 수락을 파견 할 수 있습니다.

class Node 
    def initialize(a, b, c) 
    @a, @b, @c = a, b, c 
    end 

    def accept(visitor, traversal=:pre) 
    visitor.visit(self) if traversal == :pre 

    order = traversal == :pre ? :each : :reverse_each 
    [@a,@b,@c].send(order) { |e| e.accept(visitor, traversal) } 

    visitor.visit(self) if traversal == :post 
    end 
end 
+0

어린이 순회를 취소해야합니다. –

+0

@DonRoby 좋은 지적, 수리. – dbenhur

+0

이것은 실제로 훌륭한 솔루션처럼 보입니다. 나는'send' 메소드를 알지 못했다. 고맙습니다! –