cas_parser/parser/ast/
return_expr.rs1use cas_error::Error;
2use crate::parser::{
3 ast::expr::Expr,
4 error::ReturnOutsideFunction,
5 fmt::Latex,
6 keyword::Return as ReturnToken,
7 Parse,
8 Parser,
9};
10use std::{fmt, ops::Range};
11
12#[cfg(feature = "serde")]
13use serde::{Deserialize, Serialize};
14
15#[derive(Debug, Clone, PartialEq, Eq)]
17#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
18pub struct Return {
19 pub value: Option<Box<Expr>>,
21
22 pub span: Range<usize>,
24
25 pub return_span: Range<usize>,
27}
28
29impl Return {
30 pub fn span(&self) -> Range<usize> {
32 self.span.clone()
33 }
34}
35
36impl<'source> Parse<'source> for Return {
37 fn std_parse(
38 input: &mut Parser<'source>,
39 recoverable_errors: &mut Vec<Error>
40 ) -> Result<Self, Vec<Error>> {
41 let return_token = input.try_parse::<ReturnToken>().forward_errors(recoverable_errors)?;
42 let value = input.try_parse_with_state::<_, Expr>(|state| {
43 state.expr_end_at_eol = true;
44 }).forward_errors(recoverable_errors).ok();
45 let span = if let Some(value) = &value {
46 return_token.span.start..value.span().end
47 } else {
48 return_token.span.clone()
49 };
50
51 if !input.state.allow_return {
53 recoverable_errors.push(Error::new(
54 vec![return_token.span.clone()],
55 ReturnOutsideFunction,
56 ));
57 }
58
59 Ok(Self {
60 value: value.map(Box::new),
61 span,
62 return_span: return_token.span,
63 })
64 }
65}
66
67impl std::fmt::Display for Return {
68 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
69 write!(f, "return")?;
70 if let Some(value) = &self.value {
71 write!(f, " {}", value)?;
72 }
73 Ok(())
74 }
75}
76
77impl Latex for Return {
78 fn fmt_latex(&self, f: &mut fmt::Formatter) -> fmt::Result {
79 write!(f, "\\text{{return }}")?;
80 if let Some(value) = &self.value {
81 value.fmt_latex(f)?;
82 }
83 Ok(())
84 }
85}