Documentation
¶
Overview ¶
Package cspan implements the brace-counting body-span scanner shared by internal/langspec (the primary parsing pass) and internal/resolve (the FFI bridging resolver). It is a leaf package with zero non-stdlib imports, which is exactly why it exists: internal/index imports internal/langspec, and internal/resolve sits below internal/index, so resolve cannot import langspec without a cycle (langspec -> index -> resolve -> langspec). Both layers can import this package instead.
Span (and its helpers SpanFrom, Delta) is T-0053's shipped semantics, moved verbatim — not reimplemented — from internal/langspec's former braceSpan/braceSpanFrom/braceDelta. Before T-0054, internal/resolve/ffi.go carried its own independent, unfixed, K&R-only copy of this same logic (ffiBraceSpan); T-0054 deletes that copy and switches ffi.go to this package instead, alongside internal/langspec/langspec.go doing the same (see docs/validation-ddnet.md's "## ffi re-validation" section for why that duplication was the last blocker on ddnet's cpp:->c: FFI crossing).
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Delta ¶
Delta returns the net brace-depth change contributed by line ('{' is +1, '}' is -1) and whether the line contains at least one '{'.
func KeywordSpan ¶
KeywordSpan finds the end of the body opened for the def hit on lines[start], for end-terminated languages (Lua's function/if/for/do .. end, Ruby's def/class/module .. end, and similar) that have no braces for Span to count. Depth is counted the same way as Span/Delta, just with regexes standing in for '{'/'}': open and close are matched against each line with FindAllString, and each match increments/decrements depth respectively — nested and repeated keywords on one line (e.g. an interleaved "if x then y end" one-liner) are handled by the same net-sum logic Delta already uses for braces, no special-casing required.
The def line (lines[start]) is where counting begins: it "counts as one open when it matches open" exactly as Span's K&R case treats the def line's own '{' — if open doesn't match lines[start] at all, there is nothing to close and ok is false without touching any other line. From there, depth is tracked forward exactly like SpanFrom: the first line where it returns to <= 0 is the end, single-line bodies (open and close both on lines[start]) included. If depth never returns to <= 0 before the source ends, ok is false.
func Span ¶
Span finds the end of the body opened for the def hit on lines[start]. K&R style (the def line itself opens '{') is handled first and is byte-identical to the pre-T-0053 behavior: depth-count forward ('{' +1, '}' -1) until depth returns to <= 0, single-line bodies included.
When the def line has no '{' at all, T-0053 extends the search rather than bailing immediately:
- a def line ending in ';' is a prototype/forward-declaration (or a function-like macro whose expansion has no body) — no body exists, ok is false, and no forward line is ever touched (same early-exit invariant as before this extension).
- a def line ending in ',' or '(' is a multi-line parameter list — the header is scanned forward to the line containing the closing ')', and the brace search (same-line or Allman) resumes from there.
- otherwise the def is Allman style: the opening '{' lives on one of the next few source lines instead of the def line itself (ddnet's universal C/C++ brace placement). Span looks ahead over subsequent lines, skipping blank lines and pure '//'-comment lines, for at most 3 lines; if the first significant line found begins with '{' (ignoring leading whitespace), depth tracking starts there. Anything else — including finding no significant line within the 3-line window — means no body, ok is false, and (as with the K&R no-brace case) lines beyond the window are never touched, so a braceless def can never wander into the next, unrelated def's lines.
Types ¶
This section is empty.