Phosphorus15
Phosphorus15

Reputation: 134

How to parse Rust code without using procedural macros?

I am writing an analyzer which needs an abstract syntax tree (AST) or control flow graph (CFG) of Rust code. It seems impossible for me to do this without implementing a parser by myself.

I've noticed some crates such as syn and quote, but they don't work without using procedural macros and creating a totally unnecessary project structure. I've found that there's a crate called syntex_syntax which meets my requirements, but it is no longer maintained and panics when some code with newer syntax is given.

Is there any way of parsing Rust code directly: read from an arbitrary external *.rs file and parse it using syn or quote just like syntex_syntax did?

Upvotes: 5

Views: 2043

Answers (1)

Lukas Kalbertodt
Lukas Kalbertodt

Reputation: 88916

syn is a Rust parser and is not only for procedural macros. Take a look at the "functions" section of the documentation. There you will find these functions (as of syn 0.15):

  • fn parse<T: Parse>(tokens: proc_macro::TokenStream) -> Result<T>: this is what you would use in a procedural macro.
  • fn parse2<T: Parse>(tokens: proc_macro2::TokenStream) -> Result<T>: the same, but with the TokenStream from the proc_macro2 crate.
  • fn parse_str<T: Parse>(s: &str) -> Result<T>: parsing from a simple string. No TokenStreams required.
  • fn parse_file(content: &str) -> Result<File>: Very similar to parse_str, but some convenient differences. See docs for more information.

You can use parse_str or parse_file to parse Rust code from outside of procedural macros.

A few additional notes:

  • quote is not needed in your case. This crate is just used to easily create TokenStreams; it's not required for parsing.
  • In case you are just interested in parsing the tokens, you can use proc_macro2 outside of a procedural macro, too!
  • syntex_syntax is indeed deprecated and shouldn't be used anymore. Just thinking about how it was used makes me shudder :P

Upvotes: 9

Related Questions