It compiles :o

This commit is contained in:
elkowar 2021-07-22 17:44:15 +02:00
parent c752cc928e
commit 4bf3c6fd63
No known key found for this signature in database
GPG key ID: E321AD71B1D1F27F
47 changed files with 279 additions and 265 deletions

11
Cargo.lock generated
View file

@ -436,6 +436,7 @@ dependencies = [
"debug_stub_derive", "debug_stub_derive",
"derive_more", "derive_more",
"dyn-clone", "dyn-clone",
"eww_shared_util",
"extend", "extend",
"futures-core", "futures-core",
"futures-util", "futures-util",
@ -475,6 +476,14 @@ dependencies = [
"yuck", "yuck",
] ]
[[package]]
name = "eww_shared_util"
version = "0.1.0"
dependencies = [
"derive_more",
"serde",
]
[[package]] [[package]]
name = "extend" name = "extend"
version = "1.1.1" version = "1.1.1"
@ -1874,6 +1883,7 @@ dependencies = [
name = "simplexpr" name = "simplexpr"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"eww_shared_util",
"insta", "insta",
"itertools 0.10.1", "itertools 0.10.1",
"lalrpop", "lalrpop",
@ -2374,6 +2384,7 @@ dependencies = [
"anyhow", "anyhow",
"codespan-reporting", "codespan-reporting",
"derive_more", "derive_more",
"eww_shared_util",
"insta", "insta",
"itertools 0.10.1", "itertools 0.10.1",
"lalrpop", "lalrpop",

View file

@ -2,5 +2,6 @@
members = [ members = [
"crates/eww", "crates/eww",
"crates/simplexpr", "crates/simplexpr",
"crates/yuck" "crates/yuck",
"crates/eww_shared_util"
] ]

View file

@ -69,6 +69,8 @@ notify = "5.0.0-pre.7"
simplexpr = { path = "../simplexpr" } simplexpr = { path = "../simplexpr" }
yuck = { path = "../yuck" } yuck = { path = "../yuck" }
eww_shared_util = { path = "../eww_shared_util" }
[dev-dependencies] [dev-dependencies]
pretty_assertions = "0.7.1" pretty_assertions = "0.7.1"

View file

@ -6,6 +6,7 @@ use crate::{
}; };
use anyhow::*; use anyhow::*;
use debug_stub_derive::*; use debug_stub_derive::*;
use eww_shared_util::VarName;
use gdk::WindowExt; use gdk::WindowExt;
use gtk::{ContainerExt, CssProviderExt, GtkWindowExt, StyleContextExt, WidgetExt}; use gtk::{ContainerExt, CssProviderExt, GtkWindowExt, StyleContextExt, WidgetExt};
use itertools::Itertools; use itertools::Itertools;
@ -14,7 +15,7 @@ use std::collections::HashMap;
use tokio::sync::mpsc::UnboundedSender; use tokio::sync::mpsc::UnboundedSender;
use yuck::{ use yuck::{
config::window_geometry::{AnchorPoint, WindowGeometry}, config::window_geometry::{AnchorPoint, WindowGeometry},
value::{Coords, VarName}, value::Coords,
}; };
/// Response that the app may send as a response to a event. /// Response that the app may send as a response to a event.
@ -112,30 +113,26 @@ impl App {
} }
} }
DaemonCommand::ReloadConfigAndCss(sender) => { DaemonCommand::ReloadConfigAndCss(sender) => {
let mut errors = Vec::new();
// TODO implement this let config_result = EwwConfig::read_from_file(&self.paths.get_yuck_path());
//let mut errors = Vec::new(); match config_result {
todo!() Ok(new_config) => self.handle_command(DaemonCommand::UpdateConfig(new_config)),
Err(e) => errors.push(e),
}
//let config_result = let css_result = crate::util::parse_scss_from_file(&self.paths.get_eww_scss_path());
//EwwConfig::read_from_file(&self.paths.get_eww_xml_path()).and_then(config::EwwConfig::generate); match css_result {
//match config_result { Ok(new_css) => self.handle_command(DaemonCommand::UpdateCss(new_css)),
//Ok(new_config) => self.handle_command(DaemonCommand::UpdateConfig(new_config)), Err(e) => errors.push(e),
//Err(e) => errors.push(e), }
//}
//let css_result = crate::util::parse_scss_from_file(&self.paths.get_eww_scss_path()); let errors = errors.into_iter().map(|e| format!("{:?}", e)).join("\n");
//match css_result { if errors.is_empty() {
//Ok(new_css) => self.handle_command(DaemonCommand::UpdateCss(new_css)), sender.send(DaemonResponse::Success(String::new()))?;
//Err(e) => errors.push(e), } 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) => { DaemonCommand::UpdateConfig(config) => {
self.load_config(config)?; self.load_config(config)?;

View file

@ -1,15 +1,13 @@
use anyhow::*; use anyhow::*;
use eww_shared_util::VarName;
use std::collections::HashMap; use std::collections::HashMap;
use yuck::{ use yuck::{
config::{script_var_definition::ScriptVarDefinition, widget_definition::WidgetDefinition}, config::{script_var_definition::ScriptVarDefinition, widget_definition::WidgetDefinition},
parser::from_ast::FromAst, parser::from_ast::FromAst,
value::VarName,
}; };
use simplexpr::dynval::DynVal; use simplexpr::dynval::DynVal;
use std::path::PathBuf;
use super::{script_var, EwwWindowDefinition}; use super::{script_var, EwwWindowDefinition};
/// Eww configuration structure. /// Eww configuration structure.
@ -19,33 +17,30 @@ pub struct EwwConfig {
windows: HashMap<String, EwwWindowDefinition>, windows: HashMap<String, EwwWindowDefinition>,
initial_variables: HashMap<VarName, DynVal>, initial_variables: HashMap<VarName, DynVal>,
script_vars: HashMap<VarName, ScriptVarDefinition>, script_vars: HashMap<VarName, ScriptVarDefinition>,
pub filepath: PathBuf,
} }
impl EwwConfig { impl EwwConfig {
pub fn read_from_file<P: AsRef<std::path::Path>>(path: P) -> Result<Self> { pub fn read_from_file<P: AsRef<std::path::Path>>(path: P) -> Result<Self> {
let content = std::fs::read_to_string(path)?; 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)?; let config = yuck::config::Config::from_ast(ast)?;
Self::generate(config) Self::generate(config)
} }
pub fn generate(config: yuck::config::Config) -> Result<Self> { pub fn generate(config: yuck::config::Config) -> Result<Self> {
let yuck::config::Config { widget_definitions, window_definitions, var_definitions, script_vars } = config;
Ok(EwwConfig { Ok(EwwConfig {
windows: config windows: window_definitions
.window_definitions
.into_iter() .into_iter()
.map(|(name, window)| { .map(|(name, window)| {
Ok(( Ok((
name, name,
EwwWindowDefinition::generate(&config.widget_definitions, window) EwwWindowDefinition::generate(&widget_definitions, window).context("Failed expand window definition")?,
.context("Failed expand window definition")?,
)) ))
}) })
.collect::<Result<HashMap<_, _>>>()?, .collect::<Result<HashMap<_, _>>>()?,
widgets: config.widget_definitions, widgets: widget_definitions,
initial_variables: config.var_definitions.into_iter().map(|(k, v)| (k, v.initial_value)).collect(), initial_variables: var_definitions.into_iter().map(|(k, v)| (k, v.initial_value)).collect(),
script_vars: config.script_vars, script_vars,
filepath: todo!(),
}) })
} }

View file

@ -1,12 +1,10 @@
use std::{collections::HashMap, time::Duration}; use std::{collections::HashMap, time::Duration};
use simplexpr::dynval::DynVal; use simplexpr::dynval::DynVal;
use yuck::{ use yuck::config::script_var_definition::{PollScriptVar, ScriptVarDefinition, VarSource};
config::script_var_definition::{PollScriptVar, ScriptVarDefinition, VarSource},
value::VarName,
};
use crate::config::system_stats::*; use crate::config::system_stats::*;
use eww_shared_util::VarName;
macro_rules! builtin_vars { macro_rules! builtin_vars {
($interval:expr, $($name:literal => $fun:expr),*$(,)?) => {{ ($interval:expr, $($name:literal => $fun:expr),*$(,)?) => {{

View file

@ -1,6 +1,6 @@
use anyhow::*; use anyhow::*;
use eww_shared_util::{AttrName, VarName};
use std::{collections::HashMap, sync::Arc}; use std::{collections::HashMap, sync::Arc};
use yuck::value::{AttrName, VarName};
use simplexpr::{dynval::DynVal, SimplExpr}; use simplexpr::{dynval::DynVal, SimplExpr};
@ -12,9 +12,8 @@ pub struct StateChangeHandler {
} }
impl StateChangeHandler { impl StateChangeHandler {
fn used_variables(&self) -> impl Iterator<Item = VarName> + '_ { fn used_variables(&self) -> impl Iterator<Item = &VarName> {
// TODO fix this clone self.unresolved_values.iter().flat_map(|(_, value)| value.var_refs())
self.unresolved_values.iter().flat_map(|(_, value)| value.var_refs()).map(|x| VarName(x.to_string()))
} }
/// Run the StateChangeHandler. /// Run the StateChangeHandler.
@ -24,7 +23,7 @@ impl StateChangeHandler {
.unresolved_values .unresolved_values
.clone() .clone()
.into_iter() .into_iter()
.map(|(attr_name, value)| Ok((attr_name, value.resolve_fully(state)?))) .map(|(attr_name, value)| Ok((attr_name, value.eval(state)?)))
.collect::<Result<_>>(); .collect::<Result<_>>();
match resolved_attrs { match resolved_attrs {
@ -107,8 +106,7 @@ impl EwwState {
/// resolves a value if possible, using the current eww_state. /// resolves a value if possible, using the current eww_state.
pub fn resolve_once<'a>(&'a self, value: &'a SimplExpr) -> Result<DynVal> { pub fn resolve_once<'a>(&'a self, value: &'a SimplExpr) -> Result<DynVal> {
// TODO fix this clone Ok(value.clone().eval(&self.variables_state)?)
Ok(value.clone().eval(&self.variables_state.into_iter().map(|(k, v)| (k.0, v)).collect())?)
} }
/// Resolve takes a function that applies a set of fully resolved attribute /// Resolve takes a function that applies a set of fully resolved attribute

View file

@ -162,8 +162,8 @@ impl EwwPaths {
self.config_dir.as_path() self.config_dir.as_path()
} }
pub fn get_eww_xml_path(&self) -> PathBuf { pub fn get_yuck_path(&self) -> PathBuf {
self.config_dir.join("eww.xml") self.config_dir.join("eww.yuck")
} }
pub fn get_eww_scss_path(&self) -> PathBuf { pub fn get_eww_scss_path(&self) -> PathBuf {

View file

@ -1,11 +1,9 @@
use anyhow::*; use anyhow::*;
use eww_shared_util::VarName;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use simplexpr::dynval::DynVal; use simplexpr::dynval::DynVal;
use structopt::StructOpt; use structopt::StructOpt;
use yuck::{ use yuck::{config::window_geometry::AnchorPoint, value::Coords};
config::window_geometry::AnchorPoint,
value::{Coords, VarName},
};
use crate::app; use crate::app;
@ -23,7 +21,7 @@ struct RawOpt {
#[structopt(long = "debug", global = true)] #[structopt(long = "debug", global = true)]
log_debug: bool, 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)] #[structopt(short, long, global = true)]
config: Option<std::path::PathBuf>, config: Option<std::path::PathBuf>,
@ -153,7 +151,7 @@ fn parse_var_update_arg(s: &str) -> Result<(VarName, DynVal)> {
impl ActionWithServer { impl ActionWithServer {
pub fn into_daemon_command(self) -> (app::DaemonCommand, Option<app::DaemonResponseReceiver>) { pub fn into_daemon_command(self) -> (app::DaemonCommand, Option<app::DaemonResponseReceiver>) {
let command = match self { 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::KillServer => app::DaemonCommand::KillServer,
ActionWithServer::CloseAll => app::DaemonCommand::CloseAll, ActionWithServer::CloseAll => app::DaemonCommand::CloseAll,

View file

@ -4,13 +4,14 @@ use crate::app;
use anyhow::*; use anyhow::*;
use app::DaemonCommand; use app::DaemonCommand;
use eww_shared_util::VarName;
use simplexpr::dynval::DynVal; use simplexpr::dynval::DynVal;
use tokio::{ use tokio::{
io::{AsyncBufReadExt, BufReader}, io::{AsyncBufReadExt, BufReader},
sync::mpsc::UnboundedSender, sync::mpsc::UnboundedSender,
}; };
use tokio_util::sync::CancellationToken; 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 /// Initialize the script var handler, and return a handle to that handler, which can be used to control
/// the script var execution. /// the script var execution.

View file

@ -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()))?; .with_context(|| format!("Failed to change working directory to {}", paths.get_config_dir().display()))?;
log::info!("Loading paths: {}", &paths); 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()?; gtk::init()?;

View file

@ -1,9 +1,10 @@
use crate::eww_state::*; use crate::eww_state::*;
use anyhow::*; use anyhow::*;
use eww_shared_util::AttrName;
use gtk::prelude::*; use gtk::prelude::*;
use itertools::Itertools; use itertools::Itertools;
use std::collections::HashMap; use std::collections::HashMap;
use yuck::{config::widget_definition::WidgetDefinition, value::AttrName}; use yuck::config::widget_definition::WidgetDefinition;
use std::process::Command; use std::process::Command;
use widget_definitions::*; use widget_definitions::*;
@ -129,7 +130,7 @@ macro_rules! resolve_block {
let attr_map: Result<_> = try { let attr_map: Result<_> = try {
::maplit::hashmap! { ::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)?) resolve_block!(@get_value $args, &::std::stringify!($attr_name).replace('_', "-"), $(= $default)?)
),* ),*
} }

View file

@ -1,7 +1,7 @@
#![allow(clippy::option_map_unit_fn)] #![allow(clippy::option_map_unit_fn)]
use super::{run_command, BuilderArgs}; use super::{run_command, BuilderArgs};
use crate::{ use crate::{
config, enum_parse, eww_state, resolve_block, enum_parse, eww_state, resolve_block,
util::{list_difference, parse_duration}, util::{list_difference, parse_duration},
widgets::widget_node, widgets::widget_node,
}; };
@ -10,6 +10,7 @@ use gdk::WindowExt;
use glib; use glib;
use gtk::{self, prelude::*, ImageExt}; use gtk::{self, prelude::*, ImageExt};
use std::{cell::RefCell, collections::HashMap, rc::Rc}; use std::{cell::RefCell, collections::HashMap, rc::Rc};
use yuck::parser::from_ast::FromAst;
// TODO figure out how to // TODO figure out how to
// TODO https://developer.gnome.org/gtk3/stable/GtkFixed.html // TODO https://developer.gnome.org/gtk3/stable/GtkFixed.html
@ -244,12 +245,13 @@ fn build_gtk_combo_box_text(bargs: &mut BuilderArgs) -> Result<gtk::ComboBoxText
let on_change_handler_id: Rc<RefCell<Option<glib::SignalHandlerId>>> = Rc::new(RefCell::new(None)); let on_change_handler_id: Rc<RefCell<Option<glib::SignalHandlerId>>> = Rc::new(RefCell::new(None));
resolve_block!(bargs, gtk_widget, { resolve_block!(bargs, gtk_widget, {
// @prop items - Items that should be displayed in the combo box // @prop items - Items that should be displayed in the combo box
prop(items: as_vec) { // TODO reimplement, obviously
gtk_widget.remove_all(); //prop(items: as_vec) {
for i in items { //gtk_widget.remove_all();
gtk_widget.append_text(&i); //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 - runs the code when a item was selected, replacing {} with the item as a string
prop(onchange: as_string) { prop(onchange: as_string) {
let old_id = on_change_handler_id.replace(Some( let old_id = on_change_handler_id.replace(Some(
@ -518,15 +520,16 @@ fn build_gtk_literal(bargs: &mut BuilderArgs) -> Result<gtk::Box> {
gtk_widget.set_widget_name("literal"); gtk_widget.set_widget_name("literal");
// TODO these clones here are dumdum // 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(); let widget_definitions = bargs.widget_definitions.clone();
resolve_block!(bargs, gtk_widget, { resolve_block!(bargs, gtk_widget, {
// @prop content - inline Eww XML that will be rendered as a widget. // @prop content - inline Eww XML that will be rendered as a widget.
prop(content: as_string) { prop(content: as_string) {
gtk_widget.get_children().iter().for_each(|w| gtk_widget.remove(w)); gtk_widget.get_children().iter().for_each(|w| gtk_widget.remove(w));
if !content.is_empty() { if !content.is_empty() {
let document = roxmltree::Document::parse(&content).map_err(|e| anyhow!("Failed to parse eww xml literal: {:?}", e))?; let ast = yuck::parser::parse_string(usize::MAX, &content)?;
let content_widget_use = config::element::WidgetUse::from_xml_node(document.root_element().into())?; 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 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)?; let child_widget = widget_node.render(&mut eww_state::EwwState::default(), &window_name, &widget_definitions)?;

View file

@ -1,13 +1,10 @@
use crate::eww_state::EwwState; use crate::eww_state::EwwState;
use anyhow::*; use anyhow::*;
use dyn_clone; use dyn_clone;
use eww_shared_util::{AttrName, Span, VarName};
use simplexpr::SimplExpr; use simplexpr::SimplExpr;
use std::collections::HashMap; use std::collections::HashMap;
use yuck::{ use yuck::config::{widget_definition::WidgetDefinition, widget_use::WidgetUse};
config::{widget_definition::WidgetDefinition, widget_use::WidgetUse},
parser::ast::Span,
value::{AttrName, VarName},
};
pub trait WidgetNode: std::fmt::Debug + dyn_clone::DynClone + Send + Sync { pub trait WidgetNode: std::fmt::Debug + dyn_clone::DynClone + Send + Sync {
fn get_name(&self) -> &str; fn get_name(&self) -> &str;
@ -70,9 +67,8 @@ impl Generic {
} }
/// returns all the variables that are referenced in this widget /// returns all the variables that are referenced in this widget
pub fn referenced_vars(&self) -> impl Iterator<Item = VarName> + '_ { pub fn referenced_vars(&self) -> impl Iterator<Item = &VarName> {
// TODO fix this clone self.attrs.iter().flat_map(|(_, value)| value.var_refs())
self.attrs.iter().flat_map(|(_, value)| value.var_refs()).map(|x| VarName(x.to_string()))
} }
} }
@ -108,12 +104,7 @@ pub fn generate_generic_widget_node(
.attrs .attrs
.attrs .attrs
.into_iter() .into_iter()
.map(|(name, value)| { .map(|(name, value)| Ok((VarName(name.0), value.value.as_simplexpr()?.resolve_one_level(local_env))))
Ok((
VarName(name.0),
SimplExpr::Literal(value.value.span().into(), value.value.as_simplexpr()?.resolve_one_level(local_env)?),
))
})
.collect::<Result<HashMap<VarName, _>>>()?; .collect::<Result<HashMap<VarName, _>>>()?;
let content = generate_generic_widget_node(defs, &new_local_env, def.widget.clone())?; 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
.attrs .attrs
.into_iter() .into_iter()
.map(|(name, value)| { .map(|(name, value)| Ok((name, value.value.as_simplexpr()?.resolve_one_level(local_env))))
Ok(( .collect::<Result<HashMap<_, _>>>()?,
VarName(name.0),
SimplExpr::Literal(value.value.span().into(), value.value.as_simplexpr()?.resolve_one_level(local_env)?),
))
})
.collect()?,
children: w children: w
.children .children

View file

@ -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"

View file

@ -0,0 +1,5 @@
pub mod span;
pub mod wrappers;
pub use span::*;
pub use wrappers::*;

View file

@ -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)
}
}

View file

@ -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<str> 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<str> for AttrName {
fn borrow(&self) -> &str {
&self.0
}
}
impl From<&str> for AttrName {
fn from(s: &str) -> Self {
AttrName(s.to_owned())
}
}

View file

@ -20,6 +20,7 @@ serde_json = "1.0"
strum = { version = "0.21", features = ["derive"] } strum = { version = "0.21", features = ["derive"] }
eww_shared_util = { path = "../eww_shared_util" }
[build-dependencies] [build-dependencies]

View file

@ -1,23 +1,9 @@
use crate::dynval::DynVal; use crate::dynval::DynVal;
use eww_shared_util::{Span, DUMMY_SPAN};
use itertools::Itertools; use itertools::Itertools;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// stores the left and right end of a span, and a given file identifier. use eww_shared_util::VarName;
#[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)
}
}
#[rustfmt::skip] #[rustfmt::skip]
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug, strum::EnumString, strum::Display)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug, strum::EnumString, strum::Display)]
@ -46,7 +32,7 @@ pub enum UnaryOp {
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum SimplExpr { pub enum SimplExpr {
Literal(Span, DynVal), Literal(Span, DynVal),
VarRef(Span, String), VarRef(Span, VarName),
BinOp(Span, Box<SimplExpr>, BinOp, Box<SimplExpr>), BinOp(Span, Box<SimplExpr>, BinOp, Box<SimplExpr>),
UnaryOp(Span, UnaryOp, Box<SimplExpr>), UnaryOp(Span, UnaryOp, Box<SimplExpr>),
IfElse(Span, Box<SimplExpr>, Box<SimplExpr>, Box<SimplExpr>), IfElse(Span, Box<SimplExpr>, Box<SimplExpr>, Box<SimplExpr>),

View file

@ -1,4 +1,4 @@
use crate::ast::Span; use eww_shared_util::Span;
use itertools::Itertools; use itertools::Itertools;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{fmt, iter::FromIterator, str::FromStr}; use std::{fmt, iter::FromIterator, str::FromStr};

View file

@ -1,8 +1,8 @@
use crate::{ use crate::{
ast::Span,
dynval, dynval,
parser::lexer::{self, LexicalError}, parser::lexer::{self, LexicalError},
}; };
use eww_shared_util::Span;
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]

View file

@ -1,9 +1,10 @@
use itertools::Itertools; use itertools::Itertools;
use crate::{ use crate::{
ast::{BinOp, SimplExpr, Span, UnaryOp}, ast::{BinOp, SimplExpr, UnaryOp},
dynval::{ConversionError, DynVal}, dynval::{ConversionError, DynVal},
}; };
use eww_shared_util::{Span, VarName};
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Debug, thiserror::Error)] #[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<DynVal, Self::Err>;
}
impl SimplExpr { impl SimplExpr {
pub fn map_terminals_into(self, f: impl Fn(Self) -> Self) -> Self { pub fn map_terminals_into(self, f: impl Fn(Self) -> Self) -> Self {
use SimplExpr::*; 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<E, F: Fn(Span, VarName) -> Result<SimplExpr, E> + Copy>(self, f: F) -> Result<Self, E> {
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::<Result<_, _>>()?)
}
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<VarName, SimplExpr>) -> 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. /// resolve variable references in the expression. Fails if a variable cannot be resolved.
pub fn resolve_refs(self, variables: &HashMap<VarName, DynVal>) -> Result<Self, EvalError> { pub fn resolve_refs(self, variables: &HashMap<VarName, DynVal>) -> Result<Self, EvalError> {
use SimplExpr::*; use SimplExpr::*;
@ -96,7 +120,7 @@ impl SimplExpr {
} }
} }
pub fn var_refs(&self) -> Vec<&String> { pub fn var_refs(&self) -> Vec<&VarName> {
use SimplExpr::*; use SimplExpr::*;
match self { match self {
Literal(..) => Vec::new(), Literal(..) => Vec::new(),
@ -130,7 +154,7 @@ impl SimplExpr {
let value = match self { let value = match self {
SimplExpr::Literal(_, x) => Ok(x.clone()), SimplExpr::Literal(_, x) => Ok(x.clone()),
SimplExpr::VarRef(span, ref name) => { 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) => { SimplExpr::BinOp(_, a, op, b) => {
let a = a.eval(values)?; let a = a.eval(values)?;

View file

@ -1,13 +1,16 @@
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(try_blocks)] #![feature(try_blocks)]
#![feature(unwrap_infallible)]
#![feature(never_type)]
pub mod ast; pub mod ast;
pub mod dynval; pub mod dynval;
pub mod error; pub mod error;
pub mod eval; pub mod eval;
pub mod parser; pub mod parser;
pub use ast::{SimplExpr, Span}; pub use ast::SimplExpr;
use lalrpop_util::lalrpop_mod; use lalrpop_util::lalrpop_mod;

View file

@ -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::lexer::{Token, LexicalError};
use crate::parser::lalrpop_helpers::*; use crate::parser::lalrpop_helpers::*;
use lalrpop_util::ParseError; use lalrpop_util::ParseError;
@ -66,7 +67,7 @@ pub Expr: SimplExpr = {
}, },
<Literal>, <Literal>,
<l:@L> <ident:"identifier"> <r:@R> => VarRef(Span(l, r, fid), ident.to_string()), <l:@L> <ident:"identifier"> <r:@R> => VarRef(Span(l, r, fid), VarName(ident.to_string())),
"(" <ExprReset> ")", "(" <ExprReset> ")",
#[precedence(level="1")] #[assoc(side="right")] #[precedence(level="1")] #[assoc(side="right")]

View file

@ -27,6 +27,7 @@ static_assertions = "1.1"
simplexpr = { path = "../simplexpr" } simplexpr = { path = "../simplexpr" }
eww_shared_util = { path = "../eww_shared_util" }
[build-dependencies] [build-dependencies]
lalrpop = "0.19.5" lalrpop = "0.19.5"

View file

@ -11,12 +11,9 @@ use simplexpr::{
use crate::{ use crate::{
error::AstError, error::AstError,
parser::{ parser::{ast::Ast, from_ast::FromAst},
ast::{Ast, Span},
from_ast::FromAst,
},
value::AttrName,
}; };
use eww_shared_util::{AttrName, Span, VarName};
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum AttrError { pub enum AttrError {

View file

@ -5,13 +5,10 @@ use anyhow::*;
use crate::{ use crate::{
enum_parse, enum_parse,
error::AstResult, error::AstResult,
parser::{ parser::{ast::Ast, ast_iterator::AstIterator, from_ast::FromAstElementContent},
ast::{Ast, Span},
ast_iterator::AstIterator,
from_ast::FromAstElementContent,
},
value::NumWithUnit, value::NumWithUnit,
}; };
use eww_shared_util::Span;
use super::{attributes::Attributes, window_definition::EnumParseError}; use super::{attributes::Attributes, window_definition::EnumParseError};

View file

@ -10,12 +10,12 @@ use crate::{
config::script_var_definition::{PollScriptVar, TailScriptVar}, config::script_var_definition::{PollScriptVar, TailScriptVar},
error::{AstError, AstResult, OptionAstErrorExt}, error::{AstError, AstResult, OptionAstErrorExt},
parser::{ parser::{
ast::{Ast, Span}, ast::Ast,
ast_iterator::AstIterator, ast_iterator::AstIterator,
from_ast::{FromAst, FromAstElementContent}, from_ast::{FromAst, FromAstElementContent},
}, },
value::{AttrName, VarName},
}; };
use eww_shared_util::{AttrName, Span, VarName};
pub enum TopLevel { pub enum TopLevel {
VarDefinition(VarDefinition), VarDefinition(VarDefinition),

View file

@ -5,12 +5,12 @@ use simplexpr::{dynval::DynVal, SimplExpr};
use crate::{ use crate::{
error::{AstError, AstResult}, error::{AstError, AstResult},
parser::{ parser::{
ast::{Ast, Span}, ast::Ast,
ast_iterator::AstIterator, ast_iterator::AstIterator,
from_ast::{FromAst, FromAstElementContent}, from_ast::{FromAst, FromAstElementContent},
}, },
value::{AttrName, VarName},
}; };
use eww_shared_util::{AttrName, Span, VarName};
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)] #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)]
pub enum ScriptVarDefinition { pub enum ScriptVarDefinition {

View file

@ -1,16 +1,11 @@
use crate::{ use crate::{
config::config::Config, config::config::Config,
parser::{ parser::{self, ast::Ast, from_ast::FromAst, lexer::Lexer},
self,
ast::{Ast, Span},
from_ast::FromAst,
lexer::Lexer,
},
}; };
#[test] #[test]
fn test_config() { fn test_config() {
let input = r#" let input = r#"
(defwidget foo [arg] (defwidget foo [arg]
"heyho") "heyho")
(defwidget bar [arg arg2] (defwidget bar [arg arg2]

View file

@ -4,15 +4,11 @@ use simplexpr::SimplExpr;
use crate::{ use crate::{
error::AstResult, error::AstResult,
parser::{ parser::{ast::Ast, ast_iterator::AstIterator, from_ast::FromAst},
ast::{Ast, Span},
ast_iterator::AstIterator,
from_ast::FromAst,
},
value::{AttrName, VarName},
}; };
use super::{widget_definition::WidgetDefinition, widget_use::WidgetUse}; use super::{widget_definition::WidgetDefinition, widget_use::WidgetUse};
use eww_shared_util::{AttrName, Span, VarName};
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum ValidationError { pub enum ValidationError {

View file

@ -5,12 +5,12 @@ use simplexpr::{dynval::DynVal, SimplExpr};
use crate::{ use crate::{
error::AstResult, error::AstResult,
parser::{ parser::{
ast::{Ast, Span}, ast::Ast,
ast_iterator::AstIterator, ast_iterator::AstIterator,
from_ast::{FromAst, FromAstElementContent}, from_ast::{FromAst, FromAstElementContent},
}, },
value::{AttrName, VarName},
}; };
use eww_shared_util::{AttrName, Span, VarName};
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize)] #[derive(Debug, PartialEq, Eq, Clone, serde::Serialize)]
pub struct VarDefinition { pub struct VarDefinition {

View file

@ -5,12 +5,12 @@ use simplexpr::SimplExpr;
use crate::{ use crate::{
error::AstResult, error::AstResult,
parser::{ parser::{
ast::{Ast, Span}, ast::Ast,
ast_iterator::AstIterator, ast_iterator::AstIterator,
from_ast::{FromAst, FromAstElementContent}, from_ast::{FromAst, FromAstElementContent},
}, },
value::{AttrName, VarName},
}; };
use eww_shared_util::{AttrName, Span, VarName};
use super::widget_use::WidgetUse; use super::widget_use::WidgetUse;
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize)] #[derive(Debug, PartialEq, Eq, Clone, serde::Serialize)]

View file

@ -5,13 +5,9 @@ use simplexpr::SimplExpr;
use crate::{ use crate::{
config::attributes::AttrEntry, config::attributes::AttrEntry,
error::AstResult, error::AstResult,
parser::{ parser::{ast::Ast, ast_iterator::AstIterator, from_ast::FromAst},
ast::{Ast, Span},
ast_iterator::AstIterator,
from_ast::FromAst,
},
value::AttrName,
}; };
use eww_shared_util::{AttrName, Span, VarName};
use super::attributes::Attributes; use super::attributes::Attributes;
@ -28,7 +24,7 @@ impl FromAst for WidgetUse {
let span = e.span(); let span = e.span();
if let Ok(text) = e.as_literal_ref() { if let Ok(text) = e.as_literal_ref() {
Ok(Self { Ok(Self {
name: "text".to_string(), name: "label".to_string(),
attrs: Attributes::new( attrs: Attributes::new(
span.into(), span.into(),
maplit::hashmap! { maplit::hashmap! {

View file

@ -5,12 +5,13 @@ use simplexpr::{dynval::DynVal, SimplExpr};
use crate::{ use crate::{
error::{AstError, AstResult}, error::{AstError, AstResult},
parser::{ parser::{
ast::{Ast, Span}, ast::Ast,
ast_iterator::AstIterator, ast_iterator::AstIterator,
from_ast::{FromAst, FromAstElementContent}, 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}; use super::{backend_window_options::BackendWindowOptions, widget_use::WidgetUse, window_geometry::WindowGeometry};

View file

@ -2,13 +2,20 @@ use std::collections::HashMap;
use simplexpr::{dynval::DynVal, SimplExpr}; use simplexpr::{dynval::DynVal, SimplExpr};
use crate::{enum_parse, error::{AstError, AstResult}, parser::{ use crate::{
ast::{Ast, Span}, ast_iterator::AstIterator, enum_parse,
error::{AstError, AstResult},
parser::{
ast::Ast,
ast_iterator::AstIterator,
from_ast::{FromAst, FromAstElementContent}, from_ast::{FromAst, FromAstElementContent},
}, value::{AttrName, Coords, VarName}}; },
value::Coords,
};
use super::{widget_use::WidgetUse, window_definition::EnumParseError}; 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)] #[derive(Debug, Clone, Copy, Eq, PartialEq, smart_default::SmartDefault, Serialize, Deserialize, strum::Display)]
pub enum AnchorAlignment { pub enum AnchorAlignment {
@ -84,7 +91,6 @@ pub enum AnchorPointParseError {
EnumParseError(#[from] EnumParseError), EnumParseError(#[from] EnumParseError),
} }
impl std::str::FromStr for AnchorPoint { impl std::str::FromStr for AnchorPoint {
type Err = AnchorPointParseError; type Err = AnchorPointParseError;
@ -92,9 +98,7 @@ impl std::str::FromStr for AnchorPoint {
if s == "center" { if s == "center" {
Ok(AnchorPoint { x: AnchorAlignment::CENTER, y: AnchorAlignment::CENTER }) Ok(AnchorPoint { x: AnchorAlignment::CENTER, y: AnchorAlignment::CENTER })
} else { } else {
let (first, second) = s let (first, second) = s.split_once(' ').ok_or_else(|| AnchorPointParseError::WrongFormat(s.to_string()))?;
.split_once(' ')
.ok_or_else(|| AnchorPointParseError::WrongFormat(s.to_string()))?;
let x_y_result: Result<_, EnumParseError> = try { let x_y_result: Result<_, EnumParseError> = try {
AnchorPoint { x: AnchorAlignment::from_x_alignment(first)?, y: AnchorAlignment::from_y_alignment(second)? } AnchorPoint { x: AnchorAlignment::from_x_alignment(first)?, y: AnchorAlignment::from_y_alignment(second)? }
}; };

View file

@ -1,11 +1,12 @@
use crate::{ use crate::{
config::{attributes::AttrError, validate::ValidationError}, config::{attributes::AttrError, validate::ValidationError},
parser::{ parser::{
ast::{Ast, AstType, Span}, ast::{Ast, AstType},
lexer, parse_error, lexer, parse_error,
}, },
}; };
use codespan_reporting::{diagnostic, files}; use codespan_reporting::{diagnostic, files};
use eww_shared_util::{AttrName, Span, VarName};
use simplexpr::dynval; use simplexpr::dynval;
use thiserror::Error; use thiserror::Error;

View file

@ -5,7 +5,8 @@ use diagnostic::*;
use crate::error::AstError; 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 { macro_rules! gen_diagnostic {
( (

View file

@ -2,61 +2,15 @@ use itertools::Itertools;
use simplexpr::{ast::SimplExpr, dynval::DynVal}; use simplexpr::{ast::SimplExpr, dynval::DynVal};
use std::collections::HashMap; use std::collections::HashMap;
use eww_shared_util::Span;
use std::fmt::Display; use std::fmt::Display;
use super::{ast_iterator::AstIterator, from_ast::FromAst}; use super::{ast_iterator::AstIterator, from_ast::FromAst};
use crate::{ use crate::{
config::attributes::{AttrEntry, Attributes}, config::attributes::{AttrEntry, Attributes},
error::{AstError, AstResult, OptionAstErrorExt}, 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<simplexpr::Span> for Span {
fn into(self) -> simplexpr::Span {
simplexpr::Span(self.0, self.1, self.2)
}
}
impl From<simplexpr::Span> 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)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum AstType { pub enum AstType {
List, List,

View file

@ -5,14 +5,14 @@ use std::collections::HashMap;
use std::fmt::Display; use std::fmt::Display;
use super::{ use super::{
ast::{Ast, AstType, Span}, ast::{Ast, AstType},
from_ast::FromAst, from_ast::FromAst,
}; };
use crate::{ use crate::{
config::attributes::{AttrEntry, Attributes}, config::attributes::{AttrEntry, Attributes},
error::{AstError, AstResult, OptionAstErrorExt}, error::{AstError, AstResult, OptionAstErrorExt},
value::AttrName,
}; };
use eww_shared_util::{AttrName, Span, VarName};
pub struct AstIterator<I: Iterator<Item = Ast>> { pub struct AstIterator<I: Iterator<Item = Ast>> {
remaining_span: Span, remaining_span: Span,
@ -54,7 +54,7 @@ impl<I: Iterator<Item = Ast>> AstIterator<I> {
} }
pub fn expect_any<T: FromAst>(&mut self) -> AstResult<T> { pub fn expect_any<T: FromAst>(&mut self) -> AstResult<T> {
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<Attributes> { pub fn expect_key_values(&mut self) -> AstResult<Attributes> {

View file

@ -1,8 +1,9 @@
use super::{ use super::{
ast::{Ast, AstType, Span}, ast::{Ast, AstType},
ast_iterator::AstIterator, 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 itertools::Itertools;
use simplexpr::{ast::SimplExpr, dynval::DynVal}; use simplexpr::{ast::SimplExpr, dynval::DynVal};
use std::{ use std::{
@ -49,7 +50,7 @@ impl<T: FromAstElementContent> FromAst for T {
impl FromAst for SimplExpr { impl FromAst for SimplExpr {
fn from_ast(e: Ast) -> AstResult<Self> { fn from_ast(e: Ast) -> AstResult<Self> {
match e { 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::Literal(span, x) => Ok(SimplExpr::Literal(span.into(), x)),
Ast::SimplExpr(span, x) => Ok(x), Ast::SimplExpr(span, x) => Ok(x),
_ => Err(AstError::NotAValue(e.span(), e.expr_type())), _ => Err(AstError::NotAValue(e.span(), e.expr_type())),

View file

@ -1,6 +1,7 @@
use regex::{Regex, RegexSet}; 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)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum Token { pub enum Token {

View file

@ -25,6 +25,13 @@ pub fn parse_string(file_id: usize, s: &str) -> AstResult<Ast> {
parser.parse(file_id, lexer).map_err(|e| AstError::from_parse_error(file_id, e)) 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<Ast> {
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 { macro_rules! test_parser {
($($text:literal),*) => {{ ($($text:literal),*) => {{
let p = parser::AstParser::new(); let p = parser::AstParser::new();

View file

@ -1,4 +1,4 @@
use super::ast::Span; use eww_shared_util::{AttrName, Span, VarName};
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum ParseError { pub enum ParseError {

View file

@ -1,5 +1,6 @@
use std::str::FromStr; 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::ast::SimplExpr;
use simplexpr; use simplexpr;
use lalrpop_util::ParseError; use lalrpop_util::ParseError;
@ -59,7 +60,7 @@ SimplExpr: SimplExpr = {
<l:@L> <x:"simplexpr"> =>? { <l:@L> <x:"simplexpr"> =>? {
let expr = x[1..x.len() - 1].to_string(); let expr = x[1..x.len() - 1].to_string();
simplexpr::parse_string(file_id, &expr).map_err(|e| { 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) }}) ParseError::User { error: parse_error::ParseError::SimplExpr(span, e) }})
} }
} }

View file

@ -3,39 +3,3 @@ use serde::{Deserialize, Serialize};
pub mod coords; pub mod coords;
pub use 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<str> 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<str> for AttrName {
fn borrow(&self) -> &str {
&self.0
}
}
impl From<&str> for AttrName {
fn from(s: &str) -> Self {
AttrName(s.to_owned())
}
}