use super::prelude::*;
use crate::parsing::Parser;
use std::fmt::{self, Debug};
mod mapping;
pub mod impls;
pub use self::mapping::get_rules_for_token;
#[derive(Copy, Clone)]
pub struct Rule {
name: &'static str,
position: LineRequirement,
try_consume_fn: TryConsumeFn,
}
impl Rule {
#[inline]
pub fn name(self) -> &'static str {
self.name
}
#[inline]
pub fn try_consume<'r, 't>(
self,
parser: &mut Parser<'r, 't>,
) -> ParseResult<'r, 't, Elements<'t>> {
debug!("Trying to consume for parse rule {}", self.name);
match self.position {
LineRequirement::Any => (),
LineRequirement::StartOfLine => {
if !parser.start_of_line() {
return Err(parser.make_err(ParseErrorKind::NotStartOfLine));
}
}
}
let parser_state = parser.get_mutable_state();
let mut sub_parser = parser.clone_with_rule(self);
let result = (self.try_consume_fn)(&mut sub_parser);
match result {
Ok(ref output) => {
output.check_partials(parser)?;
parser.update(&sub_parser);
}
Err(_) => parser.reset_mutable_state(parser_state),
}
result
}
}
impl Debug for Rule {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Rule")
.field("name", &self.name)
.field("position", &self.position)
.field("try_consume_fn", &(self.try_consume_fn as *const ()))
.finish()
}
}
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum LineRequirement {
Any,
StartOfLine,
}
pub type TryConsumeFn = for<'p, 'r, 't> fn(
parser: &'p mut Parser<'r, 't>,
) -> ParseResult<'r, 't, Elements<'t>>;