Skip to content
Snippets Groups Projects
macros.rs 19.7 KiB
Newer Older
macro_rules! char {
    ($e:literal) => {
        crate::combinators::common::characters::Char{c: $e}
Carlos Valencia's avatar
Carlos Valencia committed
    };
    ($e:expr) => {
        $e
Carlos Valencia's avatar
Carlos Valencia committed
}

#[macro_export]
macro_rules! parser {
    // done converting
    (@cvt () $postfix:tt) => { parser!(@pfx () $postfix) };
    //                                |    |  ^ postfix expression
    //                                |    ^ operand stack
    //                                ^ postfix interpreter
    
    // infix to postfix conversion using the rules at the bottom of this page: http://csis.pace.edu/~wolf/CS122/infix-postfix.htm
    
    // at end of input, flush the operators to postfix
    (@cvt ($ophead:tt $($optail:tt)*) ($($postfix:tt)*)) => { parser!(@cvt ($($optail)*) ($($postfix)* $ophead)) };
    
    // 2. push an operator onto the stack if it's empty or has a left-parent on top
    (@cvt (                 ) $postfix:tt <|> $($tail:tt)*) => { parser!(@cvt (<|>               ) $postfix $($tail)*) };
    (@cvt (                 ) $postfix:tt *> $($tail:tt)*) => { parser!(@cvt (*>               ) $postfix $($tail)*) };
    (@cvt (                 ) $postfix:tt <* $($tail:tt)*) => { parser!(@cvt (<*               ) $postfix $($tail)*) };
    (@cvt (                 ) $postfix:tt <~> $($tail:tt)*) => { parser!(@cvt (<~>               ) $postfix $($tail)*) };
    (@cvt (LP $($optail:tt)*) $postfix:tt <|> $($tail:tt)*) => { parser!(@cvt (<|> LP $($optail)*) $postfix $($tail)*) };
    (@cvt (LP $($optail:tt)*) $postfix:tt *> $($tail:tt)*) => { parser!(@cvt (*> LP $($optail)*) $postfix $($tail)*) };
    (@cvt (LP $($optail:tt)*) $postfix:tt <* $($tail:tt)*) => { parser!(@cvt (<* LP $($optail)*) $postfix $($tail)*) };
    (@cvt (LP $($optail:tt)*) $postfix:tt <~> $($tail:tt)*) => { parser!(@cvt (<~> LP $($optail)*) $postfix $($tail)*) };

    (@cvt (                 ) $postfix:tt pure $($tail:tt)*) => { parser!(@cvt (pure               ) $postfix $($tail)*) };
    (@cvt (LP $($optail:tt)*) $postfix:tt pure $($tail:tt)*) => { parser!(@cvt (pure LP $($optail)*) $postfix $($tail)*) };

    (@cvt (                 ) $postfix:tt empty $($tail:tt)*) => { parser!(@cvt (empty               ) $postfix $($tail)*) };
    (@cvt (LP $($optail:tt)*) $postfix:tt empty $($tail:tt)*) => { parser!(@cvt (empty LP $($optail)*) $postfix $($tail)*) };

    (@cvt (                 ) $postfix:tt try $($tail:tt)*) => { parser!(@cvt (try               ) $postfix $($tail)*) };
    (@cvt (LP $($optail:tt)*) $postfix:tt try $($tail:tt)*) => { parser!(@cvt (try LP $($optail)*) $postfix $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed

Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (                 ) $postfix:tt many $($tail:tt)*) => { parser!(@cvt (many               ) $postfix $($tail)*) };
    (@cvt (LP $($optail:tt)*) $postfix:tt many $($tail:tt)*) => { parser!(@cvt (many LP $($optail)*) $postfix $($tail)*) };

Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (                 ) $postfix:tt sat $($tail:tt)*) => { parser!(@cvt (sat               ) $postfix $($tail)*) };
    (@cvt (LP $($optail:tt)*) $postfix:tt sat $($tail:tt)*) => { parser!(@cvt (sat LP $($optail)*) $postfix $($tail)*) };

    (@cvt (                 ) $postfix:tt <#> $($tail:tt)*) => { parser!(@cvt (<#>               ) $postfix $($tail)*) };
    (@cvt (LP $($optail:tt)*) $postfix:tt <#> $($tail:tt)*) => { parser!(@cvt (<#> LP $($optail)*) $postfix $($tail)*) };

    // 3. push a left-parent onto the stack
    (@cvt ($($operator:tt)*) $postfix:tt ($($inner:tt)*) $($tail:tt)*) => { parser!(@cvt (LP $($operator)*) $postfix $($inner)* RP $($tail)*) };
    
    // 4. see right-parent, pop operators to postfix until left-parent
    (@cvt (LP         $($optail:tt)*) $postfix:tt       RP $($tail:tt)*) => { parser!(@cvt ($($optail)*) $postfix               $($tail)*)    };
    (@cvt ($ophead:tt $($optail:tt)*) ($($postfix:tt)*) RP $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* $ophead) RP $($tail)*) };
    
    // 5. if an operator w/ lower precedence is on top, just push
    (@cvt (<|> $($optail:tt)*) $postfix:tt *> $($tail:tt)*) => { parser!(@cvt (*> <|> $($optail)*) $postfix $($tail)*) };
    (@cvt (<|> $($optail:tt)*) $postfix:tt <* $($tail:tt)*) => { parser!(@cvt (<* <|> $($optail)*) $postfix $($tail)*) };
    (@cvt (<|> $($optail:tt)*) $postfix:tt <~> $($tail:tt)*) => { parser!(@cvt (<~> <|> $($optail)*) $postfix $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (<|> $($optail:tt)*) $postfix:tt <#> $($tail:tt)*) => { parser!(@cvt (<#> <|> $($optail)*) $postfix $($tail)*) };
    (@cvt (<|> $($optail:tt)*) $postfix:tt pure $($tail:tt)*) => { parser!(@cvt (pure <|> $($optail)*) $postfix $($tail)*) };
    (@cvt (*> $($optail:tt)*) $postfix:tt pure $($tail:tt)*) => { parser!(@cvt (pure *> $($optail)*) $postfix $($tail)*) };
    (@cvt (<* $($optail:tt)*) $postfix:tt pure $($tail:tt)*) => { parser!(@cvt (pure <* $($optail)*) $postfix $($tail)*) };
    (@cvt (<~> $($optail:tt)*) $postfix:tt pure $($tail:tt)*) => { parser!(@cvt (pure <~> $($optail)*) $postfix $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (<#> $($optail:tt)*) $postfix:tt pure $($tail:tt)*) => { parser!(@cvt (pure <#> $($optail)*) $postfix $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (try $($optail:tt)*) $postfix:tt pure $($tail:tt)*) => { parser!(@cvt (pure try $($optail)*) $postfix $($tail)*) };
    (@cvt (many $($optail:tt)*) $postfix:tt pure $($tail:tt)*) => { parser!(@cvt (pure many $($optail)*) $postfix $($tail)*) };

    (@cvt (<|> $($optail:tt)*) $postfix:tt empty $($tail:tt)*) => { parser!(@cvt (empty <|> $($optail)*) $postfix $($tail)*) };
    (@cvt (*> $($optail:tt)*) $postfix:tt empty $($tail:tt)*) => { parser!(@cvt (empty *> $($optail)*) $postfix $($tail)*) };
    (@cvt (<* $($optail:tt)*) $postfix:tt empty $($tail:tt)*) => { parser!(@cvt (empty <* $($optail)*) $postfix $($tail)*) };
    (@cvt (<~> $($optail:tt)*) $postfix:tt empty $($tail:tt)*) => { parser!(@cvt (empty <~> $($optail)*) $postfix $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (<#> $($optail:tt)*) $postfix:tt empty $($tail:tt)*) => { parser!(@cvt (empty <#> $($optail)*) $postfix $($tail)*) };

    (@cvt (<|> $($optail:tt)*) $postfix:tt try $($tail:tt)*) => { parser!(@cvt (try <|> $($optail)*) $postfix $($tail)*) };
    (@cvt (*> $($optail:tt)*) $postfix:tt try $($tail:tt)*) => { parser!(@cvt (try *> $($optail)*) $postfix $($tail)*) };
    (@cvt (<* $($optail:tt)*) $postfix:tt try $($tail:tt)*) => { parser!(@cvt (try <* $($optail)*) $postfix $($tail)*) };
    (@cvt (<~> $($optail:tt)*) $postfix:tt try $($tail:tt)*) => { parser!(@cvt (try <~> $($optail)*) $postfix $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (<#> $($optail:tt)*) $postfix:tt try $($tail:tt)*) => { parser!(@cvt (try <#> $($optail)*) $postfix $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    //(@cvt (many $($optail:tt)*) $postfix:tt try $($tail:tt)*) => { parser!(@cvt (try many $($optail)*) $postfix $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed

    (@cvt (<|> $($optail:tt)*) $postfix:tt sat $($tail:tt)*) => { parser!(@cvt (sat <|> $($optail)*) $postfix $($tail)*) };
    (@cvt (*> $($optail:tt)*) $postfix:tt sat $($tail:tt)*) => { parser!(@cvt (sat *> $($optail)*) $postfix $($tail)*) };
    (@cvt (<* $($optail:tt)*) $postfix:tt sat $($tail:tt)*) => { parser!(@cvt (sat <* $($optail)*) $postfix $($tail)*) };
    (@cvt (<~> $($optail:tt)*) $postfix:tt sat $($tail:tt)*) => { parser!(@cvt (sat <~> $($optail)*) $postfix $($tail)*) };
    (@cvt (<#> $($optail:tt)*) $postfix:tt sat $($tail:tt)*) => { parser!(@cvt (sat <#> $($optail)*) $postfix $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (try $($optail:tt)*) $postfix:tt sat $($tail:tt)*) => { parser!(@cvt (sat try $($optail)*) $postfix $($tail)*) };
    (@cvt (many $($optail:tt)*) $postfix:tt sat $($tail:tt)*) => { parser!(@cvt (sat many $($optail)*) $postfix $($tail)*) };

    (@cvt (<|> $($optail:tt)*) $postfix:tt many $($tail:tt)*) => { parser!(@cvt (many <|> $($optail)*) $postfix $($tail)*) };
    (@cvt (*> $($optail:tt)*) $postfix:tt many $($tail:tt)*) => { parser!(@cvt (many *> $($optail)*) $postfix $($tail)*) };
    (@cvt (<* $($optail:tt)*) $postfix:tt many $($tail:tt)*) => { parser!(@cvt (many <* $($optail)*) $postfix $($tail)*) };
    (@cvt (<~> $($optail:tt)*) $postfix:tt many $($tail:tt)*) => { parser!(@cvt (many <~> $($optail)*) $postfix $($tail)*) };
    (@cvt (<#> $($optail:tt)*) $postfix:tt many $($tail:tt)*) => { parser!(@cvt (many <#> $($optail)*) $postfix $($tail)*) };

    
    // 6. if an operator w/ equal precedence is on top, pop and push
    (@cvt (<|> $($optail:tt)*) $postfix:tt <|> $($tail:tt)*) => { parser!(@cvt (<|> <|> $($optail)*) $postfix $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (try $($optail:tt)*) $postfix:tt try $($tail:tt)*) => { parser!(@cvt (try try $($optail)*) $postfix $($tail)*) };
    (@cvt (many $($optail:tt)*) $postfix:tt many $($tail:tt)*) => { parser!(@cvt (many many $($optail)*) $postfix $($tail)*) };

    // if try has higher precedence
    (@cvt (many $($optail:tt)*) $postfix:tt try $($tail:tt)*) => { parser!(@cvt (many try $($optail)*) $postfix $($tail)*) };
    (@cvt (try $($optail:tt)*) $postfix:tt many $($tail:tt)*) => { parser!(@cvt (try many $($optail)*) $postfix $($tail)*) };

    // if many has higher precedence
    // (@cvt (many $($optail:tt)*) $postfix:tt try $($tail:tt)*) => { parser!(@cvt (try many $($optail)*) $postfix $($tail)*) };
    // (@cvt (try $($optail:tt)*) $postfix:tt many $($tail:tt)*) => { parser!(@cvt (many try $($optail)*) $postfix $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed

    (@cvt (*> $($optail:tt)*) ($($postfix:tt)*) *> $($tail:tt)*) => { parser!(@cvt (*> $($optail)*) ($($postfix)* *>) $($tail)*) };
    (@cvt (*> $($optail:tt)*) ($($postfix:tt)*) <~> $($tail:tt)*) => { parser!(@cvt (<~> $($optail)*) ($($postfix)* *>) $($tail)*) };
    (@cvt (*> $($optail:tt)*) ($($postfix:tt)*) <* $($tail:tt)*) => { parser!(@cvt (<* $($optail)*) ($($postfix)* *>) $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (*> $($optail:tt)*) ($($postfix:tt)*) <#> $($tail:tt)*) => { parser!(@cvt (<#> $($optail)*) ($($postfix)* *>) $($tail)*) };
    (@cvt (<* $($optail:tt)*) ($($postfix:tt)*) <* $($tail:tt)*) => { parser!(@cvt (<* $($optail)*) ($($postfix)* <*) $($tail)*) };
    (@cvt (<* $($optail:tt)*) ($($postfix:tt)*) *> $($tail:tt)*) => { parser!(@cvt (*> $($optail)*) ($($postfix)* <*) $($tail)*) };
    (@cvt (<* $($optail:tt)*) ($($postfix:tt)*) <~> $($tail:tt)*) => { parser!(@cvt (<~> $($optail)*) ($($postfix)* <*) $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (<* $($optail:tt)*) ($($postfix:tt)*) <#> $($tail:tt)*) => { parser!(@cvt (<#> $($optail)*) ($($postfix)* <*) $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed

    (@cvt (<~> $($optail:tt)*) ($($postfix:tt)*) <~> $($tail:tt)*) => { parser!(@cvt (<~> $($optail)*) ($($postfix)* <~>) $($tail)*) };
    (@cvt (<~> $($optail:tt)*) ($($postfix:tt)*) *> $($tail:tt)*) => { parser!(@cvt (*> $($optail)*) ($($postfix)* <~>) $($tail)*) };
    (@cvt (<~> $($optail:tt)*) ($($postfix:tt)*) <* $($tail:tt)*) => { parser!(@cvt (<* $($optail)*) ($($postfix)* <~>) $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (<~> $($optail:tt)*) ($($postfix:tt)*) <#> $($tail:tt)*) => { parser!(@cvt (<#> $($optail)*) ($($postfix)* <~>) $($tail)*) };

    (@cvt (<#> $($optail:tt)*) ($($postfix:tt)*) <#> $($tail:tt)*) => { parser!(@cvt (<#> $($optail)*) ($($postfix)* <#>) $($tail)*) };
    (@cvt (<#> $($optail:tt)*) ($($postfix:tt)*) *> $($tail:tt)*) => { parser!(@cvt (*> $($optail)*) ($($postfix)* <#>) $($tail)*) };
    (@cvt (<#> $($optail:tt)*) ($($postfix:tt)*) <* $($tail:tt)*) => { parser!(@cvt (<* $($optail)*) ($($postfix)* <#>) $($tail)*) };
    (@cvt (<#> $($optail:tt)*) ($($postfix:tt)*) <~> $($tail:tt)*) => { parser!(@cvt (<~> $($optail)*) ($($postfix)* <#>) $($tail)*) };
    
    // 7. if an operator w/ higher precedence is on top, pop it to postfix
    (@cvt (*> $($optail:tt)*) ($($postfix:tt)*) <|> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* *>) <|> $($tail)*) };
    (@cvt (<* $($optail:tt)*) ($($postfix:tt)*) <|> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* <*) <|> $($tail)*) };
    (@cvt (<~> $($optail:tt)*) ($($postfix:tt)*) <|> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* <~>) <|> $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (<#> $($optail:tt)*) ($($postfix:tt)*) <|> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* <#>) <|> $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed

    (@cvt (pure $($optail:tt)*) ($($postfix:tt)*) <|> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* pure) <|> $($tail)*) };
    (@cvt (pure $($optail:tt)*) ($($postfix:tt)*) *> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* pure) *> $($tail)*) };
    (@cvt (pure $($optail:tt)*) ($($postfix:tt)*) <* $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* pure) <* $($tail)*) };
    (@cvt (pure $($optail:tt)*) ($($postfix:tt)*) <~> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* pure) <~> $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (pure $($optail:tt)*) ($($postfix:tt)*) <#> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* pure) <#> $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (pure $($optail:tt)*) ($($postfix:tt)*) try $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* pure) try $($tail)*) };
    (@cvt (pure $($optail:tt)*) ($($postfix:tt)*) many $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* pure) many $($tail)*) };

    (@cvt (empty $($optail:tt)*) ($($postfix:tt)*) <|> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* empty) <|> $($tail)*) };
    (@cvt (empty $($optail:tt)*) ($($postfix:tt)*) *> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* empty) *> $($tail)*) };
    (@cvt (empty $($optail:tt)*) ($($postfix:tt)*) <* $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* empty) <* $($tail)*) };
    (@cvt (empty $($optail:tt)*) ($($postfix:tt)*) <~> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* empty) <~> $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (empty $($optail:tt)*) ($($postfix:tt)*) <#> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* empty) <#> $($tail)*) };
    (@cvt (try $($optail:tt)*) ($($postfix:tt)*) <|> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* try) <|> $($tail)*) };
    (@cvt (try $($optail:tt)*) ($($postfix:tt)*) *> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* try) *> $($tail)*) };
    (@cvt (try $($optail:tt)*) ($($postfix:tt)*) <* $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* try) <* $($tail)*) };
    (@cvt (try $($optail:tt)*) ($($postfix:tt)*) <~> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* try) <~> $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (try $($optail:tt)*) ($($postfix:tt)*) <#> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* try) <#> $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    
Carlos Valencia's avatar
Carlos Valencia committed

    (@cvt (sat $($optail:tt)*) ($($postfix:tt)*) <|> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* sat) <|> $($tail)*) };
    (@cvt (sat $($optail:tt)*) ($($postfix:tt)*) *> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* sat) *> $($tail)*) };
    (@cvt (sat $($optail:tt)*) ($($postfix:tt)*) <* $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* sat) <* $($tail)*) };
    (@cvt (sat $($optail:tt)*) ($($postfix:tt)*) <~> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* sat) <~> $($tail)*) };
    (@cvt (sat $($optail:tt)*) ($($postfix:tt)*) <#> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* sat) <#> $($tail)*) };
Carlos Valencia's avatar
Carlos Valencia committed
    (@cvt (sat $($optail:tt)*) ($($postfix:tt)*) try $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* sat) try $($tail)*) };
    (@cvt (sat $($optail:tt)*) ($($postfix:tt)*) many $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* sat) many $($tail)*) };

    (@cvt (many $($optail:tt)*) ($($postfix:tt)*) <|> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* many) <|> $($tail)*) };
    (@cvt (many $($optail:tt)*) ($($postfix:tt)*) *> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* many) *> $($tail)*) };
    (@cvt (many $($optail:tt)*) ($($postfix:tt)*) <* $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* many) <* $($tail)*) };
    (@cvt (many $($optail:tt)*) ($($postfix:tt)*) <~> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* many) <~> $($tail)*) };
    (@cvt (many $($optail:tt)*) ($($postfix:tt)*) <#> $($tail:tt)*) => { parser!(@cvt ($($optail)*) ($($postfix)* many) <#> $($tail)*) };
    // 1. operands go to the postfix output
    (@cvt $operators:tt ($($postfix:tt)*) $head:tt $($tail:tt)*) => { parser!(@cvt $operators ($($postfix)* ($head)) $($tail)*) };
    
    // postfix interpreter
    (@pfx ($result:expr                     ) (                     )) => { $result };
Carlos Valencia's avatar
Carlos Valencia committed

    // // Char
    // (@pfx (($a:literal) $($stack:tt)*) ($($tail:tt)*)) => { parser!(@pfx (((
    //     crate::combinators::common::characters::Char{c: $a}
    // )) $($stack)*) ($($tail)*)) };

    // Empty
    (@pfx ($($stack:tt)*) (empty $($tail:tt)*)) => { parser!(@pfx (((
        crate::combinators::primitive_combinators::Empty{_t: std::marker::PhantomData}
    )) $($stack)*) ($($tail)*)) };

    // Pure
    (@pfx (($a:expr) $($stack:tt)*) (pure $($tail:tt)*)) => { parser!(@pfx (((
        crate::combinators::primitive_combinators::Pure{a: $a}
    )) $($stack)*) ($($tail)*)) };

    // Try
    (@pfx (($e:expr) $($stack:tt)*) (try $($tail:tt)*)) => { parser!(@pfx (((
        crate::combinators::primitive_combinators::Try{parser: crate::char!($e), _t: std::marker::PhantomData}
    )) $($stack)*) ($($tail)*)) };

Carlos Valencia's avatar
Carlos Valencia committed
    // Sat
    (@pfx (($e:expr) $($stack:tt)*) (sat $($tail:tt)*)) => { parser!(@pfx (((
        crate::combinators::primitive_combinators::Sat{sat_fun: $e}
    )) $($stack)*) ($($tail)*)) };

    // Map
    (@pfx (($a:expr) ($b:expr) $($stack:tt)*) (<#> $($tail:tt)*)) => { parser!(@pfx (((
        crate::combinators::primitive_combinators::Map{
            map_a_b_fun: $b,
            parser_a: crate::char!($a),
            _a: std::marker::PhantomData,
            _b: std::marker::PhantomData
            
        }
    )) $($stack)*) ($($tail)*)) };
