# CASE Statements

Source: https://rungs.dev/docs/structured-text/case-statements

> CASE statements in Structured Text on rungs.dev select one branch from many based on a numeric expression — tidier than long IF…ELSIF chains for state machines.

CASE checks one numeric expression and runs the statements that match the first selector. It keeps branching tidy compared to a long `IF...ELSIF` chain.

## Syntax [#syntax]

```iecst
CASE numeric_expression OF
    selector1: Statements;
    selector2: Statements;
    selector3, selector4: Statements; // Matches selector3 or selector4
    selector5..selector6: Statements; // Matches any value from selector5 to selector6
ELSE
    Default_Statements;
END_CASE;
```

### Syntax Rules [#syntax-rules]

- `numeric_expression` can be any `DINT` or `REAL` tag or math expression.
- Each selector is a literal value (for example `1` or `7.5`). You cannot use tag names as selectors.
- Separate multiple selectors with commas (`,`).
- Use two dots (`..`) for an inclusive range such as `0..10`.
- `ELSE` is optional but helpful as a default branch.
- Always finish the block with `END_CASE;`.
- With `REAL` selectors, ranges work better than matching a single decimal value.

## Example: Mode Selector [#example-mode-selector]

```iecst
CASE Mode OF
    1: Operation_Code := 10;
    2: Operation_Code := 20;
    3: Operation_Code := 30;
ELSE
    Operation_Code := 0; // Default
END_CASE;
```

This sets `Operation_Code` based on the current `Mode` value. If `Mode` is not `1`, `2`, or `3`, the `ELSE` branch executes.

## Example: Speed Level Control with Ranges [#example-speed-level-control-with-ranges]

```iecst
CASE Speed_Level OF
    0: Motor_Speed := 0;
    1..3: Motor_Speed := 25; // Values 1, 2, 3
    4..6: Motor_Speed := 50;
    7..10: Motor_Speed := 100;
ELSE
    Motor_Speed := 0; // Fallback if out of range
END_CASE;
```

This example uses numeric ranges to group related values. Each range is inclusive of both start and end values.

## Example: Multiple Selectors (Comma-Separated) [#example-multiple-selectors-comma-separated]

```iecst
CASE Error_Code OF
    1, 2, 3: Reset_Flag := 1; // Matches any of 1, 2, or 3
    4, 5: Reset_Flag := 0;
ELSE
    Reset_Flag := 0;
END_CASE;
```

Comma-separated selectors allow multiple exact values to share the same action.

## When to Use CASE Instead of IF [#when-to-use-case-instead-of-if]

- Comparing one numeric expression to several values
- You want cleaner logic than stacked `IF...ELSIF`
- You need to group ranges or sets of numbers under one result

## Notes [#notes]

- Use `IF...THEN...ELSE` when conditions depend on multiple variables or relational comparisons.
- `END_CASE;` still needs the semicolon.
- Include an `ELSE` section when you need a defined default outcome.

## Summary Table [#summary-table]

| Feature                    | Supported | Example       | Description                         |
| -------------------------- | --------- | ------------- | ----------------------------------- |
| Single selector            | Yes       | `1:`          | Exact match                         |
| Multiple selectors         | Yes       | `1, 2, 3:`    | Comma-separated constants           |
| Numeric range              | Yes       | `0..10:`      | Inclusive bounds                    |
| Distinct selectors + range | Yes       | `1, 4, 5..7:` | Combine discrete values and a range |
| Non-numeric range          | No        | `'A'..'Z'`    | Invalid                             |

> **IDEA**
>
> **Practice**
>
> Try `CASE` in the [Mux 4 exercise](https://rungs.dev/exercises/mux-4) — route one of four inputs to the output by a select value.