This commit is contained in:
Michael Zhang 2021-08-07 22:09:36 -05:00
parent f6b193f69e
commit f5b076d54c
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
5 changed files with 59 additions and 15 deletions

2
Justfile Normal file
View file

@ -0,0 +1,2 @@
fmt:
cargo +nightly fmt --all

View file

@ -1,3 +1,4 @@
#[macro_export]
macro_rules! rule { macro_rules! rule {
($vis:vis $name:ident : $ret:ty => $expr:expr) => { ($vis:vis $name:ident : $ret:ty => $expr:expr) => {
$vis fn $name(i: &[u8]) -> nom::IResult<&[u8], $ret> { $vis fn $name(i: &[u8]) -> nom::IResult<&[u8], $ret> {
@ -5,3 +6,20 @@ macro_rules! rule {
} }
}; };
} }
#[macro_export]
macro_rules! pred {
($($expr:tt)*) => { |c: u8| _pred!(expr { $($expr)* })(c) };
}
macro_rules! _pred {
(expr {}) => {};
(expr { $name:ident }) => { |b| $name(b) };
(expr { ! $($expr:tt)* }) => { |b| !_pred!(expr { $($expr)* })(b) };
(expr { ($($L:tt)*) && ($($R:tt)*) }) => {
|b| { _pred!(expr { $($L)* })(b) && _pred!(expr { $($R)* })(b) }
};
(expr { ($($L:tt)*) || ($($R:tt)*) }) => {
|b| { _pred!(expr { $($L)* })(b) || _pred!(expr { $($R)* })(b) }
};
}

View file

@ -8,17 +8,20 @@ rule!(pub ALPHA : u8 => satisfy(|c| (c >= b'a' && c <= b'z') || (c >= b'A' && c
rule!(pub BIT : u8 => satisfy(|c| c == b'0' || c == b'1')); rule!(pub BIT : u8 => satisfy(|c| c == b'0' || c == b'1'));
rule!(pub CHAR : u8 => satisfy(|c| c != b'\0')); pub fn is_char(c: u8) -> bool { c != b'\0' }
rule!(pub CHAR : u8 => satisfy(is_char));
rule!(pub CR : u8 => byte(b'\x0d')); rule!(pub CR : u8 => byte(b'\x0d'));
rule!(pub CRLF : (u8, u8) => pair(CR, LF)); rule!(pub CRLF : (u8, u8) => pair(CR, LF));
rule!(pub CTL : u8 => satisfy(|c| c <= b'\x1f' || c == b'\x7f')); pub fn is_ctl(c: u8) -> bool { c <= b'\x1f' || c == b'\x7f' }
rule!(pub CTL : u8 => satisfy(is_ctl));
rule!(pub DIGIT : u8 => satisfy(|c| c >= b'\x30' && c <= b'\x39')); rule!(pub DIGIT : u8 => satisfy(|c| c >= b'\x30' && c <= b'\x39'));
rule!(pub DQUOTE : u8 => byte(b'\x22')); pub fn is_dquote(c: u8) -> bool { c == b'\x22' }
rule!(pub DQUOTE : u8 => satisfy(is_dquote));
rule!(pub HEXDIG : u8 => alt((DIGIT, satisfy(|c| c >= b'A' && c <= b'F')))); rule!(pub HEXDIG : u8 => alt((DIGIT, satisfy(|c| c >= b'A' && c <= b'F'))));
@ -30,7 +33,8 @@ rule!(pub LWSP : () => skip(many0(alt((skip(WSP), skip(pair(CRLF, WSP)))))));
rule!(pub OCTET : char => anychar); rule!(pub OCTET : char => anychar);
rule!(pub SP : u8 => byte(b'\x20')); pub fn is_sp(c: u8) -> bool { c == b'\x20' }
rule!(pub SP : u8 => satisfy(is_sp));
rule!(pub VCHAR : u8 => satisfy(|c| c >= b'\x21' && c <= b'\x7e')); rule!(pub VCHAR : u8 => satisfy(|c| c >= b'\x21' && c <= b'\x7e'));

View file

@ -10,8 +10,8 @@ use nom::{
IResult, IResult,
}; };
use super::rfc2234::{CRLF, DIGIT, DQUOTE}; use super::parsers::satisfy;
use super::parsers::byte; use super::rfc2234::{is_char, is_ctl, is_dquote, is_sp, CRLF, DIGIT, DQUOTE};
rule!(pub astring : Vec<u8> => alt((many1(ASTRING_CHAR), string))); rule!(pub astring : Vec<u8> => alt((many1(ASTRING_CHAR), string)));
@ -19,9 +19,26 @@ rule!(pub ASTRING_CHAR : u8 => alt((ATOM_CHAR, resp_specials)));
rule!(pub atom : Vec<u8> => many1(ATOM_CHAR)); rule!(pub atom : Vec<u8> => many1(ATOM_CHAR));
pub fn ATOM_CHAR(i: &[u8]) -> IResult<&[u8], u8> { // TODO: somehow incorporate CHAR in here?
todo!() // technically ATOM_CHAR is defined as <any CHAR except atom-specials>
// but "except"-style rules don't really make sense except for character sets
// and some other niche cases so probably doesn't warrant a separate combinator
rule!(pub ATOM_CHAR : u8 => satisfy(pred!((is_char) && (!is_atom_specials))));
pub fn is_atom_specials(c: u8) -> bool {
c == b'('
|| c == b')'
|| c == b'{'
|| is_sp(c)
|| is_ctl(c)
|| is_list_wildcards(c)
|| is_quoted_specials(c)
|| is_resp_specials(c)
} }
rule!(pub atom_specials : u8 => satisfy(is_atom_specials));
pub fn is_list_wildcards(c: u8) -> bool { c == b'%' || c == b'*' }
rule!(pub list_wildcards : u8 => satisfy(is_list_wildcards));
/// literal = "{" number "}" CRLF *CHAR8 /// literal = "{" number "}" CRLF *CHAR8
/// ; Number represents the number of CHAR8s /// ; Number represents the number of CHAR8s
@ -52,14 +69,14 @@ pub fn number(i: &[u8]) -> IResult<&[u8], u32> {
rule!(pub quoted : Vec<u8> => delimited(DQUOTE, many0(QUOTED_CHAR), DQUOTE)); rule!(pub quoted : Vec<u8> => delimited(DQUOTE, many0(QUOTED_CHAR), DQUOTE));
pub fn QUOTED_CHAR(i: &[u8]) -> IResult<&[u8], u8> { pub fn QUOTED_CHAR(i: &[u8]) -> IResult<&[u8], u8> { todo!() }
todo!()
}
rule!(pub resp_specials : u8 => byte(b']')); pub fn is_quoted_specials(c: u8) -> bool { is_dquote(c) || c == b'\\' }
rule!(pub quoted_specials : u8 => satisfy(is_quoted_specials));
pub fn is_resp_specials(c: u8) -> bool { c == b']' }
rule!(pub resp_specials : u8 => satisfy(is_resp_specials));
rule!(pub string : Vec<u8> => alt((quoted, literal))); rule!(pub string : Vec<u8> => alt((quoted, literal)));
pub fn TEXT_CHAR(i: &[u8]) -> IResult<&[u8], u8> { pub fn TEXT_CHAR(i: &[u8]) -> IResult<&[u8], u8> { todo!() }
todo!()
}

3
rustfmt.toml Normal file
View file

@ -0,0 +1,3 @@
fn_single_line = true
max_width = 100
wrap_comments = true