From 2bb0135d2ad45b2a7228dbb61a04a703b1942798 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Thu, 2 Feb 2023 22:22:16 +0100 Subject: Fix inconsistency between text and idents in math --- src/syntax/parser.rs | 51 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 13 deletions(-) (limited to 'src/syntax') diff --git a/src/syntax/parser.rs b/src/syntax/parser.rs index 5933d481..9f951389 100644 --- a/src/syntax/parser.rs +++ b/src/syntax/parser.rs @@ -230,9 +230,11 @@ fn math_expr(p: &mut Parser) { fn math_expr_prec(p: &mut Parser, min_prec: usize, stop: SyntaxKind) { let m = p.marker(); + let mut continuable = false; match p.current() { SyntaxKind::Hashtag => embedded_code_expr(p), SyntaxKind::MathIdent => { + continuable = true; p.eat(); while p.directly_at(SyntaxKind::Text) && p.current_text() == "." @@ -245,30 +247,41 @@ fn math_expr_prec(p: &mut Parser, min_prec: usize, stop: SyntaxKind) { p.convert(SyntaxKind::Ident); p.wrap(m, SyntaxKind::FieldAccess); } - if p.directly_at(SyntaxKind::Text) && p.current_text() == "(" { + if min_prec < 3 && p.directly_at(SyntaxKind::Text) && p.current_text() == "(" + { math_args(p); p.wrap(m, SyntaxKind::FuncCall); + continuable = false; } } SyntaxKind::Text | SyntaxKind::Shorthand => { - if math_class(p.current_text()) == Some(MathClass::Fence) { - math_delimited(p, MathClass::Fence) - } else if math_class(p.current_text()) == Some(MathClass::Opening) { - math_delimited(p, MathClass::Closing) - } else { - p.eat() + continuable = matches!( + math_class(p.current_text()), + None | Some(MathClass::Alphabetic) + ); + if !maybe_delimited(p, true) { + p.eat(); } } - SyntaxKind::Linebreak - | SyntaxKind::Escape - | SyntaxKind::MathAlignPoint - | SyntaxKind::Str => p.eat(), + SyntaxKind::Linebreak | SyntaxKind::MathAlignPoint => p.eat(), + SyntaxKind::Escape | SyntaxKind::Str => { + continuable = true; + p.eat(); + } _ => p.expected("expression"), } + if continuable + && min_prec < 3 + && p.prev_end() == p.current_start() + && maybe_delimited(p, false) + { + p.wrap(m, SyntaxKind::Math); + } + while !p.eof() && !p.at(stop) { let Some((kind, stop, assoc, mut prec)) = math_op(p.current()) else { break; @@ -302,6 +315,18 @@ fn math_expr_prec(p: &mut Parser, min_prec: usize, stop: SyntaxKind) { } } +fn maybe_delimited(p: &mut Parser, allow_fence: bool) -> bool { + if allow_fence && math_class(p.current_text()) == Some(MathClass::Fence) { + math_delimited(p, MathClass::Fence); + true + } else if math_class(p.current_text()) == Some(MathClass::Opening) { + math_delimited(p, MathClass::Closing); + true + } else { + false + } +} + fn math_delimited(p: &mut Parser, stop: MathClass) { let m = p.marker(); p.eat(); @@ -361,10 +386,10 @@ fn math_class(text: &str) -> Option { fn math_op(kind: SyntaxKind) -> Option<(SyntaxKind, SyntaxKind, ast::Assoc, usize)> { match kind { SyntaxKind::Underscore => { - Some((SyntaxKind::MathAttach, SyntaxKind::Hat, ast::Assoc::Right, 2)) + Some((SyntaxKind::MathAttach, SyntaxKind::Hat, ast::Assoc::Right, 3)) } SyntaxKind::Hat => { - Some((SyntaxKind::MathAttach, SyntaxKind::Underscore, ast::Assoc::Right, 2)) + Some((SyntaxKind::MathAttach, SyntaxKind::Underscore, ast::Assoc::Right, 3)) } SyntaxKind::Slash => { Some((SyntaxKind::MathFrac, SyntaxKind::Eof, ast::Assoc::Left, 1)) -- cgit v1.2.3