Enum parsel::ast::RightAssoc
source · pub enum RightAssoc<O, L> {
Binary {
lhs: L,
op: O,
rhs: Box<Self>,
},
Lhs(L),
}
Expand description
Helper type for parsing right-associative binary infix operators.
Reduces deep right-recursion by parsing a stream of binary infix operators iteratively, then transforming the sequence of nodes into a right-leaning tree.
L
is the type of the left-hand side of the production, i.e., the sub-production at the next highest precedence level.O
is the type of the interleaved binary operator itself.
That is, a production in EBNF style would look like:
RightAssoc = L O RightAssoc
| L
Examples
#[derive(PartialEq, Eq, Debug, Parse, ToTokens)]
enum Term {
Lit(LitBool),
Var(Ident),
Not(
Tilde,
#[parsel(recursive)]
Box<Term>,
),
Group(
#[parsel(recursive)]
Box<Paren<Expr>>
),
}
type Expr = RightAssoc<
Or,
RightAssoc<
And,
Term
>
>;
let actual: Expr = parse_quote!((~false | a) & ~(b & c & true));
let expected = RightAssoc::<Or, _>::Lhs(RightAssoc::<And, _>::Binary {
lhs: Term::Group(Box::new(Paren::from(
RightAssoc::<Or, _>::Binary {
lhs: RightAssoc::<And, _>::Lhs(Term::Not(
Tilde::default(),
Box::new(Term::Lit(LitBool::from(false)))
)),
op: Or::default(),
rhs: Box::new(RightAssoc::<Or, _>::Lhs(
RightAssoc::<And, _>::Lhs(
Term::Var(ident("a"))
)
)),
}
))),
op: And::default(),
rhs: Box::new(RightAssoc::<And, _>::Lhs(
Term::Not(
Tilde::default(),
Box::new(Term::Group(Box::new(Paren::from(
RightAssoc::<Or, _>::Lhs(RightAssoc::<And, _>::Binary {
lhs: Term::Var(ident("b")),
op: And::default(),
rhs: Box::new(RightAssoc::<And, _>::Binary {
lhs: Term::Var(ident("c")),
op: And::default(),
rhs: Box::new(RightAssoc::<And, _>::Lhs(
Term::Lit(LitBool::from(true)),
)),
}),
})
))))
)
)),
});
assert_eq!(actual, expected);
assert_eq!(actual.to_string(), expected.to_string());
Variants§
Binary
A right-associative binary infix operator was found.
Lhs(L)
No binary operator was found at this level of precedence, so simply forward to the next level.
Trait Implementations§
source§impl<O: Clone, L: Clone> Clone for RightAssoc<O, L>
impl<O: Clone, L: Clone> Clone for RightAssoc<O, L>
source§fn clone(&self) -> RightAssoc<O, L>
fn clone(&self) -> RightAssoc<O, L>
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moresource§impl<O, L> From<L> for RightAssoc<O, L>
impl<O, L> From<L> for RightAssoc<O, L>
source§impl<O, L> Parse for RightAssoc<O, L>where
O: Parse,
L: Parse,
impl<O, L> Parse for RightAssoc<O, L>where O: Parse, L: Parse,
fn parse(input: ParseStream<'_>) -> Result<Self>
source§impl<O: PartialEq, L: PartialEq> PartialEq<RightAssoc<O, L>> for RightAssoc<O, L>
impl<O: PartialEq, L: PartialEq> PartialEq<RightAssoc<O, L>> for RightAssoc<O, L>
source§fn eq(&self, other: &RightAssoc<O, L>) -> bool
fn eq(&self, other: &RightAssoc<O, L>) -> bool
self
and other
values to be equal, and is used
by ==
.source§impl<O, L> ToTokens for RightAssoc<O, L>where
O: ToTokens,
L: ToTokens,
impl<O, L> ToTokens for RightAssoc<O, L>where O: ToTokens, L: ToTokens,
source§fn to_tokens(&self, tokens: &mut TokenStream)
fn to_tokens(&self, tokens: &mut TokenStream)
source§fn to_token_stream(&self) -> TokenStream
fn to_token_stream(&self) -> TokenStream
source§fn into_token_stream(self) -> TokenStreamwhere
Self: Sized,
fn into_token_stream(self) -> TokenStreamwhere Self: Sized,
impl<O: Eq, L: Eq> Eq for RightAssoc<O, L>
impl<O, L> StructuralEq for RightAssoc<O, L>
impl<O, L> StructuralPartialEq for RightAssoc<O, L>
Auto Trait Implementations§
impl<O, L> RefUnwindSafe for RightAssoc<O, L>where L: RefUnwindSafe, O: RefUnwindSafe,
impl<O, L> Send for RightAssoc<O, L>where L: Send, O: Send,
impl<O, L> Sync for RightAssoc<O, L>where L: Sync, O: Sync,
impl<O, L> Unpin for RightAssoc<O, L>where L: Unpin, O: Unpin,
impl<O, L> UnwindSafe for RightAssoc<O, L>where L: UnwindSafe, O: UnwindSafe,
Blanket Implementations§
source§impl<T> Spanned for Twhere
T: Spanned + ?Sized,
impl<T> Spanned for Twhere T: Spanned + ?Sized,
source§fn span(&self) -> Span
fn span(&self) -> Span
Span
covering the complete contents of this syntax tree
node, or Span::call_site()
if this node is empty.source§impl<T> SpannedExt for Twhere
T: Spanned + ?Sized,
impl<T> SpannedExt for Twhere T: Spanned + ?Sized,
source§fn byte_range(&self, source: &str) -> Range<usize>
fn byte_range(&self, source: &str) -> Range<usize>
TODO(H2CO3): a faster, less naive implementation would be great.
We should use the byte offset of start
to compute that of end
,
sparing the double scan of the source up until the start location.
let source = r#"
-3.667
1248 "string ű literal"
"wíőzs"
"#;
let tokens: Many<Lit> = source.parse()?;
assert_eq!(tokens.len(), 4);
assert_eq!(tokens[0].byte_range(source), 4..10);
assert_eq!(tokens[1].byte_range(source), 13..17);
assert_eq!(tokens[2].byte_range(source), 19..38);
assert_eq!(tokens[3].byte_range(source), 45..54);
source§fn char_range(&self, source: &str) -> Range<usize>
fn char_range(&self, source: &str) -> Range<usize>
TODO(H2CO3): a faster, less naive implementation would be great.
We should use the char offset of start
to compute that of end
,
sparing the double scan of the source up until the start location.
let source = r#"
-3.667
1248 "string ű literal"
"wíőzs"
"#;
let tokens: Many<Lit> = source.parse()?;
assert_eq!(tokens.len(), 4);
assert_eq!(tokens[0].char_range(source), 4..10);
assert_eq!(tokens[1].char_range(source), 13..17);
assert_eq!(tokens[2].char_range(source), 19..37);
assert_eq!(tokens[3].char_range(source), 44..51);