pulsar_frontend/
op.rs

1// Copyright (C) 2024 Ethan Uppal. All rights reserved.
2use super::token::TokenType;
3
4/// A precedence value must be strictly nonnegative.
5pub 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/// Parsing information for an operator.
28#[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    /// Constructs an operator from the given token type `ty` if one exists.
65    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}