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
Fields
rhs: Box<Self>
Right-hand side of the binary operation.
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
sourceimpl<O: Clone, L: Clone> Clone for RightAssoc<O, L>
impl<O: Clone, L: Clone> Clone for RightAssoc<O, L>
sourcefn clone(&self) -> RightAssoc<O, L>
fn clone(&self) -> RightAssoc<O, L>
1.0.0 · sourcefn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moresourceimpl<O, L> Debug for RightAssoc<O, L>where
O: Debug,
L: Debug,
impl<O, L> Debug for RightAssoc<O, L>where
O: Debug,
L: Debug,
sourceimpl<O, L> Display for RightAssoc<O, L>where
O: ToTokens,
L: ToTokens,
impl<O, L> Display for RightAssoc<O, L>where
O: ToTokens,
L: ToTokens,
sourceimpl<O, L> From<L> for RightAssoc<O, L>
impl<O, L> From<L> for RightAssoc<O, L>
sourceimpl<O, L> FromStr for RightAssoc<O, L>where
O: Parse,
L: Parse,
impl<O, L> FromStr for RightAssoc<O, L>where
O: Parse,
L: Parse,
sourceimpl<O: Hash, L: Hash> Hash for RightAssoc<O, L>
impl<O: Hash, L: Hash> Hash for RightAssoc<O, L>
sourceimpl<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>
sourceimpl<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>
sourcefn eq(&self, other: &RightAssoc<O, L>) -> bool
fn eq(&self, other: &RightAssoc<O, L>) -> bool
sourceimpl<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,
sourcefn to_tokens(&self, tokens: &mut TokenStream)
fn to_tokens(&self, tokens: &mut TokenStream)
sourcefn to_token_stream(&self) -> TokenStream
fn to_token_stream(&self) -> TokenStream
sourcefn into_token_stream(self) -> TokenStream
fn into_token_stream(self) -> TokenStream
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
sourceimpl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
sourceimpl<T> Spanned for Twhere
T: Spanned + ?Sized,
impl<T> Spanned for Twhere
T: Spanned + ?Sized,
sourcefn 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. Read moresourceimpl<T> SpannedExt for Twhere
T: Spanned + ?Sized,
impl<T> SpannedExt for Twhere
T: Spanned + ?Sized,
sourcefn 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);
sourcefn 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);