use crate::err::{SJFLError, Span};
use crate::value::{List, InternedString, Table, Variable, Value};
use super::{match_exact, Parse, Session};
use hmath::Ratio;
impl Parse for Value {
fn parse(s: &[u8], ind: usize, session: &mut Session) -> Result<(Self, usize), SJFLError> {
match s[ind] {
b'"' | b'\'' => {
let (s, ind) = InternedString::parse(s, ind, session)?;
Ok((Value::String(s), ind))
}
b'-' | b'0'..=b'9' => { let (n, ind) = Ratio::parse(s, ind, session)?;
Ok((Value::Number(n), ind))
}
b'A'..=b'Z' | b'_' => { if let Ok(n) = match_exact(s, ind, b"True") {
Ok((Value::Boolean(true), n))
}
else if let Ok(n) = match_exact(s, ind, b"False") {
Ok((Value::Boolean(false), n))
}
else if let Ok(n) = match_exact(s, ind, b"None") {
Ok((Value::None, n))
}
else {
let (var, ind) = Variable::parse(s, ind, session)?;
Ok((Value::Variable(var), ind))
}
}
b'[' => { let (l, ind) = List::parse(s, ind, session)?;
Ok((Value::List(l), ind))
}
b'a'..=b'z' => { if let Ok(n) = match_exact(s, ind, b"true") {
Ok((Value::Boolean(true), n))
}
else if let Ok(n) = match_exact(s, ind, b"false") {
Ok((Value::Boolean(false), n))
}
else if let Ok(n) = match_exact(s, ind, b"null") {
Ok((Value::None, n))
}
else {
let (var, ind) = Variable::parse(s, ind, session)?;
Ok((Value::Variable(var), ind))
}
}
b'{' => { let (t, ind) = Table::parse(s, ind, session)?;
Ok((Value::Table(t), ind))
}
_ => Err(SJFLError::UnexpectedChar(s[ind], Span::from_index(ind)))
}
}
}