Skip to content

Commit

Permalink
Merge pull request #535 from epage/seq
Browse files Browse the repository at this point in the history
fix(comb): Clarify `seq`s behavior
  • Loading branch information
epage authored Jun 6, 2024
2 parents c1ac018 + acda2d8 commit 9ebdf0c
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 39 deletions.
51 changes: 12 additions & 39 deletions src/macros/seq.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
/// Initialize a struct or tuple out of a sequences of parsers
///
/// Unlike normal struct initialization syntax:
/// - `_` fields can exist to run a parser but ignore the result
/// - Parse results for a field can later be referenced using the field name
///
/// Unlike normal tuple initialization syntax:
/// - Struct-style initialization (`{ 0: _, 1: _}`) is not supported
/// - `_: <parser>` fields can exist to run a parser but ignore the result
///
///# Example
///
/// ```
Expand Down Expand Up @@ -53,39 +61,6 @@
/// },
/// )),
/// );
///
/// // Or parse into enum variants
/// #[derive(Debug, PartialEq, Eq)]
/// enum Expr {
/// Add { lhs: u32, rhs: u32 },
/// Mul(u32, u32),
/// }
///
/// fn add(input: &mut &[u8]) -> PResult<Expr> {
/// seq!{Expr::Add {
/// lhs: dec_uint::<_, u32, ContextError>,
/// _: b" + ",
/// rhs: dec_uint::<_, u32, ContextError>,
/// }}.parse_next(input)
/// }
///
/// fn mul(input: &mut &[u8]) -> PResult<Expr> {
/// seq!(Expr::Mul(
/// dec_uint::<_, u32, ContextError>,
/// _: b" * ",
/// dec_uint::<_, u32, ContextError>,
/// )).parse_next(input)
/// }
///
/// assert_eq!(
/// add.parse_peek(&b"1 + 2"[..]),
/// Ok((&b""[..], Expr::Add { lhs: 1, rhs: 2 })),
/// );
///
/// assert_eq!(
/// mul.parse_peek(&b"3 * 4"[..]),
/// Ok((&b""[..], Expr::Mul(3, 4))),
/// );
/// ```
#[macro_export]
#[doc(alias = "tuple")]
Expand All @@ -99,15 +74,13 @@
macro_rules! seq {
($($name: ident)::* { $($fields: tt)* }) => {
$crate::combinator::trace(stringify!($($name)::*), move |input: &mut _| {
use $crate::Parser;
$crate::seq_parse_struct_fields!(input; $($fields)*);
#[allow(clippy::redundant_field_names)]
Ok($crate::seq_init_struct_fields!( ($($fields)*); $($name)::*;))
})
};
($($name: ident)::* ( $($elements: tt)* )) => {
$crate::combinator::trace(stringify!($($name)::*), move |input: &mut _| {
use $crate::Parser;
$crate::seq_parse_tuple_fields!( ($($elements)*) ; ).map(|t| {
$crate::seq_init_tuple_fields!(
($($elements)*);
Expand Down Expand Up @@ -141,27 +114,27 @@ macro_rules! seq_parse_struct_fields {
$input: ident;
_ : $head_parser: expr, $($fields: tt)*
) => {
let _ = $head_parser.parse_next($input)?;
let _ = $crate::Parser::parse_next(&mut $head_parser, $input)?;
$crate::seq_parse_struct_fields!($input; $($fields)*)
};
(
$input: ident;
_ : $head_parser: expr
) => {
let _ = $head_parser.parse_next($input)?;
let _ = $crate::Parser::parse_next(&mut $head_parser, $input)?;
};
(
$input: ident;
$head_field: ident : $head_parser: expr, $($fields: tt)*
) => {
let $head_field = $head_parser.parse_next($input)?;
let $head_field = $crate::Parser::parse_next(&mut $head_parser, $input)?;
$crate::seq_parse_struct_fields!($input; $($fields)*)
};
(
$input: ident;
$head_field: ident : $head_parser: expr
) => {
let $head_field = $head_parser.parse_next($input)?;
let $head_field = $crate::Parser::parse_next(&mut $head_parser, $input)?;
};
(
$input: expr;
Expand Down
37 changes: 37 additions & 0 deletions src/macros/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,43 @@ fn seq_struct_no_trailing_comma_elided() {
}
}

#[test]
fn seq_enum_struct_variant() {
#[derive(Debug, PartialEq, Eq)]
enum Expr {
Add { lhs: u32, rhs: u32 },
Mul(u32, u32),
}

fn add(input: &mut &[u8]) -> PResult<Expr> {
seq! {Expr::Add {
lhs: dec_uint::<_, u32, _>,
_: b" + ",
rhs: dec_uint::<_, u32, _>,
}}
.parse_next(input)
}

fn mul(input: &mut &[u8]) -> PResult<Expr> {
seq!(Expr::Mul(
dec_uint::<_, u32, _>,
_: b" * ",
dec_uint::<_, u32, _>,
))
.parse_next(input)
}

assert_eq!(
add.parse_peek(&b"1 + 2"[..]),
Ok((&b""[..], Expr::Add { lhs: 1, rhs: 2 })),
);

assert_eq!(
mul.parse_peek(&b"3 * 4"[..]),
Ok((&b""[..], Expr::Mul(3, 4))),
);
}

#[test]
fn seq_tuple_struct_basics() {
#[derive(Debug, PartialEq)]
Expand Down

0 comments on commit 9ebdf0c

Please sign in to comment.