Carlos Valencia's avatar
Carlos Valencia committed

    // Many
    (@pfx (($e:expr) $($stack:tt)*) (many $($tail:tt)*)) => { parser!(@pfx (((
        crate::combinators::non_primitive_combinators::Many{
            parser: crate::char!($e),
            _t: std::marker::PhantomData
        }
    )) $($stack)*) ($($tail)*)) };
    // <|>
    (@pfx (($a:expr) ($b:expr) $($stack:tt)*) (<|>        $($tail:tt)*)) => { parser!(@pfx (((
        crate::combinators::primitive_combinators::Alternative {
            parser_first: crate::char!($b), 
            parser_second: crate::char!($a),
            _t: std::marker::PhantomData
Carlos Valencia's avatar
Carlos Valencia committed
        }
    )) $($stack)*) ($($tail)*)) };
Carlos Valencia's avatar
Carlos Valencia committed

    // *>
    (@pfx (($a:expr) ($b:expr) $($stack:tt)*) (*>        $($tail:tt)*)) => { parser!(@pfx (((
        crate::combinators::non_primitive_combinators::ThenR{
            parser_first: crate::char!($b), 
            parser_second: crate::char!($a),
            _a: std::marker::PhantomData,
            _b: std::marker::PhantomData
        }
    )) $($stack)*) ($($tail)*)) };

    // <*
    (@pfx (($a:expr) ($b:expr) $($stack:tt)*) (<*        $($tail:tt)*)) => { parser!(@pfx (((
        crate::combinators::non_primitive_combinators::ThenL{
            parser_first: crate::char!($b), 
            parser_second: crate::char!($a),
Carlos Valencia's avatar
Carlos Valencia committed
            _a: std::marker::PhantomData,
            _b: std::marker::PhantomData
Carlos Valencia's avatar
Carlos Valencia committed
        }
    )) $($stack)*) ($($tail)*)) };
