use std::fmt;
macro_rules! callback {
($parser:expr, $handler:expr, $context:expr, $callback:ident, $data:expr, $exec:expr) => ({
if $handler.$callback($data) {
$exec
}
exit_callback!($parser, $context);
});
($parser:expr, $handler:expr, $context:expr, $callback:ident, $exec:expr) => ({
if bs_slice_length!($context) > 0 {
if $handler.$callback(bs_slice!($context)) {
$exec
}
exit_callback!($parser, $context);
}
$exec
});
}
macro_rules! callback_eos_expr {
($parser:expr, $handler:expr, $context:expr, $callback:ident) => ({
callback!($parser, $handler, $context, $callback, {
exit_eos!($parser, $context);
});
});
}
macro_rules! callback_ignore_transition {
($parser:expr, $handler:expr, $context:expr, $callback:ident, $state:ident,
$state_function:ident) => ({
set_state!($parser, $state, $state_function);
if bs_slice_length!($context) > 1 {
if $handler.$callback(bs_slice_ignore!($context)) {
transition!($parser, $context);
}
exit_callback!($parser, $context);
}
transition!($parser, $context);
});
}
macro_rules! callback_transition {
($parser:expr, $handler:expr, $context:expr, $callback:ident, $data:expr, $state:ident,
$state_function:ident) => ({
set_state!($parser, $state, $state_function);
callback!($parser, $handler, $context, $callback, $data, {
transition!($parser, $context);
});
});
($parser:expr, $handler:expr, $context:expr, $callback:ident, $state:ident,
$state_function:ident) => ({
set_state!($parser, $state, $state_function);
callback!($parser, $handler, $context, $callback, {
transition!($parser, $context);
});
});
}
macro_rules! exit_callback {
($parser:expr, $context:expr, $state:ident, $state_function:ident) => ({
set_state!($parser, $state, $state_function);
return Ok(ParserValue::Exit(Success::Callback($context.stream_index)));
});
($parser:expr, $context:expr) => ({
return Ok(ParserValue::Exit(Success::Callback($context.stream_index)));
});
}
macro_rules! exit_eos {
($parser:expr, $context:expr) => ({
return Ok(ParserValue::Exit(Success::Eos($context.stream_index)));
});
}
macro_rules! exit_error {
($error:ident, $byte:expr) => ({
return Err(ParserError::$error($byte));
});
($error:ident) => ({
return Err(ParserError::$error);
});
}
macro_rules! exit_finished {
($parser:expr, $context:expr) => ({
return Ok(ParserValue::Exit(Success::Finished($context.stream_index)));
});
}
macro_rules! exit_if_eos {
($parser:expr, $context:expr) => ({
bs_available!($context) > 0 || exit_eos!($parser, $context);
});
}
macro_rules! get_state {
($parser:expr) => ({
$parser.state
})
}
macro_rules! set_state {
($parser:expr, $state:ident, $state_function:ident) => ({
$parser.state = ParserState::$state;
$parser.state_function = Parser::$state_function;
});
}
macro_rules! transition {
($parser:expr, $context:expr, $state:ident, $state_function:ident) => ({
set_state!($parser, $state, $state_function);
bs_mark!($context, $context.stream_index);
return Ok(ParserValue::Continue);
});
($parser:expr, $context:expr) => ({
bs_mark!($context, $context.stream_index);
return Ok(ParserValue::Continue);
});
}
macro_rules! transition_no_remark {
($parser:expr, $context:expr, $state:ident, $state_function:ident) => ({
set_state!($parser, $state, $state_function);
return Ok(ParserValue::Continue);
});
}
pub enum ParserValue {
Continue,
Exit(Success)
}
#[derive(Clone,Copy,PartialEq)]
pub enum Success {
Callback(usize),
Eos(usize),
Finished(usize)
}
impl fmt::Debug for Success {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match *self {
Success::Callback(length) => {
write!(formatter, "Success::Callback({})", length)
},
Success::Eos(length) => {
write!(formatter, "Success::Eos({})", length)
},
Success::Finished(length) => {
write!(formatter, "Success::Finished({})", length)
}
}
}
}
impl fmt::Display for Success {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match *self {
Success::Callback(length) => {
write!(formatter, "{}", length)
},
Success::Eos(length) => {
write!(formatter, "{}", length)
},
Success::Finished(length) => {
write!(formatter, "{}", length)
}
}
}
}