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