Closed
Conversation
By inlining the enumeration index, we can avoid the O(n) `nth()` calls.
Collaborator
Author
|
Closing based on the discussion in the forum |
isuffix
added a commit
to isuffix/typst
that referenced
this pull request
Oct 6, 2025
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is an accompanying PR to my blog post at https://isuffix.com/runtime-math-parsing arguing that we should revert #6442 and use runtime parsing for Typst's math syntax. The blog post argues why, while this description discusses the implementation.
Also, since this is my first PR as @isuffix, I'll mention that I've changed my account over from @wrzian so that I can use isuffix as a consistent username around the internet. Hi!
As usual for my PRs, this is best reviewed commit-by-commit.
(1,2) Two independent commits
The first two commits are used by the later changes, but would likely be useful outside of this PR. However, they're small enough that I didn't want to separate out two other PRs for them. If you would prefer them as separate PRs, let me know and I can split those out.
The first commit turns a potentially$O(n)$ runtime in the sibling node calculation to $O(1)$ .
The second commit simplifies
MathPrimesby removing the unnecessaryPrimeSyntaxKind, and also adds a newBangkind for passing info about exclamation points in math mode from the lexer to the current parser. However, theBangkind should never be observeable outside the parser in the normal math parsing.(3) Adding tests
The third commit adds tests that pass with the existing code. These are modified alongside other tests in the next commits as the runtime parser is implemented.
(4) AST Preparation
This commit updates the existing lexer, parser, and AST to output a flat list of math tokens when the
MATH_RUNTIMEboolean is set totrue(but leaves itfalse). Instead of theMathSyntaxKind, we now output aMathTokensSyntaxKind. This also adds new SyntaxKinds for opening and closing delimiters,MathOpeningandMathClosing, so that the AST can avoid extra analysis of token characters. Andast.rshas plenty of comments for the new ast structs/enums.I also updated the highlighter to ensure tokens are highlighted as before when
MATH_RUNTIMEis true. This is tested by theraw-highlight-typm-extratest from the previous commit.(5) Implementation
This commit toggles
MATH_RUNTIMEtotrue, implements the runtime parser intypst-eval/src/math_parser/{mod, parser, tokens}.rs, updates many tests with new error messages or results.The
math_parser/parser.rsandmath_parser/tokens.rsfiles are heavily commented, and should be the main part of this review. I've iterated on these files a ton, but I'm still open to feedback and changes. And I'm certain that I've become blind to a bunch of possible simplifications or helpful renamings since I've been writing this for a while, so I'm excited to see what you think of the interface!This PR does not lex math shorthands at runtime, but has been designed so that lexing shorthands at runtime (and adding runtime configuration of shorthands) should be straightforward if desired in the future.
This commit also changes the test runner at
tests/src/run.rsto not fail tests when error ranges differ. This avoids a lot of noise when checking tests and is reverted in theSpanPluscommit.(6) Fix deparenthesizing fractions
Three tests were added to
skip.txtin the previous commit because they involved the new fraction variants and require deparenthesizing logic. This commit is a simple hacking to get the necessary information in the right spots to make the fraction variants work with deparenthesizing.My original work on this PR was largely before the new fraction variants were added, so it was more natural to leave this as a separate commit.
The reason I still have this split out from the overall implementation is to highlight these changes and, because I think there's likely a better design for fraction deparenthesizing if we do go with runtime math parsing.
(7) Add
SpanPlusto diagnosticsThis adds the
SpanPlusconcept and wires it up in the runtime parser so that we can have accurate error ranges despite the math tokens being a flat list. Most of the implementation is making sure that users ofSourceDiagnosticuse the correct range. This had a surprisingly long tail of changes that led to a series of tricky compiler errors, but I believe the implementation is now correct.I was not bold enough to add this concept to spans themselves, as that would have a much higher implementation/performance cost at relatively little gain. This means that spanned values may still only use their initial span, causing some error messages to be worse.
You can see some worse error ranges in
math-{cases,mat,vec}-linebreaksandmath-call-named-single-char-error. However some errors now have better ranges, such asmath-call-unclosed-funcandmath-call-spread-multiple-exprs(8) Fix IDE tests
I kept this commit separate to highlight that the VM tracing is solely for autocompletion support. This is a part of the compiler I'm not confident in, so I've left a TODO comment since I'm unsure if tracing should happen in those locations or elsewhere. Feedback is appreciated :)
(9) Purge
The final commit, purging the existing math parser, isn't actually present yet. And won't be needed until the final direction is chosen, so I've declined to implement it for now as it would consistently conflict with changes made to previous commits making rebasing a hassle.
However an initial attempt shows that it would delete roughly 800 lines, leading this PR to be somewhere around +1800, -800, or roughly 1000 new lines of code to implement runtime parsing. I'm overall pretty happy with this number, especially since more than 10% of the new lines are descriptive comments.