Carlos Valencia's avatar
Carlos Valencia committed

    // <~>
    (@pfx (($a:expr) ($b:expr) $($stack:tt)*) (<~>        $($tail:tt)*)) => { parser!(@pfx (((
        crate::combinators::primitive_combinators::Zip{
            parser_first: crate::char!($b), 
            parser_second: crate::char!($a),
Carlos Valencia's avatar
Carlos Valencia committed
            _a: std::marker::PhantomData,
            _b: std::marker::PhantomData
Carlos Valencia's avatar
Carlos Valencia committed
        }
    )) $($stack)*) ($($tail)*)) };
Carlos Valencia's avatar
Carlos Valencia committed

    (@pfx ($($stack:tt)*                    ) ($head:tt $($tail:tt)*)) => { parser!(@pfx ($head       $($stack)*) ($($tail)*)) };
    
    // Case when we have just one character. Parsing it another way would yield the character only due to the 2 artity contstrain
    ($e:literal) => {crate::combinators::common::characters::Char{c: $e}};
    
    // Removing outer brackets
    (($($t:tt)*)) => {parser!($($t)*)};

    ($($t:tt)*) => { parser!(@cvt () () $($t)*) };
    //                      |    |  |  ^ infix expression
    //                      |    |  ^ postfix expression
    //                      |    ^ operator stack
    //                      ^ convert infix to postfix
Carlos Valencia's avatar
Carlos Valencia committed