diff options
Diffstat (limited to 'src/syntax')
| -rw-r--r-- | src/syntax/mod.rs | 87 | ||||
| -rw-r--r-- | src/syntax/parsing.rs | 64 | ||||
| -rw-r--r-- | src/syntax/span.rs | 72 |
3 files changed, 114 insertions, 109 deletions
diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index 9406fdf4..33413317 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -2,13 +2,15 @@ use std::fmt::{self, Display, Formatter}; -use crate::func::Function; +use crate::func::LayoutFunc; use crate::size::Size; mod tokens; #[macro_use] mod parsing; +mod span; +pub use span::{Span, Spanned}; pub use tokens::{tokenize, Tokens}; pub use parsing::{parse, ParseContext, ParseError, ParseResult}; @@ -90,7 +92,13 @@ pub enum Node { #[derive(Debug)] pub struct FuncCall { pub header: Spanned<FuncHeader>, - pub body: Spanned<Box<dyn Function>>, + pub body: Spanned<Box<dyn LayoutFunc>>, +} + +impl PartialEq for FuncCall { + fn eq(&self, other: &FuncCall) -> bool { + (self.header == other.header) && (&self.body == &other.body) + } } /// Contains header information of a function invocation. @@ -134,12 +142,6 @@ pub enum Expression { Bool(bool), } -impl PartialEq for FuncCall { - fn eq(&self, other: &FuncCall) -> bool { - (self.header == other.header) && (&self.body == &other.body) - } -} - impl Display for Expression { fn fmt(&self, f: &mut Formatter) -> fmt::Result { use Expression::*; @@ -154,72 +156,3 @@ impl Display for Expression { } debug_display!(Expression); - -/// Annotates a value with the part of the source code it corresponds to. -#[derive(Copy, Clone, Eq, PartialEq)] -pub struct Spanned<T> { - pub val: T, - pub span: Span, -} - -impl<T> Spanned<T> { - pub fn new(val: T, span: Span) -> Spanned<T> { - Spanned { val, span } - } - - pub fn value(self) -> T { - self.val - } - - pub fn span_map<F, U>(self, f: F) -> Spanned<U> where F: FnOnce(T) -> U { - Spanned::new(f(self.val), self.span) - } -} - -impl<T> Display for Spanned<T> where T: std::fmt::Debug { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "({:?}:{})", self.val, self.span) - } -} - -debug_display!(Spanned; T where T: std::fmt::Debug); - -/// Describes a slice of source code. -#[derive(Copy, Clone, Eq, PartialEq)] -pub struct Span { - pub start: usize, - pub end: usize, -} - -impl Span { - pub fn new(start: usize, end: usize) -> Span { - Span { start, end } - } - - pub fn merge(a: Span, b: Span) -> Span { - Span { - start: a.start.min(b.start), - end: a.end.max(b.end), - } - } - - pub fn at(index: usize) -> Span { - Span { start: index, end: index + 1 } - } - - pub fn pair(&self) -> (usize, usize) { - (self.start, self.end) - } - - pub fn expand(&mut self, other: Span) { - *self = Span::merge(*self, other) - } -} - -impl Display for Span { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "[{}, {}]", self.start, self.end) - } -} - -debug_display!(Span); diff --git a/src/syntax/parsing.rs b/src/syntax/parsing.rs index 77697161..b56094e1 100644 --- a/src/syntax/parsing.rs +++ b/src/syntax/parsing.rs @@ -2,7 +2,7 @@ use unicode_xid::UnicodeXID; -use crate::func::{Function, Scope}; +use crate::func::{LayoutFunc, Scope}; use crate::size::Size; use super::*; @@ -120,10 +120,10 @@ impl<'s> Parser<'s> { if is_identifier(word) { Ok(Spanned::new(word.to_owned(), span)) } else { - perr!("invalid identifier: '{}'", word); + pr!("invalid identifier: '{}'", word); } } - _ => perr!("expected identifier"), + _ => pr!("expected identifier"), }?; self.skip_white(); @@ -132,7 +132,7 @@ impl<'s> Parser<'s> { let args = match self.tokens.next().map(Spanned::value) { Some(Token::RightBracket) => FuncArgs::new(), Some(Token::Colon) => self.parse_func_args()?, - _ => perr!("expected arguments or closing bracket"), + _ => pr!("expected arguments or closing bracket"), }; let end = self.tokens.string_index(); @@ -158,7 +158,7 @@ impl<'s> Parser<'s> { match self.tokens.next().map(Spanned::value) { Some(Token::Comma) => {}, Some(Token::RightBracket) => break, - _ => perr!("expected comma or closing bracket"), + _ => pr!("expected comma or closing bracket"), } } @@ -183,7 +183,7 @@ impl<'s> Parser<'s> { self.skip_white(); let name = token.span_map(|_| name.to_string()); - let next = self.tokens.next().ok_or_else(|| perr!(@"expected value"))?; + let next = self.tokens.next().ok_or_else(|| pr!(@"expected value"))?; let val = Self::parse_expression(next)?; let span = Span::merge(name.span, val.span); @@ -219,18 +219,19 @@ impl<'s> Parser<'s> { } } - _ => perr!("expected expression"), + _ => pr!("expected expression"), }, token.span)) } /// Parse the body of a function. - fn parse_func_body(&mut self, header: &FuncHeader) -> ParseResult<Spanned<Box<dyn Function>>> { + fn parse_func_body(&mut self, header: &FuncHeader) + -> ParseResult<Spanned<Box<dyn LayoutFunc>>> { // Now we want to parse this function dynamically. let parser = self .ctx .scope .get_parser(&header.name.val) - .ok_or_else(|| perr!(@"unknown function: '{}'", &header.name.val))?; + .ok_or_else(|| pr!(@"unknown function: '{}'", &header.name.val))?; let has_body = self.tokens.peek().map(Spanned::value) == Some(Token::LeftBracket); @@ -298,7 +299,7 @@ impl<'s> Parser<'s> { state = NewlineState::Zero; match token.val { Token::LineComment(_) | Token::BlockComment(_) => self.advance(), - Token::StarSlash => perr!("unexpected end of block comment"), + Token::StarSlash => pr!("unexpected end of block comment"), _ => break, } } @@ -454,7 +455,7 @@ mod tests { #![allow(non_snake_case)] use super::*; - use crate::func::{CommandList, Function, Scope}; + use crate::func::{Commands, Scope}; use crate::layout::{LayoutContext, LayoutResult}; use funcs::*; use Node::{Func as F, Newline as N, Space as S}; @@ -464,37 +465,36 @@ mod tests { mod funcs { use super::*; - /// A testing function which just parses it's body into a syntax tree. - #[derive(Debug)] - pub struct TreeFn(pub SyntaxTree); - function! { - data: TreeFn, + /// A testing function which just parses it's body into a syntax + /// tree. + #[derive(Debug)] + pub struct TreeFn { pub tree: SyntaxTree } + + parse(args, body, ctx) { + args.clear(); + TreeFn { + tree: parse!(expected: body, ctx) + } + } - parse(_args, body, ctx) { Ok(TreeFn(parse!(required: body, ctx))) } - layout(_, _) { Ok(vec![]) } + layout() { vec![] } } impl PartialEq for TreeFn { fn eq(&self, other: &TreeFn) -> bool { - assert_tree_equal(&self.0, &other.0); + assert_tree_equal(&self.tree, &other.tree); true } } - /// A testing function without a body. - #[derive(Debug)] - pub struct BodylessFn; - function! { - data: BodylessFn, - - parse(_args, body, _ctx) { parse!(forbidden: body); Ok(BodylessFn) } - layout(_, _) { Ok(vec![]) } - } + /// A testing function without a body. + #[derive(Debug, Default, PartialEq)] + pub struct BodylessFn; - impl PartialEq for BodylessFn { - fn eq(&self, _: &BodylessFn) -> bool { true } + parse(default) + layout() { vec![] } } } @@ -583,7 +583,7 @@ mod tests { func!(@$name, Box::new(BodylessFn), FuncArgs::new()) ); (name => $name:expr, body => $tree:expr $(,)*) => ( - func!(@$name, Box::new(TreeFn($tree)), FuncArgs::new()) + func!(@$name, Box::new(TreeFn { tree: $tree }), FuncArgs::new()) ); (@$name:expr, $body:expr, $args:expr) => ( FuncCall { @@ -789,7 +789,7 @@ mod tests { assert_eq!(func.header.val.args.positional[0].span.pair(), (13, 16)); assert_eq!(func.header.val.args.positional[1].span.pair(), (18, 23)); - let body = &func.body.val.downcast::<TreeFn>().unwrap().0.nodes; + let body = &func.body.val.downcast::<TreeFn>().unwrap().tree.nodes; assert_eq!(func.body.span.pair(), (24, 37)); assert_eq!(body[0].span.pair(), (0, 4)); assert_eq!(body[1].span.pair(), (4, 5)); diff --git a/src/syntax/span.rs b/src/syntax/span.rs new file mode 100644 index 00000000..aa494224 --- /dev/null +++ b/src/syntax/span.rs @@ -0,0 +1,72 @@ +//! Spans map elements to the part of source code they originate from. + +use std::fmt::{self, Display, Formatter}; + +/// Annotates a value with the part of the source code it corresponds to. +#[derive(Copy, Clone, Eq, PartialEq)] +pub struct Spanned<T> { + pub val: T, + pub span: Span, +} + +impl<T> Spanned<T> { + pub fn new(val: T, span: Span) -> Spanned<T> { + Spanned { val, span } + } + + pub fn value(self) -> T { + self.val + } + + pub fn span_map<F, U>(self, f: F) -> Spanned<U> where F: FnOnce(T) -> U { + Spanned::new(f(self.val), self.span) + } +} + +impl<T> Display for Spanned<T> where T: std::fmt::Debug { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "({:?}:{})", self.val, self.span) + } +} + +debug_display!(Spanned; T where T: std::fmt::Debug); + +/// Describes a slice of source code. +#[derive(Copy, Clone, Eq, PartialEq)] +pub struct Span { + pub start: usize, + pub end: usize, +} + +impl Span { + pub fn new(start: usize, end: usize) -> Span { + Span { start, end } + } + + pub fn merge(a: Span, b: Span) -> Span { + Span { + start: a.start.min(b.start), + end: a.end.max(b.end), + } + } + + pub fn at(index: usize) -> Span { + Span { start: index, end: index + 1 } + } + + pub fn pair(&self) -> (usize, usize) { + (self.start, self.end) + } + + pub fn expand(&mut self, other: Span) { + *self = Span::merge(*self, other) + } +} + +impl Display for Span { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "[{}, {}]", self.start, self.end) + } +} + +debug_display!(Span); |
