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}
32 \newcommand{\RDROP}{\vartriangleright}
38 \section{Introduction}
40 MathML~\cite{MathML1,MathML2,MathML2E} is an XML application for the
41 representation of mathematical expressions. As most XML applications,
42 MathML is unsuitable to be hand-written, except for the simplest
43 cases, because of its verbosity. In fact, the MathML specification
44 explicitly states that
46 ``While MathML is human-readable, it is anticipated that, in all but
47 the simplest cases, authors will use equation editors, conversion
48 programs, and other specialized software tools to generate MathML''
51 The statement about human readability of MathML is already too strong,
52 as the large number of mathematical symbols, operators, and
53 diacritical marks that are used in mathematical notation cause MathML
54 documents to make extensive use of Unicode characters that typically
55 are not in the ``visible'' range of common text editors. Such
56 characters may appear as entity references, whose name indicates
57 somehow the kind of symbol used, or character references or they are
58 directly encoded in the document encoding scheme (for instance,
61 It is thus obvious that authoring MathML documents assumes the
62 assistance of dedicated tools. As of today, such tools can be
63 classified into two main categories:
65 \item WYSIWYG (What You See Is What You Get) editors that allow the
66 author to see the formatted document on the screen as it is
68 \item conversion tools that generate MathML markup from different
69 sources, typically other markup languages for scientific
70 documents, such as \TeX.
73 While the former tools are certainly more appealing, especially to the
74 unexperienced user, as they give a direct visual feedback, the
75 existance of tools in the second category takes into account the large
76 availability of existing documents in \TeX{} format, and also the fact
77 that experienced or ``lazy'' users may continue to prefer the use of a
78 markup language other than MathML for editing, and generate MathML
79 only as a final step of the authoring process. The ``laziness'' is not
80 really intended as a way of being reluctant towards a new technology,
81 but rather as a justified convincement that WYSIWYG editors are ``nice
82 to look at'' but after all they may slow down the authoring process.
83 WYSIWYG editors often involve the use of menus, palettes of symbols,
84 and, in general, an extensive use of the pointing device (the mouse)
85 for completing most operations. The use of shortcuts is of little
86 help, as it implies very soon a challenging exercise for the fingers
87 and the mind. Moreover, authors \emph{cannot improve} their authoring
88 speed with time. On the other side, the gap between the syntax of any
89 markup language for mathematics and mathematical notation may be
90 relevant, especially for large, non-trivial formulas and authoring is
91 a re-iterated process in which the author repeadtedly types the markup
92 in the editor, compiles, and looks at the result inside a pre-viewer.
94 \EdiTeX{} tries to synthesize the ``best of both worlds'' in a single
95 tool. The basic idea is that of creating a WYSIWYG editor in which
96 editing is achieved by typing \TeX{} markup as the author would do in
97 a text editor. The \TeX{} markup is tokenized and parsed on-the-fly
98 and a corresponding MathML representation is created and
99 displayed. This way, the author can see the rendered document as it
100 changes. The advantages of this approach can be summarized as follows:
102 \item the document is rendered concurrently with the editing, the
103 user has an immediate feedback hence it is easier to spot errors;
104 \item the author types in a concrete (and likely familiar) syntax
105 improving the editing speed;
106 \item the usual WYSIWYG mechanisms are still available. In
107 particular, it is possible to select \emph{visually} a fragment of
108 the document that needs re-editing, or that was left behind for
112 \paragraph{The Name of the Game:} there is no reference to MathML in
113 the name ``\EdiTeX.'' In fact, the architecture of the editor is not
114 tied to MathML markup. Although we focus on MathML editing, by
115 changing a completely modularized component of the editor it is
116 virtually possible to generate any other markup language.
118 \paragraph{Acknowledgments.} Stephen M. Watt and Igor Rodionov for
119 their work on the \TeX{} to MathML conversion tool; Stan Devitt for an
120 illuminating discussion about the architecture of \TeX{} to XML
121 conversion tools; Claudio Sacerdoti Coen for the valuable feedback and
122 uncountable bug reports.
124 \section{Architecture}
126 \section{Customization}
128 \subsection{Short and Long Identifiers}
130 \subsection{The Dictionary}
132 \subsection{Stylesheets and Trasformations}
134 \subsection{Rendering}
136 \section{XML Representation of \TeX{} Markup}
140 The following tokens are defined:
142 \begin{tabular}{lllp{0.5\textwidth}}
143 \textbf{\TeX{}} & \textbf{Notation} & \textbf{Node} & \textbf{Description} \\
145 \verb+{+ & $\mathrm{begin}$ & \texttt{g} & Beginning of a group \\
146 \verb+}+ & $\mathrm{end}$ & & End of a group \\
147 \verb+$+ & $\$$ & \texttt{math} & Math shift \\ %$ \\
149 \verb+#+$i$ & $p(i)$ & \texttt{p} & Parameter \\
150 \verb+^+ & $\uparrow$ & \texttt{sp} & Superscript \\
151 \verb+_+ & $\downarrow$ & \texttt{sb} & Subscript \\
152 & $\square$ & & Space-like character that can be ignored \\
153 & $s$ & \texttt{s} & Space-like character that may be significant \\
154 letter & $i(v)$ & \texttt{i} & Identifier $v$ \\
155 digit & $n(v)$ & \texttt{n} & Number $v$ \\
156 other & $o(v)$ & \texttt{o} & Other character or operator $v$ \\
157 \verb+~+ & $\sim$ & & Active character \\
158 \verb+%+ & $\%$ & & Comment \\
159 control & $c(v)\langle\alpha_1,\dots,\alpha_n\rangle$ & \texttt{c} &
160 Control sequence $v$ that expects the $\alpha_1,\dots,\alpha_n$ sequence of tokens. \\
161 backspace & $\vartriangleleft$ & & \\
162 backspace & $\blacktriangleleft$ & & \\
165 %% Some tokens are mapped directly into nodes of the TML tree. The following functions shows
168 \begin{tabular}{r@{\quad$=$\quad}l}
169 $\tmap{\{}$ & \verb+g+ \\
170 $\tmap{p(i)}$ & \verb+p[@index=+$i$\verb+]+ \\
171 $\tmap{p_l(i)}$ & \verb+p[@index=+$i$\verb+][@left-open='1']+ \\
172 $\tmap{p_r(i)}$ & \verb+p[@index=+$i$\verb+][@right-open='1']+ \\
173 $\tmap{s}$ & \verb+s+ \\
174 $\tmap{\uparrow}$ & \verb+sp+ \\
175 $\tmap{\downarrow}$ & \verb+sb+ \\
176 $\tmap{i(v)}$ & \verb+i[@value=+$v$\verb+]+ \\
177 $\tmap{n(v)}$ & \verb+n[@value=+$v$\verb+]+ \\
178 $\tmap{o(v)}$ & \verb+o[@value=+$v$\verb+]+ \\
179 $\tmap{c(v)\langle\alpha_1,\dots,\alpha_n\rangle}$ & \verb+c[@name=+$v$\verb+][^+$\tmap{\alpha_1}\cdots\tmap{\alpha_n}$\verb+$]+\\
183 %% \section{Description and Semantics of the Pattern Language}
186 %% \mathit{NodeTest} & ::= & \mathtt{*} \\
187 %% & | & \mathit{ElementType} \\
188 %% & | & \mathtt{<}~\mathit{ElementTypePattern}~\mathtt{>} \\[1ex]
189 %% \mathit{ElementTypePattern} & ::= & \mathtt{*} \\
190 %% & | & \mathit{ElementType}~(\mathtt{|}~\mathit{ElementType})^* \\
191 %% & | & \mathtt{!}\mathit{ElementType}~(\mathtt{|}~\mathit{ElementType})^*\\[1ex]
192 %% \mathit{NodePattern} & ::= & \mathit{NodeTest}~\mathit{AttributeQualifier}^*\\[1ex]
193 %% \mathit{AttributeQualifier} & ::= & \mathtt{[@}\mathit{AttributeTest}\mathtt{]}\\
194 %% & | & \mathtt{[!@}\mathit{AttributeTest}\mathtt{]}\\[1ex]
195 %% \mathit{AttributeTest} & ::= & \mathit{AttributeName} \\
196 %% & | & \mathit{AttributeName}\mathtt{='}\mathit{Text}\mathtt{'}
199 \section{Insert Rules}
201 \paragraph{Begin Group:} $\{$
204 \item{\verb+table/cursor+}\\
205 create a \texttt{row} node, create a \texttt{cell} node, create a \texttt{g} node,
206 append the cursor to the \texttt{g} node, append the \texttt{g} node to the \texttt{cell} node,
207 append the \texttt{cell} node to the \texttt{row} node, append the \texttt{row} node to the
209 \item{\verb+cursor+} \\ create a \texttt{g} node, replace the cursor with the new \texttt{g} node,
210 append the cursor to the new \texttt{g} node
213 % CASE: c/g[!@id]/cursor
220 % CASE: c[@table='1']/cursor
222 % create a g node with id, replace the cursor with the fresh g and append
223 % the cursor as only child of it
225 \paragraph{End Group:} $\}$
228 \item{\verb+g[@id]/cursor+}\\
229 remove the cursor, put $\tadvance$ after the \texttt{g} node
230 \item{\verb+row/cell/g/cursor+}\\
231 remove the cursor, put $\tadvance$ after the \texttt{row} node
232 \item{\verb+math/g[!@id]/cursor+}\\
234 \item{\verb+cursor+}\\
238 \paragraph{Math Shift:} $\$$
241 \item{\verb+tex/cursor+}\\
242 create a \texttt{math} node, create a \texttt{g} node, append the \texttt{g} node
243 as child of the \texttt{math} node, append the cursor as child of the \texttt{g} node
244 \item{\verb+math[@display='1']/g[!@id][*#]/cursor+}\\
245 append the cursor as last child of the \texttt{math} node
246 \item{\verb+math/g[!@id][*#]/cursor+}\\
248 \item{\verb+math[!display='1']/g[!@id]/cursor+}\\
249 set \verb+display='1'+ in the \texttt{math} node
250 \item{\verb+math/g[!@id]+}\\
251 append the cursor after the \texttt{math} node
252 \item{\verb+math/cursor+}\\
254 \item{\verb+cursor+} \\
260 % create a math node. create a g node. append g as child of math.
261 % append the cursor as child of g
262 % CASE: math[@display='1']/g[!@id][*#]/cursor
263 % append the cursor as last child of math
264 % CASE: math/g[!@id][*#]/cursor
265 % remove the cursor. Editing is done
266 % CASE: math[!display='1']/g[!@id]/cursor
267 % set the display attribute to '1'
269 % append the cursor after math (?)
271 % remove the cursor. Editing is done
275 \paragraph{Align:} $\&$
278 \item{\verb+g[@id]/cursor+}\\
279 create a \texttt{row} node, create a \texttt{cell} node, create a \texttt{g} node,
280 append the cursor to the new \texttt{g} node, append the \texttt{cell} node to the
281 the \texttt{row} node ?
282 \item{\verb+row/cell/g/cursor+}\\
283 create the \texttt{g} node, create the \texttt{cell} node, append the cursor
284 as child of the new \texttt{g} node, append the new \texttt{g} node to the new
285 \texttt{cell} node after the old \texttt{cell} node
286 \item{\verb+cursor+}\\
291 % CASE: g[@id]/cursor
292 % create a row node. create a cell node. create a g node. append the
293 % cursor to g, append the g to cell, append the cell to row, ???
294 % CASE: row/cell/g/cursor
295 % create a g node. create a cell node. appent the cursor to g,
296 % append the g to cell, insert the new cell after the existing cell
300 \paragraph{End-of-line:}
305 \paragraph{Parameter:} $p(i)$
309 \paragraph{Superscript:} $\uparrow$
312 \item{\verb+<g|p>[^#]/cursor+}\\
313 create a \SP{} node, create a \G{} node, replace the cursor with the \SP{} node,
314 append the \G{} node as first child of the \SP{} node, append the cursor as last
315 child of the \SP{} node
316 \item{\verb+<g|p>[*#]/cursor+}\\
317 create a \SP{} node, replace \texttt{*} with the \SP{} node, append \texttt{*} to
318 the \SP{} node, append cursor to the \SP{} node
319 \item{\verb+sp[^*#$][!@over='1']/cursor+}\\ %$
320 set \verb+over='1'+ in the \SP{} node
321 \item{\verb+sp[^*#$][@over='1']/cursor+}\\ %$
323 \item{\verb+cursor+}\\
328 % create sp node. create g node, replace cursor with sp, append g to sp, append cursor to sp
330 % create sp node, replace * with sp, append * to sp, append cursor to sp
331 % CASE: sp[^*#$][!@over='1']/cursor
332 % set over='1' in sp node
333 % CASE: sp[^*#$][@over='1']/cursor
338 \paragraph{Subscript:} $\downarrow$
341 \item{\verb+<g|p>[^#]/cursor+}\\
342 create a \SB{} node, create a \G{} node, replace the cursor with the \SB{} node,
343 append the \G{} node as first child of the \SB{} node, append the cursor as last
344 child of the \SB{} node
345 \item{\verb+<g|p>[*#]/cursor+}\\
346 create a \SB{} node, replace \texttt{*} with the \SB{} node, append \texttt{*} to
347 the \SB{} node, append cursor to the \SB{} node
348 \item{\verb+sb[^*#$][!@under='1']/cursor+}\\ %$
349 set \verb+under='1'+ in the \SB{} node
350 \item{\verb+sb[^*#$][@under='1']/cursor+}\\ %$
352 \item{\verb+cursor+}\\
357 % create sb node. create g node, replace cursor with sb, append g to sb, append cursor to sb
359 % create sb node, replace * with sb, append * to sb, append cursor to sb
360 % CASE: sb[^*#$][!@under='1']/cursor
361 % set over='1' in sb node
362 % CASE: sb[^*#$][@under='1']/cursor
367 \paragraph{Ignorable space:} $\square$
369 % do_ignorable_space:
372 \paragraph{Space:} $s$
375 \item{\verb+cursor+}\\
376 create \SNODE{} node, replace cursor with the \SNODE{} node, append
377 $\tadvance$ after \SNODE{} node
381 % create s node, replace cursor with s, append \advance after s
383 \paragraph{Identifier:} $i(v)$
386 \item{\verb+cursor+}\\
387 create an \INODE{}, set \verb+value=+$v$ in the \INODE{}, replace
388 cursor with \INODE{}, append $\tadvance$ after the \INODE{} node
392 % create i node, replace cursor with i, append \advance after i
394 \paragraph{Number:} $n(v)$
397 \item{\verb+cursor+}\\
398 create an \NNODE{}, set \verb+value=+$v$ in the \NNODE{}, replace
399 cursor with \NNODE{}, append $\tadvance$ after the \NNODE{} node
403 % create n node, replace cursor with n, append \advance after n
405 \paragraph{Apostrophe:} $o({}')$
408 \item{\verb+<g/p>[(sp[*#$]/g[o[@name='prime']$])#]/cursor+}\\
409 create a \ONODE{} node, set \verb+name='prime'+ in the \ONODE{},
410 append the \ONODE{} to the innermost \G{} node
411 \item{\verb+<g|p>[(sb[^sp[^*#$]/g[o[@name='prime']]$])#]/cursor+}\\
412 create a \ONODE{} node, set \verb+name='prime'+ in the \ONODE{},
413 append the \ONODE{} to the innermost \G{} node
414 \item{\verb+<g|p>[*#]/cursor+}\\
415 create a \ONODE{} node, set \verb+name='prime'+ in the \ONODE{},
416 create a \SP{} node, create a \G{} node, replace \texttt{*} with \SP{} node,
417 append the new \G{} node to the \SP{} node, append the \ONODE{}
418 node to the new \G{} node
419 \item{\verb+<g|p>[^#]/cursor+}\\
421 \item{\verb+cursor+}\\
422 cursor is not in a group, error?
426 % CASE: g[(sp[^*#$]/g[o[@name='prime']$])#]/cursor
427 % append a new o[@name='prime'] node to the inner g node
428 % CASE: g[(sb[^sp[^*#$]/g[o[@name='prime']]$])#]/cursor
429 % append a new o[@name='prime'] node to the inner g node
431 % create sp node, create g node, replace * with sp, append * to sp, append g to sp,
432 % append a new o[@name='prime'[ node to the new g node
436 % cursor is not in a group, error?
438 \paragraph{Other:} $o(v)$
440 create an \ONODE{}, set \verb+value=+$v$ in the \ONODE{}, replace
441 cursor with \ONODE{}, append $\tadvance$ after the \ONODE{} node
444 % create o node, replace cursor with o, append \advance after o
446 \paragraph{Active:} $\sim$
451 \paragraph{Comment:} $\%$
456 \paragraph{Begin Environment:} $c(\mathtt{begin})\langle\alpha_1,\dots,\alpha_n\rangle$
458 \paragraph{End Environment:} $c(\mathtt{end})\langle\rangle$
460 \paragraph{Left Delimiter:} $c(\mathtt{left})\langle\alpha\rangle$
462 \paragraph{Right Delimiter:} $c(\mathtt{right})\langle\alpha\rangle$
464 \paragraph{Carriage-Return:} $c(\mathtt{cr})\langle\rangle$
467 \item{\verb+row/cell/g/cursor+}\\
468 create a \ROW{} node, create a \CELL{} node, create a \G{}
469 node, append the cursor to the new \G{} node, append the new \G{}
470 node to the new \CELL{} node, append the new \CELL{} node to the
471 new \ROW{} node, insert the new \ROW{} node after the old \ROW{} node
472 \item{\verb+cursor+}\\
477 % CASE: row/cell/g/cursor
478 % create row node, create cell node, create g node,
479 % append cursor to g, append g to cell, append cell to row,
480 % insert new row after old row
484 \paragraph{Macro:} $c(v)\langle\alpha_1,\dots,\alpha_n\rangle$
487 \item{\verb+<p|g>/cursor+}\\
488 create a \CNODE{} node with the children corresponding to the pattern
489 $\tmap{\alpha_1}$,\dots,$\tmap{\alpha_n}$, replace the cursor with
490 the new \CNODE{} node. put $\tnext$ as the first child of the new
493 \item{\verb+*/cursor+}\\
494 create a \CNODE{} node with the children corresponding to the pattern
495 $\tmap{\alpha_1}$,\dots,$\tmap{\alpha_n}$, replace the cursor with
496 the new \CNODE{} node, put $\tnext$ as the first child of the new
497 \CNODE{} node. If $n\ne0$ emit a warning (the macro has arguments but
498 but the context wouldn't normally allow them to be entered)
503 % create a c node with children corresponding to the pattern of the macro
504 % append \nextparam as first child of the macro
506 \section{Left Drop Rules}
508 \paragraph{Normal Left Drop:} $\NLDROP$
512 \item{\verb+cursor+}\\
513 replace the cursor with the $\NLDROP$.
517 \paragraph{Special Left Drop:} $\SLDROP$
521 \item{\verb+cursor+}\\
522 replace the cursor with the $\SLDROP$.
526 \section{Right Drop Rules}
530 \item{\verb+cursor+}\\
531 replace the cursor with the $\RDROP$.
535 \section{$\varepsilon$-rules}
537 \paragraph{Nromal Left Drop}
541 %**************************************************************************************
542 %****************************** epsilon-rules with \NLDROP ****************************
543 %**************************************************************************************
545 %************** \NLDROP has neither preceding nor following nodes ********************
547 \item{\verb+math[^#$]/+$\NLDROP$}\\
548 replace the $\NLDROP$ with the cursor.
550 \item{\verb+g[^#$]/+$\NLDROP$}\\
551 replace the \G{} node with the $\NLDROP$.
553 % this rule overrides the one above
554 \item{\verb+math/g[^#$]/+$\NLDROP$}\\
555 replace the $\NLDROP$ with the cursor.
557 % this rule is overridden by the two ones below
558 \item{\verb+c/p[^#$]/+$\NLDROP$}\\
559 remove the $\NLDROP$ and insert it before the \PNODE{} node.
561 \item{\verb+c[p[@left-open='1'][*]#$]/p[@right-open='1'][^#$]/+$\NLDROP$}\\
562 replace the \CNODE{} node with the content of the first \PNODE{} node and insert the $\NLDROP$ after this content
564 \item{\verb+c[p[@left-open='1'][!*]#$]/p[@right-open='1'][^#$]/+$\NLDROP$}\\
565 replace the \CNODE{} node with the $\NLDROP$.
567 \item{\verb+c[^#][!p(*)]/+$\NLDROP$}\\
568 replace the \CNODE{} node with the $\NLDROP$.
570 \item{\verb+cell[^#$]/+$\NLDROP$}\\
571 replace the cell with the $\NLDROP_n$.
573 \item{\verb+table[^#$]/+$\NLDROP$}\\
574 replace the \TABLE{} node with the $\NLDROP$.
576 %************************* \NLDROP has at least one preceding node *********************
580 % this rule should also handles the case where the \NLDROP is the third (and last) child of a script.
581 \item{\verb+*[*#]/+$\NLDROP$}\\
582 remove the $\NLDROP$ and append it as the last child of its ex preceding brother.
584 % this rule overrides the one above
585 \item{\verb+*[(i|n|o|s|c[!*])#]/+$\NLDROP$}\\
586 remove the $\NLDROP$ and replace the token with the $\NLDROP_n$.
590 \item{\verb+<sp|sb>[^*#$]+/$\NLDROP$}\\
591 replace the script node with its first child and insert the $\NLDROP$ after it.
593 % this rule overrides the one above.
594 \item{\verb+<sp|sb>[^g[!@id][!*]#$]/+$\NLDROP$}\\
595 replace the script with the cursor.
597 % this rule overrides the one above
598 \item{\verb+*[sp[!@id][^*g[!@id][^o[@name='prime']++\verb+o[@name='prime']$]]#]/+$\NLDROP$}\\
599 remove the last \ONODE{} node and replace the $\NLDROP$ with the cursor.%$\NLDROP_n$.
601 \item{\verb+*[sp[!@id][^*g[!@id][^o[@name='prime']$]]#]/+$\NLDROP$}\\
602 replace the script with its first child and replace the $\NLDROP$ with the cursor.%$\NLDROP_n$.
604 \item{\verb+c[(i|n|o|s|c[!*])#]/+$\NLDROP$}\\
605 move the $\NLDROP$ before the delimiter.
607 % this rule is true for both right-open and parameterized macros.
608 \item{\verb+c[p#]/+$\NLDROP$}\\
609 move the $\NLDROP$ into the \PNODE{} node.
611 %**************** \NLDROP has no preceding nodes, but has following nodes **************
614 \item{\verb+*[^#*]/+$\NLDROP$}\\
615 remove the $\NLDROP$ and insert it before its parent.
619 \item{\verb+math/g[^#*]/+$\NLDROP$}\\
620 replace the $\NLDROP$ with the cursor.
622 % this rule is applicable to all macros.
623 \item{\verb+c[^#][p[*]]/+$\NLDROP$}\\
624 remove the $\NLDROP$ and insert it before the \CNODE{} node.
628 \paragraph{Special Left Drop}
632 %********************************************************************************************************
633 %************************************ epsilon-rules with \SLDROP ****************************************
634 %********************************************************************************************************
636 \item{\verb+math/+$\SLDROP$}\\
637 replace the $\SLDROP$ with the cursor.
639 %************************ \SLDROP has neither preceding nor following nodes *****************************
641 % this rule overrides the one below
642 \item{\verb+math/g[^#$]/+$\SLDROP$}\\
643 replace the $\SLDROP$ with the cursor.
645 \item{\verb+g[^#$]/+$\SLDROP$}\\
646 replace the \G{} node with the cursor.
648 \item{\verb+c[p[@left-open='1'][*]#$]/p[@right-open='1'][^#$]/+$\SLDROP$}\\
649 replace the \CNODE{} node with the content of the first \PNODE{} node and insert the cursor after this content
651 \item{\verb+c[p[@left-open='1'][!*]#$]/p[@right-open='1'][^#$]/+$\SLDROP$}\\
652 replace the \CNODE{} node with the cursor.
654 \item{\verb+c/p[^#$]/+$\SLDROP$}\\
655 remove the $\SLDROP$ and insert it before the \PNODE{} node.
657 \item{\verb+c[^#][!p(*)]/+$\SLDROP$}\\
658 replace the \CNODE{} node with the cursor.
660 \item{\verb+cell[^#$]/+$\SLDROP$}\\
661 replace the cell with the $\NLDROP_n$.
663 \item{\verb+table[^#$]/+$\SLDROP$}\\
664 replace the \TABLE{} node with the cursor.
666 %*********************** \SLDROP has at least one preceding node ***********************************
668 \item{\verb+*[sp[!@id][^*g[!@id][^o[@name='prime']++\verb+o[@name='prime']$]]#]/+$\SLDROP$}\\
669 remove the last \ONODE{} node and replace the $\SLDROP$ with the cursor.
671 \item{\verb+*[sp[!@id][^*g[!@id][^o[@name='prime']$]]#]/+$\SLDROP$}\\
672 replace the script with its first child and replace the $\SLDROP$ with the cursor.%$\NLDROP_n$.
674 \item{\verb+<sp|sb>[^g[!@id][!*]#$]/+$\SLDROP$}\\
675 replace the script with the cursor.
677 % this rule is overridden by the three rules above.
678 \item{\verb+<sp|sb>[^*#$]+/$\SLDROP$}\\
679 replace the script node with its first child and insert the cursor after it.
681 \item{\verb+c[(i|n|o|s|c[!*])#]/+$\SLDROP$}\\
682 remove the $\SLDROP$ and insert the cursor before the delimiter.
684 \item{\verb+c[p#(i|n|o|s|c[!*])]/+$\SLDROP$}\\
685 remove the $\SLDROP$ and insert the cursor into the \PNODE{} node.
687 \item{\verb+c[p[@right-open='1']#]+}\\
688 remove the $\SLDROP$ and append the curor as last child of the \PNODE{} node.
690 % this rule is overridden by the two ones above.
691 \item{\verb+c[p#]/+$\SLDROP$}\\
692 move the $\SLDROP$ into the \PNODE{} node.
694 \item{\verb+*[(i|n|o|s|c[!*])#]/+$\SLDROP$}\\
695 remove the $\SLDROP$ and replace the token with the cursor.
697 \item{\verb+*[table#]/$\SLDROP$+}\\
698 remove the $\SLDROP$ and append the $\NLDROP_n$ as the last child of the \TABLE{} node.
700 \item{\verb+*[c#]/+$\SLDROP$}\\
701 move the $\SLDROP$ into the \CNODE{} node.
703 \item{\verb+*[g#]/+$\SLDROP$}\\
704 remove the $\SLDROP$ and append the cursor as the last child of the \G{} node.
706 %********** \SLDROP has no preceding node, but has following ones **************
708 \item{\verb+math/g[^#*]/+$\SLDROP$}\\
709 replace the $\SLDROP$ with the cursor.
711 \item{\verb+c[^#p][p(*)]/+$\SLDROP$}\\
712 remove the $\SLDROP$ and insert the cursor before the \CNODE{} node.
715 \item{\verb+*[^#*]/+$\SLDROP$}\\
716 remove the $\SLDROP$ and insert the cursor before its parent.
720 \paragraph{Normalize Left Drop}
724 %****************************************************************************************
725 %***************************** epsilon-rules with \NLDROP_n *****************************
726 %****************************************************************************************
728 \item{\verb+*[*#]/+$\NLDROP_n$}\\
729 replace the $\NLDROP_n$ with the cursor.
731 \item{\verb+row[cell#]/+$\NLDROP_n$}\\
732 remove the $\NLDROP_n$ and append the cursor as the last child of the \CELL{} node.
734 \item{\verb+row[^#$]/+$\NLDROP_n$}\\
735 replace the \ROW{} node with the $\NLDROP_n$
737 \item{\verb+table[row#]/+$\NLDROP_n$}\\
738 remove the $\NLDROP_n$ and append it as last child of the \ROW{} node.
740 \item{\verb+table[^#$]/+$\NLDROP_n$}\\
741 replace the \TABLE{} with the cursor.%$\NLDROP_n$.
743 \item{\verb+g[@id][^#$]/+$\NLDROP_n$}\\
744 replace the \G{} node with the $\NLDROP_n$.
747 replace the $\NLDROP_n$ with the cursor.
751 \paragraph{Right Drop}
755 %************************* \RDROP has at least a following node ****************************************
757 \item{\verb+c[#(i|n|o|s|c[!*])]/+$\RDROP$}\\
758 remove the $\RDROP$ and append it after the delimiter
760 \item{\verb+*[#(i|n|o|s|c[!*])]/+$\RDROP$}\\
761 remove the token and replace the $\RDROP$ with the cursor $\RDROP_n$.
763 % this rule is overridden by those ones above.
764 \item{\verb+*[#*]/+$\RDROP$}\\
765 remove the $\RDROP$ and append it as the first child of the following node.
767 %************************** \RDROP has neither following nor preceding nodes ******************************
769 \item{\verb+c[#$][!p[*]]/+$\RDROP$}\\
770 replace the \CNODE{} with the $\RDROP$.
772 \item{\verb+p[^#$]/+$\RDROP$}\\
773 move the $\RDROP$ after the \PNODE{} node.
775 \item{\verb+g[^#$]/+$\RDROP$}\\
776 replace the \G{} node with the $\RDROP$.
780 \paragraph{Normalize Right Drop}
784 % at the moment it's the only rule, defined for this symbol.
785 \item{\verb+g[@id][^#$]/+$\RDROP_n$}\\
786 replace the \G{} node with the $\RDROP_n$.
789 replace the $\RDROP$ with the cursor.
796 \item{\verb+g/+$\tadvance$}\\
797 replace $\tadvance$ with the cursor
799 \item{\verb+p[#$]/+$\tadvance$}\\ %$
800 put $\tadvance$ after the \PNODE{} node
802 \item{\verb+c[#p]/+$\tadvance$} \\
803 remove $\tadvance$, put the cursor as first child of the \PNODE{} node
805 \item{\verb+c[#*]/+$\tadvance$} \\ %$
806 replace $\tadvance$ with the cursor
808 \item{\verb+c[#$]/+$\tadvance$} \\ %$
809 move $\tadvance$ after the \CNODE{} node
812 \paragraph{Next Parameter}
814 \paragraph{Next Token}
816 %% \begin{description}
817 %% \item{\verb+c[#p]/+$\tnext$} \\
820 % g[@id]/(c[#$][@right-open]/g[!@id][#$]/)+cursor } let p = cursor.parent() in remove; advance(p)
824 % */cursor { let g = new group in replace
826 % g[@id][^#$]/cursor <= cursor.parent().replace(cursor)
827 % g[@id][^#$]/cursor <- cursor
828 % (!g[@id][^#$])[A#B]/(g[@id][^#$]/)+cursor <- (!g[@id][^#$])[A#B]/cursor