refactor: utils macros

This commit is contained in:
PoiScript 2019-01-14 14:10:12 +08:00
parent 93ed18602a
commit 75362bd2a8
16 changed files with 70 additions and 91 deletions

View file

@ -11,7 +11,7 @@ impl Block {
let args = eol!(src);
let name = until_while!(src, 8, |c| c == b' ' || c == b'\n', |c: u8| c
.is_ascii_alphabetic());
.is_ascii_alphabetic())?;
// TODO: ignore case match
let content = src.find(&format!("\n#+END_{}", &src[8..name]))?;
let end = eol!(src, content + 1);

View file

@ -11,7 +11,7 @@ impl DynBlock {
let args = eol!(src);
let name = until_while!(src, 9, |c| c == b' ' || c == b'\n', |c: u8| c
.is_ascii_alphabetic());
.is_ascii_alphabetic())?;
// TODO: ignore case matching
let content = src.find("\n#+END:")?;
let end = eol!(src, content + 1);

View file

@ -11,7 +11,7 @@ impl FnDef {
pub fn parse(src: &str) -> Option<(&str, &str, usize)> {
starts_with!(src, "[fn:");
let label = until_while!(src, 4, b']', valid_label);
let label = until_while!(src, 4, b']', valid_label)?;
if label == 4 {
return None;

View file

@ -9,7 +9,7 @@ impl Keyword {
starts_with!(src, "#+");
}
let key = until_while!(src, 2, b':', |c: u8| c.is_ascii_uppercase() || c == b'_');
let key = until_while!(src, 2, b':', |c: u8| c.is_ascii_uppercase() || c == b'_')?;
// includes the eol character
let end = src.find('\n').map(|i| i + 1).unwrap_or_else(|| src.len());

View file

@ -5,7 +5,7 @@ pub struct Rule;
impl Rule {
pub fn parse(src: &str) -> Option<usize> {
let end = eol!(src);
let leading = until_while!(src, 0, b'-', |c| c == b' ' || c == b'\t');
let leading = until_while!(src, 0, b'-', |c| c == b' ' || c == b'\t')?;
if src[leading..end].chars().all(|c| c == '-') && end - leading > 4 {
Some(end)
} else {

View file

@ -11,7 +11,7 @@ impl<'a> Cookie<'a> {
}
let num1 = until_while!(src, 1, |c| c == b'%' || c == b'/', |c: u8| c
.is_ascii_digit());
.is_ascii_digit())?;
if src.as_bytes()[num1] == b'%' && *src.as_bytes().get(num1 + 1)? == b']' {
Some((
@ -21,7 +21,7 @@ impl<'a> Cookie<'a> {
num1 + 2,
))
} else {
let num2 = until_while!(src, num1 + 1, b']', |c: u8| c.is_ascii_digit());
let num2 = until_while!(src, num1 + 1, b']', |c: u8| c.is_ascii_digit())?;
Some((
Cookie {
value: &src[0..=num2],

View file

@ -3,7 +3,7 @@ pub struct Emphasis;
impl Emphasis {
// TODO: return usize instead of Option<usize>
pub fn parse(src: &str, marker: u8) -> Option<usize> {
expect!(src, 1, |c: u8| !c.is_ascii_whitespace());
expect!(src, 1, |c: u8| !c.is_ascii_whitespace())?;
let mut lines = 0;
let end = until_while!(src, 1, marker, |c| {
@ -11,9 +11,9 @@ impl Emphasis {
lines += 1;
}
lines < 2
});
})?;
expect!(src, end - 1, |c: u8| !c.is_ascii_whitespace());
expect!(src, end - 1, |c: u8| !c.is_ascii_whitespace())?;
if end < src.len() - 1 {
expect!(src, end + 1, |ch| ch == b' '
@ -26,7 +26,7 @@ impl Emphasis {
|| ch == b'\''
|| ch == b'\n'
|| ch == b')'
|| ch == b'}');
|| ch == b'}')?;
}
Some(end)

View file

@ -7,7 +7,7 @@ impl<'a> Entity<'a> {
pub fn parse(src: &'a str) -> Option<(Entity<'a>, usize)> {
expect!(src, 0, b'\\')?;
let name = position!(src, 1, |c| !c.is_ascii_alphabetic());
let name = 0;
if src.as_bytes()[name] == b'[' {
Some((

View file

@ -13,7 +13,7 @@ impl<'a> FnRef<'a> {
pub fn parse(src: &'a str) -> Option<(FnRef<'a>, usize)> {
starts_with!(src, "[fn:");
let label = until_while!(src, 4, |c| c == b']' || c == b':', valid_label);
let label = until_while!(src, 4, |c| c == b']' || c == b':', valid_label)?;
if src.as_bytes()[label] == b':' {
let mut pairs = 1;

View file

@ -14,28 +14,28 @@ impl<'a> InlineCall<'a> {
starts_with!(src, "call_");
let mut pos = until_while!(src, 5, |c| c == b'[' || c == b'(', |c: u8| c
.is_ascii_graphic());
.is_ascii_graphic())?;
let mut pos_;
let name = &src[5..pos];
let inside_header = if src.as_bytes()[pos] == b'[' {
pos_ = pos;
pos = until_while!(src, pos, b']', |c: u8| c != b'\n') + 1;
expect!(src, pos, b'(');
pos = until_while!(src, pos, b']', |c: u8| c != b'\n')? + 1;
expect!(src, pos, b'(')?;
Some(&src[pos_ + 1..pos - 1])
} else {
None
};
pos_ = pos;
pos = until_while!(src, pos, b')', |c| c != b'\n');
pos = until_while!(src, pos, b')', |c| c != b'\n')?;
let args = &src[pos_ + 1..pos];
let end_header = if src.len() > pos + 1 && src.as_bytes()[pos + 1] == b'[' {
pos_ = pos;
pos = until_while!(src, pos_ + 1, |c| c == b']', |c: u8| c != b'\n'
&& c != b')');
&& c != b')')?;
Some(&src[pos_ + 2..pos])
} else {
None

View file

@ -11,15 +11,15 @@ impl<'a> InlineSrc<'a> {
starts_with!(src, "src_");
let lang = until_while!(src, 4, |c| c == b'[' || c == b'{', |c: u8| !c
.is_ascii_whitespace());
.is_ascii_whitespace())?;
if lang == 4 {
return None;
}
if src.as_bytes()[lang] == b'[' {
let option = until_while!(src, lang, b']', |c| c != b'\n');
let body = until_while!(src, option, b'}', |c| c != b'\n');
let option = until_while!(src, lang, b']', |c| c != b'\n')?;
let body = until_while!(src, option, b'}', |c| c != b'\n')?;
Some((
InlineSrc {
@ -30,7 +30,7 @@ impl<'a> InlineSrc<'a> {
body + 1,
))
} else {
let body = until_while!(src, lang, b'}', |c| c != b'\n');
let body = until_while!(src, lang, b'}', |c| c != b'\n')?;
Some((
InlineSrc {

View file

@ -11,7 +11,7 @@ impl<'a> Link<'a> {
starts_with!(src, "[[");
}
let path = until_while!(src, 2, b']', |c| c != b'<' && c != b'>' && c != b'\n');
let path = until_while!(src, 2, b']', |c| c != b'<' && c != b'>' && c != b'\n')?;
if cond_eq!(src, path + 1, b']') {
Some((
@ -22,7 +22,7 @@ impl<'a> Link<'a> {
path + 2,
))
} else if src.as_bytes()[path + 1] == b'[' {
let desc = until_while!(src, path + 2, b']', |c| c != b'[');
let desc = until_while!(src, path + 2, b']', |c| c != b'[')?;
expect!(src, desc + 1, b']')?;
Some((

View file

@ -15,9 +15,9 @@ impl<'a> Macros<'a> {
pub fn parse(src: &'a str) -> Option<(Macros<'a>, usize)> {
starts_with!(src, "{{{");
expect!(src, 3, |c: u8| c.is_ascii_alphabetic());
expect!(src, 3, |c: u8| c.is_ascii_alphabetic())?;
let name = until_while!(src, 3, |c| c == b'}' || c == b'(', valid_name);
let name = until_while!(src, 3, |c| c == b'}' || c == b'(', valid_name)?;
if src.as_bytes()[name] == b'}' {
expect!(src, name + 1, b'}')?;

View file

@ -13,7 +13,7 @@ impl<'a> Snippet<'a> {
starts_with!(src, "@@");
}
let name = until_while!(src, 2, b':', |c: u8| c.is_ascii_alphanumeric() || c == b'-');
let name = until_while!(src, 2, b':', |c: u8| c.is_ascii_alphanumeric() || c == b'-')?;
if name == 2 {
return None;

View file

@ -9,11 +9,11 @@ impl<'a> RadioTarget<'a> {
starts_with!(src, "<<<");
}
expect!(src, 3, |c| c != b' ');
expect!(src, 3, |c| c != b' ')?;
let end = until_while!(src, 3, b'>', |c| c != b'<' && c != b'\n');
let end = until_while!(src, 3, b'>', |c| c != b'<' && c != b'\n')?;
expect!(src, end - 1, |c| c != b' ');
expect!(src, end - 1, |c| c != b' ')?;
expect!(src, end + 1, b'>')?;
expect!(src, end + 2, b'>')?;
@ -31,11 +31,11 @@ impl<'a> Target<'a> {
starts_with!(src, "<<");
}
expect!(src, 2, |c| c != b' ');
expect!(src, 2, |c| c != b' ')?;
let end = until_while!(src, 2, b'>', |c| c != b'<' && c != b'\n');
let end = until_while!(src, 2, b'>', |c| c != b'<' && c != b'\n')?;
expect!(src, end - 1, |c| c != b' ');
expect!(src, end - 1, |c| c != b' ')?;
expect!(src, end + 1, b'>')?;
Some((Target(&src[2..end]), end + 2))

View file

@ -3,13 +3,10 @@
#[macro_export]
macro_rules! expect {
($src:ident, $index:expr, $expect:tt) => {
$src.as_bytes().get($index).filter(|&b| b == &$expect)
$src.as_bytes().get($index).filter(|&&b| b == $expect)
};
($src:ident, $index:expr, $expect:expr) => {
// $src.as_bytes().get($index).filter($expect)
if $index >= $src.len() || !$expect($src.as_bytes()[$index]) {
return None;
}
$src.as_bytes().get($index).filter(|&&b| $expect(b))
};
}
@ -30,30 +27,30 @@ macro_rules! eol {
macro_rules! until {
($src:expr, $until:tt) => {{
let mut pos = 0;
while pos < $src.len() {
if $until == $src.as_bytes()[pos] {
break;
loop {
if pos >= $src.len() {
break None;
}
if $until == $src.as_bytes()[pos] {
break Some(pos);
} else {
pos += 1;
}
pos += 1;
}
if pos == $src.len() {
None
} else {
Some(pos)
}
}};
($src:expr, $until:expr) => {{
let mut pos = 0;
while pos < $src.len() {
if $until($src.as_bytes()[pos]) {
break;
loop {
if pos >= $src.len() {
break None;
}
if $until($src.as_bytes()[pos]) {
break Some(pos);
} else {
pos += 1;
}
pos += 1;
}
if pos == $src.len() {
None
} else {
Some(pos)
}
}};
}
@ -62,41 +59,33 @@ macro_rules! until {
macro_rules! until_while {
($src:expr, $start:expr, $until:tt, $while:expr) => {{
let mut pos = $start;
while pos < $src.len() {
// println!("pos {} char {} ", pos, $src.as_bytes()[pos] as char,);
if $until == $src.as_bytes()[pos] {
break;
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 {
return None;
break None;
}
}
if pos == $src.len() {
return None;
} else {
pos
}
}};
($src:expr, $start:expr, $until:expr, $while:expr) => {{
let mut pos = $start;
while pos < $src.len() {
// println!("pos {} char {}", pos, $src.as_bytes()[pos] as char);
if $until($src.as_bytes()[pos]) {
break;
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 {
return None;
break None;
}
}
if pos == $src.len() {
return None;
} else {
pos
}
}};
}
@ -111,16 +100,6 @@ macro_rules! cond_eq {
};
}
#[macro_export]
macro_rules! position {
($s:ident, $i:expr, $p:expr) => {
match $s[$i..].chars().position($p) {
Some(x) => x + $i,
None => return None,
}
};
}
#[macro_export]
macro_rules! starts_with {
($s:ident, $p:expr) => {
@ -144,13 +123,13 @@ macro_rules! skip_space {
macro_rules! skip_empty_line {
($src:ident, $from:expr) => {{
let mut pos = $from;
while pos < $src.len() {
if $src.as_bytes()[pos] != b'\n' {
break;
loop {
if pos >= $src.len() || $src.as_bytes()[pos] != b'\n' {
break pos;
} else {
pos += 1;
}
pos += 1;
}
pos
}};
}