165 lines
3.6 KiB
Rust
165 lines
3.6 KiB
Rust
//! Utils macros
|
|
|
|
#[macro_export]
|
|
macro_rules! expect {
|
|
($src:ident, $index:expr, $expect:tt) => {
|
|
$src.as_bytes().get($index).filter(|&&b| b == $expect)
|
|
};
|
|
($src:ident, $index:expr, $expect:expr) => {
|
|
$src.as_bytes().get($index).filter(|&&b| $expect(b))
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! eol {
|
|
($src:expr) => {
|
|
$src.find('\n').unwrap_or_else(|| $src.len())
|
|
};
|
|
($src:expr, $from:expr) => {
|
|
$src[$from..]
|
|
.find('\n')
|
|
.map(|i| i + $from)
|
|
.unwrap_or_else(|| $src.len())
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! until {
|
|
($src:expr, $until:tt) => {{
|
|
let mut pos = 0;
|
|
loop {
|
|
if pos >= $src.len() {
|
|
break None;
|
|
}
|
|
|
|
if $until == $src.as_bytes()[pos] {
|
|
break Some(pos);
|
|
} else {
|
|
pos += 1;
|
|
}
|
|
}
|
|
}};
|
|
($src:expr, $until:expr) => {{
|
|
let mut pos = 0;
|
|
loop {
|
|
if pos >= $src.len() {
|
|
break None;
|
|
}
|
|
|
|
if $until($src.as_bytes()[pos]) {
|
|
break Some(pos);
|
|
} else {
|
|
pos += 1;
|
|
}
|
|
}
|
|
}};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! until_while {
|
|
($src:expr, $start:expr, $until:tt, $while:expr) => {{
|
|
let mut pos = $start;
|
|
loop {
|
|
if pos >= $src.len() {
|
|
break None;
|
|
} else if $until == $src.as_bytes()[pos] {
|
|
break Some(pos);
|
|
} else if $while($src.as_bytes()[pos]) {
|
|
pos += 1;
|
|
continue;
|
|
} else {
|
|
break None;
|
|
}
|
|
}
|
|
}};
|
|
($src:expr, $start:expr, $until:expr, $while:expr) => {{
|
|
let mut pos = $start;
|
|
loop {
|
|
if pos >= $src.len() {
|
|
break None;
|
|
} else if $until($src.as_bytes()[pos]) {
|
|
break Some(pos);
|
|
} else if $while($src.as_bytes()[pos]) {
|
|
pos += 1;
|
|
continue;
|
|
} else {
|
|
break None;
|
|
}
|
|
}
|
|
}};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! cond_eq {
|
|
($s:ident, $i:expr, $p:expr) => {
|
|
if $i >= $s.len() {
|
|
return None;
|
|
} else {
|
|
$s.as_bytes()[$i] == $p
|
|
}
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! starts_with {
|
|
($s:ident, $p:expr) => {
|
|
if !$s.starts_with($p) {
|
|
return None;
|
|
}
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! skip_space {
|
|
($src:ident) => {
|
|
until!($src, |c| c != b' ' && c != b'\t').unwrap_or(0)
|
|
};
|
|
($src:ident, $from:expr) => {
|
|
until!($src[$from..], |c| c != b' ' && c != b'\t').unwrap_or(0) + $from
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! skip_empty_line {
|
|
($src:ident, $from:expr) => {{
|
|
let mut pos = $from;
|
|
loop {
|
|
if pos >= $src.len() || $src.as_bytes()[pos] != b'\n' {
|
|
break pos;
|
|
} else {
|
|
pos += 1;
|
|
}
|
|
}
|
|
}};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! parse_fail {
|
|
($ty:ident, $src:expr) => {
|
|
assert_eq!($ty::parse($src), None);
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! parse_succ {
|
|
($ty:ident, $src:expr, $($field:ident : $value:expr),* ) => {
|
|
assert_eq!(
|
|
$ty::parse($src),
|
|
Some((
|
|
$ty {
|
|
$( $field : $value ),*
|
|
},
|
|
$src.len()
|
|
)),
|
|
);
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! lines {
|
|
($src:ident) => {
|
|
memchr::memchr_iter(b'\n', $src.as_bytes())
|
|
.map(|i| i + 1)
|
|
.chain(std::iter::once($src.len()))
|
|
};
|
|
}
|