X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2Fmath_parser.C;h=c0e7a4165343556cba2c705b79e2cfd8bfda9069;hb=5c40a062b2034f48f5b79079017bbaac8ba9363c;hp=20e4c73276354d261aaefa07801ae2b4aa372b5c;hpb=b24b504cd296351e1109a6cd58b645567a8a68a3;p=lyx.git diff --git a/src/mathed/math_parser.C b/src/mathed/math_parser.C index 20e4c73276..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 @@ -26,22 +28,22 @@ #include "math_parser.h" #include "array.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_arrayinset.h" -#include "math_sqrtinset.h" #include "math_matrixinset.h" -#include "math_accentinset.h" -#include "math_bigopinset.h" -#include "math_funcinset.h" -#include "math_spaceinset.h" +#include "math_rootinset.h" +#include "math_scriptinset.h" #include "math_sizeinset.h" -#include "math_dotsinset.h" -#include "math_fracinset.h" -#include "math_deliminset.h" -#include "math_decorationinset.h" +#include "math_spaceinset.h" +#include "math_sqrtinset.h" #include "debug.h" #include "mathed/support.h" #include "lyxlex.h" @@ -75,12 +77,10 @@ lexcode_enum lexcode[256]; char const * latex_special_chars = "#$%&_{}"; -/// Read TeX into data, flags give stop conditions -void mathed_parse(MathArray & data, unsigned flags); - - namespace { +void mathed_parse(MathArray & array, unsigned flags); + unsigned char getuchar(std::istream * is) { char c; @@ -93,18 +93,18 @@ const unsigned char LM_TK_CLOSE = '}'; enum { FLAG_BRACE = 1 << 0, // A { needed //} - FLAG_BRACE_OPT = 1 << 2, // Optional { - FLAG_BRACE_LAST = 1 << 3, // Last } ends the parsing process - FLAG_BRACK_ARG = 1 << 4, // Optional [ - FLAG_RIGHT = 1 << 5, // Next right ends the parsing process - FLAG_END = 1 << 6, // Next end ends the parsing process - FLAG_BRACE_FONT = 1 << 7, // Next } closes a font - FLAG_BRACK_END = 1 << 9, // Next ] ends the parsing process - FLAG_AMPERSAND = 1 << 10, // Next & ends the parsing process - FLAG_NEWLINE = 1 << 11 // Next \\ ends the parsing process + 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 { /// @@ -114,6 +114,7 @@ union { } yylval; + string yytext; int yylineno; istream * yyis; @@ -150,11 +151,12 @@ 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[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 (isdigit(i)) @@ -189,47 +191,54 @@ void LexInitCodes() } -unsigned char LexGetArg(unsigned char lf, bool accept_spaces = false) +string lexArg(unsigned char lf, bool accept_spaces = false) { + string result; + unsigned char c = 0; while (yyis->good()) { - unsigned char c = getuchar(yyis); - if (c > ' ') { - if (!lf) - lf = c; - else if (c != lf) { - lyxerr[Debug::MATHED] << "Math parse error: unexpected '" << c << "'" << endl; - return '\0'; - } + c = getuchar(yyis); + if (!isspace(c)) break; - } } + + if (c != lf) { + yyis->putback(c); + return result; + } + unsigned char rg = 0; if (lf == '{') rg = '}'; if (lf == '[') rg = ']'; if (lf == '(') rg = ')'; if (!rg) { - lyxerr[Debug::MATHED] << "Math parse error: unknown bracket '" << lf << "'" << endl; - return '\0'; + lyxerr[Debug::MATHED] << "Math parse error: unknown bracket '" + << lf << "'" << endl; + return result; } - yytext.erase(); - int bcnt = 1; + + int depth = 1; do { unsigned char c = getuchar(yyis); - if (c == lf) ++bcnt; - if (c == rg) --bcnt; - if ((c > ' ' || (c == ' ' && accept_spaces)) && bcnt > 0) - yytext += c; - } while (bcnt > 0 && yyis->good()); - - return rg; + 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() { - static int init_done; + static bool init_done = false; - if (!init_done) LexInitCodes(); + if (!init_done) { + lexInit(); + init_done = true; + } while (yyis->good()) { unsigned char c = getuchar(yyis); @@ -299,23 +308,23 @@ int yylex() yylval.i = (i < 4) ? i : 0; return LM_TK_SPACE; } - if (lexcode[c] == LexAlpha || lexcode[c] == LexDigit) { + if (lexcode[c] == LexAlpha) { yytext.erase(); - while (lexcode[c] == LexAlpha || lexcode[c] == LexDigit) { + while (lexcode[c] == LexAlpha) { yytext += c; c = getuchar(yyis); } if (yyis->good()) yyis->putback(c); - lyxerr[Debug::MATHED] << "reading: text '" << yytext << "'\n"; + //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) { - LexGetArg('{'); + string name = lexArg('{'); int i = 0; - while (i < latex_mathenv_num && yytext != latex_mathenv[i].name) + while (i < latex_mathenv_num && name != latex_mathenv[i].name) ++i; yylval.i = i; } else if (l->token == LM_TK_SPACE) @@ -330,87 +339,26 @@ int yylex() } -// Accent hacks only for 0.12. Stolen from Cursor. -int accent = 0; -int nestaccent[8]; - -void setAccent(int ac) -{ - if (ac > 0 && accent < 8) - nestaccent[accent++] = ac; - else - accent = 0; // consumed! -} - - -MathInset * doAccent(unsigned char c, MathTextCodes t) +MathInset * lastUpDownInset(MathArray & array, bool up, bool down) { - MathInset * 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; -} - - -MathInset * doAccent(MathInset * p) -{ - MathInset * 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]); + MathInset * p = array.back_inset(); + if (!p || !p->isUpDownInset()) { + p = new MathScriptInset(up, down); + array.push_back(p); } - accent = 0; // consumed! - - return ac; -} - - -void do_insert(MathArray & dat, MathInset * m) -{ - if (accent) - dat.push_back(doAccent(m)); - else - dat.push_back(m); -} - -void do_insert(MathArray & dat, unsigned char ch, MathTextCodes fcode) -{ - if (accent) - dat.push_back(doAccent(ch, fcode)); - else - dat.push_back(ch, fcode); -} - - -void handle_frac(MathArray & dat, string const & name) -{ - MathFracInset * p = new MathFracInset(name); - mathed_parse(p->cell(0), FLAG_BRACE | FLAG_BRACE_LAST); - mathed_parse(p->cell(1), FLAG_BRACE | FLAG_BRACE_LAST); - dat.push_back(p); + MathUpDownInset * q = static_cast(p); + if (up) + q->up(true); + if (down) + q->down(down); + return p; } -MathScriptInset * lastScriptInset(MathArray & array) +MathBigopInset * lastBigopInset(MathArray & array) { MathInset * p = array.back_inset(); - if (!p || !p->isScriptInset()) { - p = new MathScriptInset; - array.push_back(p); - } - return static_cast(p); -} - + return (p && p->isBigopInset()) ? static_cast(p) : 0; } @@ -463,36 +411,30 @@ MathInset * mathed_parse() switch (t) { case LM_TK_NEWCOMMAND: { - LexGetArg('{'); - string name = yytext.substr(1); - - int na = 0; - unsigned char const c = yyis->peek(); - if (c == '[') { - LexGetArg('['); - na = atoi(yytext.c_str()); - } - - p = new MathMacroTemplate(name, na); + 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 << " na: " << na << "\n"; + //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"; + //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(p->cell(0), 0); - MathMatrixInset * m = static_cast(p); + mathed_parse(m->cell(0), 0); m->numbered(0, curr_num); m->label(0, curr_label); break; @@ -501,24 +443,26 @@ MathInset * mathed_parse() case LM_OT_EQUATION: { curr_num = latex_mathenv[i].numbered; curr_label = string(); - mathed_parse(p->cell(0), FLAG_END); - MathMatrixInset * m = static_cast(p); + 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(p, 3, latex_mathenv[i].numbered, true); + 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: { - LexGetArg('{'); - //int c = atoi(yytext.c_str()); - lyxerr[Debug::MATHED] << "LM_OT_ALIGNAT: not implemented\n"; - mathed_parse_lines(p, 2, latex_mathenv[i].numbered, true); - lyxerr[Debug::MATHED] << "LM_OT_ALIGNAT: par: " << *p << "\n"; + m->halign(lexArg('{')); + mathed_parse_lines(m, 2, latex_mathenv[i].numbered, true); break; } @@ -539,37 +483,56 @@ MathInset * mathed_parse() } +void handle_frac(MathArray & array, string const & name) +{ + MathFracInset * p = new MathFracInset(name); + mathed_parse(p->cell(0), FLAG_ITEM); + mathed_parse(p->cell(1), FLAG_ITEM); + array.push_back(p); +} + + void mathed_parse(MathArray & array, unsigned flags) { - int t = yylex(); - int tprev = 0; + int t = yylex(); bool panic = false; static int plevel = -1; yyvarcode = LM_TC_VAR; int brace = 0; - int acc_brace = 0; - int acc_braces[8]; ++plevel; while (t) { - //lyxerr << "t: " << t << " flags: " << flags; + //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 != '[') { - mathPrintError( - "Expected {. Maybe you forgot to enclose an argument in {}"); - panic = true; - break; + 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 { + // 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: - do_insert(array, yylval.i, yyvarcode); + array.push_back(yylval.i, yyvarcode); break; case LM_TK_ARGUMENT: @@ -581,20 +544,11 @@ void mathed_parse(MathArray & array, unsigned flags) break; case LM_TK_STR: - do_insert(array, 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 @@ -608,66 +562,39 @@ void mathed_parse(MathArray & array, unsigned flags) panic = true; break; } - if (acc_brace && brace == acc_braces[acc_brace - 1] - 1) { - --acc_brace; - break; - } if (flags & FLAG_BRACE_FONT) { yyvarcode = LM_TC_VAR; flags &= ~FLAG_BRACE_FONT; break; } - if (brace == 0 && (flags & FLAG_BRACE_LAST)) { - --plevel; - return; - } - array.push_back('}', 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; - unsigned char const rg = LexGetArg('['); - if (rg != ']') { - mathPrintError("Expected ']'"); - panic = true; - break; - } - } else - array.push_back('[', LM_TC_CONST); + array.push_back('[', LM_TC_CONST); break; case ']': - if (flags & FLAG_BRACK_END) { - --plevel; - return; - } - array.push_back(']', LM_TC_CONST); + if (flags & FLAG_BRACK_END) + flags |= FLAG_LEAVE; + else + array.push_back(']', LM_TC_CONST); break; case '^': - { - MathArray ar; - mathed_parse(ar, FLAG_BRACE_OPT | FLAG_BRACE_LAST); - MathScriptInset * p = lastScriptInset(array); - p->setData(ar, 0); - p->up(true); + mathed_parse(lastUpDownInset(array, true, false)->cell(0), FLAG_ITEM); break; - } case '_': - { - MathArray ar; - mathed_parse(ar, FLAG_BRACE_OPT | FLAG_BRACE_LAST); - MathScriptInset * p = lastScriptInset(array); - p->setData(ar, 1); - p->down(true); + mathed_parse(lastUpDownInset(array, false, true)->cell(1), FLAG_ITEM); break; - } case LM_TK_LIMIT: { - MathScriptInset * p = lastScriptInset(array); + MathBigopInset * p = lastBigopInset(array); if (p) p->limits(yylval.l->id ? 1 : -1); break; @@ -703,14 +630,14 @@ void mathed_parse(MathArray & array, unsigned flags) case LM_TK_SYM: if (yylval.l->id < 256) { - MathTextCodes tc = MathIsBOPS(yylval.l->id) ? LM_TC_BOPS: LM_TC_SYMB; - do_insert(array, yylval.l->id, tc); + MathTextCodes tc = MathIsBOPS(yylval.l->id) ? LM_TC_BOPS : LM_TC_SYMB; + array.push_back(yylval.l->id, tc); } else - do_insert(array, new MathFuncInset(yylval.l->name)); + array.push_back(new MathFuncInset(yylval.l->name)); break; case LM_TK_BOP: - do_insert(array, yylval.i, LM_TC_BOP); + array.push_back(yylval.i, LM_TC_BOP); break; case LM_TK_SPACE: @@ -735,18 +662,16 @@ void mathed_parse(MathArray & array, unsigned flags) break; case LM_TK_SQRT: - { + { unsigned char c = getuchar(yyis); if (c == '[') { - MathRootInset * rt = new MathRootInset; - mathed_parse(rt->cell(0), FLAG_BRACK_END); - mathed_parse(rt->cell(1), FLAG_BRACE | FLAG_BRACE_LAST); - array.push_back(rt); + 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 * sq = new MathSqrtInset; - mathed_parse(sq->cell(0), FLAG_BRACE | FLAG_BRACE_LAST); - array.push_back(sq); + array.push_back(new MathSqrtInset); + mathed_parse(array.back_inset()->cell(0), FLAG_ITEM); } break; } @@ -769,7 +694,7 @@ void mathed_parse(MathArray & array, unsigned flags) rd = yylval.i; MathDelimInset * dl = new MathDelimInset(ld, rd); - dl->setData(ar, 0); + dl->cell(0) = ar; array.push_back(dl); break; } @@ -799,17 +724,14 @@ void mathed_parse(MathArray & array, unsigned flags) } - case LM_TK_WIDE: + case LM_TK_DECORATION: { - MathDecorationInset * sq = new MathDecorationInset(yylval.l->id); - mathed_parse(sq->cell(0), FLAG_BRACE | FLAG_BRACE_LAST); - array.push_back(sq); + 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: curr_num = false; @@ -817,10 +739,7 @@ void mathed_parse(MathArray & array, unsigned flags) case LM_TK_PMOD: case LM_TK_FUNC: - if (accent) - array.push_back(t, LM_TC_CONST); - else - array.push_back(new MathFuncInset(yylval.l->name)); + array.push_back(new MathFuncInset(yylval.l->name)); break; case LM_TK_FUNCLIM: @@ -831,11 +750,11 @@ void mathed_parse(MathArray & array, unsigned flags) if (MathMacroTable::hasTemplate(yytext)) { MathMacro * m = MathMacroTable::cloneTemplate(yytext); for (int i = 0; i < m->nargs(); ++i) - mathed_parse(m->cell(i), FLAG_BRACE_OPT | FLAG_BRACE_LAST); - do_insert(array, m); + mathed_parse(m->cell(i), FLAG_ITEM); + array.push_back(m); m->Metrics(LM_ST_TEXT); } else - do_insert(array, new MathFuncInset(yytext, LM_OT_UNDEF)); + array.push_back(new MathFuncInset(yytext, LM_OT_UNDEF)); break; case LM_TK_END: @@ -848,22 +767,17 @@ void mathed_parse(MathArray & array, unsigned flags) MathInsetTypes typ = latex_mathenv[i].typ; if (typ == LM_OT_MATRIX) { - string valign = "\0"; - unsigned char rg = LexGetArg(0); - if (rg == ']') { - valign = yytext; - rg = LexGetArg('{'); - } - - string halign = yytext; - MathArrayInset * mm = new MathArrayInset(halign.size(), 1); - valign += 'c'; - mm->valign(valign[0]); - mm->halign(halign); - - mathed_parse_lines(mm, halign.size(), latex_mathenv[i].numbered, false); - do_insert(array, mm); - //lyxerr << "read matrix " << *mm << "\n"; + 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"; @@ -871,23 +785,12 @@ void mathed_parse(MathArray & array, unsigned flags) } case LM_TK_MACRO: - do_insert(array, MathMacroTable::cloneTemplate(yylval.l->name)); + array.push_back(MathMacroTable::cloneTemplate(yylval.l->name)); break; case LM_TK_LABEL: - { - unsigned char const rg = LexGetArg('\0', true); - if (rg != '}') { - mathPrintError("Expected '{'"); - // debug info - lyxerr[Debug::MATHED] << "[" << yytext << "]" << endl; - panic = true; - break; - } - //lyxerr << " setting label to " << yytext << "\n"; - curr_label = yytext; + curr_label = lexArg('{', true); break; - } default: mathPrintError("Unrecognized token"); @@ -895,8 +798,12 @@ void mathed_parse(MathArray & array, unsigned flags) break; } // end of big switch - - tprev = t; + + if (flags & FLAG_LEAVE) { + flags &= ~FLAG_LEAVE; + break; + } + if (panic) { lyxerr << " Math Panic, expect problems!" << endl; // Search for the end command. @@ -905,15 +812,13 @@ void mathed_parse(MathArray & array, unsigned flags) } while (t != LM_TK_END && t); } else t = yylex(); - - if (flags & FLAG_BRACE_OPT) { - flags &= ~FLAG_BRACE_OPT; - break; - } + } --plevel; } +} + MathInset * mathed_parse(istream & is) { @@ -945,4 +850,4 @@ MathInset * mathed_parse(LyXLex & lex) return p; } - +//]})