py_ast/parse/
flow.rs

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}