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

wip

parent fd104dee
Branches
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