Move Item verification to be a method of TokenFmt.
This commit is contained in:
parent
d9513492fe
commit
56694d4fc8
|
@ -149,38 +149,6 @@ impl<'a, T: Keyword> Section<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Check whether a single Item matches a TokenFmt rule, with respect
|
||||
/// to its number of arguments.
|
||||
///
|
||||
/// TODO: Move this to rules?
|
||||
fn item_matches_fmt_args<'a, T: Keyword>(t: T, fmt: &TokenFmt<T>, item: &Item<'a>) -> Result<()> {
|
||||
let n_args = item.n_args();
|
||||
if let Some(max) = fmt.max_args {
|
||||
if n_args > max {
|
||||
return Err(Error::TooManyArguments(t.to_str(), item.pos()));
|
||||
}
|
||||
}
|
||||
if let Some(min) = fmt.min_args {
|
||||
if n_args < min {
|
||||
return Err(Error::TooFewArguments(t.to_str(), item.pos()));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check whether a single Item matches a TokenFmt rule, with respect
|
||||
/// to its object's presence and type.
|
||||
///
|
||||
/// TODO: Move this to rules?
|
||||
fn item_matches_fmt_obj<'a, T: Keyword>(t: T, fmt: &TokenFmt<T>, item: &Item<'a>) -> Result<()> {
|
||||
match (&fmt.obj, item.has_obj()) {
|
||||
(ObjKind::NoObj, true) => Err(Error::UnexpectedObject(t.to_str(), item.pos())),
|
||||
(ObjKind::RequireObj, false) => Err(Error::MissingObject(t.to_str(), item.pos())),
|
||||
(_, _) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Keyword> SectionRules<T> {
|
||||
/// Create a new SectionRules with no rules.
|
||||
///
|
||||
|
@ -265,8 +233,7 @@ impl<T: Keyword> SectionRules<T> {
|
|||
// The number is right. Check each individual item.
|
||||
for item in t.as_slice() {
|
||||
let tok = T::from_idx(idx).unwrap();
|
||||
item_matches_fmt_args(tok, rule, item)?;
|
||||
item_matches_fmt_obj(tok, rule, item)?;
|
||||
rule.check_item(tok, item)?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use crate::tokenize::Item;
|
||||
use crate::{Error, Result};
|
||||
use std::hash::Hash;
|
||||
|
||||
pub trait Keyword: Hash + Eq + PartialEq + Copy + Clone {
|
||||
|
@ -24,11 +26,49 @@ pub enum ObjKind {
|
|||
#[derive(Clone)]
|
||||
pub struct TokenFmt<T: Keyword> {
|
||||
pub kwd: T,
|
||||
pub min_args: Option<usize>,
|
||||
pub max_args: Option<usize>,
|
||||
min_args: Option<usize>,
|
||||
max_args: Option<usize>,
|
||||
pub required: bool,
|
||||
pub may_repeat: bool,
|
||||
pub obj: ObjKind,
|
||||
obj: ObjKind,
|
||||
}
|
||||
|
||||
impl<T: Keyword> TokenFmt<T> {
|
||||
/// Check whether a single Item matches this TokenFmt rule, with respect
|
||||
/// to its number of arguments.
|
||||
fn item_matches_args<'a>(&self, t: T, item: &Item<'a>) -> Result<()> {
|
||||
let n_args = item.n_args();
|
||||
if let Some(max) = self.max_args {
|
||||
if n_args > max {
|
||||
return Err(Error::TooManyArguments(t.to_str(), item.pos()));
|
||||
}
|
||||
}
|
||||
if let Some(min) = self.min_args {
|
||||
if n_args < min {
|
||||
return Err(Error::TooFewArguments(t.to_str(), item.pos()));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check whether a single Item matches a TokenFmt rule, with respect
|
||||
/// to its object's presence and type.
|
||||
///
|
||||
/// TODO: Move this to rules?
|
||||
fn item_matches_obj<'a>(&self, t: T, item: &Item<'a>) -> Result<()> {
|
||||
match (&self.obj, item.has_obj()) {
|
||||
(ObjKind::NoObj, true) => Err(Error::UnexpectedObject(t.to_str(), item.pos())),
|
||||
(ObjKind::RequireObj, false) => Err(Error::MissingObject(t.to_str(), item.pos())),
|
||||
(_, _) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Check whether a single item has the right number of arguments
|
||||
/// and object.
|
||||
pub fn check_item<'a>(&self, t: T, item: &Item<'a>) -> Result<()> {
|
||||
self.item_matches_args(t, item)?;
|
||||
self.item_matches_obj(t, item)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TokenFmtBuilder<T: Keyword>(TokenFmt<T>);
|
||||
|
|
Loading…
Reference in New Issue