Source code is surprisingly compact.
As for one data point on how much better it can be, here is Zig's own parser, parsing Zig's own parser:
# Source bytes: 139 KiB
# Tokens: 24646 (120 KiB)
# AST Nodes: 10998 (140 KiB)
Each token is 5 bytes which is pretty minimal (1 byte tag + 4 byte file offset). AST Nodes are also encoded compactly and non-uniformly, in this case coming out to roughly 13 bytes each. Despite these minimal encodings, the parse tree comes out to almost 2x the size of the source file in this case. 2x is a lot better than 50x though.
Source: zig ast-check -t lib/std/zig/Parse.zig | head -n7