# Parsing
> **Accounting track:** to use the parser in an application, see
> [Accounting: Getting started](accounting/getting_started.md) and
> [Parsing (Livebook)](livebook/parsing.livemd). This page documents the
> library implementation.
`Beancount.Parser` is a native regex-lexer and line-grammar parser that turns
`.bean` text into the same typed directive structs you build with the public
`Beancount.*` constructors.
## Public API
```elixir
# Parse text
{:ok, directives} = Beancount.parse_text(bean_text)
# Parse a file
{:ok, directives} = Beancount.parse_file("ledger.bean")
# Lists pass through unchanged
{:ok, directives} = Beancount.parse(directives)
# Raise on failure
directives = Beancount.parse!(bean_text)
```
Parse failures return `{:error, %Beancount.Parser.Error{}}` with `line`,
`column`, `message`, and optional `token` fields - never a bare
`FunctionClauseError`.
## Grammar coverage
The parser covers the full Beancount surface syntax used in production ledgers:
- dated directives: `open`, `close`, `commodity`, `balance`, `price`, `event`,
`note`, `document`, `pad`, `query`, `custom`
- undated directives: `include`, `option`, `plugin`, `pushtag`, `poptag`
- transactions with flags, payee, narration, tags, links, metadata, and postings
(amount elision, cost specs `{…}`, and price annotations `@` / `@@`)
- comments (`;`), metadata (`key: value`), and multi-line metadata blocks
New directive structs (`Query`, `Plugin`, `PushTag`, `PopTag`) implement the
`Beancount.Directive` protocol so they round-trip through `Beancount.render/1`.
## Round-trip contract
For every golden fixture:
```elixir
expected = File.read!("expected.bean")
{:ok, directives} = Beancount.parse_text(expected)
assert Beancount.render(directives) == expected
```
Property tests also assert `parse(render(ledger))` recovers equivalent text for
generated ledgers from `Beancount.Property.ledger/0`.
## Relationship to engines
`Beancount.Engine.Elixir` uses the parser internally for `check/1` and canned
reports in `query/2`. `Beancount.Engine.CLI` shells out to `bean-check` /
`bean-query` and remains the **default** engine for validation and arbitrary
BQL. Native parity on the canned report set is proven; swap engines via
`config :beancount_ex, engine: Beancount.Engine.Elixir` when you want to run
without Python tooling.
Parsing is independent of validation semantics: the parser produces structs;
engines decide what is valid.