use crate::models::statements::*;
pub struct StatementLexer;
impl StatementLexer {
pub fn parse(statements: &[String]) -> Vec<Statement> {
let mut result = vec![];
for stmt in statements {
let parts: Vec<&str> = stmt.splitn(2, ':').collect();
let command = parts[0].trim();
let args = parts.get(1).unwrap_or(&"").trim();
let statement = match command {
"query" | "all" => Statement::Query(QueryStatement {
model: Self::parse_model_arg(args),
methods: vec!["all".to_string()],
}),
"find" | "first" => {
let model = Self::parse_model_arg(args);
Statement::Find(FindStatement {
model,
key: None,
})
}
"save" => Statement::Save(SaveStatement {
model: Self::parse_model_arg(args),
}),
"update" => {
let parts: Vec<&str> = args.split_whitespace().collect();
let model = if parts.is_empty() {
None
} else {
Some(parts[0].to_string())
};
let columns = if parts.len() > 1 {
parts[1..].iter().map(|s| s.to_string()).collect()
} else {
vec![]
};
Statement::Update(UpdateStatement { model, columns })
}
"delete" => Statement::Delete(DeleteStatement {
model: Self::parse_model_arg(args),
}),
"validate" => Statement::Validate(ValidateStatement {
fields: args.split(',').map(|s| s.trim().to_string()).filter(|s| !s.is_empty()).collect(),
}),
"send" => {
let parts: Vec<&str> = args.split_whitespace().collect();
let class = parts.first().unwrap_or(&"").to_string();
let to = parts.iter().position(|&p| p == "to")
.and_then(|i| parts.get(i + 1))
.map(|s| s.to_string());
let data = parts.iter().position(|&p| p == "with")
.and_then(|i| parts.get(i + 1))
.map(|s| s.split(',').map(|s| s.trim().to_string()).collect())
.unwrap_or_default();
Statement::Send(SendStatement { class, to, data })
}
"notify" => {
let parts: Vec<&str> = args.split_whitespace().collect();
let model = parts.first().map(|s| s.to_string());
let notification = parts.iter().position(|&p| p == "with")
.and_then(|i| parts.get(i + 1))
.map(|s| s.to_string())
.unwrap_or_default();
let data = vec![];
Statement::Notify(NotifyStatement {
model,
notification,
data,
})
}
"dispatch" => {
let parts: Vec<&str> = args.split_whitespace().collect();
let job = parts.first().unwrap_or(&"").to_string();
let data = parts.iter().position(|&p| p == "with")
.and_then(|i| parts.get(i + 1))
.map(|s| s.split(',').map(|s| s.trim().to_string()).collect())
.unwrap_or_default();
Statement::Dispatch(DispatchStatement { job, data })
}
"fire" => {
let parts: Vec<&str> = args.split_whitespace().collect();
let event = parts.first().unwrap_or(&"").to_string();
let data = parts.iter().position(|&p| p == "with")
.and_then(|i| parts.get(i + 1))
.map(|s| s.split(',').map(|s| s.trim().to_string()).collect())
.unwrap_or_default();
Statement::Fire(FireStatement { event, data })
}
"render" => {
let parts: Vec<&str> = args.split_whitespace().collect();
let view = parts.first().unwrap_or(&"").to_string();
let data = parts.iter().position(|&p| p == "with")
.and_then(|i| parts.get(i + 1))
.map(|s| s.split(',').map(|s| s.trim().to_string()).collect())
.unwrap_or_default();
Statement::Render(RenderStatement { view, data })
}
"redirect" => {
let parts: Vec<&str> = args.split_whitespace().collect();
let route = parts.first().unwrap_or(&"").to_string();
let params = if parts.len() > 1 {
parts[1..].iter().map(|s| s.to_string()).collect()
} else {
vec![]
};
Statement::Redirect(RedirectStatement { route, params })
}
"respond" => {
let status = args.parse::<u16>().ok();
Statement::Respond(RespondStatement { status })
}
"resource" => {
let parts: Vec<&str> = args.split_whitespace().collect();
let collection = parts.iter().any(|&p| p == "collection:");
let model = if collection {
parts.iter().find_map(|&p| {
if p.starts_with("collection:") {
p.strip_prefix("collection:").map(|s| s.to_string())
} else {
None
}
})
} else {
parts.first().map(|s| s.to_string())
};
Statement::Resource(ResourceStatement { model, collection })
}
"flash" => Statement::Flash(FlashStatement {
reference: args.to_string(),
}),
"inertia" => {
let parts: Vec<&str> = args.split_whitespace().collect();
let component = parts.first().unwrap_or(&"").to_string();
let data = parts.iter().position(|&p| p == "with")
.and_then(|i| parts.get(i + 1))
.map(|s| s.split(',').map(|s| s.trim().to_string()).collect())
.unwrap_or_default();
Statement::Inertia(InertiaStatement { component, data })
}
_ => {
let parts: Vec<&str> = args.split_whitespace().collect();
Statement::Eloquent(EloquentStatement {
operation: command.to_string(),
model: parts.first().map(|s| s.to_string()),
columns: parts[1..].iter().map(|s| s.to_string()).collect(),
})
}
};
result.push(statement);
}
result
}
fn parse_model_arg(args: &str) -> Option<String> {
let args = args.trim();
if args.is_empty() { None } else { Some(args.to_string()) }
}
}