use super::{Expression, ParseState, ParseResult};
macro_rules! seq( ( $( $ex:expr ),* ) => (
&base::Sequence::new( &[ $( $ex ),* ] ) ); );
pub struct Sequence<'a> {
exprs: &'a [&'a (Expression + 'a)]
}
impl<'b> Sequence<'b> {
pub fn new<'a>( exprs: &'a [&Expression] ) -> Sequence<'a> {
Sequence { exprs: exprs }
}
}
impl<'b> Expression for Sequence<'b> {
fn apply<'a>( &self, parse_state: &ParseState<'a> ) ->
Option< ParseResult<'a> > {
let mut final_result = ParseResult::fromParseState( *parse_state );
for expr in self.exprs.iter() {
match expr.apply( &final_result.parse_state ) {
Some( result ) => {
final_result.parse_state = result.parse_state;
final_result.nodes.extend( result.nodes.into_iter() );
}
_ => return None
}
}
Some( final_result )
}
}
#[cfg(test)]
mod tests {
use base;
use base::{Node, ParseResult, Expression, Data};
#[test]
fn Sequence_Match() {
let orig_state = input_state!( "ab" );
match seq!( lit!( "a" ), lit!( "b" ) ).apply( &orig_state ) {
Some( ParseResult{ nodes, parse_state } ) => {
assert_eq!( nodes[ 0 ],
Node::withoutName( 0, 1, Data( b"a" ) ) );
assert_eq!( nodes[ 1 ],
Node::withoutName( 1, 2, Data( b"b" ) ) );
assert_eq!( parse_state, orig_state.advanceTo( 2 ) );
}
_ => panic!( "No match." )
}
}
#[test]
fn Sequence_NoMatch() {
assert!( seq!( lit!( "a" ), lit!( "b" ) ).apply(
&input_state!( "aa" ) ).is_none() );
}
}