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