← Back to scenarios
ScenarioCatalog DB

Expression interpreter

Represent an arithmetic expression as terminal and non-terminal expression nodes and evaluate the resulting tree.

Problem

An application must evaluate arithmetic expressions with a defined grammar while keeping the meaning of numbers and operators separate from the client that constructs and evaluates the expression tree.

Related patterns

Implementations

Interpreter

TypeScriptApplication

Interpreter in TypeScript

Models a small rule language as expression objects that evaluate a user context to determine access.

TypeScript
type AccessContext = {
  role: string;
  region: string;
};

interface Expression {
  interpret(context: AccessContext): boolean;
}

class RoleExpression implements Expression {
  constructor(private readonly expectedRole: string) {}

  interpret(context: AccessContext) {
    return context.role === this.expectedRole;
  }
}

class RegionExpression implements Expression {
  constructor(private readonly expectedRegion: string) {}

  interpret(context: AccessContext) {
    return context.region === this.expectedRegion;
  }
}

class AndExpression implements Expression {
  constructor(
    private readonly left: Expression,
    private readonly right: Expression,
  ) {}

  interpret(context: AccessContext) {
    return this.left.interpret(context) && this.right.interpret(context);
  }
}

class OrExpression implements Expression {
  constructor(
    private readonly left: Expression,
    private readonly right: Expression,
  ) {}

  interpret(context: AccessContext) {
    return this.left.interpret(context) || this.right.interpret(context);
  }
}

const canManageBilling = new AndExpression(
  new RoleExpression("admin"),
  new RegionExpression("us"),
);

const canViewDashboard = new OrExpression(
  canManageBilling,
  new RoleExpression("analyst"),
);

console.log(
  canViewDashboard.interpret({
    role: "analyst",
    region: "eu",
  }),
);

Associated technologies