diff options
| author | Laurenz <laurmaedje@gmail.com> | 2020-01-13 14:36:40 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2020-01-13 14:36:40 +0100 |
| commit | dde69276d47818174c35523c8ed86b6888b6d02b (patch) | |
| tree | 68f0f56efd42f47156fddf67158cdcdcde3717b9 /src/syntax/expr.rs | |
| parent | 6527d31dfba78330a39e52d7772f6c8561fb23ef (diff) | |
Refactor expressions and create tuples and objects 🧮
Diffstat (limited to 'src/syntax/expr.rs')
| -rw-r--r-- | src/syntax/expr.rs | 245 |
1 files changed, 101 insertions, 144 deletions
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<Spanned<PosArg>>, - pub key: Vec<Spanned<KeyArg>>, -} - -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<PosArg>) { - self.pos.push(arg); - } - - /// Add a keyword argument. - pub fn add_key(&mut self, arg: Spanned<KeyArg>) { - self.key.push(arg); - } - - /// Force-extract the first positional argument. - pub fn get_pos<E: ExpressionKind>(&mut self) -> ParseResult<E> { - expect(self.get_pos_opt()) - } - - /// Extract the first positional argument. - pub fn get_pos_opt<E: ExpressionKind>(&mut self) -> ParseResult<Option<E>> { - 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<Spanned<PosArg>> { - let vec = std::mem::replace(&mut self.pos, vec![]); - vec.into_iter() - } - - /// Force-extract a keyword argument. - pub fn get_key<E: ExpressionKind>(&mut self, name: &str) -> ParseResult<E> { - expect(self.get_key_opt(name)) - } - - /// Extract a keyword argument. - pub fn get_key_opt<E: ExpressionKind>(&mut self, name: &str) -> ParseResult<Option<E>> { - 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<Spanned<KeyArg>> { - self.key.pop() - } - - /// Iterator over all keyword arguments. - pub fn keys(&mut self) -> std::vec::IntoIter<Spanned<KeyArg>> { - 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<E: ExpressionKind>(opt: ParseResult<Option<E>>) -> ParseResult<E> { - 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<Ident>, - pub value: Spanned<Expression>, -} - -/// Either a positional or keyword argument. -#[derive(Debug, Clone, PartialEq)] -pub enum DynArg { - Pos(Spanned<PosArg>), - Key(Spanned<KeyArg>), -} - /// 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<Spanned<Expression>>, +} + +impl Tuple { + pub fn new() -> Tuple { + Tuple { items: vec![] } + } + + pub fn add(&mut self, item: Spanned<Expression>) { + 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<Pair>, +} + +#[derive(Clone, PartialEq)] +pub struct Pair { + pub key: Spanned<Ident>, + pub value: Spanned<Expression>, +} + +impl Object { + pub fn new() -> Object { + Object { pairs: vec![] } + } + + pub fn add(&mut self, key: Spanned<Ident>, value: Spanned<Expression>) { + 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 <name>` error. const NAME: &'static str; /// Create from expression. fn from_expr(expr: Spanned<Expression>) -> ParseResult<Self>; } +/// 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<T> ExpressionKind for Spanned<T> where T: ExpressionKind { @@ -206,22 +179,6 @@ impl<T> ExpressionKind for Spanned<T> where T: ExpressionKind { fn from_expr(expr: Spanned<Expression>) -> ParseResult<Spanned<T>> { let span = expr.span; - T::from_expr(expr) - .map(|v| Spanned::new(v, span)) - } -} - -impl<T> ExpressionKind for Option<T> where T: ExpressionKind { - const NAME: &'static str = T::NAME; - - fn from_expr(expr: Spanned<Expression>) -> ParseResult<Option<T>> { - 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 }) } } |
