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
//! Token and syntax-node definitions for the Praxis language.
//!
//! Per §14.1 of the design, this crate owns the token kinds and the lossless
//! syntax tree node kinds. The tree is [`rowan`]-backed (ADR-003): this crate
//! contributes the [`SyntaxKind`] vocabulary, the [`PraxisLanguage`] tag that
//! binds it to rowan, and the [`SyntaxNode`]/[`SyntaxToken`]/[`SyntaxElement`]
//! type aliases.
//!
//! The modules:
//! - [`kind`] — the single `SyntaxKind` enum (tokens, trivia, tree nodes).
//! - [`ident`] — the one identifier character class (§4.1).
//! - [`interp`] — the one rule for where a `"…"` literal ends and where its
//! interpolation holes are (§8.1, ADR-147), shared by the lexer's pre-scan
//! and its resume path.
//! - [`literal`] — the one text-literal decoder (§4.3).
//! - [`numeric`] — the one digit-separator rule for numeric literals (§4.3).
//! - [`template`] — the one rule for where a backtick template ends (§7.2,
//! D10), shared by the lexer and the input parser's template scanner.
//! - [`language`] — the rowan `Language` impl and node aliases.
//! - [`span_bridge`] — `Span` ↔ `rowan::TextRange` conversions (the only place
//! the two offset worlds meet; Praxis `Span` stays the diagnostic source of
//! truth).
//!
//! [`SyntaxNode`]: language::SyntaxNode
pub use SyntaxKind;
pub use ;
use Span;
/// How deeply backtick templates may nest inside each other's captures (D10).
///
/// A capture body is a full parser expression, so `` `{g:choice(A: `{x:int}`)}` ``
/// is one template containing another — which makes the lexer's template run
/// and the input parser's `scan_template` mutually recursive with the file's
/// own text. Both must refuse deep nesting rather than overflow the stack, and
/// they must refuse it at the *same* depth or one of them accepts what the
/// other cannot read. It lives here because `praxis-syntax` is the crate they
/// both already depend on.
///
/// The bound is far above anything a person writes.
pub const MAX_TEMPLATE_NESTING: usize = 32;
/// How deeply `"…"` literals may nest inside each other's interpolation holes
/// (§8.1, ADR-147).
///
/// A hole holds a full expression, so `"{f("{y}")}"` is one literal containing
/// another and [`interp::text_end`] is recursive with the file's own text. The
/// bound is what keeps adversarial input off the stack.
///
/// Unlike [`MAX_TEMPLATE_NESTING`], reaching this bound does not change what a
/// delimiter *means* — it refuses to enter, and the literal is reported as
/// unterminated. That difference is deliberate: the lexer's resume path only
/// ever runs for a literal the pre-scan proved closes, so a bound that answered
/// "closed, measured differently" would put the two on different rules at
/// exactly the depth nobody writes.
pub const MAX_INTERPOLATION_NESTING: usize = 32;
/// A token the lexer emits before it is folded into the lossless tree: its kind,
/// the source span it covers, and whether a line break sits in front of it.
///
/// The parser consumes these into a `rowan::GreenNode`; the spans are kept so
/// diagnostics can point at lexer-level locations (§6).