syncat-stylesheet 3.6.0

Parser for Syncat Stylesheets.
Documentation
use super::{Color, Variable, helper::*};
use crate::Matches;
use enquote::unquote;
use std::collections::BTreeMap;
use tree_sitter::TreeCursor;

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub(crate) enum Value {
    Color(Color),
    Number(u32),
    String(String),
    Boolean(bool),
    Variable(Variable),
    Capture(u32),
}

impl Value {
    pub(crate) fn resolve(
        &self,
        variables: &BTreeMap<String, Value>,
        matches: &Matches,
    ) -> Option<crate::Value> {
        match self {
            Value::Color(color) => Some(crate::Value::Color(*color)),
            Value::Number(number) => Some(crate::Value::Number(*number)),
            Value::String(string) => Some(crate::Value::String(string.to_string())),
            Value::Boolean(boolean) => Some(crate::Value::Boolean(*boolean)),
            Value::Variable(variable) => matches
                .get(variable.name())
                .map(str::to_string)
                .map(crate::Value::String)
                .or_else(|| variables.get(variable.name())?.resolve(variables, matches)),
            Value::Capture(index) => Some(crate::Value::String(
                matches.capture(*index as usize)?.to_string(),
            )),
        }
    }
}

impl FromSource for Value {
    fn from_source(tree: &mut TreeCursor, source: &[u8]) -> crate::Result<Self> {
        children!(tree, "value");
        extras!(tree, "value");
        let value = match tree.node().kind() {
            "color" => Value::Color(Color::from_source(tree, source)?),
            "number" => Value::Number(text!(tree, source, "number")?.parse()?),
            "string" => Value::String(unquote(text!(tree, source, "string")?)?),
            "name" => Value::String(text!(tree, source, "name")?.to_string()),
            "boolean" => Value::Boolean(text!(tree, source, "boolean")?.parse()?),
            "variable" => Value::Variable(Variable::from_source(tree, source)?),
            "capture" => Value::Capture(text!(tree, source, "number")?[1..].parse()?),
            name => return Err(crate::Error::invalid("value", name)),
        };

        tree.goto_parent();
        Ok(value)
    }
}