Is there a better way to represent an abstract syntax tree?

That's basically how rustc's own internals look. Depending on your use cases when working with the AST you might want to swap in reference counted types rather than Box, but that's basically it.