use pest::iterators::Pair;
use serde::ser::{Serialize, Serializer};
use serde::Serialize as SerializeDerive;
use crate::grammar::parser::Rule;
#[derive(Debug, Clone, Eq, PartialEq, SerializeDerive)]
#[serde(untagged)]
pub enum LiteralTypes {
Array(Vec<Literal>),
String(String),
Boolean(bool),
Number(usize),
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Literal {
pub inner: LiteralTypes,
}
impl Default for Literal {
fn default() -> Self {
Self {
inner: LiteralTypes::String(String::default()),
}
}
}
impl Serialize for Literal {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.inner.serialize(serializer)
}
}
impl<'r> From<Pair<'r, Rule>> for Literal {
fn from(pair: Pair<'r, Rule>) -> Self {
let inner = match pair.as_rule() {
Rule::r#true | Rule::r#false => {
let span = pair.as_span().as_str();
match span.parse::<bool>() {
Ok(v) => LiteralTypes::Boolean(v),
Err(_) => {
unreachable!("Could not parse string to boolean")
}
}
}
Rule::number => {
let span = pair.as_span().as_str();
match span.parse::<u32>() {
Ok(n) => LiteralTypes::Number(n as usize),
Err(e) => {
unreachable!("Could not parse string to number: {:?}", e)
}
}
}
Rule::string | Rule::multi_line_string => {
let inner = pair.into_inner().next().unwrap().as_span().as_str();
LiteralTypes::String(String::from(inner))
}
Rule::array => {
let mut result = Vec::new();
for p in pair.clone().into_inner() {
result.push(Literal::from(p));
}
LiteralTypes::Array(result)
}
_ => {
unreachable!("Unexpected {:?} literal type", pair.as_rule())
}
};
Self { inner }
}
}
impl Literal {
pub fn inner(&self) -> LiteralTypes {
self.inner.clone()
}
}