X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2Fmath_parser.C;h=c0e7a4165343556cba2c705b79e2cfd8bfda9069;hb=5c40a062b2034f48f5b79079017bbaac8ba9363c;hp=c762e8e1aaf49da6e69c65ee5e36b8997bcfcf1c;hpb=f1d829a18584fe8c787c7ea428f10cc7a82d6083;p=lyx.git diff --git a/src/mathed/math_parser.C b/src/mathed/math_parser.C index c762e8e1aa..c0e7a41653 100644 --- a/src/mathed/math_parser.C +++ b/src/mathed/math_parser.C @@ -15,6 +15,8 @@ * the GNU General Public Licence version 2 or later. */ +// {[( + #include #include @@ -25,91 +27,31 @@ #include "math_parser.h" #include "array.h" -#include "math_rowst.h" -#include "math_iter.h" #include "math_inset.h" +#include "math_arrayinset.h" +#include "math_bigopinset.h" +#include "math_dotsinset.h" +#include "math_decorationinset.h" +#include "math_deliminset.h" +#include "math_fracinset.h" +#include "math_funcinset.h" #include "math_macro.h" #include "math_macrotable.h" #include "math_macrotemplate.h" -#include "math_root.h" #include "math_matrixinset.h" -#include "math_accentinset.h" -#include "math_bigopinset.h" -#include "math_funcinset.h" +#include "math_rootinset.h" +#include "math_scriptinset.h" +#include "math_sizeinset.h" #include "math_spaceinset.h" -#include "math_dotsinset.h" -#include "math_fracinset.h" -#include "math_deliminset.h" -#include "math_decorationinset.h" +#include "math_sqrtinset.h" #include "debug.h" -#include "support/lyxlib.h" #include "mathed/support.h" -#include "boost/array.hpp" +#include "lyxlex.h" using std::istream; using std::endl; -extern MathMatrixInset create_multiline(short int type, int cols); - -namespace { - -enum { - FLAG_BRACE = 1, // A { needed - FLAG_BRACE_ARG = 2, // Next { is argument - FLAG_BRACE_OPT = 4, // Optional { - FLAG_BRACE_LAST = 8, // Last } ends the parsing process - FLAG_BRACK_ARG = 16, // Optional [ - FLAG_RIGHT = 32, // Next right ends the parsing process - FLAG_END = 64, // Next end ends the parsing process - FLAG_BRACE_FONT = 128, // Next } closes a font - FLAG_BRACK_END = 256 // Next ] ends the parsing process -}; - - -/// -union YYSTYPE { - /// - unsigned char c; - /// - char const * s; - /// - int i; - /// - latexkeys const * l; -}; - - -YYSTYPE yylval; - - -MathedInsetTypes mathed_env = LM_OT_MIN; - - -} // namespace anon - - -int const latex_mathenv_num = 12; -char const * latex_mathenv[latex_mathenv_num] = { - "math", - "displaymath", - "equation", - "eqnarray*", - "eqnarray", - "align*", - "align", - "alignat*", - "alignat", - "multline*", - "multline", - "array" -}; - - -char const * latex_special_chars = "#$%&_{}"; - - -namespace { // These are lexical codes, not semantic enum lexcode_enum { @@ -129,35 +71,100 @@ enum lexcode_enum { LexSelf }; - lexcode_enum lexcode[256]; -#ifdef WITH_WARNINGS -#warning Replace with string -#endif -//char yytext[256]; -boost::array yytext; + + +char const * latex_special_chars = "#$%&_{}"; + + +namespace { + +void mathed_parse(MathArray & array, unsigned flags); + +unsigned char getuchar(std::istream * is) +{ + char c; + is->get(c); + return static_cast(c); +} + +const unsigned char LM_TK_OPEN = '{'; +const unsigned char LM_TK_CLOSE = '}'; + +enum { + FLAG_BRACE = 1 << 0, // A { needed //} + FLAG_BRACE_LAST = 1 << 1, // // { Last } ends the parsing process + FLAG_RIGHT = 1 << 2, // Next right ends the parsing process + FLAG_END = 1 << 3, // Next end ends the parsing process + FLAG_BRACE_FONT = 1 << 4, // // { Next } closes a font + FLAG_BRACK_END = 1 << 5, // // [ Next ] ends the parsing process + FLAG_AMPERSAND = 1 << 6, // Next & ends the parsing process + FLAG_NEWLINE = 1 << 7, // Next \\ ends the parsing process + FLAG_ITEM = 1 << 8, // read a (possibly braced token) + FLAG_LEAVE = 1 << 9, // marker for leaving the + FLAG_OPTARG = 1 << 10 // reads an argument in [] +}; + +/// +union { + /// + int i; + /// + latexkeys const * l; +} yylval; + + + +string yytext; int yylineno; istream * yyis; -bool yy_mtextmode= false; +MathTextCodes yyvarcode; + + + +struct latex_mathenv_type { + char const * name; + char const * basename; + MathInsetTypes typ; + bool numbered; + bool ams; +}; + +latex_mathenv_type latex_mathenv[] = { + {"math", "math", LM_OT_SIMPLE, 0, 0}, + {"equation*", "equation", LM_OT_EQUATION, 0, 0}, + {"equation", "equation", LM_OT_EQUATION, 1, 0}, + {"eqnarray*", "eqnarray", LM_OT_EQNARRAY, 0, 0}, + {"eqnarray", "eqnarray", LM_OT_EQNARRAY, 1, 0}, + {"align*", "align", LM_OT_ALIGN, 0, 1}, + {"align", "align", LM_OT_ALIGN, 1, 1}, + {"alignat*", "alignat", LM_OT_ALIGNAT, 0, 1}, + {"alignat", "alignat", LM_OT_ALIGNAT, 1, 1}, + {"multline*", "multline", LM_OT_MULTLINE, 0, 1}, + {"multline", "multline", LM_OT_MULTLINE, 1, 1}, + {"array", "array", LM_OT_MATRIX, 0, 1} +}; + +int const latex_mathenv_num = sizeof(latex_mathenv)/sizeof(latex_mathenv[0]); + void mathPrintError(string const & msg) { + //lyxerr[Debug::MATHED] << "Line ~" << yylineno << ": Math parse error: " << msg << endl; lyxerr << "Line ~" << yylineno << ": Math parse error: " << msg << endl; } -void LexInitCodes() +void lexInit() { for (int i = 0; i <= 255; ++i) { - if (isalpha(i)) - lexcode[i] = LexAlpha; - else if (isdigit(i)) + if (isdigit(i)) lexcode[i] = LexDigit; else if (isspace(i)) lexcode[i] = LexSpace; else - lexcode[i] = LexNone; + lexcode[i] = LexAlpha; } lexcode['\t'] = lexcode['\f'] = lexcode[' '] = LexSpace; @@ -184,88 +191,84 @@ void LexInitCodes() } -char LexGetArg(char lf, bool accept_spaces = false) +string lexArg(unsigned char lf, bool accept_spaces = false) { - // unsigned char c; - // char cc; + string result; + unsigned char c = 0; while (yyis->good()) { - char cc; - yyis->get(cc); - unsigned char c = cc; - if (c > ' ') { - if (!lf) - lf = c; - else if (c != lf) { - lyxerr << "Math parse error: unexpected '" << c << "'" << endl; - return '\0'; - } + c = getuchar(yyis); + if (!isspace(c)) break; - } } - char const rg = - (lf == '{') ? '}' : - ((lf == '[') ? ']' - : ((lf == '(') ? ')' : 0)); + + if (c != lf) { + yyis->putback(c); + return result; + } + + unsigned char rg = 0; + if (lf == '{') rg = '}'; + if (lf == '[') rg = ']'; + if (lf == '(') rg = ')'; if (!rg) { - lyxerr << "Math parse error: unknown bracket '" << lf << "'" << endl; - return '\0'; + lyxerr[Debug::MATHED] << "Math parse error: unknown bracket '" + << lf << "'" << endl; + return result; } - char * p = &yytext[0]; - int bcnt = 1; + + int depth = 1; do { - char cc; - yyis->get(cc); - unsigned char c = cc; - if (c == lf) ++bcnt; - if (c == rg) --bcnt; - if ((c > ' ' || (c == ' ' && accept_spaces)) && bcnt > 0) - *(p++) = c; - } while (bcnt > 0 && yyis->good() && p - yytext.data() < 255); - - *p = '\0'; - return rg; + unsigned char c = getuchar(yyis); + if (c == lf) + ++depth; + if (c == rg) + --depth; + if ((!isspace(c) || (c == ' ' && accept_spaces)) && depth > 0) + result += c; + } while (depth > 0 && yyis->good()); + + return result; } -int yylex(void) +int yylex() { - static int init_done = 0; + static bool init_done = false; - if (!init_done) LexInitCodes(); + if (!init_done) { + lexInit(); + init_done = true; + } - unsigned char c; - char cc; while (yyis->good()) { - yyis->get(cc); - c = cc; + unsigned char c = getuchar(yyis); + //lyxerr << "reading byte: '" << c << "' code: " << lexcode[c] << endl; - if (yy_mtextmode && c == ' ') { - yylval.i= ' '; + if (yyvarcode == LM_TC_TEXTRM && c == ' ') { + yylval.i = ' '; return LM_TK_ALPHA; } else if (lexcode[c] == LexNewLine) { ++yylineno; continue; } else if (lexcode[c] == LexComment) { do { - yyis->get(cc); - c = cc; - } while (c != '\n' % yyis->good()); // eat comments + c = getuchar(yyis); + } while (c != '\n' && yyis->good()); // eat comments } else if (lexcode[c] == LexDigit || lexcode[c] == LexOther || lexcode[c] == LexMathSpace) { yylval.i = c; return LM_TK_STR; } else if (lexcode[c] == LexAlpha) { - yylval.i= c; + yylval.i = c; return LM_TK_ALPHA; } else if (lexcode[c] == LexBOP) { - yylval.i= c; + yylval.i = c; return LM_TK_BOP; } else if (lexcode[c] == LexSelf) { return c; } else if (lexcode[c] == LexArgument) { - yyis->get(cc); - c = cc; + c = getuchar(yyis); yylval.i = c - '0'; return LM_TK_ARGUMENT; } else if (lexcode[c] == LexOpen) { @@ -273,77 +276,62 @@ int yylex(void) } else if (lexcode[c] == LexClose) { return LM_TK_CLOSE; } else if (lexcode[c] == LexESC) { - yyis->get(cc); - c = cc; + c = getuchar(yyis); if (c == '\\') { + yylval.i = -1; return LM_TK_NEWLINE; } if (c == '(') { - yylval.i = LM_OT_MIN; + yylval.i = LM_OT_SIMPLE; return LM_TK_BEGIN; } if (c == ')') { - yylval.i = LM_OT_MIN; + yylval.i = LM_OT_SIMPLE; return LM_TK_END; } if (c == '[') { - yylval.i = LM_OT_PAR; + yylval.i = LM_OT_EQUATION; return LM_TK_BEGIN; } if (c == ']') { - yylval.i = LM_OT_PAR; + yylval.i = LM_OT_EQUATION; return LM_TK_END; } - if ( -#if 0 - strchr(latex_special_chars, c) -#else - contains(latex_special_chars, c) -#endif - ) { + if (contains(latex_special_chars, c)) { yylval.i = c; return LM_TK_SPECIAL; } if (lexcode[c] == LexMathSpace) { int i; - for (i = 0; i < 4 && static_cast(c) != latex_mathspace[i][0]; ++i); + for (i = 0; i < 4 && static_cast(c) != latex_mathspace[i][0]; ++i) + ; yylval.i = (i < 4) ? i : 0; return LM_TK_SPACE; } - if (lexcode[c] == LexAlpha || lexcode[c] == LexDigit) { - char * p = &yytext[0]; - while ((lexcode[c] == LexAlpha || lexcode[c] == LexDigit) - && p - yytext.data() < 255) { - *p = c; - yyis->get(cc); - c = cc; - ++p; + if (lexcode[c] == LexAlpha) { + yytext.erase(); + while (lexcode[c] == LexAlpha) { + yytext += c; + c = getuchar(yyis); } - *p = '\0'; if (yyis->good()) yyis->putback(c); - //lyxerr << "reading: '" << yytext.data() << "'\n"; - latexkeys const * l = in_word_set(yytext.data()); - if (l) { - if (l->token == LM_TK_BEGIN || l->token == LM_TK_END) { - int i; - LexGetArg('{'); -// for (i = 0; i < 5 && compare(yytext, latex_mathenv[i], -// strlen(latex_mathenv[i])); ++i); - - for (i = 0; - i < latex_mathenv_num - && compare(yytext.data(), latex_mathenv[i]); ++i); - yylval.i = i; - } else if (l->token == LM_TK_SPACE) - yylval.i = l->id; - else - yylval.l = l; - return l->token; - } else { - yylval.s = yytext.data(); + //lyxerr[Debug::MATHED] << "reading: text '" << yytext << "'\n"; + latexkeys const * l = in_word_set(yytext); + if (!l) return LM_TK_UNDEF; - } + + if (l->token == LM_TK_BEGIN || l->token == LM_TK_END) { + string name = lexArg('{'); + int i = 0; + while (i < latex_mathenv_num && name != latex_mathenv[i].name) + ++i; + yylval.i = i; + } else if (l->token == LM_TK_SPACE) + yylval.i = l->id; + else + yylval.l = l; + return l->token; } } } @@ -351,194 +339,220 @@ int yylex(void) } -#if 0 -int parse_align(char const * hor) -{ - int nc = 0; - for (char * c = hor; c && *c > ' '; ++c) ++nc; - return nc; -} -#else -int parse_align(string const & hor) +MathInset * lastUpDownInset(MathArray & array, bool up, bool down) { - int nc = 0; - string::const_iterator cit = hor.begin(); - string::const_iterator end = hor.end(); - for (; cit != end; ++cit) - if (*cit > ' ') ++nc; - return nc; + MathInset * p = array.back_inset(); + if (!p || !p->isUpDownInset()) { + p = new MathScriptInset(up, down); + array.push_back(p); + } + MathUpDownInset * q = static_cast(p); + if (up) + q->up(true); + if (down) + q->down(down); + return p; } -#endif -// Accent hacks only for 0.12. Stolen from Cursor. -int accent = 0; -int nestaccent[8]; -void setAccent(int ac) +MathBigopInset * lastBigopInset(MathArray & array) { - if (ac > 0 && accent < 8) - nestaccent[accent++] = ac; - else - accent = 0; // consumed! + MathInset * p = array.back_inset(); + return (p && p->isBigopInset()) ? static_cast(p) : 0; } -MathedInset * doAccent(byte c, MathedTextCodes t) -{ - MathedInset * ac = 0; - - for (int i = accent - 1; i >= 0; --i) { - if (i == accent - 1) - ac = new MathAccentInset(c, t, nestaccent[i]); - else - ac = new MathAccentInset(ac, nestaccent[i]); - } - accent = 0; // consumed! - - return ac; -} +static bool curr_num; +static string curr_label; -MathedInset * doAccent(MathedInset * p) +void mathed_parse_lines(MathInset * inset, int col, bool numbered, bool outmost) { - MathedInset * ac = 0; - - for (int i = accent - 1; i >= 0; --i) { - if (i == accent - 1) - ac = new MathAccentInset(p, nestaccent[i]); - else - ac = new MathAccentInset(ac, nestaccent[i]); + // save global variables + bool saved_num = curr_num; + string saved_label = curr_label; + + MathGridInset * p = static_cast(inset); + for (int row = 0; true; ++row) { + // reset global variables + curr_num = numbered; + curr_label = string(); + + // reading a row + int idx = p->nargs() - p->ncols(); + for (int i = 0; i < col - 1; ++i, ++idx) + mathed_parse(p->cell(idx), FLAG_AMPERSAND); + mathed_parse(p->cell(idx), FLAG_NEWLINE | FLAG_END); + + if (outmost) { + MathMatrixInset * m = static_cast(p); + m->numbered(row, curr_num); + m->label(row, curr_label); + } + + // Hack! + // no newline + if (yylval.i != -1) + break; + + p->appendRow(); } - accent = 0; // consumed! - - return ac; + + // restore global variables + curr_num = saved_num; + curr_label = saved_label; } -void do_insert(MathedIter & it, MathedInset * m, MathedTextCodes t) +MathInset * mathed_parse() { - if (accent) - it.insertInset(doAccent(m), t); - else - it.insertInset(m, t); + MathInset * p = 0; + int t = yylex(); + + switch (t) { + case LM_TK_NEWCOMMAND: { + string name = lexArg('{').substr(1); + string arg = lexArg('['); + int narg = arg.empty() ? 0 : atoi(arg.c_str()); + p = new MathMacroTemplate(name, narg); + mathed_parse(p->cell(0), FLAG_BRACE | FLAG_BRACE_LAST); + //lyxerr[Debug::MATHED] << "LM_TK_NEWCOMMAND: name: " + // << name << " nargs: " << narg << "\n"; + break; + } + + case LM_TK_BEGIN: { + int i = yylval.i; + //lyxerr[Debug::MATHED] << "reading math environment " << i << " " + // << latex_mathenv[i].name << "\n"; + + MathInsetTypes typ = latex_mathenv[i].typ; + p = new MathMatrixInset(typ); + MathMatrixInset * m = static_cast(p); + switch (typ) { + + case LM_OT_SIMPLE: { + curr_num = latex_mathenv[i].numbered; + curr_label = string(); + mathed_parse(m->cell(0), 0); + m->numbered(0, curr_num); + m->label(0, curr_label); + break; + } + + case LM_OT_EQUATION: { + curr_num = latex_mathenv[i].numbered; + curr_label = string(); + mathed_parse(m->cell(0), FLAG_END); + m->numbered(0, curr_num); + m->label(0, curr_label); + break; + } + + case LM_OT_EQNARRAY: { + mathed_parse_lines(m, 3, latex_mathenv[i].numbered, true); + break; + } + + case LM_OT_ALIGN: { + m->halign(lexArg('{')); + mathed_parse_lines(m, 2, latex_mathenv[i].numbered, true); + break; + } + + case LM_OT_ALIGNAT: { + m->halign(lexArg('{')); + mathed_parse_lines(m, 2, latex_mathenv[i].numbered, true); + break; + } + + default: + lyxerr[Debug::MATHED] << "1: unknown math environment: " << typ << "\n"; + } + + p->SetName(latex_mathenv[i].basename); + + break; + } + + default: + lyxerr[Debug::MATHED] << "2 unknown math environment: " << t << "\n"; + } + + return p; } -void handle_frac(MathedIter & it, MathParInset * & par, MathedInsetTypes t) +void handle_frac(MathArray & array, string const & name) { - MathFracInset fc(t); - MathedArray num; - mathed_parse(num, par, FLAG_BRACE|FLAG_BRACE_LAST); - MathedArray den; - mathed_parse(den, par, FLAG_BRACE|FLAG_BRACE_LAST); - fc.SetData(num, den); - it.insertInset(fc.Clone(), LM_TC_ACTIVE_INSET); + MathFracInset * p = new MathFracInset(name); + mathed_parse(p->cell(0), FLAG_ITEM); + mathed_parse(p->cell(1), FLAG_ITEM); + array.push_back(p); } -} // namespace anon - -/** - */ -void mathed_parse(MathedArray & array, MathParInset * & par, unsigned flags) +void mathed_parse(MathArray & array, unsigned flags) { int t = yylex(); - int tprev = 0; bool panic = false; static int plevel = -1; - static int size = LM_ST_TEXT; - MathedTextCodes varcode = LM_TC_VAR; - MathedInset * binset = 0; + yyvarcode = LM_TC_VAR; - string last_label; // last label seen - bool last_numbered = true; // have we seen '\nonumber' lately? - int brace = 0; - int acc_brace = 0; - int acc_braces[8]; ++plevel; - MathedIter data(&array); while (t) { - //lyxerr << "t: " << t << " par: " << par << " flags: " << flags; - //lyxerr << "label: '" << last_label << "' "; + //lyxerr << "t: " << t << " flags: " << flags << " i: " << yylval.i << " " + // << " plevel: " << plevel << " "; //array.dump(lyxerr); //lyxerr << "\n"; - if ((flags & FLAG_BRACE) && t != LM_TK_OPEN) { - if ((flags & FLAG_BRACK_ARG) && t == '[') { + if (flags & FLAG_ITEM) { + flags &= ~FLAG_ITEM; + if (t == LM_TK_OPEN) { + // skip the brace and regard everything to the next matching + // closing brace + t = yylex(); + ++brace; + flags |= FLAG_BRACE_LAST; } else { - mathPrintError("Expected {. Maybe you forgot to enclose an argument in {}"); - panic = true; - break; + // regard only this single token + flags |= FLAG_LEAVE; } } + if ((flags & FLAG_BRACE) && t != LM_TK_OPEN) { + mathPrintError( + "Expected {. Maybe you forgot to enclose an argument in {}"); + panic = true; + break; + } + switch (t) { case LM_TK_ALPHA: - if (accent) - data.insertInset(doAccent(yylval.i, varcode), LM_TC_INSET); - else - data.insert(yylval.i, varcode); //LM_TC_VAR); + array.push_back(yylval.i, yyvarcode); break; case LM_TK_ARGUMENT: - { - data.insertInset(new MathMacroArgument(yylval.i), LM_TC_INSET); + array.push_back(new MathMacroArgument(yylval.i)); break; - } - - case LM_TK_NEWCOMMAND: - { - int na = 0; - - LexGetArg('{'); - string name = &yytext[1]; - - char const c = yyis->peek(); - if (c == '[') { - LexGetArg('['); - na = lyx::atoi(yytext.data()); - } - //lyxerr << "LM_TK_NEWCOMMAND: name: " << name << " " << na << endl; -#ifdef WITH_WARNINGS -#warning dirty -#endif - par->SetName(name); - par->xo(na); // abuse xo - flags = FLAG_BRACE|FLAG_BRACE_LAST; - break; - } - case LM_TK_SPECIAL: - data.insert(yylval.i, LM_TC_SPECIAL); + array.push_back(yylval.i, LM_TC_SPECIAL); break; case LM_TK_STR: - if (accent) { - data.insertInset(doAccent(yylval.i, LM_TC_CONST), LM_TC_INSET); - } else - data.insert(yylval.i, LM_TC_CONST); + array.push_back(yylval.i, LM_TC_CONST); break; case LM_TK_OPEN: ++brace; - if (accent && tprev == LM_TK_ACCENT) { - acc_braces[acc_brace++] = brace; - break; - } - if (flags & FLAG_BRACE_OPT) { - flags &= ~FLAG_BRACE_OPT; - flags |= FLAG_BRACE; - } - if (flags & FLAG_BRACE) flags &= ~FLAG_BRACE; - else { - data.insert('{', LM_TC_TEX); - } + else + array.push_back('{', LM_TC_TEX); break; case LM_TK_CLOSE: @@ -548,471 +562,292 @@ void mathed_parse(MathedArray & array, MathParInset * & par, unsigned flags) panic = true; break; } - if (acc_brace && brace == acc_braces[acc_brace - 1] - 1) { - --acc_brace; - break; - } if (flags & FLAG_BRACE_FONT) { - varcode = LM_TC_VAR; - yy_mtextmode = false; + yyvarcode = LM_TC_VAR; flags &= ~FLAG_BRACE_FONT; break; } - if (brace == 0 && (flags & FLAG_BRACE_LAST)) { - --plevel; - goto clean_up; - } - data.insert('}', LM_TC_TEX); + if (brace == 0 && (flags & FLAG_BRACE_LAST)) + flags |= FLAG_LEAVE; + else + array.push_back('}', LM_TC_TEX); break; case '[': - if (flags & FLAG_BRACK_ARG) { - flags &= ~FLAG_BRACK_ARG; - char const rg = LexGetArg('['); - if (rg != ']') { - mathPrintError("Expected ']'"); - panic = true; - break; - } - // if (arg) strcpy(arg, yytext); - } else - data.insert('[', LM_TC_CONST); + array.push_back('[', LM_TC_CONST); break; case ']': - if (flags & FLAG_BRACK_END) { - --plevel; - goto clean_up; - } - data.insert(']', LM_TC_CONST); + if (flags & FLAG_BRACK_END) + flags |= FLAG_LEAVE; + else + array.push_back(']', LM_TC_CONST); break; case '^': - { - MathParInset * p = new MathParInset(size, "", LM_OT_SCRIPT); - MathedArray ar; - mathed_parse(ar, par, FLAG_BRACE_OPT|FLAG_BRACE_LAST); - p->setData(ar); - // lyxerr << "UP[" << p->GetStyle() << "]" << endl; - data.insertInset(p, LM_TC_UP); + mathed_parse(lastUpDownInset(array, true, false)->cell(0), FLAG_ITEM); break; - } case '_': - { - MathParInset * p = new MathParInset(size, "", - LM_OT_SCRIPT); - MathedArray ar; - mathed_parse(ar, par, FLAG_BRACE_OPT|FLAG_BRACE_LAST); - p->setData(ar); - data.insertInset(p, LM_TC_DOWN); + mathed_parse(lastUpDownInset(array, false, true)->cell(1), FLAG_ITEM); break; - } case LM_TK_LIMIT: - if (binset) { - binset->SetLimits(bool(yylval.l->id)); - binset = 0; - } + { + MathBigopInset * p = lastBigopInset(array); + if (p) + p->limits(yylval.l->id ? 1 : -1); break; + } - case '&': // Tab - data.insert('T', LM_TC_TAB); -#ifdef WITH_WARNINGS -#warning look here -#endif - data.setNumCols(par->GetColumns()); + case '&': + { + if (flags & FLAG_AMPERSAND) { + flags &= ~FLAG_AMPERSAND; + --plevel; + return; + } + lyxerr[Debug::MATHED] << "found tab unexpectedly, array: '" << array << "'\n"; break; + } case LM_TK_NEWLINE: - //lyxerr << "reading line " << par->getRowSt().size() << "\n"; - if (flags & FLAG_END) { - if (par->Permit(LMPF_ALLOW_CR)) { - par->getRowSt().push_back(); - if (last_numbered) { - //lyxerr << "line " << par->getRowSt().size() << " not numbered\n"; - par->getRowSt().back().setNumbered(false); - last_numbered = true; - } - if (last_label.size()) { - //lyxerr << "line " << par->getRowSt().size() << " labeled: " - // << last_label << endl; - par->getRowSt().back().setLabel(last_label); - last_label.erase(); - } - data.insert('K', LM_TC_CR); - } else - mathPrintError("Unexpected newline"); + { + if (flags & FLAG_NEWLINE) { + flags &= ~FLAG_NEWLINE; + --plevel; + return; } + lyxerr[Debug::MATHED] << "found newline unexpectedly, array: '" << array << "'\n"; break; - + } + case LM_TK_BIGSYM: { - binset = new MathBigopInset(yylval.l->name, yylval.l->id); - data.insertInset(binset, LM_TC_INSET); + array.push_back(new MathBigopInset(yylval.l->name, yylval.l->id)); break; } case LM_TK_SYM: if (yylval.l->id < 256) { - MathedTextCodes tc = MathIsBOPS(yylval.l->id) ? LM_TC_BOPS: LM_TC_SYMB; - if (accent) { - data.insertInset(doAccent(yylval.l->id, tc), LM_TC_INSET); - } else - data.insert(yylval.l->id, tc); - } else { - MathFuncInset * bg = new MathFuncInset(yylval.l->name); - if (accent) { - data.insertInset(doAccent(bg), LM_TC_INSET); - } else { -#ifdef WITH_WARNINGS -#warning This is suspisious! (Lgb) -#endif - // it should not take a bool as second arg (Lgb) - data.insertInset(bg, true); - } - - } + MathTextCodes tc = MathIsBOPS(yylval.l->id) ? LM_TC_BOPS : LM_TC_SYMB; + array.push_back(yylval.l->id, tc); + } else + array.push_back(new MathFuncInset(yylval.l->name)); break; case LM_TK_BOP: - if (accent) - data.insertInset(doAccent(yylval.i, LM_TC_BOP), LM_TC_INSET); - else - data.insert(yylval.i, LM_TC_BOP); + array.push_back(yylval.i, LM_TC_BOP); break; - case LM_TK_STY: - par->UserSetSize(yylval.l->id); - break; - case LM_TK_SPACE: - if (yylval.i >= 0) { - MathSpaceInset * sp = new MathSpaceInset(yylval.i); - data.insertInset(sp, LM_TC_INSET); - } + if (yylval.i >= 0) + array.push_back(new MathSpaceInset(yylval.i)); break; case LM_TK_DOTS: - { - MathDotsInset * p = new MathDotsInset(yylval.l->name, yylval.l->id); - data.insertInset(p, LM_TC_INSET); + array.push_back(new MathDotsInset(yylval.l->name, yylval.l->id)); break; - } case LM_TK_CHOOSE: - handle_frac(data, par, LM_OT_ATOP); + handle_frac(array, "atop"); break; case LM_TK_STACK: - handle_frac(data, par, LM_OT_STACKREL); + handle_frac(array, "stackrel"); break; case LM_TK_FRAC: - handle_frac(data, par, LM_OT_FRAC); + handle_frac(array, "frac"); break; case LM_TK_SQRT: - { - char c; - yyis->get(c); - + { + unsigned char c = getuchar(yyis); if (c == '[') { - MathRootInset rt(size); - - MathedArray ar1; - mathed_parse(ar1, par, FLAG_BRACK_END); - rt.setArgumentIdx(0); - rt.setData(ar1); // I belive that line is not needed (Lgb) - - MathedArray ar2; - mathed_parse(ar2, par, FLAG_BRACE|FLAG_BRACE_LAST); - - rt.setArgumentIdx(1); - rt.setData(ar2); // I belive that this line is not needed (Lgb) - - data.insertInset(rt.Clone(), LM_TC_ACTIVE_INSET); + array.push_back(new MathRootInset); + mathed_parse(array.back_inset()->cell(0), FLAG_BRACK_END); + mathed_parse(array.back_inset()->cell(1), FLAG_ITEM); } else { yyis->putback(c); - MathSqrtInset rt(size); - MathedArray ar; - mathed_parse(ar, par, FLAG_BRACE|FLAG_BRACE_LAST); - rt.setData(ar); // I belive that this line is not needed (Lgb) - data.insertInset(rt.Clone(), LM_TC_ACTIVE_INSET); + array.push_back(new MathSqrtInset); + mathed_parse(array.back_inset()->cell(0), FLAG_ITEM); } break; } case LM_TK_LEFT: { - int lfd = yylex(); - if (lfd == LM_TK_SYM || lfd == LM_TK_STR || lfd == LM_TK_BOP|| lfd == LM_TK_SPECIAL) - lfd = (lfd == LM_TK_SYM) ? yylval.l->id: yylval.i; -// lyxerr << "L[" << lfd << " " << lfd << "]"; - MathedArray ar; - mathed_parse(ar, par, FLAG_RIGHT); - int rgd = yylex(); -// lyxerr << "R[" << rgd << "]"; - if (rgd == LM_TK_SYM || rgd == LM_TK_STR || rgd == LM_TK_BOP || rgd == LM_TK_SPECIAL) - rgd = (rgd == LM_TK_SYM) ? yylval.l->id: yylval.i; - MathDelimInset * dl = new MathDelimInset(lfd, rgd); - dl->setData(ar); - data.insertInset(dl, LM_TC_ACTIVE_INSET); -// lyxerr << "RL[" << lfd << " " << rgd << "]"; + int ld = yylex(); + if (ld == LM_TK_SYM) + ld = yylval.l->id; + else if (ld == LM_TK_STR || ld == LM_TK_BOP || ld == LM_TK_SPECIAL) + ld = yylval.i; + + MathArray ar; + mathed_parse(ar, FLAG_RIGHT); + + int rd = yylex(); + if (rd == LM_TK_SYM) + rd = yylval.l->id; + else if (rd == LM_TK_STR || rd == LM_TK_BOP || rd == LM_TK_SPECIAL) + rd = yylval.i; + + MathDelimInset * dl = new MathDelimInset(ld, rd); + dl->cell(0) = ar; + array.push_back(dl); break; } case LM_TK_RIGHT: if (flags & FLAG_RIGHT) { --plevel; - goto clean_up; + return; } mathPrintError("Unmatched right delimiter"); // panic = true; break; case LM_TK_FONT: - varcode = static_cast(yylval.l->id); - yy_mtextmode = bool(varcode == LM_TC_TEXTRM); - flags |= (FLAG_BRACE|FLAG_BRACE_FONT); + yyvarcode = static_cast(yylval.l->id); + flags |= (FLAG_BRACE | FLAG_BRACE_FONT); break; - case LM_TK_WIDE: + case LM_TK_STY: + { + lyxerr[Debug::MATHED] << "LM_TK_STY not implemented\n"; + //MathArray tmp = array; + //MathSizeInset * p = new MathSizeInset(MathStyles(yylval.l->id)); + //array.push_back(p); + //mathed_parse(p->cell(0), FLAG_BRACE_FONT); + break; + } + + + case LM_TK_DECORATION: { - MathDecorationInset * sq = new MathDecorationInset(yylval.l->id, - size); - MathedArray ar; - mathed_parse(ar, par, FLAG_BRACE|FLAG_BRACE_LAST); - sq->setData(ar); - data.insertInset(sq, LM_TC_ACTIVE_INSET); + MathDecorationInset * p + = new MathDecorationInset(yylval.l->name, yylval.l->id); + mathed_parse(p->cell(0), FLAG_ITEM); + array.push_back(p); break; } - - case LM_TK_ACCENT: - setAccent(yylval.l->id); - break; case LM_TK_NONUM: - //lyxerr << "prepare line " << par->getRowSt().size() - // << " not numbered\n"; - last_numbered = false; + curr_num = false; break; case LM_TK_PMOD: case LM_TK_FUNC: - if (accent) { - data.insert(t, LM_TC_CONST); - } else { - MathedInset * bg = new MathFuncInset(yylval.l->name); - data.insertInset(bg, LM_TC_INSET); - } + array.push_back(new MathFuncInset(yylval.l->name)); break; case LM_TK_FUNCLIM: - data.insertInset(new MathFuncInset(yylval.l->name, LM_OT_FUNCLIM), - LM_TC_INSET); + array.push_back(new MathFuncInset(yylval.l->name, LM_OT_FUNCLIM)); break; - case LM_TK_UNDEF: - { - // save this value, yylval.s might get overwritten soon - const string name = yylval.s; - //lyxerr << "LM_TK_UNDEF: str = " << name << endl; - if (MathMacroTable::hasTemplate(name)) { - MathMacro * m = MathMacroTable::cloneTemplate(name); - //lyxerr << "Macro: " << m->GetData() << endl; - for (int i = 0; i < m->nargs(); ++i) { - MathedArray ar; - mathed_parse(ar, par, FLAG_BRACE|FLAG_BRACE_LAST); - m->setData(ar, i); - } - do_insert(data, m, m->getTCode()); - } else { - MathedInset * q = new MathFuncInset(name, LM_OT_UNDEF); - do_insert(data, q, LM_TC_INSET); - } + case LM_TK_UNDEF: + if (MathMacroTable::hasTemplate(yytext)) { + MathMacro * m = MathMacroTable::cloneTemplate(yytext); + for (int i = 0; i < m->nargs(); ++i) + mathed_parse(m->cell(i), FLAG_ITEM); + array.push_back(m); + m->Metrics(LM_ST_TEXT); + } else + array.push_back(new MathFuncInset(yytext, LM_OT_UNDEF)); break; - } case LM_TK_END: - if (mathed_env != yylval.i && yylval.i != LM_OT_MATRIX) - mathPrintError("Unmatched environment"); - // debug info [made that conditional -JMarc] - if (lyxerr.debugging(Debug::MATHED)) - lyxerr << "[" << yylval.i << "]" << endl; --plevel; - - //if (mt) { // && (flags & FLAG_END)) { - // par.setData(array); - // array.clear(); - //} -#ifdef WITH_WARNINGS -#warning Look here -#endif - goto clean_up; + return; case LM_TK_BEGIN: - if (yylval.i == LM_OT_MATRIX) { - //lyxerr << "###### Reading LM_OT_MATRIX \n"; -#if 0 - char ar[120]; - char ar2[8]; - ar[0] = ar2[0] = '\0'; -#endif - char rg = LexGetArg(0); -#if 1 - string ar2; -#endif - if (rg == ']') { -#if 0 - strcpy(ar2, yytext.data()); -#else - ar2 = yytext.data(); -#endif - rg = LexGetArg('{'); - } -#if 0 - strcpy(ar, yytext.data()); - int const nc = parse_align(ar); -#else - string ar(yytext.data()); - int const nc = parse_align(ar); -#endif - - MathParInset * mm = new MathMatrixInset(nc, 0); - mm->SetAlign(ar2[0], ar); - MathedArray dat; - mathed_parse(dat, mm, FLAG_END); - data.insertInset(mm, LM_TC_ACTIVE_INSET); - mm->setData(dat); - - } else if (is_eqn_type(yylval.i)) { - //lyxerr << "###### Reading is_eqn_type \n"; - if (plevel!= 0) { - mathPrintError("Misplaced environment"); - break; - } - - mathed_env = static_cast(yylval.i); - if (mathed_env != LM_OT_MIN) { - //lyxerr << "###### Reading mathed_env != LM_OT_MIN \n"; - size = LM_ST_DISPLAY; - if (is_multiline(mathed_env)) { - //lyxerr << "###### Reading is_multiline(mathed_env) \n"; - int cols = 1; - if (is_multicolumn(mathed_env)) { - //lyxerr << "###### Reading is_multicolumn(mathed_env) \n"; - if (mathed_env != LM_OT_ALIGNAT && - mathed_env != LM_OT_ALIGNATN && - yyis->good()) { - //lyxerr << "###### Reading is !align\n"; - char c; - yyis->get(c); - if (c != '%') - lyxerr << "Math parse error: unexpected '" - << c << "'" << endl; - } - LexGetArg('{'); - cols = strToInt(string(yytext.data())); - } -#ifdef WITH_WARNINGS -#warning look here -#endif - //mt = create_multiline(mathed_env, cols); - //if (mtx) *mtx = mt; - - //MathMatrixInset mat = create_multiline(mathed_env, cols); - //data.insertInset(mat.Clone(), LM_TC_ACTIVE_INSET); - - par = new MathMatrixInset(create_multiline(mathed_env, cols)); - flags |= FLAG_END; - } - par->SetStyle(size); - par->SetType(mathed_env); - } - - lyxerr[Debug::MATHED] << "MATH BEGIN[" << mathed_env << "]" << endl; - } else { - MathMacro * m = MathMacroTable::cloneTemplate(yytext.data()); - data.insertInset(m, m->getTCode()); - MathedArray dat; - mathed_parse(dat, par, FLAG_END); - } + { + int i = yylval.i; + MathInsetTypes typ = latex_mathenv[i].typ; + + if (typ == LM_OT_MATRIX) { + string valign = lexArg('[') + 'c'; + string halign = lexArg('{'); + //lyxerr << "valign: '" << valign << "'\n"; + //lyxerr << "halign: '" << halign << "'\n"; + MathArrayInset * m = new MathArrayInset(halign.size(), 1); + m->valign(valign[0]); + m->halign(halign); + + mathed_parse_lines(m, halign.size(), latex_mathenv[i].numbered, false); + array.push_back(m); + //lyxerr << "read matrix " << *m << "\n"; + break; + } else + lyxerr[Debug::MATHED] << "unknow math inset " << typ << "\n"; break; - + } + case LM_TK_MACRO: - { - MathMacro * m = MathMacroTable::cloneTemplate(yylval.l->name); - do_insert(data, m, m->getTCode()); + array.push_back(MathMacroTable::cloneTemplate(yylval.l->name)); break; - } case LM_TK_LABEL: - { - char const rg = LexGetArg('\0', true); - if (rg != '}') { - mathPrintError("Expected '{'"); - // debug info - lyxerr << "[" << yytext.data() << "]" << endl; - panic = true; - break; - } - last_label = yytext.data(); - //lyxerr << "prepare line " << par->getRowSt().size() - // << " label: " << last_label << endl; + curr_label = lexArg('{', true); break; - } default: mathPrintError("Unrecognized token"); - // debug info - lyxerr << "[" << t << " " << yytext.data() << "]" << endl; + lyxerr[Debug::MATHED] << "[" << t << " " << yytext << "]" << endl; break; - } // end of switch - - tprev = t; + + } // end of big switch + + if (flags & FLAG_LEAVE) { + flags &= ~FLAG_LEAVE; + break; + } + if (panic) { lyxerr << " Math Panic, expect problems!" << endl; // Search for the end command. do { - t = yylex (); + t = yylex(); } while (t != LM_TK_END && t); } else - t = yylex (); - - if ((flags & FLAG_BRACE_OPT)/* && t!= '^' && t!= '_'*/) { - flags &= ~FLAG_BRACE_OPT; - break; - } + t = yylex(); + } --plevel; +} -clean_up: - - if (last_numbered == false) { - //lyxerr << "last line " << par->getRowSt().size() << " not numbered\n"; - if (par->getRowSt().size() == 0) - par->getRowSt().push_back(); - par->getRowSt().back().setNumbered(false); - } - if (last_label.size()) { - //lyxerr << "last line " << par->getRowSt().size() << " labeled: " - // << last_label << endl; - if (par->getRowSt().size() == 0) - par->getRowSt().push_back(); - par->getRowSt().back().setLabel(last_label); - } } -void mathed_parser_file(istream & is, int lineno) +MathInset * mathed_parse(istream & is) { - yyis = &is; - yylineno = lineno; + yyis = &is; + yylineno = 0; + return mathed_parse(); } -int mathed_parser_lineno() +MathInset * mathed_parse(LyXLex & lex) { - return yylineno; + yyis = &lex.getStream(); + yylineno = lex.GetLineNo(); + + MathInset * p = mathed_parse(); + + // Update line number + lex.setLineNo(yylineno); + + // reading of end_inset + while (lex.IsOK()) { + lex.nextToken(); + if (lex.GetString() == "\\end_inset") + break; + lyxerr[Debug::MATHED] << "InsetFormula::Read: Garbage before \\end_inset," + " or missing \\end_inset!" << endl; + } + + return p; } + +//]})