use crate::error::ErrorCode;
use crate::parser::PErr;
pub(crate) fn check(chars: &[char]) -> Result<(), PErr> {
let n = chars.len();
let mut i = 0;
let mut in_class = 0usize;
while i < n {
let c = chars[i];
match c {
'\\' => {
let next = chars.get(i + 1).copied();
match next {
Some('Q') => {
i += 2;
while i < n && !(chars[i] == '\\' && chars.get(i + 1) == Some(&'E')) {
i += 1;
}
i += 2;
continue;
}
Some('b') if in_class > 0 => {
return Err(PErr::new(
ErrorCode::P004,
i,
"\\b is not allowed inside a Java character class",
))
}
Some('b') if chars.get(i + 2) == Some(&'{') => {
return Err(PErr::new(
ErrorCode::U007,
i,
"\\b{...} boundaries are not supported",
))
}
Some('0') if !matches!(chars.get(i + 2), Some('0'..='7')) => {
return Err(PErr::new(
ErrorCode::P004,
i,
"\\0 must be followed by an octal digit in Java",
))
}
_ => {}
}
i += 2;
continue;
}
'[' => {
if in_class > 0 {
return Err(PErr::new(
ErrorCode::U007,
i,
"nested character classes (union) are not yet supported for Java",
));
}
in_class = 1;
i += 1;
if chars.get(i) == Some(&'^') {
i += 1;
}
continue;
}
']' if in_class > 0 => in_class = 0,
'&' if in_class > 0 && chars.get(i + 1) == Some(&'&') => {
return Err(PErr::new(
ErrorCode::U007,
i,
"class intersection && is not yet supported for Java",
))
}
'(' if in_class == 0
&& chars.get(i + 1) == Some(&'?')
&& chars.get(i + 2) == Some(&'P') =>
{
return Err(PErr::new(
ErrorCode::P001,
i,
"Java has no (?P...) groups; use (?<name>...)",
))
}
'{' if in_class == 0 && !valid_brace(chars, i) => {
return Err(PErr::new(
ErrorCode::P005,
i,
"illegal repetition: Java requires {n}, {n,} or {n,m}",
))
}
_ => {}
}
i += 1;
}
Ok(())
}
fn valid_brace(chars: &[char], i: usize) -> bool {
let mut j = i + 1;
let digits = |j: &mut usize| {
let s = *j;
while chars.get(*j).is_some_and(char::is_ascii_digit) {
*j += 1;
}
*j > s
};
if !digits(&mut j) {
return false;
}
if chars.get(j) == Some(&',') {
j += 1;
digits(&mut j);
}
chars.get(j) == Some(&'}')
}