1 \documentclass[10pt]{article}
9 \title{\EdiTeX: a MathML Editor Based on \TeX{} Syntax\\\small Description and Formal Specification}
10 \author{Paolo Marinelli\\Luca Padovani\\\small\{{\tt pmarinel},{\tt lpadovan}\}{\tt @cs.unibo.it}\\\small Department of Computer Science\\\small University of Bologna}
13 \newcommand{\EdiTeX}{Edi\TeX}
15 \newcommand{\tmap}[1]{\llbracket#1\rrbracket}
16 \newcommand{\tadvance}{\vartriangle}
17 \newcommand{\tnext}{\rhd}
18 \newcommand{\G}{\texttt{g}}
19 \newcommand{\PNODE}{\texttt{p}}
20 \newcommand{\SNODE}{\texttt{s}}
21 \newcommand{\INODE}{\texttt{i}}
22 \newcommand{\NNODE}{\texttt{n}}
23 \newcommand{\ONODE}{\texttt{o}}
24 \newcommand{\CNODE}{\texttt{c}}
25 \newcommand{\TABLE}{\texttt{table}}
26 \newcommand{\SP}{\texttt{sp}}
27 \newcommand{\SB}{\texttt{sb}}
28 \newcommand{\CELL}{\texttt{cell}}
29 \newcommand{\ROW}{\texttt{row}}
30 \newcommand{\SLDROP}{\blacktriangleleft}
31 \newcommand{\SLDSCRIPT}{\blacktriangleleft_{s}}
32 \newcommand{\NLDROP}{\vartriangleleft}
33 \newcommand{\RGROUP}{\vartriangleleft_{rg}}
34 \newcommand{\NLDGP}{\vartriangleleft_{g}}
35 \newcommand{\NLDSCRIPT}{\vartriangleleft_{s}}
36 \newcommand{\NLDMACRO}{\vartriangleleft_{c}}
37 \newcommand{\NLDTABLE}{\vartriangleleft_{t}}
43 \section{Introduction}
45 MathML~\cite{MathML1,MathML2,MathML2E} is an XML application for the
46 representation of mathematical expressions. As most XML applications,
47 MathML is unsuitable to be hand-written, except for the simplest
48 cases, because of its verbosity. In fact, the MathML specification
49 explicitly states that
51 ``While MathML is human-readable, it is anticipated that, in all but
52 the simplest cases, authors will use equation editors, conversion
53 programs, and other specialized software tools to generate MathML''
56 The statement about human readability of MathML is already too strong,
57 as the large number of mathematical symbols, operators, and
58 diacritical marks that are used in mathematical notation cause MathML
59 documents to make extensive use of Unicode characters that typically
60 are not in the ``visible'' range of common text editors. Such
61 characters may appear as entity references, whose name indicates
62 somehow the kind of symbol used, or character references or they are
63 directly encoded in the document encoding scheme (for instance,
66 It is thus obvious that authoring MathML documents assumes the
67 assistance of dedicated tools. As of today, such tools can be
68 classified into two main categories:
70 \item WYSIWYG (What You See Is What You Get) editors that allow the
71 author to see the formatted document on the screen as it is
73 \item conversion tools that generate MathML markup from different
74 sources, typically other markup languages for scientific
75 documents, such as \TeX.
78 While the former tools are certainly more appealing, especially to the
79 unexperienced user, as they give a direct visual feedback, the
80 existance of tools in the second category takes into account the large
81 availability of existing documents in \TeX{} format, and also the fact
82 that experienced or ``lazy'' users may continue to prefer the use of a
83 markup language other than MathML for editing, and generate MathML
84 only as a final step of the authoring process. The ``laziness'' is not
85 really intended as a way of being reluctant towards a new technology,
86 but rather as a justified convincement that WYSIWYG editors are ``nice
87 to look at'' but after all they may slow down the authoring process.
88 WYSIWYG editors often involve the use of menus, palettes of symbols,
89 and, in general, an extensive use of the pointing device (the mouse)
90 for completing most operations. The use of shortcuts is of little
91 help, as it implies very soon a challenging exercise for the fingers
92 and the mind. Moreover, authors \emph{cannot improve} their authoring
93 speed with time. On the other side, the gap between the syntax of any
94 markup language for mathematics and mathematical notation may be
95 relevant, especially for large, non-trivial formulas and authoring is
96 a re-iterated process in which the author repeadtedly types the markup
97 in the editor, compiles, and looks at the result inside a pre-viewer.
99 \EdiTeX{} tries to synthesize the ``best of both worlds'' in a single
100 tool. The basic idea is that of creating a WYSIWYG editor in which
101 editing is achieved by typing \TeX{} markup as the author would do in
102 a text editor. The \TeX{} markup is tokenized and parsed on-the-fly
103 and a corresponding MathML representation is created and
104 displayed. This way, the author can see the rendered document as it
105 changes. The advantages of this approach can be summarized as follows:
107 \item the document is rendered concurrently with the editing, the
108 user has an immediate feedback hence it is easier to spot errors;
109 \item the author types in a concrete (and likely familiar) syntax
110 improving the editing speed;
111 \item the usual WYSIWYG mechanisms are still available. In
112 particular, it is possible to select \emph{visually} a fragment of
113 the document that needs re-editing, or that was left behind for
117 \paragraph{The Name of the Game:} there is no reference to MathML in
118 the name ``\EdiTeX.'' In fact, the architecture of the editor is not
119 tied to MathML markup. Although we focus on MathML editing, by
120 changing a completely modularized component of the editor it is
121 virtually possible to generate any other markup language.
123 \paragraph{Acknowledgments.} Stephen M. Watt and Igor Rodionov for
124 their work on the \TeX{} to MathML conversion tool; Stan Devitt for an
125 illuminating discussion about the architecture of \TeX{} to XML
126 conversion tools; Claudio Sacerdoti Coen for the valuable feedback and
127 uncountable bug reports.
129 \section{Architecture}
131 \section{Customization}
133 \subsection{Short and Long Identifiers}
135 \subsection{The Dictionary}
137 \subsection{Stylesheets and Trasformations}
139 \subsection{Rendering}
141 \section{XML Representation of \TeX{} Markup}
145 The following tokens are defined:
147 \begin{tabular}{lllp{0.5\textwidth}}
148 \textbf{\TeX{}} & \textbf{Notation} & \textbf{Node} & \textbf{Description} \\
150 \verb+{+ & $\mathrm{begin}$ & \texttt{g} & Beginning of a group \\
151 \verb+}+ & $\mathrm{end}$ & & End of a group \\
152 \verb+$+ & $\$$ & \texttt{math} & Math shift \\ %$ \\
154 \verb+#+$i$ & $p(i)$ & \texttt{p} & Parameter \\
155 \verb+^+ & $\uparrow$ & \texttt{sp} & Superscript \\
156 \verb+_+ & $\downarrow$ & \texttt{sb} & Subscript \\
157 & $\square$ & & Space-like character that can be ignored \\
158 & $s$ & \texttt{s} & Space-like character that may be significant \\
159 letter & $i(v)$ & \texttt{i} & Identifier $v$ \\
160 digit & $n(v)$ & \texttt{n} & Number $v$ \\
161 other & $o(v)$ & \texttt{o} & Other character or operator $v$ \\
162 \verb+~+ & $\sim$ & & Active character \\
163 \verb+%+ & $\%$ & & Comment \\
164 control & $c(v)\langle\alpha_1,\dots,\alpha_n\rangle$ & \texttt{c} &
165 Control sequence $v$ that expects the $\alpha_1,\dots,\alpha_n$ sequence of tokens. \\
166 backspace & $\vartriangleleft$ & & \\
167 backspace & $\blacktriangleleft$ & & \\
170 %% Some tokens are mapped directly into nodes of the TML tree. The following functions shows
173 \begin{tabular}{r@{\quad$=$\quad}l}
174 $\tmap{\{}$ & \verb+g+ \\
175 $\tmap{p(i)}$ & \verb+p[@index=+$i$\verb+]+ \\
176 $\tmap{p_l(i)}$ & \verb+p[@index=+$i$\verb+][@left-open='1']+ \\
177 $\tmap{p_r(i)}$ & \verb+p[@index=+$i$\verb+][@right-open='1']+ \\
178 $\tmap{s}$ & \verb+s+ \\
179 $\tmap{\uparrow}$ & \verb+sp+ \\
180 $\tmap{\downarrow}$ & \verb+sb+ \\
181 $\tmap{i(v)}$ & \verb+i[@value=+$v$\verb+]+ \\
182 $\tmap{n(v)}$ & \verb+n[@value=+$v$\verb+]+ \\
183 $\tmap{o(v)}$ & \verb+o[@value=+$v$\verb+]+ \\
184 $\tmap{c(v)\langle\alpha_1,\dots,\alpha_n\rangle}$ & \verb+c[@name=+$v$\verb+][^+$\tmap{\alpha_1}\cdots\tmap{\alpha_n}$\verb+$]+\\
188 %% \section{Description and Semantics of the Pattern Language}
191 %% \mathit{NodeTest} & ::= & \mathtt{*} \\
192 %% & | & \mathit{ElementType} \\
193 %% & | & \mathtt{<}~\mathit{ElementTypePattern}~\mathtt{>} \\[1ex]
194 %% \mathit{ElementTypePattern} & ::= & \mathtt{*} \\
195 %% & | & \mathit{ElementType}~(\mathtt{|}~\mathit{ElementType})^* \\
196 %% & | & \mathtt{!}\mathit{ElementType}~(\mathtt{|}~\mathit{ElementType})^*\\[1ex]
197 %% \mathit{NodePattern} & ::= & \mathit{NodeTest}~\mathit{AttributeQualifier}^*\\[1ex]
198 %% \mathit{AttributeQualifier} & ::= & \mathtt{[@}\mathit{AttributeTest}\mathtt{]}\\
199 %% & | & \mathtt{[!@}\mathit{AttributeTest}\mathtt{]}\\[1ex]
200 %% \mathit{AttributeTest} & ::= & \mathit{AttributeName} \\
201 %% & | & \mathit{AttributeName}\mathtt{='}\mathit{Text}\mathtt{'}
204 \section{Insert Rules}
206 \paragraph{Begin Group:} $\{$
209 \item{\verb+table/cursor+}\\
210 create a \texttt{row} node, create a \texttt{cell} node, create a \texttt{g} node,
211 append the cursor to the \texttt{g} node, append the \texttt{g} node to the \texttt{cell} node,
212 append the \texttt{cell} node to the \texttt{row} node, append the \texttt{row} node to the
214 \item{\verb+cursor+} \\ create a \texttt{g} node, replace the cursor with the new \texttt{g} node,
215 append the cursor to the new \texttt{g} node
218 % CASE: c/g[!@id]/cursor
225 % CASE: c[@table='1']/cursor
227 % create a g node with id, replace the cursor with the fresh g and append
228 % the cursor as only child of it
230 \paragraph{End Group:} $\}$
233 \item{\verb+g[@id]/cursor+}\\
234 remove the cursor, put $\tadvance$ after the \texttt{g} node
235 \item{\verb+row/cell/g/cursor+}\\
236 remove the cursor, put $\tadvance$ after the \texttt{row} node
237 \item{\verb+math/g[!@id]/cursor+}\\
239 \item{\verb+cursor+}\\
243 \paragraph{Math Shift:} $\$$
246 \item{\verb+tex/cursor+}\\
247 create a \texttt{math} node, create a \texttt{g} node, append the \texttt{g} node
248 as child of the \texttt{math} node, append the cursor as child of the \texttt{g} node
249 \item{\verb+math[@display='1']/g[!@id][*#]/cursor+}\\
250 append the cursor as last child of the \texttt{math} node
251 \item{\verb+math/g[!@id][*#]/cursor+}\\
253 \item{\verb+math[!display='1']/g[!@id]/cursor+}\\
254 set \verb+display='1'+ in the \texttt{math} node
255 \item{\verb+math/g[!@id]+}\\
256 append the cursor after the \texttt{math} node
257 \item{\verb+math/cursor+}\\
259 \item{\verb+cursor+} \\
265 % create a math node. create a g node. append g as child of math.
266 % append the cursor as child of g
267 % CASE: math[@display='1']/g[!@id][*#]/cursor
268 % append the cursor as last child of math
269 % CASE: math/g[!@id][*#]/cursor
270 % remove the cursor. Editing is done
271 % CASE: math[!display='1']/g[!@id]/cursor
272 % set the display attribute to '1'
274 % append the cursor after math (?)
276 % remove the cursor. Editing is done
280 \paragraph{Align:} $\&$
283 \item{\verb+g[@id]/cursor+}\\
284 create a \texttt{row} node, create a \texttt{cell} node, create a \texttt{g} node,
285 append the cursor to the new \texttt{g} node, append the \texttt{cell} node to the
286 the \texttt{row} node ?
287 \item{\verb+row/cell/g/cursor+}\\
288 create the \texttt{g} node, create the \texttt{cell} node, append the cursor
289 as child of the new \texttt{g} node, append the new \texttt{g} node to the new
290 \texttt{cell} node after the old \texttt{cell} node
291 \item{\verb+cursor+}\\
296 % CASE: g[@id]/cursor
297 % create a row node. create a cell node. create a g node. append the
298 % cursor to g, append the g to cell, append the cell to row, ???
299 % CASE: row/cell/g/cursor
300 % create a g node. create a cell node. appent the cursor to g,
301 % append the g to cell, insert the new cell after the existing cell
305 \paragraph{End-of-line:}
310 \paragraph{Parameter:} $p(i)$
314 \paragraph{Superscript:} $\uparrow$
317 \item{\verb+<g|p>[^#]/cursor+}\\
318 create a \SP{} node, create a \G{} node, replace the cursor with the \SP{} node,
319 append the \G{} node as first child of the \SP{} node, append the cursor as last
320 child of the \SP{} node
321 \item{\verb+<g|p>[*#]/cursor+}\\
322 create a \SP{} node, replace \texttt{*} with the \SP{} node, append \texttt{*} to
323 the \SP{} node, append cursor to the \SP{} node
324 \item{\verb+sp[^*#$][!@over='1']/cursor+}\\ %$
325 set \verb+over='1'+ in the \SP{} node
326 \item{\verb+sp[^*#$][@over='1']/cursor+}\\ %$
328 \item{\verb+cursor+}\\
333 % create sp node. create g node, replace cursor with sp, append g to sp, append cursor to sp
335 % create sp node, replace * with sp, append * to sp, append cursor to sp
336 % CASE: sp[^*#$][!@over='1']/cursor
337 % set over='1' in sp node
338 % CASE: sp[^*#$][@over='1']/cursor
343 \paragraph{Subscript:} $\downarrow$
346 \item{\verb+<g|p>[^#]/cursor+}\\
347 create a \SB{} node, create a \G{} node, replace the cursor with the \SB{} node,
348 append the \G{} node as first child of the \SB{} node, append the cursor as last
349 child of the \SB{} node
350 \item{\verb+<g|p>[*#]/cursor+}\\
351 create a \SB{} node, replace \texttt{*} with the \SB{} node, append \texttt{*} to
352 the \SB{} node, append cursor to the \SB{} node
353 \item{\verb+sb[^*#$][!@under='1']/cursor+}\\ %$
354 set \verb+under='1'+ in the \SB{} node
355 \item{\verb+sb[^*#$][@under='1']/cursor+}\\ %$
357 \item{\verb+cursor+}\\
362 % create sb node. create g node, replace cursor with sb, append g to sb, append cursor to sb
364 % create sb node, replace * with sb, append * to sb, append cursor to sb
365 % CASE: sb[^*#$][!@under='1']/cursor
366 % set over='1' in sb node
367 % CASE: sb[^*#$][@under='1']/cursor
372 \paragraph{Ignorable space:} $\square$
374 % do_ignorable_space:
377 \paragraph{Space:} $s$
380 \item{\verb+cursor+}\\
381 create \SNODE{} node, replace cursor with the \SNODE{} node, append
382 $\tadvance$ after \SNODE{} node
386 % create s node, replace cursor with s, append \advance after s
388 \paragraph{Identifier:} $i(v)$
391 \item{\verb+cursor+}\\
392 create an \INODE{}, set \verb+value=+$v$ in the \INODE{}, replace
393 cursor with \INODE{}, append $\tadvance$ after the \INODE{} node
397 % create i node, replace cursor with i, append \advance after i
399 \paragraph{Number:} $n(v)$
402 \item{\verb+cursor+}\\
403 create an \NNODE{}, set \verb+value=+$v$ in the \NNODE{}, replace
404 cursor with \NNODE{}, append $\tadvance$ after the \NNODE{} node
408 % create n node, replace cursor with n, append \advance after n
410 \paragraph{Apostrophe:} $o({}')$
413 \item{\verb+<g/p>[(sp[*#$]/g[o[@name='prime']$])#]/cursor+}\\
414 create a \ONODE{} node, set \verb+name='prime'+ in the \ONODE{},
415 append the \ONODE{} to the innermost \G{} node
416 \item{\verb+<g|p>[(sb[^sp[^*#$]/g[o[@name='prime']]$])#]/cursor+}\\
417 create a \ONODE{} node, set \verb+name='prime'+ in the \ONODE{},
418 append the \ONODE{} to the innermost \G{} node
419 \item{\verb+<g|p>[*#]/cursor+}\\
420 create a \ONODE{} node, set \verb+name='prime'+ in the \ONODE{},
421 create a \SP{} node, create a \G{} node, replace \texttt{*} with \SP{} node,
422 append the new \G{} node to the \SP{} node, append the \ONODE{}
423 node to the new \G{} node
424 \item{\verb+<g|p>[^#]/cursor+}\\
426 \item{\verb+cursor+}\\
427 cursor is not in a group, error?
431 % CASE: g[(sp[^*#$]/g[o[@name='prime']$])#]/cursor
432 % append a new o[@name='prime'] node to the inner g node
433 % CASE: g[(sb[^sp[^*#$]/g[o[@name='prime']]$])#]/cursor
434 % append a new o[@name='prime'] node to the inner g node
436 % create sp node, create g node, replace * with sp, append * to sp, append g to sp,
437 % append a new o[@name='prime'[ node to the new g node
441 % cursor is not in a group, error?
443 \paragraph{Other:} $o(v)$
445 create an \ONODE{}, set \verb+value=+$v$ in the \ONODE{}, replace
446 cursor with \ONODE{}, append $\tadvance$ after the \ONODE{} node
449 % create o node, replace cursor with o, append \advance after o
451 \paragraph{Active:} $\sim$
456 \paragraph{Comment:} $\%$
461 \paragraph{Begin Environment:} $c(\mathtt{begin})\langle\alpha_1,\dots,\alpha_n\rangle$
463 \paragraph{End Environment:} $c(\mathtt{end})\langle\rangle$
465 \paragraph{Left Delimiter:} $c(\mathtt{left})\langle\alpha\rangle$
467 \paragraph{Right Delimiter:} $c(\mathtt{right})\langle\alpha\rangle$
469 \paragraph{Carriage-Return:} $c(\mathtt{cr})\langle\rangle$
472 \item{\verb+row/cell/g/cursor+}\\
473 create a \ROW{} node, create a \CELL{} node, create a \G{}
474 node, append the cursor to the new \G{} node, append the new \G{}
475 node to the new \CELL{} node, append the new \CELL{} node to the
476 new \ROW{} node, insert the new \ROW{} node after the old \ROW{} node
477 \item{\verb+cursor+}\\
482 % CASE: row/cell/g/cursor
483 % create row node, create cell node, create g node,
484 % append cursor to g, append g to cell, append cell to row,
485 % insert new row after old row
489 \paragraph{Macro:} $c(v)\langle\alpha_1,\dots,\alpha_n\rangle$
492 \item{\verb+<p|g>/cursor+}\\
493 create a \CNODE{} node with the children corresponding to the pattern
494 $\tmap{\alpha_1}$,\dots,$\tmap{\alpha_n}$, replace the cursor with
495 the new \CNODE{} node. put $\tnext$ as the first child of the new
498 \item{\verb+*/cursor+}\\
499 create a \CNODE{} node with the children corresponding to the pattern
500 $\tmap{\alpha_1}$,\dots,$\tmap{\alpha_n}$, replace the cursor with
501 the new \CNODE{} node, put $\tnext$ as the first child of the new
502 \CNODE{} node. If $n\ne0$ emit a warning (the macro has arguments but
503 but the context wouldn't normally allow them to be entered)
508 % create a c node with children corresponding to the pattern of the macro
509 % append \nextparam as first child of the macro
511 \section{Left Drop Rules}
513 \paragraph{Normal Left Drop:} $\NLDROP$
517 \item{\verb+cursor+}\\
518 replace the cursor with the $\NLDROP$.
522 \paragraph{Special Left Drop:} $\SLDROP$
526 \item{\verb+cursor+}\\
527 replace the cursor with the $\SLDROP$.
531 \section{Right Drop Rules}
533 \section{$\varepsilon$-rules}
535 \paragraph{Nromal Left Drop}
539 %**************************************************************************************
540 %****************************** epsilon-rules with \NLDROP ****************************
541 %**************************************************************************************
543 %************** \NLDROP has neither preceding nor following nodes ********************
545 \item{\verb+math[^#$]/+$\NLDROP$}\\
546 replace the $\NLDROP$ with the cursor.
548 \item{\verb+g[^#$]/+$\NLDROP$}\\
549 replace the \G{} node with the $\NLDROP$.
551 % this rule overrides the one above
552 \item{\verb+math/g[^#$]/+$\NLDROP$}\\
553 replace the $\NLDROP$ with the cursor.
555 % this rule is overridden by the two ones below
556 \item{\verb+c/p[^#$]/+$\NLDROP$}\\
557 remove the $\NLDROP$ and insert it before the \PNODE{} node.
559 \item{\verb+c[p[@left-open='1'][*]#$]/p[@right-open='1'][^#$]/+$\NLDROP$}\\
560 replace the \CNODE{} node with the content of the first \PNODE{} node and insert the $\NLDROP$ after this content
562 \item{\verb+c[p[@left-open='1'][!*]#$]/p[@right-open='1'][^#$]/+$\NLDROP$}\\
563 replace the \CNODE{} node with the $\NLDROP$.
565 \item{\verb+c[^#][!p(*)]/+$\NLDROP$}\\
566 replace the \CNODE{} node with the $\NLDROP$.
568 \item{\verb+cell[^#$]/+$\NLDROP$}\\
569 replace the cell with the $\NLDROP_n$.
571 \item{\verb+table[^#$]/+$\NLDROP$}\\
572 replace the \TABLE{} node with the $\NLDROP$.
574 %************************* \NLDROP has at least one preceding node *********************
578 % this rule should also handles the case where the \NLDROP is the third (and last) child of a script.
579 \item{\verb+*[*#]/+$\NLDROP$}\\
580 remove the $\NLDROP$ and append it as the last child of its ex preceding brother.
582 % this rule overrides the one above
583 \item{\verb+*[(i|n|o|s|c[!*])#]/+$\NLDROP$}\\
584 remove the $\NLDROP$ and replace the token with the $\NLDROP_n$.
588 \item{\verb+<sp|sb>[^*#$]+/$\NLDROP$}\\
589 replace the script node with its first child and insert the $\NLDROP$ after it.
591 % this rule overrides the one above.
592 \item{\verb+<sp|sb>[^g[!@id][!*]#$]/+$\NLDROP$}\\
593 replace the script with the cursor.
595 % this rule overrides the one above
596 \item{\verb+*[sp[!@id][^*g[!@id][^o[@name='prime']++\verb+o[@name='prime']$]]#]/+$\NLDROP$}\\
597 remove the last \ONODE{} node and replace the $\NLDROP$ with the cursor.%$\NLDROP_n$.
599 \item{\verb+*[sp[!@id][^*g[!@id][^o[@name='prime']$]]#]/+$\NLDROP$}\\
600 replace the script with its first child and replace the $\NLDROP$ with the cursor.%$\NLDROP_n$.
602 \item{\verb+c[(i|n|o|s|c[!*])#]/+$\NLDROP$}\\
603 move the $\NLDROP$ before the delimiter.
605 % this rule is true for both right-open and parameterized macros.
606 \item{\verb+c[p#]/+$\NLDROP$}\\
607 move the $\NLDROP$ into the \PNODE{} node.
609 %**************** \NLDROP has no preceding nodes, but has following nodes **************
612 \item{\verb+*[^#*]/+$\NLDROP$}\\
613 remove the $\NLDROP$ and insert it before its parent.
617 \item{\verb+math/g[^#*]/+$\NLDROP$}\\
618 replace the $\NLDROP$ with the cursor.
620 % this rule is applicable to all macros.
621 \item{\verb+c[^#][p[*]]/+$\NLDROP$}\\
622 remove the $\NLDROP$ and insert it before the \CNODE{} node.
626 \paragraph{Special Left Drop}
630 %********************************************************************************************************
631 %************************************ epsilon-rules with \SLDROP ****************************************
632 %********************************************************************************************************
634 \item{\verb+math/+$\SLDROP$}\\
635 replace the $\SLDROP$ with the cursor.
637 %************************ \SLDROP has neither preceding nor following nodes *****************************
639 % this rule overrides the one below
640 \item{\verb+math/g[^#$]/+$\SLDROP$}\\
641 replace the $\SLDROP$ with the cursor.
643 \item{\verb+g[^#$]/+$\SLDROP$}\\
644 replace the \G{} node with the cursor.
646 \item{\verb+c[p[@left-open='1'][*]#$]/p[@right-open='1'][^#$]/+$\SLDROP$}\\
647 replace the \CNODE{} node with the content of the first \PNODE{} node and insert the cursor after this content
649 \item{\verb+c[p[@left-open='1'][!*]#$]/p[@right-open='1'][^#$]/+$\SLDROP$}\\
650 replace the \CNODE{} node with the cursor.
652 \item{\verb+c/p[^#$]/+$\SLDROP$}\\
653 remove the $\SLDROP$ and insert it before the \PNODE{} node.
655 \item{\verb+c[^#][!p(*)]/+$\SLDROP$}\\
656 replace the \CNODE{} node with the cursor.
658 \item{\verb+cell[^#$]/+$\SLDROP$}\\
659 replace the cell with the $\NLDROP_n$.
661 \item{\verb+table[^#$]/+$\SLDROP$}\\
662 replace the \TABLE{} node with the cursor.
664 %*********************** \SLDROP has at least one preceding node ***********************************
666 \item{\verb+*[sp[!@id][^*g[!@id][^o[@name='prime']++\verb+o[@name='prime']$]]#]/+$\SLDROP$}\\
667 remove the last \ONODE{} node and replace the $\SLDROP$ with the cursor.
669 \item{\verb+*[sp[!@id][^*g[!@id][^o[@name='prime']$]]#]/+$\SLDROP$}\\
670 replace the script with its first child and replace the $\SLDROP$ with the cursor.%$\NLDROP_n$.
672 \item{\verb+<sp|sb>[^g[!@id][!*]#$]/+$\SLDROP$}\\
673 replace the script with the cursor.
675 % this rule is overridden by the three rules above.
676 \item{\verb+<sp|sb>[^*#$]+/$\SLDROP$}\\
677 replace the script node with its first child and insert the cursor after it.
679 \item{\verb+c[(i|n|o|s|c[!*])#]/+$\SLDROP$}\\
680 remove the $\SLDROP$ and insert the cursor before the delimiter.
682 \item{\verb+c[p#(i|n|o|s|c[!*])]/+$\SLDROP$}\\
683 remove the $\SLDROP$ and insert the cursor into the \PNODE{} node.
685 \item{\verb+c[p[@right-open='1']#]+}\\
686 remove the $\SLDROP$ and append the curor as last child of the \PNODE{} node.
688 % this rule is overridden by the two ones above.
689 \item{\verb+c[p#]/+$\SLDROP$}\\
690 move the $\SLDROP$ into the \PNODE{} node.
692 \item{\verb+*[(i|n|o|s|c[!*])#]/+$\SLDROP$}\\
693 remove the $\SLDROP$ and replace the token with the cursor.
695 \item{\verb+*[table#]/$\SLDROP$+}\\
696 remove the $\SLDROP$ and append the $\NLDROP_n$ as the last child of the \TABLE{} node.
698 \item{\verb+*[c#]/+$\SLDROP$}\\
699 move the $\SLDROP$ into the \CNODE{} node.
701 \item{\verb+*[g#]/+$\SLDROP$}\\
702 remove the $\SLDROP$ and append the cursor as the last child of the \G{} node.
704 %********** \SLDROP has no preceding node, but has following ones **************
706 \item{\verb+math/g[^#*]/+$\SLDROP$}\\
707 replace the $\SLDROP$ with the cursor.
709 \item{\verb+c[^#p][p(*)]/+$\SLDROP$}\\
710 remove the $\SLDROP$ and insert the cursor before the \CNODE{} node.
713 \item{\verb+*[^#*]/+$\SLDROP$}\\
714 remove the $\SLDROP$ and insert the cursor before its parent.
718 \paragraph{Normalize Left Drop}
722 %****************************************************************************************
723 %***************************** epsilon-rules with \NLDROP_n *****************************
724 %****************************************************************************************
726 \item{\verb+*[*#]/+$\NLDROP_n$}\\
727 replace the $\NLDROP_n$ with the cursor.
729 \item{\verb+row[cell#]/+$\NLDROP_n$}\\
730 remove the $\NLDROP_n$ and append the cursor as the last child of the \CELL{} node.
732 \item{\verb+row[^#$]/+$\NLDROP_n$}\\
733 replace the \ROW{} node with the $\NLDROP_n$
735 \item{\verb+table[row#]/+$\NLDROP_n$}\\
736 remove the $\NLDROP_n$ and append it as last child of the \ROW{} node.
738 \item{\verb+table[^#$]/+$\NLDROP_n$}\\
739 replace the \TABLE{} with the cursor.%$\NLDROP_n$.
741 \item{\verb+g[@id][^#$]/+$\NLDROP_n$}\\
742 replace the \G{} node with the $\NLDROP_n$.
749 \item{\verb+g/+$\tadvance$}\\
750 replace $\tadvance$ with the cursor
752 \item{\verb+p[#$]/+$\tadvance$}\\ %$
753 put $\tadvance$ after the \PNODE{} node
755 \item{\verb+c[#p]/+$\tadvance$} \\
756 remove $\tadvance$, put the cursor as first child of the \PNODE{} node
758 \item{\verb+c[#*]/+$\tadvance$} \\ %$
759 replace $\tadvance$ with the cursor
761 \item{\verb+c[#$]/+$\tadvance$} \\ %$
762 move $\tadvance$ after the \CNODE{} node
765 \paragraph{Next Parameter}
767 \paragraph{Next Token}
769 %% \begin{description}
770 %% \item{\verb+c[#p]/+$\tnext$} \\
773 % g[@id]/(c[#$][@right-open]/g[!@id][#$]/)+cursor } let p = cursor.parent() in remove; advance(p)
777 % */cursor { let g = new group in replace
779 % g[@id][^#$]/cursor <= cursor.parent().replace(cursor)
780 % g[@id][^#$]/cursor <- cursor
781 % (!g[@id][^#$])[A#B]/(g[@id][^#$]/)+cursor <- (!g[@id][^#$])[A#B]/cursor