cas_parser/parser/ast/
unary.rs1use cas_error::Error;
2use crate::{
3 parser::{
4 ast::{binary::Binary, expr::{Expr, Primary}},
5 error::NonFatal,
6 fmt::Latex,
7 token::op::{Associativity, UnaryOp},
8 Parser,
9 ParseResult,
10 },
11 return_if_ok,
12};
13use std::{fmt, ops::Range};
14
15#[cfg(feature = "serde")]
16use serde::{Deserialize, Serialize};
17
18fn try_parse_unary_op(input: &mut Parser, associativity: Associativity) -> Result<UnaryOp, Vec<Error>> {
21 input.try_parse_then::<UnaryOp, _>(|op, input| {
22 if op.associativity() == associativity {
23 ParseResult::Ok(())
24 } else {
25 ParseResult::Unrecoverable(vec![input.error(NonFatal)])
26 }
27 }).forward_errors(&mut Vec::new())
28}
29
30#[derive(Debug, Clone, PartialEq, Eq)]
34#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
35pub struct Unary {
36 pub operand: Box<Expr>,
38
39 pub op: UnaryOp,
41
42 pub span: Range<usize>,
44}
45
46impl Unary {
47 pub fn span(&self) -> Range<usize> {
49 self.span.clone()
50 }
51
52 pub fn parse_right(input: &mut Parser, recoverable_errors: &mut Vec<Error>) -> Result<Self, Vec<Error>> {
54 let op = try_parse_unary_op(input, Associativity::Right)?;
55 let op_precedence = op.precedence();
56 let start_span = op.span.start;
57 let operand = {
58 let lhs = Unary::parse_or_lower(input, recoverable_errors)?;
59 Binary::parse_expr(input, recoverable_errors, lhs, op_precedence)?.0
60 };
61 let end_span = operand.span().end;
62 Ok(Self {
63 operand: Box::new(operand),
64 op,
65 span: start_span..end_span,
66 })
67 }
68
69 pub fn parse_left_or_operand(input: &mut Parser, recoverable_errors: &mut Vec<Error>) -> Result<Expr, Vec<Error>> {
76 let operand = input.try_parse::<Primary>().forward_errors(recoverable_errors)?;
77 let start_span = operand.span().start;
78
79 let op = match try_parse_unary_op(input, Associativity::Left) {
81 Ok(op) => op,
82 Err(_) => return Ok(operand.into()),
83 };
84 let mut result = Self {
85 operand: Box::new(operand.into()),
86 op,
87 span: start_span..input.prev_token().unwrap().span.end,
88 };
89
90 while let Ok(next_op) = try_parse_unary_op(input, Associativity::Left) {
92 result = Self {
93 operand: Box::new(Expr::Unary(result)),
94 op: next_op,
95 span: start_span..input.prev_token().unwrap().span.end,
96 };
97 }
98
99 Ok(Expr::Unary(result))
100 }
101
102 pub fn parse_or_lower(
104 input: &mut Parser,
105 recoverable_errors: &mut Vec<Error>
106 ) -> Result<Expr, Vec<Error>> {
107 let _ = return_if_ok!(Self::parse_right(input, recoverable_errors).map(Expr::Unary));
108 Self::parse_left_or_operand(input, recoverable_errors)
109 }
110}
111
112impl std::fmt::Display for Unary {
113 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
114 match self.op.associativity() {
115 Associativity::Left => {
116 self.operand.fmt(f)?;
117 self.op.fmt(f)
118 },
119 Associativity::Right => {
120 self.op.fmt(f)?;
121 self.operand.fmt(f)
122 },
123 }
124 }
125}
126
127impl Latex for Unary {
128 fn fmt_latex(&self, f: &mut fmt::Formatter) -> fmt::Result {
129 match self.op.associativity() {
130 Associativity::Left => {
131 self.operand.fmt_latex(f)?;
132 self.op.fmt_latex(f)
133 },
134 Associativity::Right => {
135 self.op.fmt_latex(f)?;
136 self.operand.fmt_latex(f)
137 },
138 }
139 }
140}