Interpreter
Interpreter defines a small language and evaluates expressions in that language. It is useful when users save rules or filters that must be applied repeatedly. It is usually excessive for one hard-coded condition.
iOS problem and example
A task app saves filters such as “flagged AND due soon.” Model the grammar as Swift values rather than evaluating a raw string.
import Foundation
struct TaskItem {
let isFlagged: Bool
let daysUntilDue: Int
}
indirect enum FilterExpression {
case flagged
case dueWithin(Int)
case and(FilterExpression, FilterExpression)
case or(FilterExpression, FilterExpression)
func matches(_ item: TaskItem) -> Bool {
switch self {
case .flagged:
return item.isFlagged
case .dueWithin(let days):
return item.daysUntilDue <= days
case .and(let left, let right):
return left.matches(item) && right.matches(item)
case .or(let left, let right):
return left.matches(item) || right.matches(item)
}
}
}
let filter = FilterExpression.and(.flagged, .dueWithin(3))
let visible = filter.matches(TaskItem(isFlagged: true, daysUntilDue: 2))The enum is an abstract syntax tree. The recursive matches method is its interpreter. A filter editor can build this tree from controlled UI choices and persist a Codable representation.
Production decisions
Define what “due within” means for overdue tasks and time zones. If you accept typed text, write a parser that validates tokens and limits nesting; never turn user text into executable Swift or SQL. For large task sets, translate the expression into a database predicate instead of evaluating every row in memory.
Read the expression tree
FilterExpression is a tiny grammar. Its terminal nodes are flagged and dueWithin; and and or combine smaller expressions into larger ones. The enum is indirect because composite cases contain more FilterExpression values. matches(_:) recursively evaluates the tree for one task, short-circuiting through Swift's Boolean operators. This is safer and easier to test than interpreting arbitrary text or assembling string predicates.
From example to an iOS filter editor
A filter editor can present controlled chips such as Flagged, Due within 3 days, and Match all/any. It turns those selections into an expression tree, stores a versioned representation, and evaluates it when the task list changes. Define whether overdue tasks count as due soon and compute dates in the user's calendar and time zone. For a large data set, translate the same validated tree into a database query so every page uses one consistent filter.
Failure modes and verification
Test nested and and or, empty task sets, boundary day counts, and persisted expression migration. If users type a query language, parser errors must be shown clearly and recursion depth must be limited. An Interpreter is justified when expressions are user-configurable and composable; one fixed filter is simply a predicate.