]> git.lyx.org Git - features.git/blob - src/mathed/math_parser.C
make mathed compile (but not link), adjust
[features.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: 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 // {[(
19
20 #include <config.h>
21
22 #include <cctype>
23
24 #ifdef __GNUG__
25 #pragma implementation
26 #endif
27
28 #include "math_parser.h"
29 #include "array.h"
30 #include "math_inset.h"
31 #include "math_arrayinset.h"
32 #if 0
33 #include "math_bigopinset.h"
34 #endif
35 #include "math_dotsinset.h"
36 #include "math_decorationinset.h"
37 #include "math_deliminset.h"
38 #include "math_fracinset.h"
39 #include "math_funcinset.h"
40 #if 0
41 #include "math_funcliminset.h"
42 #endif
43 #include "math_macro.h"
44 #include "math_macrotable.h"
45 #include "math_macrotemplate.h"
46 #include "math_matrixinset.h"
47 #include "math_rootinset.h"
48 #include "math_scriptinset.h"
49 #include "math_sizeinset.h"
50 #include "math_spaceinset.h"
51 #include "math_sqrtinset.h"
52 #include "math_symbolinset.h"
53 #include "debug.h"
54 #include "mathed/support.h"
55 #include "lyxlex.h"
56 #include "support/lstrings.h"
57
58 using std::istream;
59 using std::endl;
60
61
62
63 // These are lexical codes, not semantic
64 enum lexcode_enum {
65         LexNone,
66         LexESC,
67         LexAlpha,
68         LexDigit,
69         LexBOP,         // Binary operators or relations
70         LexMathSpace,
71         LexOpen,
72         LexClose,
73         LexComment,
74         LexArgument,
75         LexSpace,
76         LexNewLine,
77         LexOther,
78         LexMath,
79         LexSelf
80 };
81
82 lexcode_enum lexcode[256];  
83
84
85 char const * latex_special_chars = "#$%&_{}";
86
87
88 namespace {
89
90 void mathed_parse_into(MathArray & array, unsigned flags);
91
92 unsigned char getuchar(std::istream * is)
93 {
94         char c = 0;
95         is->get(c);
96         if (!is->good())
97                 lyxerr << "The input stream is not well..." << endl;
98         
99         return static_cast<unsigned char>(c);
100 }
101
102 const unsigned char LM_TK_OPEN  = '{';
103 const unsigned char LM_TK_CLOSE = '}';
104
105 enum {
106         FLAG_BRACE      = 1 << 0,  //  A { needed              //}
107         FLAG_BRACE_LAST = 1 << 1,  //  // { Last } ends the parsing process
108         FLAG_RIGHT      = 1 << 2,  //  Next right ends the parsing process
109         FLAG_END        = 1 << 3,  //  Next end ends the parsing process
110         FLAG_BRACE_FONT = 1 << 4,  //  // { Next } closes a font
111         FLAG_BRACK_END  = 1 << 5,  //  // [ Next ] ends the parsing process
112         FLAG_AMPERSAND  = 1 << 6,  //  Next & ends the parsing process
113         FLAG_NEWLINE    = 1 << 7,  //  Next \\ ends the parsing process
114         FLAG_ITEM       = 1 << 8,  //  read a (possibly braced token)
115         FLAG_LEAVE      = 1 << 9,  //  marker for leaving the 
116         FLAG_OPTARG     = 1 << 10  //  reads an argument in []
117 };
118
119 ///
120 union {
121         ///
122         int i;
123         ///
124         latexkeys const * l;
125 } yylval;
126
127
128
129 string yytext;
130 int yylineno;
131 istream * yyis;
132
133
134
135 struct latex_mathenv_type {
136         char const *      name;
137         char const *      basename;
138         MathInsetTypes    typ;
139         bool              numbered;
140         bool              ams;
141 };
142
143 latex_mathenv_type latex_mathenv[] = { 
144         {"math",         "math",         LM_OT_SIMPLE,   0, 0},
145         {"equation*",    "equation",     LM_OT_EQUATION, 0, 0},
146         {"equation",     "equation",     LM_OT_EQUATION, 1, 0},
147         {"eqnarray*",    "eqnarray",     LM_OT_EQNARRAY, 0, 0},
148         {"eqnarray",     "eqnarray",     LM_OT_EQNARRAY, 1, 0},
149         {"align*",       "align",        LM_OT_ALIGN,    0, 1},
150         {"align",        "align",        LM_OT_ALIGN,    1, 1},
151         {"alignat*",     "alignat",      LM_OT_ALIGNAT,  0, 1},
152         {"alignat",      "alignat",      LM_OT_ALIGNAT,  1, 1},
153         {"multline*",    "multline",     LM_OT_MULTLINE, 0, 1},
154         {"multline",     "multline",     LM_OT_MULTLINE, 1, 1},
155         {"array",        "array",        LM_OT_MATRIX,   0, 1}
156 };
157
158 int const latex_mathenv_num = sizeof(latex_mathenv)/sizeof(latex_mathenv[0]);
159
160
161
162 void mathPrintError(string const & msg) 
163 {
164         //lyxerr[Debug::MATHED] << "Line ~" << yylineno << ": Math parse error: " << msg << endl;
165         lyxerr << "Line ~" << yylineno << ": Math parse error: " << msg << endl;
166 }
167
168
169 void lexInit()
170 {
171         for (int i = 0; i <= 255; ++i) {
172                 if (isdigit(i))
173                         lexcode[i] = LexDigit;
174                 else if (isspace(i))
175                         lexcode[i] = LexSpace;
176                 else
177                         lexcode[i] = LexAlpha;
178         }
179         
180         lexcode['\t'] = lexcode['\f'] = lexcode[' '] = LexSpace;
181         lexcode['\n'] = LexNewLine;
182         lexcode['%'] = LexComment;
183         lexcode['#'] = LexArgument;
184         lexcode['$'] = LexMath;
185         lexcode['+'] = lexcode['-'] = lexcode['*'] = lexcode['/']
186                 = lexcode['<'] = lexcode['>'] = lexcode['='] = LexBOP;
187         
188         lexcode['!'] = lexcode[','] = lexcode[':']
189                 = lexcode[';'] = LexMathSpace;
190         
191         lexcode['('] = lexcode[')'] = lexcode['|'] = lexcode['.'] =
192                 lexcode['?'] = LexOther; 
193         
194         lexcode['\''] = lexcode['@'] = LexAlpha;
195         
196         lexcode['['] = lexcode[']'] = lexcode['^'] = lexcode['_'] = 
197                 lexcode['&'] = LexSelf;  
198         
199         lexcode['\\'] = LexESC;
200         lexcode['{'] = LexOpen;
201         lexcode['}'] = LexClose;
202 }
203
204
205 string lexArg(unsigned char lf, bool accept_spaces = false)
206 {
207         string result;
208         unsigned char c = 0;
209         while (yyis->good()) {
210                 c = getuchar(yyis);
211                 if (!isspace(c))
212                         break;
213         }
214
215         if (c != lf) {
216                 yyis->putback(c);
217                 return result;
218         }
219                 
220         unsigned char rg = 0;
221         if (lf == '{') rg = '}';
222         if (lf == '[') rg = ']';
223         if (lf == '(') rg = ')';
224         if (!rg) {
225                 lyxerr[Debug::MATHED] << "Math parse error: unknown bracket '"
226                         << lf << "'" << endl;
227                 return result;
228         }
229
230         int depth = 1;
231         do {
232                 unsigned char c = getuchar(yyis);
233                 if (c == lf)
234                         ++depth;
235                 if (c == rg)
236                         --depth;
237                 if ((!isspace(c) || (c == ' ' && accept_spaces)) && depth > 0)
238                         result += c;
239         } while (depth > 0 && yyis->good());
240
241         return result;
242 }
243
244
245 int yylex()
246 {
247         static bool init_done = false;
248         
249         if (!init_done) {
250                 lexInit();
251                 init_done = true;
252         }
253         
254         while (yyis->good()) {
255                 unsigned char c = getuchar(yyis);
256                 //lyxerr << "reading byte: '" << c << "' code: " << lexcode[c] << endl;
257                 
258                 if (lexcode[c] == LexNewLine) {
259                         ++yylineno; 
260                         continue;
261                 } else if (lexcode[c] == LexComment) {
262                         do {
263                                 c = getuchar(yyis);
264                         } while (c != '\n' && yyis->good());  // eat comments
265                 } else if (lexcode[c] == LexDigit
266                            || lexcode[c] == LexOther
267                            || lexcode[c] == LexMathSpace) {
268                         yylval.i = c;
269                         return LM_TK_STR;
270                 } else if (lexcode[c] == LexAlpha || lexcode[c] == LexSpace) {
271                         yylval.i = c;
272                         return LM_TK_ALPHA;
273                 } else if (lexcode[c] == LexBOP) {
274                         yylval.i = c;
275                         return LM_TK_BOP;
276                 } else if (lexcode[c] == LexMath) {
277                         yylval.i = 0;
278                         return LM_TK_MATH;
279                 } else if (lexcode[c] == LexSelf) {
280                         return c;
281                 } else if (lexcode[c] == LexArgument) {
282                         c = getuchar(yyis);
283                         yylval.i = c - '0';
284                         return LM_TK_ARGUMENT; 
285                 } else if (lexcode[c] == LexOpen) {
286                         return LM_TK_OPEN;
287                 } else if (lexcode[c] == LexClose) {
288                         return LM_TK_CLOSE;
289                 } else if (lexcode[c] == LexESC)   {
290                         c = getuchar(yyis);
291                         if (c == '\\')  {
292                                 yylval.i = -1;
293                                 return LM_TK_NEWLINE;
294                         }
295                         if (c == '(') {
296                                 yylval.i = LM_OT_SIMPLE;
297                                 return LM_TK_BEGIN;
298                         }
299                         if (c == ')') {
300                                 yylval.i = LM_OT_SIMPLE;
301                                 return LM_TK_END;
302                         }
303                         if (c == '[') {
304                                 yylval.i = LM_OT_EQUATION;
305                                 return LM_TK_BEGIN;
306                         }
307                         if (c == ']') {
308                                 yylval.i = LM_OT_EQUATION;
309                                 return LM_TK_END;
310                         }
311                         if (c == '|') {
312                                 yytext = "|";
313                                 return LM_TK_UNDEF;
314                         }
315                         if (contains(latex_special_chars, c)) {
316                                 yylval.i = c;
317                                 return LM_TK_SPECIAL;
318                         } 
319                         if (lexcode[c] == LexMathSpace) {
320                                 int i;
321                                 for (i = 0; i < 4 && static_cast<int>(c) != latex_mathspace[i][0]; ++i)
322                                         ;
323                                 yylval.i = (i < 4) ? i : 0; 
324                                 return LM_TK_SPACE; 
325                         }
326                         if (lexcode[c] == LexAlpha) {
327                                 yytext.erase();
328                                 while (lexcode[c] == LexAlpha && yyis->good()) {
329                                         yytext += c;
330                                         c = getuchar(yyis);
331                                 }
332                                 while (lexcode[c] == LexSpace && yyis->good()) 
333                                         c = getuchar(yyis);
334                                 if (lexcode[c] != LexSpace)
335                                         yyis->putback(c);
336                         
337                                 //lyxerr[Debug::MATHED] << "reading: text '" << yytext << "'\n";
338                                 latexkeys const * l = in_word_set(yytext);
339                                 if (!l) 
340                                         return LM_TK_UNDEF;
341
342                                 if (l->token == LM_TK_BEGIN || l->token == LM_TK_END) { 
343                                         string name = lexArg('{');
344                                         int i = 0;
345                                         while (i < latex_mathenv_num && name != latex_mathenv[i].name)
346                                                  ++i;
347                                         yylval.i = i;
348                                 } else if (l->token == LM_TK_SPACE) 
349                                         yylval.i = l->id;
350                                 else
351                                         yylval.l = l;
352                                 return l->token;
353                         }
354                 }
355         }
356         return 0;
357 }
358
359
360 MathScriptInset * prevScriptInset(MathArray const & array)
361 {
362         MathInset * p = array.back();
363         return (p && p->isScriptInset()) ? static_cast<MathScriptInset *>(p) : 0;
364 }
365
366
367 MathInset * lastScriptInset(MathArray & array, bool up, bool down, int limits)
368 {
369         MathScriptInset * p = prevScriptInset(array);
370         if (!p) {
371                 MathInset * b = array.back();
372                 if (b && b->isScriptable()) {
373                         p = new MathScriptInset(up, down, b->clone());
374                         array.pop_back();       
375                 } else {
376                         p = new MathScriptInset(up, down);
377                 }
378                 array.push_back(p);
379         }
380         if (up)
381                 p->up(true);
382         if (down)
383                 p->down(down);
384         if (limits)
385                 p->limits(limits);
386         return p;
387 }
388
389
390 static bool   curr_num;
391 static string curr_label;
392
393 void mathed_parse_lines(MathInset * inset, int col,
394                         bool numbered, bool outmost)
395 {
396         // save global variables
397         bool   const saved_num   = curr_num;
398         string const saved_label = curr_label;
399
400         MathGridInset * p = static_cast<MathGridInset *>(inset);
401         for (int row = 0; true; ++row) {
402                 // reset global variables
403                 curr_num   = numbered;
404                 curr_label.erase();
405
406                 // reading a row
407                 int idx = p->nargs() - p->ncols();
408                 for (int i = 0; i < col - 1; ++i, ++idx)
409                         mathed_parse_into(p->cell(idx), FLAG_AMPERSAND);
410                 mathed_parse_into(p->cell(idx), FLAG_NEWLINE | FLAG_END);
411
412                 if (outmost) {
413                         MathMatrixInset * m = static_cast<MathMatrixInset *>(p);
414                         m->numbered(row, curr_num);
415                         m->label(row, curr_label);
416                 }
417
418                 // Hack!
419                 // no newline
420                 if (yylval.i != -1)
421                         break;
422
423                 p->appendRow();
424         }
425
426         // restore global variables
427         curr_num   = saved_num;
428         curr_label = saved_label;
429 }
430
431
432 MathMacroTemplate * mathed_parse_macro()
433 {
434         if (yylex() != LM_TK_NEWCOMMAND) {
435                 lyxerr << "\\newcommand expected\n";
436                 return 0;
437         }
438
439         string name = lexArg('{').substr(1);
440         string arg  = lexArg('[');
441         int    narg = arg.empty() ? 0 : atoi(arg.c_str()); 
442         MathMacroTemplate * p = new MathMacroTemplate(name, narg);
443         mathed_parse_into(p->cell(0), FLAG_BRACE | FLAG_BRACE_LAST);
444         return p;
445 }
446
447
448 MathMatrixInset * mathed_parse_normal()
449 {
450         MathMatrixInset * p = 0;
451         int t = yylex();
452
453         switch (t) {
454                 case LM_TK_MATH:
455                 case LM_TK_BEGIN: {
456                         int i = yylval.i;
457                         lyxerr[Debug::MATHED]
458                                 << "reading math environment " << i << " "
459                                 << latex_mathenv[i].name << "\n";
460
461                         MathInsetTypes typ = latex_mathenv[i].typ;
462                         p = new MathMatrixInset(typ);
463                         MathMatrixInset * m = static_cast<MathMatrixInset *>(p);
464                         switch (typ) {
465
466                                 case LM_OT_SIMPLE: {
467                                         curr_num   = latex_mathenv[i].numbered;
468                                         curr_label.erase();
469                                         mathed_parse_into(m->cell(0), 0);
470                                         m->numbered(0, curr_num);
471                                         m->label(0, curr_label);
472                                         break;
473                                 }
474
475                                 case LM_OT_EQUATION: {
476                                         curr_num   = latex_mathenv[i].numbered;
477                                         curr_label.erase();
478                                         mathed_parse_into(m->cell(0), FLAG_END);
479                                         m->numbered(0, curr_num);
480                                         m->label(0, curr_label);
481                                         break;
482                                 }
483
484                                 case LM_OT_EQNARRAY: {
485                                         mathed_parse_lines(m, 3, latex_mathenv[i].numbered, true);
486                                         break;
487                                 }
488
489                                 case LM_OT_ALIGN: {
490                                         m->halign(lexArg('{'));
491                                         mathed_parse_lines(m, 2, latex_mathenv[i].numbered, true);
492                                         break;
493                                 }
494
495                                 case LM_OT_ALIGNAT: {
496                                         m->halign(lexArg('{'));
497                                         mathed_parse_lines(m, 2, latex_mathenv[i].numbered, true);
498                                         break;
499                                 }
500
501                                 default: 
502                                         lyxerr[Debug::MATHED]
503                                                 << "1: unknown math environment: " << typ << "\n";
504                         }
505
506                         p->setName(latex_mathenv[i].basename);
507
508                         break;
509                 }
510                 
511                 default:
512                         lyxerr[Debug::MATHED]
513                                 << "2 unknown math environment: " << t << "\n";
514         }
515
516         return p;
517 }
518
519
520 void handle_frac(MathArray & array, string const & name)
521 {
522         MathFracInset * p = new MathFracInset(name);
523         mathed_parse_into(p->cell(0), FLAG_ITEM);
524         mathed_parse_into(p->cell(1), FLAG_ITEM);
525         array.push_back(p);
526 }
527
528
529 void mathed_parse_into(MathArray & array, unsigned flags)
530 {
531         static int plevel = -1;
532
533         ++plevel;
534         MathTextCodes yyvarcode   = LM_TC_VAR;
535
536         int  t      = yylex();
537         bool panic  = false;
538         int  brace  = 0;
539         int  limits = 0;
540
541         while (t) {
542                 //lyxerr << "t: " << t << " flags: " << flags << " i: " << yylval.i
543                 //      << " '" << yytext << "'\n";
544                 //array.dump(lyxerr);
545                 //lyxerr << "\n";
546
547                 if (flags & FLAG_ITEM) {
548                         flags &= ~FLAG_ITEM;
549                         if (t == LM_TK_OPEN) { 
550                                 // skip the brace and regard everything to the next matching
551                                 // closing brace
552                                 t = yylex();
553                                 ++brace;
554                                 flags |= FLAG_BRACE_LAST;
555                         } else {
556                                 // regard only this single token
557                                 flags |= FLAG_LEAVE;
558                         }
559                 }
560
561                 if ((flags & FLAG_BRACE) && t != LM_TK_OPEN) {
562                         mathPrintError(
563                                 "Expected {. Maybe you forgot to enclose an argument in {}");
564                         panic = true;
565                         break;
566                 }
567
568                 switch (t) {
569                         
570                 case LM_TK_ALPHA:
571                         if (!isspace(yylval.i) || yyvarcode == LM_TC_TEXTRM)
572                                 array.push_back(yylval.i, yyvarcode);
573                         break;
574
575                 case LM_TK_ARGUMENT: {
576                         MathMacroArgument * p = new MathMacroArgument(yylval.i);
577                         p->code(yyvarcode);
578                         array.push_back(p);
579                         break;
580                 }
581
582                 case LM_TK_SPECIAL:
583                         array.push_back(yylval.i, LM_TC_SPECIAL);
584                         break;
585
586                 case LM_TK_STR:
587                         array.push_back(yylval.i, LM_TC_CONST);
588                         break;
589
590                 case LM_TK_OPEN:
591                         ++brace;
592                         if (flags & FLAG_BRACE)
593                                 flags &= ~FLAG_BRACE;
594                         else 
595                                 array.push_back('{', LM_TC_TEX);
596                         break;
597
598                 case LM_TK_CLOSE:
599                         --brace;
600                         if (brace < 0) {
601                                 mathPrintError("Unmatching braces");
602                                 panic = true;
603                                 break;
604                         }
605                         if (flags & FLAG_BRACE_FONT) {
606                                 yyvarcode = LM_TC_VAR;
607                                 flags &= ~FLAG_BRACE_FONT;
608                                 break;
609                         }
610                         if (brace == 0 && (flags & FLAG_BRACE_LAST))
611                                 flags |= FLAG_LEAVE;
612                         else
613                                 array.push_back('}', LM_TC_TEX);
614                         break;
615                 
616                 case '[':
617                         array.push_back('[', LM_TC_CONST);
618                         break;
619
620                 case ']':
621                         if (flags & FLAG_BRACK_END)
622                                 flags |= FLAG_LEAVE;
623                         else 
624                                 array.push_back(']', LM_TC_CONST);
625                         break;
626                 
627                 case '^':
628                         mathed_parse_into(
629                                 lastScriptInset(array, true, false, limits)->cell(0), FLAG_ITEM);
630                         break;
631                 
632                 case '_':
633                         mathed_parse_into(
634                                 lastScriptInset(array, false, true, limits)->cell(1), FLAG_ITEM);
635                         break;
636                 
637                 case LM_TK_LIMIT:
638                         limits = yylval.l->id;
639                         //lyxerr << "setting limit to " << limits << "\n";
640                         break;
641                 
642                 case '&':
643                         if (flags & FLAG_AMPERSAND) {
644                                 flags &= ~FLAG_AMPERSAND;
645                                 --plevel;
646                                 return;
647                         }
648                         lyxerr[Debug::MATHED]
649                                 << "found tab unexpectedly, array: '" << array << "'\n";
650                         break;
651                 
652                 case LM_TK_NEWLINE:
653                         if (flags & FLAG_NEWLINE) {
654                                 flags &= ~FLAG_NEWLINE;
655                                 --plevel;
656                                 return;
657                         }
658                         lyxerr[Debug::MATHED]
659                                 << "found newline unexpectedly, array: '" << array << "'\n";
660                         break;
661                 
662                 case LM_TK_PROTECT: 
663                         break;
664
665                 case LM_TK_BIGSYM:  
666                         limits = 0;
667 #if 0
668                         array.push_back(new MathBigopInset(yylval.l));
669 #endif
670                         break;
671
672                 case LM_TK_FUNCLIM:
673                         limits = 0;
674 #if 0
675                         array.push_back(new MathFuncLimInset(yylval.l));
676 #endif
677                         break;
678
679                 case LM_TK_SYM:
680                         limits = 0;
681                         array.push_back(new MathSymbolInset(yylval.l));
682                         break;
683
684                 case LM_TK_BOP:
685                         array.push_back(yylval.i, LM_TC_BOP);
686                         break;
687
688                 case LM_TK_SPACE:
689                         if (yylval.i >= 0) 
690                                 array.push_back(new MathSpaceInset(yylval.i));
691                         break;
692
693                 case LM_TK_DOTS:
694                         array.push_back(new MathDotsInset(yylval.l));
695                         break;
696                 
697                 case LM_TK_CHOOSE:
698                         handle_frac(array, "atop");     
699                         break;
700
701                 case LM_TK_STACK:
702                         handle_frac(array, "stackrel"); 
703                         break;
704
705                 case LM_TK_FRAC:
706                         handle_frac(array, "frac");     
707                         break;
708
709                 case LM_TK_SQRT:
710                 {
711                         unsigned char c = getuchar(yyis);
712                         if (c == '[') {
713                                 array.push_back(new MathRootInset);
714                                 mathed_parse_into(array.back()->cell(0), FLAG_BRACK_END);
715                                 mathed_parse_into(array.back()->cell(1), FLAG_ITEM);
716                         } else {
717                                 yyis->putback(c);
718                                 array.push_back(new MathSqrtInset);
719                                 mathed_parse_into(array.back()->cell(0), FLAG_ITEM);
720                         }
721                         break;
722                 }
723                 
724                 case LM_TK_LEFT:
725                 {
726                         int ld = yylex();
727                         if (ld == LM_TK_SYM)
728                                 ld = yylval.l->id;
729                         else if (ld == LM_TK_STR || ld == LM_TK_BOP || ld == LM_TK_SPECIAL)
730                                 ld = yylval.i;
731
732                         MathArray ar;
733                         mathed_parse_into(ar, FLAG_RIGHT);
734
735                         int rd = yylex();
736                         if (rd == LM_TK_SYM)
737                                 rd = yylval.l->id;
738                         else if (rd == LM_TK_STR || rd == LM_TK_BOP || rd == LM_TK_SPECIAL)
739                                 rd = yylval.i;   
740
741                         MathDelimInset * dl = new MathDelimInset(ld, rd);
742                         dl->cell(0) = ar;
743                         array.push_back(dl);
744                         break;
745                 }
746                 
747                 case LM_TK_RIGHT:
748                         if (flags & FLAG_RIGHT) { 
749                                 --plevel;
750                                 return;
751                         }
752                         mathPrintError("Unmatched right delimiter");
753 //        panic = true;
754                         break;
755                 
756                 case LM_TK_FONT:
757                         yyvarcode = static_cast<MathTextCodes>(yylval.l->id);
758                         flags |= (FLAG_BRACE | FLAG_BRACE_FONT);
759                         break;
760
761                 case LM_TK_STY:
762                 {
763                         lyxerr[Debug::MATHED] << "LM_TK_STY not implemented\n";
764                         //MathArray tmp = array;
765                         //MathSizeInset * p = new MathSizeInset(MathStyles(yylval.l->id));
766                         //array.push_back(p);
767                         //mathed_parse_into(p->cell(0), FLAG_BRACE_FONT);
768                         break; 
769                 }
770
771
772                 case LM_TK_DECORATION:
773                 {  
774                         MathDecorationInset * p = new MathDecorationInset(yylval.l);
775                         mathed_parse_into(p->cell(0), FLAG_ITEM);
776                         array.push_back(p);
777                         break;
778                 }
779                         
780                 case LM_TK_NONUM:
781                         curr_num = false;
782                         break;
783                 
784                 case LM_TK_FUNC:
785                         array.push_back(new MathSymbolInset(yylval.l));
786                         break;
787                 
788                 case LM_TK_UNDEF: 
789                         if (MathMacroTable::hasTemplate(yytext)) {
790                                 MathMacro * m = MathMacroTable::cloneTemplate(yytext);
791                                 for (int i = 0; i < m->nargs(); ++i) 
792                                         mathed_parse_into(m->cell(i), FLAG_ITEM);
793                                 array.push_back(m);
794                                 m->metrics(LM_ST_TEXT);
795                         } else
796                                 array.push_back(new MathFuncInset(yytext));
797                         break;
798                 
799                 case LM_TK_MATH:
800                 case LM_TK_END:
801                         --plevel;
802                         return;
803
804                 case LM_TK_BEGIN:
805                 {
806                         int i = yylval.i;
807                         MathInsetTypes typ = latex_mathenv[i].typ;
808
809                         if (typ == LM_OT_MATRIX) {
810                                 string const valign = lexArg('[') + 'c';
811                                 string const halign = lexArg('{');
812                                 //lyxerr << "valign: '" << valign << "'\n";
813                                 //lyxerr << "halign: '" << halign << "'\n";
814                                 MathArrayInset * m = new MathArrayInset(halign.size(), 1);
815                                 m->valign(valign[0]);
816                                 m->halign(halign);
817
818                                 mathed_parse_lines(m, halign.size(), latex_mathenv[i].numbered, false);
819                                 array.push_back(m);
820                                 //lyxerr << "read matrix " << *m << "\n";       
821                                 break;
822                         } else 
823                                 lyxerr[Debug::MATHED] << "unknow math inset " << typ << "\n";   
824                         break;
825                 }
826         
827                 case LM_TK_MACRO:
828                         array.push_back(MathMacroTable::cloneTemplate(yylval.l->name));
829                         break;
830                 
831                 case LM_TK_LABEL:
832                         curr_label = lexArg('{', true);
833                         break;
834                 
835                 default:
836                         mathPrintError("Unrecognized token");
837                         lyxerr[Debug::MATHED] << "[" << t << " " << yytext << "]" << endl;
838                         break;
839
840                 } // end of big switch
841
842                 if (flags & FLAG_LEAVE) {
843                         flags &= ~FLAG_LEAVE;
844                         break;
845                 }
846
847                 if (panic) {
848                         lyxerr << " Math Panic, expect problems!" << endl;
849                         //   Search for the end command. 
850                         do {
851                                 t = yylex();
852                         } while (yyis->good() && t != LM_TK_END && t);
853                 } else {
854                         t = yylex();
855                 }
856         }
857         --plevel;
858 }
859
860 }
861
862
863 MathArray mathed_parse_cell(string const & str)
864 {
865         istringstream is(str.c_str());
866         yyis     = &is;
867         yylineno = 0;
868         MathArray ar;
869         mathed_parse_into(ar, 0);
870         return ar;
871 }
872
873
874 MathMacroTemplate * mathed_parse_macro(string const & str)
875 {
876         istringstream is(str.c_str());
877         return mathed_parse_macro(is);
878 }
879
880
881 MathMatrixInset * mathed_parse_normal(string const & str)
882 {
883         istringstream is(str.c_str());
884         return mathed_parse_normal(is);
885 }
886
887
888
889 MathMatrixInset * mathed_parse_normal(istream & is)
890 {
891         yyis     = &is;
892         yylineno = 0;
893         return mathed_parse_normal();
894 }
895
896
897 MathMacroTemplate * mathed_parse_macro(istream & is)
898 {
899         yyis     = &is;
900         yylineno = 0;
901         return mathed_parse_macro();
902 }
903
904
905
906 MathMatrixInset * mathed_parse_normal(LyXLex & lex)
907 {
908         yyis     = &lex.getStream();
909         yylineno = lex.getLineNo();
910
911         MathMatrixInset * p = mathed_parse_normal();
912
913         // Update line number
914         lex.setLineNo(yylineno);
915
916         // reading of end_inset
917         while (lex.isOK()) {
918                 lex.nextToken();
919                 if (lex.getString() == "\\end_inset")
920                         break;
921                 lyxerr[Debug::MATHED] << "InsetFormula::Read: Garbage before \\end_inset,"
922                         " or missing \\end_inset!" << endl;
923         }
924
925         return p;
926 }
927
928 MathMacroTemplate * mathed_parse_macro(LyXLex & lex)
929 {
930         yyis     = &lex.getStream();
931         yylineno = lex.getLineNo();
932
933         MathMacroTemplate * p = mathed_parse_macro();
934
935         // Update line number
936         lex.setLineNo(yylineno);
937
938         // reading of end_inset
939         while (lex.isOK()) {
940                 lex.nextToken();
941                 if (lex.getString() == "\\end_inset")
942                         break;
943                 lyxerr[Debug::MATHED] << "InsetFormula::Read: Garbage before \\end_inset,"
944                         " or missing \\end_inset!" << endl;
945         }
946
947         return p;
948 }
949 //]})