1use crate::error::{Result, ShapeError};
4use crate::parser::pair_location;
5use pest::iterators::Pair;
6
7use crate::ast::{Assignment, ForInit, ForLoop, IfStatement, Span, Statement, WhileLoop};
8use crate::parser::extensions::parse_extend_statement;
9use crate::parser::{Rule, expressions, pair_span, parse_variable_decl};
10
11pub fn parse_statement(pair: Pair<Rule>) -> Result<Statement> {
13 let pair_loc = pair_location(&pair);
14 let span = pair_span(&pair);
15 let inner = pair
16 .into_inner()
17 .next()
18 .ok_or_else(|| ShapeError::ParseError {
19 message: "expected statement content".to_string(),
20 location: Some(pair_loc.clone()),
21 })?;
22
23 match inner.as_rule() {
24 Rule::return_stmt => parse_return_stmt(inner),
25 Rule::break_stmt => Ok(Statement::Break(pair_span(&inner))),
26 Rule::continue_stmt => Ok(Statement::Continue(pair_span(&inner))),
27 Rule::variable_decl => {
28 let decl = parse_variable_decl(inner)?;
29 Ok(Statement::VariableDecl(decl, span))
30 }
31 Rule::assignment => {
32 let inner_loc = pair_location(&inner);
33 let inner_span = pair_span(&inner);
34 let mut inner = inner.into_inner();
35 let pattern_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
36 message: "expected pattern in assignment".to_string(),
37 location: Some(inner_loc.clone()),
38 })?;
39 let pattern = crate::parser::parse_pattern(pattern_pair)?;
40 let value_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
41 message: "expected value in assignment".to_string(),
42 location: Some(inner_loc),
43 })?;
44 let value = expressions::parse_expression(value_pair)?;
45 Ok(Statement::Assignment(
46 Assignment { pattern, value },
47 inner_span,
48 ))
49 }
50 Rule::expression_stmt => {
51 let inner_loc = pair_location(&inner);
52 let inner_span = pair_span(&inner);
53 let expr_pair = inner
54 .into_inner()
55 .next()
56 .ok_or_else(|| ShapeError::ParseError {
57 message: "expected expression in statement".to_string(),
58 location: Some(inner_loc),
59 })?;
60 let expr = expressions::parse_expression(expr_pair)?;
61 Ok(Statement::Expression(expr, inner_span))
62 }
63 Rule::for_loop => parse_for_loop(inner),
64 Rule::while_loop => parse_while_loop(inner),
65 Rule::if_stmt => parse_if_stmt(inner),
66 Rule::extend_statement => {
67 let ext = parse_extend_statement(inner)?;
68 Ok(Statement::Extend(ext, span))
69 }
70 Rule::function_def => {
71 let func_def = crate::parser::functions::parse_function_def(inner)?;
74 let func_expr = crate::ast::Expr::FunctionExpr {
75 params: func_def.params,
76 return_type: func_def.return_type,
77 body: func_def.body,
78 span,
79 };
80 Ok(Statement::VariableDecl(
81 crate::ast::VariableDecl {
82 kind: crate::ast::VarKind::Let,
83 is_mut: false,
84 pattern: crate::ast::DestructurePattern::Identifier(func_def.name, span),
85 type_annotation: None,
86 value: Some(func_expr),
87 ownership: Default::default(),
88 },
89 span,
90 ))
91 }
92 Rule::remove_target_stmt => Ok(Statement::RemoveTarget(pair_span(&inner))),
93 Rule::set_param_value_stmt => {
94 let inner_span = pair_span(&inner);
95 let mut inner_parts = inner.into_inner();
96 let param_pair = inner_parts.next().ok_or_else(|| ShapeError::ParseError {
97 message: "expected parameter name in `set param` value directive".to_string(),
98 location: Some(pair_loc.clone()),
99 })?;
100 let expr_pair = inner_parts.next().ok_or_else(|| ShapeError::ParseError {
101 message: "expected expression in `set param` value directive".to_string(),
102 location: Some(pair_loc.clone()),
103 })?;
104 let expression = crate::parser::expressions::parse_expression(expr_pair)?;
105 Ok(Statement::SetParamValue {
106 param_name: param_pair.as_str().to_string(),
107 expression,
108 span: inner_span,
109 })
110 }
111 Rule::set_param_type_stmt => {
112 let inner_span = pair_span(&inner);
113 let mut inner_parts = inner.into_inner();
114 let param_pair = inner_parts.next().ok_or_else(|| ShapeError::ParseError {
115 message: "expected parameter name in `set param` directive".to_string(),
116 location: Some(pair_loc.clone()),
117 })?;
118 let type_pair = inner_parts.next().ok_or_else(|| ShapeError::ParseError {
119 message: "expected type annotation in `set param` directive".to_string(),
120 location: Some(pair_loc.clone()),
121 })?;
122 let type_annotation = crate::parser::types::parse_type_annotation(type_pair)?;
123 Ok(Statement::SetParamType {
124 param_name: param_pair.as_str().to_string(),
125 type_annotation,
126 span: inner_span,
127 })
128 }
129 Rule::set_return_stmt => {
130 let inner_span = pair_span(&inner);
131 let mut inner_parts = inner.into_inner();
132 let payload_pair = inner_parts.next().ok_or_else(|| ShapeError::ParseError {
133 message: "expected type annotation or expression in `set return` directive"
134 .to_string(),
135 location: Some(pair_loc.clone()),
136 })?;
137 match payload_pair.as_rule() {
138 Rule::type_annotation => {
139 let type_annotation =
140 crate::parser::types::parse_type_annotation(payload_pair)?;
141 Ok(Statement::SetReturnType {
142 type_annotation,
143 span: inner_span,
144 })
145 }
146 Rule::set_return_expr_payload => {
147 let expr_pair =
148 payload_pair
149 .into_inner()
150 .next()
151 .ok_or_else(|| ShapeError::ParseError {
152 message:
153 "expected expression in parenthesized `set return` directive"
154 .to_string(),
155 location: Some(pair_loc.clone()),
156 })?;
157 let expression = expressions::parse_expression(expr_pair)?;
158 Ok(Statement::SetReturnExpr {
159 expression,
160 span: inner_span,
161 })
162 }
163 _ => Err(ShapeError::ParseError {
164 message: "expected type annotation or expression in `set return` directive"
165 .to_string(),
166 location: Some(pair_loc),
167 }),
168 }
169 }
170 Rule::replace_body_stmt => {
171 let inner_span = pair_span(&inner);
172 let mut parts = inner.into_inner();
173 let Some(payload) = parts.next() else {
174 return Ok(Statement::ReplaceBody {
175 body: Vec::new(),
176 span: inner_span,
177 });
178 };
179 match payload.as_rule() {
180 Rule::replace_body_expr_payload => {
181 let expr_pair =
182 payload
183 .into_inner()
184 .next()
185 .ok_or_else(|| ShapeError::ParseError {
186 message:
187 "expected expression in parenthesized `replace body` directive"
188 .to_string(),
189 location: Some(pair_loc.clone()),
190 })?;
191 let expression = expressions::parse_expression(expr_pair)?;
192 Ok(Statement::ReplaceBodyExpr {
193 expression,
194 span: inner_span,
195 })
196 }
197 Rule::statement => {
198 let mut body = Vec::new();
199 body.push(parse_statement(payload)?);
200 body.extend(parse_statements(parts)?);
201 Ok(Statement::ReplaceBody {
202 body,
203 span: inner_span,
204 })
205 }
206 _ => Err(ShapeError::ParseError {
207 message: "expected body block or expression in `replace body` directive"
208 .to_string(),
209 location: Some(pair_loc),
210 }),
211 }
212 }
213 Rule::replace_module_stmt => {
214 let inner_span = pair_span(&inner);
215 let mut parts = inner.into_inner();
216 let payload = parts.next().ok_or_else(|| ShapeError::ParseError {
217 message: "expected expression payload in `replace module` directive".to_string(),
218 location: Some(pair_loc.clone()),
219 })?;
220 if payload.as_rule() != Rule::replace_module_expr_payload {
221 return Err(ShapeError::ParseError {
222 message: "expected parenthesized expression in `replace module` directive"
223 .to_string(),
224 location: Some(pair_loc),
225 });
226 }
227 let expr_pair = payload
228 .into_inner()
229 .next()
230 .ok_or_else(|| ShapeError::ParseError {
231 message: "expected expression in parenthesized `replace module` directive"
232 .to_string(),
233 location: Some(pair_loc),
234 })?;
235 let expression = expressions::parse_expression(expr_pair)?;
236 Ok(Statement::ReplaceModuleExpr {
237 expression,
238 span: inner_span,
239 })
240 }
241 _ => Err(ShapeError::ParseError {
242 message: format!("Unexpected statement type: {:?}", inner.as_rule()),
243 location: None,
244 }),
245 }
246}
247
248fn parse_return_stmt(pair: Pair<Rule>) -> Result<Statement> {
250 let span = pair_span(&pair);
251 let mut inner = pair.into_inner();
252
253 let first = inner.next();
255 if let Some(ref p) = first {
256 if p.as_rule() == Rule::return_keyword {
257 if let Some(expr_pair) = inner.next() {
259 let expr = expressions::parse_expression(expr_pair)?;
260 return Ok(Statement::Return(Some(expr), span));
261 } else {
262 return Ok(Statement::Return(None, span));
263 }
264 }
265 }
266
267 if let Some(expr_pair) = first {
268 let expr = expressions::parse_expression(expr_pair)?;
270 Ok(Statement::Return(Some(expr), span))
271 } else {
272 Ok(Statement::Return(None, span))
274 }
275}
276
277pub fn parse_for_loop(pair: Pair<Rule>) -> Result<Statement> {
279 let pair_loc = pair_location(&pair);
280 let span = pair_span(&pair);
281 let mut inner = pair.into_inner();
282
283 let for_clause = inner.next().ok_or_else(|| ShapeError::ParseError {
285 message: "expected for clause".to_string(),
286 location: Some(pair_loc),
287 })?;
288 let init = parse_for_clause(for_clause)?;
289
290 let mut body = vec![];
292 for stmt_pair in inner {
293 if stmt_pair.as_rule() == Rule::statement {
294 body.push(parse_statement(stmt_pair)?);
295 }
296 }
297
298 Ok(Statement::For(
299 ForLoop {
300 init,
301 body,
302 is_async: false,
303 },
304 span,
305 ))
306}
307
308fn parse_for_clause(pair: Pair<Rule>) -> Result<ForInit> {
310 let pair_loc = pair_location(&pair);
311 let inner_str = pair.as_str();
312 let mut inner = pair.into_inner();
313
314 if inner_str.contains(" in ") {
316 let pattern_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
318 message: "expected pattern in for-in loop".to_string(),
319 location: Some(pair_loc.clone()),
320 })?;
321 let pattern = super::items::parse_pattern(pattern_pair)?;
322 let iter_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
323 message: "expected iterable expression in for-in loop".to_string(),
324 location: Some(pair_loc),
325 })?;
326 let iter_expr = expressions::parse_expression(iter_pair)?;
327 Ok(ForInit::ForIn {
328 pattern,
329 iter: iter_expr,
330 })
331 } else {
332 let init_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
334 message: "expected initialization in for loop".to_string(),
335 location: Some(pair_loc.clone()),
336 })?;
337 let init_decl = parse_variable_decl(init_pair)?;
338 let condition_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
339 message: "expected condition in for loop".to_string(),
340 location: Some(pair_loc.clone()),
341 })?;
342 let condition = expressions::parse_expression(condition_pair)?;
343 let update_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
344 message: "expected update expression in for loop".to_string(),
345 location: Some(pair_loc),
346 })?;
347 let update = expressions::parse_expression(update_pair)?;
348
349 Ok(ForInit::ForC {
350 init: Box::new(Statement::VariableDecl(init_decl, Span::DUMMY)),
351 condition,
352 update,
353 })
354 }
355}
356
357pub fn parse_while_loop(pair: Pair<Rule>) -> Result<Statement> {
359 let pair_loc = pair_location(&pair);
360 let span = pair_span(&pair);
361 let mut inner = pair.into_inner();
362
363 let condition_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
365 message: "expected condition in while loop".to_string(),
366 location: Some(pair_loc),
367 })?;
368 let condition = expressions::parse_expression(condition_pair)?;
369
370 let mut body = vec![];
372 for stmt_pair in inner {
373 if stmt_pair.as_rule() == Rule::statement {
374 body.push(parse_statement(stmt_pair)?);
375 }
376 }
377
378 Ok(Statement::While(WhileLoop { condition, body }, span))
379}
380
381pub fn parse_if_stmt(pair: Pair<Rule>) -> Result<Statement> {
383 let pair_loc = pair_location(&pair);
384 let span = pair_span(&pair);
385 let mut inner = pair.into_inner();
386
387 let condition_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
389 message: "expected condition in if statement".to_string(),
390 location: Some(pair_loc),
391 })?;
392 let condition = expressions::parse_expression(condition_pair)?;
393
394 let mut then_body = vec![];
396 let mut else_body = None;
397
398 for part in inner {
399 match part.as_rule() {
400 Rule::statement => {
401 then_body.push(parse_statement(part)?);
402 }
403 Rule::else_clause => {
404 else_body = Some(parse_else_clause(part)?);
405 }
406 _ => {}
407 }
408 }
409
410 Ok(Statement::If(
411 IfStatement {
412 condition,
413 then_body,
414 else_body,
415 },
416 span,
417 ))
418}
419
420fn parse_else_clause(pair: Pair<Rule>) -> Result<Vec<Statement>> {
422 let span = pair_span(&pair);
423 let mut inner = pair.into_inner();
424 let mut statements = vec![];
425
426 let first = inner.next();
428 if let Some(first_pair) = first {
429 match first_pair.as_rule() {
430 Rule::expression => {
431 let condition = expressions::parse_expression(first_pair)?;
433 let mut then_body = vec![];
434 let mut else_body = None;
435
436 for part in inner {
438 match part.as_rule() {
439 Rule::statement => {
440 then_body.push(parse_statement(part)?);
441 }
442 Rule::else_clause => {
443 else_body = Some(parse_else_clause(part)?);
444 }
445 _ => {}
446 }
447 }
448
449 statements.push(Statement::If(
451 IfStatement {
452 condition,
453 then_body,
454 else_body,
455 },
456 span,
457 ));
458 }
459 Rule::statement => {
460 statements.push(parse_statement(first_pair)?);
462 for stmt_pair in inner {
463 if stmt_pair.as_rule() == Rule::statement {
464 statements.push(parse_statement(stmt_pair)?);
465 }
466 }
467 }
468 _ => {}
469 }
470 }
471
472 Ok(statements)
473}
474
475pub fn parse_statements(pairs: pest::iterators::Pairs<Rule>) -> Result<Vec<Statement>> {
477 let mut statements = vec![];
478
479 for pair in pairs {
480 if pair.as_rule() == Rule::statement {
481 statements.push(parse_statement(pair)?);
482 } else if pair.as_rule() == Rule::stmt_recovery {
483 let span = pair.as_span();
484 let text = pair.as_str().trim();
485 let preview = if text.len() > 40 {
486 format!("{}...", &text[..40])
487 } else {
488 text.to_string()
489 };
490 return Err(ShapeError::ParseError {
491 message: format!("Syntax error near: {}", preview),
492 location: Some(pair_location(&pair).with_length(span.end() - span.start())),
493 });
494 }
495 }
496
497 Ok(statements)
498}