# `Otera.Parser`
[🔗](https://github.com/georgeguimaraes/otera/blob/v0.1.0/lib/otera/parser.ex#L1)

Parses the tokens of `Otera.Lexer` into an abstract syntax tree, with the grammar of the Python Jinja2 parser.

The tree is a list of nodes. Nodes are tuples, so that the evaluator can pattern match on them.

Statements:

  * `{:text, string}` and `{:output, expr}`
  * `{:if, [{test, body}], else_body}`
  * `{:for, target, iter, filter_or_nil, body, else_body, recursive?}`
  * `{:set, target, expr}` and `{:set_block, target, filter_or_nil, body}`
  * `{:macro, name, params, body, special_names}` and `{:call_block, call, params, body, special_names}`
  * `{:filter_block, filter, body}`, `{:with, [{target, expr}], body}` and `{:generation, body}`
  * `:break` and `:continue`

Expressions:

  * `{:const, value}`, `{:name, name}`, `{:list, items}`, `{:tuple, items}` and `{:dict, [{key, value}]}`
  * `{:getattr, expr, name}`, `{:getitem, expr, key}` and `{:slice, start, stop, step}` as a key
  * `{:call, callee, args, kwargs}`, `{:filter, name, expr, args, kwargs, line}` and `{:test, name, expr, args, kwargs, line}`, where `args` has expressions and `{:unpack, expr}` for `*expr`, and `kwargs` has `{name, expr}` and `{:unpack, expr}` for `**expr`
  * `{:not, expr}`, `{:neg, expr}`, `{:pos, expr}`, `{:and, left, right}` and `{:or, left, right}`
  * `{:binop, op, left, right}` with op `:add`, `:sub`, `:mul`, `:div`, `:floordiv`, `:mod` or `:pow`
  * `{:concat, exprs}`, `{:compare, expr, [{op, expr}]}` and `{:cond, test, then, else}`
  * `{:ns_ref, name, attr}` as an assignment target

A filter of a filter block or a set block has `nil` as its innermost expression. An inline `if` without `else` gets an undefined value as its `else`. `params` of a macro is a list of `{name, default_or_nil}`, and `special_names` lists which of `caller`, `varargs` and `kwargs` the body uses.

As in Jinja2, an unknown filter or test is a syntax error, except inside an `if` block or an inline `if`, where it fails only when the template uses it.

# `parse`

```elixir
@spec parse([Otera.Lexer.token()], keyword()) :: [tuple() | atom()]
```

Returns the syntax tree of `tokens`. Raises `Otera.SyntaxError`.

Options: `:filters` and `:tests`, the names of the custom filters and tests besides the builtin ones.

---

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