Closed dashed closed 8 years ago
macro_rules! make_parser_struct {
($name: ident) => {
pub struct $name<T> {
phantom: PhantomData<T>,
}
impl<T> $name<T> {
fn new() -> Self {
$name {
phantom: PhantomData
}
}
}
}
}
make_parser_struct!(LineTerminator);
impl<I> Parser for LineTerminator<I> where I: Stream<Item=char> {
type Input = I;
type Output = char;
fn parse_stream(&mut self, input: I) -> ParseResult<Self::Output, Self::Input> {
crlf()
.or(char('\r'))
.or(char('\n'))
.parse_stream(input)
}
}
make_parser_struct
macroimpl<I> Parser for LineTerminator<I> where I: Stream<Item=$input_item_type> {
type Input = I;
type Output = $output_type;
fn parse_stream(&mut self, $input_var: I) -> ParseResult<Self::Output, Self::Input> {
$content
}
}
// macro'd by
make_parser!(
LineTerminator($input_var: $input_item_type) -> $output_type {
$content
}
);
macro_rules! make_parser {
// base case
() => {};
($name:ident ($input_var:ident : $input_item_type:ty) -> $output_type:ty { $($tmpl:tt)* } $($rest:tt)*) => {
pub struct $name<T> {
phantom: PhantomData<T>,
}
impl<T> $name<T> {
pub fn new() -> Self {
$name {
phantom: PhantomData
}
}
}
impl<I> Parser for $name<I> where I: Stream<Item=$input_item_type> {
type Input = I;
type Output = $output_type;
fn parse_stream(&mut self, $input_var: I) -> ParseResult<Self::Output, Self::Input> {
$($tmpl)*
}
}
make_parser!($($rest)*);
};
($name:ident ($input_var:ident : $input_item_type:ty , $($field:ident : &$typ:ty),*)
-> $output_type:ty { $($tmpl:tt)* } $($rest:tt)*) => {
pub struct $name<'a, T> {
phantom: PhantomData<T>,
$( $field: &'a $typ),*
}
impl<'a, T> $name<'a, T> {
pub fn new($($field: &'a $typ),*) -> Self {
$name {
phantom: PhantomData,
$( $field: $field),*
}
}
}
impl<'a, I> Parser for $name<'a, I> where I: Stream<Item=$input_item_type> {
type Input = I;
type Output = $output_type;
fn parse_stream(&mut self, $input_var: I) -> ParseResult<Self::Output, Self::Input> {
let &mut $name { phantom, $($field),* } = self;
$($tmpl)*
}
}
make_parser!($($rest)*);
};
}
make_parser!(
LineTerminator(input: char) -> char {
crlf()
.or(char('\r'))
.or(char('\n'))
.parse_stream(input)
}
);
make_parser!(
Comment(input: char) -> char {
char('#')
.skip(LineTerminator::new())
.parse_stream(input)
}
);
make_parser!(
LineTerminator(input: char) -> char {
crlf()
.or(char('\r'))
.or(char('\n'))
.parse_stream(input)
}
Comment(input: char) -> char {
char('#')
.skip(LineTerminator::new())
.parse_stream(input)
}
);
make_parser!(
LineTerminator(input: char, is_clr: &bool) -> char {
if !is_clr {
return char('\r')
.or(char('\n'))
.parse_stream(input);
}
crlf()
.or(char('\r'))
.or(char('\n'))
.parse_stream(input)
}
);
// usage ...
make_parser!(
Comment(input: char) -> char {
char('#')
.skip(LineTerminator::new(&true))
.parse_stream(input)
}
);
version 1