Some code and styling improvements 🎨

This commit is contained in:
Laurenz 2020-07-18 17:52:12 +02:00
parent e9a9581252
commit 332f83ed2d
2 changed files with 55 additions and 60 deletions

View File

@ -230,12 +230,11 @@ impl<'s> FuncParser<'s> {
}).v }).v
} }
/// Parse an expression which may contain math operands. /// Parse an expression which may contain math operands. For this, this
/// For this, this method looks for operators in /// method looks for operators in descending order of associativity, i.e. we
/// descending order of associativity, i.e. we first drill down to find all /// first drill down to find all negations, brackets and tuples, the next
/// negations, brackets and tuples, the next level, /// level, we look for multiplication and division and here finally, for
/// we look for multiplication and division and here finally, for addition /// addition and subtraction.
/// and subtraction.
fn parse_expr(&mut self) -> Option<Spanned<Expr>> { fn parse_expr(&mut self) -> Option<Spanned<Expr>> {
let o1 = self.parse_term()?; let o1 = self.parse_term()?;
self.parse_binop(o1, "summand", Self::parse_expr, |token| match token { self.parse_binop(o1, "summand", Self::parse_expr, |token| match token {
@ -258,21 +257,17 @@ impl<'s> FuncParser<'s> {
&mut self, &mut self,
o1: Spanned<Expr>, o1: Spanned<Expr>,
operand_name: &str, operand_name: &str,
mut parse_operand: F, parse_operand: F,
parse_op: G, parse_op: G,
) -> Option<Spanned<Expr>> ) -> Option<Spanned<Expr>>
where where
F: FnMut(&mut Self) -> Option<Spanned<Expr>>, F: FnOnce(&mut Self) -> Option<Spanned<Expr>>,
G: FnOnce(Token) -> Option<fn(Box<Spanned<Expr>>, Box<Spanned<Expr>>) -> Expr>, G: FnOnce(Token) -> Option<fn(Box<Spanned<Expr>>, Box<Spanned<Expr>>) -> Expr>,
{ {
self.skip_whitespace(); self.skip_whitespace();
if let Some(next) = self.peek() { if let Some(next) = self.peek() {
let binop = match parse_op(next.v) { if let Some(binop) = parse_op(next.v) {
Some(op) => op,
None => return Some(o1),
};
self.eat(); self.eat();
self.skip_whitespace(); self.skip_whitespace();
@ -287,11 +282,12 @@ impl<'s> FuncParser<'s> {
)); ));
} }
} }
}
Some(o1) Some(o1)
} }
/// Parse expressions that are of the form value or -value /// Parse expressions that are of the form value or -value.
fn parse_factor(&mut self) -> Option<Spanned<Expr>> { fn parse_factor(&mut self) -> Option<Spanned<Expr>> {
let first = self.peek()?; let first = self.peek()?;
if first.v == Token::Hyphen { if first.v == Token::Hyphen {
@ -349,12 +345,12 @@ impl<'s> FuncParser<'s> {
}, },
Token::LeftParen => { Token::LeftParen => {
let mut tuple = self.parse_tuple(); let (mut tuple, can_be_coerced) = self.parse_tuple();
// Coerce 1-tuple into value // Coerce 1-tuple into value
if tuple.1 && tuple.0.v.items.len() > 0 { if can_be_coerced && tuple.v.items.len() > 0 {
tuple.0.v.items.pop().expect("Length is one") tuple.v.items.pop().expect("length is at least one")
} else { } else {
tuple.0.map(|t| Expr::Tuple(t)) tuple.map(|t| Expr::Tuple(t))
} }
}, },
Token::LeftBrace => self.parse_object().map(|o| Expr::Object(o)), Token::LeftBrace => self.parse_object().map(|o| Expr::Object(o)),
@ -364,14 +360,14 @@ impl<'s> FuncParser<'s> {
} }
/// Parse a tuple expression: `(<expr>, ...)`. The boolean in the return /// Parse a tuple expression: `(<expr>, ...)`. The boolean in the return
/// values showes whether the tuple can be coerced into a single value /// values showes whether the tuple can be coerced into a single value.
fn parse_tuple(&mut self) -> (Spanned<Tuple>, bool) { fn parse_tuple(&mut self) -> (Spanned<Tuple>, bool) {
let token = self.eat(); let token = self.eat();
debug_assert_eq!(token.map(Spanned::value), Some(Token::LeftParen)); debug_assert_eq!(token.map(Spanned::value), Some(Token::LeftParen));
// Parse a collection until a right paren appears and complain about // Parse a collection until a right paren appears and complain about
// missing a `value` when an invalid token is encoutered. // missing a `value` when an invalid token is encoutered.
self.parse_collection_bracket_aware(Some(Token::RightParen), self.parse_collection_comma_aware(Some(Token::RightParen),
|p| p.parse_expr().ok_or(("value", None))) |p| p.parse_expr().ok_or(("value", None)))
} }
@ -413,12 +409,25 @@ impl<'s> FuncParser<'s> {
}) })
} }
/// Parse a comma-separated collection where each item is parsed through
/// `parse_item` until the `end` token is met.
fn parse_collection<C, I, F>(
&mut self,
end: Option<Token>,
parse_item: F
) -> Spanned<C>
where
C: FromIterator<Spanned<I>>,
F: FnMut(&mut Self) -> Result<Spanned<I>, (&'static str, Option<Position>)>,
{
self.parse_collection_comma_aware(end, parse_item).0
}
/// Parse a comma-separated collection where each item is parsed through /// Parse a comma-separated collection where each item is parsed through
/// `parse_item` until the `end` token is met. The first item in the return /// `parse_item` until the `end` token is met. The first item in the return
/// tuple is the collection, the second item indicates whether the /// tuple is the collection, the second item indicates whether the
/// collection can be coerced into a single item /// collection can be coerced into a single item (i.e. no comma appeared).
/// (i.e. at least one comma appeared). fn parse_collection_comma_aware<C, I, F>(
fn parse_collection_bracket_aware<C, I, F>(
&mut self, &mut self,
end: Option<Token>, end: Option<Token>,
mut parse_item: F mut parse_item: F
@ -490,20 +499,6 @@ impl<'s> FuncParser<'s> {
(Spanned::new(collection, Span { start, end }), can_be_coerced) (Spanned::new(collection, Span { start, end }), can_be_coerced)
} }
/// Parse a comma-separated collection where each item is parsed through
/// `parse_item` until the `end` token is met.
fn parse_collection<C, I, F>(
&mut self,
end: Option<Token>,
parse_item: F
) -> Spanned<C>
where
C: FromIterator<Spanned<I>>,
F: FnMut(&mut Self) -> Result<Spanned<I>, (&'static str, Option<Position>)>,
{
self.parse_collection_bracket_aware(end, parse_item).0
}
/// Try to parse an identifier and do nothing if the peekable token is no /// Try to parse an identifier and do nothing if the peekable token is no
/// identifier. /// identifier.
fn parse_ident(&mut self) -> Option<Spanned<Ident>> { fn parse_ident(&mut self) -> Option<Spanned<Ident>> {