php_parser_rs/parser/ast/
control_flow.rs

1use schemars::JsonSchema;
2use serde::Deserialize;
3use serde::Serialize;
4
5use crate::lexer::token::Span;
6use crate::node::Node;
7use crate::parser::ast::Ending;
8use crate::parser::ast::Expression;
9use crate::parser::ast::Statement;
10
11#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, JsonSchema)]
12
13pub struct IfStatement {
14    pub r#if: Span,              // `if`
15    pub left_parenthesis: Span,  // `(`
16    pub condition: Expression,   // *expression*
17    pub right_parenthesis: Span, // `)`
18    pub body: IfStatementBody,   // `{ ... }`
19}
20
21impl Node for IfStatement {
22    fn children(&mut self) -> Vec<&mut dyn Node> {
23        vec![&mut self.condition, &mut self.body]
24    }
25}
26
27#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, JsonSchema)]
28#[serde(tag = "type", content = "value")]
29pub enum IfStatementBody {
30    Statement {
31        statement: Box<Statement>,       // `*statement*`
32        elseifs: Vec<IfStatementElseIf>, // `elseif (*expression*) *statement*`
33        r#else: Option<IfStatementElse>, // `else *statement*`
34    },
35    Block {
36        colon: Span,                          // `:`
37        statements: Vec<Statement>,           // `*statements*`
38        elseifs: Vec<IfStatementElseIfBlock>, // `elseif (*expression*): *statements*`
39        r#else: Option<IfStatementElseBlock>, // `else: *statements*`
40        endif: Span,                          // `endif`
41        ending: Ending,                       // `;` or `?>`
42    },
43}
44
45impl Node for IfStatementBody {
46    fn children(&mut self) -> Vec<&mut dyn Node> {
47        match self {
48            IfStatementBody::Statement {
49                statement,
50                elseifs,
51                r#else,
52            } => {
53                let mut children: Vec<&mut dyn Node> = vec![statement.as_mut()];
54                children.extend(
55                    elseifs
56                        .iter_mut()
57                        .map(|elseif| elseif as &mut dyn Node)
58                        .collect::<Vec<&mut dyn Node>>(),
59                );
60                if let Some(r#else) = r#else {
61                    children.push(r#else as &mut dyn Node);
62                }
63                children
64            }
65            IfStatementBody::Block {
66                statements,
67                elseifs,
68                r#else,
69                ..
70            } => {
71                let mut children: Vec<&mut dyn Node> = vec![];
72                children.extend(
73                    statements
74                        .iter_mut()
75                        .map(|statement| statement as &mut dyn Node),
76                );
77                children.extend(elseifs.iter_mut().map(|elseif| elseif as &mut dyn Node));
78                if let Some(r#else) = r#else {
79                    children.push(r#else as &mut dyn Node);
80                }
81                children
82            }
83        }
84    }
85}
86
87#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, JsonSchema)]
88
89pub struct IfStatementElseIf {
90    pub elseif: Span,              // `elseif`
91    pub left_parenthesis: Span,    // `(`
92    pub condition: Expression,     // `( *expression* )`
93    pub right_parenthesis: Span,   // `)`
94    pub statement: Box<Statement>, // `*statement*`
95}
96
97impl Node for IfStatementElseIf {
98    fn children(&mut self) -> Vec<&mut dyn Node> {
99        vec![&mut self.condition, self.statement.as_mut()]
100    }
101}
102
103#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, JsonSchema)]
104
105pub struct IfStatementElse {
106    pub r#else: Span,              // `else`
107    pub statement: Box<Statement>, // `*statement*`
108}
109
110impl Node for IfStatementElse {
111    fn children(&mut self) -> Vec<&mut dyn Node> {
112        vec![self.statement.as_mut()]
113    }
114}
115
116#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, JsonSchema)]
117
118pub struct IfStatementElseIfBlock {
119    pub elseif: Span,               // `elseif`
120    pub left_parenthesis: Span,     // `(`
121    pub condition: Expression,      // `( *expression* )`
122    pub right_parenthesis: Span,    // `)`
123    pub colon: Span,                // `:`
124    pub statements: Vec<Statement>, // `*statements*`
125}
126
127impl Node for IfStatementElseIfBlock {
128    fn children(&mut self) -> Vec<&mut dyn Node> {
129        let mut children: Vec<&mut dyn Node> = vec![&mut self.condition];
130        children.extend(
131            self.statements
132                .iter_mut()
133                .map(|statement| statement as &mut dyn Node),
134        );
135        children
136    }
137}
138
139#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, JsonSchema)]
140
141pub struct IfStatementElseBlock {
142    pub r#else: Span,               // `else`
143    pub colon: Span,                // `:`
144    pub statements: Vec<Statement>, // `*statements*`
145}
146
147impl Node for IfStatementElseBlock {
148    fn children(&mut self) -> Vec<&mut dyn Node> {
149        self.statements
150            .iter_mut()
151            .map(|statement| statement as &mut dyn Node)
152            .collect()
153    }
154}