Skip to content

Commit 48bff70

Browse files
committed
merge: 'feature-empty-collection-item' => dev
2 parents b259733 + 7fd38af commit 48bff70

File tree

1 file changed

+141
-5
lines changed

1 file changed

+141
-5
lines changed

src/parser.rs

Lines changed: 141 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ pub enum ParsingError {
6969
RangeEndLimitExpected(usize),
7070
/// It is not Text, but expected to be a text.
7171
ExpectedText(usize),
72-
/// Comma is used invalid, e.g. `{,A,B}` or `{A,}` or `{,}`
72+
/// Comma is used invalid, e.g. `{A..,B}` or `{A,..B}`
7373
InvalidCommaUsage(usize),
7474
/// Extra Closing Brace, e.g. `{} }`
7575
ExtraCBra(usize),
@@ -370,15 +370,24 @@ fn collection(tokens: &Vec<Token>) -> Result<Node, ParsingError> {
370370
// start and end positions.
371371
let mut pos = (0_usize, 0_usize);
372372
// in the seperate function, we're dealing with `{}}` or `{{}`, no need to deal with it here.
373-
let mut count = (0, 0);
373+
// count of OBra (`{`), CBra (`}`), and the seperator (`,`).
374+
let mut count = (0_usize, 0_usize, 0_usize);
374375
let mut collections: Vec<Vec<Token>> = vec![];
375376
let mut current = vec![];
376377
for token in tokens {
377378
match token {
378379
Token::Comma(s) if count.0 == (count.1 + 1) => {
380+
// increase the seperator count by 1.
381+
count.2 += 1;
379382
if current.is_empty() {
380-
return Err(ParsingError::InvalidCommaUsage(*s));
383+
match collections.len() == 0 {
384+
true => current.push(Token::Text(String::new(), s.clone())),
385+
// The previous token was comma.
386+
false => current.push(Token::Text(String::new(), s - 1)),
387+
}
381388
}
389+
// we dealt with if it's empty.
390+
// so it can't be empty.
382391
collections.push(current.clone());
383392
current.clear();
384393
}
@@ -404,9 +413,10 @@ fn collection(tokens: &Vec<Token>) -> Result<Node, ParsingError> {
404413
_ => current.push(token.clone()),
405414
}
406415
}
407-
if !current.is_empty() {
408-
collections.push(current);
416+
if current.is_empty() && collections.len() == count.2 {
417+
current.push(Token::Text(String::new(), pos.1 - 1));
409418
}
419+
collections.push(current);
410420
match collections.len() {
411421
0 => Err(ParsingError::NothingInBraces(pos.0)),
412422
1 => {
@@ -456,6 +466,132 @@ mod tests {
456466
use super::*;
457467
use crate::tokenizer::Token;
458468

469+
#[test]
470+
fn test_feature_empty_collection_item_at_the_end() {
471+
assert_eq!(
472+
parse(&vec![
473+
Token::Text("A".into(), 0),
474+
Token::OBra(1),
475+
Token::Text("B".into(), 2),
476+
Token::Comma(3),
477+
Token::Text("C".into(), 4),
478+
Token::Comma(5),
479+
Token::CBra(6),
480+
]),
481+
Ok(Node::BraceExpansion {
482+
prefix: Some(Box::new(Node::Text {
483+
message: "A".into(),
484+
start: 0
485+
})),
486+
inside: Some(Box::new(Node::Collection {
487+
items: vec![
488+
Node::Text {
489+
message: "B".into(),
490+
start: 2
491+
},
492+
Node::Text {
493+
message: "C".into(),
494+
start: 4
495+
},
496+
Node::Text {
497+
message: String::new(),
498+
start: 5
499+
},
500+
],
501+
start: 1,
502+
end: 6
503+
})),
504+
postfix: None,
505+
start: 0,
506+
end: 6
507+
})
508+
)
509+
}
510+
511+
#[test]
512+
fn test_feature_empty_collection_item_at_the_start() {
513+
assert_eq!(
514+
parse(&vec![
515+
Token::Text("A".into(), 0),
516+
Token::OBra(1),
517+
Token::Comma(2),
518+
Token::Text("B".into(), 3),
519+
Token::Comma(4),
520+
Token::Text("C".into(), 5),
521+
Token::CBra(6),
522+
]),
523+
Ok(Node::BraceExpansion {
524+
prefix: Some(Box::new(Node::Text {
525+
message: "A".into(),
526+
start: 0
527+
})),
528+
inside: Some(Box::new(Node::Collection {
529+
items: vec![
530+
Node::Text {
531+
message: String::new(),
532+
start: 2
533+
},
534+
Node::Text {
535+
message: "B".into(),
536+
start: 3
537+
},
538+
Node::Text {
539+
message: "C".into(),
540+
start: 5
541+
},
542+
],
543+
start: 1,
544+
end: 6
545+
})),
546+
postfix: None,
547+
start: 0,
548+
end: 6
549+
})
550+
)
551+
}
552+
553+
#[test]
554+
fn test_feature_empty_collection_item_in_the_middle() {
555+
assert_eq!(
556+
parse(&vec![
557+
Token::Text("A".into(), 0),
558+
Token::OBra(1),
559+
Token::Text("B".into(), 2),
560+
Token::Comma(3),
561+
Token::Comma(4),
562+
Token::Text("C".into(), 5),
563+
Token::CBra(6),
564+
]),
565+
Ok(Node::BraceExpansion {
566+
prefix: Some(Box::new(Node::Text {
567+
message: "A".into(),
568+
start: 0
569+
})),
570+
inside: Some(Box::new(Node::Collection {
571+
items: vec![
572+
Node::Text {
573+
message: "B".into(),
574+
start: 2
575+
},
576+
Node::Text {
577+
message: String::new(),
578+
start: 3
579+
},
580+
Node::Text {
581+
message: "C".into(),
582+
start: 5
583+
},
584+
],
585+
start: 1,
586+
end: 6
587+
})),
588+
postfix: None,
589+
start: 0,
590+
end: 6
591+
})
592+
)
593+
}
594+
459595
#[test]
460596
fn test_really_complex() {
461597
assert_eq!(

0 commit comments

Comments
 (0)