Expand description
Where a backtick template ends — one answer, for both scanners (D10).
Two hand-written scanners have to agree about the extent of a
`…` run: praxis-parser’s lexer, which turns it into one
BacktickTemplate token, and praxis-input-parser’s template scanner,
which re-reads that token’s interior and has to find the same nested
templates and the same closing backtick inside it. Two implementations of
one rule drift, so there is one implementation.
praxis-syntax is the crate below both (it is where crate::ident and
crate::numeric already live for exactly this reason), so the rule lives
here and is called twice rather than written twice.
§The rule
Scanning starts just past the opening backtick and, until the run closes:
\hides the next scalar, so an escaped backtick cannot terminate a run.{opens a capture and}closes one — this is the only thing brace depth is for."inside a capture opens a string literal, which is skipped whole:one_of("{"),sep("}", int)andone_of("“)all hold delimiters that are text, not structure. Outside a capture a quote is ordinary literal text (``He said “hi” {x:int}` ``), which is why the rule is conditioned on depth rather than applied everywhere.`closes the run at capture depth 0. Inside a capture it opens a template of its own, because a capture body is a full parser expression (D10) and`{g:choice(A: `{x:int}`)}`is one template containing another.
At most MAX_TEMPLATE_NESTING templates may nest; past that a backtick
simply closes, so adversarial input lands on the ordinary
unterminated/unexpected-token paths rather than on the stack. There is one
bound because there is one function.
§The quoted-run and scalar primitives
A "…" inside a capture and a '…' inside an interpolation hole are the
same scan with a different closing byte, and both scanners have to step over
a multi-byte scalar the same way. [quoted_run] and [skip_scalar]
therefore live in this module — the lower of the two — and crate::interp
calls them instead of keeping a second copy, for the same reason this module
exists at all.
Enums§
- Template
End - Where a
`…`run ends.
Functions§
- string_
end - Find the end of the
"…"literal whose opening quote is atopen, returning the index just past the closing quote, orNoneif the text ends first.\hides the next scalar, so"\""is one literal. - template_
end - Find the end of the backtick template whose opening backtick is at
open.