1use super::*;
2use py_lex::syntax::{ControlFlow, Symbol};
3
4#[derive(Debug, Clone)]
5pub struct Conditions {
6 pub conds: Vec<Expr>,
7 pub semicolons: Vec<Span>,
8}
9
10impl std::ops::Deref for Conditions {
11 type Target = Vec<Expr>;
12
13 fn deref(&self) -> &Self::Target {
14 &self.conds
15 }
16}
17
18impl ParseUnit<Token> for Conditions {
19 type Target = Conditions;
20
21 fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
22 p.r#match(Symbol::Parameter)?;
23 let Some(cond) = p.parse::<Expr>().apply(mapper::Try)? else {
24 p.r#match(Symbol::EndOfBlock).apply(mapper::MustMatch)?;
25 return Ok(Conditions {
26 conds: vec![],
27 semicolons: vec![],
28 });
29 };
30
31 let mut conds = vec![cond];
32 let mut semicolons = vec![];
33
34 while let Some(semicolon) = p.r#match(RPU(Symbol::Semicolon)).apply(mapper::Try)? {
35 semicolons.push(semicolon.get_span());
36 conds.push(p.parse::<Expr>()?);
37 }
38
39 p.r#match(Symbol::EndOfBlock).apply(mapper::MustMatch)?;
40 Ok(Conditions { conds, semicolons })
41 }
42}
43
44#[derive(Debug, Clone)]
45pub struct IfBranch {
46 pub conds: Conditions,
47 pub body: CodeBlock,
48}
49
50impl ParseUnit<Token> for IfBranch {
51 type Target = IfBranch;
52
53 fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
54 p.r#match(ControlFlow::If)?;
55 let conds = p.parse::<Conditions>()?;
56 let body = p.parse::<CodeBlock>().apply(mapper::MustMatch)?;
57 Ok(IfBranch { conds, body })
58 }
59}
60
61#[derive(Debug, Clone)]
62pub struct ElseBranch {
63 pub block: CodeBlock,
64}
65
66impl ParseUnit<Token> for ElseBranch {
67 type Target = ElseBranch;
68
69 fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
70 p.r#match(ControlFlow::Else)?;
71 let block = p.parse::<CodeBlock>().apply(mapper::MustMatch)?;
72 Ok(ElseBranch { block })
73 }
74}
75
76#[derive(Debug, Clone)]
77pub struct ElseIfBranch {
78 pub block: PU<CodeBlock>,
79}
80
81impl ParseUnit<Token> for ElseIfBranch {
82 type Target = IfBranch;
83
84 fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
85 p.r#match(ControlFlow::Else)?;
86 p.r#match(ControlFlow::If)?;
87
88 let conds = p.parse::<Conditions>()?;
89 let body = p.parse::<CodeBlock>().apply(mapper::MustMatch)?;
90 Ok(IfBranch { conds, body })
91 }
92}
93
94#[derive(Debug, Clone)]
95pub struct If {
96 pub branches: Vec<IfBranch>,
97 pub else_: Option<ElseBranch>,
98}
99
100impl ParseUnit<Token> for If {
101 type Target = If;
102
103 fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
104 let mut branches = vec![p.parse::<IfBranch>()?];
105 while let Some(chain) = p.parse::<ElseIfBranch>().apply(mapper::Try)? {
106 branches.push(chain);
107 }
108 let else_ = p.parse::<ElseBranch>().apply(mapper::Try)?;
109 Ok(If { branches, else_ })
110 }
111}
112
113#[derive(Debug, Clone)]
114pub struct While {
115 pub conds: Conditions,
116 pub block: CodeBlock,
117}
118
119impl ParseUnit<Token> for While {
120 type Target = While;
121
122 fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
123 p.r#match(ControlFlow::Repeat)?;
124 let conds = p.parse::<Conditions>().apply(mapper::MustMatch)?;
125 let block = p.parse::<CodeBlock>().apply(mapper::MustMatch)?;
126 Ok(While { conds, block })
127 }
128}
129
130#[derive(Debug, Clone)]
131pub struct Return {
132 pub val: Option<Expr>,
133}
134
135impl ParseUnit<Token> for Return {
136 type Target = Return;
137
138 fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
139 p.r#match(ControlFlow::Return)?;
140 let val = p.parse::<Expr>().apply(mapper::Try)?;
141 p.r#match(Symbol::Semicolon)?;
142
143 Ok(Return { val })
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150 use crate::parse_test;
151
152 #[test]
153 fn r#if() {
154 let src = "
155 ruo4 can1 jie2 1 da4 0 he2 huo4 jie2 2 xiao3 3 he2 yu3 fei1 fou3 jie2 han2
156
157 jie2 ze2 han2
158
159 jie2";
160
161 parse_test(src, |p| {
162 p.parse::<If>()?;
163 Ok(())
164 });
165 }
166
167 #[test]
168 fn r#while() {
169 let src = "
170 chong2 can1 i xiao3 5 jie2 han2
171 i wei2 i jia1 1 fen1
172 jie2";
173 parse_test(src, |p| {
174 p.parse::<While>()?;
175 Ok(())
176 });
177 }
178}