compose_syntax/ast/
assignment.rs1use crate::ast::Expr;
2use crate::ast::macros::node;
3use crate::kind::SyntaxKind;
4
5node! {
6 struct Assignment
7}
8
9impl<'a> Assignment<'a> {
10 pub fn lhs(self) -> Expr<'a> {
11 self.0.cast_first()
12 }
13
14 pub fn op(self) -> AssignOp {
15 self.0.children().find_map(|n| AssignOp::from_kind(n.kind()))
16 .unwrap_or(AssignOp::Assign)
17 }
18
19 pub fn rhs(self) -> Expr<'a> {
20 self.0.cast_last()
21 }
22}
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25pub enum AssignOp {
26 Assign,
27 AddAssign,
28 SubAssign,
29 MulAssign,
30 DivAssign,
31 ModAssign,
32}
33
34impl AssignOp {
35 pub(crate) fn from_kind(kind: SyntaxKind) -> Option<Self> {
36 Some(match kind {
37 SyntaxKind::Eq => AssignOp::Assign,
38 SyntaxKind::PlusEq => AssignOp::AddAssign,
39 SyntaxKind::MinusEq => AssignOp::SubAssign,
40 SyntaxKind::StarEq => AssignOp::MulAssign,
41 SyntaxKind::SlashEq => AssignOp::DivAssign,
42 SyntaxKind::AmpersandEq => AssignOp::ModAssign,
43 _ => return None,
44 })
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use crate::assert_ast;
51 use crate::ast::{Ident, Int};
52 use super::*;
53
54 #[test]
55 fn test_assign_op() {
56 assert_eq!(AssignOp::from_kind(SyntaxKind::Eq), Some(AssignOp::Assign));
57 assert_eq!(AssignOp::from_kind(SyntaxKind::PlusEq), Some(AssignOp::AddAssign));
58 assert_eq!(AssignOp::from_kind(SyntaxKind::MinusEq), Some(AssignOp::SubAssign));
59 assert_eq!(AssignOp::from_kind(SyntaxKind::StarEq), Some(AssignOp::MulAssign));
60 assert_eq!(AssignOp::from_kind(SyntaxKind::SlashEq), Some(AssignOp::DivAssign));
61 assert_eq!(AssignOp::from_kind(SyntaxKind::AmpersandEq), Some(AssignOp::ModAssign));
62 }
63
64 #[test]
65 fn assignment() {
66 assert_ast!(
67 "a = 23",
68 assignment as Assignment {
69 with lhs: Ident = assignment.lhs() => {
70 assert_eq!(lhs.get(), "a");
71 }
72 with rhs: Int = assignment.rhs() => {
73 assert_eq!(rhs.get(), 23);
74 }
75 }
76 )
77 }
78}