Interpreter 패턴

김태현·2022년 8월 28일
0

CS

목록 보기
7/7

참고 자료_ 정의, UML, 예제 코드

정의

  • 특정 언어로 composite pattern 으로 이뤄진 문장을 바꿀 때 사용되는 디자인 패턴
  • termianl / non-terminal 클래스 가진다.
  • 재귀적 문제 해결(문법)에 용이

UML

  • Abstract Expression
    Abstract Syntax Tree의 모든 노드에서 사용할 Interpret 작업을 정의합니다.
  • Terminal Expression

    터미널 기호와 관련된 작업을 구현합니다.

    문장의 모든 터미널 기호에 인스턴스가 필요합니다.
    여기서 말하는 터미널 기호라고 함은 어떤 문장에서 의미있는 최소의 단위입니다.
    ex. 연산식의 숫자(피 연산자)

  • Nonterminal Expression
    하나의 클래스는 문법이 가진 모든 규칙을 필요로합니다. (규칙은 R1... Rn으로 표현합니다.)
    R1... Rn Symbol 각각에 대한 AbstractExpression 타입의 인스턴스 변수를 유지합니다.
    Grammar에서 Nonterminal Symbol에 대한 해석 연산을 구현합니다. Interpret는 R1... Rn까지의 규칙을 나타내는 변수를 통해 재귀적 방식으로 해석합니다.
    ex. 연산식의 연산기호

  • Context
    Interpreter가 해석할 문장

  • Client

    문법이 정의하는 언어의 특정 문장을 나타내는 Abstract Syntax Tree를 정의합니다. Abstract Syntax Tree는 Nonterminal Expression, Terminal Expression의 인스턴스로 구성됩니다. 

    Interpret 작업을 호출

참고 자료_ 예제2

참고 자료 이미지 후위 연산(post-order)

예제 코드

import Foundation

protocol Expression {
    func evaluate() -> Int
}

class Number: Expression { //Terminal Experssion
    private let number: Int
    
    init(number: Int) {
        self.number = number
    }
    
    func evaluate() -> Int {
        return number
    }
}

class Addition: Expression { //NonTerminal Experssion
    private let leftOperand: Expression
    private let rightOperand: Expression
    
    init(leftOperand: Expression, rightOperand: Expression) {
        self.leftOperand = leftOperand
        self.rightOperand = rightOperand
    }
    
    func evaluate() -> Int {
        return leftOperand.evaluate() + rightOperand.evaluate()
    }
}

class Interpreter {
    func evaluate(problem: String) -> Int {
        var tokens: [Expression] = []
        let tokenList = problem.components(separatedBy: " ")
        
        for token in tokenList {
            if token == "+" {
                let lo = tokens.removeFirst()
                let ro = tokens.removeFirst()
                
                let op = Addition(leftOperand: lo, rightOperand: ro)
                
                let result = op.evaluate()
                
                tokens.insert(Number(number: result), at: 0)
            } else {
                let num = Number(number: Int(token)!)
                tokens.insert(num, at: 0)
            }
        }
        
        let result = tokens.remove(at: 0)
        return result.evaluate()
    }
}

let calcaulator = Interpreter()

let result = calcaulator.evaluate(problem: "4 4 + 5 10 + +")
// "4 4 + 5 10 + +" : context
print(result)
// 8 15 +
// 23
profile
iOS 공부 중

0개의 댓글