# `Yarnspinnex.Parser.Body`
[🔗](https://github.com/atavistock/yarnspinnex/blob/main/lib/yarnspinnex/parser/body.ex#L1)

Parses the lines inside one Yarn node (between `---` and `===`) into a tree of statements
consumed by `Yarnspinnex.Interpreter`. Every statement and option ends with the source line it
came from; consecutive `->` options are folded into one `{:options, ...}` statement.

# `branch`

```elixir
@type branch() :: {Yarnspinnex.Parser.Expression.ast(), [statement()]}
```

# `line`

```elixir
@type line() :: pos_integer()
```

The 1-based source line a statement was parsed from.

# `option`

```elixir
@type option() ::
  {:option, [part()], Yarnspinnex.Parser.Expression.ast() | nil, [statement()],
   tags(), line()}
```

# `opts`

```elixir
@type opts() :: %{
  calls: %{optional(String.t()) =&gt; non_neg_integer()},
  context: MapSet.t(String.t())
}
```

What the compiler validates each expression against: known calls and context-owned names.

# `part`

```elixir
@type part() :: {:text, String.t()} | {:expr, Yarnspinnex.Parser.Expression.ast()}
```

One piece of a line or option label: literal text or an interpolated `{expression}`.

# `source_line`

```elixir
@type source_line() :: {String.t(), pos_integer()}
```

A raw source line paired with its 1-based line number.

# `statement`

```elixir
@type statement() ::
  {:line, String.t() | nil, [part()], tags(), line()}
  | {:options, [option()], line()}
  | {:set, String.t(), Yarnspinnex.Parser.Expression.ast(), line()}
  | {:declare, String.t(), Yarnspinnex.Parser.Expression.ast(), line()}
  | {:jump, String.t(), line()}
  | {:stop, line()}
  | {:if, [branch()], [statement()], line()}
  | {:command, String.t(), [Yarnspinnex.Parser.Expression.ast()], line()}
```

# `tags`

```elixir
@type tags() :: [String.t()]
```

The `#tags` written after a line or option, without their `#`.

# `parse`

```elixir
@spec parse([source_line()], opts()) :: [statement()]
```

Parses a node body's source lines into statements, raising `CompileError` on bad structure.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
