Reuse parser scratch buffers (#26798)
## Summary
Use scratch buffers instead of allocating new `Vec`s and shrinking them
when constructing the AST node. While this doesn't remove the need for
copying the elements, it reduces the allocations within our parser
(`shrink_to_fit` often needs to allocate a new buffer and move all
elements). One shared scratch buffer per node type is sufficient,
because our parser is recursive (more nested parse rule always push to
the end, and parse function drain from the end as they complete).
## Performance
Very consistent perf improvement
## Codspeed memory regression
This can cause the parser's peak memory to increase, because we retain
the scratch buffer allocation after parsing a clause completed. However,
that memory is only temporary and released as soon as the parser
completes. Most project-level memory reports show a memory reduction.
It's only specific parser benchmarks that show a memory increase