<!-- Generated from sources/appendices/v1/appendix-grammar-flow.aeon; do not edit. -->

<a id="appendix-grammar-flow-cards"></a>
# Appendix — Grammar Flow Cards

Scope: parser-context flow illustrations for AEON Core v1.

This appendix illustrates the legal flow through AEON Core v1 syntax by parser context. It is not a replacement for the AEON Core v1 Structure and Syntax Reference; when this appendix and the structure syntax reference conflict, the structure syntax reference wins.

The key framing is:

- the lexer produces tokens without deciding most structural legality;
- parser contexts decide what may legally follow;
- recovery may produce partial syntax trees, but a parse with errors is not a successful parse unless a recovery surface explicitly says so.

<a id="document-flow"></a>
## 1. Document Flow

```ebnf
Document ::= [HeaderBindings] BodyBinding {Separator BodyBinding} EOF
Separator ::= "," | Newline
```

*AEON document grammar*

Rules:

- shorthand header bindings and structured header bindings are recognized only in the initial header block;
- after the first body binding, `aeon:mode = "strict"` is parsed as an ordinary typed binding unless another rule rejects it;
- top-level binding keys in one document must be unique after key decoding;
- duplicate top-level keys fail closed with `DUPLICATE_KEY`.

<a id="binding-head-flow"></a>
## 2. Binding Head Flow

Canonical binding head order is:

```aeon
key\identity\@{attributes}:type = value
```

```ebnf
Binding ::= Key [Identity] [Attributes] [TypeAnnotation] "=" Value
```

*AEON binding-head grammar*

Legal:

```aeon
a = 1
a\id\ = 1
a@{meta=1} = 1
a:int = 1
a\id\@{meta=1}:int = 1
```

Illegal:

```aeon
a@{meta=1}\id\:int = 1
a:int@{meta=1} = 1
a@{x=1}@{y=2} = 1
```

<a id="attribute-entry-flow"></a>
## 3. Attribute Entry Flow

Attribute entries reuse the binding-head shape, but live inside `@{...}`:

```aeon
a@{entry@{nested=1}:type = value} = payload
```

```ebnf
AttributeEntry ::= Key [Identity] [NestedAttributes] [TypeAnnotation] "=" Value
```

*AEON attribute-entry grammar*

Rules:

- duplicate keys inside one attribute map fail closed with `DUPLICATE_KEY`;
- one nested attribute head is legal when `max_attribute_depth` allows it;
- repeated heads on one attribute entry are illegal, even when depth is raised;
- `key\id\@{...}:type = value` is legal; `key:type@{...} = value` and `key@{...}\id\:type = value` are not.

Examples:

```aeon
a@{x=1, y=2} = 3
a@{x@{origin="core"} = 2} = 1
```

Rejected:

```aeon
a@{x=1, x=2} = 3
a@{x@{y=1}@{z=2} = 3} = 4
a@{x:int@{y=1} = 2} = 3
```

<a id="type-annotation-flow"></a>
## 4. Type Annotation Flow

```ebnf
TypeAnnotation ::= ":" TypeName [GenericArguments] [DatatypeClarifiers]
GenericArguments ::= "<" Type {"," Type} ">"
DatatypeClarifiers ::= "[" Value {"," Value} "]"
```

*AEON type-annotation grammar*

Rules:

- binding and attribute-entry type annotations must be followed by `=`;
- anonymous typed values use `:type = value` only in list, tuple, and node-child contexts;
- node-head inline datatypes are syntactically narrower than ordinary binding types and accept generic arguments only for `:node<T>`;
- generic and separator depth policies are enforced by parser options.

<a id="value-dispatch"></a>
## 5. Value Dispatch

```ebnf
Value ::= Object | List | Tuple | Node | Reference | Literal | TrimtickString
```

*AEON value grammar*

Value starts include:

| Start | Value family |
| :--- | :--- |
| `{` | object |
| `[` | list |
| `(` | tuple |
| `<` | node |
| `~`, `~>` | clone or pointer reference |
| string token | string |
| number-like token | number, infinity, NaN |
| `!` form | null literal |
| boolean/toggle keyword | boolean or toggle |
| `#`, `%`, `$`, `^` literal token | hex, radix, encoding, separator literal |
| trimtick opener | trimtick string |

*AEON value-start dispatch*

An identifier by itself is not a value. Use a reference marker for reference values.

<a id="container-flow-matrix"></a>
## 6. Container Flow Matrix

