From 4bf3c6fd638f8537cd978fde7b720ac503d5284a Mon Sep 17 00:00:00 2001 From: elkowar <5300871+elkowar@users.noreply.github.com> Date: Thu, 22 Jul 2021 17:44:15 +0200 Subject: [PATCH] It compiles :o --- Cargo.lock | 11 +++++ Cargo.toml | 3 +- crates/eww/Cargo.toml | 2 + crates/eww/src/app.rs | 41 ++++++++-------- crates/eww/src/config/eww_config.rs | 21 ++++---- crates/eww/src/config/inbuilt.rs | 6 +-- crates/eww/src/eww_state.rs | 12 ++--- crates/eww/src/main.rs | 4 +- crates/eww/src/opts.rs | 10 ++-- crates/eww/src/script_var_handler.rs | 3 +- crates/eww/src/server.rs | 2 +- crates/eww/src/widgets/mod.rs | 5 +- crates/eww/src/widgets/widget_definitions.rs | 23 +++++---- crates/eww/src/widgets/widget_node.rs | 28 +++-------- crates/eww_shared_util/Cargo.toml | 8 ++++ crates/eww_shared_util/src/lib.rs | 5 ++ crates/eww_shared_util/src/span.rs | 36 ++++++++++++++ crates/eww_shared_util/src/wrappers.rs | 42 ++++++++++++++++ crates/simplexpr/Cargo.toml | 1 + crates/simplexpr/src/ast.rs | 20 ++------ crates/simplexpr/src/dynval.rs | 2 +- crates/simplexpr/src/error.rs | 2 +- crates/simplexpr/src/eval.rs | 44 +++++++++++++---- crates/simplexpr/src/lib.rs | 5 +- crates/simplexpr/src/simplexpr_parser.lalrpop | 5 +- crates/yuck/Cargo.toml | 1 + crates/yuck/src/config/attributes.rs | 7 +-- .../yuck/src/config/backend_window_options.rs | 7 +-- crates/yuck/src/config/config.rs | 4 +- .../yuck/src/config/script_var_definition.rs | 4 +- crates/yuck/src/config/test.rs | 9 +--- crates/yuck/src/config/validate.rs | 8 +--- crates/yuck/src/config/var_definition.rs | 4 +- crates/yuck/src/config/widget_definition.rs | 4 +- crates/yuck/src/config/widget_use.rs | 10 ++-- crates/yuck/src/config/window_definition.rs | 5 +- crates/yuck/src/config/window_geometry.rs | 20 ++++---- crates/yuck/src/error.rs | 3 +- crates/yuck/src/format_diagnostic.rs | 3 +- crates/yuck/src/parser/ast.rs | 48 +------------------ crates/yuck/src/parser/ast_iterator.rs | 6 +-- crates/yuck/src/parser/from_ast.rs | 7 +-- crates/yuck/src/parser/lexer.rs | 3 +- crates/yuck/src/parser/mod.rs | 7 +++ crates/yuck/src/parser/parse_error.rs | 2 +- crates/yuck/src/parser/parser.lalrpop | 5 +- crates/yuck/src/value/mod.rs | 36 -------------- 47 files changed, 279 insertions(+), 265 deletions(-) create mode 100644 crates/eww_shared_util/Cargo.toml create mode 100644 crates/eww_shared_util/src/lib.rs create mode 100644 crates/eww_shared_util/src/span.rs create mode 100644 crates/eww_shared_util/src/wrappers.rs diff --git a/Cargo.lock b/Cargo.lock index 1349726..6a62da4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -436,6 +436,7 @@ dependencies = [ "debug_stub_derive", "derive_more", "dyn-clone", + "eww_shared_util", "extend", "futures-core", "futures-util", @@ -475,6 +476,14 @@ dependencies = [ "yuck", ] +[[package]] +name = "eww_shared_util" +version = "0.1.0" +dependencies = [ + "derive_more", + "serde", +] + [[package]] name = "extend" version = "1.1.1" @@ -1874,6 +1883,7 @@ dependencies = [ name = "simplexpr" version = "0.1.0" dependencies = [ + "eww_shared_util", "insta", "itertools 0.10.1", "lalrpop", @@ -2374,6 +2384,7 @@ dependencies = [ "anyhow", "codespan-reporting", "derive_more", + "eww_shared_util", "insta", "itertools 0.10.1", "lalrpop", diff --git a/Cargo.toml b/Cargo.toml index bed4082..ce16374 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,5 +2,6 @@ members = [ "crates/eww", "crates/simplexpr", - "crates/yuck" + "crates/yuck", + "crates/eww_shared_util" ] diff --git a/crates/eww/Cargo.toml b/crates/eww/Cargo.toml index 910bfbe..2d77226 100644 --- a/crates/eww/Cargo.toml +++ b/crates/eww/Cargo.toml @@ -69,6 +69,8 @@ notify = "5.0.0-pre.7" simplexpr = { path = "../simplexpr" } yuck = { path = "../yuck" } +eww_shared_util = { path = "../eww_shared_util" } + [dev-dependencies] pretty_assertions = "0.7.1" diff --git a/crates/eww/src/app.rs b/crates/eww/src/app.rs index 77456d6..18b2cd9 100644 --- a/crates/eww/src/app.rs +++ b/crates/eww/src/app.rs @@ -6,6 +6,7 @@ use crate::{ }; use anyhow::*; use debug_stub_derive::*; +use eww_shared_util::VarName; use gdk::WindowExt; use gtk::{ContainerExt, CssProviderExt, GtkWindowExt, StyleContextExt, WidgetExt}; use itertools::Itertools; @@ -14,7 +15,7 @@ use std::collections::HashMap; use tokio::sync::mpsc::UnboundedSender; use yuck::{ config::window_geometry::{AnchorPoint, WindowGeometry}, - value::{Coords, VarName}, + value::Coords, }; /// Response that the app may send as a response to a event. @@ -112,30 +113,26 @@ impl App { } } DaemonCommand::ReloadConfigAndCss(sender) => { + let mut errors = Vec::new(); - // TODO implement this - //let mut errors = Vec::new(); - todo!() + let config_result = EwwConfig::read_from_file(&self.paths.get_yuck_path()); + match config_result { + Ok(new_config) => self.handle_command(DaemonCommand::UpdateConfig(new_config)), + Err(e) => errors.push(e), + } - //let config_result = - //EwwConfig::read_from_file(&self.paths.get_eww_xml_path()).and_then(config::EwwConfig::generate); - //match config_result { - //Ok(new_config) => self.handle_command(DaemonCommand::UpdateConfig(new_config)), - //Err(e) => errors.push(e), - //} + let css_result = crate::util::parse_scss_from_file(&self.paths.get_eww_scss_path()); + match css_result { + Ok(new_css) => self.handle_command(DaemonCommand::UpdateCss(new_css)), + Err(e) => errors.push(e), + } - //let css_result = crate::util::parse_scss_from_file(&self.paths.get_eww_scss_path()); - //match css_result { - //Ok(new_css) => self.handle_command(DaemonCommand::UpdateCss(new_css)), - //Err(e) => errors.push(e), - //} - - //let errors = errors.into_iter().map(|e| format!("{:?}", e)).join("\n"); - //if errors.is_empty() { - //sender.send(DaemonResponse::Success(String::new()))?; - //} else { - //sender.send(DaemonResponse::Failure(errors))?; - //} + let errors = errors.into_iter().map(|e| format!("{:?}", e)).join("\n"); + if errors.is_empty() { + sender.send(DaemonResponse::Success(String::new()))?; + } else { + sender.send(DaemonResponse::Failure(errors))?; + } } DaemonCommand::UpdateConfig(config) => { self.load_config(config)?; diff --git a/crates/eww/src/config/eww_config.rs b/crates/eww/src/config/eww_config.rs index ed1af4b..1fafdcd 100644 --- a/crates/eww/src/config/eww_config.rs +++ b/crates/eww/src/config/eww_config.rs @@ -1,15 +1,13 @@ use anyhow::*; +use eww_shared_util::VarName; use std::collections::HashMap; use yuck::{ config::{script_var_definition::ScriptVarDefinition, widget_definition::WidgetDefinition}, parser::from_ast::FromAst, - value::VarName, }; use simplexpr::dynval::DynVal; -use std::path::PathBuf; - use super::{script_var, EwwWindowDefinition}; /// Eww configuration structure. @@ -19,33 +17,30 @@ pub struct EwwConfig { windows: HashMap, initial_variables: HashMap, script_vars: HashMap, - pub filepath: PathBuf, } impl EwwConfig { pub fn read_from_file>(path: P) -> Result { let content = std::fs::read_to_string(path)?; - let ast = yuck::parser::parse_string(0, &content)?; + let ast = yuck::parser::parse_toplevel(0, &content)?; let config = yuck::config::Config::from_ast(ast)?; Self::generate(config) } pub fn generate(config: yuck::config::Config) -> Result { + let yuck::config::Config { widget_definitions, window_definitions, var_definitions, script_vars } = config; Ok(EwwConfig { - windows: config - .window_definitions + windows: window_definitions .into_iter() .map(|(name, window)| { Ok(( name, - EwwWindowDefinition::generate(&config.widget_definitions, window) - .context("Failed expand window definition")?, + EwwWindowDefinition::generate(&widget_definitions, window).context("Failed expand window definition")?, )) }) .collect::>>()?, - widgets: config.widget_definitions, - initial_variables: config.var_definitions.into_iter().map(|(k, v)| (k, v.initial_value)).collect(), - script_vars: config.script_vars, - filepath: todo!(), + widgets: widget_definitions, + initial_variables: var_definitions.into_iter().map(|(k, v)| (k, v.initial_value)).collect(), + script_vars, }) } diff --git a/crates/eww/src/config/inbuilt.rs b/crates/eww/src/config/inbuilt.rs index 5f98212..9e36276 100644 --- a/crates/eww/src/config/inbuilt.rs +++ b/crates/eww/src/config/inbuilt.rs @@ -1,12 +1,10 @@ use std::{collections::HashMap, time::Duration}; use simplexpr::dynval::DynVal; -use yuck::{ - config::script_var_definition::{PollScriptVar, ScriptVarDefinition, VarSource}, - value::VarName, -}; +use yuck::config::script_var_definition::{PollScriptVar, ScriptVarDefinition, VarSource}; use crate::config::system_stats::*; +use eww_shared_util::VarName; macro_rules! builtin_vars { ($interval:expr, $($name:literal => $fun:expr),*$(,)?) => {{ diff --git a/crates/eww/src/eww_state.rs b/crates/eww/src/eww_state.rs index 20bb448..92aeeee 100644 --- a/crates/eww/src/eww_state.rs +++ b/crates/eww/src/eww_state.rs @@ -1,6 +1,6 @@ use anyhow::*; +use eww_shared_util::{AttrName, VarName}; use std::{collections::HashMap, sync::Arc}; -use yuck::value::{AttrName, VarName}; use simplexpr::{dynval::DynVal, SimplExpr}; @@ -12,9 +12,8 @@ pub struct StateChangeHandler { } impl StateChangeHandler { - fn used_variables(&self) -> impl Iterator + '_ { - // TODO fix this clone - self.unresolved_values.iter().flat_map(|(_, value)| value.var_refs()).map(|x| VarName(x.to_string())) + fn used_variables(&self) -> impl Iterator { + self.unresolved_values.iter().flat_map(|(_, value)| value.var_refs()) } /// Run the StateChangeHandler. @@ -24,7 +23,7 @@ impl StateChangeHandler { .unresolved_values .clone() .into_iter() - .map(|(attr_name, value)| Ok((attr_name, value.resolve_fully(state)?))) + .map(|(attr_name, value)| Ok((attr_name, value.eval(state)?))) .collect::>(); match resolved_attrs { @@ -107,8 +106,7 @@ impl EwwState { /// resolves a value if possible, using the current eww_state. pub fn resolve_once<'a>(&'a self, value: &'a SimplExpr) -> Result { - // TODO fix this clone - Ok(value.clone().eval(&self.variables_state.into_iter().map(|(k, v)| (k.0, v)).collect())?) + Ok(value.clone().eval(&self.variables_state)?) } /// Resolve takes a function that applies a set of fully resolved attribute diff --git a/crates/eww/src/main.rs b/crates/eww/src/main.rs index a39850c..527e222 100644 --- a/crates/eww/src/main.rs +++ b/crates/eww/src/main.rs @@ -162,8 +162,8 @@ impl EwwPaths { self.config_dir.as_path() } - pub fn get_eww_xml_path(&self) -> PathBuf { - self.config_dir.join("eww.xml") + pub fn get_yuck_path(&self) -> PathBuf { + self.config_dir.join("eww.yuck") } pub fn get_eww_scss_path(&self) -> PathBuf { diff --git a/crates/eww/src/opts.rs b/crates/eww/src/opts.rs index 95872d5..9e82045 100644 --- a/crates/eww/src/opts.rs +++ b/crates/eww/src/opts.rs @@ -1,11 +1,9 @@ use anyhow::*; +use eww_shared_util::VarName; use serde::{Deserialize, Serialize}; use simplexpr::dynval::DynVal; use structopt::StructOpt; -use yuck::{ - config::window_geometry::AnchorPoint, - value::{Coords, VarName}, -}; +use yuck::{config::window_geometry::AnchorPoint, value::Coords}; use crate::app; @@ -23,7 +21,7 @@ struct RawOpt { #[structopt(long = "debug", global = true)] log_debug: bool, - /// override path to configuration directory (directory that contains eww.xml and eww.scss) + /// override path to configuration directory (directory that contains eww.yuck and eww.scss) #[structopt(short, long, global = true)] config: Option, @@ -153,7 +151,7 @@ fn parse_var_update_arg(s: &str) -> Result<(VarName, DynVal)> { impl ActionWithServer { pub fn into_daemon_command(self) -> (app::DaemonCommand, Option) { let command = match self { - ActionWithServer::Update { mappings } => app::DaemonCommand::UpdateVars(mappings.into_iter().collect()), + ActionWithServer::Update { mappings } => app::DaemonCommand::UpdateVars(mappings), ActionWithServer::KillServer => app::DaemonCommand::KillServer, ActionWithServer::CloseAll => app::DaemonCommand::CloseAll, diff --git a/crates/eww/src/script_var_handler.rs b/crates/eww/src/script_var_handler.rs index ced0b17..0d94395 100644 --- a/crates/eww/src/script_var_handler.rs +++ b/crates/eww/src/script_var_handler.rs @@ -4,13 +4,14 @@ use crate::app; use anyhow::*; use app::DaemonCommand; +use eww_shared_util::VarName; use simplexpr::dynval::DynVal; use tokio::{ io::{AsyncBufReadExt, BufReader}, sync::mpsc::UnboundedSender, }; use tokio_util::sync::CancellationToken; -use yuck::{config::script_var_definition::{PollScriptVar, ScriptVarDefinition, TailScriptVar}, value::VarName}; +use yuck::config::script_var_definition::{PollScriptVar, ScriptVarDefinition, TailScriptVar}; /// Initialize the script var handler, and return a handle to that handler, which can be used to control /// the script var execution. diff --git a/crates/eww/src/server.rs b/crates/eww/src/server.rs index 3df39a6..f2c8127 100644 --- a/crates/eww/src/server.rs +++ b/crates/eww/src/server.rs @@ -27,7 +27,7 @@ pub fn initialize_server(paths: EwwPaths) -> Result<()> { .with_context(|| format!("Failed to change working directory to {}", paths.get_config_dir().display()))?; log::info!("Loading paths: {}", &paths); - let eww_config = config::EwwConfig::read_from_file(&paths.get_eww_xml_path())?; + let eww_config = config::EwwConfig::read_from_file(&paths.get_yuck_path())?; gtk::init()?; diff --git a/crates/eww/src/widgets/mod.rs b/crates/eww/src/widgets/mod.rs index f36d48b..7598ff7 100644 --- a/crates/eww/src/widgets/mod.rs +++ b/crates/eww/src/widgets/mod.rs @@ -1,9 +1,10 @@ use crate::eww_state::*; use anyhow::*; +use eww_shared_util::AttrName; use gtk::prelude::*; use itertools::Itertools; use std::collections::HashMap; -use yuck::{config::widget_definition::WidgetDefinition, value::AttrName}; +use yuck::config::widget_definition::WidgetDefinition; use std::process::Command; use widget_definitions::*; @@ -129,7 +130,7 @@ macro_rules! resolve_block { let attr_map: Result<_> = try { ::maplit::hashmap! { $( - yuck::value::AttrName(::std::stringify!($attr_name).to_owned()) => + eww_shared_util::AttrName(::std::stringify!($attr_name).to_owned()) => resolve_block!(@get_value $args, &::std::stringify!($attr_name).replace('_', "-"), $(= $default)?) ),* } diff --git a/crates/eww/src/widgets/widget_definitions.rs b/crates/eww/src/widgets/widget_definitions.rs index 2494042..f4cd54c 100644 --- a/crates/eww/src/widgets/widget_definitions.rs +++ b/crates/eww/src/widgets/widget_definitions.rs @@ -1,7 +1,7 @@ #![allow(clippy::option_map_unit_fn)] use super::{run_command, BuilderArgs}; use crate::{ - config, enum_parse, eww_state, resolve_block, + enum_parse, eww_state, resolve_block, util::{list_difference, parse_duration}, widgets::widget_node, }; @@ -10,6 +10,7 @@ use gdk::WindowExt; use glib; use gtk::{self, prelude::*, ImageExt}; use std::{cell::RefCell, collections::HashMap, rc::Rc}; +use yuck::parser::from_ast::FromAst; // TODO figure out how to // TODO https://developer.gnome.org/gtk3/stable/GtkFixed.html @@ -244,12 +245,13 @@ fn build_gtk_combo_box_text(bargs: &mut BuilderArgs) -> Result>> = Rc::new(RefCell::new(None)); resolve_block!(bargs, gtk_widget, { // @prop items - Items that should be displayed in the combo box - prop(items: as_vec) { - gtk_widget.remove_all(); - for i in items { - gtk_widget.append_text(&i); - } - }, + // TODO reimplement, obviously + //prop(items: as_vec) { + //gtk_widget.remove_all(); + //for i in items { + //gtk_widget.append_text(&i); + //} + //}, // @prop onchange - runs the code when a item was selected, replacing {} with the item as a string prop(onchange: as_string) { let old_id = on_change_handler_id.replace(Some( @@ -518,15 +520,16 @@ fn build_gtk_literal(bargs: &mut BuilderArgs) -> Result { gtk_widget.set_widget_name("literal"); // TODO these clones here are dumdum - let window_name = bargs.window_name.clone(); + let window_name = bargs.window_name.to_string(); let widget_definitions = bargs.widget_definitions.clone(); + resolve_block!(bargs, gtk_widget, { // @prop content - inline Eww XML that will be rendered as a widget. prop(content: as_string) { gtk_widget.get_children().iter().for_each(|w| gtk_widget.remove(w)); if !content.is_empty() { - let document = roxmltree::Document::parse(&content).map_err(|e| anyhow!("Failed to parse eww xml literal: {:?}", e))?; - let content_widget_use = config::element::WidgetUse::from_xml_node(document.root_element().into())?; + let ast = yuck::parser::parse_string(usize::MAX, &content)?; + let content_widget_use = yuck::config::widget_use::WidgetUse::from_ast(ast)?; let widget_node = &*widget_node::generate_generic_widget_node(&widget_definitions, &HashMap::new(), content_widget_use)?; let child_widget = widget_node.render(&mut eww_state::EwwState::default(), &window_name, &widget_definitions)?; diff --git a/crates/eww/src/widgets/widget_node.rs b/crates/eww/src/widgets/widget_node.rs index ad0ef0d..82a367f 100644 --- a/crates/eww/src/widgets/widget_node.rs +++ b/crates/eww/src/widgets/widget_node.rs @@ -1,13 +1,10 @@ use crate::eww_state::EwwState; use anyhow::*; use dyn_clone; +use eww_shared_util::{AttrName, Span, VarName}; use simplexpr::SimplExpr; use std::collections::HashMap; -use yuck::{ - config::{widget_definition::WidgetDefinition, widget_use::WidgetUse}, - parser::ast::Span, - value::{AttrName, VarName}, -}; +use yuck::config::{widget_definition::WidgetDefinition, widget_use::WidgetUse}; pub trait WidgetNode: std::fmt::Debug + dyn_clone::DynClone + Send + Sync { fn get_name(&self) -> &str; @@ -70,9 +67,8 @@ impl Generic { } /// returns all the variables that are referenced in this widget - pub fn referenced_vars(&self) -> impl Iterator + '_ { - // TODO fix this clone - self.attrs.iter().flat_map(|(_, value)| value.var_refs()).map(|x| VarName(x.to_string())) + pub fn referenced_vars(&self) -> impl Iterator { + self.attrs.iter().flat_map(|(_, value)| value.var_refs()) } } @@ -108,12 +104,7 @@ pub fn generate_generic_widget_node( .attrs .attrs .into_iter() - .map(|(name, value)| { - Ok(( - VarName(name.0), - SimplExpr::Literal(value.value.span().into(), value.value.as_simplexpr()?.resolve_one_level(local_env)?), - )) - }) + .map(|(name, value)| Ok((VarName(name.0), value.value.as_simplexpr()?.resolve_one_level(local_env)))) .collect::>>()?; let content = generate_generic_widget_node(defs, &new_local_env, def.widget.clone())?; @@ -126,13 +117,8 @@ pub fn generate_generic_widget_node( .attrs .attrs .into_iter() - .map(|(name, value)| { - Ok(( - VarName(name.0), - SimplExpr::Literal(value.value.span().into(), value.value.as_simplexpr()?.resolve_one_level(local_env)?), - )) - }) - .collect()?, + .map(|(name, value)| Ok((name, value.value.as_simplexpr()?.resolve_one_level(local_env)))) + .collect::>>()?, children: w .children diff --git a/crates/eww_shared_util/Cargo.toml b/crates/eww_shared_util/Cargo.toml new file mode 100644 index 0000000..3293833 --- /dev/null +++ b/crates/eww_shared_util/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "eww_shared_util" +version = "0.1.0" +edition = "2018" + +[dependencies] +serde = {version = "1.0", features = ["derive"]} +derive_more = "0.99" diff --git a/crates/eww_shared_util/src/lib.rs b/crates/eww_shared_util/src/lib.rs new file mode 100644 index 0000000..de590ff --- /dev/null +++ b/crates/eww_shared_util/src/lib.rs @@ -0,0 +1,5 @@ +pub mod span; +pub mod wrappers; + +pub use span::*; +pub use wrappers::*; diff --git a/crates/eww_shared_util/src/span.rs b/crates/eww_shared_util/src/span.rs new file mode 100644 index 0000000..589f295 --- /dev/null +++ b/crates/eww_shared_util/src/span.rs @@ -0,0 +1,36 @@ +#[derive(Eq, PartialEq, Clone, Copy, serde::Serialize, serde::Deserialize)] +pub struct Span(pub usize, pub usize, pub usize); +pub static DUMMY_SPAN: Span = Span(usize::MAX, usize::MAX, usize::MAX); + +impl Span { + /// Get the span that includes this and the other span completely. + /// Will panic if the spans are from different file_ids. + pub fn to(mut self, other: Span) -> Self { + assert!(other.2 == self.2); + self.1 = other.1; + self + } + + pub fn ending_at(mut self, end: usize) -> Self { + self.1 = end; + self + } + + /// Turn this span into a span only highlighting the point it starts at, setting the length to 0. + pub fn point_span(mut self) -> Self { + self.1 = self.0; + self + } +} + +impl std::fmt::Display for Span { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}..{}", self.0, self.1) + } +} + +impl std::fmt::Debug for Span { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}..{}", self.0, self.1) + } +} diff --git a/crates/eww_shared_util/src/wrappers.rs b/crates/eww_shared_util/src/wrappers.rs new file mode 100644 index 0000000..dabdfe8 --- /dev/null +++ b/crates/eww_shared_util/src/wrappers.rs @@ -0,0 +1,42 @@ +use derive_more::*; +use serde::{Deserialize, Serialize}; + +/// The name of a variable +#[repr(transparent)] +#[derive( + Clone, Hash, PartialEq, Eq, Serialize, Deserialize, AsRef, From, FromStr, Display, DebugCustom, +)] +#[debug(fmt = "VarName({})", .0)] +pub struct VarName(pub String); + +impl std::borrow::Borrow for VarName { + fn borrow(&self) -> &str { + &self.0 + } +} + +impl From<&str> for VarName { + fn from(s: &str) -> Self { + VarName(s.to_owned()) + } +} + +/// The name of an attribute +#[repr(transparent)] +#[derive( + Clone, Hash, PartialEq, Eq, Serialize, Deserialize, AsRef, From, FromStr, Display, DebugCustom, +)] +#[debug(fmt="AttrName({})", .0)] +pub struct AttrName(pub String); + +impl std::borrow::Borrow for AttrName { + fn borrow(&self) -> &str { + &self.0 + } +} + +impl From<&str> for AttrName { + fn from(s: &str) -> Self { + AttrName(s.to_owned()) + } +} diff --git a/crates/simplexpr/Cargo.toml b/crates/simplexpr/Cargo.toml index df354ef..ead2853 100644 --- a/crates/simplexpr/Cargo.toml +++ b/crates/simplexpr/Cargo.toml @@ -20,6 +20,7 @@ serde_json = "1.0" strum = { version = "0.21", features = ["derive"] } +eww_shared_util = { path = "../eww_shared_util" } [build-dependencies] diff --git a/crates/simplexpr/src/ast.rs b/crates/simplexpr/src/ast.rs index 22bc15d..e63d2d3 100644 --- a/crates/simplexpr/src/ast.rs +++ b/crates/simplexpr/src/ast.rs @@ -1,23 +1,9 @@ use crate::dynval::DynVal; +use eww_shared_util::{Span, DUMMY_SPAN}; use itertools::Itertools; use serde::{Deserialize, Serialize}; -/// stores the left and right end of a span, and a given file identifier. -#[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)] -pub struct Span(pub usize, pub usize, pub usize); -pub static DUMMY_SPAN: Span = Span(usize::MAX, usize::MAX, usize::MAX); - -impl std::fmt::Display for Span { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}..{}", self.0, self.1) - } -} - -impl std::fmt::Debug for Span { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}..{}", self.0, self.1) - } -} +use eww_shared_util::VarName; #[rustfmt::skip] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug, strum::EnumString, strum::Display)] @@ -46,7 +32,7 @@ pub enum UnaryOp { #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum SimplExpr { Literal(Span, DynVal), - VarRef(Span, String), + VarRef(Span, VarName), BinOp(Span, Box, BinOp, Box), UnaryOp(Span, UnaryOp, Box), IfElse(Span, Box, Box, Box), diff --git a/crates/simplexpr/src/dynval.rs b/crates/simplexpr/src/dynval.rs index e9685f0..f72248d 100644 --- a/crates/simplexpr/src/dynval.rs +++ b/crates/simplexpr/src/dynval.rs @@ -1,4 +1,4 @@ -use crate::ast::Span; +use eww_shared_util::Span; use itertools::Itertools; use serde::{Deserialize, Serialize}; use std::{fmt, iter::FromIterator, str::FromStr}; diff --git a/crates/simplexpr/src/error.rs b/crates/simplexpr/src/error.rs index 187f18d..76bbbbc 100644 --- a/crates/simplexpr/src/error.rs +++ b/crates/simplexpr/src/error.rs @@ -1,8 +1,8 @@ use crate::{ - ast::Span, dynval, parser::lexer::{self, LexicalError}, }; +use eww_shared_util::Span; pub type Result = std::result::Result; #[derive(thiserror::Error, Debug)] diff --git a/crates/simplexpr/src/eval.rs b/crates/simplexpr/src/eval.rs index 3c70583..ea2bb2a 100644 --- a/crates/simplexpr/src/eval.rs +++ b/crates/simplexpr/src/eval.rs @@ -1,9 +1,10 @@ use itertools::Itertools; use crate::{ - ast::{BinOp, SimplExpr, Span, UnaryOp}, + ast::{BinOp, SimplExpr, UnaryOp}, dynval::{ConversionError, DynVal}, }; +use eww_shared_util::{Span, VarName}; use std::collections::HashMap; #[derive(Debug, thiserror::Error)] @@ -50,13 +51,6 @@ impl EvalError { } } -type VarName = String; - -pub trait FunctionSource { - type Err; - fn run_fn(&self, name: &str, args: &[DynVal]) -> Result; -} - impl SimplExpr { pub fn map_terminals_into(self, f: impl Fn(Self) -> Self) -> Self { use SimplExpr::*; @@ -70,6 +64,36 @@ impl SimplExpr { } } + /// map over all of the variable references, replacing them with whatever expression the provided function returns. + /// Returns [Err] when the provided function fails with an [Err] + pub fn try_map_var_refs Result + Copy>(self, f: F) -> Result { + use SimplExpr::*; + Ok(match self { + BinOp(span, box a, op, box b) => BinOp(span, box a.try_map_var_refs(f)?, op, box b.try_map_var_refs(f)?), + UnaryOp(span, op, box a) => UnaryOp(span, op, box a.try_map_var_refs(f)?), + IfElse(span, box a, box b, box c) => { + IfElse(span, box a.try_map_var_refs(f)?, box b.try_map_var_refs(f)?, box c.try_map_var_refs(f)?) + } + JsonAccess(span, box a, box b) => JsonAccess(span, box a.try_map_var_refs(f)?, box b.try_map_var_refs(f)?), + FunctionCall(span, name, args) => { + FunctionCall(span, name, args.into_iter().map(|x| x.try_map_var_refs(f)).collect::>()?) + } + VarRef(span, name) => f(span, name)?, + x @ Literal(..) => x, + }) + } + + pub fn map_var_refs(self, f: impl Fn(Span, VarName) -> SimplExpr) -> Self { + self.try_map_var_refs(|span, var| Ok::<_, !>(f(span, var))).into_ok() + } + + /// resolve partially. + /// If a var-ref links to another var-ref, that other var-ref is used. + /// If a referenced variable is not found in the given hashmap, returns the var-ref unchanged. + pub fn resolve_one_level(self, variables: &HashMap) -> Self { + self.map_var_refs(|span, name| variables.get(&name).cloned().unwrap_or_else(|| Self::VarRef(span, name))) + } + /// resolve variable references in the expression. Fails if a variable cannot be resolved. pub fn resolve_refs(self, variables: &HashMap) -> Result { use SimplExpr::*; @@ -96,7 +120,7 @@ impl SimplExpr { } } - pub fn var_refs(&self) -> Vec<&String> { + pub fn var_refs(&self) -> Vec<&VarName> { use SimplExpr::*; match self { Literal(..) => Vec::new(), @@ -130,7 +154,7 @@ impl SimplExpr { let value = match self { SimplExpr::Literal(_, x) => Ok(x.clone()), SimplExpr::VarRef(span, ref name) => { - Ok(values.get(name).cloned().ok_or_else(|| EvalError::UnresolvedVariable(name.to_string()).at(*span))?.at(*span)) + Ok(values.get(name).cloned().ok_or_else(|| EvalError::UnresolvedVariable(name.clone()).at(*span))?.at(*span)) } SimplExpr::BinOp(_, a, op, b) => { let a = a.eval(values)?; diff --git a/crates/simplexpr/src/lib.rs b/crates/simplexpr/src/lib.rs index 74df615..48156f4 100644 --- a/crates/simplexpr/src/lib.rs +++ b/crates/simplexpr/src/lib.rs @@ -1,13 +1,16 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(try_blocks)] +#![feature(unwrap_infallible)] +#![feature(never_type)] + pub mod ast; pub mod dynval; pub mod error; pub mod eval; pub mod parser; -pub use ast::{SimplExpr, Span}; +pub use ast::SimplExpr; use lalrpop_util::lalrpop_mod; diff --git a/crates/simplexpr/src/simplexpr_parser.lalrpop b/crates/simplexpr/src/simplexpr_parser.lalrpop index f351087..9620aac 100644 --- a/crates/simplexpr/src/simplexpr_parser.lalrpop +++ b/crates/simplexpr/src/simplexpr_parser.lalrpop @@ -1,4 +1,5 @@ -use crate::ast::{SimplExpr::{self, *}, Span, BinOp::*, UnaryOp::*}; +use crate::ast::{SimplExpr::{self, *}, BinOp::*, UnaryOp::*}; +use eww_shared_util::{Span, VarName}; use crate::parser::lexer::{Token, LexicalError}; use crate::parser::lalrpop_helpers::*; use lalrpop_util::ParseError; @@ -66,7 +67,7 @@ pub Expr: SimplExpr = { }, , - => VarRef(Span(l, r, fid), ident.to_string()), + => VarRef(Span(l, r, fid), VarName(ident.to_string())), "(" ")", #[precedence(level="1")] #[assoc(side="right")] diff --git a/crates/yuck/Cargo.toml b/crates/yuck/Cargo.toml index c0031dd..68f4557 100644 --- a/crates/yuck/Cargo.toml +++ b/crates/yuck/Cargo.toml @@ -27,6 +27,7 @@ static_assertions = "1.1" simplexpr = { path = "../simplexpr" } +eww_shared_util = { path = "../eww_shared_util" } [build-dependencies] lalrpop = "0.19.5" diff --git a/crates/yuck/src/config/attributes.rs b/crates/yuck/src/config/attributes.rs index e749c71..0efd2a5 100644 --- a/crates/yuck/src/config/attributes.rs +++ b/crates/yuck/src/config/attributes.rs @@ -11,12 +11,9 @@ use simplexpr::{ use crate::{ error::AstError, - parser::{ - ast::{Ast, Span}, - from_ast::FromAst, - }, - value::AttrName, + parser::{ast::Ast, from_ast::FromAst}, }; +use eww_shared_util::{AttrName, Span, VarName}; #[derive(Debug, thiserror::Error)] pub enum AttrError { diff --git a/crates/yuck/src/config/backend_window_options.rs b/crates/yuck/src/config/backend_window_options.rs index 1e61f16..4267388 100644 --- a/crates/yuck/src/config/backend_window_options.rs +++ b/crates/yuck/src/config/backend_window_options.rs @@ -5,13 +5,10 @@ use anyhow::*; use crate::{ enum_parse, error::AstResult, - parser::{ - ast::{Ast, Span}, - ast_iterator::AstIterator, - from_ast::FromAstElementContent, - }, + parser::{ast::Ast, ast_iterator::AstIterator, from_ast::FromAstElementContent}, value::NumWithUnit, }; +use eww_shared_util::Span; use super::{attributes::Attributes, window_definition::EnumParseError}; diff --git a/crates/yuck/src/config/config.rs b/crates/yuck/src/config/config.rs index 710e717..e893876 100644 --- a/crates/yuck/src/config/config.rs +++ b/crates/yuck/src/config/config.rs @@ -10,12 +10,12 @@ use crate::{ config::script_var_definition::{PollScriptVar, TailScriptVar}, error::{AstError, AstResult, OptionAstErrorExt}, parser::{ - ast::{Ast, Span}, + ast::Ast, ast_iterator::AstIterator, from_ast::{FromAst, FromAstElementContent}, }, - value::{AttrName, VarName}, }; +use eww_shared_util::{AttrName, Span, VarName}; pub enum TopLevel { VarDefinition(VarDefinition), diff --git a/crates/yuck/src/config/script_var_definition.rs b/crates/yuck/src/config/script_var_definition.rs index 5659563..8091110 100644 --- a/crates/yuck/src/config/script_var_definition.rs +++ b/crates/yuck/src/config/script_var_definition.rs @@ -5,12 +5,12 @@ use simplexpr::{dynval::DynVal, SimplExpr}; use crate::{ error::{AstError, AstResult}, parser::{ - ast::{Ast, Span}, + ast::Ast, ast_iterator::AstIterator, from_ast::{FromAst, FromAstElementContent}, }, - value::{AttrName, VarName}, }; +use eww_shared_util::{AttrName, Span, VarName}; #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)] pub enum ScriptVarDefinition { diff --git a/crates/yuck/src/config/test.rs b/crates/yuck/src/config/test.rs index bd34c77..677f4b3 100644 --- a/crates/yuck/src/config/test.rs +++ b/crates/yuck/src/config/test.rs @@ -1,16 +1,11 @@ use crate::{ config::config::Config, - parser::{ - self, - ast::{Ast, Span}, - from_ast::FromAst, - lexer::Lexer, - }, + parser::{self, ast::Ast, from_ast::FromAst, lexer::Lexer}, }; #[test] fn test_config() { - let input = r#" + let input = r#" (defwidget foo [arg] "heyho") (defwidget bar [arg arg2] diff --git a/crates/yuck/src/config/validate.rs b/crates/yuck/src/config/validate.rs index 153656a..093e2c5 100644 --- a/crates/yuck/src/config/validate.rs +++ b/crates/yuck/src/config/validate.rs @@ -4,15 +4,11 @@ use simplexpr::SimplExpr; use crate::{ error::AstResult, - parser::{ - ast::{Ast, Span}, - ast_iterator::AstIterator, - from_ast::FromAst, - }, - value::{AttrName, VarName}, + parser::{ast::Ast, ast_iterator::AstIterator, from_ast::FromAst}, }; use super::{widget_definition::WidgetDefinition, widget_use::WidgetUse}; +use eww_shared_util::{AttrName, Span, VarName}; #[derive(Debug, thiserror::Error)] pub enum ValidationError { diff --git a/crates/yuck/src/config/var_definition.rs b/crates/yuck/src/config/var_definition.rs index da458d5..065820d 100644 --- a/crates/yuck/src/config/var_definition.rs +++ b/crates/yuck/src/config/var_definition.rs @@ -5,12 +5,12 @@ use simplexpr::{dynval::DynVal, SimplExpr}; use crate::{ error::AstResult, parser::{ - ast::{Ast, Span}, + ast::Ast, ast_iterator::AstIterator, from_ast::{FromAst, FromAstElementContent}, }, - value::{AttrName, VarName}, }; +use eww_shared_util::{AttrName, Span, VarName}; #[derive(Debug, PartialEq, Eq, Clone, serde::Serialize)] pub struct VarDefinition { diff --git a/crates/yuck/src/config/widget_definition.rs b/crates/yuck/src/config/widget_definition.rs index b7bf2d9..641f587 100644 --- a/crates/yuck/src/config/widget_definition.rs +++ b/crates/yuck/src/config/widget_definition.rs @@ -5,12 +5,12 @@ use simplexpr::SimplExpr; use crate::{ error::AstResult, parser::{ - ast::{Ast, Span}, + ast::Ast, ast_iterator::AstIterator, from_ast::{FromAst, FromAstElementContent}, }, - value::{AttrName, VarName}, }; +use eww_shared_util::{AttrName, Span, VarName}; use super::widget_use::WidgetUse; #[derive(Debug, PartialEq, Eq, Clone, serde::Serialize)] diff --git a/crates/yuck/src/config/widget_use.rs b/crates/yuck/src/config/widget_use.rs index 78a6cfc..18efcc0 100644 --- a/crates/yuck/src/config/widget_use.rs +++ b/crates/yuck/src/config/widget_use.rs @@ -5,13 +5,9 @@ use simplexpr::SimplExpr; use crate::{ config::attributes::AttrEntry, error::AstResult, - parser::{ - ast::{Ast, Span}, - ast_iterator::AstIterator, - from_ast::FromAst, - }, - value::AttrName, + parser::{ast::Ast, ast_iterator::AstIterator, from_ast::FromAst}, }; +use eww_shared_util::{AttrName, Span, VarName}; use super::attributes::Attributes; @@ -28,7 +24,7 @@ impl FromAst for WidgetUse { let span = e.span(); if let Ok(text) = e.as_literal_ref() { Ok(Self { - name: "text".to_string(), + name: "label".to_string(), attrs: Attributes::new( span.into(), maplit::hashmap! { diff --git a/crates/yuck/src/config/window_definition.rs b/crates/yuck/src/config/window_definition.rs index f49f940..8687455 100644 --- a/crates/yuck/src/config/window_definition.rs +++ b/crates/yuck/src/config/window_definition.rs @@ -5,12 +5,13 @@ use simplexpr::{dynval::DynVal, SimplExpr}; use crate::{ error::{AstError, AstResult}, parser::{ - ast::{Ast, Span}, + ast::Ast, ast_iterator::AstIterator, from_ast::{FromAst, FromAstElementContent}, }, - value::{AttrName, NumWithUnit, VarName}, + value::NumWithUnit, }; +use eww_shared_util::{AttrName, Span, VarName}; use super::{backend_window_options::BackendWindowOptions, widget_use::WidgetUse, window_geometry::WindowGeometry}; diff --git a/crates/yuck/src/config/window_geometry.rs b/crates/yuck/src/config/window_geometry.rs index 16aac88..4245ab0 100644 --- a/crates/yuck/src/config/window_geometry.rs +++ b/crates/yuck/src/config/window_geometry.rs @@ -2,13 +2,20 @@ use std::collections::HashMap; use simplexpr::{dynval::DynVal, SimplExpr}; -use crate::{enum_parse, error::{AstError, AstResult}, parser::{ - ast::{Ast, Span}, ast_iterator::AstIterator, +use crate::{ + enum_parse, + error::{AstError, AstResult}, + parser::{ + ast::Ast, + ast_iterator::AstIterator, from_ast::{FromAst, FromAstElementContent}, - }, value::{AttrName, Coords, VarName}}; + }, + value::Coords, +}; use super::{widget_use::WidgetUse, window_definition::EnumParseError}; -use serde::{Serialize, Deserialize}; +use eww_shared_util::{AttrName, Span, VarName}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Copy, Eq, PartialEq, smart_default::SmartDefault, Serialize, Deserialize, strum::Display)] pub enum AnchorAlignment { @@ -84,7 +91,6 @@ pub enum AnchorPointParseError { EnumParseError(#[from] EnumParseError), } - impl std::str::FromStr for AnchorPoint { type Err = AnchorPointParseError; @@ -92,9 +98,7 @@ impl std::str::FromStr for AnchorPoint { if s == "center" { Ok(AnchorPoint { x: AnchorAlignment::CENTER, y: AnchorAlignment::CENTER }) } else { - let (first, second) = s - .split_once(' ') - .ok_or_else(|| AnchorPointParseError::WrongFormat(s.to_string()))?; + let (first, second) = s.split_once(' ').ok_or_else(|| AnchorPointParseError::WrongFormat(s.to_string()))?; let x_y_result: Result<_, EnumParseError> = try { AnchorPoint { x: AnchorAlignment::from_x_alignment(first)?, y: AnchorAlignment::from_y_alignment(second)? } }; diff --git a/crates/yuck/src/error.rs b/crates/yuck/src/error.rs index 846a5d0..f973ebd 100644 --- a/crates/yuck/src/error.rs +++ b/crates/yuck/src/error.rs @@ -1,11 +1,12 @@ use crate::{ config::{attributes::AttrError, validate::ValidationError}, parser::{ - ast::{Ast, AstType, Span}, + ast::{Ast, AstType}, lexer, parse_error, }, }; use codespan_reporting::{diagnostic, files}; +use eww_shared_util::{AttrName, Span, VarName}; use simplexpr::dynval; use thiserror::Error; diff --git a/crates/yuck/src/format_diagnostic.rs b/crates/yuck/src/format_diagnostic.rs index a1238c3..c724f74 100644 --- a/crates/yuck/src/format_diagnostic.rs +++ b/crates/yuck/src/format_diagnostic.rs @@ -5,7 +5,8 @@ use diagnostic::*; use crate::error::AstError; -use super::parser::{ast::Span, parse_error}; +use super::parser::parse_error; +use eww_shared_util::{AttrName, Span, VarName}; macro_rules! gen_diagnostic { ( diff --git a/crates/yuck/src/parser/ast.rs b/crates/yuck/src/parser/ast.rs index 24a6abc..bcaa402 100644 --- a/crates/yuck/src/parser/ast.rs +++ b/crates/yuck/src/parser/ast.rs @@ -2,61 +2,15 @@ use itertools::Itertools; use simplexpr::{ast::SimplExpr, dynval::DynVal}; use std::collections::HashMap; +use eww_shared_util::Span; use std::fmt::Display; use super::{ast_iterator::AstIterator, from_ast::FromAst}; use crate::{ config::attributes::{AttrEntry, Attributes}, error::{AstError, AstResult, OptionAstErrorExt}, - value::AttrName, }; -#[derive(Eq, PartialEq, Clone, Copy, serde::Serialize)] -pub struct Span(pub usize, pub usize, pub usize); - -impl Span { - /// Get the span that includes this and the other span completely. - /// Will panic if the spans are from different file_ids. - pub fn to(mut self, other: Span) -> Self { - assert!(other.2 == self.2); - self.1 = other.1; - self - } - - pub fn ending_at(mut self, end: usize) -> Self { - self.1 = end; - self - } - - pub fn with_length(mut self, end: usize) -> Self { - self.1 = self.0; - self - } -} - -impl Into for Span { - fn into(self) -> simplexpr::Span { - simplexpr::Span(self.0, self.1, self.2) - } -} -impl From for Span { - fn from(x: simplexpr::Span) -> Span { - Span(x.0, x.1, x.2) - } -} - -impl std::fmt::Display for Span { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}..{}", self.0, self.1) - } -} - -impl std::fmt::Debug for Span { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}..{}", self.0, self.1) - } -} - #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum AstType { List, diff --git a/crates/yuck/src/parser/ast_iterator.rs b/crates/yuck/src/parser/ast_iterator.rs index 6f841d0..e8983c6 100644 --- a/crates/yuck/src/parser/ast_iterator.rs +++ b/crates/yuck/src/parser/ast_iterator.rs @@ -5,14 +5,14 @@ use std::collections::HashMap; use std::fmt::Display; use super::{ - ast::{Ast, AstType, Span}, + ast::{Ast, AstType}, from_ast::FromAst, }; use crate::{ config::attributes::{AttrEntry, Attributes}, error::{AstError, AstResult, OptionAstErrorExt}, - value::AttrName, }; +use eww_shared_util::{AttrName, Span, VarName}; pub struct AstIterator> { remaining_span: Span, @@ -54,7 +54,7 @@ impl> AstIterator { } pub fn expect_any(&mut self) -> AstResult { - self.iter.next().or_missing(self.remaining_span.with_length(0)).and_then(T::from_ast) + self.iter.next().or_missing(self.remaining_span.point_span()).and_then(T::from_ast) } pub fn expect_key_values(&mut self) -> AstResult { diff --git a/crates/yuck/src/parser/from_ast.rs b/crates/yuck/src/parser/from_ast.rs index bca20b4..06fe2df 100644 --- a/crates/yuck/src/parser/from_ast.rs +++ b/crates/yuck/src/parser/from_ast.rs @@ -1,8 +1,9 @@ use super::{ - ast::{Ast, AstType, Span}, + ast::{Ast, AstType}, ast_iterator::AstIterator, }; -use crate::{error::*, parser, util, value::AttrName}; +use crate::{error::*, parser, util}; +use eww_shared_util::{AttrName, Span, VarName}; use itertools::Itertools; use simplexpr::{ast::SimplExpr, dynval::DynVal}; use std::{ @@ -49,7 +50,7 @@ impl FromAst for T { impl FromAst for SimplExpr { fn from_ast(e: Ast) -> AstResult { match e { - Ast::Symbol(span, x) => Ok(SimplExpr::VarRef(span.into(), x)), + Ast::Symbol(span, x) => Ok(SimplExpr::VarRef(span.into(), VarName(x))), Ast::Literal(span, x) => Ok(SimplExpr::Literal(span.into(), x)), Ast::SimplExpr(span, x) => Ok(x), _ => Err(AstError::NotAValue(e.span(), e.expr_type())), diff --git a/crates/yuck/src/parser/lexer.rs b/crates/yuck/src/parser/lexer.rs index eb74f14..322abdf 100644 --- a/crates/yuck/src/parser/lexer.rs +++ b/crates/yuck/src/parser/lexer.rs @@ -1,6 +1,7 @@ use regex::{Regex, RegexSet}; -use super::{ast::Span, parse_error}; +use super::parse_error; +use eww_shared_util::{AttrName, Span, VarName}; #[derive(Debug, PartialEq, Eq, Clone)] pub enum Token { diff --git a/crates/yuck/src/parser/mod.rs b/crates/yuck/src/parser/mod.rs index c4654b2..497d428 100644 --- a/crates/yuck/src/parser/mod.rs +++ b/crates/yuck/src/parser/mod.rs @@ -25,6 +25,13 @@ pub fn parse_string(file_id: usize, s: &str) -> AstResult { parser.parse(file_id, lexer).map_err(|e| AstError::from_parse_error(file_id, e)) } +/// Parse multiple toplevel nodes into an [Ast::List] +pub fn parse_toplevel(file_id: usize, s: &str) -> AstResult { + let lexer = lexer::Lexer::new(file_id, s.to_string()); + let parser = parser::ToplevelParser::new(); + parser.parse(file_id, lexer).map(|(span, nodes)| Ast::List(span, nodes)).map_err(|e| AstError::from_parse_error(file_id, e)) +} + macro_rules! test_parser { ($($text:literal),*) => {{ let p = parser::AstParser::new(); diff --git a/crates/yuck/src/parser/parse_error.rs b/crates/yuck/src/parser/parse_error.rs index 9c2fe44..b5f0816 100644 --- a/crates/yuck/src/parser/parse_error.rs +++ b/crates/yuck/src/parser/parse_error.rs @@ -1,4 +1,4 @@ -use super::ast::Span; +use eww_shared_util::{AttrName, Span, VarName}; #[derive(Debug, thiserror::Error)] pub enum ParseError { diff --git a/crates/yuck/src/parser/parser.lalrpop b/crates/yuck/src/parser/parser.lalrpop index 110c749..a7d05d4 100644 --- a/crates/yuck/src/parser/parser.lalrpop +++ b/crates/yuck/src/parser/parser.lalrpop @@ -1,5 +1,6 @@ use std::str::FromStr; -use crate::parser::{lexer::{Token}, ast::{Ast, Span}, parse_error}; +use crate::parser::{lexer::Token, ast::Ast, parse_error}; +use eww_shared_util::Span; use simplexpr::ast::SimplExpr; use simplexpr; use lalrpop_util::ParseError; @@ -59,7 +60,7 @@ SimplExpr: SimplExpr = { =>? { let expr = x[1..x.len() - 1].to_string(); simplexpr::parse_string(file_id, &expr).map_err(|e| { - let span = e.get_span().map(|simplexpr::Span(simpl_l, simpl_r, file_id)| Span(1 + l + simpl_l, 1 + l + simpl_r, file_id)); + let span = e.get_span().map(|Span(simpl_l, simpl_r, file_id)| Span(1 + l + simpl_l, 1 + l + simpl_r, file_id)); ParseError::User { error: parse_error::ParseError::SimplExpr(span, e) }}) } } diff --git a/crates/yuck/src/value/mod.rs b/crates/yuck/src/value/mod.rs index b3e80a0..cc26f2d 100644 --- a/crates/yuck/src/value/mod.rs +++ b/crates/yuck/src/value/mod.rs @@ -3,39 +3,3 @@ use serde::{Deserialize, Serialize}; pub mod coords; pub use coords::*; - -/// The name of a variable -#[repr(transparent)] -#[derive(Clone, Hash, PartialEq, Eq, Serialize, Deserialize, AsRef, From, FromStr, Display, DebugCustom)] -#[debug(fmt = "VarName({})", .0)] -pub struct VarName(pub String); - -impl std::borrow::Borrow for VarName { - fn borrow(&self) -> &str { - &self.0 - } -} - -impl From<&str> for VarName { - fn from(s: &str) -> Self { - VarName(s.to_owned()) - } -} - -/// The name of an attribute -#[repr(transparent)] -#[derive(Clone, Hash, PartialEq, Eq, Serialize, Deserialize, AsRef, From, FromStr, Display, DebugCustom)] -#[debug(fmt="AttrName({})", .0)] -pub struct AttrName(pub String); - -impl std::borrow::Borrow for AttrName { - fn borrow(&self) -> &str { - &self.0 - } -} - -impl From<&str> for AttrName { - fn from(s: &str) -> Self { - AttrName(s.to_owned()) - } -}