]> git.lyx.org Git - lyx.git/blob - src/mathed/math_parser.C
Two configuration fixes. Bugfree configure is coming soon (do you really believe...
[lyx.git] / src / mathed / math_parser.C
1 /*
2  *  File:        math_parser.C
3  *  Purpose:     Parser for mathed
4  *  Author:      Alejandro Aguilar Sierra <asierra@servidor.unam.mx> 
5  *  Created:     January 1996
6  *  Description: Parse LaTeX2e math mode code.
7  *
8  *  Dependencies: Xlib, XForms
9  *
10  *  Copyright: (c) 1996, Alejandro Aguilar Sierra
11  *
12  *   Version: 0.8beta.
13  *
14  *   You are free to use and modify this code under the terms of
15  *   the GNU General Public Licence version 2 or later.
16  */
17
18 #include <config.h>
19 #include <cstdlib>
20 #include <cctype>
21
22 #ifdef __GNUG__
23 #pragma implementation "math_parser.h"
24 #endif
25
26 #include "math_parser.h"
27 #include "math_iter.h"
28 #include "math_inset.h"
29 #include "math_macro.h"
30 #include "math_root.h"
31 #include "debug.h"
32
33 enum {
34         FLAG_BRACE      = 1,    //  A { needed
35         FLAG_BRACE_ARG  = 2,    //  Next { is argument
36         FLAG_BRACE_OPT  = 4,    //  Optional {
37         FLAG_BRACE_LAST = 8,    //  Last } ends the parsing process
38         FLAG_BRACK_ARG  = 16,   //  Optional [
39         FLAG_RIGHT      = 32,      //  Next right ends the parsing process
40         FLAG_END        = 64,      //  Next end ends the parsing process
41         FLAG_BRACE_FONT = 128,  //  Next } closes a font
42         FLAG_BRACK_END  = 256   // Next ] ends the parsing process
43 };
44
45 YYSTYPE yylval;
46
47
48 static short mathed_env = LM_EN_INTEXT;
49
50 char * mathed_label = 0;
51
52 char const * latex_mathenv[] = { 
53    "math", 
54    "displaymath", 
55    "equation", 
56    "eqnarray*",
57    "eqnarray",
58    "array"
59 };
60
61
62 char const * latex_mathspace[] = {
63    "!", ",", ":", ";", "quad", "qquad"
64 };
65    
66 char const * latex_special_chars = "#$%&_{}";
67             
68 // These are lexical codes, not semantic
69 enum lexcode_enum {
70    LexNone,
71    LexESC,
72    LexAlpha,
73    LexDigit,
74    LexBOP,         // Binary operators or relations
75    LexMathSpace,
76    LexOpen,
77    LexClose,
78    LexComment,
79    LexArgument,
80    LexSpace,
81    LexNewLine,
82    LexOther,
83    LexSelf
84 };
85
86 static lexcode_enum lexcode[256];  
87 static char yytext[256];
88 static int yylineno;
89 static FILE * yyin;
90 static bool yy_mtextmode= false;
91             
92 inline
93 char * strnew(char const * s)
94 {
95         char *s1 = new char[strlen(s)+1]; // this leaks when not delete[]'ed
96         strcpy(s1, s);
97         return s1;
98 }
99
100
101 static void mathPrintError(char const * msg) 
102 {
103         lyxerr << "Line ~" << yylineno << ": Math parse error: "
104                << msg << endl;
105 }
106
107
108 static void LexInitCodes()
109 {
110    for (int i = 0;  i <= 255; ++i)     {
111      if (isalpha(i)) lexcode[i] = LexAlpha;
112      else if (isdigit(i)) lexcode[i] = LexDigit;
113      else if (isspace(i)) lexcode[i] = LexSpace;
114      else lexcode[i] = LexNone;
115    }
116     
117    lexcode['\t'] = lexcode['\f'] = lexcode[' '] = LexSpace;
118    lexcode['\n'] = LexNewLine;
119    lexcode['%'] = LexComment;
120    lexcode['#'] = LexArgument;
121    lexcode['+'] = lexcode['-'] = lexcode['*'] = lexcode['/'] = 
122    lexcode['<'] = lexcode['>'] = lexcode['='] = LexBOP;
123    
124    lexcode['!'] = lexcode[','] = lexcode[':'] = lexcode[';'] = LexMathSpace;
125    lexcode['('] = lexcode[')'] = lexcode['|'] = lexcode['.'] = lexcode['?'] = LexOther; 
126    lexcode['\'']= LexAlpha;
127    
128    lexcode['['] = lexcode[']'] = lexcode['^'] = lexcode['_'] = 
129    lexcode['&'] = LexSelf;  
130    
131    lexcode['\\'] = LexESC;
132    lexcode['{'] = LexOpen;
133    lexcode['}'] = LexClose;
134 }
135
136
137 static char LexGetArg(char lf, bool accept_spaces= false)
138 {
139    char c, rg, * p = &yytext[0];
140    int bcnt = 1;
141    
142    while (!feof(yyin)) {
143       c = getc(yyin); 
144       if (c>' ') {
145          if (!lf) lf = c; else
146          if (c!= lf)
147                  lyxerr << "Math parse error: unexpected '"
148                         << c << "'" << endl;
149          break;
150       }
151    }
152    rg = (lf == '{') ? '}': ((lf == '[') ? ']': ((lf == '(') ? ')': 0));
153    if (!rg) {
154            lyxerr << "Math parse error: unknown bracket '"
155                   << lf << "'" << endl;
156       return '\0';
157    } 
158    do {
159       c = getc(yyin); 
160       if (c == lf) bcnt++;
161       if (c == rg) bcnt--;
162       if ((c>' ' || (c == ' ' && accept_spaces)) && bcnt>0) *(p++) = c;
163    } while (bcnt>0 && !feof(yyin));
164    *p = '\0';
165    return rg;
166 }
167
168
169 static int yylex(void)
170 {
171    static int init_done = 0;
172    unsigned char c;
173    
174    if (!init_done) LexInitCodes();
175    
176    while (!feof(yyin)) { 
177       c = getc(yyin);
178        
179       if (yy_mtextmode && c == ' ') {
180           yylval.i= ' ';
181           return LM_TK_ALPHA;
182       }
183        
184        if (lexcode[c] == LexNewLine) {
185            yylineno++; 
186            continue;
187        }
188          
189       if (lexcode[c] == LexComment) 
190         do c = getc(yyin); while (c!= '\n' % !feof(yyin));  // eat comments
191     
192       if (lexcode[c] == LexDigit || lexcode[c] == LexOther || lexcode[c] == LexMathSpace) 
193         { yylval.i= c; return LM_TK_STR; }
194       if (lexcode[c] == LexAlpha) { yylval.i= c; return LM_TK_ALPHA; }
195       if (lexcode[c] == LexBOP)   { yylval.i= c; return LM_TK_BOP; }
196       if (lexcode[c] == LexSelf)  { return c; }   
197       if (lexcode[c] == LexArgument)   { 
198           c = getc(yyin);
199           yylval.i = c - '0';
200           return LM_TK_ARGUMENT; 
201       }
202       if (lexcode[c] == LexOpen)   { return LM_TK_OPEN; }
203       if (lexcode[c] == LexClose)   { return LM_TK_CLOSE; }
204       
205       if (lexcode[c] == LexESC)   {
206          c = getc(yyin);
207          if (c == '\\') { return LM_TK_NEWLINE; }
208          if (c == '(')  { yylval.i = LM_EN_INTEXT; return LM_TK_BEGIN; }
209          if (c == ')')  { yylval.i = LM_EN_INTEXT; return LM_TK_END; }
210          if (c == '[')  { yylval.i = LM_EN_DISPLAY; return LM_TK_BEGIN; }
211          if (c == ']')  { yylval.i = LM_EN_DISPLAY; return LM_TK_END; }
212          if (strchr(latex_special_chars, c)) {
213              yylval.i = c;
214              return LM_TK_SPECIAL;
215          }  
216          if (lexcode[c] == LexMathSpace) {
217             int i;
218             for (i= 0; i<4 && c!= latex_mathspace[i][0]; i++);
219             yylval.i = (i<4) ? i: 0; 
220             return LM_TK_SPACE; 
221          }
222          if (lexcode[c] == LexAlpha || lexcode[c] == LexDigit) {
223             char* p = &yytext[0];
224             while (lexcode[c] == LexAlpha || lexcode[c] == LexDigit) {
225                *p = c;
226                c = getc(yyin);
227                p++;
228             }
229             *p = '\0';
230             if (!feof(yyin)) ungetc(c, yyin);
231             latexkeys *l = in_word_set (yytext, strlen(yytext));
232             if (l) {
233                if (l->token == LM_TK_BEGIN || l->token == LM_TK_END) { 
234                   int i;
235                   LexGetArg('{');
236 //                for (i= 0; i<5 && strncmp(yytext, latex_mathenv[i],
237 //                              strlen(latex_mathenv[i])); i++);
238                   
239                   for (i= 0; i<6 && strcmp(yytext, latex_mathenv[i]); i++);
240                   yylval.i = i;
241                } else
242                if (l->token == LM_TK_SPACE) 
243                  yylval.i = l->id;
244                else
245                  yylval.l = l;
246                return l->token;
247             } else { 
248                yylval.s = yytext;
249                return LM_TK_UNDEF;
250             }
251          }
252       }
253    }
254    return 0;
255 }
256
257
258 int parse_align(char * hor, char *)
259 {
260    int nc = 0;
261    for (char * c = hor; c && *c > ' '; ++c) nc++;
262    return nc;
263 }
264
265
266 // Accent hacks only for 0.12. Stolen from Cursor.
267 int accent = 0;
268 int nestaccent[8];
269
270 void setAccent(int ac)
271 {
272         if (ac > 0 && accent < 8) {
273                 nestaccent[accent++] = ac;
274         } else
275           accent = 0;  // consumed!
276 }
277
278
279 MathedInset * doAccent(byte c, MathedTextCodes t)
280 {
281         MathedInset * ac = 0;
282         
283         for (int i= accent-1; i>= 0; i--) {
284                 if (i == accent-1)
285                   ac = new MathAccentInset(c, t, nestaccent[i]);
286                 else 
287                   ac = new MathAccentInset(ac, nestaccent[i]);
288         }
289         accent = 0;  // consumed!
290         
291         return ac;
292 }
293
294
295 MathedInset * doAccent(MathedInset * p)
296 {
297         MathedInset * ac = 0;
298         
299         for (int i= accent-1; i>= 0; i--) {
300                 if (i == accent-1)
301                   ac = new MathAccentInset(p, nestaccent[i]);
302                 else 
303                   ac = new MathAccentInset(ac, nestaccent[i]);
304         }
305         accent = 0;  // consumed!
306         
307         return ac;
308 }
309
310
311
312
313 LyxArrayBase * mathed_parse(unsigned flags, LyxArrayBase * array,
314                             MathParInset ** mtx)
315 {
316    int t = yylex(), tprev = 0;
317    bool panic = false;
318    static int plevel = -1;
319    static int size = LM_ST_TEXT;
320    MathedTextCodes varcode = LM_TC_VAR;
321    MathedInset* binset = 0;
322    static MathMacroTemplate *macro= 0;
323    
324    int brace = 0;
325    int acc_brace = 0;
326    int acc_braces[8];
327    MathParInset * mt = (mtx) ? *mtx: 0;//(MathParInset*)0;
328     MathedRowSt * crow = (mt) ? mt->getRowSt(): 0;
329
330    ++plevel;
331    if (!array) array = new LyxArrayBase;
332    MathedIter data(array);
333    while (t) {
334       if ((flags & FLAG_BRACE) && t != LM_TK_OPEN) {
335          if ((flags & FLAG_BRACK_ARG) && t == '[') {
336          }
337          else {
338              mathPrintError("Expected {. Maybe you forgot to enclose an argument in {}");
339             panic = true;
340             break;
341          }
342       }
343     MathedInsetTypes fractype = LM_OT_FRAC;
344     switch (t) {
345     case LM_TK_ALPHA:
346       {
347          if (accent) {
348              data.Insert(doAccent(yylval.i, varcode));
349          } else
350             data.Insert (yylval.i, varcode);  //LM_TC_VAR);
351          break;
352       }
353     case LM_TK_ARGUMENT:
354       {
355           if (macro) {
356               data.Insert(macro->getMacroPar(yylval.i-1), LM_TC_INSET);
357           } 
358           break;
359       } 
360     case LM_TK_NEWCOMMAND:
361       {
362           int na = 0; 
363
364           LexGetArg('{');
365           // This name lives until quitting, for that reason
366           // I didn't care on deleting explicitly. Later I will.
367           char const *name = strnew(&yytext[1]);
368           // ugly trick to be removed soon (lyx3)
369           char c = getc(yyin);
370           ungetc(c, yyin);
371           if (c == '[') {
372               LexGetArg('[');
373               na = atoi(yytext);
374           }  
375           macro = new MathMacroTemplate(name, na);
376           flags = FLAG_BRACE|FLAG_BRACE_LAST;
377           *mtx = macro;
378           macro->SetData(array);
379           break;
380       }
381     case LM_TK_SPECIAL:
382       {   
383           data.Insert (yylval.i, LM_TC_SPECIAL);
384           break;
385       }
386     case LM_TK_STR:
387       {   
388           if (accent) {
389                   data.Insert(doAccent(yylval.i, LM_TC_CONST));
390           } else
391             data.Insert (yylval.i, LM_TC_CONST);
392           break;
393       }
394     case LM_TK_OPEN:
395       {
396         brace++;
397         if  (accent && tprev == LM_TK_ACCENT) {
398             acc_braces[acc_brace++] = brace;
399             break;
400         }
401         if (flags & FLAG_BRACE_OPT) {
402            flags &= ~FLAG_BRACE_OPT;
403            flags |= FLAG_BRACE;
404         }
405                  
406         if (flags & FLAG_BRACE)
407           flags &= ~FLAG_BRACE;
408          else {
409             data.Insert ('{', LM_TC_TEX);
410          }
411         break;
412       }
413     case LM_TK_CLOSE:
414       {
415          brace--;        
416          if (brace < 0) {
417             mathPrintError("Unmatching braces");
418             panic = true;
419             break;
420          }
421          if (acc_brace && brace == acc_braces[acc_brace-1]-1) {
422              acc_brace--;
423              break;
424          }
425          if (flags & FLAG_BRACE_FONT) {
426             varcode = LM_TC_VAR;
427             yy_mtextmode = false;
428             flags &= ~FLAG_BRACE_FONT;
429             break;
430          }
431          if (brace == 0 && (flags & FLAG_BRACE_LAST)) {
432             plevel--;
433             return array;
434          } else {
435             data.Insert ('}', LM_TC_TEX);
436          }
437          break;
438       }
439
440     case '[':
441       {
442          if (flags & FLAG_BRACK_ARG) {
443            flags &= ~FLAG_BRACK_ARG;
444            char rg= LexGetArg('[');
445            if (rg!= ']') {
446               mathPrintError("Expected ']'");
447               panic = true;
448               break;
449            }       
450 //         if (arg) strcpy(arg, yytext);
451         } else
452           data.Insert ('[');
453         break;
454       }
455     case ']':
456       {
457           if (flags & FLAG_BRACK_END) {
458               plevel--;
459               return array;
460           } else
461             data.Insert (']');
462         break;
463       }
464
465     case '^':
466       {  
467          MathParInset *p = new MathParInset(size, "", LM_OT_SCRIPT);
468          LyxArrayBase * ar = mathed_parse(FLAG_BRACE_OPT|FLAG_BRACE_LAST, 0);
469          p->SetData(ar);
470 //       lyxerr << "UP[" << p->GetStyle() << "]" << endl;
471          data.Insert (p, LM_TC_UP);
472          break;
473       }
474     case '_':
475       {
476          MathParInset * p = new MathParInset(size, "", LM_OT_SCRIPT);
477          LyxArrayBase * ar = mathed_parse(FLAG_BRACE_OPT|FLAG_BRACE_LAST, 0);
478          p->SetData(ar);
479          data.Insert (p, LM_TC_DOWN);
480          break;
481       }
482
483     case LM_TK_LIMIT:
484       {
485          if (binset) {
486             binset->SetLimits((bool)(yylval.l->id));
487             binset = 0;
488          }
489          break;
490       }
491       
492     case '&':    // Tab
493       {
494          if ((flags & FLAG_END) && mt && data.getCol()<mt->GetColumns()-1) {
495              data.setNumCols(mt->GetColumns());
496              data.Insert('T', LM_TC_TAB);
497          } else 
498             mathPrintError("Unexpected tab");
499          // debug info. [made that conditional -JMarc]
500          if (lyxerr.debugging(Debug::MATHED))
501                  lyxerr << data.getCol() << " " << mt->GetColumns() << endl;
502         break;
503       }
504     case LM_TK_NEWLINE:
505       {
506           if (mt && (flags & FLAG_END)) {
507               if (mt->Permit(LMPF_ALLOW_CR)) {
508                   if (crow) {
509                           crow->setNext(new MathedRowSt(mt->GetColumns()+1)); // this leaks
510                       crow = crow->getNext();
511                   }
512                   data.Insert('K', LM_TC_CR);
513               } else 
514                 mathPrintError("Unexpected newline");
515           }
516           break;
517       }
518     case LM_TK_BIGSYM:  
519       {
520          binset = new MathBigopInset(yylval.l->name, yylval.l->id);
521          data.Insert(binset);   
522          break;
523       }
524     case LM_TK_SYM:
525       {
526          if (yylval.l->id < 256) {
527             MathedTextCodes tc = MathIsBOPS(yylval.l->id) ? LM_TC_BOPS: LM_TC_SYMB;
528             if (accent) {
529                 data.Insert(doAccent(yylval.l->id, tc));
530             } else
531             data.Insert (yylval.l->id, tc);
532          } else {
533             MathFuncInset *bg = new MathFuncInset(yylval.l->name);
534              if (accent) {
535                      data.Insert(doAccent(bg));
536              } else
537              data.Insert(bg, true);     
538          }
539          break;
540       }
541     case LM_TK_BOP:
542       {
543          if (accent) {
544                  data.Insert(doAccent(yylval.i, LM_TC_BOP));
545           } else
546             data.Insert (yylval.i, LM_TC_BOP);
547          break;
548       }
549     case LM_TK_STY:
550       {
551           if (mt) {
552               mt->UserSetSize(yylval.l->id);
553           }
554           break; 
555       }
556     case LM_TK_SPACE:
557       {
558          if (yylval.i>= 0) {
559             MathSpaceInset * sp = new MathSpaceInset(yylval.i);
560             data.Insert(sp);
561          }
562          break;
563       }    
564     case LM_TK_DOTS:
565       {
566          MathDotsInset * p = new MathDotsInset(yylval.l->name, yylval.l->id);
567          data.Insert(p);
568          break;
569       }     
570     case LM_TK_STACK:
571        fractype = LM_OT_STACKREL;
572     case LM_TK_FRAC:
573       {
574          MathFracInset * fc = new MathFracInset(fractype);
575          LyxArrayBase * num = mathed_parse(FLAG_BRACE|FLAG_BRACE_LAST);
576          LyxArrayBase * den = mathed_parse(FLAG_BRACE|FLAG_BRACE_LAST);
577          fc->SetData(num, den);
578          data.Insert(fc, LM_TC_ACTIVE_INSET);
579          break;
580       }
581     case LM_TK_SQRT:
582       {     
583          MathParInset * rt;
584           
585          char c = getc(yyin);
586           
587          if (c == '[') {
588              rt = new MathRootInset(size);
589              rt->setArgumentIdx(0);
590              rt->SetData(mathed_parse(FLAG_BRACK_END, 0, &rt));
591              rt->setArgumentIdx(1);
592          } else {
593              ungetc(c, yyin);
594              rt = new MathSqrtInset(size);
595          }
596          rt->SetData(mathed_parse(FLAG_BRACE|FLAG_BRACE_LAST, 0, &rt));
597          data.Insert(rt, LM_TC_ACTIVE_INSET);
598          break;
599       }
600        
601     case LM_TK_LEFT:
602       {
603          int lfd, rgd;
604          lfd = yylex();
605          if (lfd == LM_TK_SYM || lfd == LM_TK_STR || lfd == LM_TK_BOP|| lfd == LM_TK_SPECIAL)
606            lfd = (lfd == LM_TK_SYM) ? yylval.l->id: yylval.i;
607 //       lyxerr << "L[" << lfd << " " << lfd << "]";
608          LyxArrayBase * a = mathed_parse(FLAG_RIGHT);
609          rgd = yylex();
610 //       lyxerr << "R[" << rgd << "]";
611          if (rgd == LM_TK_SYM || rgd == LM_TK_STR || rgd == LM_TK_BOP || rgd == LM_TK_SPECIAL)
612            rgd = (rgd == LM_TK_SYM) ? yylval.l->id: yylval.i;    
613          MathDelimInset * dl = new MathDelimInset(lfd, rgd);
614          dl->SetData(a);
615          data.Insert(dl, LM_TC_ACTIVE_INSET);
616 //       lyxerr << "RL[" << lfd << " " << rgd << "]";
617          break;
618       }
619     case LM_TK_RIGHT:
620       {
621          if (flags & FLAG_RIGHT) { 
622             plevel--;
623             return array;
624          } else {
625             mathPrintError("Unmatched right delimiter");
626 //          panic = true;
627          }
628          break;
629       }
630
631     case LM_TK_FONT:
632       {
633          varcode = (MathedTextCodes)yylval.l->id;
634           yy_mtextmode = bool(varcode == LM_TC_TEXTRM);
635          flags |= (FLAG_BRACE|FLAG_BRACE_FONT);
636         break;
637       }
638     case LM_TK_WIDE:
639       {  
640          MathDecorationInset * sq = new MathDecorationInset(yylval.l->id,
641                                                             size);
642          sq->SetData(mathed_parse(FLAG_BRACE|FLAG_BRACE_LAST));
643          data.Insert(sq, LM_TC_ACTIVE_INSET);
644          break;
645       }
646       
647     case LM_TK_ACCENT: setAccent(yylval.l->id); break;
648           
649     case LM_TK_NONUM:
650       {
651           if (crow)
652             crow->setNumbered(false);
653           break;
654       }
655
656     case LM_TK_PMOD:
657     case LM_TK_FUNC:
658       {
659           MathedInset * bg = new MathFuncInset(yylval.l->name); 
660           if (accent) {
661               data.Insert(t);
662           } else
663             data.Insert(bg);
664           break;
665       }
666     case LM_TK_FUNCLIM:
667       {
668          data.Insert(new MathFuncInset(yylval.l->name, LM_OT_FUNCLIM));
669          break;
670       }
671     case LM_TK_UNDEF:
672       {
673           
674        MathMacro * p = 
675          MathMacroTable::mathMTable.getMacro(yylval.s);
676        if (p) {
677            if (accent) 
678              data.Insert(doAccent(p), p->getTCode());
679            else
680              data.Insert(p, p->getTCode());
681            for (int i= 0; p->setArgumentIdx(i); i++)
682              p->SetData(mathed_parse(FLAG_BRACE|FLAG_BRACE_LAST));
683        }
684        else {
685            MathedInset * q = new MathFuncInset(yylval.s, LM_OT_UNDEF);
686            if (accent) {
687                    data.Insert(doAccent(q));
688            } else {
689                data.Insert(q);
690            }
691        }
692          break;
693       }
694     case LM_TK_END:
695       {
696          if (mathed_env != yylval.i && yylval.i!= LM_EN_ARRAY)
697            mathPrintError("Unmatched environment");
698          // debug info [made that conditional -JMarc]
699          if (lyxerr.debugging(Debug::MATHED))
700                  lyxerr << "[" << yylval.i << "]" << endl;
701          plevel--;
702          if (mt) { // && (flags & FLAG_END)) {
703             mt->SetData(array);
704             array = 0;
705          }
706          return array;
707       }
708     case LM_TK_BEGIN:
709       {
710          if (yylval.i == LM_EN_ARRAY) {
711             char ar[120], ar2[8];
712             ar[0] = ar2[0] = '\0'; 
713             char rg= LexGetArg(0);
714             if (rg == ']') {
715                strcpy(ar2, yytext);
716                rg = LexGetArg('{');
717             }
718             strcpy(ar, yytext);
719             int nc = parse_align(ar, ar2);
720             MathParInset * mm = new MathMatrixInset(nc, 0);
721             mm->SetAlign(ar2[0], ar);
722             data.Insert(mm, LM_TC_ACTIVE_INSET);
723             mathed_parse(FLAG_END, mm->GetData(), &mm);
724          } else
725          if (yylval.i>= LM_EN_INTEXT && yylval.i<= LM_EN_EQNARRAY) {
726              if (plevel!= 0) {
727                  mathPrintError("Misplaced environment");
728                  break;
729              }
730              if (!mt) {
731                  mathPrintError("0 paragraph.");
732                  panic = true;
733              }
734              
735              mathed_env = yylval.i;
736              if (mathed_env>= LM_EN_DISPLAY) {
737                  size = LM_ST_DISPLAY;
738                  if (mathed_env>LM_EN_EQUATION) {
739                      mt = new MathMatrixInset(3, -1);
740                      mt->SetAlign(' ', "rcl");
741                      if (mtx) *mtx = mt;
742                      flags |= FLAG_END;
743 //                   data.Insert(' ', LM_TC_TAB);
744 //                   data.Insert(' ', LM_TC_TAB);
745 //                   data.Reset();
746                  }
747                  mt->SetStyle(size);
748                  mt->SetType(mathed_env);
749                  crow = mt->getRowSt();
750              }
751                                
752 #ifdef DEBUG
753              lyxerr << "MATH BEGIN[" << mathed_env << "]" << endl;
754 #endif
755          } else {
756 //           lyxerr << "MATHCRO[" << yytext << "]";
757              MathMacro * p = 
758                MathMacroTable::mathMTable.getMacro(yytext);
759              if (p) {
760                  data.Insert(p, p->getTCode());
761                  p->setArgumentIdx(0);
762                  mathed_parse(FLAG_END, p->GetData(), (MathParInset**)&p);
763 //               for (int i= 0; p->setArgumentIdx(i); i++)
764 //                 p->SetData(mathed_parse(FLAG_BRACE|FLAG_BRACE_LAST));
765              } else 
766                mathPrintError("Unrecognized environment");
767          }
768          break;
769       }
770        
771     case LM_TK_MACRO:
772      { 
773           MathedInset * p = 
774             MathMacroTable::mathMTable.getMacro(yylval.l->name);
775          
776           if (p) {
777               if (accent) {
778                 data.Insert(doAccent(p));
779               } else
780                 data.Insert(p, ((MathMacro*)p)->getTCode());
781           }
782           break;
783       }
784        
785      case LM_TK_LABEL:
786        {           
787           char rg = LexGetArg('\0', true);
788           if (rg != '}') {
789              mathPrintError("Expected '{'");
790               // debug info
791              lyxerr << "[" << yytext << "]" << endl;
792               panic = true;
793              break;
794           } 
795           if (crow) {
796               // This is removed by crow's destructor. Bad design? yes, this 
797               // will be changed after 0.12
798               crow->setLabel(strnew(yytext));
799           }
800           else {
801                   // where is this math_label free'ed?
802                   // Supposedly in ~formula, another bad hack,
803                   // give me some time please.
804                   mathed_label = strnew(yytext);
805           }
806 #ifdef DEBUG
807           lyxerr << "Label[" << mathed_label << "]" << endl;
808 #endif
809           break;
810         } 
811      default:
812        mathPrintError("Unrecognized token");
813        // debug info
814        lyxerr << "[" << t << " " << yytext << "]" << endl;
815        break;
816     }
817     tprev = t;
818     if (panic) {
819             lyxerr << " Math Panic, expect problems!" << endl;
820        //   Search for the end command. 
821        do t = yylex (); while (t != LM_TK_END && t);
822     } else
823      t = yylex ();
824    
825    if ((flags & FLAG_BRACE_OPT)/* && t!= '^' && t!= '_'*/) {
826         flags &= ~FLAG_BRACE_OPT;
827        //data.Insert (LM_TC_CLOSE);
828        break;
829     }
830    }
831    plevel--;
832    return array;
833 }
834
835
836 void mathed_parser_file(FILE * file, int lineno)
837 {
838     yyin = file;
839     yylineno = lineno;
840     if (!MathMacroTable::built)
841         MathMacroTable::mathMTable.builtinMacros();
842 }
843
844
845 int mathed_parser_lineno()
846 {
847     return yylineno;
848 }
849