Skip to content
Snippets Groups Projects
Commit 0b808a4b authored by Per's avatar Per
Browse files

wip

parent fd104dee
No related branches found
No related tags found
No related merge requests found
...@@ -95,19 +95,6 @@ impl Synom for MyLit { ...@@ -95,19 +95,6 @@ impl Synom for MyLit {
)); ));
} }
#[proc_macro]
pub fn mylit(input: TokenStream) -> TokenStream {
let v: MyLit = syn::parse(input).unwrap();
let value: u32 = v.val.value() as u32;
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())
}
``` ```
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.)
``` rust
fn parse(i: ::buffer::Cursor) -> ::synom::PResult<Self> {
match <LitInt as ::synom::Synom>::parse(i) {
::std::result::Result::Err(err) => ::std::result::Result::Err(err),
::std::result::Result::Ok((o, i)) => {
let val = o;
::std::result::Result::Ok(((MyLit { val }), i))
}
}
}
```
(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]
pub fn mylit(input: TokenStream) -> TokenStream {
let v: MyLit = syn::parse(input).unwrap();
let value: u32 = v.val.value() as u32;
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
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment