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 let keyword_end_line = p.as_span().end_pos().line_col().0;
258 if let Some(expr_pair) = inner.next() {
260 let expr_start_line = expr_pair.as_span().start_pos().line_col().0;
264 if expr_start_line > keyword_end_line {
265 return Ok(Statement::Return(None, span));
266 }
267 let expr = expressions::parse_expression(expr_pair)?;
268 return Ok(Statement::Return(Some(expr), span));
269 } else {
270 return Ok(Statement::Return(None, span));
271 }
272 }
273 }
274
275 if let Some(expr_pair) = first {
276 let expr = expressions::parse_expression(expr_pair)?;
278 Ok(Statement::Return(Some(expr), span))
279 } else {
280 Ok(Statement::Return(None, span))
282 }
283}
284
285pub fn parse_for_loop(pair: Pair<Rule>) -> Result<Statement> {
287 let pair_loc = pair_location(&pair);
288 let span = pair_span(&pair);
289 let mut inner = pair.into_inner();
290
291 let for_clause = inner.next().ok_or_else(|| ShapeError::ParseError {
293 message: "expected for clause".to_string(),
294 location: Some(pair_loc),
295 })?;
296 let init = parse_for_clause(for_clause)?;
297
298 let mut body = vec![];
300 for stmt_pair in inner {
301 if stmt_pair.as_rule() == Rule::statement {
302 body.push(parse_statement(stmt_pair)?);
303 }
304 }
305
306 Ok(Statement::For(
307 ForLoop {
308 init,
309 body,
310 is_async: false,
311 },
312 span,
313 ))
314}
315
316fn parse_for_clause(pair: Pair<Rule>) -> Result<ForInit> {
318 let pair_loc = pair_location(&pair);
319 let inner_str = pair.as_str();
320 let mut inner = pair.into_inner();
321
322 if inner_str.contains(" in ") {
324 let pattern_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
326 message: "expected pattern in for-in loop".to_string(),
327 location: Some(pair_loc.clone()),
328 })?;
329 let pattern = super::items::parse_pattern(pattern_pair)?;
330 let iter_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
331 message: "expected iterable expression in for-in loop".to_string(),
332 location: Some(pair_loc),
333 })?;
334 let iter_expr = expressions::parse_expression(iter_pair)?;
335 Ok(ForInit::ForIn {
336 pattern,
337 iter: iter_expr,
338 })
339 } else {
340 let init_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
342 message: "expected initialization in for loop".to_string(),
343 location: Some(pair_loc.clone()),
344 })?;
345 let init_decl = parse_variable_decl(init_pair)?;
346 let condition_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
347 message: "expected condition in for loop".to_string(),
348 location: Some(pair_loc.clone()),
349 })?;
350 let condition = expressions::parse_expression(condition_pair)?;
351 let update_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
352 message: "expected update expression in for loop".to_string(),
353 location: Some(pair_loc),
354 })?;
355 let update = expressions::parse_expression(update_pair)?;
356
357 Ok(ForInit::ForC {
358 init: Box::new(Statement::VariableDecl(init_decl, Span::DUMMY)),
359 condition,
360 update,
361 })
362 }
363}
364
365pub fn parse_while_loop(pair: Pair<Rule>) -> Result<Statement> {
367 let pair_loc = pair_location(&pair);
368 let span = pair_span(&pair);
369 let mut inner = pair.into_inner();
370
371 let condition_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
373 message: "expected condition in while loop".to_string(),
374 location: Some(pair_loc),
375 })?;
376 let condition = expressions::parse_expression(condition_pair)?;
377
378 let mut body = vec![];
380 for stmt_pair in inner {
381 if stmt_pair.as_rule() == Rule::statement {
382 body.push(parse_statement(stmt_pair)?);
383 }
384 }
385
386 Ok(Statement::While(WhileLoop { condition, body }, span))
387}
388
389pub fn parse_if_stmt(pair: Pair<Rule>) -> Result<Statement> {
391 let pair_loc = pair_location(&pair);
392 let span = pair_span(&pair);
393 let mut inner = pair.into_inner();
394
395 let condition_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
397 message: "expected condition in if statement".to_string(),
398 location: Some(pair_loc),
399 })?;
400 let condition = expressions::parse_expression(condition_pair)?;
401
402 let mut then_body = vec![];
404 let mut else_body = None;
405
406 for part in inner {
407 match part.as_rule() {
408 Rule::statement => {
409 then_body.push(parse_statement(part)?);
410 }
411 Rule::else_clause => {
412 else_body = Some(parse_else_clause(part)?);
413 }
414 _ => {}
415 }
416 }
417
418 Ok(Statement::If(
419 IfStatement {
420 condition,
421 then_body,
422 else_body,
423 },
424 span,
425 ))
426}
427
428fn parse_else_clause(pair: Pair<Rule>) -> Result<Vec<Statement>> {
430 let span = pair_span(&pair);
431 let mut inner = pair.into_inner();
432 let mut statements = vec![];
433
434 let first = inner.next();
436 if let Some(first_pair) = first {
437 match first_pair.as_rule() {
438 Rule::expression => {
439 let condition = expressions::parse_expression(first_pair)?;
441 let mut then_body = vec![];
442 let mut else_body = None;
443
444 for part in inner {
446 match part.as_rule() {
447 Rule::statement => {
448 then_body.push(parse_statement(part)?);
449 }
450 Rule::else_clause => {
451 else_body = Some(parse_else_clause(part)?);
452 }
453 _ => {}
454 }
455 }
456
457 statements.push(Statement::If(
459 IfStatement {
460 condition,
461 then_body,
462 else_body,
463 },
464 span,
465 ));
466 }
467 Rule::statement => {
468 statements.push(parse_statement(first_pair)?);
470 for stmt_pair in inner {
471 if stmt_pair.as_rule() == Rule::statement {
472 statements.push(parse_statement(stmt_pair)?);
473 }
474 }
475 }
476 _ => {}
477 }
478 }
479
480 Ok(statements)
481}
482
483pub fn parse_statements(pairs: pest::iterators::Pairs<Rule>) -> Result<Vec<Statement>> {
485 let mut statements = vec![];
486
487 for pair in pairs {
488 if pair.as_rule() == Rule::statement {
489 statements.push(parse_statement(pair)?);
490 } else if pair.as_rule() == Rule::stmt_recovery {
491 let span = pair.as_span();
492 let text = pair.as_str().trim();
493 let preview = if text.len() > 40 {
494 format!("{}...", &text[..40])
495 } else {
496 text.to_string()
497 };
498 return Err(ShapeError::ParseError {
499 message: format!("Syntax error near: {}", preview),
500 location: Some(pair_location(&pair).with_length(span.end() - span.start())),
501 });
502 }
503 }
504
505 Ok(statements)
506}