|
|
@ -28,88 +28,69 @@ use std::cmp::Reverse;
|
|
|
|
/// Panics when missing head or anchor.
|
|
|
|
/// Panics when missing head or anchor.
|
|
|
|
/// Panics when head come after head or anchor come after anchor.
|
|
|
|
/// Panics when head come after head or anchor come after anchor.
|
|
|
|
pub fn print(s: &str) -> (String, Selection) {
|
|
|
|
pub fn print(s: &str) -> (String, Selection) {
|
|
|
|
let mut primary = None;
|
|
|
|
let mut primary_idx = None;
|
|
|
|
let mut ranges = SmallVec::new();
|
|
|
|
let mut ranges = SmallVec::new();
|
|
|
|
let mut iter = s.chars().peekable();
|
|
|
|
let mut iter = s.chars().peekable();
|
|
|
|
let mut left = String::with_capacity(s.len());
|
|
|
|
let mut left = String::with_capacity(s.len());
|
|
|
|
|
|
|
|
|
|
|
|
'outer: while let Some(c) = iter.next() {
|
|
|
|
'outer: while let Some(c) = iter.next() {
|
|
|
|
let start = left.len();
|
|
|
|
let start = left.len();
|
|
|
|
if c == '#' {
|
|
|
|
|
|
|
|
if iter.next_if_eq(&'[').is_some() {
|
|
|
|
if c != '#' {
|
|
|
|
if primary.is_some() {
|
|
|
|
|
|
|
|
panic!("primary `#[` already appeared {left:?} {s:?}");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if iter.next_if_eq(&'|').is_some() {
|
|
|
|
|
|
|
|
while let Some(c) = iter.next() {
|
|
|
|
|
|
|
|
if c == ']' && iter.next_if_eq(&'#').is_some() {
|
|
|
|
|
|
|
|
primary = Some(ranges.len());
|
|
|
|
|
|
|
|
ranges.push(Range::new(left.len(), start));
|
|
|
|
|
|
|
|
continue 'outer;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
left.push(c);
|
|
|
|
left.push(c);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let (is_primary, close_pair) = match iter.next() {
|
|
|
|
|
|
|
|
Some('[') => (true, ']'),
|
|
|
|
|
|
|
|
Some('(') => (false, ')'),
|
|
|
|
|
|
|
|
Some(ch) => {
|
|
|
|
|
|
|
|
left.push(ch);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
None => break,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if is_primary && primary_idx.is_some() {
|
|
|
|
|
|
|
|
panic!("primary `#[` already appeared {left:?} {s:?}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
panic!("missing primary end `]#` {left:?} {s:?}");
|
|
|
|
|
|
|
|
} else {
|
|
|
|
let head_at_beg = iter.next_if_eq(&'|').is_some();
|
|
|
|
|
|
|
|
|
|
|
|
while let Some(c) = iter.next() {
|
|
|
|
while let Some(c) = iter.next() {
|
|
|
|
if c == '|' {
|
|
|
|
if !(c == close_pair && iter.peek() == Some(&'#')) {
|
|
|
|
if let Some(cc) = iter.next_if_eq(&']') {
|
|
|
|
|
|
|
|
if iter.next_if_eq(&'#').is_some() {
|
|
|
|
|
|
|
|
primary = Some(ranges.len());
|
|
|
|
|
|
|
|
ranges.push(Range::new(start, left.len()));
|
|
|
|
|
|
|
|
continue 'outer;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
left.push(c);
|
|
|
|
left.push(c);
|
|
|
|
left.push(cc);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if !head_at_beg {
|
|
|
|
|
|
|
|
let prev = left.pop().unwrap();
|
|
|
|
|
|
|
|
if prev != '|' {
|
|
|
|
|
|
|
|
left.push(prev);
|
|
|
|
left.push(c);
|
|
|
|
left.push(c);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
|
|
|
|
left.push(c);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
panic!("missing primary end `|]#` {left:?} {s:?}");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if iter.next_if_eq(&'(').is_some() {
|
|
|
|
|
|
|
|
if iter.next_if_eq(&'|').is_some() {
|
|
|
|
|
|
|
|
while let Some(c) = iter.next() {
|
|
|
|
|
|
|
|
if c == ')' && iter.next_if_eq(&'#').is_some() {
|
|
|
|
|
|
|
|
ranges.push(Range::new(left.len(), start));
|
|
|
|
|
|
|
|
continue 'outer;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
left.push(c);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
iter.next(); // skip "#"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if is_primary {
|
|
|
|
|
|
|
|
primary_idx = Some(ranges.len());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
panic!("missing end `)#` {left:?} {s:?}");
|
|
|
|
let (anchor, head) = match head_at_beg {
|
|
|
|
} else {
|
|
|
|
true => (left.len(), start),
|
|
|
|
while let Some(c) = iter.next() {
|
|
|
|
false => (start, left.len()),
|
|
|
|
if c == '|' {
|
|
|
|
};
|
|
|
|
if let Some(cc) = iter.next_if_eq(&')') {
|
|
|
|
ranges.push(Range::new(anchor, head));
|
|
|
|
if iter.next_if_eq(&'#').is_some() {
|
|
|
|
|
|
|
|
ranges.push(Range::new(start, left.len()));
|
|
|
|
|
|
|
|
continue 'outer;
|
|
|
|
continue 'outer;
|
|
|
|
} else {
|
|
|
|
|
|
|
|
left.push(c);
|
|
|
|
|
|
|
|
left.push(cc);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
left.push(c);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
left.push(c);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
panic!("missing end `|)#` {left:?} {s:?}");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
left.push(c);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if head_at_beg {
|
|
|
|
|
|
|
|
panic!("missing end `{close_pair}#` {left:?} {s:?}");
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
left.push(c);
|
|
|
|
panic!("missing end `|{close_pair}#` {left:?} {s:?}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let primary = match primary {
|
|
|
|
|
|
|
|
|
|
|
|
let primary = match primary_idx {
|
|
|
|
Some(i) => i,
|
|
|
|
Some(i) => i,
|
|
|
|
None => panic!("missing primary `#[|]#` {s:?}"),
|
|
|
|
None => panic!("missing primary `#[|]#` {s:?}"),
|
|
|
|
};
|
|
|
|
};
|
|
|
|