Interpreter Design Pattern in Swift

1. Definition

The Interpreter design pattern provides a way to evaluate language grammar or expressions for particular languages. It primarily deals with the problem of evaluation, parsing, and execution. It involves building an interpreter to interpret the expressions defined in a language grammar.

2. Problem Statement

Imagine you are building a simple calculator app that takes input as a string (e.g., "5 + 3 - 2"). Evaluating such expressions directly can become complex, especially when you add more operations or variables.

3. Solution

The Interpreter pattern suggests defining a grammar for the language, then implementing an interpreter to interpret the expressions of the language.

4. Real-World Use Cases

1. Compilers and parsers for programming languages.

2. Query interpreters like SQL.

3. Rule-based engines.

5. Implementation Steps

1. Define an abstract Expression that declares a method interpret().

2. For every rule in the grammar, define a concrete implementation of Expression.

3. Interpret the expression.

6. Implementation in Swift Programming

// 1. The abstract Expression
protocol Expression {
    func interpret(context: String) -> Bool
}
// 2. Concrete Expressions
class TerminalExpression: Expression {
    private let data: String
    init(data: String) {
        self.data = data
    }
    func interpret(context: String) -> Bool {
        return context.contains(data)
    }
}
class OrExpression: Expression {
    private let expr1: Expression
    private let expr2: Expression
    init(expr1: Expression, expr2: Expression) {
        self.expr1 = expr1
        self.expr2 = expr2
    }
    func interpret(context: String) -> Bool {
        return expr1.interpret(context: context) || expr2.interpret(context: context)
    }
}
// Client Code
let julia = TerminalExpression(data: "Julia")
let married = TerminalExpression(data: "Married")
let isMarriedWoman = OrExpression(expr1: julia, expr2: married)
let context = "Julia is Married"
print(isMarriedWoman.interpret(context: context))

Output:

true

Explanation:

1. The Expression protocol defines a way to interpret a context.

2. TerminalExpression checks if the context contains a specific string.

3. OrExpression is a compound expression that checks if either of its sub-expressions are true in the given context.

4. In the client code, we define terminal expressions for "Julia" and "Married" and then combine them using the OrExpression to check if a context has either "Julia" or "Married".

7. When to use?

Use the Interpreter pattern when:

1. The grammar of the language is simple. For complex grammars, tools like parsers or compilers are more appropriate.

2. Efficiency is not a critical concern, as interpreters can be slower than hand-tailored solutions.


Comments