use super::{Token, TokenKind};
fn find_flat_pair(tokens: &[Token], from: usize) -> Option<(usize, usize, usize)> {
let mut open = None;
for i in from..tokens.len() {
match tokens[i].kind() {
TokenKind::LParen => open = Some(i),
TokenKind::RParen => {
if let Some(start) = open {
let left_count = tokens[..start].iter().rev().take_while(|t| t.kind() == TokenKind::LParen).count();
let right_count = tokens[i + 1..].iter().take_while(|t| t.kind() == TokenKind::RParen).count();
let extra = left_count.min(right_count);
return Some((start, i, extra));
}
}
_ => {}
}
}
None
}
pub(crate) fn reduce_single_rule_wrapping(tokens: &mut Vec<Token>) {
let mut i = 0;
while i < tokens.len() {
if let Some((left, right, consecutive)) = find_flat_pair(tokens, i) {
let content_len = right - left - 1;
let is_single_rule = content_len == 1 && matches!(tokens[left + 1].kind(), TokenKind::ConditionIndex(_));
let is_not_rule =
content_len == 2 && tokens[left + 1].kind() == TokenKind::Not && matches!(tokens[left + 2].kind(), TokenKind::ConditionIndex(_));
if is_single_rule || is_not_rule {
tokens.drain(right..=right + consecutive);
tokens.drain(left - consecutive..=left);
i = left - consecutive;
} else {
i = right + consecutive + 1;
}
} else {
break;
}
}
}
pub(crate) fn reduce_outermost_wrapping(tokens: &mut Vec<Token>) {
loop {
let len = tokens.len();
if len < 2 { return; }
if tokens[0].kind() != TokenKind::LParen { return; }
if tokens[len - 1].kind() != TokenKind::RParen { return; }
let mut depth = 0usize;
let mut spans_all = false;
for i in 0..len {
match tokens[i].kind() {
TokenKind::LParen => depth += 1,
TokenKind::RParen => {
depth -= 1;
if depth == 0 {
spans_all = i == len - 1;
break;
}
}
_ => {}
}
}
if !spans_all { return; }
tokens.remove(len - 1);
tokens.remove(0);
}
}
pub(crate) fn reduce_extra_wrapping(tokens: &mut Vec<Token>) {
let mut i = 0;
while i < tokens.len() {
if let Some((left, right, consecutive)) = find_flat_pair(tokens, i) {
if consecutive > 0 {
tokens.drain(right + 1..=right + consecutive); tokens.drain(left - consecutive..left); i = left - consecutive; } else {
i = right + 1; }
} else {
break;
}
}
}
pub(crate) fn reduce_parentheses(tokens: &mut Vec<Token>) {
loop {
let len = tokens.len();
reduce_single_rule_wrapping(tokens); reduce_outermost_wrapping(tokens); reduce_extra_wrapping(tokens); if tokens.len() == len {
break;
}
}
}