Refactor parser a bit

This commit is contained in:
Laurenz 2021-05-21 23:58:34 +02:00
parent 6472c1e425
commit a175d37ff2

View File

@ -51,7 +51,7 @@ pub enum Group {
Subheader, Subheader,
/// A group ended by a semicolon or a line break: `;`, `\n`. /// A group ended by a semicolon or a line break: `;`, `\n`.
Stmt, Stmt,
/// A group for a single expression. Not ended by something specific. /// A group for a single expression, ended by a line break.
Expr, Expr,
} }
@ -330,25 +330,23 @@ impl<'s> Parser<'s> {
scanner scanner
} }
/// Move to the next token, skipping whitespace and comments in code mode. /// Move to the next token.
fn bump(&mut self) { fn bump(&mut self) {
self.last_end = self.tokens.pos(); self.last_end = self.tokens.pos();
self.next_start = self.tokens.pos(); self.next_start = self.tokens.pos();
self.next = self.tokens.next(); self.next = self.tokens.next();
match self.tokens.mode() { if self.tokens.mode() == TokenMode::Code {
TokenMode::Markup => {} // Skip whitespace and comments.
TokenMode::Code => loop { while match self.next {
match self.next { Some(Token::Space(n)) => n < 1 || !self.stop_at_newline(),
Some(Token::Space(n)) if n < 1 || !self.in_line_group() => {} Some(Token::LineComment(_)) => true,
Some(Token::LineComment(_)) => {} Some(Token::BlockComment(_)) => true,
Some(Token::BlockComment(_)) => {} _ => false,
_ => break, } {
}
self.next_start = self.tokens.pos(); self.next_start = self.tokens.pos();
self.next = self.tokens.next(); self.next = self.tokens.next();
}, }
} }
self.repeek(); self.repeek();
@ -362,31 +360,28 @@ impl<'s> Parser<'s> {
None => return, None => return,
}; };
let inside = |x| self.kinds().any(|k| k == x); if match token {
match token { Token::RightParen => self.inside(Group::Paren),
Token::RightParen if inside(Group::Paren) => {} Token::RightBracket => self.inside(Group::Bracket),
Token::RightBracket if inside(Group::Bracket) => {} Token::RightBrace => self.inside(Group::Brace),
Token::RightBrace if inside(Group::Brace) => {} Token::Semicolon => self.inside(Group::Stmt),
Token::Semicolon if inside(Group::Stmt) => {} Token::Pipe => self.inside(Group::Subheader),
Token::Pipe if inside(Group::Subheader) => {} Token::Space(n) => n >= 1 && self.stop_at_newline(),
Token::Space(n) if n >= 1 && self.in_line_group() => {} _ => false,
_ => return, } {
self.peeked = None;
} }
self.peeked = None;
} }
/// Whether the active group ends at a newline. /// Whether the active group ends at a newline.
fn in_line_group(&self) -> bool { fn stop_at_newline(&self) -> bool {
matches!( let active = self.groups.last().map(|group| group.kind);
self.kinds().next_back(), matches!(active, Some(Group::Stmt) | Some(Group::Expr))
Some(Group::Stmt) | Some(Group::Expr)
)
} }
/// The outer groups. /// Whether we are inside the given group.
fn kinds(&self) -> impl DoubleEndedIterator<Item = Group> + '_ { fn inside(&self, kind: Group) -> bool {
self.groups.iter().map(|group| group.kind) self.groups.iter().any(|g| g.kind == kind)
} }
} }