use serde_json::Value;
use crate::lexer::TokenKind;
use super::stream::Stream;
pub fn js_number(text: &str) -> Value {
let f: f64 = text.parse().unwrap_or(f64::NAN);
number_from_f64(f)
}
pub fn number_from_f64(f: f64) -> Value {
if f.is_finite() && f.fract() == 0.0 {
if f >= i64::MIN as f64 && f <= i64::MAX as f64 {
return Value::from(f as i64);
}
if f >= 0.0 && f <= u64::MAX as f64 {
return Value::from(f as u64);
}
}
serde_json::Number::from_f64(f)
.map(Value::Number)
.unwrap_or(Value::Null)
}
pub fn s_identifier(s: &mut Stream) -> Option<String> {
match s.peek()?.kind.clone() {
TokenKind::IdentifierQuoted => s.eat(&TokenKind::IdentifierQuoted),
TokenKind::IdentifierUnquoted => s.eat(&TokenKind::IdentifierUnquoted),
TokenKind::Keyword(_) => {
let v = s.peek().map(|t| t.value.clone());
s.bump();
v
}
_ => None,
}
}
pub fn o_quoted_string(s: &mut Stream) -> Option<String> {
s.eat(&TokenKind::DQuoteString)
.or_else(|| s.eat(&TokenKind::SQuoteString))
}
pub fn o_string_or_ident(s: &mut Stream) -> Option<String> {
if let Some(v) = o_quoted_string(s) {
return Some(v);
}
s_identifier(s)
}
pub fn o_table_option_value(s: &mut Stream) -> Option<Value> {
if let Some(v) = o_quoted_string(s) {
return Some(Value::String(v));
}
let save = s.pos();
if let Some(v) = s_identifier(s) {
return Some(Value::String(v));
}
s.set(save);
if let Some(text) = s.eat(&TokenKind::Number) {
return Some(js_number(&text));
}
None
}
pub fn s_number(s: &mut Stream) -> Option<Value> {
s.eat(&TokenKind::Number).map(|t| js_number(&t))
}