sqparse/parser/
control.rs1use crate::ast::{
2 ForDefinition, ForeachIndex, Identifier, IfStatementType, Precedence, Statement, SwitchCase,
3 SwitchCaseCondition, Type,
4};
5use crate::parser::expression::expression;
6use crate::parser::identifier::identifier;
7use crate::parser::parse_result_ext::ParseResultExt;
8use crate::parser::statement::{statement, statement_type, typed_var_definition_statement};
9use crate::parser::token_list::TokenList;
10use crate::parser::token_list_ext::TokenListExt;
11use crate::parser::type_::type_;
12use crate::parser::ParseResult;
13use crate::token::{TerminalToken, Token};
14use crate::ContextType;
15
16pub fn if_statement_type(tokens: TokenList) -> ParseResult<IfStatementType> {
17 let (tokens, body) = statement_type(tokens)?;
18
19 let (next_tokens, semicolon) = tokens.terminal(TerminalToken::Semicolon).maybe(tokens)?;
21
22 let Ok((tokens, else_)) = next_tokens.terminal(TerminalToken::Else) else {
23 return Ok((tokens, IfStatementType::NoElse { body: Box::new(body) }))
25 };
26
27 let (tokens, else_body) = statement_type(tokens).definite()?;
28 Ok((
29 tokens,
30 IfStatementType::Else {
31 body: Box::new(Statement {
32 ty: body,
33 semicolon,
34 }),
35 else_,
36 else_body: Box::new(else_body),
37 },
38 ))
39}
40
41pub fn switch_case(tokens: TokenList) -> ParseResult<SwitchCase> {
42 switch_case_condition(tokens).determines(|tokens, condition| {
43 let (tokens, colon) = tokens.terminal(TerminalToken::Colon)?;
44 let (tokens, body) = tokens.many(statement)?;
45 Ok((
46 tokens,
47 SwitchCase {
48 condition,
49 colon,
50 body,
51 },
52 ))
53 })
54}
55
56pub fn switch_case_condition(tokens: TokenList) -> ParseResult<SwitchCaseCondition> {
57 default_switch_case_condition(tokens).or_try(|| case_switch_case_condition(tokens))
58}
59
60fn default_switch_case_condition(tokens: TokenList) -> ParseResult<SwitchCaseCondition> {
61 tokens
62 .terminal(TerminalToken::Default)
63 .map_val(|default| SwitchCaseCondition::Default { default })
64}
65
66fn case_switch_case_condition(tokens: TokenList) -> ParseResult<SwitchCaseCondition> {
67 tokens
68 .terminal(TerminalToken::Case)
69 .determines(|tokens, case| {
70 let (tokens, value) = expression(tokens, Precedence::None)?;
71 Ok((tokens, SwitchCaseCondition::Case { case, value }))
72 })
73}
74
75pub fn for_definition(tokens: TokenList) -> ParseResult<ForDefinition> {
76 var_for_definition(tokens).or_try(|| expression_for_definition(tokens))
77}
78
79fn var_for_definition(tokens: TokenList) -> ParseResult<ForDefinition> {
80 type_(tokens)
81 .not_definite()
82 .and_then(|(tokens, type_)| typed_var_definition_statement(tokens, type_))
83 .with_context_from(ContextType::VarDefinition, tokens)
84 .map_val(ForDefinition::Definition)
85}
86
87fn expression_for_definition(tokens: TokenList) -> ParseResult<ForDefinition> {
88 expression(tokens, Precedence::None)
89 .with_context_from(ContextType::Expression, tokens)
90 .map_val(ForDefinition::Expression)
91}
92
93pub fn foreach_index(tokens: TokenList) -> ParseResult<ForeachIndex> {
94 untyped_foreach_index(tokens).or_try(|| typed_foreach_index(tokens))
95}
96
97fn untyped_foreach_index(tokens: TokenList) -> ParseResult<ForeachIndex> {
98 let (tokens, name) = identifier(tokens)?;
99 let (tokens, comma) = tokens.terminal(TerminalToken::Comma)?;
100 Ok((
101 tokens,
102 ForeachIndex {
103 type_: None,
104 name,
105 comma,
106 },
107 ))
108}
109
110fn typed_foreach_index(tokens: TokenList) -> ParseResult<ForeachIndex> {
111 let (tokens, type_) = type_(tokens)?;
112 let (tokens, name) = identifier(tokens)?;
113 let (tokens, comma) = tokens.terminal(TerminalToken::Comma)?;
114 Ok((
115 tokens,
116 ForeachIndex {
117 type_: Some(type_),
118 name,
119 comma,
120 },
121 ))
122}
123
124pub fn foreach_value(tokens: TokenList) -> ParseResult<(Option<Type>, Identifier, &Token)> {
125 untyped_foreach_value(tokens).or_try(|| typed_foreach_value(tokens))
126}
127
128fn typed_foreach_value(tokens: TokenList) -> ParseResult<(Option<Type>, Identifier, &Token)> {
129 type_(tokens)
130 .and_then(|(tokens, type_)| identifier(tokens).map_val(|name| (type_, name)))
131 .determines(|tokens, (type_, name)| {
132 let (tokens, in_) = tokens.terminal(TerminalToken::In)?;
133 Ok((tokens, (Some(type_), name, in_)))
134 })
135}
136
137fn untyped_foreach_value(tokens: TokenList) -> ParseResult<(Option<Type>, Identifier, &Token)> {
138 let (tokens, name) = identifier(tokens)?;
139 let (tokens, in_) = tokens.terminal(TerminalToken::In)?;
140 Ok((tokens, (None, name, in_)))
141}