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_type_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` directive".to_string(),
98 location: Some(pair_loc.clone()),
99 })?;
100 let type_pair = inner_parts.next().ok_or_else(|| ShapeError::ParseError {
101 message: "expected type annotation in `set param` directive".to_string(),
102 location: Some(pair_loc.clone()),
103 })?;
104 let type_annotation = crate::parser::types::parse_type_annotation(type_pair)?;
105 Ok(Statement::SetParamType {
106 param_name: param_pair.as_str().to_string(),
107 type_annotation,
108 span: inner_span,
109 })
110 }
111 Rule::set_return_stmt => {
112 let inner_span = pair_span(&inner);
113 let mut inner_parts = inner.into_inner();
114 let payload_pair = inner_parts.next().ok_or_else(|| ShapeError::ParseError {
115 message: "expected type annotation or expression in `set return` directive"
116 .to_string(),
117 location: Some(pair_loc.clone()),
118 })?;
119 match payload_pair.as_rule() {
120 Rule::type_annotation => {
121 let type_annotation =
122 crate::parser::types::parse_type_annotation(payload_pair)?;
123 Ok(Statement::SetReturnType {
124 type_annotation,
125 span: inner_span,
126 })
127 }
128 Rule::set_return_expr_payload => {
129 let expr_pair =
130 payload_pair
131 .into_inner()
132 .next()
133 .ok_or_else(|| ShapeError::ParseError {
134 message:
135 "expected expression in parenthesized `set return` directive"
136 .to_string(),
137 location: Some(pair_loc.clone()),
138 })?;
139 let expression = expressions::parse_expression(expr_pair)?;
140 Ok(Statement::SetReturnExpr {
141 expression,
142 span: inner_span,
143 })
144 }
145 _ => Err(ShapeError::ParseError {
146 message: "expected type annotation or expression in `set return` directive"
147 .to_string(),
148 location: Some(pair_loc),
149 }),
150 }
151 }
152 Rule::replace_body_stmt => {
153 let inner_span = pair_span(&inner);
154 let mut parts = inner.into_inner();
155 let Some(payload) = parts.next() else {
156 return Ok(Statement::ReplaceBody {
157 body: Vec::new(),
158 span: inner_span,
159 });
160 };
161 match payload.as_rule() {
162 Rule::replace_body_expr_payload => {
163 let expr_pair =
164 payload
165 .into_inner()
166 .next()
167 .ok_or_else(|| ShapeError::ParseError {
168 message:
169 "expected expression in parenthesized `replace body` directive"
170 .to_string(),
171 location: Some(pair_loc.clone()),
172 })?;
173 let expression = expressions::parse_expression(expr_pair)?;
174 Ok(Statement::ReplaceBodyExpr {
175 expression,
176 span: inner_span,
177 })
178 }
179 Rule::statement => {
180 let mut body = Vec::new();
181 body.push(parse_statement(payload)?);
182 body.extend(parse_statements(parts)?);
183 Ok(Statement::ReplaceBody {
184 body,
185 span: inner_span,
186 })
187 }
188 _ => Err(ShapeError::ParseError {
189 message: "expected body block or expression in `replace body` directive"
190 .to_string(),
191 location: Some(pair_loc),
192 }),
193 }
194 }
195 Rule::replace_module_stmt => {
196 let inner_span = pair_span(&inner);
197 let mut parts = inner.into_inner();
198 let payload = parts.next().ok_or_else(|| ShapeError::ParseError {
199 message: "expected expression payload in `replace module` directive".to_string(),
200 location: Some(pair_loc.clone()),
201 })?;
202 if payload.as_rule() != Rule::replace_module_expr_payload {
203 return Err(ShapeError::ParseError {
204 message: "expected parenthesized expression in `replace module` directive"
205 .to_string(),
206 location: Some(pair_loc),
207 });
208 }
209 let expr_pair = payload
210 .into_inner()
211 .next()
212 .ok_or_else(|| ShapeError::ParseError {
213 message: "expected expression in parenthesized `replace module` directive"
214 .to_string(),
215 location: Some(pair_loc),
216 })?;
217 let expression = expressions::parse_expression(expr_pair)?;
218 Ok(Statement::ReplaceModuleExpr {
219 expression,
220 span: inner_span,
221 })
222 }
223 _ => Err(ShapeError::ParseError {
224 message: format!("Unexpected statement type: {:?}", inner.as_rule()),
225 location: None,
226 }),
227 }
228}
229
230fn parse_return_stmt(pair: Pair<Rule>) -> Result<Statement> {
232 let span = pair_span(&pair);
233 let mut inner = pair.into_inner();
234
235 let first = inner.next();
237 if let Some(ref p) = first {
238 if p.as_rule() == Rule::return_keyword {
239 if let Some(expr_pair) = inner.next() {
241 let expr = expressions::parse_expression(expr_pair)?;
242 return Ok(Statement::Return(Some(expr), span));
243 } else {
244 return Ok(Statement::Return(None, span));
245 }
246 }
247 }
248
249 if let Some(expr_pair) = first {
250 let expr = expressions::parse_expression(expr_pair)?;
252 Ok(Statement::Return(Some(expr), span))
253 } else {
254 Ok(Statement::Return(None, span))
256 }
257}
258
259pub fn parse_for_loop(pair: Pair<Rule>) -> Result<Statement> {
261 let pair_loc = pair_location(&pair);
262 let span = pair_span(&pair);
263 let mut inner = pair.into_inner();
264
265 let for_clause = inner.next().ok_or_else(|| ShapeError::ParseError {
267 message: "expected for clause".to_string(),
268 location: Some(pair_loc),
269 })?;
270 let init = parse_for_clause(for_clause)?;
271
272 let mut body = vec![];
274 for stmt_pair in inner {
275 if stmt_pair.as_rule() == Rule::statement {
276 body.push(parse_statement(stmt_pair)?);
277 }
278 }
279
280 Ok(Statement::For(
281 ForLoop {
282 init,
283 body,
284 is_async: false,
285 },
286 span,
287 ))
288}
289
290fn parse_for_clause(pair: Pair<Rule>) -> Result<ForInit> {
292 let pair_loc = pair_location(&pair);
293 let inner_str = pair.as_str();
294 let mut inner = pair.into_inner();
295
296 if inner_str.contains(" in ") {
298 let pattern_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
300 message: "expected pattern in for-in loop".to_string(),
301 location: Some(pair_loc.clone()),
302 })?;
303 let pattern = super::items::parse_pattern(pattern_pair)?;
304 let iter_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
305 message: "expected iterable expression in for-in loop".to_string(),
306 location: Some(pair_loc),
307 })?;
308 let iter_expr = expressions::parse_expression(iter_pair)?;
309 Ok(ForInit::ForIn {
310 pattern,
311 iter: iter_expr,
312 })
313 } else {
314 let init_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
316 message: "expected initialization in for loop".to_string(),
317 location: Some(pair_loc.clone()),
318 })?;
319 let init_decl = parse_variable_decl(init_pair)?;
320 let condition_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
321 message: "expected condition in for loop".to_string(),
322 location: Some(pair_loc.clone()),
323 })?;
324 let condition = expressions::parse_expression(condition_pair)?;
325 let update_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
326 message: "expected update expression in for loop".to_string(),
327 location: Some(pair_loc),
328 })?;
329 let update = expressions::parse_expression(update_pair)?;
330
331 Ok(ForInit::ForC {
332 init: Box::new(Statement::VariableDecl(init_decl, Span::DUMMY)),
333 condition,
334 update,
335 })
336 }
337}
338
339pub fn parse_while_loop(pair: Pair<Rule>) -> Result<Statement> {
341 let pair_loc = pair_location(&pair);
342 let span = pair_span(&pair);
343 let mut inner = pair.into_inner();
344
345 let condition_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
347 message: "expected condition in while loop".to_string(),
348 location: Some(pair_loc),
349 })?;
350 let condition = expressions::parse_expression(condition_pair)?;
351
352 let mut body = vec![];
354 for stmt_pair in inner {
355 if stmt_pair.as_rule() == Rule::statement {
356 body.push(parse_statement(stmt_pair)?);
357 }
358 }
359
360 Ok(Statement::While(WhileLoop { condition, body }, span))
361}
362
363pub fn parse_if_stmt(pair: Pair<Rule>) -> Result<Statement> {
365 let pair_loc = pair_location(&pair);
366 let span = pair_span(&pair);
367 let mut inner = pair.into_inner();
368
369 let condition_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
371 message: "expected condition in if statement".to_string(),
372 location: Some(pair_loc),
373 })?;
374 let condition = expressions::parse_expression(condition_pair)?;
375
376 let mut then_body = vec![];
378 let mut else_body = None;
379
380 for part in inner {
381 match part.as_rule() {
382 Rule::statement => {
383 then_body.push(parse_statement(part)?);
384 }
385 Rule::else_clause => {
386 else_body = Some(parse_else_clause(part)?);
387 }
388 _ => {}
389 }
390 }
391
392 Ok(Statement::If(
393 IfStatement {
394 condition,
395 then_body,
396 else_body,
397 },
398 span,
399 ))
400}
401
402fn parse_else_clause(pair: Pair<Rule>) -> Result<Vec<Statement>> {
404 let span = pair_span(&pair);
405 let mut inner = pair.into_inner();
406 let mut statements = vec![];
407
408 let first = inner.next();
410 if let Some(first_pair) = first {
411 match first_pair.as_rule() {
412 Rule::expression => {
413 let condition = expressions::parse_expression(first_pair)?;
415 let mut then_body = vec![];
416 let mut else_body = None;
417
418 for part in inner {
420 match part.as_rule() {
421 Rule::statement => {
422 then_body.push(parse_statement(part)?);
423 }
424 Rule::else_clause => {
425 else_body = Some(parse_else_clause(part)?);
426 }
427 _ => {}
428 }
429 }
430
431 statements.push(Statement::If(
433 IfStatement {
434 condition,
435 then_body,
436 else_body,
437 },
438 span,
439 ));
440 }
441 Rule::statement => {
442 statements.push(parse_statement(first_pair)?);
444 for stmt_pair in inner {
445 if stmt_pair.as_rule() == Rule::statement {
446 statements.push(parse_statement(stmt_pair)?);
447 }
448 }
449 }
450 _ => {}
451 }
452 }
453
454 Ok(statements)
455}
456
457pub fn parse_statements(pairs: pest::iterators::Pairs<Rule>) -> Result<Vec<Statement>> {
459 let mut statements = vec![];
460
461 for pair in pairs {
462 if pair.as_rule() == Rule::statement {
463 statements.push(parse_statement(pair)?);
464 } else if pair.as_rule() == Rule::stmt_recovery {
465 let span = pair.as_span();
466 let text = pair.as_str().trim();
467 let preview = if text.len() > 40 {
468 format!("{}...", &text[..40])
469 } else {
470 text.to_string()
471 };
472 return Err(ShapeError::ParseError {
473 message: format!("Syntax error near: {}", preview),
474 location: Some(pair_location(&pair).with_length(span.end() - span.start())),
475 });
476 }
477 }
478
479 Ok(statements)
480}