use crate::core_ir::{Expr, Stmt};
pub fn parse_simple_expr(text: &str) -> Option<Expr> {
let text = text.trim();
if text.is_empty() {
return None;
}
if let Some(inner) = text
.strip_prefix("print(")
.and_then(|rest| rest.strip_suffix(')'))
{
return Some(Expr::Call {
callee: Box::new(Expr::Ident("print".into())),
args: vec![parse_simple_expr(inner.trim())?],
});
}
if let Some(inner) = text.strip_prefix("print ") {
return Some(Expr::Call {
callee: Box::new(Expr::Ident("print".into())),
args: vec![parse_simple_expr(inner.trim())?],
});
}
if let Some((lhs, rhs)) = text.split_once(" + ") {
return Some(Expr::Binary {
op: "+".into(),
lhs: Box::new(parse_simple_expr(lhs)?),
rhs: Box::new(parse_simple_expr(rhs)?),
});
}
if let Ok(value) = text.parse::<i64>() {
return Some(Expr::IntLit(value));
}
if text == "true" {
return Some(Expr::BoolLit(true));
}
if text == "false" {
return Some(Expr::BoolLit(false));
}
if (text.starts_with('"') && text.ends_with('"'))
|| (text.starts_with('\'') && text.ends_with('\''))
{
return Some(Expr::StringLit(text[1..text.len() - 1].to_string()));
}
Some(Expr::Ident(text.to_string()))
}
pub fn parse_simple_body(text: &str, implicit_return: bool) -> Vec<Stmt> {
let mut out = Vec::new();
for raw in text.lines() {
let line = raw.trim().trim_end_matches([';', '.', ',']).trim();
if line.is_empty() || matches!(line, "{" | "}" | "end" | "->") {
continue;
}
if matches!(line, "nil" | "discard") {
out.push(Stmt::Return(None));
continue;
}
if let Some(expr) = line
.strip_prefix("return(")
.and_then(|rest| rest.strip_suffix(')'))
.and_then(parse_simple_expr)
{
out.push(Stmt::Return(Some(expr)));
continue;
}
if let Some(expr) = line.strip_prefix("return ").and_then(parse_simple_expr) {
out.push(Stmt::Return(Some(expr)));
continue;
}
if let Some(expr) = parse_simple_expr(line) {
out.push(Stmt::Expr(expr));
}
}
if implicit_return && let Some(Stmt::Expr(expr)) = out.pop() {
out.push(Stmt::Return(Some(expr)));
}
out
}