pub use crate::parsers::{
alt, empty, lines, map, opt, pair, plus, sequence, single_value, star, RuleParser,
RuleSetBuilder,
};
#[macro_export]
macro_rules! parser {
($($pattern:tt)*) => { $crate::aoc_parse_helper!( $( $pattern )* ) }
}
#[macro_export]
#[doc(hidden)]
macro_rules! aoc_parse_helper {
(@seq [ => $mapper:expr ] [ $($stack:tt)* ] [ $($pats:tt ,)* ]) => {
$crate::macros::map(
$crate::aoc_parse_helper!(@reverse_map [ $($stack)* ] []),
| ( $crate::aoc_parse_helper!(@reverse_pats [ $($pats ,)* ] []) ) | $mapper ,
)
};
(@seq [ * ? $($tail:tt)* ] [ $($stack:expr ,)* ] [ $($pats:tt ,)* ]) => {
core::compile_error!("non-greedy quantifier `*?` is not supported")
};
(@seq [ + ? $($tail:tt)* ] [ $($stack:expr ,)* ] [ $($pats:tt ,)* ]) => {
core::compile_error!("non-greedy quantifier `+?` is not supported")
};
(@seq [ * $($tail:tt)* ] [ $top:expr , $($stack:expr ,)* ] [ $($pats:tt ,)* ]) => {
$crate::aoc_parse_helper!(@seq [ $($tail)* ] [ $crate::macros::star($top) , $($stack ,)* ] [ $($pats ,)* ])
};
(@seq [ + $($tail:tt)* ] [ $top:expr , $($stack:expr ,)* ] [ $($pats:tt ,)* ]) => {
$crate::aoc_parse_helper!(@seq [ $($tail)* ] [ $crate::macros::plus($top) , $($stack ,)* ] [ $($pats ,)* ])
};
(@seq [ ? $($tail:tt)* ] [ $top:expr , $($stack:tt)* ] [ $($pats:tt ,)* ]) => {
$crate::aoc_parse_helper!(@seq [ $($tail)* ] [ $crate::macros::opt($top) , $($stack)* ] [ $($pats ,)* ])
};
(@seq [ * $($tail:tt)* ] [ ] [ $($pats:tt ,)* ]) => {
core::compile_error!("quantifier `*` has to come after something, not at the start of an expression.")
};
(@seq [ + $($tail:tt)* ] [ ] [ $($pats:tt ,)* ]) => {
core::compile_error!("quantifier `+` has to come after something, not at the start of an expression.")
};
(@seq [ ? $($tail:tt)* ] [ ] [ $($pats:tt ,)* ]) => {
core::compile_error!("quantifier `?` has to come after something, not at the start of an expression.")
};
(@seq [ $label:ident : => $($tail:tt)* ] [ $($stack:expr ,)* ] [ $($pats:tt ,)* ]) => {
core::compile_error!(
core::concat!("missing pattern after `", core::stringify!($label), ":`")
);
};
(@seq [ $label:ident : ] [ $($stack:expr ,)* ] [ $($pats:tt ,)* ]) => {
core::compile_error!(
core::concat!("missing pattern after `", core::stringify!($label), ":`")
);
};
(@seq [ $label1:ident : $label2:ident : $( $tail:tt )* ] [ $($stack:expr ,)* ] [ $($pats:tt ,)* ]) => {
core::compile_error!(
core::concat!(
"missing pattern between `", core::stringify!($label1), ":` and `",
core::stringify!($label2), ":`"
)
);
};
(@seq [ $f:ident ( $($args:tt)* ) $($tail:tt)* ] [ $($stack:expr ,)* ] [ $($pats:tt ,)* ]) => {
$crate::aoc_parse_helper!(
@seq
[ $($tail)* ]
[
$crate::aoc_parse_helper!(@args ( $f ) [ $( $args )* ] [] ())
,
$($stack ,)*
]
[ _ , $($pats ,)* ]
)
};
(@seq [ $label:ident : $f:ident ( $( $args:tt )* ) $( $tail:tt )* ] [ $($stack:expr ,)* ] [ $($pats:tt ,)* ]) => {
$crate::aoc_parse_helper!(
@seq
[ $($tail)* ]
[
$crate::aoc_parse_helper!(@args ( $f ) [ $( $args )* ] [] ())
,
$($stack ,)*
]
[ $label , $($pats ,)* ]
)
};
(@seq [ $x:literal $($tail:tt)* ] [ $($stack:expr ,)* ] [ $($pats:tt ,)* ]) => {
$crate::aoc_parse_helper!(
@seq
[ $($tail)* ]
[
$crate::aoc_parse_helper!(@prim $x) ,
$($stack ,)*
]
[ _, $($pats ,)* ]
)
};
(@seq [ $label:ident : $x:tt $($tail:tt)* ] [ $($stack:expr ,)* ] [ $($pats:tt ,)* ]) => {
$crate::aoc_parse_helper!(
@seq
[ $($tail)* ]
[
$crate::aoc_parse_helper!(@prim $x) ,
$($stack ,)*
]
[ $label , $($pats ,)* ]
)
};
(@seq [ $x:tt $($tail:tt)* ] [ $($stack:expr ,)* ] [ $($pats:tt ,)* ]) => {
$crate::aoc_parse_helper!(
@seq
[ $($tail)* ]
[
$crate::aoc_parse_helper!(@prim $x) ,
$($stack ,)*
]
[ _ , $($pats ,)* ]
)
};
(@seq [ ] [ $($parts:expr ,)* ] [ $($pats:tt ,)* ]) => {
$crate::aoc_parse_helper!(@reverse [ $($parts ,)* ] [])
};
(@seq [ $($tail:tt)* ] [ $($parts:expr ,)* ] [ $($pats:tt ,)* ]) => {
core::compile_error!(stringify!(unrecognized syntax @ $($tail)*))
};
(@reverse [ ] [ ]) => {
$crate::macros::empty()
};
(@reverse [ ] [ $out:expr ]) => {
$out
};
(@reverse [ $head:expr , $($tail:expr ,)* ] [ ]) => {
$crate::aoc_parse_helper!(@reverse [ $($tail ,)* ] [ $head ])
};
(@reverse [ $head:expr , $($tail:expr ,)* ] [ $out:expr ]) => {
$crate::aoc_parse_helper!(@reverse [ $($tail ,)* ] [ $crate::macros::sequence($head, $out) ])
};
(@reverse_map [] []) => {
$crate::macros::empty()
};
(@reverse_map [] [ $out:expr ]) => {
$out
};
(@reverse_map [ $head:expr , $( $tail:expr , )* ] []) => {
$crate::aoc_parse_helper!(@reverse_map [ $( $tail , )* ] [ $head ])
};
(@reverse_map [ $head:expr , $( $tail:expr , )* ] [ $out:expr ]) => {
$crate::aoc_parse_helper!(
@reverse_map
[ $( $tail , )* ]
[ $crate::macros::pair($head, $out) ]
)
};
(@reverse_pats [] []) => {
()
};
(@reverse_pats [] [ $out:pat ]) => {
$out
};
(@reverse_pats [ $head:pat , $( $tail:pat , )* ] []) => {
$crate::aoc_parse_helper!(@reverse_pats [ $( $tail , )* ] [ $head ])
};
(@reverse_pats [ $head:pat , $( $tail:pat , )* ] [ $out:pat ]) => {
$crate::aoc_parse_helper!(@reverse_pats [ $( $tail , )* ] [ ($head, $out) ])
};
(@prim $x:ident) => {
$x
};
(@prim $x:literal) => {
$x
};
(@prim ( $($nested:tt)* )) => {
$crate::macros::single_value(
$crate::aoc_parse_helper!(@seq [ $( $nested )* ] [ ] [ ])
)
};
(@prim { $($nested:tt)* }) => {
$crate::aoc_parse_helper!(@list [ $( $nested )* ] [ ] [ ])
};
(@args ( $f:expr ) [ , $($tail:tt)* ] [ $($seq:tt)* ] ( $( $arg:expr , )* )) => {
$crate::aoc_parse_helper!(
@args
( $f )
[ $( $tail )* ]
[ ]
(
$( $arg , )*
$crate::aoc_parse_helper!(@seq [ $( $seq )* ] [ ] [ ]) ,
)
)
};
(@args ( $f:expr ) [ $next:tt $($tail:tt)* ] [ $($seq:tt)* ] ( $( $out:expr , )* )) => {
$crate::aoc_parse_helper!(
@args
( $f )
[ $( $tail )* ]
[ $( $seq )* $next ]
( $( $out , )* )
)
};
(@args ( $f:expr ) [] [] ( $( $out:expr , )* )) => {
$f ( $( $out , )* )
};
(@args ( $f:expr ) [] [ $($seq:tt)+ ] ( $( $out:expr , )* )) => {
$crate::aoc_parse_helper!(@args ( $f ) [,] [ $($seq)+ ] ( $( $out , )* ))
};
(@list [ , $($tail:tt)* ] [ $($seq:tt)* ] [ ]) => {
$crate::aoc_parse_helper!(
@list
[ $( $tail )* ]
[ ]
[ $crate::aoc_parse_helper!(@seq [ $( $seq )* ] [ ] [ ]) ]
)
};
(@list [ , $($tail:tt)* ] [ $($seq:tt)* ] [ $out:expr ]) => {
$crate::aoc_parse_helper!(
@list
[ $( $tail )* ]
[ ]
[ $crate::macros::alt($out, $crate::aoc_parse_helper!(@seq [ $( $seq )* ] [ ] [ ])) ]
)
};
(@list [ $next:tt $($tail:tt)* ] [ $($seq:tt)* ] [ $($out:expr)? ]) => {
$crate::aoc_parse_helper!(
@list
[ $( $tail )* ]
[ $( $seq )* $next ]
[ $( $out )? ]
)
};
(@list [ ] [ ] [ ]) => {
::core::compile_error("no arms in alternation")
};
(@list [ ] [ ] [ $out:expr ]) => {
$out
};
(@list [ ] [ $($seq:tt)+ ] [ $( $out:expr )? ]) => {
$crate::aoc_parse_helper!(@list [,] [ $($seq)+ ] [ $( $out )? ])
};
(@rules [] ( $( $pattern:tt )* )) => {
$crate::parser!(@seq [ $( $pattern )* ] [] [])
};
(@rules
[ $( [ rule $name:ident : $output_ty:ty = $( $rule_pat:tt )* ] )+ ]
( $( $pattern:tt )* )
) => {
{
let mut builder = $crate::macros::RuleSetBuilder::new();
$(
let $name : $crate::macros::RuleParser<$output_ty> = builder.new_rule();
)*
$(
builder.assign_parser_for_rule(
&$name,
$crate::parser!(@seq [ $( $rule_pat )* ] [] [])
);
)*
builder.build($crate::parser!(@seq [ $( $pattern )* ] [] []))
}
};
(@split_rules [ rule $( $tail:tt )* ] [] [ $( $out:tt )* ]) => {
$crate::aoc_parse_helper!(
@split_rules
[ $( $tail )* ]
[ rule ]
[ $( $out )* ]
)
};
(@split_rules [ $( $tail:tt )+ ] [] [ $( $out:tt )* ]) => {
$crate::aoc_parse_helper!(
@rules
[ $( $out )* ]
( $( $tail )+ )
)
};
(@split_rules [ ; $( $tail:tt )* ] [ $( $rule:tt )* ] [ $( $out:tt )* ]) => {
$crate::aoc_parse_helper!(
@split_rules
[ $( $tail )* ]
[]
[ $( $out )* [ $( $rule )* ] ]
)
};
(@split_rules [ rule $( $tail:tt )* ] [ $( $rule:tt )+ ] [ $( $out:tt )* ]) => {
::core::compile_error!(stringify!(missing semicolon before: rule $($tail)*))
};
(@split_rules [ $other:tt $( $tail:tt )* ] [ $( $rule:tt )* ] [ $( $out:tt )* ]) => {
$crate::aoc_parse_helper!(
@split_rules
[ $( $tail )* ]
[ $( $rule )* $other ]
[ $( $out )* ]
)
};
(@split_rules [] [] [ $( $out:tt )* ]) => {
::core::compile_error!("missing final pattern (at the end of a rule set, specify which rule is the starting point for parsing)")
};
(@ $($tail:tt)*) => {
::core::compile_error!(stringify!(unrecognized syntax @ $($tail)*))
};
( $( $tail:tt )* ) => {
$crate::macros::single_value(
$crate::aoc_parse_helper!(@split_rules [ $($tail)* ] [ ] [ ])
)
};
}