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{\NLDROP}{\vartriangleleft}
37 \section{Introduction}
39 MathML~\cite{MathML1,MathML2,MathML2E} is an XML application for the
40 representation of mathematical expressions. As most XML applications,
41 MathML is unsuitable to be hand-written, except for the simplest
42 cases, because of its verbosity. In fact, the MathML specification
43 explicitly states that
45 ``While MathML is human-readable, it is anticipated that, in all but
46 the simplest cases, authors will use equation editors, conversion
47 programs, and other specialized software tools to generate MathML''
50 The statement about human readability of MathML is already too strong,
51 as the large number of mathematical symbols, operators, and
52 diacritical marks that are used in mathematical notation cause MathML
53 documents to make extensive use of Unicode characters that typically
54 are not in the ``visible'' range of common text editors. Such
55 characters may appear as entity references, whose name indicates
56 somehow the kind of symbol used, or character references or they are
57 directly encoded in the document encoding scheme (for instance,
60 It is thus obvious that authoring MathML documents assumes the
61 assistance of dedicated tools. As of today, such tools can be
62 classified into two main categories:
64 \item WYSIWYG (What You See Is What You Get) editors that allow the
65 author to see the formatted document on the screen as it is
67 \item conversion tools that generate MathML markup from different
68 sources, typically other markup languages for scientific
69 documents, such as \TeX.
72 While the former tools are certainly more appealing, especially to the
73 unexperienced user, as they give a direct visual feedback, the
74 existance of tools in the second category takes into account the large
75 availability of existing documents in \TeX{} format, and also the fact
76 that experienced or ``lazy'' users may continue to prefer the use of a
77 markup language other than MathML for editing, and generate MathML
78 only as a final step of the authoring process. The ``laziness'' is not
79 really intended as a way of being reluctant towards a new technology,
80 but rather as a justified convincement that WYSIWYG editors are ``nice
81 to look at'' but after all they may slow down the authoring process.
82 WYSIWYG editors often involve the use of menus, palettes of symbols,
83 and, in general, an extensive use of the pointing device (the mouse)
84 for completing most operations. The use of shortcuts is of little
85 help, as it implies very soon a challenging exercise for the fingers
86 and the mind. Moreover, authors \emph{cannot improve} their authoring
87 speed with time. On the other side, the gap between the syntax of any
88 markup language for mathematics and mathematical notation may be
89 relevant, especially for large, non-trivial formulas and authoring is
90 a re-iterated process in which the author repeadtedly types the markup
91 in the editor, compiles, and looks at the result inside a pre-viewer.
93 \EdiTeX{} tries to synthesize the ``best of both worlds'' in a single
94 tool. The basic idea is that of creating a WYSIWYG editor in which
95 editing is achieved by typing \TeX{} markup as the author would do in
96 a text editor. The \TeX{} markup is tokenized and parsed on-the-fly
97 and a corresponding MathML representation is created and
98 displayed. This way, the author can see the rendered document as it
99 changes. The advantages of this approach can be summarized as follows:
101 \item the document is rendered concurrently with the editing, the
102 user has an immediate feedback hence it is easier to spot errors;
103 \item the author types in a concrete (and likely familiar) syntax
104 improving the editing speed;
105 \item the usual WYSIWYG mechanisms are still available. In
106 particular, it is possible to select \emph{visually} a fragment of
107 the document that needs re-editing, or that was left behind for
111 \paragraph{The Name of the Game:} there is no reference to MathML in
112 the name ``\EdiTeX.'' In fact, the architecture of the editor is not
113 tied to MathML markup. Although we focus on MathML editing, by
114 changing a completely modularized component of the editor it is
115 virtually possible to generate any other markup language.
117 \paragraph{Acknowledgments.} Stephen M. Watt and Igor Rodionov for
118 their work on the \TeX{} to MathML conversion tool; Stan Devitt for an
119 illuminating discussion about the architecture of \TeX{} to XML
120 conversion tools; Claudio Sacerdoti Coen for the valuable feedback and
121 uncountable bug reports.
123 \section{Architecture}
125 \section{Customization}
127 \subsection{Short and Long Identifiers}
129 \subsection{The Dictionary}
131 \subsection{Stylesheets and Trasformations}
133 \subsection{Rendering}
135 \section{XML Representation of \TeX{} Markup}
139 The following tokens are defined:
141 \begin{tabular}{lllp{0.5\textwidth}}
142 \textbf{\TeX{}} & \textbf{Notation} & \textbf{Node} & \textbf{Description} \\
144 \verb+{+ & $\mathrm{begin}$ & \texttt{g} & Beginning of a group \\
145 \verb+}+ & $\mathrm{end}$ & & End of a group \\
146 \verb+$+ & $\$$ & \texttt{math} & Math shift \\ %$ \\
148 \verb+#+$i$ & $p(i)$ & \texttt{p} & Parameter \\
149 \verb+^+ & $\uparrow$ & \texttt{sp} & Superscript \\
150 \verb+_+ & $\downarrow$ & \texttt{sb} & Subscript \\
151 & $\square$ & & Space-like character that can be ignored \\
152 & $s$ & \texttt{s} & Space-like character that may be significant \\
153 letter & $i(v)$ & \texttt{i} & Identifier $v$ \\
154 digit & $n(v)$ & \texttt{n} & Number $v$ \\
155 other & $o(v)$ & \texttt{o} & Other character or operator $v$ \\
156 \verb+~+ & $\sim$ & & Active character \\
157 \verb+%+ & $\%$ & & Comment \\
158 control & $c(v)\langle\alpha_1,\dots,\alpha_n\rangle$ & \texttt{c} &
159 Control sequence $v$ that expects the $\alpha_1,\dots,\alpha_n$ sequence of tokens. \\
160 backspace & $\vartriangleleft$ & & \\
161 backspace & $\blacktriangleleft$ & & \\
164 %% Some tokens are mapped directly into nodes of the TML tree. The following functions shows
167 \begin{tabular}{r@{\quad$=$\quad}l}
168 $\tmap{\{}$ & \verb+g+ \\
169 $\tmap{p(i)}$ & \verb+p[@index=+$i$\verb+]+ \\
170 $\tmap{p_l(i)}$ & \verb+p[@index=+$i$\verb+][@left-open='1']+ \\
171 $\tmap{p_r(i)}$ & \verb+p[@index=+$i$\verb+][@right-open='1']+ \\
172 $\tmap{s}$ & \verb+s+ \\
173 $\tmap{\uparrow}$ & \verb+sp+ \\
174 $\tmap{\downarrow}$ & \verb+sb+ \\
175 $\tmap{i(v)}$ & \verb+i[@value=+$v$\verb+]+ \\
176 $\tmap{n(v)}$ & \verb+n[@value=+$v$\verb+]+ \\
177 $\tmap{o(v)}$ & \verb+o[@value=+$v$\verb+]+ \\
178 $\tmap{c(v)\langle\alpha_1,\dots,\alpha_n\rangle}$ & \verb+c[@name=+$v$\verb+][^+$\tmap{\alpha_1}\cdots\tmap{\alpha_n}$\verb+$]+\\
182 %% \section{Description and Semantics of the Pattern Language}
185 %% \mathit{NodeTest} & ::= & \mathtt{*} \\
186 %% & | & \mathit{ElementType} \\
187 %% & | & \mathtt{<}~\mathit{ElementTypePattern}~\mathtt{>} \\[1ex]
188 %% \mathit{ElementTypePattern} & ::= & \mathtt{*} \\
189 %% & | & \mathit{ElementType}~(\mathtt{|}~\mathit{ElementType})^* \\
190 %% & | & \mathtt{!}\mathit{ElementType}~(\mathtt{|}~\mathit{ElementType})^*\\[1ex]
191 %% \mathit{NodePattern} & ::= & \mathit{NodeTest}~\mathit{AttributeQualifier}^*\\[1ex]
192 %% \mathit{AttributeQualifier} & ::= & \mathtt{[@}\mathit{AttributeTest}\mathtt{]}\\
193 %% & | & \mathtt{[!@}\mathit{AttributeTest}\mathtt{]}\\[1ex]
194 %% \mathit{AttributeTest} & ::= & \mathit{AttributeName} \\
195 %% & | & \mathit{AttributeName}\mathtt{='}\mathit{Text}\mathtt{'}
198 \section{Insert Rules}
200 \paragraph{Begin Group:} $\{$
203 \item{\verb+table/cursor+}\\
204 create a \texttt{row} node, create a \texttt{cell} node, create a \texttt{g} node,
205 append the cursor to the \texttt{g} node, append the \texttt{g} node to the \texttt{cell} node,
206 append the \texttt{cell} node to the \texttt{row} node, append the \texttt{row} node to the
208 \item{\verb+cursor+} \\ create a \texttt{g} node, replace the cursor with the new \texttt{g} node,
209 append the cursor to the new \texttt{g} node
212 % CASE: c/g[!@id]/cursor
219 % CASE: c[@table='1']/cursor
221 % create a g node with id, replace the cursor with the fresh g and append
222 % the cursor as only child of it
224 \paragraph{End Group:} $\}$
227 \item{\verb+g[@id]/cursor+}\\
228 remove the cursor, put $\tadvance$ after the \texttt{g} node
229 \item{\verb+row/cell/g/cursor+}\\
230 remove the cursor, put $\tadvance$ after the \texttt{row} node
231 \item{\verb+math/g[!@id]/cursor+}\\
233 \item{\verb+cursor+}\\
237 \paragraph{Math Shift:} $\$$
240 \item{\verb+tex/cursor+}\\
241 create a \texttt{math} node, create a \texttt{g} node, append the \texttt{g} node
242 as child of the \texttt{math} node, append the cursor as child of the \texttt{g} node
243 \item{\verb+math[@display='1']/g[!@id][*#]/cursor+}\\
244 append the cursor as last child of the \texttt{math} node
245 \item{\verb+math/g[!@id][*#]/cursor+}\\
247 \item{\verb+math[!display='1']/g[!@id]/cursor+}\\
248 set \verb+display='1'+ in the \texttt{math} node
249 \item{\verb+math/g[!@id]+}\\
250 append the cursor after the \texttt{math} node
251 \item{\verb+math/cursor+}\\
253 \item{\verb+cursor+} \\
259 % create a math node. create a g node. append g as child of math.
260 % append the cursor as child of g
261 % CASE: math[@display='1']/g[!@id][*#]/cursor
262 % append the cursor as last child of math
263 % CASE: math/g[!@id][*#]/cursor
264 % remove the cursor. Editing is done
265 % CASE: math[!display='1']/g[!@id]/cursor
266 % set the display attribute to '1'
268 % append the cursor after math (?)
270 % remove the cursor. Editing is done
274 \paragraph{Align:} $\&$
277 \item{\verb+g[@id]/cursor+}\\
278 create a \texttt{row} node, create a \texttt{cell} node, create a \texttt{g} node,
279 append the cursor to the new \texttt{g} node, append the \texttt{cell} node to the
280 the \texttt{row} node ?
281 \item{\verb+row/cell/g/cursor+}\\
282 create the \texttt{g} node, create the \texttt{cell} node, append the cursor
283 as child of the new \texttt{g} node, append the new \texttt{g} node to the new
284 \texttt{cell} node after the old \texttt{cell} node
285 \item{\verb+cursor+}\\
290 % CASE: g[@id]/cursor
291 % create a row node. create a cell node. create a g node. append the
292 % cursor to g, append the g to cell, append the cell to row, ???
293 % CASE: row/cell/g/cursor
294 % create a g node. create a cell node. appent the cursor to g,
295 % append the g to cell, insert the new cell after the existing cell
299 \paragraph{End-of-line:}
304 \paragraph{Parameter:} $p(i)$
308 \paragraph{Superscript:} $\uparrow$
311 \item{\verb+<g|p>[^#]/cursor+}\\
312 create a \SP{} node, create a \G{} node, replace the cursor with the \SP{} node,
313 append the \G{} node as first child of the \SP{} node, append the cursor as last
314 child of the \SP{} node
315 \item{\verb+<g|p>[*#]/cursor+}\\
316 create a \SP{} node, replace \texttt{*} with the \SP{} node, append \texttt{*} to
317 the \SP{} node, append cursor to the \SP{} node
318 \item{\verb+sp[^*#$][!@over='1']/cursor+}\\ %$
319 set \verb+over='1'+ in the \SP{} node
320 \item{\verb+sp[^*#$][@over='1']/cursor+}\\ %$
322 \item{\verb+cursor+}\\
327 % create sp node. create g node, replace cursor with sp, append g to sp, append cursor to sp
329 % create sp node, replace * with sp, append * to sp, append cursor to sp
330 % CASE: sp[^*#$][!@over='1']/cursor
331 % set over='1' in sp node
332 % CASE: sp[^*#$][@over='1']/cursor
337 \paragraph{Subscript:} $\downarrow$
340 \item{\verb+<g|p>[^#]/cursor+}\\
341 create a \SB{} node, create a \G{} node, replace the cursor with the \SB{} node,
342 append the \G{} node as first child of the \SB{} node, append the cursor as last
343 child of the \SB{} node
344 \item{\verb+<g|p>[*#]/cursor+}\\
345 create a \SB{} node, replace \texttt{*} with the \SB{} node, append \texttt{*} to
346 the \SB{} node, append cursor to the \SB{} node
347 \item{\verb+sb[^*#$][!@under='1']/cursor+}\\ %$
348 set \verb+under='1'+ in the \SB{} node
349 \item{\verb+sb[^*#$][@under='1']/cursor+}\\ %$
351 \item{\verb+cursor+}\\
356 % create sb node. create g node, replace cursor with sb, append g to sb, append cursor to sb
358 % create sb node, replace * with sb, append * to sb, append cursor to sb
359 % CASE: sb[^*#$][!@under='1']/cursor
360 % set over='1' in sb node
361 % CASE: sb[^*#$][@under='1']/cursor
366 \paragraph{Ignorable space:} $\square$
368 % do_ignorable_space:
371 \paragraph{Space:} $s$
374 \item{\verb+cursor+}\\
375 create \SNODE{} node, replace cursor with the \SNODE{} node, append
376 $\tadvance$ after \SNODE{} node
380 % create s node, replace cursor with s, append \advance after s
382 \paragraph{Identifier:} $i(v)$
385 \item{\verb+cursor+}\\
386 create an \INODE{}, set \verb+value=+$v$ in the \INODE{}, replace
387 cursor with \INODE{}, append $\tadvance$ after the \INODE{} node
391 % create i node, replace cursor with i, append \advance after i
393 \paragraph{Number:} $n(v)$
396 \item{\verb+cursor+}\\
397 create an \NNODE{}, set \verb+value=+$v$ in the \NNODE{}, replace
398 cursor with \NNODE{}, append $\tadvance$ after the \NNODE{} node
402 % create n node, replace cursor with n, append \advance after n
404 \paragraph{Apostrophe:} $o({}')$
407 \item{\verb+<g/p>[(sp[*#$]/g[o[@name='prime']$])#]/cursor+}\\
408 create a \ONODE{} node, set \verb+name='prime'+ in the \ONODE{},
409 append the \ONODE{} to the innermost \G{} node
410 \item{\verb+<g|p>[(sb[^sp[^*#$]/g[o[@name='prime']]$])#]/cursor+}\\
411 create a \ONODE{} node, set \verb+name='prime'+ in the \ONODE{},
412 append the \ONODE{} to the innermost \G{} node
413 \item{\verb+<g|p>[*#]/cursor+}\\
414 create a \ONODE{} node, set \verb+name='prime'+ in the \ONODE{},
415 create a \SP{} node, create a \G{} node, replace \texttt{*} with \SP{} node,
416 append the new \G{} node to the \SP{} node, append the \ONODE{}
417 node to the new \G{} node
418 \item{\verb+<g|p>[^#]/cursor+}\\
420 \item{\verb+cursor+}\\
421 cursor is not in a group, error?
425 % CASE: g[(sp[^*#$]/g[o[@name='prime']$])#]/cursor
426 % append a new o[@name='prime'] node to the inner g node
427 % CASE: g[(sb[^sp[^*#$]/g[o[@name='prime']]$])#]/cursor
428 % append a new o[@name='prime'] node to the inner g node
430 % create sp node, create g node, replace * with sp, append * to sp, append g to sp,
431 % append a new o[@name='prime'[ node to the new g node
435 % cursor is not in a group, error?
437 \paragraph{Other:} $o(v)$
439 create an \ONODE{}, set \verb+value=+$v$ in the \ONODE{}, replace
440 cursor with \ONODE{}, append $\tadvance$ after the \ONODE{} node
443 % create o node, replace cursor with o, append \advance after o
445 \paragraph{Active:} $\sim$
450 \paragraph{Comment:} $\%$
455 \paragraph{Begin Environment:} $c(\mathtt{begin})\langle\alpha_1,\dots,\alpha_n\rangle$
457 \paragraph{End Environment:} $c(\mathtt{end})\langle\rangle$
459 \paragraph{Left Delimiter:} $c(\mathtt{left})\langle\alpha\rangle$
461 \paragraph{Right Delimiter:} $c(\mathtt{right})\langle\alpha\rangle$
463 \paragraph{Carriage-Return:} $c(\mathtt{cr})\langle\rangle$
466 \item{\verb+row/cell/g/cursor+}\\
467 create a \ROW{} node, create a \CELL{} node, create a \G{}
468 node, append the cursor to the new \G{} node, append the new \G{}
469 node to the new \CELL{} node, append the new \CELL{} node to the
470 new \ROW{} node, insert the new \ROW{} node after the old \ROW{} node
471 \item{\verb+cursor+}\\
476 % CASE: row/cell/g/cursor
477 % create row node, create cell node, create g node,
478 % append cursor to g, append g to cell, append cell to row,
479 % insert new row after old row
483 \paragraph{Macro:} $c(v)\langle\alpha_1,\dots,\alpha_n\rangle$
486 \item{\verb+<p|g>/cursor+}\\
487 create a \CNODE{} node with the children corresponding to the pattern
488 $\tmap{\alpha_1}$,\dots,$\tmap{\alpha_n}$, replace the cursor with
489 the new \CNODE{} node. put $\tnext$ as the first child of the new
492 \item{\verb+*/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
496 \CNODE{} node. If $n\ne0$ emit a warning (the macro has arguments but
497 but the context wouldn't normally allow them to be entered)
502 % create a c node with children corresponding to the pattern of the macro
503 % append \nextparam as first child of the macro
505 \section{Left Drop Rules}
507 \paragraph{Normal Left Drop:} $\NLDROP$
511 \item{\verb+cursor+}\\
512 replace the cursor with the $\NLDROP$.
516 \paragraph{Special Left Drop:} $\SLDROP$
520 \item{\verb+cursor+}\\
521 replace the cursor with the $\SLDROP$.
525 \section{Right Drop Rules}
527 \section{$\varepsilon$-rules}
529 \paragraph{Nromal Left Drop}
533 %**************************************************************************************
534 %****************************** epsilon-rules with \NLDROP ****************************
535 %**************************************************************************************
537 %************** \NLDROP has neither preceding nor following nodes ********************
539 \item{\verb+math[^#$]/+$\NLDROP$}\\
540 replace the $\NLDROP$ with the cursor.
542 \item{\verb+g[^#$]/+$\NLDROP$}\\
543 replace the \G{} node with the $\NLDROP$.
545 % this rule overrides the one above
546 \item{\verb+math/g[^#$]/+$\NLDROP$}\\
547 replace the $\NLDROP$ with the cursor.
549 % this rule is overridden by the two ones below
550 \item{\verb+c/p[^#$]/+$\NLDROP$}\\
551 remove the $\NLDROP$ and insert it before the \PNODE{} node.
553 \item{\verb+c[p[@left-open='1'][*]#$]/p[@right-open='1'][^#$]/+$\NLDROP$}\\
554 replace the \CNODE{} node with the content of the first \PNODE{} node and insert the $\NLDROP$ after this content
556 \item{\verb+c[p[@left-open='1'][!*]#$]/p[@right-open='1'][^#$]/+$\NLDROP$}\\
557 replace the \CNODE{} node with the $\NLDROP$.
559 \item{\verb+c[^#][!p(*)]/+$\NLDROP$}\\
560 replace the \CNODE{} node with the $\NLDROP$.
562 \item{\verb+cell[^#$]/+$\NLDROP$}\\
563 replace the cell with the $\NLDROP_n$.
565 \item{\verb+table[^#$]/+$\NLDROP$}\\
566 replace the \TABLE{} node with the $\NLDROP$.
568 %************************* \NLDROP has at least one preceding node *********************
572 % this rule should also handles the case where the \NLDROP is the third (and last) child of a script.
573 \item{\verb+*[*#]/+$\NLDROP$}\\
574 remove the $\NLDROP$ and append it as the last child of its ex preceding brother.
576 % this rule overrides the one above
577 \item{\verb+*[(i|n|o|s|c[!*])#]/+$\NLDROP$}\\
578 remove the $\NLDROP$ and replace the token with the $\NLDROP_n$.
582 \item{\verb+<sp|sb>[^*#$]+/$\NLDROP$}\\
583 replace the script node with its first child and insert the $\NLDROP$ after it.
585 % this rule overrides the one above.
586 \item{\verb+<sp|sb>[^g[!@id][!*]#$]/+$\NLDROP$}\\
587 replace the script with the cursor.
589 % this rule overrides the one above
590 \item{\verb+*[sp[!@id][^*g[!@id][^o[@name='prime']++\verb+o[@name='prime']$]]#]/+$\NLDROP$}\\
591 remove the last \ONODE{} node and replace the $\NLDROP$ with the cursor.%$\NLDROP_n$.
593 \item{\verb+*[sp[!@id][^*g[!@id][^o[@name='prime']$]]#]/+$\NLDROP$}\\
594 replace the script with its first child and replace the $\NLDROP$ with the cursor.%$\NLDROP_n$.
596 \item{\verb+c[(i|n|o|s|c[!*])#]/+$\NLDROP$}\\
597 move the $\NLDROP$ before the delimiter.
599 % this rule is true for both right-open and parameterized macros.
600 \item{\verb+c[p#]/+$\NLDROP$}\\
601 move the $\NLDROP$ into the \PNODE{} node.
603 %**************** \NLDROP has no preceding nodes, but has following nodes **************
606 \item{\verb+*[^#*]/+$\NLDROP$}\\
607 remove the $\NLDROP$ and insert it before its parent.
611 \item{\verb+math/g[^#*]/+$\NLDROP$}\\
612 replace the $\NLDROP$ with the cursor.
614 % this rule is applicable to all macros.
615 \item{\verb+c[^#][p[*]]/+$\NLDROP$}\\
616 remove the $\NLDROP$ and insert it before the \CNODE{} node.
620 \paragraph{Special Left Drop}
624 %********************************************************************************************************
625 %************************************ epsilon-rules with \SLDROP ****************************************
626 %********************************************************************************************************
628 \item{\verb+math/+$\SLDROP$}\\
629 replace the $\SLDROP$ with the cursor.
631 %************************ \SLDROP has neither preceding nor following nodes *****************************
633 % this rule overrides the one below
634 \item{\verb+math/g[^#$]/+$\SLDROP$}\\
635 replace the $\SLDROP$ with the cursor.
637 \item{\verb+g[^#$]/+$\SLDROP$}\\
638 replace the \G{} node with the cursor.
640 \item{\verb+c[p[@left-open='1'][*]#$]/p[@right-open='1'][^#$]/+$\SLDROP$}\\
641 replace the \CNODE{} node with the content of the first \PNODE{} node and insert the cursor after this content
643 \item{\verb+c[p[@left-open='1'][!*]#$]/p[@right-open='1'][^#$]/+$\SLDROP$}\\
644 replace the \CNODE{} node with the cursor.
646 \item{\verb+c/p[^#$]/+$\SLDROP$}\\
647 remove the $\SLDROP$ and insert it before the \PNODE{} node.
649 \item{\verb+c[^#][!p(*)]/+$\SLDROP$}\\
650 replace the \CNODE{} node with the cursor.
652 \item{\verb+cell[^#$]/+$\SLDROP$}\\
653 replace the cell with the $\NLDROP_n$.
655 \item{\verb+table[^#$]/+$\SLDROP$}\\
656 replace the \TABLE{} node with the cursor.
658 %*********************** \SLDROP has at least one preceding node ***********************************
660 \item{\verb+*[sp[!@id][^*g[!@id][^o[@name='prime']++\verb+o[@name='prime']$]]#]/+$\SLDROP$}\\
661 remove the last \ONODE{} node and replace the $\SLDROP$ with the cursor.
663 \item{\verb+*[sp[!@id][^*g[!@id][^o[@name='prime']$]]#]/+$\SLDROP$}\\
664 replace the script with its first child and replace the $\SLDROP$ with the cursor.%$\NLDROP_n$.
666 \item{\verb+<sp|sb>[^g[!@id][!*]#$]/+$\SLDROP$}\\
667 replace the script with the cursor.
669 % this rule is overridden by the three rules above.
670 \item{\verb+<sp|sb>[^*#$]+/$\SLDROP$}\\
671 replace the script node with its first child and insert the cursor after it.
673 \item{\verb+c[(i|n|o|s|c[!*])#]/+$\SLDROP$}\\
674 remove the $\SLDROP$ and insert the cursor before the delimiter.
676 \item{\verb+c[p#(i|n|o|s|c[!*])]/+$\SLDROP$}\\
677 remove the $\SLDROP$ and insert the cursor into the \PNODE{} node.
679 \item{\verb+c[p[@right-open='1']#]+}\\
680 remove the $\SLDROP$ and append the curor as last child of the \PNODE{} node.
682 % this rule is overridden by the two ones above.
683 \item{\verb+c[p#]/+$\SLDROP$}\\
684 move the $\SLDROP$ into the \PNODE{} node.
686 \item{\verb+*[(i|n|o|s|c[!*])#]/+$\SLDROP$}\\
687 remove the $\SLDROP$ and replace the token with the cursor.
689 \item{\verb+*[table#]/$\SLDROP$+}\\
690 remove the $\SLDROP$ and append the $\NLDROP_n$ as the last child of the \TABLE{} node.
692 \item{\verb+*[c#]/+$\SLDROP$}\\
693 move the $\SLDROP$ into the \CNODE{} node.
695 \item{\verb+*[g#]/+$\SLDROP$}\\
696 remove the $\SLDROP$ and append the cursor as the last child of the \G{} node.
698 %********** \SLDROP has no preceding node, but has following ones **************
700 \item{\verb+math/g[^#*]/+$\SLDROP$}\\
701 replace the $\SLDROP$ with the cursor.
703 \item{\verb+c[^#p][p(*)]/+$\SLDROP$}\\
704 remove the $\SLDROP$ and insert the cursor before the \CNODE{} node.
707 \item{\verb+*[^#*]/+$\SLDROP$}\\
708 remove the $\SLDROP$ and insert the cursor before its parent.
712 \paragraph{Normalize Left Drop}
716 %****************************************************************************************
717 %***************************** epsilon-rules with \NLDROP_n *****************************
718 %****************************************************************************************
720 \item{\verb+*[*#]/+$\NLDROP_n$}\\
721 replace the $\NLDROP_n$ with the cursor.
723 \item{\verb+row[cell#]/+$\NLDROP_n$}\\
724 remove the $\NLDROP_n$ and append the cursor as the last child of the \CELL{} node.
726 \item{\verb+row[^#$]/+$\NLDROP_n$}\\
727 replace the \ROW{} node with the $\NLDROP_n$
729 \item{\verb+table[row#]/+$\NLDROP_n$}\\
730 remove the $\NLDROP_n$ and append it as last child of the \ROW{} node.
732 \item{\verb+table[^#$]/+$\NLDROP_n$}\\
733 replace the \TABLE{} with the cursor.%$\NLDROP_n$.
735 \item{\verb+g[@id][^#$]/+$\NLDROP_n$}\\
736 replace the \G{} node with the $\NLDROP_n$.
743 \item{\verb+g/+$\tadvance$}\\
744 replace $\tadvance$ with the cursor
746 \item{\verb+p[#$]/+$\tadvance$}\\ %$
747 put $\tadvance$ after the \PNODE{} node
749 \item{\verb+c[#p]/+$\tadvance$} \\
750 remove $\tadvance$, put the cursor as first child of the \PNODE{} node
752 \item{\verb+c[#*]/+$\tadvance$} \\ %$
753 replace $\tadvance$ with the cursor
755 \item{\verb+c[#$]/+$\tadvance$} \\ %$
756 move $\tadvance$ after the \CNODE{} node
759 \paragraph{Next Parameter}
761 \paragraph{Next Token}
763 %% \begin{description}
764 %% \item{\verb+c[#p]/+$\tnext$} \\
767 % g[@id]/(c[#$][@right-open]/g[!@id][#$]/)+cursor } let p = cursor.parent() in remove; advance(p)
771 % */cursor { let g = new group in replace
773 % g[@id][^#$]/cursor <= cursor.parent().replace(cursor)
774 % g[@id][^#$]/cursor <- cursor
775 % (!g[@id][^#$])[A#B]/(g[@id][^#$]/)+cursor <- (!g[@id][^#$])[A#B]/cursor