1use super::token::TokenType;
3
4pub type Precedence = i32;
6
7#[derive(PartialEq, Eq, Clone, Copy)]
8pub enum Associativity {
9 Left,
10 Right
11}
12
13pub struct InfixBinaryOp {
14 pub precedence: Precedence,
15 pub associativity: Associativity,
16 pub name: Option<String>,
17 pub required_token_ty: Option<TokenType>
18}
19
20pub struct PrefixUnaryOp {}
21
22pub struct PostfixBinaryOp {
23 pub close_token_ty: TokenType,
24 pub name: Option<String>
25}
26
27#[derive(Default)]
29pub struct Op {
30 pub infix_binary: Option<InfixBinaryOp>,
31 pub prefix_unary: Option<PrefixUnaryOp>,
32 pub postfix_binary: Option<PostfixBinaryOp>
33}
34
35impl Op {
36 pub fn infix_binary(
37 mut self, precedence: Precedence, associativity: Associativity,
38 name: Option<String>, required_token_ty: Option<TokenType>
39 ) -> Self {
40 self.infix_binary = Some(InfixBinaryOp {
41 precedence,
42 associativity,
43 name,
44 required_token_ty
45 });
46 self
47 }
48
49 pub fn prefix_unary(mut self) -> Self {
50 self.prefix_unary = Some(PrefixUnaryOp {});
51 self
52 }
53
54 pub fn postfix_binary(
55 mut self, close_token_ty: TokenType, name: Option<String>
56 ) -> Self {
57 self.postfix_binary = Some(PostfixBinaryOp {
58 close_token_ty,
59 name
60 });
61 self
62 }
63
64 pub fn from(ty: TokenType) -> Option<Op> {
66 match ty {
67 TokenType::Plus | TokenType::Minus => Some(
68 Op::default()
69 .infix_binary(50, Associativity::Left, None, None)
70 .prefix_unary()
71 ),
72 TokenType::Times => Some(Op::default().infix_binary(
73 100,
74 Associativity::Left,
75 Some("multiplication".into()),
76 None
77 )),
78 TokenType::LeftBracket => Some(Op::default().postfix_binary(
79 TokenType::RightBracket,
80 Some("subscript".into())
81 )),
82 TokenType::Dot => Some(Op::default().infix_binary(
83 150,
84 Associativity::Left,
85 Some("member access".into()),
86 Some(TokenType::Identifier)
87 )),
88 _ => None
89 }
90 }
91
92 pub fn is_unary_prefix(&self) -> bool {
93 self.prefix_unary.is_some()
94 }
95
96 pub fn is_infix_binary(&self) -> bool {
97 self.infix_binary.is_some()
98 }
99
100 pub fn is_postfix_binary(&self) -> bool {
101 self.postfix_binary.is_some()
102 }
103}