stefnotch / aftermath-editor

A WYSIWYG mathematics editor that understands your formulas!
https://stefnotch.github.io/aftermath-editor
MIT License
13 stars 0 forks source link

Parsing and syntax highlighted rendering #20

Closed stefnotch closed 1 year ago

stefnotch commented 1 year ago

Parsing MathLayout and giving me another tree (and not directly MathJson, because I can't always parse everything)

And the closely related task:

Notice that selections and the caret are explicitly something different. I don't want to repeatedly rerender the formula every time I move the caret.

Semantic annotations

Should have a clear mapping back to the MathLayout (well, specifically the rows and offsets - with caret navigation, one can reach every offset)

Non-semantic annotations

Should follow the MathLayout tree. Should never have overlapping ranges (but smaller ranges inside larger ranges is fine). Multiple nested equally large ranges is also fine, like "annotation border > annotation blue background > annotation padding > actual math formula".

Annotation example

<math display="block">
            <mover>
              <mrow>
                <mi>x</mi>
                <mo>+</mo>
                <mo>...</mo>
                <mo>+</mo>
                <mi>x</mi>
              </mrow>
              <mover>
                <mo>⏞</mo>
                <mrow>
                  <mi>k</mi>
                  <mspace width="0.1111111111111111em"></mspace>
                  <mtext>times</mtext>
                </mrow>
              </mover>
            </mover>
          </math>

Open question: Writing 123.45 and then highlighting (aka adding an annotation) to .45 should be possible. Do I slap that into the rendered mathml, and if so, how?

Special annotations

stefnotch commented 1 year ago

Since passing a tree-like structure to a parser doesn't seem to work out, we'll opt for the "Copium" option and will settle with "parsing every row separately".

Though, when parsing a row, and then encountering an element (like a under), we do get to choose which parser to call. In some contexts, it makes sense to use a parser that knows what a lim is, in other contexts, it doesn't.

stefnotch commented 1 year ago

Also interesting https://www.brics.dk/metafront/metafront.pdf

stefnotch commented 1 year ago

Parsing tasks

stefnotch commented 1 year ago

Greedy parser for multi-character symbols

Would a greedy parsing approach work well enough for all special constructs? Like, I encounter a symbol, so I call all possible parsers for that, and then take the longest result.

That greedy parser gets used to get the next token, and then a pratt parser is used for the standard operator precedence, associativity, etc.

e.g.

Optimisation

For the greedy parsing, we introduce the concept of a "token hash". We then construct a trie like

// TODO: Immutable variant of this, aka a HAMT
/**
 * This trie takes you to an approximate position, however there might be multiple definitions with overlapping token-hashes.
 * So once we've found something, we need to check all MathDefinition.tokens again, to make sure they're exact matches.
 * Nested tokens are flattened for the purposes of checking the hashes 
 */
struct Trie {
  values: Vec<TokenDefinition>, // Token definitions plus an actual parser to go with them
  children: Map<Hash, Trie>, // if the next token has an appropriate hash, then we go down the trie
}
stefnotch commented 1 year ago

\ could act as escape character for

stefnotch commented 1 year ago

https://levelup.gitconnected.com/writing-a-custom-typescript-ast-transformer-731e2b0b66e6 maybe

stefnotch commented 1 year ago

Recursive renderer: Takes a slice of mathelements, and a single mathsemantic, and returns an array of mathml dom nodes

Even better: Virtual DOM

stefnotch commented 1 year ago

Okay, this has been split into future issues