macro_rules! construct {
    ($con:ident { $($tokens:tt)* }) => { ... };
    ($con:ident ( $($tokens:tt)* )) => { ... };
    ($ns:ident :: $con:ident { $($tokens:tt)* }) => { ... };
    ($ns:ident :: $con:ident ( $($tokens:tt)* )) => { ... };
    ($first:ident $($tokens:tt)*) => { ... };
    ([$first:ident $($tokens:tt)*]) => { ... };
    (@prepare $ty:tt [$($fields:tt)*] $field:ident (), $($rest:tt)*) => { ... };
    (@prepare $ty:tt [$($fields:tt)*] $field:ident () $($rest:tt)*) => { ... };
    (@prepare $ty:tt [$($fields:tt)*] $field:ident, $($rest:tt)*) => { ... };
    (@prepare $ty:tt [$($fields:tt)*] $field:ident $($rest:tt)*) => { ... };
    (@prepare [alt] [$first:ident $($fields:ident)*]) => { ... };
    (@prepare $ty:tt [$($fields:tt)*]) => { ... };
    (@make [named [$con:ident]] [$($fields:ident)*]) => { ... };
    (@make [pos [$con:ident]] [$($fields:ident)*]) => { ... };
    (@make [named [$ns:ident $con:ident]] [$($fields:ident)*]) => { ... };
    (@make [pos [$ns:ident $con:ident]] [$($fields:ident)*]) => { ... };
    (@make [pos] [$($fields:ident)*]) => { ... };
}
Expand description

Compose several parsers to produce a single result

Every parser must succeed in order to produce a result for sequential composition and only one parser needs to succeed for a parallel one (construct!([a, b, c]))

Each parser must be present in a local scope and have the same name as struct field. Alternatively a parser can be present as a function producing a parser bpaf will call this function and use it’s result. Later option might be useful when single parser is used in several construct! macros

struct Res {
    a: bool,
    b: u32,
}

// parser defined as a local variable
let a: Parser<bool> = short('a').switch();

// parser defined as a function
fn b() -> Parser<u32> { short('b').argument("B").from_str() }
let res: Parser<Res> = construct!(Res { a, b() });

construct! supports following representations:

  • structs with unnamed fields:
construct!(Res(a, b))
  • structs with named fields:
construct!(Res {a, b})
  • enums with unnamed fields:
construct!(Ty::Res(a, b))
  • enums with named fields:
construct!(Ty::Res {a, b})
  • tuples:
construct!(a, b)
  • parallel composition, a equivalent of a.or_else(b).or_else(c)
construct!([a, b, c])