16. Compress with_mode and with_nl_mode to reduce rightward drift

This commit is contained in:
Ian Wrzesinski 2024-10-24 22:03:35 -04:00
parent 26c61be1dc
commit 86ce443806

View File

@ -206,12 +206,10 @@ fn reference(p: &mut Parser) {
/// Parses a mathematical equation: `$x$`, `$ x^2 $`. /// Parses a mathematical equation: `$x$`, `$ x^2 $`.
fn equation(p: &mut Parser) { fn equation(p: &mut Parser) {
let m = p.marker(); let m = p.marker();
p.with_mode(LexMode::Math, |p| { p.enter_modes(LexMode::Math, AtNewline::Continue, |p| {
p.with_nl_mode(AtNewline::Continue, |p| { p.assert(SyntaxKind::Dollar);
p.assert(SyntaxKind::Dollar); math(p, |p| p.at(SyntaxKind::Dollar));
math(p, |p| p.at(SyntaxKind::Dollar)); p.expect_closing_delimiter(m, SyntaxKind::Dollar);
p.expect_closing_delimiter(m, SyntaxKind::Dollar);
});
}); });
p.wrap(m, SyntaxKind::Equation); p.wrap(m, SyntaxKind::Equation);
} }
@ -596,30 +594,28 @@ fn code_exprs(p: &mut Parser, mut stop: impl FnMut(&Parser) -> bool) {
/// Parses an atomic code expression embedded in markup or math. /// Parses an atomic code expression embedded in markup or math.
fn embedded_code_expr(p: &mut Parser) { fn embedded_code_expr(p: &mut Parser) {
p.with_mode(LexMode::Code, |p| { p.enter_modes(LexMode::Code, AtNewline::Stop, |p| {
p.with_nl_mode(AtNewline::Stop, |p| { p.assert(SyntaxKind::Hash);
p.assert(SyntaxKind::Hash); if p.had_trivia() {
if p.had_trivia() { p.expected("expression");
p.expected("expression"); return;
return; }
}
let stmt = p.at_set(set::STMT); let stmt = p.at_set(set::STMT);
let at = p.at_set(set::ATOMIC_CODE_EXPR); let at = p.at_set(set::ATOMIC_CODE_EXPR);
code_expr_prec(p, true, 0); code_expr_prec(p, true, 0);
// Consume error for things like `#12p` or `#"abc\"`.# // Consume error for things like `#12p` or `#"abc\"`.#
if !at && !p.end() { if !at && !p.end() {
p.unexpected(); p.unexpected();
} }
let semi = (stmt || p.directly_at(SyntaxKind::Semicolon)) let semi = (stmt || p.directly_at(SyntaxKind::Semicolon))
&& p.eat_if(SyntaxKind::Semicolon); && p.eat_if(SyntaxKind::Semicolon);
if stmt && !semi && !p.end() && !p.at(SyntaxKind::RightBracket) { if stmt && !semi && !p.end() && !p.at(SyntaxKind::RightBracket) {
p.expected("semicolon or line break"); p.expected("semicolon or line break");
} }
});
}); });
} }
@ -779,12 +775,10 @@ fn block(p: &mut Parser) {
/// Parses a code block: `{ let x = 1; x + 2 }`. /// Parses a code block: `{ let x = 1; x + 2 }`.
fn code_block(p: &mut Parser) { fn code_block(p: &mut Parser) {
let m = p.marker(); let m = p.marker();
p.with_mode(LexMode::Code, |p| { p.enter_modes(LexMode::Code, AtNewline::Continue, |p| {
p.with_nl_mode(AtNewline::Continue, |p| { p.assert(SyntaxKind::LeftBrace);
p.assert(SyntaxKind::LeftBrace); code(p, |p| p.at_set(syntax_set!(RightBrace, RightBracket, RightParen)));
code(p, |p| p.at_set(syntax_set!(RightBrace, RightBracket, RightParen))); p.expect_closing_delimiter(m, SyntaxKind::RightBrace);
p.expect_closing_delimiter(m, SyntaxKind::RightBrace);
});
}); });
p.wrap(m, SyntaxKind::CodeBlock); p.wrap(m, SyntaxKind::CodeBlock);
} }
@ -792,12 +786,10 @@ fn code_block(p: &mut Parser) {
/// Parses a content block: `[*Hi* there!]`. /// Parses a content block: `[*Hi* there!]`.
fn content_block(p: &mut Parser) { fn content_block(p: &mut Parser) {
let m = p.marker(); let m = p.marker();
p.with_mode(LexMode::Markup, |p| { p.enter_modes(LexMode::Markup, AtNewline::Continue, |p| {
p.with_nl_mode(AtNewline::Continue, |p| { p.assert(SyntaxKind::LeftBracket);
p.assert(SyntaxKind::LeftBracket); markup(p, true, true, |p| p.at(SyntaxKind::RightBracket));
markup(p, true, true, |p| p.at(SyntaxKind::RightBracket)); p.expect_closing_delimiter(m, SyntaxKind::RightBracket);
p.expect_closing_delimiter(m, SyntaxKind::RightBracket);
});
}); });
p.wrap(m, SyntaxKind::ContentBlock); p.wrap(m, SyntaxKind::ContentBlock);
} }
@ -1815,10 +1807,15 @@ impl<'s> Parser<'s> {
/// current token). This may re-lex the final token on exit. /// current token). This may re-lex the final token on exit.
/// ///
/// This function effectively repurposes the call stack as a stack of modes. /// This function effectively repurposes the call stack as a stack of modes.
fn with_mode(&mut self, mode: LexMode, func: impl FnOnce(&mut Parser<'s>)) { fn enter_modes(
&mut self,
mode: LexMode,
stop: AtNewline,
func: impl FnOnce(&mut Parser<'s>),
) {
let previous = self.lexer.mode(); let previous = self.lexer.mode();
self.lexer.set_mode(mode); self.lexer.set_mode(mode);
func(self); self.with_nl_mode(stop, func);
if mode != previous { if mode != previous {
self.lexer.set_mode(previous); self.lexer.set_mode(previous);
self.lexer.jump(self.token.prev_end); self.lexer.jump(self.token.prev_end);