use super::{Expression, ParseState, ParseResult};
macro_rules! or( ( $( $ex:expr ),* ) => (
&base::Or::new( &[ $( $ex ),* ] ) ); );
pub struct Or<'a> {
exprs: &'a [&'a (Expression + 'a)]
}
impl<'b> Or<'b> {
pub fn new<'a>( exprs: &'a [&Expression] ) -> Or<'a> {
Or { exprs: exprs }
}
}
impl<'b> Expression for Or<'b> {
fn apply<'a>( &self, parse_state: &ParseState<'a> ) ->
Option< ParseResult<'a> > {
for expr in self.exprs.iter() {
match expr.apply( parse_state ) {
result @ Some( _ ) => return result,
_ => ()
}
}
None
}
}
#[cfg(test)]
mod tests {
use base;
use base::{Node, ParseResult, Expression, Data};
#[test]
fn Or_Match_FirstExpr() {
let orig_state = input_state!( "a" );
match or!( 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!( parse_state, orig_state.advanceTo( 1 ) );
}
_ => panic!( "No match." )
}
}
#[test]
fn Or_Match_SecondExpr() {
let orig_state = input_state!( "a" );
match or!( lit!( "b" ), lit!( "a" ) ).apply( &orig_state ) {
Some( ParseResult{ nodes, parse_state } ) => {
assert_eq!( nodes[ 0 ],
Node::withoutName( 0, 1, Data( b"a" ) ) );
assert_eq!( parse_state, orig_state.advanceTo( 1 ) );
}
_ => panic!( "No match." )
}
}
#[test]
fn Or_Match_FirstExprIfBoth() {
let orig_state = input_state!( "a" );
match or!( lit!( "a" ), lit!( "a" ) ).apply( &orig_state ) {
Some( ParseResult{ nodes, parse_state } ) => {
assert_eq!( nodes[ 0 ],
Node::withoutName( 0, 1, Data( b"a" ) ) );
assert_eq!( parse_state, orig_state.advanceTo( 1 ) );
}
_ => panic!( "No match." )
}
}
#[test]
fn Or_NoMatch() {
assert!( or!( lit!( "b" ), lit!( "c" ) ).apply(
&input_state!( "a" ) ).is_none() );
}
}