public final class BlockScopeDetector extends Object
Pp2TokenStream, the lexical block
nesting depth and the kind of block it sits directly inside
(parenthesised group or BEGIN ... END block).
Traversal uses an explicit ArrayDeque of open frames — never
recursion — so a 2000-deep nested input cannot StackOverflowError
(CLAUDE.md "CRITICAL: Iterative Traversal"; plan §10.1, §13/R3). The whole
pass is a single left-to-right walk: O(n) time, O(maxDepth) stack space.
The detector does not mutate any Pp2Token, its roles, or the
wrapped TSourceToken. It returns a BlockScopeDetector.BlockScopeResult side
structure indexed by token position (consistent with S18's match list).
S19 is not one of the designated role-annotator stages (S9/S21/S33), so it
deliberately keeps its output off the token.
An opener (( or BEGIN) and its matching closer
() or END) both report the enclosing depth; tokens
strictly between them report enclosing depth + 1. A token's
BlockKind is the kind of the frame it belongs to at that depth
(BlockKind.NONE at depth 0).
BEGIN pushes a BlockKind.BEGIN_END frame. An unqualified
END (not immediately followed by IF/LOOP/WHILE/REPEAT/FOR/CASE)
pops the top BEGIN_END frame. Qualified ends (END IF, etc.)
close inner constructs that this detector does not track, so they do not pop
the block frame — mirroring StatementBoundaryDetector. CASE
blocks are out of S19 scope (handled by the S27 layout rules); mixing a bare
CASE ... END inside a BEGIN block is a known limitation.
Plan reference: §7.3/S19, §7.4/S19, §10.1, §13/R3.
| Modifier and Type | Class and Description |
|---|---|
static class |
BlockScopeDetector.BlockScope
An immutable detected block span.
|
static class |
BlockScopeDetector.BlockScopeResult
Per-token block depth + kind, plus the list of detected scopes.
|
| Constructor and Description |
|---|
BlockScopeDetector() |
| Modifier and Type | Method and Description |
|---|---|
BlockScopeDetector.BlockScopeResult |
detect(Pp2TokenStream stream)
Annotate block depth + kind for every token in
stream. |
public BlockScopeDetector()
public BlockScopeDetector.BlockScopeResult detect(Pp2TokenStream stream)
stream.stream - the token stream; must not be nullBlockScopeDetector.BlockScopeResult indexed by token position; never nullNullPointerException - if stream is null