macro_rules! construct {
    ($(::)? $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 ($expr:expr) $(, $($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:tt)+]] [$($fields:ident)*]) => { ... };
    (@make [pos   [$($con:tt)+]] [$($fields:ident)*]) => { ... };
    (@make [pos] [$($fields:ident)*]) => { ... };
}
Expand description

Compose several parsers to produce a single result

Usage reference

// structs with unnamed fields:
construct!(Res(a, b, c));

// structs with named fields:
construct!(Res {a, b, c});

// enums with unnamed fields:
construct!(Ty::Res(a, b, c));

// enums with named fields:
construct!(Ty::Res {a, b, c});

// tuples:
construct!(a, b, c);

// parallel composition, tries all parsers, picks succeeding left most one:
construct!([a, b, c]);

// defining primitive parsers inside construct macro :)
construct!(a(short('a').switch()), b(long("arg").argument::<usize>("ARG")));

Combinatoric usage

construct! can compose parsers sequentially or in parallel.

Sequential composition runs each parser and if all of them succeed you get a parser object of a new type back. Placeholder names for values inside construct! macro must correspond to both struct/enum names and parser names present in scope. In examples below a corresponds to a function and b corresponds to a variable name. Note parens in a(), you must to use them to indicate function parsers.

Inside the parens you can put a whole expression to use instead of having to define them in advance: a(positional::<String>("POS")). Probably a good idea to use this approach only for simple parsers.

struct Res (u32, u32);
enum Ul { T { a: u32, b: u32 } }

// You can share parameters across multiple construct invocations
// if defined as functions
fn a() -> impl Parser<u32> {
    short('a').argument::<u32>("N")
}

// You can construct structs or enums with unnamed fields
fn res() -> impl Parser<Res> {
    let b = short('b').argument::<u32>("n");
    construct!(Res ( a(), b ))
}

// You can construct structs or enums with named fields
fn ult() -> impl Parser<Ul> {
    let b = short('b').argument::<u32>("n");
    construct!(Ul::T { a(), b })
}

// You can also construct simple tuples
fn tuple() -> impl Parser<(u32, u32)> {
    let b = short('b').argument::<u32>("n");
    construct!(a(), b)
}

// You can create boxed version of parsers so the type matches as long
// as return type is the same - can be useful for all sort of dynamic parsers
fn boxed() -> impl Parser<u32> {
    let a = short('a').argument::<u32>("n");
    construct!(a)
}

// In addition to having primitives defined before using them - you can also define
// them directly inside construct macro. Probably only a good idea if you have only simple
// components
struct Options {
    arg: u32,
    switch: bool,
}

fn coyoda() -> impl Parser<Options> {
    construct!(Options {
        arg(short('a').argument::<u32>("ARG")),
        switch(short('s').switch())
    })
}

Parallel composition picks one of several available parsers (result types must match) and returns a parser object of the same type. Similar to sequential composition you can use parsers from variables or functions:

fn b() -> impl Parser<u32> {
    short('b').argument::<u32>("NUM")
}

fn a_or_b() -> impl Parser<u32> {
    let a = short('a').argument::<u32>("NUM");
    // equivalent way of writing this would be `a.or_else(b())`
    construct!([a, b()])
}

Derive usage

bpaf_derive would combine fields of struct or enum constructors sequentially and enum variants in parallel.

// to satisfy this parser user needs to pass both -a and -b
#[derive(Debug, Clone, Bpaf)]
struct Res {
    a: u32,
    b: u32,
}

// to satisfy this parser user needs to pass one (and only one) of -a, -b, -c or -d
#[derive(Debug, Clone, Bpaf)]
enum Enumeraton {
    A { a: u32 },
    B { b: u32 },
    C { c: u32 },
    D { d: u32 },
}

// here user needs to pass either both -a AND -b or both -c AND -d
#[derive(Debug, Clone, Bpaf)]
enum Ult {
    AB { a: u32, b: u32 },
    CD { c: u32, d: u32 }
}