| Context | Entry form | Separators | Close | Attribute rule |
| :--- | :--- | :--- | :--- | :--- |
| Document | `Binding` | comma or newline | EOF | attributes attach to binding head |
| Object | `Binding` | comma or newline | `}` | attributes attach to member binding head |
| List | `Value` or `TypedValue` | comma or newline | `]` | no floating binding head |
| Tuple | `Value` or `TypedValue` | comma or newline | `)` | no floating binding head |
| Node children | `Value` or `TypedValue` | comma or newline | `)` then `>` | node head attributes appear before children |
| Attribute map | `AttributeEntry` | comma or newline | `}` | nested entry head allowed only once and policy-limited |

*AEON container parsing contexts*

Object attachment examples:

```aeon
x@{meta=1} = { k = 2 }
x = { k@{meta=1} = 2 }
```

Rejected floating form:

```aeon
x = { @{meta=1} k = 2 }
```

<a id="node-head-flow"></a>
## 7. Node Head Flow

```ebnf
Node ::= "<" Tag [Attributes] [NodeType] (">" | "(" [Value {Separator Value}] ")" ">")
```

*AEON node grammar*

Rules:

- node heads may have one attribute block;
- repeated node head attribute blocks are illegal;
- child-bearing nodes require the final `>` after the child list closes.

<a id="reference-path-flow"></a>
## 8. Reference Path Flow

```ebnf
Reference ::= ("~" | "~>") (Root | Member | BracketMember) {ReferenceSegment}
ReferenceSegment ::= "." Member | "[" IndexOrMember "]" | "@" Attribute
```

*AEON reference-path grammar*

Rules:

- `$` is the explicit root;
- dot traversal and bracket traversal address data namespace segments;
- `.@.key` and `.@.["key"]` address attribute namespace segments;
- empty quoted member segments and empty quoted attribute segments are invalid.

<a id="comments-and-trivia-flow"></a>
## 9. Comments And Trivia Flow

Comments are not values, bindings, or separators by themselves.

| Surface | Lexer/parser role | Grammar effect |
| :--- | :--- | :--- |
| spaces/tabs | layout trivia | never separate two same-line bindings by themselves |
| newline | structural token when enabled | separator only in contexts that consume newline |
| line comment | comment/trivia | ends at newline; surrounding grammar still decides separation |
| block comment | comment/trivia | may span newlines; does not become a value |
| structured comment channel | annotation side channel | attachment rules do not redefine syntax |

*Comment and trivia grammar effects*

Examples:

```aeon
a = 1 // comment
b = 2
```

The newline after the line comment separates the bindings; the comment itself does not.

```aeon
a = 1 /* comment */ b = 2
```

Plain spaces plus a block comment do not create a document binding separator.

<a id="ambiguity-checklist"></a>
## 10. Ambiguity Checklist

| Ambiguity | Legal form | Illegal form | Expected diagnostic |
| :--- | :--- | :--- | :--- |
| duplicate top-level key | distinct top-level keys | `a=1\na=2` | `DUPLICATE_KEY` |
| duplicate object member key | distinct member keys | `x={a=1,a=2}` | `DUPLICATE_KEY` |
| duplicate attribute key | distinct attribute keys | `a@{x=1,x=2}=3` | `DUPLICATE_KEY` |
| object vs member attribute | `x@{m=1}={k=2}` or `x={k@{m=1}=2}` | `x={@{m=1} k=2}` | `SYNTAX_ERROR` |
| nested vs repeated attribute head | `a@{x@{y=1}=2}=3` | `a@{x@{y=1}@{z=2}=3}=4` | `SYNTAX_ERROR` |
| binding attribute order | `a@{x=1}:int=2` | `a:int@{x=1}=2` | `SYNTAX_ERROR` |
| node attribute order | `<tag@{x=1}:node>` | `<tag:node@{x=1}>` | `SYNTAX_ERROR` |
| typed anonymous context | `a=[:int=1]` | `a=:int=1` | `SYNTAX_ERROR` |
| space-only separation | `a=1\nb=2` or `a=1,b=2` | `a=1 b=2` | `SYNTAX_ERROR` |

*Table 1: AEON grammar ambiguities and expected diagnostics*

These examples should remain mirrored by implementation tests or CTS cases when the behavior is normative.

---

## Related documents

- [AEON v1 Structure Syntax Reference](./aeon-core-v1-structure-syntax.md)
- [AEON Specification v1](./aeon-core-v1.md)
- [Appendix — Whitespace Boundaries](./appendix-whitespace-boundaries-v1.md)
