1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
//! Method macro combinators //! //! These macros make parsers as methods of structs //! and that can take methods of structs to call //! as parsers. //! //! There is a trick to make them easier to assemble, //! combinators are defined like this: //! //! ```ignore //! macro_rules! tag ( //! ($i:expr, $inp: expr) => ( //! { //! ... //! } //! ); //! ); //! ``` //! //! But when used as methods in other combinators, are used //! like this: //! //! ```ignore //! method!(my_function<Parser<'a> >, self, tag!("abcd")); //! ``` //! //! Internally, other combinators will rewrite //! that call to pass the input as second argument: //! //! ```ignore //! macro_rules! method ( //! ($name:ident<$a:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => ( //! fn $name( $self_: $a, i: &[u8] ) -> IResult<&[u8], &[u8]> { //! $submac!(i, $($args)*) //! } //! ); //! ); //! ``` //! //! The `method!` macro is similar to the `named!` macro in the macros module. //! While `named!` will create a parser function, `method!` will create a parser //! method on the struct it is defined in. //! //! Compared to the `named!` macro there are a few differences in how they are //! invoked. A `method!` invocation always has to have the type of `self` //! declared and it can't be a reference due to Rust's borrow lifetime //! restrictions: //! //! ```ignore //! // -`self`'s type- //! method!(method_name< Parser<'a> >, ...); //! ``` //! `self`'s type always comes first. //! The next difference is you have to input the self struct. Due to Rust's //! macro hygiene the macro can't declare it on it's own. //! //! ```ignore //! // -self- //! method!(method_name<Parser<'a>, &'a str, &'a str>, self, ...); //! ``` //! When making a parsing struct with parsing methods, due to the static borrow //! checker,calling any parsing methods on self (or any other parsing struct) //! will cause self to be moved for the rest of the method.To get around this //! restriction all self is moved into the called method and then the called //! method will return self to the caller. //! //! To call a method on self you need to use the `call_m!` macro. For example: //! //! ```ignore //! struct<'a> Parser<'a> { //! parsed: &'a str, //! } //! impl<'a> Parser<'a> { //! // Constructor omitted for brevity //! method!(take4<Parser<'a>, &'a str, &'a str>, self, take!(4)); //! method!(caller<Parser<'a>, &'a str, &'a str>, self, call_m!(self.take4)); //! } //! ``` //! More complicated combinations still mostly look the same as their `named!` //! counterparts: //! //! ```ignore //! method!(pub simple_chain<&mut Parser<'a>, &'a str, &'a str>, self, //! do_parse!( //! call_m!(self.tag_abc) >> //! call_m!(self.tag_def) >> //! call_m!(self.tag_ghi) >> //! last: map!(call_m!(self.simple_peek), |parsed| sb.parsed = parsed) >> //! (last) //! ) //! ); //! ``` //! The three additions to method definitions to remember are: //! 1. Specify `self`'s type //! 2. Pass `self` to the macro //! 4. Call parser methods using the `call_m!` macro. #[macro_use] extern crate nom; pub mod lib { pub use nom::{IResult, ErrorKind}; } pub use self::methods::*; #[macro_use] mod methods;