# Interpreter Pattern ```swift // MARK: - Abstract Expression // Abstract Syntax Tree의 모든 노드에서 사용할 Interpreter 작업을 정의 protocol IntegerExpression { func evaluate(_ context: IntegerContext) -> Int } // MARK: - Context // InterPreter가 해석할 문장 final class IntegerContext { private var data: [Character:Int] = [:] // 각 Character별로 Int값을 key value로 대입 func assign(expression: IntegerVariableExpression, value: Int) { self.data[expression.name] = value } // 위에서 assign으로 값을 넣어주고 lookup 메서드로 Character값으로 해당 value인 Int값 찾기 func lookup(name: Character) -> Int { return self.data[name]! } } // MARK: - Terminal Experssion // 터미널 기호와 관련된 작업을 구현함 // 여기서 말하는 터미널 기호라고 함은 어떤 문장에서 의미있는 최소의 단위 // 일종의 단위를 재가공 하는 작업 ex) Int -> String, Int -> Double, String -> Int final class IntegerVariableExpression: IntegerExpression { let name: Character init(name: Character) { self.name = name } func evaluate(_ context: IntegerContext) -> Int { return context.lookup(name: self.name) } } // MARK: - NonTerminal Experssion // 하나의 클래스는 문법이 가진 모든 규칙을 필요로 함 // Grammar에서 Nonterminal Symbol에 대한 해석 연산을 구현함 // 재가공 된 단위를 가지고 어떠한 규칙을 만들어서 다시 재가공을 해주는 것 ex) 1 + 2 -> 3, 가 + 나 -> 가나 // 문법이기에 손쉽게 대체 및 추가 가능 ex) 더해주는 규칙을 빼주는 규칙으로 구현부분이 거의 비슷해 쉽게 변경해줄 수 있고(대체), // 더해주는 규칙 하나만 있으면 빼주는 규칙도 손쉽게 생성해줄 수 있음(추가) final class AddExpression: IntegerExpression { private var leftOperand: IntegerExpression private var rightOperand: IntegerExpression init(leftOperand: IntegerExpression, rightOperand: IntegerExpression) { self.leftOperand = leftOperand self.rightOperand = rightOperand } func evaluate(_ context: IntegerContext) -> Int { return self.leftOperand.evaluate(context) + self.rightOperand.evaluate(context) } } var context = IntegerContext() var a = IntegerVariableExpression(name: "A") var b = IntegerVariableExpression(name: "B") var c = IntegerVariableExpression(name: "C") // AddExpression(a, AddExpression(b, c)) // Client var expression = AddExpression(leftOperand: a, rightOperand: AddExpression(leftOperand: b, rightOperand: c)) // a + (b + c) context.assign(expression: a, value: 2) // a = 2 context.assign(expression: b, value: 1) // b = 1 context.assign(expression: c, value: 3) // c = 3 var result1 = expression.evaluate(context) // 6 // MARK: - Client final class Interpreter { // 인터프리터가 해석할 문장 private var context = IntegerContext() // Abstract Syntax Tree 문법을 정의하는 특정 문장 func solve(problems: String) -> Int { // context가 해석할 수 있도록 String -> Character 형변환 var problemList: [Character] = problems.map { Character(extendedGraphemeClusterLiteral: $0) } let firstProblem = problemList.removeFirst() let secondProblem = problemList.removeFirst() let thirdProblem = problemList.removeFirst() // Terminal Experssion Instance let firstOperand = IntegerVariableExpression(name: firstProblem) let secondOperand = IntegerVariableExpression(name: secondProblem) let thirdOperand = IntegerVariableExpression(name: thirdProblem) // NonTerminal Experssion Instance let solvedExpression = AddExpression(leftOperand: firstOperand, rightOperand: AddExpression(leftOperand: secondOperand, rightOperand: thirdOperand)) context.assign(expression: firstOperand, value: 1) context.assign(expression: secondOperand, value: 2) context.assign(expression: thirdOperand, value: 3) let result = solvedExpression.evaluate(context) return result } } let interpreter = Interpreter() //interpreter.solve(problems: "123") // 6 interpreter.solve(problems: "CBC") // first operand와 third operand의 value는 다른데 왜 third operand의 value로 둘다 저장이 될까 // key value값으로 assign해주었기에 처음 3은 1로 값이 들어갔지만 마지막에 3으로 다시 변경이됨 ```