diff options
| author | Laurenz <laurmaedje@gmail.com> | 2020-08-15 11:44:18 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2020-08-15 11:44:18 +0200 |
| commit | 1a0608930cea9c939319ae4b6e2c793eaf2f10d0 (patch) | |
| tree | e8a8a157a40fa2198b5db5066e91fa8ecb5e16e6 /src/syntax/value.rs | |
| parent | d90d921a910e52242c68a91ff3ff03749250253c (diff) | |
Rename Value trait into TryFromExpr ✒
Diffstat (limited to 'src/syntax/value.rs')
| -rw-r--r-- | src/syntax/value.rs | 197 |
1 files changed, 0 insertions, 197 deletions
diff --git a/src/syntax/value.rs b/src/syntax/value.rs deleted file mode 100644 index aa5049e0..00000000 --- a/src/syntax/value.rs +++ /dev/null @@ -1,197 +0,0 @@ -//! Value types for extracting function arguments. - -use fontdock::{FontStyle, FontWeight, FontWidth}; - -use crate::layout::{Dir, SpecAlign}; -use crate::length::{Length, ScaleLength}; -use crate::paper::Paper; -use crate::Feedback; -use super::expr::*; -use super::span::Spanned; -use super::tree::SyntaxTree; - -/// Value types are used to extract values from functions, tuples and -/// objects. They represent the value part of an argument. -/// -/// # Example -/// ```typst -/// [func: 12pt, key="these are both values"] -/// ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ -/// ``` -pub trait Value: Sized { - /// Try to parse this value from an expression. - /// - /// Returns `None` and generates an appropriate error if the expression is - /// not valid for this value type - fn parse(expr: Spanned<Expr>, f: &mut Feedback) -> Option<Self>; -} - -impl<V: Value> Value for Spanned<V> { - fn parse(expr: Spanned<Expr>, f: &mut Feedback) -> Option<Self> { - let span = expr.span; - V::parse(expr, f).map(|v| Spanned { v, span }) - } -} - -macro_rules! match_value { - ($type:ty, $name:expr, $($p:pat => $r:expr),* $(,)?) => { - impl Value for $type { - fn parse(expr: Spanned<Expr>, f: &mut Feedback) -> Option<Self> { - #[allow(unreachable_patterns)] - match expr.v { - $($p => Some($r)),*, - other => { - error!( - @f, expr.span, - "expected {}, found {}", $name, other.name() - ); - None - } - } - } - } - }; -} - -match_value!(Expr, "expression", e => e); -match_value!(Ident, "identifier", Expr::Ident(i) => i); -match_value!(String, "string", Expr::Str(s) => s); -match_value!(bool, "bool", Expr::Bool(b) => b); -match_value!(f64, "number", Expr::Number(n) => n); -match_value!(Length, "length", Expr::Length(l) => l); -match_value!(SyntaxTree, "tree", Expr::Tree(t) => t); -match_value!(Tuple, "tuple", Expr::Tuple(t) => t); -match_value!(Object, "object", Expr::Object(o) => o); -match_value!(ScaleLength, "number or length", - Expr::Length(length) => ScaleLength::Absolute(length), - Expr::Number(scale) => ScaleLength::Scaled(scale), -); - -/// A value type that matches identifiers and strings and implements -/// `Into<String>`. -pub struct StringLike(pub String); - -impl From<StringLike> for String { - fn from(like: StringLike) -> String { - like.0 - } -} - -match_value!(StringLike, "identifier or string", - Expr::Ident(Ident(s)) => StringLike(s), - Expr::Str(s) => StringLike(s), -); - -macro_rules! ident_value { - ($type:ty, $name:expr, $parse:expr) => { - impl Value for $type { - fn parse(expr: Spanned<Expr>, f: &mut Feedback) -> Option<Self> { - if let Expr::Ident(ident) = expr.v { - let val = $parse(ident.as_str()); - if val.is_none() { - error!(@f, expr.span, "invalid {}", $name); - } - val - } else { - error!( - @f, expr.span, - "expected {}, found {}", $name, expr.v.name() - ); - None - } - } - } - }; -} - -ident_value!(Dir, "direction", |s| match s { - "ltr" => Some(Self::LTR), - "rtl" => Some(Self::RTL), - "ttb" => Some(Self::TTB), - "btt" => Some(Self::BTT), - _ => None, -}); - -ident_value!(SpecAlign, "alignment", |s| match s { - "left" => Some(Self::Left), - "right" => Some(Self::Right), - "top" => Some(Self::Top), - "bottom" => Some(Self::Bottom), - "center" => Some(Self::Center), - _ => None, -}); - -ident_value!(FontStyle, "font style", FontStyle::from_name); -ident_value!(Paper, "paper", Paper::from_name); - -impl Value for FontWeight { - fn parse(expr: Spanned<Expr>, f: &mut Feedback) -> Option<Self> { - match expr.v { - Expr::Number(weight) => { - const MIN: u16 = 100; - const MAX: u16 = 900; - - Some(Self(if weight < MIN as f64 { - error!(@f, expr.span, "the minimum font weight is {}", MIN); - MIN - } else if weight > MAX as f64 { - error!(@f, expr.span, "the maximum font weight is {}", MAX); - MAX - } else { - weight.round() as u16 - })) - } - Expr::Ident(ident) => { - let weight = Self::from_name(ident.as_str()); - if weight.is_none() { - error!(@f, expr.span, "invalid font weight"); - } - weight - } - other => { - error!( - @f, expr.span, - "expected font weight (name or number), found {}", - other.name(), - ); - None - } - } - } -} - -impl Value for FontWidth { - fn parse(expr: Spanned<Expr>, f: &mut Feedback) -> Option<Self> { - match expr.v { - Expr::Number(width) => { - const MIN: u16 = 1; - const MAX: u16 = 9; - - Self::new(if width < MIN as f64 { - error!(@f, expr.span, "the minimum font width is {}", MIN); - MIN - } else if width > MAX as f64 { - error!(@f, expr.span, "the maximum font width is {}", MAX); - MAX - } else { - width.round() as u16 - }) - } - Expr::Ident(ident) => { - let width = Self::from_name(ident.as_str()); - if width.is_none() { - error!(@f, expr.span, "invalid font width"); - } - width - } - other => { - error!( - @f, expr.span, - "expected font width (name or number), found {}", - other.name(), - ); - None - } - } - } -} |
