diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/func/macros.rs | 41 | ||||
| -rw-r--r-- | src/func/mod.rs | 11 | ||||
| -rw-r--r-- | src/library/align.rs | 4 | ||||
| -rw-r--r-- | src/library/boxed.rs | 6 | ||||
| -rw-r--r-- | src/library/direction.rs | 4 | ||||
| -rw-r--r-- | src/library/mod.rs | 40 | ||||
| -rw-r--r-- | src/syntax/color.rs | 3 | ||||
| -rw-r--r-- | src/syntax/expr.rs | 4 | ||||
| -rw-r--r-- | src/syntax/mod.rs | 113 | ||||
| -rw-r--r-- | src/syntax/parsing.rs | 27 | ||||
| -rw-r--r-- | src/syntax/span.rs | 18 |
11 files changed, 148 insertions, 123 deletions
diff --git a/src/func/macros.rs b/src/func/macros.rs index 1083e53c..90c3b11e 100644 --- a/src/func/macros.rs +++ b/src/func/macros.rs @@ -52,46 +52,43 @@ macro_rules! function { }; // (1-arg) Parse a parse-definition with only the first argument. - (@parse $type:ident $meta:ty | parse($args:ident) $code:block $($rest:tt)*) => { - function!(@parse $type $meta | parse($args, _body, _ctx, _meta) $code $($rest)*); + (@parse $type:ident $meta:ty | parse($header:ident) $code:block $($rest:tt)*) => { + function!(@parse $type $meta | parse($header, _body, _ctx, _meta) $code $($rest)*); }; // (2-arg) Parse a parse-definition with only the first two arguments. (@parse $type:ident $meta:ty | - parse($args:ident, $body:pat) $code:block $($rest:tt)* + parse($header:ident, $body:pat) $code:block $($rest:tt)* ) => { - function!(@parse $type $meta | parse($args, $body, _ctx, _meta) $code $($rest)*); + function!(@parse $type $meta | parse($header, $body, _ctx, _meta) $code $($rest)*); }; // (3-arg) Parse a parse-definition with only the first three arguments. (@parse $type:ident $meta:ty | - parse($args:ident, $body:pat, $ctx:pat) $code:block $($rest:tt)* + parse($header:ident, $body:pat, $ctx:pat) $code:block $($rest:tt)* ) => { - function!(@parse $type $meta | parse($args, $body, $ctx, _meta) $code $($rest)*); + function!(@parse $type $meta | parse($header, $body, $ctx, _meta) $code $($rest)*); }; // (4-arg) Parse a parse-definition with all four arguments. (@parse $type:ident $meta:ty | - parse($args:ident, $body:pat, $ctx:pat, $metadata:pat) $code:block + parse($header:ident, $body:pat, $ctx:pat, $metadata:pat) $code:block $($rest:tt)* ) => { - use $crate::func::prelude::*; - impl $crate::func::ParseFunc for $type { type Meta = $meta; fn parse( - args: FuncArgs, + header: $crate::syntax::FuncHeader, $body: Option<&str>, - $ctx: ParseContext, + $ctx: $crate::syntax::ParseContext, $metadata: Self::Meta, - ) -> ParseResult<Self> where Self: Sized { + ) -> $crate::syntax::ParseResult<Self> where Self: Sized { #[allow(unused_mut)] - let mut $args = args; + let mut $header = header; let val = $code; - if !$args.is_empty() { - return Err($crate::TypesetError - ::with_message("unexpected arguments")); + if !$header.args.is_empty() { + return Err($crate::TypesetError::with_message("unexpected arguments")); } Ok(val) } @@ -112,14 +109,14 @@ macro_rules! function { // (2-arg) Parse a layout-definition with all arguments. (@layout $type:ident | layout($this:ident, $ctx:pat) $code:block) => { - use $crate::func::prelude::*; - - impl LayoutFunc for $type { + impl $crate::func::LayoutFunc for $type { fn layout<'a, 'life0, 'life1, 'async_trait>( &'a $this, - $ctx: LayoutContext<'life0, 'life1> - ) -> std::pin::Pin<Box< - dyn std::future::Future<Output = LayoutResult<Commands<'a>>> + 'async_trait + $ctx: $crate::layout::LayoutContext<'life0, 'life1> + ) -> std::pin::Pin<Box<dyn std::future::Future< + Output = $crate::layout::LayoutResult< + $crate::func::Commands<'a>> + > + 'async_trait >> where 'a: 'async_trait, diff --git a/src/func/mod.rs b/src/func/mod.rs index 90b2a31d..bfc2774c 100644 --- a/src/func/mod.rs +++ b/src/func/mod.rs @@ -14,12 +14,7 @@ mod macros; pub mod prelude { pub use crate::func::{Scope, ParseFunc, LayoutFunc, Command, Commands}; pub use crate::layout::prelude::*; - pub use crate::syntax::{ - ParseContext, ParseResult, - SyntaxTree, FuncCall, FuncArgs, - Expression, Ident, ExpressionKind, - Spanned, Span - }; + pub use crate::syntax::*; pub use crate::size::{Size, Size2D, SizeBox, ValueBox, ScaleSize, FSize, PSize}; pub use crate::style::{LayoutStyle, PageStyle, TextStyle}; pub use Command::*; @@ -31,7 +26,7 @@ pub trait ParseFunc { /// Parse the header and body into this function given a context. fn parse( - args: FuncArgs, + header: FuncHeader, body: Option<&str>, ctx: ParseContext, metadata: Self::Meta, @@ -125,7 +120,7 @@ pub struct Scope { /// A function which parses the source of a function into a function type which /// implements [`LayoutFunc`]. type Parser = dyn Fn( - FuncArgs, + FuncHeader, Option<&str>, ParseContext ) -> ParseResult<Box<dyn LayoutFunc>>; diff --git a/src/library/align.rs b/src/library/align.rs index 6114c3a3..ca2c787b 100644 --- a/src/library/align.rs +++ b/src/library/align.rs @@ -10,10 +10,10 @@ function! { map: PosAxisMap<AlignmentKey>, } - parse(args, body, ctx) { + parse(header, body, ctx) { AlignFunc { body: parse!(optional: body, ctx), - map: PosAxisMap::new(&mut args)?, + map: PosAxisMap::new(&mut header.args)?, } } diff --git a/src/library/boxed.rs b/src/library/boxed.rs index da06a371..af236da4 100644 --- a/src/library/boxed.rs +++ b/src/library/boxed.rs @@ -13,11 +13,11 @@ function! { debug: Option<bool>, } - parse(args, body, ctx) { + parse(header, body, ctx) { BoxFunc { body: parse!(optional: body, ctx).unwrap_or(SyntaxTree::new()), - map: ExtentMap::new(&mut args, false)?, - debug: args.get_key_opt::<bool>("debug")?, + map: ExtentMap::new(&mut header.args, false)?, + debug: header.args.get_key_opt::<bool>("debug")?, } } diff --git a/src/library/direction.rs b/src/library/direction.rs index 39ac2ccd..b7a6e212 100644 --- a/src/library/direction.rs +++ b/src/library/direction.rs @@ -10,10 +10,10 @@ function! { map: PosAxisMap<Direction>, } - parse(args, body, ctx) { + parse(header, body, ctx) { DirectionFunc { body: parse!(optional: body, ctx), - map: PosAxisMap::new(&mut args)?, + map: PosAxisMap::new(&mut header.args)?, } } diff --git a/src/library/mod.rs b/src/library/mod.rs index f8625904..d91f1b35 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -58,11 +58,11 @@ function! { list: Vec<String>, } - parse(args, body, ctx) { + parse(header, body, ctx) { FontFamilyFunc { body: parse!(optional: body, ctx), list: { - args.iter_pos().map(|arg| match arg.v { + header.args.iter_pos().map(|arg| match arg.v { Expression::Str(s) | Expression::Ident(Ident(s)) => Ok(s.to_lowercase()), _ => error!("expected identifier or string"), @@ -86,11 +86,11 @@ function! { style: FontStyle, } - parse(args, body, ctx) { + parse(header, body, ctx) { FontStyleFunc { body: parse!(optional: body, ctx), style: { - let s = args.get_pos::<String>()?; + let s = header.args.get_pos::<String>()?; match FontStyle::from_str(&s) { Some(style) => style, None => error!("invalid font style: `{}`", s), @@ -114,10 +114,10 @@ function! { weight: FontWeight, } - parse(args, body, ctx) { + parse(header, body, ctx) { FontWeightFunc { body: parse!(optional: body, ctx), - weight: match args.get_pos::<Expression>()? { + weight: match header.args.get_pos::<Expression>()? { Expression::Number(weight) => { let weight = weight.round() as i16; FontWeight( @@ -152,10 +152,10 @@ function! { size: ScaleSize, } - parse(args, body, ctx) { + parse(header, body, ctx) { FontSizeFunc { body: parse!(optional: body, ctx), - size: args.get_pos::<ScaleSize>()?, + size: header.args.get_pos::<ScaleSize>()?, } } @@ -187,11 +187,11 @@ function! { type Meta = ContentKind; - parse(args, body, ctx, meta) { + parse(header, body, ctx, meta) { ContentSpacingFunc { body: parse!(optional: body, ctx), content: meta, - spacing: args.get_pos::<f64>()? as f32, + spacing: header.args.get_pos::<f64>()? as f32, } } @@ -256,16 +256,18 @@ function! { type Meta = Option<SpecificAxis>; - parse(args, body, _, meta) { + parse(header, body, _, meta) { parse!(forbidden: body); if let Some(axis) = meta { SpacingFunc { axis: AxisKey::Specific(axis), - spacing: FSize::from_expr(args.get_pos::<Spanned<Expression>>()?)?, + spacing: FSize::from_expr( + header.args.get_pos::<Spanned<Expression>>()? + )?, } } else { - for arg in args.iter_keys() { + for arg in header.args.iter_keys() { let axis = AxisKey::from_ident(&arg.key) .map_err(|_| error!(@unexpected_argument))?; @@ -295,16 +297,16 @@ function! { Custom(ExtentMap<PSize>), } - parse(args, body) { + parse(header, body) { parse!(forbidden: body); - if let Some(name) = args.get_pos_opt::<Ident>()? { - let flip = args.get_key_opt::<bool>("flip")?.unwrap_or(false); + if let Some(name) = header.args.get_pos_opt::<Ident>()? { + let flip = header.args.get_key_opt::<bool>("flip")?.unwrap_or(false); let paper = Paper::from_name(name.as_str()) .ok_or_else(|| error!(@"invalid paper name: `{}`", name))?; PageSizeFunc::Paper(paper, flip) } else { - PageSizeFunc::Custom(ExtentMap::new(&mut args, true)?) + PageSizeFunc::Custom(ExtentMap::new(&mut header.args, true)?) } } @@ -341,10 +343,10 @@ function! { map: PaddingMap, } - parse(args, body) { + parse(header, body) { parse!(forbidden: body); PageMarginsFunc { - map: PaddingMap::new(&mut args)?, + map: PaddingMap::new(&mut header.args)?, } } diff --git a/src/syntax/color.rs b/src/syntax/color.rs deleted file mode 100644 index 65525480..00000000 --- a/src/syntax/color.rs +++ /dev/null @@ -1,3 +0,0 @@ -use super::*; - - diff --git a/src/syntax/expr.rs b/src/syntax/expr.rs index b06b29c8..c4feea74 100644 --- a/src/syntax/expr.rs +++ b/src/syntax/expr.rs @@ -107,6 +107,10 @@ impl Object { impl Display for Object { fn fmt(&self, f: &mut Formatter) -> fmt::Result { + if self.pairs.len() == 0 { + return write!(f, "{{}}"); + } + write!(f, "{{ ")?; let mut first = true; diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index 1c72de4d..bcec05af 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -9,7 +9,6 @@ use crate::size::{Size, ScaleSize}; pub type ParseResult<T> = crate::TypesetResult<T>; -pub_use_mod!(color); pub_use_mod!(expr); pub_use_mod!(tokens); pub_use_mod!(parsing); @@ -93,7 +92,7 @@ impl SyntaxTree { } /// A node in the syntax tree. -#[derive(Debug, PartialEq)] +#[derive(PartialEq)] pub enum Node { /// A number of whitespace characters containing less than two newlines. Space, @@ -111,6 +110,28 @@ pub enum Node { Func(FuncCall), } +impl Display for Node { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Node::Space => write!(f, "Space"), + Node::Newline => write!(f, "Newline"), + Node::Text(text) => write!(f, "{:?}", text), + Node::ToggleItalic => write!(f, "ToggleItalic"), + Node::ToggleBolder => write!(f, "ToggleBold"), + Node::ToggleMonospace => write!(f, "ToggleMonospace"), + Node::Func(func) => { + if f.alternate() { + write!(f, "{:#?}", func.0) + } else { + write!(f, "{:?}", func.0) + } + } + } + } +} + +debug_display!(Node); + /// An invocation of a function. #[derive(Debug)] pub struct FuncCall(pub Box<dyn LayoutFunc>); @@ -121,59 +142,20 @@ impl PartialEq for FuncCall { } } -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct Colorization { - pub colors: Vec<Spanned<ColorToken>>, -} - -/// Entities which can be colored by syntax highlighting. -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub enum ColorToken { - Comment, - - Bracket, - FuncName, - Colon, - - Key, - Equals, - Comma, - - Paren, - Brace, - - ExprIdent, - ExprStr, - ExprNumber, - ExprSize, - ExprBool, - - Bold, - Italic, - Monospace, - - Invalid, -} - -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct ErrorMap { - pub errors: Vec<Spanned<String>>, -} - -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq)] pub struct FuncHeader { pub name: Spanned<Ident>, pub args: FuncArgs, } -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq)] pub struct FuncArgs { - positional: Tuple, - keyword: Object, + pub positional: Tuple, + pub keyword: Object, } impl FuncArgs { - fn new() -> FuncArgs { + pub fn new() -> FuncArgs { FuncArgs { positional: Tuple::new(), keyword: Object::new(), @@ -258,3 +240,42 @@ fn expect<E: ExpressionKind>(opt: ParseResult<Option<E>>) -> ParseResult<E> { Err(e) => Err(e), } } + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct Colorization { + pub tokens: Vec<Spanned<ColorToken>>, +} + +/// Entities which can be colored by syntax highlighting. +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum ColorToken { + Comment, + + Bracket, + FuncName, + Colon, + + Key, + Equals, + Comma, + + Paren, + Brace, + + ExprIdent, + ExprStr, + ExprNumber, + ExprSize, + ExprBool, + + Bold, + Italic, + Monospace, + + Invalid, +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct ErrorMap { + pub errors: Vec<Spanned<String>>, +} diff --git a/src/syntax/parsing.rs b/src/syntax/parsing.rs index bf3bea89..f0a68641 100644 --- a/src/syntax/parsing.rs +++ b/src/syntax/parsing.rs @@ -33,7 +33,7 @@ impl<'s> Parser<'s> { src, ctx, error_map: ErrorMap { errors: vec![] }, - colorization: Colorization { colors: vec![] }, + colorization: Colorization { tokens: vec![] }, tokens: Tokens::new(src), peeked: None, @@ -114,8 +114,6 @@ impl<'s> Parser<'s> { } fn parse_func_call(&mut self, header: Option<FuncHeader>) -> Option<FuncCall> { - println!("peek: {:?}", self.peek()); - let body = if self.peek() == Some(LeftBracket) { self.eat(); @@ -140,13 +138,15 @@ impl<'s> Parser<'s> { }; let header = header?; - let name = header.name; - let parser = self.ctx.scope.get_parser(name.v.as_str()).or_else(|| { - self.error(format!("unknown function: `{}`", name.v), name.span); + let parser = self.ctx.scope.get_parser(header.name.v.as_str()).or_else(|| { + self.error( + format!("unknown function: `{}`", header.name.v), + header.name.span + ); None })?; - Some(FuncCall(parser(header.args, body, self.ctx).unwrap())) + Some(FuncCall(parser(header, body, self.ctx).unwrap())) } fn parse_func_name(&mut self) -> Option<Spanned<Ident>> { @@ -163,16 +163,17 @@ impl<'s> Parser<'s> { } fn parse_func_args(&mut self) -> FuncArgs { - // unimplemented!() + // todo!() + self.eat_until(|t| t == RightBracket, true); FuncArgs::new() } fn parse_tuple(&mut self) -> Spanned<Expression> { - unimplemented!("parse_tuple") + todo!("parse_tuple") } fn parse_object(&mut self) -> Spanned<Expression> { - unimplemented!("parse_object") + todo!("parse_object") } fn skip_whitespace(&mut self) { @@ -207,13 +208,13 @@ impl<'s> Parser<'s> { fn color(&mut self, token: Spanned<ColorToken>, replace_last: bool) { if replace_last { - if let Some(last) = self.colorization.colors.last_mut() { + if let Some(last) = self.colorization.tokens.last_mut() { *last = token; return; } } - self.colorization.colors.push(token); + self.colorization.tokens.push(token); } fn color_token(&mut self, token: Spanned<Token<'s>>) { @@ -235,7 +236,7 @@ impl<'s> Parser<'s> { }; if let Some(color) = colored { - self.colorization.colors.push(Spanned { v: color, span: token.span }); + self.colorization.tokens.push(Spanned { v: color, span: token.span }); } } diff --git a/src/syntax/span.rs b/src/syntax/span.rs index e5c6912b..546b3ad6 100644 --- a/src/syntax/span.rs +++ b/src/syntax/span.rs @@ -1,6 +1,6 @@ //! Spans map elements to the part of source code they originate from. -use std::fmt::{self, Display, Formatter}; +use std::fmt::{self, Debug, Display, Formatter}; /// Annotates a value with the part of the source code it corresponds to. @@ -28,13 +28,21 @@ impl<T> Spanned<T> { } } -impl<T> Display for Spanned<T> where T: std::fmt::Debug { +impl<T> Display for Spanned<T> where T: std::fmt::Display { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "({:?}:{})", self.v, self.span) + write!(f, "({}, {}, ", self.span.start, self.span.end)?; + self.v.fmt(f)?; + write!(f, ")") } } -debug_display!(Spanned; T where T: std::fmt::Debug); +impl<T> Debug for Spanned<T> where T: std::fmt::Debug { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "({}, {}, ", self.span.start, self.span.end)?; + self.v.fmt(f)?; + write!(f, ")") + } +} /// Describes a slice of source code. #[derive(Copy, Clone, Eq, PartialEq, Hash)] @@ -68,7 +76,7 @@ impl Span { impl Display for Span { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "[{}, {}]", self.start, self.end) + write!(f, "({}, {})", self.start, self.end) } } |
