use vize_l0::dump::Error as DumpError;
use vize_l0::{Span, String, cstr};
use crate::dump::owned::Expr;
use crate::dump::parse::line::{err, final_span, take_quoted};
use crate::expr::OpaqueReason;
pub(super) fn take_expr(rest: &str, line_no: usize) -> Result<(Expr, &str), DumpError> {
if let Some(tail) = rest.strip_prefix("js(") {
let (source, tail) = take_quoted(tail, line_no)?;
let (span, tail) = close_span(tail, line_no)?;
return Ok((Expr::Js { source, span }, tail));
}
if let Some(tail) = rest.strip_prefix("opaque(") {
let Some((word, tail)) = tail.split_once(' ') else {
return Err(err(line_no, cstr!("expected an opaque reason")));
};
let Some(reason) = OpaqueReason::from_mnemonic(word) else {
return Err(err(line_no, cstr!("unknown opaque reason `{word}`")));
};
let (source, tail) = take_quoted(tail, line_no)?;
let (span, tail) = close_span(tail, line_no)?;
return Ok((
Expr::Opaque {
reason,
source,
span,
},
tail,
));
}
if let Some(tail) = rest.strip_prefix("foreign(") {
let Some((dialect, tail)) = tail.split_once(' ') else {
return Err(err(line_no, cstr!("expected a dialect id")));
};
if dialect.is_empty() {
return Err(err(line_no, cstr!("expected a dialect id")));
}
let (source, tail) = take_quoted(tail, line_no)?;
let (span, tail) = close_span(tail, line_no)?;
return Ok((
Expr::Foreign {
dialect: String::from(dialect),
source,
span,
},
tail,
));
}
if let Some(tail) = rest.strip_prefix("vue.filter(") {
let (source, tail) = take_quoted(tail, line_no)?;
let (span, tail) = close_span(tail, line_no)?;
return Ok((Expr::Filter { source, span }, tail));
}
Err(err(line_no, cstr!("expected an expression payload")))
}
fn close_span(tail: &str, line_no: usize) -> Result<(Span, &str), DumpError> {
let Some(tail) = tail.strip_prefix(' ') else {
return Err(err(line_no, cstr!("missing span")));
};
let Some(close) = tail.find(')') else {
return Err(err(line_no, cstr!("unterminated expression payload")));
};
let (body, after) = tail.split_at(close);
let span = final_span(body, line_no)?;
Ok((span, after.get(1..).unwrap_or_default()))
}