2009-12-22 4 views
0

저는 인터프리터 작성에 대해 배우기 위해 장난감 언어에 대한 인터프리터로 작업하고 있습니다. 나는 이미 구문 분석 트리를 생성하는 문법에 대한 간단한 파서를 구현했다.표현식 코딩에서 다형성 사용에 대한 의심 구문 트리/평가자

class Node: 
    def __init__(self,left,right): 
     self.left=left 
     self.right=right 

    def evaluate(self): 
     print "throw an exception" 

class AddNode(Node): 
    def evaluate(self): 
     return evaluate(self.left)+evaluate(self.right) 

class SubNode(Node): 
    def evaluate(self): 
     return evaluate(self.left)-evaluate(self.right) 

방법은 모든 자손에서 재정의되는 평가 : 자, 파스 트리를 평가하는 일반적인 방법은 (파이썬) 아래에 뭔가를 보이는 코드, 파스 트리의 노드에서 다형성을 사용하는 것입니다 필요에 따라 행동하도록 방어하십시오. 표현식의 값은 루트에서 단순히 evaluate()을 호출하여 찾을 수 있습니다.

또 다른 방법은 노드에서 평가 기능을 사용하지 않고 단순히 유형을 노드에 할당하는 구문 분석 트리를 생성하는 것입니다. 평가 코드는 각 노드를 재귀 적으로 검사하고 평가하는 방법을 결정하는 별도의 기능으로 수행됩니다. 이렇게하면 "if else"구조, 스위치 또는 점프 테이블이 큰 함수가됩니다.

내가 볼 때 거의 모든 곳에서, 내가 대학에서 가르친 것은 첫 번째 방법이 항상 더 나은 것으로 나타납니다. 내가 완전히 이해하지 못하는 이유는 첫 번째 방법이 두 번째 방법보다 우월해야하는 이유입니다. 이 경우 다형성이 반드시 더 좋은 이유는 무엇입니까? 큰 "if else"테이블이있는 함수는 없지만 기본적으로 동일한 코드가 여전히 있지만 다른 장소로 옮겨지고 많은 다른 클래스에 분산되어 있습니다.

나중에 특정 연산자의 의미를 변경해야 할 수도 있고 런타임에 연산자를 다시 정의 할 필요가 있을지도 모른다고 생각했기 때문에이 점이주의를 끌었습니다. 또한 함수 호출을 연산자와 동일하게 취급하므로 런타임에 추가 할 수있는 점프 테이블과 같은 것이 좋을 것입니다.

내가 지금 보지 못하는 첫 번째 방법에는 아마도 상당한 이점이 있습니다. 누군가 그것을 지적 할 수 있습니까?

답변

1

흥미로운 질문입니다. 다형성은 연산자 오버로딩이 있더라도 여전히 좋은 방법입니다.

다형성 클래스로 정의하는 것은 언어에서 지원되는 기본 연산입니다. 연산자 오버로딩은 언어에 더 이상 기본 기능을 추가하지 않습니다. 오버로드 된 연산자는 실제로 함수 호출과 동일하며 유사한 방식으로 구현되어야합니다.

운영자의 클래스에서 지역화 된 연산자의 의미를 유지하면 내 생각에 명확한 디자인을 유지할 수 있습니다. 새로운 기본 연산을 구현하기 때문에 클래스를 정의한 다음 구문 분석하는 동안 인스턴스를 만들어야합니다. 대안으로는 파서와 평가자를 변경해야합니다. 평가자가 연산자에 대한 여러 가지 특수한 경우를 처리하기 위해 if 문을 중첩 할 수 있다는 느낌이 들었습니다. 이러한 특수한 경우는 연산자 클래스에서 숨길 수 있습니다.

나는 과거에 두 가지 기술을 모두 사용했기 때문에 내가 여기서 말하는 것을 실제로 믿는 데 어려움을 겪고있다. ;-)

+0

감사합니다. 언어에 새로운 연산자를 추가해야 할 때마다 파서와 평가자를 모두 변경해야한다는 점에 유의하십시오. – MAK