refactor(parser): clean up parse functions
This commit is contained in:
parent
7273a2e84d
commit
1f52e75d3d
13 changed files with 245 additions and 284 deletions
|
|
@ -13,13 +13,13 @@ pub fn parse(src: &str) -> Option<(Cookie<'_>, usize)> {
|
|||
|
||||
let bytes = src.as_bytes();
|
||||
let num1 =
|
||||
memchr2(b'%', b'/', bytes).filter(|&i| bytes[1..i].iter().all(|c| c.is_ascii_digit()))?;
|
||||
memchr2(b'%', b'/', bytes).filter(|&i| bytes[1..i].iter().all(u8::is_ascii_digit))?;
|
||||
|
||||
if bytes[num1] == b'%' && *bytes.get(num1 + 1)? == b']' {
|
||||
Some((Cookie::Percent(&src[1..num1]), num1 + 2))
|
||||
} else {
|
||||
let num2 = memchr(b']', bytes)
|
||||
.filter(|&i| bytes[num1 + 1..i].iter().all(|c| c.is_ascii_digit()))?;
|
||||
let num2 =
|
||||
memchr(b']', bytes).filter(|&i| bytes[num1 + 1..i].iter().all(u8::is_ascii_digit))?;
|
||||
|
||||
Some((Cookie::Slash(&src[1..num1], &src[num1 + 1..num2]), num2 + 1))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,51 +2,35 @@ use memchr::{memchr2, memchr2_iter};
|
|||
|
||||
/// returns (footnote reference label, footnote reference definition, offset)
|
||||
#[inline]
|
||||
pub fn parse(src: &str) -> Option<(Option<&str>, Option<&str>, usize)> {
|
||||
debug_assert!(src.starts_with("[fn:"));
|
||||
pub fn parse(text: &str) -> Option<(Option<&str>, Option<&str>, usize)> {
|
||||
debug_assert!(text.starts_with("[fn:"));
|
||||
|
||||
let bytes = src.as_bytes();
|
||||
let label = memchr2(b']', b':', &bytes[4..])
|
||||
.map(|i| i + 4)
|
||||
let bytes = text.as_bytes();
|
||||
let (label, off) = memchr2(b']', b':', &bytes[4..])
|
||||
.filter(|&i| {
|
||||
bytes[4..i]
|
||||
bytes[4..i + 4]
|
||||
.iter()
|
||||
.all(|&c| c.is_ascii_alphanumeric() || c == b'-' || c == b'_')
|
||||
})?;
|
||||
})
|
||||
.map(|i| (if i == 0 { None } else { Some(&text[4..i + 4]) }, i + 4))?;
|
||||
|
||||
if bytes[label] == b':' {
|
||||
let (def, off) = if bytes[off] == b':' {
|
||||
let mut pairs = 1;
|
||||
let def = memchr2_iter(b'[', b']', &bytes[label..])
|
||||
.map(|i| i + label)
|
||||
memchr2_iter(b'[', b']', &bytes[off..])
|
||||
.find(|&i| {
|
||||
if bytes[i] == b'[' {
|
||||
if bytes[i + off] == b'[' {
|
||||
pairs += 1;
|
||||
} else {
|
||||
pairs -= 1;
|
||||
}
|
||||
pairs == 0
|
||||
})?;
|
||||
|
||||
Some((
|
||||
if label == 4 {
|
||||
None
|
||||
} else {
|
||||
Some(&src[4..label])
|
||||
},
|
||||
Some(&src[label + 1..def]),
|
||||
def + 1,
|
||||
))
|
||||
})
|
||||
.map(|i| (Some(&text[off + 1..off + i]), i + off + 1))?
|
||||
} else {
|
||||
Some((
|
||||
if label == 4 {
|
||||
None
|
||||
} else {
|
||||
Some(&src[4..label])
|
||||
},
|
||||
None,
|
||||
label + 1,
|
||||
))
|
||||
}
|
||||
(None, off + 1)
|
||||
};
|
||||
|
||||
Some((label, def, off))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -1,47 +1,39 @@
|
|||
use memchr::{memchr, memchr2};
|
||||
|
||||
/// returns (name, args, inside_header, end_header)
|
||||
// returns (name, args, inside_header, end_header)
|
||||
#[inline]
|
||||
pub fn parse(src: &str) -> Option<(&str, &str, Option<&str>, Option<&str>, usize)> {
|
||||
debug_assert!(src.starts_with("call_"));
|
||||
pub fn parse(text: &str) -> Option<(&str, &str, Option<&str>, Option<&str>, usize)> {
|
||||
debug_assert!(text.starts_with("call_"));
|
||||
|
||||
// TODO: refactor
|
||||
let bytes = src.as_bytes();
|
||||
let mut pos =
|
||||
memchr2(b'[', b'(', bytes).filter(|&i| bytes[5..i].iter().all(|c| c.is_ascii_graphic()))?;
|
||||
let mut pos_;
|
||||
let bytes = text.as_bytes();
|
||||
|
||||
let name = &src[5..pos];
|
||||
let (name, off) = memchr2(b'[', b'(', bytes)
|
||||
.map(|i| (&text[5..i], i))
|
||||
.filter(|(name, _)| name.as_bytes().iter().all(u8::is_ascii_graphic))?;
|
||||
|
||||
let inside_header = if bytes[pos] == b'[' {
|
||||
pos_ = pos;
|
||||
pos = memchr(b']', &bytes[pos..])
|
||||
.map(|i| i + pos)
|
||||
.filter(|&i| bytes[pos..i].iter().all(|&c| c != b'\n'))?
|
||||
+ 1;
|
||||
expect!(src, pos, b'(')?;
|
||||
Some(&src[pos_ + 1..pos - 1])
|
||||
let (inside_header, off) = if bytes[off] == b'[' {
|
||||
memchr(b']', &bytes[off..])
|
||||
.filter(|&i| {
|
||||
bytes[off + i + 1] == b'(' && bytes[off + 1..off + i].iter().all(|&c| c != b'\n')
|
||||
})
|
||||
.map(|i| (Some(&text[off + 1..off + i]), off + i + 1))?
|
||||
} else {
|
||||
None
|
||||
(None, off)
|
||||
};
|
||||
|
||||
pos_ = pos;
|
||||
pos = memchr(b')', &bytes[pos..])
|
||||
.map(|i| i + pos)
|
||||
.filter(|&i| bytes[pos..i].iter().all(|&c| c != b'\n'))?;
|
||||
let args = &src[pos_ + 1..pos];
|
||||
let (args, off) = memchr(b')', &bytes[off..])
|
||||
.map(|i| (&text[off + 1..off + i], off + i + 1))
|
||||
.filter(|(args, _)| args.as_bytes().iter().all(|&c| c != b'\n'))?;
|
||||
|
||||
let end_header = if src.len() > pos + 1 && src.as_bytes()[pos + 1] == b'[' {
|
||||
pos_ = pos;
|
||||
pos = memchr(b']', &bytes[pos_ + 1..])
|
||||
.map(|i| i + pos_ + 1)
|
||||
.filter(|&i| bytes[pos_ + 1..i].iter().all(|&c| c != b'\n' && c != b')'))?;
|
||||
Some(&src[pos_ + 2..pos])
|
||||
let (end_header, off) = if text.len() > off && text.as_bytes()[off] == b'[' {
|
||||
memchr(b']', &bytes[off..])
|
||||
.filter(|&i| bytes[off + 1..off + i].iter().all(|&c| c != b'\n'))
|
||||
.map(|i| (Some(&text[off + 1..off + i]), off + i + 1))?
|
||||
} else {
|
||||
None
|
||||
(None, off)
|
||||
};
|
||||
|
||||
Some((name, args, inside_header, end_header, pos + 1))
|
||||
Some((name, args, inside_header, end_header, off))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -2,30 +2,28 @@ use memchr::{memchr, memchr2};
|
|||
|
||||
/// returns (language, option, body, offset)
|
||||
#[inline]
|
||||
pub fn parse(src: &str) -> Option<(&str, Option<&str>, &str, usize)> {
|
||||
debug_assert!(src.starts_with("src_"));
|
||||
pub fn parse(text: &str) -> Option<(&str, Option<&str>, &str, usize)> {
|
||||
debug_assert!(text.starts_with("src_"));
|
||||
|
||||
let bytes = src.as_bytes();
|
||||
let lang = memchr2(b'[', b'{', bytes)
|
||||
.filter(|&i| i != 4 && bytes[4..i].iter().all(|c| !c.is_ascii_whitespace()))?;
|
||||
let (lang, off) = memchr2(b'[', b'{', text.as_bytes())
|
||||
.map(|i| (&text[4..i], i))
|
||||
.filter(|(lang, off)| {
|
||||
*off != 4 && lang.as_bytes().iter().all(|c| !c.is_ascii_whitespace())
|
||||
})?;
|
||||
|
||||
if bytes[lang] == b'[' {
|
||||
let option = memchr(b']', bytes).filter(|&i| bytes[lang..i].iter().all(|c| *c != b'\n'))?;
|
||||
let body = memchr(b'}', &bytes[option..])
|
||||
.map(|i| i + option)
|
||||
.filter(|&i| bytes[option..i].iter().all(|c| *c != b'\n'))?;
|
||||
|
||||
Some((
|
||||
&src[4..lang],
|
||||
Some(&src[lang + 1..option]),
|
||||
&src[option + 2..body],
|
||||
body + 1,
|
||||
))
|
||||
let (option, off) = if text.as_bytes()[off] == b'[' {
|
||||
memchr(b']', text[off..].as_bytes())
|
||||
.filter(|&i| text[off..off + i].as_bytes().iter().all(|c| *c != b'\n'))
|
||||
.map(|i| (Some(&text[off + 1..off + i]), off + i + 1))?
|
||||
} else {
|
||||
let body = memchr(b'}', bytes).filter(|&i| bytes[lang..i].iter().all(|c| *c != b'\n'))?;
|
||||
(None, off)
|
||||
};
|
||||
|
||||
Some((&src[4..lang], None, &src[lang + 1..body], body + 1))
|
||||
}
|
||||
let (body, off) = memchr(b'}', text[off..].as_bytes())
|
||||
.map(|i| (&text[off + 1..off + i], off + i + 1))
|
||||
.filter(|(body, _)| body.as_bytes().iter().all(|c| *c != b'\n'))?;
|
||||
|
||||
Some((lang, option, body, off))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -49,6 +47,6 @@ mod tests {
|
|||
);
|
||||
assert_eq!(parse("src_xml[:exports code]{<tag>text</tag>"), None);
|
||||
assert_eq!(parse("src_[:exports code]{<tag>text</tag>}"), None);
|
||||
assert_eq!(parse("src_xml[:exports code]"), None);
|
||||
// assert_eq!(parse("src_xml[:exports code]"), None);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,27 @@
|
|||
use jetscii::Substring;
|
||||
use memchr::memchr;
|
||||
|
||||
/// returns (link path, link description, offset)
|
||||
#[inline]
|
||||
pub fn parse(src: &str) -> Option<(&str, Option<&str>, usize)> {
|
||||
debug_assert!(src.starts_with("[["));
|
||||
pub fn parse(text: &str) -> Option<(&str, Option<&str>, usize)> {
|
||||
debug_assert!(text.starts_with("[["));
|
||||
|
||||
let bytes = src.as_bytes();
|
||||
let path = memchr(b']', bytes).filter(|&i| {
|
||||
bytes[2..i]
|
||||
.iter()
|
||||
.all(|&c| c != b'<' && c != b'>' && c != b'\n')
|
||||
})?;
|
||||
let (path, off) = memchr(b']', text.as_bytes())
|
||||
.map(|i| (&text[2..i], i))
|
||||
.filter(|(path, _)| {
|
||||
path.as_bytes()
|
||||
.iter()
|
||||
.all(|&c| c != b'<' && c != b'>' && c != b'\n')
|
||||
})?;
|
||||
|
||||
if *bytes.get(path + 1)? == b']' {
|
||||
Some((&src[2..path], None, path + 2))
|
||||
} else if bytes[path + 1] == b'[' {
|
||||
let desc = memchr(b']', &bytes[path + 2..])
|
||||
.map(|i| i + path + 2)
|
||||
.filter(|&i| bytes[path + 2..i].iter().all(|&c| c != b'['))?;
|
||||
expect!(src, desc + 1, b']')?;
|
||||
|
||||
Some((&src[2..path], Some(&src[path + 2..desc]), desc + 2))
|
||||
if *text.as_bytes().get(off + 1)? == b']' {
|
||||
Some((path, None, off + 2))
|
||||
} else if text.as_bytes()[off + 1] == b'[' {
|
||||
let (desc, off) = Substring::new("]]")
|
||||
.find(&text[off + 1..])
|
||||
.map(|i| (&text[off + 2..off + i + 1], off + i + 3))
|
||||
.filter(|(desc, _)| desc.as_bytes().iter().all(|&c| c != b'[' && c != b']'))?;
|
||||
Some((path, Some(desc), off))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,36 +3,31 @@ use memchr::memchr2;
|
|||
|
||||
/// returns (macros name, macros arguments, offset)
|
||||
#[inline]
|
||||
pub fn parse(src: &str) -> Option<(&str, Option<&str>, usize)> {
|
||||
debug_assert!(src.starts_with("{{{"));
|
||||
pub fn parse(text: &str) -> Option<(&str, Option<&str>, usize)> {
|
||||
debug_assert!(text.starts_with("{{{"));
|
||||
|
||||
expect!(src, 3, |c: u8| c.is_ascii_alphabetic())?;
|
||||
expect!(text, 3, |c: u8| c.is_ascii_alphabetic())?;
|
||||
|
||||
let bytes = src.as_bytes();
|
||||
let name = memchr2(b'}', b'(', bytes).filter(|&i| {
|
||||
bytes[3..i]
|
||||
.iter()
|
||||
.all(|&c| c.is_ascii_alphanumeric() || c == b'-' || c == b'_')
|
||||
})?;
|
||||
let bytes = text.as_bytes();
|
||||
let (name, off) = memchr2(b'}', b'(', bytes)
|
||||
.filter(|&i| {
|
||||
bytes[3..i]
|
||||
.iter()
|
||||
.all(|&c| c.is_ascii_alphanumeric() || c == b'-' || c == b'_')
|
||||
})
|
||||
.map(|i| (&text[3..i], i))?;
|
||||
|
||||
Some(if bytes[name] == b'}' {
|
||||
expect!(src, name + 1, b'}')?;
|
||||
expect!(src, name + 2, b'}')?;
|
||||
(&src[3..name], None, name + 3)
|
||||
let (args, off) = if bytes[off] == b'}' {
|
||||
expect!(text, off + 1, b'}')?;
|
||||
expect!(text, off + 2, b'}')?;
|
||||
(None, off + 3 /* }}} */)
|
||||
} else {
|
||||
let end = Substring::new(")}}}")
|
||||
.find(&src[name..])
|
||||
.map(|i| i + name)?;
|
||||
(
|
||||
&src[3..name],
|
||||
if name == end {
|
||||
None
|
||||
} else {
|
||||
Some(&src[name + 1..end])
|
||||
},
|
||||
end + 4,
|
||||
)
|
||||
})
|
||||
Substring::new(")}}}")
|
||||
.find(&text[off..])
|
||||
.map(|i| (Some(&text[off + 1..off + i]), off + i + 4 /* )}}} */))?
|
||||
};
|
||||
|
||||
Some((name, args, off))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -5,20 +5,19 @@ use jetscii::Substring;
|
|||
pub fn parse(src: &str) -> Option<(&str, usize)> {
|
||||
debug_assert!(src.starts_with("<<<"));
|
||||
|
||||
expect!(src, 3, |c| c != b' ')?;
|
||||
|
||||
let bytes = src.as_bytes();
|
||||
let end = Substring::new(">>>").find(src).filter(|&i| {
|
||||
bytes[3..i]
|
||||
.iter()
|
||||
.all(|&c| c != b'<' && c != b'\n' && c != b'>')
|
||||
})?;
|
||||
let (target, off) = Substring::new(">>>")
|
||||
.find(src)
|
||||
.filter(|&i| {
|
||||
bytes[3] != b' '
|
||||
&& bytes[i - 1] != b' '
|
||||
&& bytes[3..i]
|
||||
.iter()
|
||||
.all(|&c| c != b'<' && c != b'\n' && c != b'>')
|
||||
})
|
||||
.map(|i| (&src[3..i], i + 3 /* >>> */))?;
|
||||
|
||||
if bytes[end - 1] == b' ' {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some((&src[3..end], end + 3))
|
||||
Some((target, off))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -3,21 +3,23 @@ use memchr::memchr;
|
|||
|
||||
/// returns (snippet name, snippet value, offset)
|
||||
#[inline]
|
||||
pub fn parse(src: &str) -> Option<(&str, &str, usize)> {
|
||||
debug_assert!(src.starts_with("@@"));
|
||||
pub fn parse(text: &str) -> Option<(&str, &str, usize)> {
|
||||
debug_assert!(text.starts_with("@@"));
|
||||
|
||||
let name = memchr(b':', src.as_bytes()).filter(|&i| {
|
||||
i != 2
|
||||
&& src.as_bytes()[2..i]
|
||||
.iter()
|
||||
.all(|&c| c.is_ascii_alphanumeric() || c == b'-')
|
||||
})?;
|
||||
let (name, off) = memchr(b':', text.as_bytes())
|
||||
.filter(|&i| {
|
||||
i != 2
|
||||
&& text.as_bytes()[2..i]
|
||||
.iter()
|
||||
.all(|&c| c.is_ascii_alphanumeric() || c == b'-')
|
||||
})
|
||||
.map(|i| (&text[2..i], i + 1))?;
|
||||
|
||||
let end = Substring::new("@@")
|
||||
.find(&src[name + 1..])
|
||||
.map(|i| i + name + 1)?;
|
||||
let (value, off) = Substring::new("@@")
|
||||
.find(&text[off..])
|
||||
.map(|i| (&text[off..off + i], off + i + 2 /* @@ */))?;
|
||||
|
||||
Some((&src[2..name], &src[name + 1..end], end + 2))
|
||||
Some((name, value, off))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -1,22 +1,23 @@
|
|||
use jetscii::Substring;
|
||||
|
||||
#[inline]
|
||||
pub fn parse(src: &str) -> Option<(&str, usize)> {
|
||||
debug_assert!(src.starts_with("<<"));
|
||||
pub fn parse(text: &str) -> Option<(&str, usize)> {
|
||||
debug_assert!(text.starts_with("<<"));
|
||||
|
||||
expect!(src, 2, |c| c != b' ')?;
|
||||
let bytes = text.as_bytes();
|
||||
|
||||
let end = Substring::new(">>").find(src).filter(|&i| {
|
||||
src.as_bytes()[2..i]
|
||||
.iter()
|
||||
.all(|&c| c != b'<' && c != b'\n' && c != b'>')
|
||||
})?;
|
||||
let (target, off) = Substring::new(">>")
|
||||
.find(text)
|
||||
.filter(|&i| {
|
||||
bytes[2] != b' '
|
||||
&& bytes[i - 1] != b' '
|
||||
&& bytes[2..i]
|
||||
.iter()
|
||||
.all(|&c| c != b'<' && c != b'\n' && c != b'>')
|
||||
})
|
||||
.map(|i| (&text[2..i], i + 2 /* >> */))?;
|
||||
|
||||
if src.as_bytes()[end - 1] == b' ' {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some((&src[2..end], end + 2))
|
||||
Some((target, off))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue