---
epic: 1
story: 1.2
title: "Parser & AST"
status: draft
---

## Epic 1 — Core Calculation Engine (Rust Crate)
**Goal:** Build `calcpad-engine` as a standalone Rust crate that powers all platforms. This is the foundation.

### Story 1.2: Parser & AST

As a CalcPad engine consumer,
I want tokens parsed into a typed abstract syntax tree respecting operator precedence and natural language constructs,
So that the interpreter can evaluate expressions with correct semantics.

**Acceptance Criteria:**

**Given** a token stream for `2 + 3 * 4`
**When** the parser builds the AST
**Then** multiplication binds tighter than addition
**And** the tree evaluates as `2 + (3 * 4)` yielding `14`

**Given** a token stream for `(2 + 3) * 4`
**When** the parser builds the AST
**Then** the parenthesized sub-expression is grouped as a single child node
**And** the tree evaluates as `(2 + 3) * 4` yielding `20`

**Given** a token stream for `2^3^2`
**When** the parser builds the AST
**Then** exponentiation is right-associative
**And** the tree evaluates as `2^(3^2)` yielding `512`

**Given** a token stream for `5kg + 200g`
**When** the parser builds the AST
**Then** it produces a `BinaryOp(Add)` node with unit-attached number children `5 kg` and `200 g`

**Given** a token stream for `$20 in euro - 5% discount`
**When** the parser builds the AST
**Then** it produces a `Conversion` node wrapping `$20` targeting `euro`, followed by a `PercentOp(Subtract, 5%)` node
**And** the percentage operation applies to the result of the conversion

**Given** a token stream for implicit multiplication such as `2(3+4)` or `3pi`
**When** the parser builds the AST
**Then** it inserts an implicit `Multiply` operator between the adjacent terms

**Given** a token stream for a natural language phrase such as `5 plus 3 times 2`
**When** the parser builds the AST
**Then** it applies the same operator precedence as symbolic operators
**And** the tree evaluates as `5 + (3 * 2)` yielding `11`

**Given** a token stream for a proportion expression such as `3 is to 6 as what is to 10?`
**When** the parser builds the AST
**Then** it produces a `Proportion` node with known values `3`, `6`, `10` and an unknown placeholder
**And** the unknown resolves to `5`

**Given** a token stream for a conditional expression such as `if x > 5 then x * 2`
**When** the parser builds the AST
**Then** it produces an `IfThen` node with a condition sub-tree and a result sub-tree
**And** an optional `else` branch is supported

**Given** a token stream containing a syntax error such as `5 + + 3`
**When** the parser attempts to build the AST
**Then** it returns a `ParseError` with a descriptive message and the span of the offending token
**And** it does not panic
