feat(lexer): Finish lexer parse and add tests
This commit is contained in:
@@ -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))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod num_sequence;
|
||||
pub mod case_list;
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user