summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib.rs49
1 files changed, 38 insertions, 11 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 02972af..fe9a720 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -184,12 +184,17 @@ pub trait Parser<I: Input>: Sized {
}
}
+pub struct ParserIterState {
+ finished: bool,
+}
+
pub trait ParserIter<I: Input> {
type Item;
fn next<OM: Mode, EM: Mode>(
&self,
it: InputIter<I>,
+ state: &mut ParserIterState,
) -> Option<ParserResult<I, Self::Item, OM, EM>>;
fn many(self) -> impl Parser<I, Output = Vec<Self::Item>>
@@ -234,6 +239,7 @@ where
fn next<OM: Mode, EM: Mode>(
&self,
it: InputIter<I>,
+ _: &mut ParserIterState,
) -> Option<ParserResult<I, Self::Item, OM, EM>> {
if it.is_finished() {
None
@@ -262,8 +268,9 @@ where
fn next<OM: Mode, EM: Mode>(
&self,
it: InputIter<I>,
+ state: &mut ParserIterState,
) -> Option<ParserResult<I, Self::Item, OM, EM>> {
- if it.is_finished() {
+ if it.is_finished() || state.finished {
None
} else {
let (rest, output) = match self.parser.run::<OM, EM>(it) {
@@ -271,15 +278,16 @@ where
Err(rest) => return Some(Err(rest)),
};
- let rest = match self.delimiter.check(rest.clone()) {
+ match self.delimiter.check(rest.clone()) {
Ok((rest, _)) => match self.parser.check(rest.clone()) {
- Ok(_) => rest,
- Err(_) => return Some(Err(EM::bind(|| rest))),
+ Ok(_) => Some(Ok((rest, output))),
+ Err(_) => Some(Err(EM::bind(|| rest))),
},
- _ => rest,
- };
-
- Some(Ok((rest, output)))
+ _ => {
+ state.finished = true;
+ Some(Ok((rest, output)))
+ }
+ }
}
}
}
@@ -300,6 +308,7 @@ where
fn next<OM: Mode, EM: Mode>(
&self,
it: InputIter<I>,
+ _: &mut ParserIterState,
) -> Option<ParserResult<I, Self::Item, OM, EM>> {
if it.is_finished() {
None
@@ -340,9 +349,10 @@ where
) -> ParserResult<I, Self::Output, OM, EM> {
let mut outputs = OM::bind(|| Vec::new());
let mut i = 0;
+ let mut state = ParserIterState { finished: false };
while !it.is_finished() {
- it = match self.parser.next::<OM, EM>(it.clone()) {
+ it = match self.parser.next::<OM, EM>(it.clone(), &mut state) {
Some(Ok((rest, output))) => {
outputs = OM::combine(outputs, output, |mut acc, e| {
acc.push(e);
@@ -384,9 +394,10 @@ where
mut it: InputIter<I>,
) -> ParserResult<I, Self::Output, OM, EM> {
let mut outputs = OM::bind(|| Vec::new());
+ let mut state = ParserIterState { finished: false };
for _ in 0..self.count {
- it = match self.parser.next::<OM, EM>(it.clone()) {
+ it = match self.parser.next::<OM, EM>(it.clone(), &mut state) {
Some(Ok((rest, output))) => {
outputs = OM::combine(outputs, output, |mut acc, e| {
acc.push(e);
@@ -418,9 +429,10 @@ where
mut it: InputIter<I>,
) -> ParserResult<I, Self::Output, OM, EM> {
let mut outputs = OM::bind(|| Vec::new());
+ let mut state = ParserIterState { finished: false };
while !it.is_finished() {
- it = match self.parser.next::<OM, EM>(it.clone()) {
+ it = match self.parser.next::<OM, EM>(it.clone(), &mut state) {
Some(Ok((rest, output))) => {
outputs = OM::combine(outputs, output, |mut acc, e| {
acc.push(e);
@@ -922,6 +934,7 @@ where
fn next<OM: Mode, EM: Mode>(
&self,
mut it: InputIter<I>,
+ _: &mut ParserIterState,
) -> Option<ParserResult<I, Self::Item, OM, EM>> {
while !it.is_finished() {
it = match self.parser.run::<OM, EM>(it.clone()) {
@@ -1107,6 +1120,20 @@ mod test {
}
#[test]
+ fn test_separated_by_with_adjacent_p() {
+ let input = "p_p_pp_p";
+ let it = InputIter::new(input);
+
+ assert!(
+ tag("p")
+ .separated_by(tag("_"))
+ .at_least(1)
+ .check_finished(it)
+ .is_err()
+ );
+ }
+
+ #[test]
fn test_separated_by_with_trailing_without_trailing() {
let input = "1.0";
let it = InputIter::new(input);