use super::{
ast::{RangeCard, Expr, List, CardRank, Span, CardSuit, Term, TermElem},
Error,
};
grammar(is_shortdeck: bool);
extern {
type Error = Error;
}
pub Expr: Box<Expr> = {
<l: Expr > "," <r: ExprAnd> => Box::new(Expr::Or(l, r)),
ExprAnd => <>,
}
ExprAnd: Box<Expr> = {
<l: ExprAnd> ":" <r: ExprNot> => Box::new(Expr::And(l, r)),
ExprNot => <>,
}
ExprNot: Box<Expr> = {
<l: ExprNot> "!" <r: ExprLeaf> => Box::new(Expr::Not(l, r)),
ExprLeaf => <>,
}
ExprLeaf: Box<Expr> = {
"(" <e: Expr> ")" => e,
ExprTerm,
}
ExprTerm: Box<Expr> = {
<l: @R> <t: Term> <r: @R> => Box::new((t, (l, r)).into()),
}
pub(crate) Term: Term = {
TermElem+ => <>.into(),
RawSpan => <>.into(),
}
pub(crate) RawSpan: Span = {
<l: @R> <cs: TermElem+> "-" <r: @R> =>? Span::spandown(<>),
<l: @R> <cs: TermElem+> "+" <r: @R> =>? Span::spanup(<>),
<l: @R> <top: TermElem+> "-" <btm: TermElem+> <r: @R> =>? Span::spanto(<>),
}
TermElem: TermElem = {
RangeCard => TermElem::Card(<>),
List => TermElem::List(<>),
"[" <s: Span> "]" => TermElem::Span(s),
}
pub(crate) Span: Span = {
<l: @R> <cs: RangeCard+> "-" <r: @R> =>? Span::spandown(<>),
<l: @R> <cs: RangeCard+> "+" <r: @R> =>? Span::spanup(<>),
<l: @R> <top: RangeCard+> "-" <btm: RangeCard+> <r: @R> =>? Span::spanto(<>),
}
pub(crate) List: List = <l: @R> "[" <v: CommaSep<RangeCard>> "]" <r: @R> =>? (<>).try_into();
pub(crate) RangeCard: RangeCard = {
CardRank => (<>).into(),
CardSuit => (<>).into(),
RankSuit => (<>).into(),
}
CardRank: CardRank = <l: @R> <s: "Rank"> <r: @R> =>?
CardRank::from_token(is_shortdeck, s.chars().next().unwrap(), (l, r));
CardSuit: CardSuit = <l: @R> <s: "Suit"> <r: @R> =>?
CardSuit::from_token(s.chars().next().unwrap(), (l, r));
RankSuit: (CardRank, CardSuit) = { <l: @R> <s: "RankSuit"> <r: @R> =>? Ok((
CardRank::from_token(is_shortdeck, s.chars().nth(0).unwrap(), (l, r-1))?,
CardSuit::from_token(s.chars().nth(1).unwrap(), (l+1, r))?,
)) }
CommaSep<T>: Vec<T> = {
<head: T> <rest: ("," <T>)*> ","? =>
[head].into_iter().chain(rest.into_iter()).collect::<Vec<_>>()
};
match {
r"(?i)[23456789TJQKABEFGILMNOPRUV\*][shdcwxyz]" => "RankSuit",
} else {
r"(?i)[23456789TJQKABEFGILMNOPRUV\*]" => "Rank",
r"(?i)[shdcwxyz]" => "Suit",
_
}