1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//! Diverts, tunnel calls, and return (charter §11 — all kept/respelled
//! verbatim from ink except the tunnel-return redirect, which trades
//! ink's `->-> x` for the self-explanatory `return -> x`).
use crate;
use Parser;
/// `-> target` (a plain divert) or `-> place ->` (a tunnel call — divert,
/// target, divert, charter §11: "KEPT as `-> place ->`"). Statement
/// position — a line whose first token is `->` (`block::body_line`'s
/// dispatch) — also consumes a trailing `NEWLINE`, since this call owns
/// terminating the line. [`divert_in_content`] is the content-position
/// sibling (N-1): a `->` that follows prose on the same content run
/// shares this exact node-shape logic but must NOT consume the `NEWLINE`
/// itself — the enclosing content loop (`content::content_items_until`)
/// owns line termination there, same as it does for any other content
/// item.
pub
/// The content-position sibling of [`divert_or_tunnel`] (N-1, charter
/// §11: diverts are "kept verbatim" including in content position — the
/// Fogg exhibit spells `* [The wager.] -> know_about_wager` this way).
/// Called from `content::content_items_until` whenever a `DIVERT` token
/// appears anywhere in a content run, not only as a line's first token.
/// Does not consume a trailing `NEWLINE` — see the doc comment above.
pub
/// Shared grammar: `-> target` or `-> place ->`, without any
/// newline-consumption policy (that differs by call site, see
/// [`divert_or_tunnel`]/[`divert_in_content`]'s doc comments).
/// `END` / `DONE` / a `PATH` (optionally followed by a call-style
/// `(args)`) — the divert target. Charter §11 keeps `-> knot(args)`
/// verbatim from ink, so a `PATH` target routes through the same
/// call-capable grammar as an ordinary expression path
/// (`expr::path_or_call`'s `(args)` half, `expr::arg_list`) rather than
/// stopping at the bare path — otherwise the parenthesized args parse
/// with zero errors but orphan into an unrelated sibling `CONTENT_LINE`
/// (bug #1196). The `ARG_LIST`, when present, is captured as a direct
/// sibling of `PATH` under `DIVERT_TARGET` rather than wrapped in a
/// `CALL_EXPR` — a divert target is not itself an expression, and the
/// existing `PATH` shape is a public accessor contract
/// (`DivertTarget::path`) shared by every call site (`divert_or_tunnel`,
/// `tunnel_call`, `return_stmt`'s redirect).
/// `return` — leave this container. `return -> x` is the tunnel-return
/// respelling (charter §11): pop the obligation, then go. `return <expr>` —
/// a value-carrying return at prose-body/content-ground position (issue
/// #1973) — mirrors the code-ground `return expr?;` value grammar
/// (`parser/stmt.rs::return_stmt`), minus the `;` terminator content-ground
/// statements never carry; `ast::ReturnStmt::value()` is the one accessor
/// shared by both grammars (see `SyntaxKind::RETURN_STMT`'s doc).
///
/// The `DIVERT` check runs first and unconditionally wins: `return -> x`
/// must always parse as `RETURN_REDIRECT`, never fall into the value
/// branch (there is no divert-target *expression* atom in `expr.rs` for it
/// to collide with today, but the ordering is the actual guarantee, not an
/// accident of the current grammar — pinned by a test).
///
/// [`at_return_value_start`] is a **positive** "does this look like an
/// expression" probe rather than a negative "not a terminator" one
/// (Finding #5's prose-collision discipline, `parser/decl.rs`'s doc) — this
/// function is reached from both `block::body_line` (terminated by
/// `NEWLINE`/`EOF`) and `family::colon_body_line` (terminated by
/// `R_BRACE`/an `else`-arm boundary, e.g. `{if cond: return else: …}`), and
/// enumerating every terminator risks missing one and mis-swallowing it as
/// a spurious "expected an expression" error where a bare `return` was
/// actually intended.
pub
/// Whether the current token can start [`return_stmt`]'s optional value
/// expression. Mirrors `expr::atom`'s atom first-set plus
/// `expr::is_prefix_op`'s prefix operators, deliberately **excluding**
/// `L_BRACE` and `PIPE`: a block-expression or lambda-literal return value
/// has no corpus motivation at this position, and `L_BRACE` specifically
/// would collide with the brace-family constructs (`{if …}`/`{?…}`/
/// alternations) that can otherwise immediately follow a bare `return` on
/// the same content line.