summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/func/macros.rs41
-rw-r--r--src/func/mod.rs11
-rw-r--r--src/library/align.rs4
-rw-r--r--src/library/boxed.rs6
-rw-r--r--src/library/direction.rs4
-rw-r--r--src/library/mod.rs40
-rw-r--r--src/syntax/color.rs3
-rw-r--r--src/syntax/expr.rs4
-rw-r--r--src/syntax/mod.rs113
-rw-r--r--src/syntax/parsing.rs27
-rw-r--r--src/syntax/span.rs18
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)
}
}