.error(format!("expected literal 10 <= x < 100, got {}",value,))
.emit();
}
From::from(v.val.into_tokens())
}
```
```
So `MyLit` here is a structure for holding the parsed token.
So `MyLit` here is a structure for holding the parsed token.
...
@@ -125,5 +112,44 @@ pub trait Synom: Sized {
...
@@ -125,5 +112,44 @@ pub trait Synom: Sized {
}
}
```
```
The `do_parse!` processes a combination of parsers (in this case just a single one),
`val: syn!(LitInt) >> (MyLit { val })`, where `val` will be assigned the result of
`syn!(LitInt)`, and used in the right hand `MyLit {val}`. (As usal in Rust a struct can be contructed from varibles with matching field names, to make it more succint.)
The `syn!` macro simly applies the parser for `LitInt` (requres a type itself implementing `Synom`).
So now we have broken down the trait implmentation, we can see the expanded code. (As we see, the use of macros greately facilitates writing parsers.)
(On a side note, we did not implment `description` for `MyLit`, here we can rely on a default implemntation given by the `syn` crate.)
The parser is made accissible to the user by a procedural macro as follows.
``` rust
#[proc_macro]
pubfnmylit(input:TokenStream)->TokenStream{
letv:MyLit=syn::parse(input).unwrap();
letvalue:u32=v.val.value()asu32;
if!(10<=value&&value<100){
v.val
.span()
.unstable()
.error(format!("expected literal 10 <= x < 100, got {}",value,))
.emit();
}
From::from(v.val.into_tokens())
}
```
In order for `syn::parse` to be able to parse a `TokenStream` for
Besides just parsing an `IntLit` (that is a `u64`), we want at compile time to ensure that it is in a given range, say between 10 and 100, and report a sensible error message for illegal usage. The