From 7057809e238c7d2fc0f64080f89649253a184d23 Mon Sep 17 00:00:00 2001 From: mkorje Date: Fri, 13 Jun 2025 17:33:32 +1000 Subject: [PATCH 1/2] Require parentheses in all function-like sub/superscripts --- crates/typst-syntax/src/parser.rs | 4 ++-- ...h-attach-followed-by-func-call-complex.png | Bin 0 -> 927 bytes .../ref/math-attach-followed-by-func-call.png | Bin 1206 -> 2901 bytes tests/ref/raw-highlight-typm.png | Bin 9269 -> 9516 bytes tests/suite/math/accent.typ | 2 +- tests/suite/math/attach.typ | 20 +++++++++++++++--- tests/suite/text/raw.typ | 2 +- 7 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 tests/ref/math-attach-followed-by-func-call-complex.png diff --git a/crates/typst-syntax/src/parser.rs b/crates/typst-syntax/src/parser.rs index b452c2c09..474edbce1 100644 --- a/crates/typst-syntax/src/parser.rs +++ b/crates/typst-syntax/src/parser.rs @@ -384,10 +384,10 @@ fn math_expr_prec(p: &mut Parser, min_prec: usize, stop: SyntaxKind) { 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::End, ast::Assoc::Left, 1)) diff --git a/tests/ref/math-attach-followed-by-func-call-complex.png b/tests/ref/math-attach-followed-by-func-call-complex.png new file mode 100644 index 0000000000000000000000000000000000000000..36de777dee460c269f339a7f820033be36e75f21 GIT binary patch literal 927 zcmV;Q17Q4#P)+6w`k#KNuot>TMij%9Wt9EvF zoSdA(!ot43zP-J@{r&yz?d|^e_?DKIsi~>3u(0s6x#^Xi`1tr|XJ=ksUj6d(?4zpb zlAHP9;`Y$f;&XlU%Fg3=f%)O&^To>6*4E|a<))^lo}QkNkdXZC?)cr`=ZTX1@$&re z@&Eh#-(+yxQD5njn(CIG_}bm+l$_>*jOBoe_t@L%k(q{uhM%9GqobqE&CTI#cjSDA z?WV2t$<26pc;@Ej&(F`8n3zvbPv__7rKP3khmhZ8ar5)@#Kgq$y1&)c)%MZV+uPgq z%g=Ffam>uj?(Xi&%F3Xip!fIp!NI}ig^tI^$9j5tLPA1$d3iZGIlR2Q>z$?Tr>@1t z#m2_Q@U*$&aeUL$)Bg7N=#G|ha&q_9+3)Y~X=!OzR#tp`d~0iKxVX5Ro11iWbgr(h z$jHdx;Na-!=%}cuhlhvq^78rl`KPC+_V)I+wzkyN)VjL5l9H0-rN~KcWF+UwQ_TY@$DJ~;5{wE8V@{0?>(v1jNW}_dkzJZ6WP82@AT+lNEn0|nAoReEp z1P%3w*qpVF4_sPZzQA{IX(yTE_y|6JU}zt3=mA!z0TU3HU~DBj3n$dpA;Ms`ZEcgB za&TxFjd~Koi)c+y$Q#_ij+Oxb3ELhgy>KiC4N8Fg3c$I%yu@?h@1OV<5`K-$Kn&vE zMZ>mvOm?_EZU}xEs~n%&0Yx9zi+F~(w=v-nvBNv^nwyodrvW+*j}5?~9>u{v*Nc=u z+{4hX|JyY>t%jq}K*{G6>y$DJlq*mzy-Ibj&H;~9PE5N6D(L_K002ovPDHLkV1iz< BAd&z8 literal 0 HcmV?d00001 diff --git a/tests/ref/math-attach-followed-by-func-call.png b/tests/ref/math-attach-followed-by-func-call.png index 71d78c16e784cc9ae84ae27a6ef0dc91318f8a44..096fb5d0091988c30a0068f5be2e8b5172aa3890 100644 GIT binary patch literal 2901 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 KMNUMnLSTZOn!Hm0 literal 9269 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 Xbc0CFfl~S{00000NkvXXu0mjfLJj=E diff --git a/tests/suite/math/accent.typ b/tests/suite/math/accent.typ index 0aef41e20..8ebfe7731 100644 --- a/tests/suite/math/accent.typ +++ b/tests/suite/math/accent.typ @@ -34,7 +34,7 @@ $tilde(sum), tilde(sum, size: #50%), accent(H, hat, size: #200%)$ --- math-accent-sized-script --- // Test accent size in script size. -$tilde(U, size: #1.1em), x^tilde(U, size: #1.1em), sscript(tilde(U, size: #1.1em))$ +$tilde(U, size: #1.1em), x^(tilde(U, size: #1.1em)), sscript(tilde(U, size: #1.1em))$ --- math-accent-dotless --- // Test dotless glyph variants. diff --git a/tests/suite/math/attach.typ b/tests/suite/math/attach.typ index 979018478..bac0417c5 100644 --- a/tests/suite/math/attach.typ +++ b/tests/suite/math/attach.typ @@ -42,9 +42,23 @@ attach(a, tl: u, t: t, tr: v, bl: x, b: b, br: y) $ --- math-attach-followed-by-func-call --- -// Test function call after subscript. -$pi_1(Y), a_f(x), a^zeta (x), a^abs(b)_sqrt(c) \ - a^subset.eq (x), a_(zeta(x)), pi_(1(Y)), a^(abs(b))_(sqrt(c))$ +// Test function call after subscripts and superscripts. +#set page(width: auto) +$a_1(x), a^10(x), a_f(x), a^zeta(x), a_"text"(x), + a_∂(x), a^cos(x), a_abs(x), a^root(2, x), a_subset.eq(x) \ + a_(1(x)), a^(10(x)), a_(f(x)), a^(zeta(x)), a_("text"(x)), + a_(∂(x)), a^(cos(x)), a_(abs(x)), a^(root(2, x)), a_(subset.eq(x))$ + +--- math-attach-followed-by-func-call-complex --- +// Test function call with named arguments after scripts. +#let cross = $c$ +$a_cancel(x, cross: #true)$ + +--- math-attach-followed-by-func-call-error --- +// Error: 14-19 unknown variable: cross +// Hint: 14-19 if you meant to display multiple letters as is, try adding spaces between each letter: `c r o s s` +// Hint: 14-19 or if you meant to display this as text, try placing it in quotes: `"cross"` +$a_cancel(x, cross: #true)$ --- math-attach-nested --- // Test associativity and scaling. diff --git a/tests/suite/text/raw.typ b/tests/suite/text/raw.typ index a7f58a8d0..849313566 100644 --- a/tests/suite/text/raw.typ +++ b/tests/suite/text/raw.typ @@ -215,7 +215,7 @@ box[] hello.world hello.world() hello.my.world() -f_zeta(x), f_zeta(x)/1 +f_(zeta(x)), f_(zeta(x))/1 emph(hello.my.world()) emph(hello.my().world) emph(hello.my().world()) From 53d13bae369ec3a186e2a7e3a340cb0032c48e1a Mon Sep 17 00:00:00 2001 From: mkorje Date: Wed, 25 Jun 2025 16:03:00 +1000 Subject: [PATCH 2/2] Add warning --- crates/typst-eval/src/math.rs | 20 +++++++++++++++--- ...h-attach-followed-by-func-call-warning.png | Bin 0 -> 630 bytes tests/suite/math/attach.typ | 18 ++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 tests/ref/math-attach-followed-by-func-call-warning.png diff --git a/crates/typst-eval/src/math.rs b/crates/typst-eval/src/math.rs index c2325a8c5..9712b2b81 100644 --- a/crates/typst-eval/src/math.rs +++ b/crates/typst-eval/src/math.rs @@ -1,5 +1,5 @@ use ecow::eco_format; -use typst_library::diag::{At, SourceResult}; +use typst_library::diag::{warning, At, SourceResult}; use typst_library::foundations::{Content, NativeElement, Symbol, SymbolElem, Value}; use typst_library::math::{ AlignPointElem, AttachElem, FracElem, LrElem, PrimesElem, RootElem, @@ -80,7 +80,14 @@ impl Eval for ast::MathAttach<'_> { let mut elem = AttachElem::new(base); if let Some(expr) = self.top() { - elem.t.set(Some(expr.eval_display(vm)?)); + let top = expr.eval(vm)?; + if let Value::Func(_) = top { + vm.engine.sink.warn(warning!( + expr.span(), "function literal used as superscript"; + hint: "wrap the entire function call in parentheses", + )); + } + elem.t.set(Some(top.display().spanned(self.span()))); } // Always attach primes in scripts style (not limits style), @@ -90,7 +97,14 @@ impl Eval for ast::MathAttach<'_> { } if let Some(expr) = self.bottom() { - elem.b.set(Some(expr.eval_display(vm)?)); + let bottom = expr.eval(vm)?; + if let Value::Func(_) = bottom { + vm.engine.sink.warn(warning!( + expr.span(), "function literal used as subscript"; + hint: "wrap the entire function call in parentheses", + )); + } + elem.b.set(Some(bottom.display().spanned(self.span()))); } Ok(elem.pack()) diff --git a/tests/ref/math-attach-followed-by-func-call-warning.png b/tests/ref/math-attach-followed-by-func-call-warning.png new file mode 100644 index 0000000000000000000000000000000000000000..1b05ef8416c0622a1e27af466852a540ffb28b55 GIT binary patch literal 630 zcmV-+0*U>JP)=GoMiZHmnfv=Z8J zp0&j0be*Nu38(DXIAhw{k9?|a2fWzs-r0rcz4@M(=Yh}7;r%w@Kb3@>2`;J$sk6i2lR=JfXhntueN%9qx!`u z5M)d|cN-);17L+yb7OTTKN)g#VgH4YEU*M*a~Plp2cpsW zQY+vEET$DNUf_wbP)@?pWj`*K6T4;MU*a+;bRUqRNWHczpgoxytig59AE+lirv`E- QM*si-07*qoM6N<$g2*-_xc~qF literal 0 HcmV?d00001 diff --git a/tests/suite/math/attach.typ b/tests/suite/math/attach.typ index bac0417c5..994355652 100644 --- a/tests/suite/math/attach.typ +++ b/tests/suite/math/attach.typ @@ -45,6 +45,10 @@ $ // Test function call after subscripts and superscripts. #set page(width: auto) $a_1(x), a^10(x), a_f(x), a^zeta(x), a_"text"(x), +// Warning: 22-25 function literal used as subscript +// Hint: 22-25 wrap the entire function call in parentheses +// Warning: 32-36 function literal used as superscript +// Hint: 32-36 wrap the entire function call in parentheses a_∂(x), a^cos(x), a_abs(x), a^root(2, x), a_subset.eq(x) \ a_(1(x)), a^(10(x)), a_(f(x)), a^(zeta(x)), a_("text"(x)), a_(∂(x)), a^(cos(x)), a_(abs(x)), a^(root(2, x)), a_(subset.eq(x))$ @@ -52,14 +56,28 @@ $a_1(x), a^10(x), a_f(x), a^zeta(x), a_"text"(x), --- math-attach-followed-by-func-call-complex --- // Test function call with named arguments after scripts. #let cross = $c$ +// Warning: 4-10 function literal used as subscript +// Hint: 4-10 wrap the entire function call in parentheses $a_cancel(x, cross: #true)$ --- math-attach-followed-by-func-call-error --- // Error: 14-19 unknown variable: cross // Hint: 14-19 if you meant to display multiple letters as is, try adding spaces between each letter: `c r o s s` // Hint: 14-19 or if you meant to display this as text, try placing it in quotes: `"cross"` +// Warning: 4-10 function literal used as subscript +// Hint: 4-10 wrap the entire function call in parentheses $a_cancel(x, cross: #true)$ +--- math-attach-followed-by-func-call-warning --- +// Test warning for function literal as subscripts and superscripts. +#let myfunc(arg) = $arg$ +// Warning: 4-10 function literal used as subscript +// Hint: 4-10 wrap the entire function call in parentheses +$a_myfunc(x) a_(myfunc(x))$ +// Warning: 4-10 function literal used as subscript +// Hint: 4-10 wrap the entire function call in parentheses +$a_myfunc a_(myfunc)$ + --- math-attach-nested --- // Test associativity and scaling. $ 1/(V^2^3^4^5),