diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-01-17 13:53:22 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-01-17 13:53:22 +0100 |
| commit | 29be90bf95f2ea10c435e7b02f8c26626b956417 (patch) | |
| tree | b6186120a443664c0d016730725b27f7c550eb78 /src/parse | |
| parent | cc5f14193c25200e254e64cc594b15e84da280f9 (diff) | |
Assertions with [eq] + better tests 🩺
Diffstat (limited to 'src/parse')
| -rw-r--r-- | src/parse/mod.rs | 10 | ||||
| -rw-r--r-- | src/parse/parser.rs | 85 |
2 files changed, 49 insertions, 46 deletions
diff --git a/src/parse/mod.rs b/src/parse/mod.rs index b6836d38..7c92185d 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -117,7 +117,7 @@ fn heading(p: &mut Parser) -> NodeHeading { // Parse the heading contents. let mut contents = vec![]; - while p.check(|t| !matches!(t, Token::Space(n) if n > 0)) { + while p.check(|t| !matches!(t, Token::Space(n) if n >= 1)) { if let Some(node) = p.span_if(|p| node(p, &mut false)) { contents.push(node); } @@ -388,8 +388,8 @@ fn string(p: &mut Parser, token: TokenStr) -> String { /// Parse a let expresion. fn expr_let(p: &mut Parser) -> Option<Expr> { p.push_mode(TokenMode::Code); - p.start_group(Group::Terminated); p.eat_assert(Token::Let); + p.start_group(Group::Expr); let pat = p.span_if(ident); let mut rhs = None; @@ -404,11 +404,11 @@ fn expr_let(p: &mut Parser) -> Option<Expr> { p.diag_expected("identifier"); } - while !p.eof() { - p.diag_unexpected(); + p.pop_mode(); + if !p.eof() { + p.diag_expected("semicolon or line break"); } - p.pop_mode(); p.end_group(); pat.map(|pat| Expr::Let(ExprLet { pat, expr: rhs })) } diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 2b5fe720..8c27c8f7 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -112,16 +112,14 @@ impl<'s> Parser<'s> { /// # Panics /// This panics if the next token does not start the given group. pub fn start_group(&mut self, group: Group) { + self.groups.push(group); match group { Group::Paren => self.eat_assert(Token::LeftParen), Group::Bracket => self.eat_assert(Token::LeftBracket), Group::Brace => self.eat_assert(Token::LeftBrace), - Group::Subheader => {} - Group::Terminated => {} + Group::Expr => self.repeek(), + Group::Subheader => self.repeek(), } - - self.groups.push(group); - self.repeek(); } /// Ends the parsing of a group and returns the span of the whole group. @@ -129,26 +127,21 @@ impl<'s> Parser<'s> { /// # Panics /// This panics if no group was started. pub fn end_group(&mut self) { - // Check that we are indeed at the end of the group. - debug_assert_eq!(self.peek(), None, "unfinished group"); - let group = self.groups.pop().expect("no started group"); self.repeek(); - let end = match group { - Group::Paren => Some(Token::RightParen), - Group::Bracket => Some(Token::RightBracket), - Group::Brace => Some(Token::RightBrace), - Group::Subheader => None, - Group::Terminated => Some(Token::Semicolon), + let (end, required) = match group { + Group::Paren => (Token::RightParen, true), + Group::Bracket => (Token::RightBracket, true), + Group::Brace => (Token::RightBrace, true), + Group::Expr => (Token::Semicolon, false), + Group::Subheader => return, }; - if let Some(token) = end { - if self.next == Some(token) { - self.bump(); - } else { - self.diag(error!(self.next_start, "expected {}", token.name())); - } + if self.next == Some(end) { + self.bump(); + } else if required { + self.diag(error!(self.next_start, "expected {}", end.name())); } } @@ -169,7 +162,7 @@ impl<'s> Parser<'s> { where F: FnOnce(&mut Self) -> Option<T>, { - self.span(|p| f(p)).transpose() + self.span(f).transpose() } /// Consume the next token. @@ -269,17 +262,21 @@ impl<'s> Parser<'s> { match self.tokens.mode() { TokenMode::Markup => {} - TokenMode::Code => { - while matches!( - self.next, - Some(Token::Space(_)) | - Some(Token::LineComment(_)) | - Some(Token::BlockComment(_)) - ) { - self.next_start = self.tokens.pos(); - self.next = self.tokens.next(); + TokenMode::Code => loop { + match self.next { + Some(Token::Space(n)) => { + if n >= 1 && self.groups.last() == Some(&Group::Expr) { + break; + } + } + Some(Token::LineComment(_)) => {} + Some(Token::BlockComment(_)) => {} + _ => break, } - } + + self.next_start = self.tokens.pos(); + self.next = self.tokens.next(); + }, } self.repeek(); @@ -287,16 +284,22 @@ impl<'s> Parser<'s> { fn repeek(&mut self) { self.peeked = self.next; - if self.groups.contains(&match self.next { - Some(Token::RightParen) => Group::Paren, - Some(Token::RightBracket) => Group::Bracket, - Some(Token::RightBrace) => Group::Brace, - Some(Token::Pipe) => Group::Subheader, - Some(Token::Semicolon) => Group::Terminated, + let token = match self.next { + Some(token) => token, + None => return, + }; + + match token { + Token::RightParen if self.groups.contains(&Group::Paren) => {} + Token::RightBracket if self.groups.contains(&Group::Bracket) => {} + Token::RightBrace if self.groups.contains(&Group::Brace) => {} + Token::Semicolon if self.groups.contains(&Group::Expr) => {} + Token::Space(n) if n >= 1 && self.groups.last() == Some(&Group::Expr) => {} + Token::Pipe if self.groups.contains(&Group::Subheader) => {} _ => return, - }) { - self.peeked = None; } + + self.peeked = None; } } @@ -316,9 +319,9 @@ pub enum Group { Bracket, /// A curly-braced group: `{...}`. Brace, + /// A group ended by a semicolon or a line break: `;`, `\n`. + Expr, /// A group ended by a chained subheader or a closing bracket: /// `... >>`, `...]`. Subheader, - /// A group ended by a semicolon: `;`. - Terminated, } |
