Skip to main content

mechylang/parser/expressions/
prefix_expression.rs

1use std::fmt;
2use std::fmt::{Display, Formatter};
3use std::rc::Rc;
4use serde::Serialize;
5use crate::{Expression, Parser, Span, TokenKind, trace};
6use crate::parser::{
7    expressions::Precedence,
8    Error,
9    Result,
10};
11use crate::parser::expressions::ExpressionSpanExt;
12
13#[derive(Debug, PartialEq, Clone, Serialize)]
14pub struct PrefixExpression {
15    pub span: Span,
16    pub right_span: Span,
17    pub operator_span: Span,
18    pub operator: PrefixOperator,
19    pub right: Rc<Expression>,
20}
21
22impl Display for PrefixExpression {
23    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
24        write!(f, "({}{})", self.operator, self.right)
25    }
26}
27
28#[derive(Debug, Clone, PartialEq, Serialize, Copy)]
29pub enum PrefixOperator {
30    Bang,
31    Minus,
32    BitwiseNot,
33    Ampersand,
34    Asterisk,
35}
36
37impl Display for PrefixOperator {
38    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
39        match self {
40            PrefixOperator::Bang => write!(f, "!"),
41            PrefixOperator::Minus => write!(f, "-"),
42            PrefixOperator::BitwiseNot => write!(f, "~"),
43            PrefixOperator::Ampersand => write!(f, "&"),
44            PrefixOperator::Asterisk => write!(f, "*"),
45        }
46    }
47}
48
49impl Parser<'_> {
50    pub(crate) fn parse_prefix(&mut self) -> Result<Expression> {
51        let _trace = trace!("parse_prefix");
52        match self.cur_token.kind {
53            TokenKind::Identifier(_) => Ok(Expression::Identifier(self.parse_identifier()?)),
54            TokenKind::Number(_) => self.parse_number(),
55            TokenKind::True | TokenKind::False => Ok(Expression::Boolean(self.parse_boolean()?)),
56
57            TokenKind::Fn => Ok(Expression::Function(self.parse_function_literal()?)),
58
59            TokenKind::If => Ok(Expression::If(self.parse_if_expression()?)),
60
61            TokenKind::Bang |
62            TokenKind::Minus |
63            TokenKind::BitwiseNot |
64            TokenKind::Ampersand => Ok(Expression::Prefix(self.parse_prefix_expression()?)),
65
66            // Block expression
67            TokenKind::LeftSquirly => Ok(Expression::Block(self.parse_block_expression()?)),
68
69            TokenKind::Struct => Ok(Expression::StructLiteral(self.parse_struct_literal()?)),
70            TokenKind::String(_) => Ok(Expression::StringLiteral(self.parse_string()?)),
71
72            TokenKind::LeftParen => self.parse_grouped_expression(),
73
74            TokenKind::LeftSquare => Ok(Expression::ArrayLiteral(self.parse_array_expression()?)),
75
76            TokenKind::For => Ok(Expression::For(self.parse_for_expression()?)),
77            TokenKind::While => Ok(Expression::While(self.parse_while_expression()?)),
78
79            TokenKind::RangeExclusive | TokenKind::RangeInclusive => self.parse_range_prefix_expression(),
80            _ => Err(Error::InvalidPrefix {
81                span: self.cur_token.span.clone(),
82                found: self.cur_token.kind.clone(),
83            }),
84        }
85    }
86
87    pub(super) fn parse_prefix_expression(&mut self) -> Result<PrefixExpression> {
88        let _trace = trace!("parse_prefix_expression");
89        let operator_span = self.cur_token.span.clone();
90
91        let operator = match &self.cur_token.kind {
92            TokenKind::Bang => PrefixOperator::Bang,
93            TokenKind::Minus => PrefixOperator::Minus,
94            TokenKind::BitwiseNot => PrefixOperator::BitwiseNot,
95            TokenKind::Ampersand => PrefixOperator::Ampersand,
96            _ => {
97                return Err(Error::InvalidPrefix {
98                    span: self.cur_token.span.clone(),
99                    found: self.cur_token.kind.clone(),
100                })
101            }
102        };
103
104        self.next_token()?;
105
106        let right = self.parse_expression(Precedence::Prefix)?;
107
108        Ok(PrefixExpression {
109            span: self.span_with_start(&operator_span),
110            right_span: right.span().clone(),
111            operator_span,
112            operator,
113            right: Rc::new(right),
114        })
115    }
116}