Today I ported gnome-class from version 0.11 of the syn crate to
version 0.12. syn
is a somewhat esoteric crate that you use to
parse Rust code... from a stream of tokens... from within the
implementation of a procedural macro. Gnome-class implements a
mini-language inside your own Rust code, and so it needs to parse
Rust!
The API of syn
has changed a lot, which is kind of a pain in the
ass — but the new API seems on the road to stabilization, and is nicer
indeed.
Here is a quick list of things I had to change in gnome-class to
upgrade its version of syn
.
There is no extern crate synom
anymore. You can use syn::synom
now.
extern crate synom; -> use syn::synom;
SynomBuffer
is now TokenBuffer
:
synom::SynomBuffer -> syn::buffer:TokenBuffer
PResult
, the result of Synom::parse()
, now has the tuple's
arguments reversed:
- pub type PResult<'a, O> = Result<(Cursor<'a>, O), ParseError>;
+ pub type PResult<'a, O> = Result<(O, Cursor<'a>), ParseError>;
// therefore:
impl Synom for MyThing { ... }
let x = MyThing::parse(...).unwrap().1; -> let x = MyThing::parse(...).unwrap().0;
The language tokens like synom::tokens::Amp
, and keywords like
synom::tokens::Type
, are easier to use now. There is a Token!
macro which you can use in type definitions, instead of having to
remember the particular name of each token type:
synom::tokens::Amp -> Token!(&)
synom::tokens::For -> Token!(for)
And for the corresponding values when matching:
syn!(tokens::Colon) -> punct!(:)
syn!(tokens::Type) -> keyword!(type)
And to instantiate them for quoting/spanning:
- tokens::Comma::default().to_tokens(tokens);
+ Token!(,)([Span::def_site()]).to_tokens(tokens);
(OK, that one wasn't nicer after all.)
To the get string for an Ident
:
ident.sym.as_str() -> ident.as_ref()
There is no Delimited
anymore; instead there is a Punctuated
struct. My diff has this:
- inputs: parens!(call!(Delimited::<MyThing, tokens::Comma>::parse_terminated)) >>
+ inputs: parens!(syn!(Punctuated<MyThing, Token!(,)>)) >>
There is no syn::Mutability
anymore; now it's an Option<token>
, so
basically
syn::Mutability -> Option<Token![mut]>
which I guess lets you refer to the span of the original mut
token
if you need.
Some things changed names:
TypeTup { tys, .. } -> TypeTuple { elems, .. }
PatIdent { -> PatIdent {
mode: BindingMode(Mutability) by_ref: Option<Token!(ref)>,
mutability: Option<Token![mut]>,
ident: Ident, ident: Ident,
subpat: ..., subpat: Option<(Token![@], Box<Pat>)>,
at_token: ..., }
}
TypeParen.ty -> TypeParen.elem (and others like this, too)
(I don't know everything that changed names; gnome-class doesn't use all the syn types yet; these are just the ones I've run into.)
This new syn
is much better at acknowledging the fine points of
macro hygiene. The examples directory is particularly instructive;
it shows how to properly span generated code vs. original code, so
compiler error messages are nice. I need to write something about
macro hygiene at some point.