Separated by
This commit is contained in:
parent
d624a54fb0
commit
5705876477
@ -49,15 +49,16 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delimited_by<D, O2>(self, delimiter: D) -> DelimitedBy<'a, I, O>
|
pub fn separated_by<D, O2>(self, delimiter: D, allow_trailing: bool) -> SeparatedBy<'a, I, O>
|
||||||
where
|
where
|
||||||
D: Parser<I, O2, I> + 'a,
|
D: Parser<I, O2, I> + 'a,
|
||||||
O2: 'a,
|
O2: 'a,
|
||||||
I: 'a,
|
I: 'a,
|
||||||
{
|
{
|
||||||
DelimitedBy {
|
SeparatedBy {
|
||||||
inner_repeated: self,
|
inner_repeated: self,
|
||||||
delimiter: BoxedParser::new(delimiter.to(())),
|
delimiter: BoxedParser::new(delimiter.to(())),
|
||||||
|
allow_trailing,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,21 +95,24 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DelimitedBy<'a, I, O>
|
pub struct SeparatedBy<'a, I, O>
|
||||||
where
|
where
|
||||||
I: Clone,
|
I: Clone,
|
||||||
{
|
{
|
||||||
inner_repeated: Repeated<'a, I, O>,
|
inner_repeated: Repeated<'a, I, O>,
|
||||||
delimiter: BoxedParser<'a, I, (), I>,
|
delimiter: BoxedParser<'a, I, (), I>,
|
||||||
|
allow_trailing: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, I, O> Parser<I, Vec<O>, I> for DelimitedBy<'a, I, O>
|
impl<'a, I, O> Parser<I, Vec<O>, I> for SeparatedBy<'a, I, O>
|
||||||
where
|
where
|
||||||
I: Clone + 'a,
|
I: Clone + 'a,
|
||||||
{
|
{
|
||||||
fn parse(&self, input: I) -> ParseResult<I, Vec<O>, I> {
|
fn parse(&self, input: I) -> ParseResult<I, Vec<O>, I> {
|
||||||
let at_least = self.inner_repeated.at_least.unwrap_or(0);
|
let at_least = self.inner_repeated.at_least.unwrap_or(0);
|
||||||
let at_most = self.inner_repeated.at_most.unwrap_or(u16::MAX);
|
let at_most = self.inner_repeated.at_most.unwrap_or(u16::MAX);
|
||||||
|
let parser = &self.inner_repeated.inner_parser;
|
||||||
|
let delimiter = &self.delimiter;
|
||||||
|
|
||||||
if at_most == 0 {
|
if at_most == 0 {
|
||||||
return Ok((vec![], input));
|
return Ok((vec![], input));
|
||||||
@ -116,20 +120,51 @@ where
|
|||||||
|
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
let mut count: u16 = 0;
|
let mut count: u16 = 0;
|
||||||
let mut further_input = input.clone();
|
let mut further_input;
|
||||||
|
|
||||||
|
match parser.parse(input.clone()) {
|
||||||
|
Ok((item, rest)) => {
|
||||||
|
results.push(item);
|
||||||
|
further_input = rest;
|
||||||
|
}
|
||||||
|
Err(_e) => {
|
||||||
|
if at_least > 0 {
|
||||||
|
return Err(input);
|
||||||
|
} else {
|
||||||
|
return Ok((vec![], input));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match delimiter.parse(further_input.clone()) {
|
||||||
|
Ok(((), rest)) => {
|
||||||
|
further_input = rest;
|
||||||
|
}
|
||||||
|
Err(_e) => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match parser.parse(further_input.clone()) {
|
||||||
|
Ok((item, rest)) => {
|
||||||
|
results.push(item);
|
||||||
|
further_input = rest;
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
Err(_e) if self.allow_trailing => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while let Ok((item, rest)) = self
|
|
||||||
.inner_repeated
|
|
||||||
.inner_parser
|
|
||||||
.parse(further_input.clone())
|
|
||||||
{
|
|
||||||
results.push(item);
|
|
||||||
further_input = rest;
|
|
||||||
count += 1;
|
|
||||||
if count >= at_most {
|
if count >= at_most {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if count < at_least {
|
if count < at_least {
|
||||||
return Err(input);
|
return Err(input);
|
||||||
}
|
}
|
||||||
@ -175,4 +210,15 @@ mod tests {
|
|||||||
assert_eq!(output.len(), 1);
|
assert_eq!(output.len(), 1);
|
||||||
assert_eq!(rest, "ecks");
|
assert_eq!(rest, "ecks");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_separated_by() {
|
||||||
|
let p = repeated(literal("garb").to(20))
|
||||||
|
.separated_by(repeated(literal(" ")).at_least(1), false);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
p.parse("garb garb garb garb").unwrap(),
|
||||||
|
(vec![20, 20, 20, 20], "")
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user