From dde69276d47818174c35523c8ed86b6888b6d02b Mon Sep 17 00:00:00 2001 From: Laurenz Date: Mon, 13 Jan 2020 14:36:40 +0100 Subject: =?UTF-8?q?Refactor=20expressions=20and=20create=20tuples=20and=20?= =?UTF-8?q?objects=20=F0=9F=A7=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/syntax/expr.rs | 245 ++++++++++++++++++++++------------------------------- 1 file changed, 101 insertions(+), 144 deletions(-) (limited to 'src/syntax/expr.rs') diff --git a/src/syntax/expr.rs b/src/syntax/expr.rs index ed5e50df..e2df3c4e 100644 --- a/src/syntax/expr.rs +++ b/src/syntax/expr.rs @@ -1,125 +1,16 @@ use super::*; -/// The arguments passed to a function. -#[derive(Debug, Clone, PartialEq)] -pub struct FuncArgs { - pub pos: Vec>, - pub key: Vec>, -} - -impl FuncArgs { - /// Create an empty collection of arguments. - pub fn new() -> FuncArgs { - FuncArgs { - pos: vec![], - key: vec![], - } - } - - /// Add a positional argument. - pub fn add_pos(&mut self, arg: Spanned) { - self.pos.push(arg); - } - - /// Add a keyword argument. - pub fn add_key(&mut self, arg: Spanned) { - self.key.push(arg); - } - - /// Force-extract the first positional argument. - pub fn get_pos(&mut self) -> ParseResult { - expect(self.get_pos_opt()) - } - - /// Extract the first positional argument. - pub fn get_pos_opt(&mut self) -> ParseResult> { - Ok(if !self.pos.is_empty() { - let spanned = self.pos.remove(0); - Some(E::from_expr(spanned)?) - } else { - None - }) - } - - /// Iterator over positional arguments. - pub fn pos(&mut self) -> std::vec::IntoIter> { - let vec = std::mem::replace(&mut self.pos, vec![]); - vec.into_iter() - } - - /// Force-extract a keyword argument. - pub fn get_key(&mut self, name: &str) -> ParseResult { - expect(self.get_key_opt(name)) - } - - /// Extract a keyword argument. - pub fn get_key_opt(&mut self, name: &str) -> ParseResult> { - Ok(if let Some(index) = self.key.iter().position(|arg| arg.v.key.v.0 == name) { - let value = self.key.swap_remove(index).v.value; - Some(E::from_expr(value)?) - } else { - None - }) - } - - /// Extract any keyword argument. - pub fn get_key_next(&mut self) -> Option> { - self.key.pop() - } - - /// Iterator over all keyword arguments. - pub fn keys(&mut self) -> std::vec::IntoIter> { - let vec = std::mem::replace(&mut self.key, vec![]); - vec.into_iter() - } - - /// Clear the argument lists. - pub fn clear(&mut self) { - self.pos.clear(); - self.key.clear(); - } - - /// Whether both the positional and keyword argument lists are empty. - pub fn is_empty(&self) -> bool { - self.pos.is_empty() && self.key.is_empty() - } -} - -/// Extract the option expression kind from the option or return an error. -fn expect(opt: ParseResult>) -> ParseResult { - match opt { - Ok(Some(spanned)) => Ok(spanned), - Ok(None) => error!("expected {}", E::NAME), - Err(e) => Err(e), - } -} - -/// A positional argument passed to a function. -pub type PosArg = Expression; - -/// A keyword argument passed to a function. -#[derive(Debug, Clone, PartialEq)] -pub struct KeyArg { - pub key: Spanned, - pub value: Spanned, -} - -/// Either a positional or keyword argument. -#[derive(Debug, Clone, PartialEq)] -pub enum DynArg { - Pos(Spanned), - Key(Spanned), -} - /// An argument or return value. #[derive(Clone, PartialEq)] pub enum Expression { Ident(Ident), Str(String), - Num(f64), + Number(f64), Size(Size), Bool(bool), + Tuple(Tuple), + Object(Object), } impl Display for Expression { @@ -128,20 +19,17 @@ impl Display for Expression { match self { Ident(i) => write!(f, "{}", i), Str(s) => write!(f, "{:?}", s), - Num(n) => write!(f, "{}", n), + Number(n) => write!(f, "{}", n), Size(s) => write!(f, "{}", s), Bool(b) => write!(f, "{}", b), + Tuple(t) => write!(f, "{}", t), + Object(o) => write!(f, "{}", o), } } } -debug_display!(Expression); - -pub struct Tuple; -pub struct Object; - /// An identifier. -#[derive(Clone, PartialEq)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Ident(pub String); impl Ident { @@ -164,16 +52,98 @@ impl Display for Ident { } } +/// A sequence of expressions. +#[derive(Clone, PartialEq)] +pub struct Tuple { + pub items: Vec>, +} + +impl Tuple { + pub fn new() -> Tuple { + Tuple { items: vec![] } + } + + pub fn add(&mut self, item: Spanned) { + self.items.push(item); + } +} + +impl Display for Tuple { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "(")?; + + let mut first = true; + for item in &self.items { + if !first { + write!(f, ", ")?; + } + write!(f, "{}", item.v)?; + first = false; + } + + write!(f, ")") + } +} + +/// A key-value collection of identifiers and associated expressions. +#[derive(Clone, PartialEq)] +pub struct Object { + pub pairs: Vec, +} + +#[derive(Clone, PartialEq)] +pub struct Pair { + pub key: Spanned, + pub value: Spanned, +} + +impl Object { + pub fn new() -> Object { + Object { pairs: vec![] } + } + + pub fn add(&mut self, key: Spanned, value: Spanned) { + self.pairs.push(Pair { key, value }); + } + + pub fn add_pair(&mut self, pair: Pair) { + self.pairs.push(pair); + } +} + +impl Display for Object { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{{ ")?; + + let mut first = true; + for pair in &self.pairs { + if !first { + write!(f, ", ")?; + } + write!(f, "{}: {}", pair.key.v, pair.value.v)?; + first = false; + } + + write!(f, " }}") + } +} + debug_display!(Ident); +debug_display!(Expression); +debug_display!(Tuple); +debug_display!(Object); + /// Kinds of expressions. pub trait ExpressionKind: Sized { + /// The name of the expression in an `expected ` error. const NAME: &'static str; /// Create from expression. fn from_expr(expr: Spanned) -> ParseResult; } +/// Implements the expression kind trait for a type. macro_rules! kind { ($type:ty, $name:expr, $($patterns:tt)*) => { impl ExpressionKind for $type { @@ -190,15 +160,18 @@ macro_rules! kind { }; } -kind!(Expression, "expression", e => e); -kind!(Ident, "identifier", Expression::Ident(ident) => ident); -kind!(String, "string", Expression::Str(string) => string); -kind!(f64, "number", Expression::Num(num) => num); -kind!(bool, "boolean", Expression::Bool(boolean) => boolean); -kind!(Size, "size", Expression::Size(size) => size); +kind!(Expression, "expression", e => e); +kind!(Ident, "identifier", Expression::Ident(ident) => ident); +kind!(String, "string", Expression::Str(string) => string); +kind!(f64, "number", Expression::Number(num) => num); +kind!(bool, "boolean", Expression::Bool(boolean) => boolean); +kind!(Size, "size", Expression::Size(size) => size); +kind!(Tuple, "tuple", Expression::Tuple(tuple) => tuple); +kind!(Object, "object", Expression::Object(object) => object); + kind!(ScaleSize, "number or size", - Expression::Size(size) => ScaleSize::Absolute(size), - Expression::Num(scale) => ScaleSize::Scaled(scale as f32) + Expression::Size(size) => ScaleSize::Absolute(size), + Expression::Number(scale) => ScaleSize::Scaled(scale as f32) ); impl ExpressionKind for Spanned where T: ExpressionKind { @@ -206,22 +179,6 @@ impl ExpressionKind for Spanned where T: ExpressionKind { fn from_expr(expr: Spanned) -> ParseResult> { let span = expr.span; - T::from_expr(expr) - .map(|v| Spanned::new(v, span)) - } -} - -impl ExpressionKind for Option where T: ExpressionKind { - const NAME: &'static str = T::NAME; - - fn from_expr(expr: Spanned) -> ParseResult> { - if let Expression::Ident(ident) = &expr.v { - match ident.as_str() { - "default" | "none" => return Ok(None), - _ => {}, - } - } - - T::from_expr(expr).map(|v| Some(v)) + T::from_expr(expr).map(|v| Spanned { v, span }) } } -- cgit v1.2.3