1 /*             itex2MML 1.5.5
2  *   itex2MML.y last modified 12/10/2016
3  */
4 
5 %parse-param {char **ret_str}
6 
7 %{
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 
12 #include "itex2MML.h"
13 
14 #define YYSTYPE char *
15 #define YYPARSE_PARAM_TYPE char **
16 #define YYPARSE_PARAM ret_str
17 
18 #define yytext itex2MML_yytext
19 
20  extern int yylex ();
21  int itex2MML_do_html_filter (const char * buffer, size_t length, const int forbid_markup);
22 
23  extern char * yytext;
24 
itex2MML_default_error(const char * msg)25  static void itex2MML_default_error (const char * msg)
26    {
27      if (msg)
28        fprintf(stderr, "Line: %d Error: %s\n", itex2MML_lineno, msg);
29    }
30 
31  void (*itex2MML_error) (const char * msg) = itex2MML_default_error;
32 
yyerror(char ** ret_str,char * s)33  static void yyerror (char **ret_str, char * s)
34    {
35      char * msg = itex2MML_copy3 (s, " at token ", yytext);
36      if (itex2MML_error)
37        (*itex2MML_error) (msg);
38      itex2MML_free_string (msg);
39    }
40 
41  /* Note: If length is 0, then buffer is treated like a string; otherwise only length bytes are written.
42   */
itex2MML_default_write(const char * buffer,size_t length)43  static void itex2MML_default_write (const char * buffer, size_t length)
44    {
45      if (buffer)
46        {
47 	 if (length)
48 	   fwrite (buffer, 1, length, stdout);
49 	 else
50 	   fputs (buffer, stdout);
51        }
52    }
53 
itex2MML_default_write_mathml(const char * mathml)54  static void itex2MML_default_write_mathml (const char * mathml)
55    {
56      if (itex2MML_write)
57        (*itex2MML_write) (mathml, 0);
58    }
59 
60 #ifdef itex2MML_CAPTURE
61     static char * itex2MML_output_string = "" ;
62 
itex2MML_output()63     const char * itex2MML_output ()
64     {
65         char * copy = (char *) malloc((itex2MML_output_string ? strlen(itex2MML_output_string) : 0) + 1);
66         if (copy)
67           {
68            if (itex2MML_output_string)
69              {
70                strcpy(copy, itex2MML_output_string);
71                if (*itex2MML_output_string != '\0')
72                    free(itex2MML_output_string);
73              }
74            else
75              copy[0] = 0;
76            itex2MML_output_string = "";
77           }
78         return copy;
79     }
80 
itex2MML_capture(const char * buffer,size_t length)81  static void itex2MML_capture (const char * buffer, size_t length)
82     {
83      if (buffer)
84        {
85          if (length)
86            {
87               size_t first_length = itex2MML_output_string ? strlen(itex2MML_output_string) : 0;
88               char * copy  = (char *) malloc(first_length + length + 1);
89               if (copy)
90                 {
91                   if (itex2MML_output_string)
92                     {
93                        strcpy(copy, itex2MML_output_string);
94                        if (*itex2MML_output_string != '\0')
95                           free(itex2MML_output_string);
96                     }
97                   else
98                      copy[0] = 0;
99                   strncat(copy, buffer, length);
100                   itex2MML_output_string = copy;
101                  }
102             }
103          else
104             {
105               char * copy = itex2MML_copy2(itex2MML_output_string, buffer);
106               if (*itex2MML_output_string != '\0')
107                  free(itex2MML_output_string);
108               itex2MML_output_string = copy;
109             }
110         }
111     }
112 
itex2MML_capture_mathml(const char * buffer)113     static void itex2MML_capture_mathml (const char * buffer)
114     {
115        char * temp = itex2MML_copy2(itex2MML_output_string, buffer);
116        if (*itex2MML_output_string != '\0')
117          free(itex2MML_output_string);
118        itex2MML_output_string = temp;
119     }
120     void (*itex2MML_write) (const char * buffer, size_t length) = itex2MML_capture;
121     void (*itex2MML_write_mathml) (const char * mathml) = itex2MML_capture_mathml;
122 #else
123     void (*itex2MML_write) (const char * buffer, size_t length) = itex2MML_default_write;
124     void (*itex2MML_write_mathml) (const char * mathml) = itex2MML_default_write_mathml;
125 #endif
126 
127  char * itex2MML_empty_string = "";
128 
129  /* Create a copy of a string, adding space for extra chars
130   */
itex2MML_copy_string_extra(const char * str,unsigned extra)131  char * itex2MML_copy_string_extra (const char * str, unsigned extra)
132    {
133      char * copy = (char *) malloc(extra + (str ? strlen (str) : 0) + 1);
134      if (copy)
135        {
136 	 if (str)
137 	   strcpy(copy, str);
138 	 else
139 	   copy[0] = 0;
140        }
141      return copy ? copy : itex2MML_empty_string;
142    }
143 
144  /* Create a copy of a string, appending two strings
145   */
itex2MML_copy3(const char * first,const char * second,const char * third)146  char * itex2MML_copy3 (const char * first, const char * second, const char * third)
147    {
148      size_t first_length =  first ? strlen( first) : 0;
149      size_t second_length = second ? strlen(second) : 0;
150      size_t third_length =  third ? strlen( third) : 0;
151 
152      char * copy = (char *) malloc(first_length + second_length + third_length + 1);
153 
154      if (copy)
155        {
156 	 if (first)
157 	   strcpy(copy, first);
158 	 else
159 	   copy[0] = 0;
160 
161 	 if (second) strcat(copy, second);
162 	 if ( third) strcat(copy,  third);
163        }
164      return copy ? copy : itex2MML_empty_string;
165    }
166 
167  /* Create a copy of a string, appending a second string
168   */
itex2MML_copy2(const char * first,const char * second)169  char * itex2MML_copy2 (const char * first, const char * second)
170    {
171      return itex2MML_copy3(first, second, 0);
172    }
173 
174  /* Create a copy of a string
175   */
itex2MML_copy_string(const char * str)176  char * itex2MML_copy_string (const char * str)
177    {
178      return itex2MML_copy3(str, 0, 0);
179    }
180 
181  /* Create a copy of a string, escaping unsafe characters for XML
182   */
itex2MML_copy_escaped(const char * str)183  char * itex2MML_copy_escaped (const char * str)
184    {
185      size_t length = 0;
186 
187      const char * ptr1 = str;
188 
189      char * ptr2 = 0;
190      char * copy = 0;
191 
192      if ( str == 0) return itex2MML_empty_string;
193      if (*str == 0) return itex2MML_empty_string;
194 
195      while (*ptr1)
196        {
197 	 switch (*ptr1)
198 	   {
199 	   case '<':  /* &lt;   */
200 	   case '>':  /* &gt;   */
201 	     length += 4;
202 	     break;
203 	   case '&':  /* &amp;  */
204 	     length += 5;
205 	     break;
206 	   case '\'': /* &apos; */
207 	   case '"':  /* &quot; */
208 	   case '-':  /* &#x2d; */
209 	     length += 6;
210 	     break;
211 	   default:
212 	     length += 1;
213 	     break;
214 	   }
215 	 ++ptr1;
216        }
217 
218      copy = (char *) malloc (length + 1);
219 
220      if (copy)
221        {
222 	 ptr1 = str;
223 	 ptr2 = copy;
224 
225 	 while (*ptr1)
226 	   {
227 	     switch (*ptr1)
228 	       {
229 	       case '<':
230 		 strcpy (ptr2, "&lt;");
231 		 ptr2 += 4;
232 		 break;
233 	       case '>':
234 		 strcpy (ptr2, "&gt;");
235 		 ptr2 += 4;
236 		 break;
237 	       case '&':  /* &amp;  */
238 		 strcpy (ptr2, "&amp;");
239 		 ptr2 += 5;
240 		 break;
241 	       case '\'': /* &apos; */
242 		 strcpy (ptr2, "&apos;");
243 		 ptr2 += 6;
244 		 break;
245 	       case '"':  /* &quot; */
246 		 strcpy (ptr2, "&quot;");
247 		 ptr2 += 6;
248 		 break;
249 	       case '-':  /* &#x2d; */
250 		 strcpy (ptr2, "&#x2d;");
251 		 ptr2 += 6;
252 		 break;
253 	       default:
254 		 *ptr2++ = *ptr1;
255 		 break;
256 	       }
257 	     ++ptr1;
258 	   }
259 	 *ptr2 = 0;
260        }
261      return copy ? copy : itex2MML_empty_string;
262    }
263 
264  /* Create a hex character reference string corresponding to code
265   */
itex2MML_character_reference(unsigned long int code)266  char * itex2MML_character_reference (unsigned long int code)
267    {
268 #define ENTITY_LENGTH 10
269      char * entity = (char *) malloc(ENTITY_LENGTH);
270      sprintf(entity, "&#x%05lx;", code);
271      return entity;
272    }
273 
itex2MML_free_string(char * str)274  void itex2MML_free_string (char * str)
275    {
276      if (str && str != itex2MML_empty_string)
277        free(str);
278    }
279 
280 %}
281 
282 %left TEXOVER TEXATOP
283 %token CHAR STARTMATH STARTDMATH ENDMATH MI MIB MN MO SUP SUB MROWOPEN MROWCLOSE LEFT RIGHT BIG BBIG BIGG BBIGG BIGL BBIGL BIGGL BBIGGL FRAC TFRAC OPERATORNAME MATHOP MATHBIN MATHREL MOP MOL MOLL MOF MOR PERIODDELIM OTHERDELIM LEFTDELIM RIGHTDELIM MOS MOB SQRT ROOT BINOM TBINOM UNDER OVER OVERBRACE UNDERLINE UNDERBRACE UNDEROVER TENSOR MULTI ARRAYALIGN COLUMNALIGN ARRAY COLSEP ROWSEP ARRAYOPTS COLLAYOUT COLALIGN ROWALIGN ALIGN EQROWS EQCOLS ROWLINES COLLINES FRAME PADDING ATTRLIST ITALICS SANS TT BOLD BOXED SLASHED RM BB ST END BBLOWERCHAR BBUPPERCHAR BBDIGIT CALCHAR FRAKCHAR CAL SCR FRAK CLAP LLAP RLAP ROWOPTS TEXTSIZE SCSIZE SCSCSIZE DISPLAY TEXTSTY TEXTBOX TEXTSTRING XMLSTRING CELLOPTS ROWSPAN COLSPAN THINSPACE MEDSPACE THICKSPACE QUAD QQUAD NEGSPACE NEGMEDSPACE NEGTHICKSPACE PHANTOM HREF UNKNOWNCHAR EMPTYMROW STATLINE TOOLTIP TOGGLE TOGGLESTART TOGGLEEND FGHIGHLIGHT BGHIGHLIGHT SPACE INTONE INTTWO INTTHREE BAR WIDEBAR VEC WIDEVEC HAT WIDEHAT CHECK WIDECHECK TILDE WIDETILDE DOT DDOT DDDOT DDDDOT UNARYMINUS UNARYPLUS BEGINENV ENDENV MATRIX PMATRIX BMATRIX BBMATRIX VMATRIX VVMATRIX SVG ENDSVG SMALLMATRIX CASES ALIGNED GATHERED SUBSTACK PMOD RMCHAR COLOR BGCOLOR XARROW OPTARGOPEN OPTARGCLOSE ITEXNUM RAISEBOX NEG
284 
285 %%
286 
287 doc:  xmlmmlTermList {/* all processing done in body*/};
288 
289 xmlmmlTermList:
290 {/* nothing - do nothing*/}
291 | char {/* proc done in body*/}
292 | expression {/* all proc. in body*/}
293 | xmlmmlTermList char {/* all proc. in body*/}
294 | xmlmmlTermList expression {/* all proc. in body*/};
295 
296 char: CHAR {printf("%s", $1);};
297 
298 expression: STARTMATH ENDMATH {/* empty math group - ignore*/}
299 | STARTDMATH ENDMATH {/* ditto */}
300 | STARTMATH compoundTermList ENDMATH {
301   char ** r = (char **) ret_str;
302   char * p = itex2MML_copy3("<math xmlns='http://www.w3.org/1998/Math/MathML' display='inline'><semantics><mrow>", $2, "</mrow><annotation encoding='application/x-tex'>");
303   char * s = itex2MML_copy3(p, $3, "</annotation></semantics></math>");
304   itex2MML_free_string(p);
305   itex2MML_free_string($2);
306   itex2MML_free_string($3);
307   if (r) {
308     (*r) = (s == itex2MML_empty_string) ? 0 : s;
309   }
310   else {
311     if (itex2MML_write_mathml)
312       (*itex2MML_write_mathml) (s);
313     itex2MML_free_string(s);
314   }
315 }
316 | STARTDMATH compoundTermList ENDMATH {
317   char ** r = (char **) ret_str;
318   char * p = itex2MML_copy3("<math xmlns='http://www.w3.org/1998/Math/MathML' display='block'><semantics><mrow>", $2, "</mrow><annotation encoding='application/x-tex'>");
319   char * s = itex2MML_copy3(p, $3, "</annotation></semantics></math>");
320   itex2MML_free_string(p);
321   itex2MML_free_string($2);
322   itex2MML_free_string($3);
323   if (r) {
324     (*r) = (s == itex2MML_empty_string) ? 0 : s;
325   }
326   else {
327     if (itex2MML_write_mathml)
328       (*itex2MML_write_mathml) (s);
329     itex2MML_free_string(s);
330   }
331 };
332 
333 compoundTermList: compoundTerm {
334   $$ = itex2MML_copy_string($1);
335   itex2MML_free_string($1);
336 }
337 | compoundTermList compoundTerm {
338   $$ = itex2MML_copy2($1, $2);
339   itex2MML_free_string($1);
340   itex2MML_free_string($2);
341 };
342 
343 compoundTerm: mob SUB closedTerm SUP closedTerm {
344   if (itex2MML_displaymode == 1) {
345     char * s1 = itex2MML_copy3("<munderover>", $1, " ");
346     char * s2 = itex2MML_copy3($3, " ", $5);
347     $$ = itex2MML_copy3(s1, s2, "</munderover>");
348     itex2MML_free_string(s1);
349     itex2MML_free_string(s2);
350   }
351   else {
352     char * s1 = itex2MML_copy3("<msubsup>", $1, " ");
353     char * s2 = itex2MML_copy3($3, " ", $5);
354     $$ = itex2MML_copy3(s1, s2, "</msubsup>");
355     itex2MML_free_string(s1);
356     itex2MML_free_string(s2);
357   }
358   itex2MML_free_string($1);
359   itex2MML_free_string($3);
360   itex2MML_free_string($5);
361 }
362 | mob SUB closedTerm {
363   if (itex2MML_displaymode == 1) {
364     char * s1 = itex2MML_copy3("<munder>", $1, " ");
365     $$ = itex2MML_copy3(s1, $3, "</munder>");
366     itex2MML_free_string(s1);
367   }
368   else {
369     char * s1 = itex2MML_copy3("<msub>", $1, " ");
370     $$ = itex2MML_copy3(s1, $3, "</msub>");
371     itex2MML_free_string(s1);
372   }
373   itex2MML_free_string($1);
374   itex2MML_free_string($3);
375 }
376 | mob SUP closedTerm SUB closedTerm {
377   if (itex2MML_displaymode == 1) {
378     char * s1 = itex2MML_copy3("<munderover>", $1, " ");
379     char * s2 = itex2MML_copy3($5, " ", $3);
380     $$ = itex2MML_copy3(s1, s2, "</munderover>");
381     itex2MML_free_string(s1);
382     itex2MML_free_string(s2);
383   }
384   else {
385     char * s1 = itex2MML_copy3("<msubsup>", $1, " ");
386     char * s2 = itex2MML_copy3($5, " ", $3);
387     $$ = itex2MML_copy3(s1, s2, "</msubsup>");
388     itex2MML_free_string(s1);
389     itex2MML_free_string(s2);
390   }
391   itex2MML_free_string($1);
392   itex2MML_free_string($3);
393   itex2MML_free_string($5);
394 }
395 | mob SUP closedTerm {
396   if (itex2MML_displaymode == 1) {
397     char * s1 = itex2MML_copy3("<mover>", $1, " ");
398     $$ = itex2MML_copy3(s1, $3, "</mover>");
399     itex2MML_free_string(s1);
400   }
401   else {
402     char * s1 = itex2MML_copy3("<msup>", $1, " ");
403     $$ = itex2MML_copy3(s1, $3, "</msup>");
404     itex2MML_free_string(s1);
405   }
406   itex2MML_free_string($1);
407   itex2MML_free_string($3);
408 }
409 |mib SUB closedTerm SUP closedTerm {
410   if (itex2MML_displaymode == 1) {
411     char * s1 = itex2MML_copy3("<munderover>", $1, " ");
412     char * s2 = itex2MML_copy3($3, " ", $5);
413     $$ = itex2MML_copy3(s1, s2, "</munderover>");
414     itex2MML_free_string(s1);
415     itex2MML_free_string(s2);
416   }
417   else {
418     char * s1 = itex2MML_copy3("<msubsup>", $1, " ");
419     char * s2 = itex2MML_copy3($3, " ", $5);
420     $$ = itex2MML_copy3(s1, s2, "</msubsup>");
421     itex2MML_free_string(s1);
422     itex2MML_free_string(s2);
423   }
424   itex2MML_free_string($1);
425   itex2MML_free_string($3);
426   itex2MML_free_string($5);
427 }
428 | mib SUB closedTerm {
429   if (itex2MML_displaymode == 1) {
430     char * s1 = itex2MML_copy3("<munder>", $1, " ");
431     $$ = itex2MML_copy3(s1, $3, "</munder>");
432     itex2MML_free_string(s1);
433   }
434   else {
435     char * s1 = itex2MML_copy3("<msub>", $1, " ");
436     $$ = itex2MML_copy3(s1, $3, "</msub>");
437     itex2MML_free_string(s1);
438   }
439   itex2MML_free_string($1);
440   itex2MML_free_string($3);
441 }
442 | mib SUP closedTerm SUB closedTerm {
443   if (itex2MML_displaymode == 1) {
444     char * s1 = itex2MML_copy3("<munderover>", $1, " ");
445     char * s2 = itex2MML_copy3($5, " ", $3);
446     $$ = itex2MML_copy3(s1, s2, "</munderover>");
447     itex2MML_free_string(s1);
448     itex2MML_free_string(s2);
449   }
450   else {
451     char * s1 = itex2MML_copy3("<msubsup>", $1, " ");
452     char * s2 = itex2MML_copy3($5, " ", $3);
453     $$ = itex2MML_copy3(s1, s2, "</msubsup>");
454     itex2MML_free_string(s1);
455     itex2MML_free_string(s2);
456   }
457   itex2MML_free_string($1);
458   itex2MML_free_string($3);
459   itex2MML_free_string($5);
460 }
461 | mib SUP closedTerm {
462   if (itex2MML_displaymode == 1) {
463     char * s1 = itex2MML_copy3("<mover>", $1, " ");
464     $$ = itex2MML_copy3(s1, $3, "</mover>");
465     itex2MML_free_string(s1);
466   }
467   else {
468     char * s1 = itex2MML_copy3("<msup>", $1, " ");
469     $$ = itex2MML_copy3(s1, $3, "</msup>");
470     itex2MML_free_string(s1);
471   }
472   itex2MML_free_string($1);
473   itex2MML_free_string($3);
474 }
475 | closedTerm SUB closedTerm SUP closedTerm {
476   char * s1 = itex2MML_copy3("<msubsup>", $1, " ");
477   char * s2 = itex2MML_copy3($3, " ", $5);
478   $$ = itex2MML_copy3(s1, s2, "</msubsup>");
479   itex2MML_free_string(s1);
480   itex2MML_free_string(s2);
481   itex2MML_free_string($1);
482   itex2MML_free_string($3);
483   itex2MML_free_string($5);
484 }
485 | closedTerm SUP closedTerm SUB closedTerm {
486   char * s1 = itex2MML_copy3("<msubsup>", $1, " ");
487   char * s2 = itex2MML_copy3($5, " ", $3);
488   $$ = itex2MML_copy3(s1, s2, "</msubsup>");
489   itex2MML_free_string(s1);
490   itex2MML_free_string(s2);
491   itex2MML_free_string($1);
492   itex2MML_free_string($3);
493   itex2MML_free_string($5);
494 }
495 | closedTerm SUB closedTerm {
496   char * s1 = itex2MML_copy3("<msub>", $1, " ");
497   $$ = itex2MML_copy3(s1, $3, "</msub>");
498   itex2MML_free_string(s1);
499   itex2MML_free_string($1);
500   itex2MML_free_string($3);
501 }
502 | closedTerm SUP closedTerm {
503   char * s1 = itex2MML_copy3("<msup>", $1, " ");
504   $$ = itex2MML_copy3(s1, $3, "</msup>");
505   itex2MML_free_string(s1);
506   itex2MML_free_string($1);
507   itex2MML_free_string($3);
508 }
509 | SUB closedTerm {
510   $$ = itex2MML_copy3("<msub><mo/>", $2, "</msub>");
511   itex2MML_free_string($2);
512 }
513 | SUP closedTerm {
514   $$ = itex2MML_copy3("<msup><mo/>", $2, "</msup>");
515   itex2MML_free_string($2);
516 }
517 | closedTerm {
518   $$ = itex2MML_copy_string($1);
519   itex2MML_free_string($1);
520 };
521 
522 closedTerm: array
523 | unaryminus
524 | unaryplus
525 | mib
526 | mi {
527   $$ = itex2MML_copy3("<mi>", $1, "</mi>");
528   itex2MML_free_string($1);
529 }
530 | mn {
531   $$ = itex2MML_copy3("<mn>", $1, "</mn>");
532   itex2MML_free_string($1);
533 }
534 | mo
535 | tensor
536 | multi
537 | mfrac
538 | binom
539 | msqrt
540 | mroot
541 | raisebox
542 | munder
543 | mover
544 | bar
545 | vec
546 | hat
547 | dot
548 | ddot
549 | dddot
550 | ddddot
551 | check
552 | tilde
553 | moverbrace
554 | munderbrace
555 | munderline
556 | munderover
557 | emptymrow
558 | mathclap
559 | mathllap
560 | mathrlap
561 | displaystyle
562 | textstyle
563 | textsize
564 | scriptsize
565 | scriptscriptsize
566 | italics
567 | sans
568 | mono
569 | bold
570 | roman
571 | rmchars
572 | bbold
573 | frak
574 | slashed
575 | boxed
576 | cal
577 | scr
578 | space
579 | textstring
580 | thinspace
581 | medspace
582 | thickspace
583 | quad
584 | qquad
585 | negspace
586 | negmedspace
587 | negthickspace
588 | phantom
589 | href
590 | statusline
591 | tooltip
592 | toggle
593 | fghighlight
594 | bghighlight
595 | color
596 | texover
597 | texatop
598 | MROWOPEN closedTerm MROWCLOSE {
599   $$ = itex2MML_copy_string($2);
600   itex2MML_free_string($2);
601 }
602 | MROWOPEN compoundTermList MROWCLOSE {
603   $$ = itex2MML_copy3("<mrow>", $2, "</mrow>");
604   itex2MML_free_string($2);
605 }
606 | left compoundTermList right {
607   char * s1 = itex2MML_copy3("<mrow>", $1, $2);
608   $$ = itex2MML_copy3(s1, $3, "</mrow>");
609   itex2MML_free_string(s1);
610   itex2MML_free_string($1);
611   itex2MML_free_string($2);
612   itex2MML_free_string($3);
613 }
614 | mathenv
615 | substack
616 | pmod
617 | unrecognized;
618 
619 left: LEFT LEFTDELIM {
620   itex2MML_rowposn = 2;
621   $$ = itex2MML_copy3("<mo>", $2, "</mo>");
622   itex2MML_free_string($2);
623 }
624 | LEFT OTHERDELIM {
625   itex2MML_rowposn = 2;
626   $$ = itex2MML_copy3("<mo>", $2, "</mo>");
627   itex2MML_free_string($2);
628 }
629 | LEFT PERIODDELIM {
630   itex2MML_rowposn = 2;
631   $$ = itex2MML_copy_string("");
632   itex2MML_free_string($2);
633 };
634 
635 right: RIGHT RIGHTDELIM {
636   $$ = itex2MML_copy3("<mo>", $2, "</mo>");
637   itex2MML_free_string($2);
638 }
639 | RIGHT OTHERDELIM {
640   $$ = itex2MML_copy3("<mo>", $2, "</mo>");
641   itex2MML_free_string($2);
642 }
643 | RIGHT PERIODDELIM {
644   $$ = itex2MML_copy_string("");
645   itex2MML_free_string($2);
646 };
647 
648 bigdelim: BIG LEFTDELIM {
649   itex2MML_rowposn = 2;
650   $$ = itex2MML_copy3("<mo maxsize=\"1.2em\" minsize=\"1.2em\">", $2, "</mo>");
651   itex2MML_free_string($2);
652 }
653 | BIG RIGHTDELIM {
654   $$ = itex2MML_copy3("<mo maxsize=\"1.2em\" minsize=\"1.2em\">", $2, "</mo>");
655   itex2MML_free_string($2);
656 }
657 | BIG OTHERDELIM {
658   $$ = itex2MML_copy3("<mo maxsize=\"1.2em\" minsize=\"1.2em\">", $2, "</mo>");
659   itex2MML_free_string($2);
660 }
661 | BBIG LEFTDELIM {
662   itex2MML_rowposn = 2;
663   $$ = itex2MML_copy3("<mo maxsize=\"1.8em\" minsize=\"1.8em\">", $2, "</mo>");
664   itex2MML_free_string($2);
665 }
666 | BBIG RIGHTDELIM {
667   $$ = itex2MML_copy3("<mo maxsize=\"1.8em\" minsize=\"1.8em\">", $2, "</mo>");
668   itex2MML_free_string($2);
669 }
670 | BBIG OTHERDELIM {
671   $$ = itex2MML_copy3("<mo maxsize=\"1.8em\" minsize=\"1.8em\">", $2, "</mo>");
672   itex2MML_free_string($2);
673 }
674 | BIGG LEFTDELIM {
675   itex2MML_rowposn = 2;
676   $$ = itex2MML_copy3("<mo maxsize=\"2.4em\" minsize=\"2.4em\">", $2, "</mo>");
677   itex2MML_free_string($2);
678 }
679 | BIGG RIGHTDELIM {
680   $$ = itex2MML_copy3("<mo maxsize=\"2.4em\" minsize=\"2.4em\">", $2, "</mo>");
681   itex2MML_free_string($2);
682 }
683 | BIGG OTHERDELIM {
684   $$ = itex2MML_copy3("<mo maxsize=\"2.4em\" minsize=\"2.4em\">", $2, "</mo>");
685   itex2MML_free_string($2);
686 }
687 | BBIGG LEFTDELIM {
688   itex2MML_rowposn = 2;
689   $$ = itex2MML_copy3("<mo maxsize=\"3em\" minsize=\"3em\">", $2, "</mo>");
690   itex2MML_free_string($2);
691 }
692 | BBIGG RIGHTDELIM {
693   $$ = itex2MML_copy3("<mo maxsize=\"3em\" minsize=\"3em\">", $2, "</mo>");
694   itex2MML_free_string($2);
695 }
696 | BBIGG OTHERDELIM {
697   $$ = itex2MML_copy3("<mo maxsize=\"3em\" minsize=\"3em\">", $2, "</mo>");
698   itex2MML_free_string($2);
699 }
700 |BIGL LEFTDELIM {
701   itex2MML_rowposn = 2;
702   $$ = itex2MML_copy3("<mo maxsize=\"1.2em\" minsize=\"1.2em\">", $2, "</mo>");
703   itex2MML_free_string($2);
704 }
705 | BIGL OTHERDELIM {
706   itex2MML_rowposn = 2;
707   $$ = itex2MML_copy3("<mo maxsize=\"1.2em\" minsize=\"1.2em\">", $2, "</mo>");
708   itex2MML_free_string($2);
709 }
710 | BBIGL LEFTDELIM {
711   itex2MML_rowposn = 2;
712   $$ = itex2MML_copy3("<mo maxsize=\"1.8em\" minsize=\"1.8em\">", $2, "</mo>");
713   itex2MML_free_string($2);
714 }
715 | BBIGL OTHERDELIM {
716   itex2MML_rowposn = 2;
717   $$ = itex2MML_copy3("<mo maxsize=\"1.8em\" minsize=\"1.8em\">", $2, "</mo>");
718   itex2MML_free_string($2);
719 }
720 | BIGGL LEFTDELIM {
721   itex2MML_rowposn = 2;
722   $$ = itex2MML_copy3("<mo maxsize=\"2.4em\" minsize=\"2.4em\">", $2, "</mo>");
723   itex2MML_free_string($2);
724 }
725 | BIGGL OTHERDELIM {
726   itex2MML_rowposn = 2;
727   $$ = itex2MML_copy3("<mo maxsize=\"2.4em\" minsize=\"2.4em\">", $2, "</mo>");
728   itex2MML_free_string($2);
729 }
730 | BBIGGL LEFTDELIM {
731   itex2MML_rowposn = 2;
732   $$ = itex2MML_copy3("<mo maxsize=\"3em\" minsize=\"3em\">", $2, "</mo>");
733   itex2MML_free_string($2);
734 }
735 | BBIGGL OTHERDELIM {
736   itex2MML_rowposn = 2;
737   $$ = itex2MML_copy3("<mo maxsize=\"3em\" minsize=\"3em\">", $2, "</mo>");
738   itex2MML_free_string($2);
739 };
740 
741 unrecognized: UNKNOWNCHAR {
742   $$ = itex2MML_copy_string("<merror><mtext>Unknown character</mtext></merror>");
743 };
744 
745 unaryminus: UNARYMINUS {
746   $$ = itex2MML_copy_string("<mo lspace=\"verythinmathspace\" rspace=\"0em\">&minus;</mo>");
747 };
748 
749 unaryplus: UNARYPLUS {
750   $$ = itex2MML_copy_string("<mo lspace=\"verythinmathspace\" rspace=\"0em\">+</mo>");
751 };
752 
753 mi: MI;
754 
755 mib: MIB {
756   itex2MML_rowposn=2;
757   $$ = itex2MML_copy3("<mi>", $1, "</mi>");
758   itex2MML_free_string($1);
759 };
760 
761 mn: MN
762 | ITEXNUM TEXTSTRING {
763   itex2MML_rowposn = 2;
764   $$ = itex2MML_copy_string($2);
765   itex2MML_free_string($2);
766 };
767 
768 mob: MOB {
769   itex2MML_rowposn = 2;
770   $$ = itex2MML_copy3("<mo lspace=\"thinmathspace\" rspace=\"thinmathspace\">", $1, "</mo>");
771   itex2MML_free_string($1);
772 };
773 
774 mo: mob
775 | bigdelim
776 | MO {
777   itex2MML_rowposn = 2;
778   $$ = itex2MML_copy3("<mo>", $1, "</mo>");
779   itex2MML_free_string($1);
780 }
781 | MOL {
782   itex2MML_rowposn = 2;
783   $$ = itex2MML_copy3("<mo>", $1, "</mo>");
784   itex2MML_free_string($1);
785 }
786 | MOLL {
787   itex2MML_rowposn = 2;
788   $$ = itex2MML_copy3("<mstyle scriptlevel=\"0\"><mo>", $1, "</mo></mstyle>");
789   itex2MML_free_string($1);
790 }
791 | RIGHTDELIM {
792   $$ = itex2MML_copy3("<mo stretchy=\"false\">", $1, "</mo>");
793   itex2MML_free_string($1);
794 }
795 | LEFTDELIM {
796   itex2MML_rowposn = 2;
797   $$ = itex2MML_copy3("<mo stretchy=\"false\">", $1, "</mo>");
798   itex2MML_free_string($1);
799 }
800 | OTHERDELIM {
801   $$ = itex2MML_copy3("<mo stretchy=\"false\">", $1, "</mo>");
802   itex2MML_free_string($1);
803 }
804 | MOF {
805   $$ = itex2MML_copy3("<mo stretchy=\"false\">", $1, "</mo>");
806   itex2MML_free_string($1);
807 }
808 | PERIODDELIM {
809   $$ = itex2MML_copy3("<mo>", $1, "</mo>");
810   itex2MML_free_string($1);
811 }
812 | MOS {
813   itex2MML_rowposn=2;
814   $$ = itex2MML_copy3("<mo lspace=\"mediummathspace\" rspace=\"mediummathspace\">", $1, "</mo>");
815   itex2MML_free_string($1);
816 }
817 | MOP {
818   itex2MML_rowposn = 2;
819   $$ = itex2MML_copy3("<mo lspace=\"0em\" rspace=\"thinmathspace\">", $1, "</mo>");
820   itex2MML_free_string($1);
821 }
822 | MOR {
823   itex2MML_rowposn = 2;
824   $$ = itex2MML_copy3("<mo lspace=\"verythinmathspace\">", $1, "</mo>");
825   itex2MML_free_string($1);
826 }
827 | OPERATORNAME TEXTSTRING {
828   itex2MML_rowposn = 2;
829   $$ = itex2MML_copy3("<mo lspace=\"0em\" rspace=\"thinmathspace\">", $2, "</mo>");
830   itex2MML_free_string($2);
831 }
832 | MATHOP TEXTSTRING {
833   itex2MML_rowposn = 2;
834   $$ = itex2MML_copy3("<mo lspace=\"thinmathspace\" rspace=\"thinmathspace\">", $2, "</mo>");
835   itex2MML_free_string($2);
836 }
837 | MATHBIN TEXTSTRING {
838   itex2MML_rowposn = 2;
839   $$ = itex2MML_copy3("<mo lspace=\"mediummathspace\" rspace=\"mediummathspace\">", $2, "</mo>");
840   itex2MML_free_string($2);
841 }
842 | MATHREL TEXTSTRING {
843   itex2MML_rowposn = 2;
844   $$ = itex2MML_copy3("<mo lspace=\"thickmathspace\" rspace=\"thickmathspace\">", $2, "</mo>");
845   itex2MML_free_string($2);
846 };
847 
848 space: SPACE ST INTONE END ST INTTWO END ST INTTHREE END {
849   char * s1 = itex2MML_copy3("<mspace height=\"", $3, "ex\" depth=\"");
850   char * s2 = itex2MML_copy3($6, "ex\" width=\"", $9);
851   $$ = itex2MML_copy3(s1, s2, "em\"/>");
852   itex2MML_free_string(s1);
853   itex2MML_free_string(s2);
854   itex2MML_free_string($3);
855   itex2MML_free_string($6);
856   itex2MML_free_string($9);
857 };
858 
859 statusline: STATLINE TEXTSTRING closedTerm {
860   char * s1 = itex2MML_copy3("<maction actiontype=\"statusline\">", $3, "<mtext>");
861   $$ = itex2MML_copy3(s1, $2, "</mtext></maction>");
862   itex2MML_free_string(s1);
863   itex2MML_free_string($2);
864   itex2MML_free_string($3);
865 };
866 
867 tooltip: TOOLTIP TEXTSTRING closedTerm {
868   char * s1 = itex2MML_copy3("<maction actiontype=\"tooltip\">", $3, "<mtext>");
869   $$ = itex2MML_copy3(s1, $2, "</mtext></maction>");
870   itex2MML_free_string(s1);
871   itex2MML_free_string($2);
872   itex2MML_free_string($3);
873 };
874 
875 toggle: TOGGLE closedTerm closedTerm {
876   char * s1 = itex2MML_copy3("<maction actiontype=\"toggle\" selection=\"2\">", $2, " ");
877   $$ = itex2MML_copy3(s1, $3, "</maction>");
878   itex2MML_free_string(s1);
879   itex2MML_free_string($2);
880   itex2MML_free_string($3);
881 }
882 | TOGGLESTART compoundTermList TOGGLEEND {
883   $$ = itex2MML_copy3("<maction actiontype=\"toggle\">", $2, "</maction>");
884   itex2MML_free_string($2);
885 };
886 
887 fghighlight: FGHIGHLIGHT ATTRLIST closedTerm {
888   char * s1 = itex2MML_copy3("<maction actiontype=\"highlight\" other='color=", $2, "'>");
889   $$ = itex2MML_copy3(s1, $3, "</maction>");
890   itex2MML_free_string(s1);
891   itex2MML_free_string($2);
892   itex2MML_free_string($3);
893 };
894 
895 bghighlight: BGHIGHLIGHT ATTRLIST closedTerm {
896   char * s1 = itex2MML_copy3("<maction actiontype=\"highlight\" other='background=", $2, "'>");
897   $$ = itex2MML_copy3(s1, $3, "</maction>");
898   itex2MML_free_string(s1);
899   itex2MML_free_string($2);
900   itex2MML_free_string($3);
901 };
902 
903 color: COLOR ATTRLIST compoundTermList {
904   char * s1 = itex2MML_copy3("<mstyle mathcolor=", $2, ">");
905   $$ = itex2MML_copy3(s1, $3, "</mstyle>");
906   itex2MML_free_string(s1);
907   itex2MML_free_string($2);
908   itex2MML_free_string($3);
909 }
910 | BGCOLOR ATTRLIST compoundTermList {
911   char * s1 = itex2MML_copy3("<mstyle mathbackground=", $2, ">");
912   $$ = itex2MML_copy3(s1, $3, "</mstyle>");
913   itex2MML_free_string(s1);
914   itex2MML_free_string($2);
915   itex2MML_free_string($3);
916 };
917 
918 mathrlap: RLAP closedTerm {
919   $$ = itex2MML_copy3("<mpadded width=\"0\">", $2, "</mpadded>");
920   itex2MML_free_string($2);
921 };
922 
923 mathllap: LLAP closedTerm {
924   $$ = itex2MML_copy3("<mpadded width=\"0\" lspace=\"-100%width\">", $2, "</mpadded>");
925   itex2MML_free_string($2);
926 };
927 
928 mathclap: CLAP closedTerm {
929   $$ = itex2MML_copy3("<mpadded width=\"0\" lspace=\"-50%width\">", $2, "</mpadded>");
930   itex2MML_free_string($2);
931 };
932 
933 textstring: TEXTBOX TEXTSTRING {
934   $$ = itex2MML_copy3("<mtext>", $2, "</mtext>");
935   itex2MML_free_string($2);
936 };
937 
938 displaystyle: DISPLAY compoundTermList {
939   $$ = itex2MML_copy3("<mstyle displaystyle=\"true\">", $2, "</mstyle>");
940   itex2MML_free_string($2);
941 };
942 
943 textstyle: TEXTSTY compoundTermList {
944   $$ = itex2MML_copy3("<mstyle displaystyle=\"false\">", $2, "</mstyle>");
945   itex2MML_free_string($2);
946 };
947 
948 textsize: TEXTSIZE compoundTermList {
949   $$ = itex2MML_copy3("<mstyle scriptlevel=\"0\">", $2, "</mstyle>");
950   itex2MML_free_string($2);
951 };
952 
953 scriptsize: SCSIZE compoundTermList {
954   $$ = itex2MML_copy3("<mstyle scriptlevel=\"1\">", $2, "</mstyle>");
955   itex2MML_free_string($2);
956 };
957 
958 scriptscriptsize: SCSCSIZE compoundTermList {
959   $$ = itex2MML_copy3("<mstyle scriptlevel=\"2\">", $2, "</mstyle>");
960   itex2MML_free_string($2);
961 };
962 
963 italics: ITALICS closedTerm {
964   $$ = itex2MML_copy3("<mstyle mathvariant=\"italic\">", $2, "</mstyle>");
965   itex2MML_free_string($2);
966 };
967 
968 sans: SANS closedTerm {
969   $$ = itex2MML_copy3("<mstyle mathvariant=\"sans-serif\">", $2, "</mstyle>");
970   itex2MML_free_string($2);
971 };
972 
973 mono: TT closedTerm {
974   $$ = itex2MML_copy3("<mstyle mathvariant=\"monospace\">", $2, "</mstyle>");
975   itex2MML_free_string($2);
976 };
977 
978 slashed: SLASHED closedTerm {
979   $$ = itex2MML_copy3("<menclose notation=\"updiagonalstrike\">", $2, "</menclose>");
980   itex2MML_free_string($2);
981 };
982 
983 boxed: BOXED closedTerm {
984   $$ = itex2MML_copy3("<menclose notation=\"box\">", $2, "</menclose>");
985   itex2MML_free_string($2);
986 };
987 
988 bold: BOLD closedTerm {
989   $$ = itex2MML_copy3("<mstyle mathvariant=\"bold\">", $2, "</mstyle>");
990   itex2MML_free_string($2);
991 };
992 
993 roman: RM ST rmchars END {
994   $$ = itex2MML_copy3("<mi mathvariant=\"normal\">", $3, "</mi>");
995   itex2MML_free_string($3);
996 };
997 
998 rmchars: RMCHAR {
999   $$ = itex2MML_copy_string($1);
1000   itex2MML_free_string($1);
1001 }
1002 | rmchars RMCHAR {
1003   $$ = itex2MML_copy2($1, $2);
1004   itex2MML_free_string($1);
1005   itex2MML_free_string($2);
1006 };
1007 
1008 bbold: BB ST bbchars END {
1009   $$ = itex2MML_copy3("<mi>", $3, "</mi>");
1010   itex2MML_free_string($3);
1011 };
1012 
1013 bbchars: bbchar {
1014   $$ = itex2MML_copy_string($1);
1015   itex2MML_free_string($1);
1016 }
1017 | bbchars bbchar {
1018   $$ = itex2MML_copy2($1, $2);
1019   itex2MML_free_string($1);
1020   itex2MML_free_string($2);
1021 };
1022 
1023 bbchar: BBLOWERCHAR {
1024   $$ = itex2MML_copy3("&", $1, "opf;");
1025   itex2MML_free_string($1);
1026 }
1027 | BBUPPERCHAR {
1028   $$ = itex2MML_copy3("&", $1, "opf;");
1029   itex2MML_free_string($1);
1030 }
1031 | BBDIGIT {
1032   /* Blackboard digits 0-9 correspond to Unicode characters 0x1D7D8-0x1D7E1 */
1033   char * end = $1 + 1;
1034   int code = 0x1D7D8 + strtoul($1, &end, 10);
1035   $$ = itex2MML_character_reference(code);
1036   itex2MML_free_string($1);
1037 };
1038 
1039 frak: FRAK ST frakletters END {
1040   $$ = itex2MML_copy3("<mi>", $3, "</mi>");
1041   itex2MML_free_string($3);
1042 };
1043 
1044 frakletters: frakletter {
1045   $$ = itex2MML_copy_string($1);
1046   itex2MML_free_string($1);
1047 }
1048 | frakletters frakletter {
1049   $$ = itex2MML_copy2($1, $2);
1050   itex2MML_free_string($1);
1051   itex2MML_free_string($2);
1052 };
1053 
1054 frakletter: FRAKCHAR {
1055   $$ = itex2MML_copy3("&", $1, "fr;");
1056   itex2MML_free_string($1);
1057 };
1058 
1059 cal: CAL ST calletters END {
1060   $$ = itex2MML_copy3("<mi>", $3, "</mi>");
1061   itex2MML_free_string($3);
1062 };
1063 
1064 scr: SCR ST calletters END {
1065   $$ = itex2MML_copy3("<mi class='mathscript'>", $3, "</mi>");
1066   itex2MML_free_string($3);
1067 };
1068 
1069 calletters: calletter {
1070   $$ = itex2MML_copy_string($1);
1071   itex2MML_free_string($1);
1072 }
1073 | calletters calletter {
1074   $$ = itex2MML_copy2($1, $2);
1075   itex2MML_free_string($1);
1076   itex2MML_free_string($2);
1077 };
1078 
1079 calletter: CALCHAR {
1080   $$ = itex2MML_copy3("&", $1, "scr;");
1081   itex2MML_free_string($1);
1082 };
1083 
1084 thinspace: THINSPACE {
1085   $$ = itex2MML_copy_string("<mspace width=\"thinmathspace\"/>");
1086 };
1087 
1088 medspace: MEDSPACE {
1089   $$ = itex2MML_copy_string("<mspace width=\"mediummathspace\"/>");
1090 };
1091 
1092 thickspace: THICKSPACE {
1093   $$ = itex2MML_copy_string("<mspace width=\"thickmathspace\"/>");
1094 };
1095 
1096 quad: QUAD {
1097   $$ = itex2MML_copy_string("<mspace width=\"1em\"/>");
1098 };
1099 
1100 qquad: QQUAD {
1101   $$ = itex2MML_copy_string("<mspace width=\"2em\"/>");
1102 };
1103 
1104 negspace: NEGSPACE {
1105   $$ = itex2MML_copy_string("<mspace width=\"negativethinmathspace\"/>");
1106 };
1107 
1108 negmedspace: NEGMEDSPACE {
1109   $$ = itex2MML_copy_string("<mspace width=\"negativemediummathspace\"/>");
1110 };
1111 
1112 negthickspace: NEGTHICKSPACE {
1113   $$ = itex2MML_copy_string("<mspace width=\"negativethickmathspace\"/>");
1114 };
1115 
1116 phantom: PHANTOM closedTerm {
1117   $$ = itex2MML_copy3("<mphantom>", $2, "</mphantom>");
1118   itex2MML_free_string($2);
1119 };
1120 
1121 href: HREF TEXTSTRING closedTerm {
1122   char * s1 = itex2MML_copy3("<mrow href=\"", $2, "\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xlink:type=\"simple\" xlink:href=\"");
1123   char * s2 = itex2MML_copy3(s1, $2, "\">");
1124   $$ = itex2MML_copy3(s2, $3, "</mrow>");
1125   itex2MML_free_string(s1);
1126   itex2MML_free_string(s2);
1127   itex2MML_free_string($2);
1128   itex2MML_free_string($3);
1129 };
1130 
1131 tensor: TENSOR closedTerm MROWOPEN subsupList MROWCLOSE {
1132   char * s1 = itex2MML_copy3("<mmultiscripts>", $2, $4);
1133   $$ = itex2MML_copy2(s1, "</mmultiscripts>");
1134   itex2MML_free_string(s1);
1135   itex2MML_free_string($2);
1136   itex2MML_free_string($4);
1137 }
1138 | TENSOR closedTerm subsupList {
1139   char * s1 = itex2MML_copy3("<mmultiscripts>", $2, $3);
1140   $$ = itex2MML_copy2(s1, "</mmultiscripts>");
1141   itex2MML_free_string(s1);
1142   itex2MML_free_string($2);
1143   itex2MML_free_string($3);
1144 };
1145 
1146 multi: MULTI MROWOPEN subsupList MROWCLOSE closedTerm MROWOPEN subsupList MROWCLOSE {
1147   char * s1 = itex2MML_copy3("<mmultiscripts>", $5, $7);
1148   char * s2 = itex2MML_copy3("<mprescripts/>", $3, "</mmultiscripts>");
1149   $$ = itex2MML_copy2(s1, s2);
1150   itex2MML_free_string(s1);
1151   itex2MML_free_string(s2);
1152   itex2MML_free_string($3);
1153   itex2MML_free_string($5);
1154   itex2MML_free_string($7);
1155 }
1156 | MULTI MROWOPEN subsupList MROWCLOSE closedTerm EMPTYMROW {
1157   char * s1 = itex2MML_copy2("<mmultiscripts>", $5);
1158   char * s2 = itex2MML_copy3("<mprescripts/>", $3, "</mmultiscripts>");
1159   $$ = itex2MML_copy2(s1, s2);
1160   itex2MML_free_string(s1);
1161   itex2MML_free_string(s2);
1162   itex2MML_free_string($3);
1163   itex2MML_free_string($5);
1164 }
1165 | MULTI EMPTYMROW closedTerm MROWOPEN subsupList MROWCLOSE {
1166   char * s1 = itex2MML_copy3("<mmultiscripts>", $3, $5);
1167   $$ = itex2MML_copy2(s1, "</mmultiscripts>");
1168   itex2MML_free_string(s1);
1169   itex2MML_free_string($3);
1170   itex2MML_free_string($5);
1171 };
1172 
1173 subsupList: subsupTerm {
1174   $$ = itex2MML_copy_string($1);
1175   itex2MML_free_string($1);
1176 }
1177 | subsupList subsupTerm {
1178   $$ = itex2MML_copy3($1, " ", $2);
1179   itex2MML_free_string($1);
1180   itex2MML_free_string($2);
1181 };
1182 
1183 subsupTerm: SUB closedTerm SUP closedTerm {
1184   $$ = itex2MML_copy3($2, " ", $4);
1185   itex2MML_free_string($2);
1186   itex2MML_free_string($4);
1187 }
1188 | SUB closedTerm {
1189   $$ = itex2MML_copy2($2, " <none/>");
1190   itex2MML_free_string($2);
1191 }
1192 | SUP closedTerm {
1193   $$ = itex2MML_copy2("<none/> ", $2);
1194   itex2MML_free_string($2);
1195 }
1196 | SUB SUP closedTerm {
1197   $$ = itex2MML_copy2("<none/> ", $3);
1198   itex2MML_free_string($3);
1199 };
1200 
1201 mfrac: FRAC closedTerm closedTerm {
1202   char * s1 = itex2MML_copy3("<mfrac>", $2, $3);
1203   $$ = itex2MML_copy2(s1, "</mfrac>");
1204   itex2MML_free_string(s1);
1205   itex2MML_free_string($2);
1206   itex2MML_free_string($3);
1207 }
1208 | TFRAC closedTerm closedTerm {
1209   char * s1 = itex2MML_copy3("<mstyle displaystyle=\"false\"><mfrac>", $2, $3);
1210   $$ = itex2MML_copy2(s1, "</mfrac></mstyle>");
1211   itex2MML_free_string(s1);
1212   itex2MML_free_string($2);
1213   itex2MML_free_string($3);
1214 };
1215 
1216 pmod: PMOD closedTerm {
1217   $$ = itex2MML_copy3( "<mrow><mo lspace=\"mediummathspace\">(</mo><mo rspace=\"thinmathspace\">mod</mo>", $2, "<mo rspace=\"mediummathspace\">)</mo></mrow>");
1218   itex2MML_free_string($2);
1219 }
1220 
1221 texover: MROWOPEN compoundTermList TEXOVER compoundTermList MROWCLOSE {
1222   char * s1 = itex2MML_copy3("<mfrac><mrow>", $2, "</mrow><mrow>");
1223   $$ = itex2MML_copy3(s1, $4, "</mrow></mfrac>");
1224   itex2MML_free_string(s1);
1225   itex2MML_free_string($2);
1226   itex2MML_free_string($4);
1227 }
1228 | left compoundTermList TEXOVER compoundTermList right {
1229   char * s1 = itex2MML_copy3("<mrow>", $1, "<mfrac><mrow>");
1230   char * s2 = itex2MML_copy3($2, "</mrow><mrow>", $4);
1231   char * s3 = itex2MML_copy3("</mrow></mfrac>", $5, "</mrow>");
1232   $$ = itex2MML_copy3(s1, s2, s3);
1233   itex2MML_free_string(s1);
1234   itex2MML_free_string(s2);
1235   itex2MML_free_string(s3);
1236   itex2MML_free_string($1);
1237   itex2MML_free_string($2);
1238   itex2MML_free_string($4);
1239   itex2MML_free_string($5);
1240 };
1241 
1242 texatop: MROWOPEN compoundTermList TEXATOP compoundTermList MROWCLOSE {
1243   char * s1 = itex2MML_copy3("<mfrac linethickness=\"0\"><mrow>", $2, "</mrow><mrow>");
1244   $$ = itex2MML_copy3(s1, $4, "</mrow></mfrac>");
1245   itex2MML_free_string(s1);
1246   itex2MML_free_string($2);
1247   itex2MML_free_string($4);
1248 }
1249 | left compoundTermList TEXATOP compoundTermList right {
1250   char * s1 = itex2MML_copy3("<mrow>", $1, "<mfrac linethickness=\"0\"><mrow>");
1251   char * s2 = itex2MML_copy3($2, "</mrow><mrow>", $4);
1252   char * s3 = itex2MML_copy3("</mrow></mfrac>", $5, "</mrow>");
1253   $$ = itex2MML_copy3(s1, s2, s3);
1254   itex2MML_free_string(s1);
1255   itex2MML_free_string(s2);
1256   itex2MML_free_string(s3);
1257   itex2MML_free_string($1);
1258   itex2MML_free_string($2);
1259   itex2MML_free_string($4);
1260   itex2MML_free_string($5);
1261 };
1262 
1263 binom: BINOM closedTerm closedTerm {
1264   char * s1 = itex2MML_copy3("<mrow><mo>(</mo><mfrac linethickness=\"0\">", $2, $3);
1265   $$ = itex2MML_copy2(s1, "</mfrac><mo>)</mo></mrow>");
1266   itex2MML_free_string(s1);
1267   itex2MML_free_string($2);
1268   itex2MML_free_string($3);
1269 }
1270 | TBINOM closedTerm closedTerm {
1271   char * s1 = itex2MML_copy3("<mrow><mo>(</mo><mstyle displaystyle=\"false\"><mfrac linethickness=\"0\">", $2, $3);
1272   $$ = itex2MML_copy2(s1, "</mfrac></mstyle><mo>)</mo></mrow>");
1273   itex2MML_free_string(s1);
1274   itex2MML_free_string($2);
1275   itex2MML_free_string($3);
1276 };
1277 
1278 munderbrace: UNDERBRACE closedTerm {
1279   $$ = itex2MML_copy3("<munder>", $2, "<mo>&UnderBrace;</mo></munder>");
1280   itex2MML_free_string($2);
1281 };
1282 
1283 munderline: UNDERLINE closedTerm {
1284   $$ = itex2MML_copy3("<munder>", $2, "<mo>&#x00332;</mo></munder>");
1285   itex2MML_free_string($2);
1286 };
1287 
1288 moverbrace: OVERBRACE closedTerm {
1289   $$ = itex2MML_copy3("<mover>", $2, "<mo>&OverBrace;</mo></mover>");
1290   itex2MML_free_string($2);
1291 };
1292 
1293 bar: BAR closedTerm {
1294   $$ = itex2MML_copy3("<mover>", $2, "<mo stretchy=\"false\">&#x000AF;</mo></mover>");
1295   itex2MML_free_string($2);
1296 }
1297 | WIDEBAR closedTerm {
1298   $$ = itex2MML_copy3("<mover>", $2, "<mo>&#x000AF;</mo></mover>");
1299   itex2MML_free_string($2);
1300 };
1301 
1302 vec: VEC closedTerm {
1303   $$ = itex2MML_copy3("<mover>", $2, "<mo stretchy=\"false\">&RightVector;</mo></mover>");
1304   itex2MML_free_string($2);
1305 }
1306 | WIDEVEC closedTerm {
1307   $$ = itex2MML_copy3("<mover>", $2, "<mo>&RightVector;</mo></mover>");
1308   itex2MML_free_string($2);
1309 };
1310 
1311 dot: DOT closedTerm {
1312   $$ = itex2MML_copy3("<mover>", $2, "<mo>&dot;</mo></mover>");
1313   itex2MML_free_string($2);
1314 };
1315 
1316 ddot: DDOT closedTerm {
1317   $$ = itex2MML_copy3("<mover>", $2, "<mo>&Dot;</mo></mover>");
1318   itex2MML_free_string($2);
1319 };
1320 
1321 dddot: DDDOT closedTerm {
1322   $$ = itex2MML_copy3("<mover>", $2, "<mo>&tdot;</mo></mover>");
1323   itex2MML_free_string($2);
1324 };
1325 
1326 ddddot: DDDDOT closedTerm {
1327   $$ = itex2MML_copy3("<mover>", $2, "<mo>&DotDot;</mo></mover>");
1328   itex2MML_free_string($2);
1329 };
1330 
1331 tilde: TILDE closedTerm {
1332   $$ = itex2MML_copy3("<mover>", $2, "<mo stretchy=\"false\">&tilde;</mo></mover>");
1333   itex2MML_free_string($2);
1334 }
1335 | WIDETILDE closedTerm {
1336   $$ = itex2MML_copy3("<mover>", $2, "<mo>&tilde;</mo></mover>");
1337   itex2MML_free_string($2);
1338 };
1339 
1340 check: CHECK closedTerm {
1341   $$ = itex2MML_copy3("<mover>", $2, "<mo stretchy=\"false\">&#x2c7;</mo></mover>");
1342   itex2MML_free_string($2);
1343 }
1344 | WIDECHECK closedTerm {
1345   $$ = itex2MML_copy3("<mover>", $2, "<mo>&#x2c7;</mo></mover>");
1346   itex2MML_free_string($2);
1347 };
1348 
1349 hat: HAT closedTerm {
1350   $$ = itex2MML_copy3("<mover>", $2, "<mo stretchy=\"false\">&#x5E;</mo></mover>");
1351   itex2MML_free_string($2);
1352 }
1353 | WIDEHAT closedTerm {
1354   $$ = itex2MML_copy3("<mover>", $2, "<mo>&#x5E;</mo></mover>");
1355   itex2MML_free_string($2);
1356 };
1357 
1358 msqrt: SQRT closedTerm {
1359   $$ = itex2MML_copy3("<msqrt>", $2, "</msqrt>");
1360   itex2MML_free_string($2);
1361 };
1362 
1363 mroot: SQRT OPTARGOPEN compoundTermList OPTARGCLOSE closedTerm {
1364   char * s1 = itex2MML_copy3("<mroot>", $5, $3);
1365   $$ = itex2MML_copy2(s1, "</mroot>");
1366   itex2MML_free_string(s1);
1367   itex2MML_free_string($3);
1368   itex2MML_free_string($5);
1369 }
1370 | ROOT closedTerm closedTerm {
1371   char * s1 = itex2MML_copy3("<mroot>", $3, $2);
1372   $$ = itex2MML_copy2(s1, "</mroot>");
1373   itex2MML_free_string(s1);
1374   itex2MML_free_string($2);
1375   itex2MML_free_string($3);
1376 };
1377 
1378 raisebox: RAISEBOX TEXTSTRING TEXTSTRING TEXTSTRING closedTerm {
1379   char * s1 = itex2MML_copy3("<mpadded voffset='", $2, "' height='");
1380   char * s2 = itex2MML_copy3(s1, $3, "' depth='");
1381   char * s3 = itex2MML_copy3(s2, $4, "'>");
1382   $$ = itex2MML_copy3(s3, $5, "</mpadded>");
1383   itex2MML_free_string(s1);
1384   itex2MML_free_string(s2);
1385   itex2MML_free_string(s3);
1386   itex2MML_free_string($2);
1387   itex2MML_free_string($3);
1388   itex2MML_free_string($4);
1389   itex2MML_free_string($5);
1390 }
1391 | RAISEBOX NEG TEXTSTRING TEXTSTRING TEXTSTRING closedTerm {
1392   char * s1 = itex2MML_copy3("<mpadded voffset='-", $3, "' height='");
1393   char * s2 = itex2MML_copy3(s1, $4, "' depth='");
1394   char * s3 = itex2MML_copy3(s2, $5, "'>");
1395   $$ = itex2MML_copy3(s3, $6, "</mpadded>");
1396   itex2MML_free_string(s1);
1397   itex2MML_free_string(s2);
1398   itex2MML_free_string(s3);
1399   itex2MML_free_string($3);
1400   itex2MML_free_string($4);
1401   itex2MML_free_string($5);
1402   itex2MML_free_string($6);
1403 }
1404 | RAISEBOX TEXTSTRING TEXTSTRING closedTerm {
1405   char * s1 = itex2MML_copy3("<mpadded voffset='", $2, "' height='");
1406   char * s2 = itex2MML_copy3(s1, $3, "' depth='depth'>");
1407   $$ = itex2MML_copy3(s2, $4, "</mpadded>");
1408   itex2MML_free_string(s1);
1409   itex2MML_free_string(s2);
1410   itex2MML_free_string($2);
1411   itex2MML_free_string($3);
1412   itex2MML_free_string($4);
1413 }
1414 | RAISEBOX NEG TEXTSTRING TEXTSTRING closedTerm {
1415   char * s1 = itex2MML_copy3("<mpadded voffset='-", $3, "' height='");
1416   char * s2 = itex2MML_copy3(s1, $4, "' depth='+");
1417   char * s3 = itex2MML_copy3(s2, $3, "'>");
1418   $$ = itex2MML_copy3(s3, $5, "</mpadded>");
1419   itex2MML_free_string(s1);
1420   itex2MML_free_string(s2);
1421   itex2MML_free_string(s3);
1422   itex2MML_free_string($3);
1423   itex2MML_free_string($4);
1424   itex2MML_free_string($5);
1425 }
1426 | RAISEBOX TEXTSTRING closedTerm {
1427   char * s1 = itex2MML_copy3("<mpadded voffset='", $2, "' height='+");
1428   char * s2 = itex2MML_copy3(s1, $2, "' depth='depth'>");
1429   $$ = itex2MML_copy3(s2, $3, "</mpadded>");
1430   itex2MML_free_string(s1);
1431   itex2MML_free_string(s2);
1432   itex2MML_free_string($2);
1433   itex2MML_free_string($3);
1434 }
1435 | RAISEBOX NEG TEXTSTRING closedTerm {
1436   char * s1 = itex2MML_copy3("<mpadded voffset='-", $3, "' height='0pt' depth='+");
1437   char * s2 = itex2MML_copy3(s1, $3, "'>");
1438   $$ = itex2MML_copy3(s2, $4, "</mpadded>");
1439   itex2MML_free_string(s1);
1440   itex2MML_free_string(s2);
1441   itex2MML_free_string($3);
1442   itex2MML_free_string($4);
1443 };
1444 
1445 munder: XARROW OPTARGOPEN compoundTermList OPTARGCLOSE EMPTYMROW {
1446   char * s1 = itex2MML_copy3("<munder><mo>", $1, "</mo><mrow>");
1447   $$ = itex2MML_copy3(s1, $3, "</mrow></munder>");
1448   itex2MML_free_string(s1);
1449   itex2MML_free_string($1);
1450   itex2MML_free_string($3);
1451 }
1452 | UNDER closedTerm closedTerm {
1453   char * s1 = itex2MML_copy3("<munder>", $3, $2);
1454   $$ = itex2MML_copy2(s1, "</munder>");
1455   itex2MML_free_string(s1);
1456   itex2MML_free_string($2);
1457   itex2MML_free_string($3);
1458 };
1459 
1460 mover: XARROW closedTerm {
1461   char * s1 = itex2MML_copy3("<mover><mo>", $1, "</mo>");
1462   $$ =  itex2MML_copy3(s1, $2, "</mover>");
1463   itex2MML_free_string(s1);
1464   itex2MML_free_string($1);
1465   itex2MML_free_string($2);
1466 }
1467 | OVER closedTerm closedTerm {
1468   char * s1 = itex2MML_copy3("<mover>", $3, $2);
1469   $$ = itex2MML_copy2(s1, "</mover>");
1470   itex2MML_free_string(s1);
1471   itex2MML_free_string($2);
1472   itex2MML_free_string($3);
1473 };
1474 
1475 munderover: XARROW OPTARGOPEN compoundTermList OPTARGCLOSE closedTerm {
1476   char * s1 = itex2MML_copy3("<munderover><mo>", $1, "</mo><mrow>");
1477   char * s2 = itex2MML_copy3(s1, $3, "</mrow>");
1478   $$ = itex2MML_copy3(s2, $5, "</munderover>");
1479   itex2MML_free_string(s1);
1480   itex2MML_free_string(s2);
1481   itex2MML_free_string($1);
1482   itex2MML_free_string($3);
1483   itex2MML_free_string($5);
1484 }
1485 | UNDEROVER closedTerm closedTerm closedTerm {
1486   char * s1 = itex2MML_copy3("<munderover>", $4, $2);
1487   $$ = itex2MML_copy3(s1, $3, "</munderover>");
1488   itex2MML_free_string(s1);
1489   itex2MML_free_string($2);
1490   itex2MML_free_string($3);
1491   itex2MML_free_string($4);
1492 };
1493 
1494 emptymrow: EMPTYMROW {
1495   $$ = itex2MML_copy_string("<mrow/>");
1496 };
1497 
1498 mathenv: BEGINENV MATRIX tableRowList ENDENV MATRIX {
1499   $$ = itex2MML_copy3("<mrow><mtable displaystyle=\"false\" rowspacing=\"0.5ex\">", $3, "</mtable></mrow>");
1500   itex2MML_free_string($3);
1501 }
1502 |  BEGINENV GATHERED tableRowList ENDENV GATHERED {
1503   $$ = itex2MML_copy3("<mrow><mtable displaystyle=\"true\" rowspacing=\"1.0ex\">", $3, "</mtable></mrow>");
1504   itex2MML_free_string($3);
1505 }
1506 | BEGINENV PMATRIX tableRowList ENDENV PMATRIX {
1507   $$ = itex2MML_copy3("<mrow><mo>(</mo><mrow><mtable displaystyle=\"false\" rowspacing=\"0.5ex\">", $3, "</mtable></mrow><mo>)</mo></mrow>");
1508   itex2MML_free_string($3);
1509 }
1510 | BEGINENV BMATRIX tableRowList ENDENV BMATRIX {
1511   $$ = itex2MML_copy3("<mrow><mo>[</mo><mrow><mtable displaystyle=\"false\" rowspacing=\"0.5ex\">", $3, "</mtable></mrow><mo>]</mo></mrow>");
1512   itex2MML_free_string($3);
1513 }
1514 | BEGINENV VMATRIX tableRowList ENDENV VMATRIX {
1515   $$ = itex2MML_copy3("<mrow><mo>&VerticalBar;</mo><mrow><mtable displaystyle=\"false\" rowspacing=\"0.5ex\">", $3, "</mtable></mrow><mo>&VerticalBar;</mo></mrow>");
1516   itex2MML_free_string($3);
1517 }
1518 | BEGINENV BBMATRIX tableRowList ENDENV BBMATRIX {
1519   $$ = itex2MML_copy3("<mrow><mo>{</mo><mrow><mtable displaystyle=\"false\" rowspacing=\"0.5ex\">", $3, "</mtable></mrow><mo>}</mo></mrow>");
1520   itex2MML_free_string($3);
1521 }
1522 | BEGINENV VVMATRIX tableRowList ENDENV VVMATRIX {
1523   $$ = itex2MML_copy3("<mrow><mo>&DoubleVerticalBar;</mo><mrow><mtable displaystyle=\"false\" rowspacing=\"0.5ex\">", $3, "</mtable></mrow><mo>&DoubleVerticalBar;</mo></mrow>");
1524   itex2MML_free_string($3);
1525 }
1526 | BEGINENV SMALLMATRIX tableRowList ENDENV SMALLMATRIX {
1527   $$ = itex2MML_copy3("<mstyle scriptlevel=\"2\"><mrow><mtable displaystyle=\"false\" rowspacing=\"0.5ex\">", $3, "</mtable></mrow></mstyle>");
1528   itex2MML_free_string($3);
1529 }
1530 | BEGINENV CASES tableRowList ENDENV CASES {
1531   $$ = itex2MML_copy3("<mrow><mo>{</mo><mrow><mtable displaystyle=\"false\" columnalign=\"left left\">", $3, "</mtable></mrow></mrow>");
1532   itex2MML_free_string($3);
1533 }
1534 | BEGINENV ALIGNED tableRowList ENDENV ALIGNED {
1535   $$ = itex2MML_copy3("<mrow><mtable displaystyle=\"true\" columnalign=\"right left right left right left right left right left\" columnspacing=\"0em\">", $3, "</mtable></mrow>");
1536   itex2MML_free_string($3);
1537 }
1538 | BEGINENV ARRAY ARRAYALIGN ST columnAlignList END tableRowList ENDENV ARRAY {
1539   char * s1 = itex2MML_copy3("<mtable displaystyle=\"false\" rowspacing=\"0.5ex\" align=\"", $3, "\" columnalign=\"");
1540   char * s2 = itex2MML_copy3(s1, $5, "\">");
1541   $$ = itex2MML_copy3(s2, $7, "</mtable>");
1542   itex2MML_free_string(s1);
1543   itex2MML_free_string(s2);
1544   itex2MML_free_string($3);
1545   itex2MML_free_string($5);
1546   itex2MML_free_string($7);
1547 }
1548 | BEGINENV ARRAY ST columnAlignList END tableRowList ENDENV ARRAY {
1549   char * s1 = itex2MML_copy3("<mtable displaystyle=\"false\" rowspacing=\"0.5ex\" columnalign=\"", $4, "\">");
1550   $$ = itex2MML_copy3(s1, $6, "</mtable>");
1551   itex2MML_free_string(s1);
1552   itex2MML_free_string($4);
1553   itex2MML_free_string($6);
1554 }
1555 | BEGINENV SVG XMLSTRING ENDSVG {
1556   $$ = itex2MML_copy3("<semantics><annotation-xml encoding=\"SVG1.1\">", $3, "</annotation-xml></semantics>");
1557   itex2MML_free_string($3);
1558 }
1559 | BEGINENV SVG ENDSVG {
1560   $$ = itex2MML_copy_string(" ");
1561 };
1562 
1563 columnAlignList: columnAlignList COLUMNALIGN {
1564   $$ = itex2MML_copy3($1, " ", $2);
1565   itex2MML_free_string($1);
1566   itex2MML_free_string($2);
1567 }
1568 | COLUMNALIGN {
1569   $$ = itex2MML_copy_string($1);
1570   itex2MML_free_string($1);
1571 };
1572 
1573 substack: SUBSTACK MROWOPEN tableRowList MROWCLOSE {
1574   $$ = itex2MML_copy3("<mrow><mtable columnalign=\"center\" rowspacing=\"0.5ex\">", $3, "</mtable></mrow>");
1575   itex2MML_free_string($3);
1576 };
1577 
1578 array: ARRAY MROWOPEN tableRowList MROWCLOSE {
1579   $$ = itex2MML_copy3("<mrow><mtable>", $3, "</mtable></mrow>");
1580   itex2MML_free_string($3);
1581 }
1582 | ARRAY MROWOPEN ARRAYOPTS MROWOPEN arrayopts MROWCLOSE tableRowList MROWCLOSE {
1583   char * s1 = itex2MML_copy3("<mrow><mtable ", $5, ">");
1584   $$ = itex2MML_copy3(s1, $7, "</mtable></mrow>");
1585   itex2MML_free_string(s1);
1586   itex2MML_free_string($5);
1587   itex2MML_free_string($7);
1588 };
1589 
1590 arrayopts: anarrayopt {
1591   $$ = itex2MML_copy_string($1);
1592   itex2MML_free_string($1);
1593 }
1594 | arrayopts anarrayopt {
1595   $$ = itex2MML_copy3($1, " ", $2);
1596   itex2MML_free_string($1);
1597   itex2MML_free_string($2);
1598 };
1599 
1600 anarrayopt: collayout {
1601   $$ = itex2MML_copy_string($1);
1602   itex2MML_free_string($1);
1603 }
1604 | colalign {
1605   $$ = itex2MML_copy_string($1);
1606   itex2MML_free_string($1);
1607 }
1608 | rowalign {
1609   $$ = itex2MML_copy_string($1);
1610   itex2MML_free_string($1);
1611 }
1612 | align {
1613   $$ = itex2MML_copy_string($1);
1614   itex2MML_free_string($1);
1615 }
1616 | eqrows {
1617   $$ = itex2MML_copy_string($1);
1618   itex2MML_free_string($1);
1619 }
1620 | eqcols {
1621   $$ = itex2MML_copy_string($1);
1622   itex2MML_free_string($1);
1623 }
1624 | rowlines {
1625   $$ = itex2MML_copy_string($1);
1626   itex2MML_free_string($1);
1627 }
1628 | collines {
1629   $$ = itex2MML_copy_string($1);
1630   itex2MML_free_string($1);
1631 }
1632 | frame {
1633   $$ = itex2MML_copy_string($1);
1634   itex2MML_free_string($1);
1635 }
1636 | padding {
1637   $$ = itex2MML_copy_string($1);
1638   itex2MML_free_string($1);
1639 };
1640 
1641 collayout: COLLAYOUT ATTRLIST {
1642   $$ = itex2MML_copy2("columnalign=", $2);
1643   itex2MML_free_string($2);
1644 };
1645 
1646 colalign: COLALIGN ATTRLIST {
1647   $$ = itex2MML_copy2("columnalign=", $2);
1648   itex2MML_free_string($2);
1649 };
1650 
1651 rowalign: ROWALIGN ATTRLIST {
1652   $$ = itex2MML_copy2("rowalign=", $2);
1653   itex2MML_free_string($2);
1654 };
1655 
1656 align: ALIGN ATTRLIST {
1657   $$ = itex2MML_copy2("align=", $2);
1658   itex2MML_free_string($2);
1659 };
1660 
1661 eqrows: EQROWS ATTRLIST {
1662   $$ = itex2MML_copy2("equalrows=", $2);
1663   itex2MML_free_string($2);
1664 };
1665 
1666 eqcols: EQCOLS ATTRLIST {
1667   $$ = itex2MML_copy2("equalcolumns=", $2);
1668   itex2MML_free_string($2);
1669 };
1670 
1671 rowlines: ROWLINES ATTRLIST {
1672   $$ = itex2MML_copy2("rowlines=", $2);
1673   itex2MML_free_string($2);
1674 };
1675 
1676 collines: COLLINES ATTRLIST {
1677   $$ = itex2MML_copy2("columnlines=", $2);
1678   itex2MML_free_string($2);
1679 };
1680 
1681 frame: FRAME ATTRLIST {
1682   $$ = itex2MML_copy2("frame=", $2);
1683   itex2MML_free_string($2);
1684 };
1685 
1686 padding: PADDING ATTRLIST {
1687   char * s1 = itex2MML_copy3("rowspacing=", $2, " columnspacing=");
1688   $$ = itex2MML_copy2(s1, $2);
1689   itex2MML_free_string(s1);
1690   itex2MML_free_string($2);
1691 };
1692 
1693 tableRowList: tableRow {
1694   $$ = itex2MML_copy_string($1);
1695   itex2MML_free_string($1);
1696 }
1697 | tableRowList ROWSEP tableRow {
1698   $$ = itex2MML_copy3($1, " ", $3);
1699   itex2MML_free_string($1);
1700   itex2MML_free_string($3);
1701 };
1702 
1703 tableRow: simpleTableRow {
1704   $$ = itex2MML_copy3("<mtr>", $1, "</mtr>");
1705   itex2MML_free_string($1);
1706 }
1707 | optsTableRow {
1708   $$ = itex2MML_copy_string($1);
1709   itex2MML_free_string($1);
1710 };
1711 
1712 simpleTableRow: tableCell {
1713   $$ = itex2MML_copy_string($1);
1714   itex2MML_free_string($1);
1715 }
1716 | simpleTableRow COLSEP tableCell {
1717   $$ = itex2MML_copy3($1, " ", $3);
1718   itex2MML_free_string($1);
1719   itex2MML_free_string($3);
1720 };
1721 
1722 optsTableRow: ROWOPTS MROWOPEN rowopts MROWCLOSE simpleTableRow {
1723   char * s1 = itex2MML_copy3("<mtr ", $3, ">");
1724   $$ = itex2MML_copy3(s1, $5, "</mtr>");
1725   itex2MML_free_string(s1);
1726   itex2MML_free_string($3);
1727   itex2MML_free_string($5);
1728 };
1729 
1730 rowopts: arowopt {
1731   $$ = itex2MML_copy_string($1);
1732   itex2MML_free_string($1);
1733 }
1734 | rowopts arowopt {
1735   $$ = itex2MML_copy3($1, " ", $2);
1736   itex2MML_free_string($1);
1737   itex2MML_free_string($2);
1738 };
1739 
1740 arowopt: colalign {
1741   $$ = itex2MML_copy_string($1);
1742   itex2MML_free_string($1);
1743 }
1744 | rowalign {
1745   $$ = itex2MML_copy_string($1);
1746   itex2MML_free_string($1);
1747 };
1748 
1749 tableCell:   {
1750   $$ = itex2MML_copy_string("<mtd/>");
1751 }
1752 | compoundTermList {
1753   $$ = itex2MML_copy3("<mtd>", $1, "</mtd>");
1754   itex2MML_free_string($1);
1755 }
1756 | CELLOPTS MROWOPEN cellopts MROWCLOSE compoundTermList {
1757   char * s1 = itex2MML_copy3("<mtd ", $3, ">");
1758   $$ = itex2MML_copy3(s1, $5, "</mtd>");
1759   itex2MML_free_string(s1);
1760   itex2MML_free_string($3);
1761   itex2MML_free_string($5);
1762 };
1763 
1764 cellopts: acellopt {
1765   $$ = itex2MML_copy_string($1);
1766   itex2MML_free_string($1);
1767 }
1768 | cellopts acellopt {
1769   $$ = itex2MML_copy3($1, " ", $2);
1770   itex2MML_free_string($1);
1771   itex2MML_free_string($2);
1772 };
1773 
1774 acellopt: colalign {
1775   $$ = itex2MML_copy_string($1);
1776   itex2MML_free_string($1);
1777 }
1778 | rowalign {
1779   $$ = itex2MML_copy_string($1);
1780   itex2MML_free_string($1);
1781 }
1782 | rowspan {
1783   $$ = itex2MML_copy_string($1);
1784   itex2MML_free_string($1);
1785 }
1786 | colspan {
1787   $$ = itex2MML_copy_string($1);
1788   itex2MML_free_string($1);
1789 };
1790 
1791 rowspan: ROWSPAN ATTRLIST {
1792   $$ = itex2MML_copy2("rowspan=", $2);
1793   itex2MML_free_string($2);
1794 };
1795 
1796 colspan: COLSPAN ATTRLIST {
1797   $$ = itex2MML_copy2("columnspan=", $2);
1798   itex2MML_free_string($2);
1799 };
1800 
1801 %%
1802 
1803 char * itex2MML_parse (const char * buffer, size_t length)
1804 {
1805   char * mathml = 0;
1806 
1807   int result;
1808 
1809   itex2MML_setup (buffer, length);
1810   itex2MML_restart ();
1811 
1812   result = itex2MML_yyparse (&mathml);
1813 
1814   if (result && mathml) /* shouldn't happen? */
1815     {
1816       itex2MML_free_string (mathml);
1817       mathml = 0;
1818     }
1819   return mathml;
1820 }
1821 
itex2MML_filter(const char * buffer,size_t length)1822 int itex2MML_filter (const char * buffer, size_t length)
1823 {
1824   itex2MML_setup (buffer, length);
1825   itex2MML_restart ();
1826 
1827   return itex2MML_yyparse (0);
1828 }
1829 
1830 #define ITEX_DELIMITER_DOLLAR 0
1831 #define ITEX_DELIMITER_DOUBLE 1
1832 #define ITEX_DELIMITER_SQUARE 2
1833 
1834 static char * itex2MML_last_error = 0;
1835 
itex2MML_keep_error(const char * msg)1836 static void itex2MML_keep_error (const char * msg)
1837 {
1838   if (itex2MML_last_error)
1839     {
1840       itex2MML_free_string (itex2MML_last_error);
1841       itex2MML_last_error = 0;
1842     }
1843   itex2MML_last_error = itex2MML_copy_escaped (msg);
1844 }
1845 
itex2MML_html_filter(const char * buffer,size_t length)1846 int itex2MML_html_filter (const char * buffer, size_t length)
1847 {
1848   return itex2MML_do_html_filter (buffer, length, 0);
1849 }
1850 
itex2MML_strict_html_filter(const char * buffer,size_t length)1851 int itex2MML_strict_html_filter (const char * buffer, size_t length)
1852 {
1853   return itex2MML_do_html_filter (buffer, length, 1);
1854 }
1855 
itex2MML_do_html_filter(const char * buffer,size_t length,const int forbid_markup)1856 int itex2MML_do_html_filter (const char * buffer, size_t length, const int forbid_markup)
1857 {
1858   int result = 0;
1859 
1860   int type = 0;
1861   int skip = 0;
1862   int match = 0;
1863 
1864   const char * ptr1 = buffer;
1865   const char * ptr2 = 0;
1866 
1867   const char * end = buffer + length;
1868 
1869   char * mathml = 0;
1870 
1871   void (*save_error_fn) (const char * msg) = itex2MML_error;
1872 
1873   itex2MML_error = itex2MML_keep_error;
1874 
1875  _until_math:
1876   ptr2 = ptr1;
1877 
1878   while (ptr2 < end)
1879     {
1880       if (*ptr2 == '$') break;
1881       if ((*ptr2 == '\\') && (ptr2 + 1 < end))
1882 	{
1883 	  if (*(ptr2+1) == '[') break;
1884 	}
1885       ++ptr2;
1886     }
1887   if (itex2MML_write && ptr2 > ptr1)
1888     (*itex2MML_write) (ptr1, ptr2 - ptr1);
1889 
1890   if (ptr2 == end) goto _finish;
1891 
1892  _until_html:
1893   ptr1 = ptr2;
1894 
1895   if (ptr2 + 1 < end)
1896     {
1897       if ((*ptr2 == '\\') && (*(ptr2+1) == '['))
1898 	{
1899 	  type = ITEX_DELIMITER_SQUARE;
1900 	  ptr2 += 2;
1901 	}
1902       else if ((*ptr2 == '$') && (*(ptr2+1) == '$'))
1903 	{
1904 	  type = ITEX_DELIMITER_DOUBLE;
1905 	  ptr2 += 2;
1906 	}
1907       else
1908 	{
1909 	  type = ITEX_DELIMITER_DOLLAR;
1910 	  ptr2 += 2;
1911 	}
1912     }
1913   else goto _finish;
1914 
1915   skip = 0;
1916   match = 0;
1917 
1918   while (ptr2 < end)
1919     {
1920       switch (*ptr2)
1921 	{
1922 	case '<':
1923 	case '>':
1924 	  if (forbid_markup == 1) skip = 1;
1925 	  break;
1926 
1927 	case '\\':
1928 	  if (ptr2 + 1 < end)
1929 	    {
1930 	      if (*(ptr2 + 1) == '[')
1931 		{
1932 		  skip = 1;
1933 		}
1934 	      else if (*(ptr2 + 1) == ']')
1935 		{
1936 		  if (type == ITEX_DELIMITER_SQUARE)
1937 		    {
1938 		      ptr2 += 2;
1939 		      match = 1;
1940 		    }
1941 		  else
1942 		    {
1943 		      skip = 1;
1944 		    }
1945 		}
1946 	    }
1947 	  break;
1948 
1949 	case '$':
1950 	  if (type == ITEX_DELIMITER_SQUARE)
1951 	    {
1952 	      skip = 1;
1953 	    }
1954 	  else if (ptr2 + 1 < end)
1955 	    {
1956 	      if (*(ptr2 + 1) == '$')
1957 		{
1958 		  if (type == ITEX_DELIMITER_DOLLAR)
1959 		    {
1960 		      ptr2++;
1961 		      match = 1;
1962 		    }
1963 		  else
1964 		    {
1965 		      ptr2 += 2;
1966 		      match = 1;
1967 		    }
1968 		}
1969 	      else
1970 		{
1971 		  if (type == ITEX_DELIMITER_DOLLAR)
1972 		    {
1973 		      ptr2++;
1974 		      match = 1;
1975 		    }
1976 		  else
1977 		    {
1978 		      skip = 1;
1979 		    }
1980 		}
1981 	    }
1982 	  else
1983 	    {
1984 	      if (type == ITEX_DELIMITER_DOLLAR)
1985 		{
1986 		  ptr2++;
1987 		  match = 1;
1988 		}
1989 	      else
1990 		{
1991 		  skip = 1;
1992 		}
1993 	    }
1994 	  break;
1995 
1996 	default:
1997 	  break;
1998 	}
1999       if (skip || match) break;
2000 
2001       ++ptr2;
2002     }
2003   if (skip)
2004     {
2005       if (type == ITEX_DELIMITER_DOLLAR)
2006 	{
2007 	  if (itex2MML_write)
2008 	    (*itex2MML_write) (ptr1, 1);
2009 	  ptr1++;
2010 	}
2011       else
2012 	{
2013 	  if (itex2MML_write)
2014 	    (*itex2MML_write) (ptr1, 2);
2015 	  ptr1 += 2;
2016 	}
2017       goto _until_math;
2018     }
2019   if (match)
2020     {
2021       mathml = itex2MML_parse (ptr1, ptr2 - ptr1);
2022 
2023       if (mathml)
2024 	{
2025 	  if (itex2MML_write_mathml)
2026 	    (*itex2MML_write_mathml) (mathml);
2027 	  itex2MML_free_string (mathml);
2028 	  mathml = 0;
2029 	}
2030       else
2031 	{
2032 	  ++result;
2033 	  if (itex2MML_write)
2034 	    {
2035 	      if (type == ITEX_DELIMITER_DOLLAR)
2036 		(*itex2MML_write) ("<math xmlns='http://www.w3.org/1998/Math/MathML' display='inline'><merror><mtext>", 0);
2037 	      else
2038 		(*itex2MML_write) ("<math xmlns='http://www.w3.org/1998/Math/MathML' display='block'><merror><mtext>", 0);
2039 
2040 	      (*itex2MML_write) (itex2MML_last_error, 0);
2041 	      (*itex2MML_write) ("</mtext></merror></math>", 0);
2042 	    }
2043 	}
2044       ptr1 = ptr2;
2045 
2046       goto _until_math;
2047     }
2048   if (itex2MML_write)
2049     (*itex2MML_write) (ptr1, ptr2 - ptr1);
2050 
2051  _finish:
2052   if (itex2MML_last_error)
2053     {
2054       itex2MML_free_string (itex2MML_last_error);
2055       itex2MML_last_error = 0;
2056     }
2057   itex2MML_error = save_error_fn;
2058 
2059   return result;
2060 }
2061