# Writing parsers using `syn` and `nom` parser combinators
# Writing parsers using `syn` and `nom` parser combinators
## Parsing a LitInt and rejecting invalid range
Disclaimer, I'm NOT the author of the `syn` and `nom` parsing frameworks, so no guarantee the text accurately conveys their idiomatic use.
The same goes for all references to supporting crates and references to other Rust libraries, crates and the language itself, so use material at own risk :)
## Parsing a `LitInt` and rejecting invalid range
As a simple example let us start out with `mylit!(LitInt)`, where
As a simple example let us start out with `mylit!(LitInt)`, where
`LitInt` should be an intereger literal `x` in the range `10 <= x < 100`.
`LitInt` should be an intereger literal `x` in the range `10 <= x < 100`.
...
@@ -71,7 +75,6 @@ The procedural macro is defined in the `src/lib.rs` as follows.
...
@@ -71,7 +75,6 @@ The procedural macro is defined in the `src/lib.rs` as follows.
#![feature(proc_macro)]
#![feature(proc_macro)]
externcrateproc_macro;
externcrateproc_macro;
#[macro_use]
externcratequote;
externcratequote;
#[macro_use]
#[macro_use]
externcratesyn;
externcratesyn;
...
@@ -114,12 +117,14 @@ pub trait Synom: Sized {
...
@@ -114,12 +117,14 @@ pub trait Synom: Sized {
The `do_parse!` processes a combination of parsers (in this case just a single one),
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
`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.)
`syn!(LitInt)`, and used in the right hand `MyLit {val}`. (As usal in Rust a struct can be constructed 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`).
The `syn!` macro simly applies the parser for `LitInt` (requires a type that 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.)
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.)
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
Besides just parsing an `IntLit` (that is a `u64`), we want at compile time to ensure that it is in a given range, (between 10 and 100 in this example), and report a sensible error message for illegal usage.
\ No newline at end of file
The error message is presented as a `TokenStream` throught the `.emit()` function.