feat(lexer): Finish lexer parse and add tests

This commit is contained in:
2026-05-06 14:30:32 +08:00
commit e8b50ae0d7
10 changed files with 696 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
use std::path::PathBuf;
use std::{collections::BTreeMap, path::Path};
use std::io;
pub struct CaseList {
index_map: BTreeMap<usize, String>,
base_path: PathBuf
}
impl CaseList {
pub fn from_dir(dir: &Path) -> io::Result<Self> {
let mut index_map = BTreeMap::new();
let case_dir = std::fs::read_dir(dir)?;
for case_item in case_dir {
let case_item = case_item?;
let file_name = match case_item.file_name().into_string() {
Ok(name) => name,
Err(_) => continue, // skip non-utf8 file names
};
if file_name.ends_with(".c") {
if let Some((index_str, _)) = file_name.split_once('_') {
if let Ok(index) = index_str.parse::<usize>() {
index_map.insert(index, file_name);
}
}
}
}
Ok(Self { index_map, base_path: dir.to_path_buf() })
}
pub fn get_case_name(&self, index: usize) -> Option<&String> {
self.index_map.get(&index)
}
pub fn get_case_path(&self, index: usize) -> Option<PathBuf> {
self.get_case_name(index).map(|name| self.base_path.join(name))
}
}
+2
View File
@@ -0,0 +1,2 @@
pub mod num_sequence;
pub mod case_list;
+54
View File
@@ -0,0 +1,54 @@
use std::{path::Iter, str::FromStr};
use num::Integer;
/// Number sequence, represents a set of integers as a union of several ranges
/// WARNING: this is intended for use in tests, so overlapping are not checked, also the ranges are not necessarily sorted
pub struct NumberSequence<T: Integer> {
cur_range_index: usize,
delta_in_range: T,
ranges: Vec<(T, T)>,
}
impl<T: Integer + Copy + FromStr> NumberSequence<T> {
pub fn from_str(s: &str) -> Option<Self> {
let mut ranges = vec![];
let groups = s.split(',');
for group in groups {
if group.is_empty() {
continue;
}
if let Ok(num) = group.parse::<T>() {
ranges.push((num, num + T::one()));
}
else if let Some((start_str, end_str)) = group.split_once('-') {
if let (Ok(start), Ok(end)) = (start_str.parse::<T>(), end_str.parse::<T>()) {
ranges.push((start, end));
} else {
return None;
}
} else {
return None;
}
}
Some(Self { cur_range_index: 0, delta_in_range: T::zero(), ranges })
}
}
impl<T: Integer + Copy> Iterator for NumberSequence<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.cur_range_index >= self.ranges.len() {
return None;
}
let (start, end) = self.ranges[self.cur_range_index];
let delta = self.delta_in_range;
if start + delta < end {
self.delta_in_range = self.delta_in_range + T::one();
Some(start + delta)
} else {
self.cur_range_index += 1;
self.delta_in_range = T::zero();
self.next()
}
}
}