X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2Fmath_parser.C;h=ea289cc82c7a59b4666d47952409c6dd73219218;hb=cd3d0bc0b26f4d92fdfbfaac4adefebcf51f11ff;hp=c26e6b6d8c36859fcb507ba65c1e25843cb00928;hpb=4dd411c61197f15b315fd9a34211b578959bca19;p=lyx.git diff --git a/src/mathed/math_parser.C b/src/mathed/math_parser.C index c26e6b6d8c..ea289cc82c 100644 --- a/src/mathed/math_parser.C +++ b/src/mathed/math_parser.C @@ -22,9 +22,9 @@ following hack as starting point to write some macros: ... \[\begin{array}{ccc} - 1 & 2\b & 3^2\\ - 4 & 5\e & 6\\ - 7 & 8 & 9 +1 +& + \end{array}\] */ @@ -32,9 +32,6 @@ following hack as starting point to write some macros: #include -#ifdef __GNUG__ -#pragma implementation -#endif #include "math_parser.h" #include "math_inset.h" @@ -42,22 +39,24 @@ following hack as starting point to write some macros: #include "math_braceinset.h" #include "math_boxinset.h" #include "math_charinset.h" +#include "math_commentinset.h" #include "math_deliminset.h" +#include "math_envinset.h" #include "math_extern.h" #include "math_factory.h" #include "math_kerninset.h" #include "math_macro.h" -#include "math_macrotable.h" #include "math_macrotemplate.h" #include "math_hullinset.h" #include "math_parboxinset.h" #include "math_parinset.h" #include "math_rootinset.h" -#include "math_sizeinset.h" -#include "math_sqrtinset.h" #include "math_scriptinset.h" +#include "math_sizeinset.h" #include "math_sqrtinset.h" +#include "math_stringinset.h" #include "math_support.h" +#include "math_tabularinset.h" #include "math_xyarrowinset.h" //#include "insets/insetref.h" @@ -69,14 +68,12 @@ following hack as starting point to write some macros: #include "support/lstrings.h" #include -#include #include using std::istream; using std::ostream; using std::ios; using std::endl; -using std::stack; using std::fill; using std::vector; using std::atoi; @@ -87,6 +84,16 @@ using std::atoi; namespace { +MathInset::mode_type asMode(MathInset::mode_type oldmode, string const & str) +{ + if (str == "mathmode") + return MathInset::MATH_MODE; + if (str == "textmode" || str == "forcetext") + return MathInset::TEXT_MODE; + return oldmode; +} + + bool stared(string const & s) { string::size_type const n = s.size(); @@ -134,7 +141,8 @@ enum { FLAG_SIMPLE = 1 << 8, // next $ leaves the loop FLAG_EQUATION = 1 << 9, // next \] leaves the loop FLAG_SIMPLE2 = 1 << 10, // next \) leaves the loop - FLAG_OPTION = 1 << 11 // read [...] style option + FLAG_OPTION = 1 << 11, // read [...] style option + FLAG_BRACED = 1 << 12 // read {...} style argument }; @@ -156,7 +164,7 @@ void catInit() theCatcode[''] = catIgnore; theCatcode[' '] = catSpace; theCatcode['\t'] = catSpace; - theCatcode['\r'] = catSpace; + theCatcode['\r'] = catNewline; theCatcode['~'] = catActive; theCatcode['%'] = catComment; } @@ -183,9 +191,7 @@ public: /// char character() const { return char_; } /// - string asString() const; - /// - bool isCR() const; + string asString() const { return cs_.size() ? cs_ : string(1, char_); } private: /// @@ -196,22 +202,12 @@ private: CatCode cat_; }; -bool Token::isCR() const -{ - return cs_ == "\\" || cs_ == "cr" || cs_ == "crcr"; -} - -string Token::asString() const -{ - return cs_.size() ? cs_ : string(1, char_); -} - ostream & operator<<(ostream & os, Token const & t) { if (t.cs().size()) - os << "\\" << t.cs(); + os << '\\' << t.cs(); else - os << "[" << t.character() << "," << t.cat() << "]"; + os << '[' << t.character() << ',' << t.cat() << ']'; return os; } @@ -219,17 +215,23 @@ ostream & operator<<(ostream & os, Token const & t) class Parser { public: + /// + typedef MathInset::mode_type mode_type; + /// Parser(LyXLex & lex); /// Parser(istream & is); /// - bool parse_macro(string & name); + bool parse(MathAtom & at); /// - bool parse_normal(MathAtom & at); + void parse(MathArray & array, unsigned flags, mode_type mode); /// - void parse_into(MathArray & array, unsigned flags, bool mathmode); + void parse1(MathGridInset & grid, unsigned flags, mode_type mode, + bool numbered); + /// + MathArray parse(unsigned flags, mode_type mode); /// int lineno() const { return lineno_; } /// @@ -237,9 +239,7 @@ public: private: /// - void parse_into1(MathGridInset & grid, unsigned flags, bool mathmode, bool numbered); - /// - void parse_into2(MathAtom & at, unsigned flags, bool mathmode, bool numbered); + void parse2(MathAtom & at, unsigned flags, mode_type mode, bool numbered); /// get arg delimited by 'left' and 'right' string getArg(char left, char right); /// @@ -248,8 +248,6 @@ private: void error(string const & msg); /// dump contents to screen void dump() const; - -private: /// void tokenize(istream & is); /// @@ -272,6 +270,10 @@ private: void lex(string const & s); /// bool good() const; + /// + string parse_verbatim_item(); + /// + string parse_verbatim_option(); /// int lineno_; @@ -333,7 +335,7 @@ Token const & Parser::getToken() void Parser::skipSpaces() { - while (nextToken().cat() == catSpace) + while (nextToken().cat() == catSpace || nextToken().cat() == catNewline) getToken(); } @@ -375,6 +377,17 @@ string Parser::getArg(char left, char right) } +void Parser::skipSpaceTokens(istream & is, char c) +{ + // skip trailing spaces + while (catcode(c) == catSpace || catcode(c) == catNewline) + if (!is.get(c)) + break; + //lyxerr << "putting back: " << c << "\n"; + is.putback(c); +} + + void Parser::tokenize(istream & is) { // eat everything up to the next \end_inset or end of stream @@ -388,23 +401,15 @@ void Parser::tokenize(istream & is) break; } } + // Remove the space after \end_inset + if (is.get(c) && c != ' ') + is.unget(); // tokenize buffer tokenize(s); } -void Parser::skipSpaceTokens(istream & is, char c) -{ - // skip trailing spaces - while (catcode(c) == catSpace || catcode(c) == catNewline) - if (!is.get(c)) - break; - //lyxerr << "putting back: " << c << "\n"; - is.putback(c); -} - - void Parser::tokenize(string const & buffer) { static bool init_done = false; @@ -427,18 +432,20 @@ void Parser::tokenize(string const & buffer) if (catcode(c) == catNewline) ; //push_back(Token("par")); else { - push_back(Token(' ', catSpace)); + push_back(Token('\n', catNewline)); is.putback(c); } break; } +/* case catComment: { while (is.get(c) && catcode(c) != catNewline) ; ++lineno_; break; } +*/ case catEscape: { is.get(c); @@ -501,121 +508,89 @@ void Parser::error(string const & msg) } -bool Parser::parse_macro(string & name) +bool Parser::parse(MathAtom & at) { - int nargs = 0; - name = "{error}"; skipSpaces(); - - if (nextToken().cs() == "def") { - - getToken(); - name = getToken().cs(); - - string pars; - while (good() && nextToken().cat() != catBegin) - pars += getToken().cs(); - - if (!good()) { - error("bad stream in parse_macro\n"); - return false; - } - - //lyxerr << "read \\def parameter list '" << pars << "'\n"; - if (!pars.empty()) { - error("can't handle non-empty parameter lists\n"); - return false; - } - - } else if (nextToken().cs() == "newcommand") { - - getToken(); - - if (getToken().cat() != catBegin) { - error("'{' in \\newcommand expected (1) \n"); - return false; - } - - name = getToken().cs(); - - if (getToken().cat() != catEnd) { - error("'}' expected\n"); - return false; - } - - string arg = getArg('[', ']'); - if (!arg.empty()) - nargs = atoi(arg.c_str()); - - } else { - lyxerr << "\\newcommand or \\def expected\n"; - return false; + MathArray ar; + parse(ar, false, MathInset::UNDECIDED_MODE); + if (ar.size() != 1 || ar.front()->getType() == "none") { + lyxerr << "unusual contents found: " << ar << endl; + at = MathAtom(new MathParInset(ar)); + //if (at->nargs() > 0) + // at.nucleus()->cell(0) = ar; + //else + // lyxerr << "unusual contents found: " << ar << endl; + return true; } + at = ar[0]; + return true; +} - if (getToken().cat() != catBegin) { - error("'{' in macro definition expected (2)\n"); - return false; +string Parser::parse_verbatim_option() +{ + skipSpaces(); + string res; + if (nextToken().character() == '[') { + Token t = getToken(); + for (Token t = getToken(); t.character() != ']' && good(); t = getToken()) { + if (t.cat() == catBegin) { + putback(); + res += '{' + parse_verbatim_item() + '}'; + } else + res += t.asString(); + } } + return res; +} - MathArray ar1; - parse_into(ar1, FLAG_BRACE_LAST, true); - // we cannot handle recursive stuff at all - MathArray test; - test.push_back(createMathInset(name)); - if (ar1.contains(test)) { - error("we cannot handle recursive macros at all.\n"); - return false; +string Parser::parse_verbatim_item() +{ + skipSpaces(); + string res; + if (nextToken().cat() == catBegin) { + Token t = getToken(); + for (Token t = getToken(); t.cat() != catEnd && good(); t = getToken()) { + if (t.cat() == catBegin) { + putback(); + res += '{' + parse_verbatim_item() + '}'; + } + else + res += t.asString(); + } } - - // is a version for display attached? - MathArray ar2; - parse_into(ar2, FLAG_ITEM, true); - - MathMacroTable::create(name, nargs, ar1, ar2); - return true; + return res; } -bool Parser::parse_normal(MathAtom & at) +MathArray Parser::parse(unsigned flags, mode_type mode) { - skipSpaces(); MathArray ar; - parse_into(ar, false, false); - if (ar.size() != 1 || ar.front()->getType() == "none") { - lyxerr << "unusual contents found: " << ar << endl; - at.reset(new MathParInset); - if (at->nargs() > 0) - at->cell(0) = ar; - else - lyxerr << "unusual contents found: " << ar << endl; - return true; - } - at = ar[0]; - return true; + parse(ar, flags, mode); + return ar; } -void Parser::parse_into(MathArray & array, unsigned flags, bool mathmode) +void Parser::parse(MathArray & array, unsigned flags, mode_type mode) { MathGridInset grid(1, 1); - parse_into1(grid, flags, mathmode, false); + parse1(grid, flags, mode, false); array = grid.cell(0); } -void Parser::parse_into2(MathAtom & at, unsigned flags, - bool mathmode, bool numbered) +void Parser::parse2(MathAtom & at, const unsigned flags, const mode_type mode, + const bool numbered) { - parse_into1(*(at->asGridInset()), flags, mathmode, numbered); + parse1(*(at.nucleus()->asGridInset()), flags, mode, numbered); } -void Parser::parse_into1(MathGridInset & grid, unsigned flags, - bool mathmode, bool numbered) +void Parser::parse1(MathGridInset & grid, unsigned flags, + const mode_type mode, const bool numbered) { - int limits = 0; + int limits = 0; MathGridInset::row_type cellrow = 0; MathGridInset::col_type cellcol = 0; MathArray * cell = &grid.cell(grid.index(cellrow, cellcol)); @@ -631,13 +606,12 @@ void Parser::parse_into1(MathGridInset & grid, unsigned flags, #ifdef FILEDEBUG lyxerr << "t: " << t << " flags: " << flags << "\n"; - //cell->dump(); + cell->dump(); lyxerr << "\n"; #endif if (flags & FLAG_ITEM) { - if (t.cat() == catSpace) - continue; + skipSpaces(); flags &= ~FLAG_ITEM; if (t.cat() == catBegin) { @@ -652,15 +626,30 @@ void Parser::parse_into1(MathGridInset & grid, unsigned flags, } - if (flags & FLAG_OPTION) { - if (t.cat() == catOther && t.character() == '[') { - // skip the bracket and collect everything to the clsing bracket - flags |= FLAG_BRACK_LAST; + if (flags & FLAG_BRACED) { + if (t.cat() == catSpace) continue; + + if (t.cat() != catBegin) { + error("opening brace expected"); + return; } - // no option found, put back token and we are done - putback(); + // skip the brace and collect everything to the next matching + // closing brace + flags = FLAG_BRACE_LAST; + } + + + if (flags & FLAG_OPTION) { + if (t.cat() == catOther && t.character() == '[') { + MathArray ar; + parse(ar, FLAG_BRACK_LAST, mode); + cell->append(ar); + } else { + // no option found, put back token and we are done + putback(); + } return; } @@ -668,19 +657,19 @@ void Parser::parse_into1(MathGridInset & grid, unsigned flags, // cat codes // if (t.cat() == catMath) { - if (!mathmode) { + if (mode != MathInset::MATH_MODE) { // we are inside some text mode thingy, so opening new math is allowed Token const & n = getToken(); if (n.cat() == catMath) { // TeX's $$...$$ syntax for displayed math cell->push_back(MathAtom(new MathHullInset("equation"))); - parse_into2(cell->back(), FLAG_SIMPLE, true, false); + parse2(cell->back(), FLAG_SIMPLE, MathInset::MATH_MODE, false); getToken(); // skip the second '$' token } else { // simple $...$ stuff putback(); cell->push_back(MathAtom(new MathHullInset("simple"))); - parse_into2(cell->back(), FLAG_SIMPLE, true, false); + parse2(cell->back(), FLAG_SIMPLE, MathInset::MATH_MODE, false); } } @@ -698,7 +687,12 @@ void Parser::parse_into1(MathGridInset & grid, unsigned flags, else if (t.cat() == catLetter) cell->push_back(MathAtom(new MathCharInset(t.character()))); - else if (t.cat() == catSpace && !mathmode) + else if (t.cat() == catSpace && mode != MathInset::MATH_MODE) { + if (cell->empty() || cell->back()->getChar() != ' ') + cell->push_back(MathAtom(new MathCharInset(t.character()))); + } + + else if (t.cat() == catNewline && mode != MathInset::MATH_MODE) cell->push_back(MathAtom(new MathCharInset(t.character()))); else if (t.cat() == catParameter) { @@ -706,15 +700,18 @@ void Parser::parse_into1(MathGridInset & grid, unsigned flags, cell->push_back(MathAtom(new MathMacroArgument(n.character()-'0'))); } + else if (t.cat() == catActive) + cell->push_back(MathAtom(new MathCharInset(t.character()))); + else if (t.cat() == catBegin) { MathArray ar; - parse_into(ar, FLAG_BRACE_LAST, mathmode); - // reduce multiple nesting levels to a single one + parse(ar, FLAG_BRACE_LAST, mode); + // do not create a BraceInset if they were written by LyX // this helps to keep the annoyance of "a choose b" to a minimum - if (ar.size() && ar.front()->asBraceInset()) - ar = ar.front()->asBraceInset()->cell(0); - cell->push_back(MathAtom(new MathBraceInset)); - cell->back()->cell(0).swap(ar); + if (ar.size() == 1 && ar[0]->extraBraces()) + cell->append(ar); + else + cell->push_back(MathAtom(new MathBraceInset(ar))); } else if (t.cat() == catEnd) { @@ -729,7 +726,7 @@ void Parser::parse_into1(MathGridInset & grid, unsigned flags, ++cellcol; //lyxerr << " column now " << cellcol << " max: " << grid.ncols() << "\n"; if (cellcol == grid.ncols()) { - lyxerr << "adding column " << cellcol << "\n"; + //lyxerr << "adding column " << cellcol << "\n"; grid.addCol(cellcol - 1); } cell = &grid.cell(grid.index(cellrow, cellcol)); @@ -737,36 +734,125 @@ void Parser::parse_into1(MathGridInset & grid, unsigned flags, else if (t.cat() == catSuper || t.cat() == catSub) { bool up = (t.cat() == catSuper); - MathScriptInset * p = 0; - if (cell->size()) - p = cell->back()->asScriptInset(); - if (!p || p->has(up)) { + // we need no new script inset if the last thing was a scriptinset, + // which has that script already not the same script already + if (!cell->size()) cell->push_back(MathAtom(new MathScriptInset(up))); - p = cell->back()->asScriptInset(); + else if (cell->back()->asScriptInset() && + !cell->back()->asScriptInset()->has(up)) + cell->back().nucleus()->asScriptInset()->ensure(up); + else if (cell->back()->asScriptInset()) + cell->push_back(MathAtom(new MathScriptInset(up))); + else + cell->back() = MathAtom(new MathScriptInset(cell->back(), up)); + MathScriptInset * p = cell->back().nucleus()->asScriptInset(); + // special handling of {}-bases + // is this always correct? + // It appears that this is wrong (Dekel) + //if (p->nuc().size() == 1 && p->nuc().back()->asNestInset() && + // p->nuc().back()->extraBraces()) + // p->nuc() = p->nuc().back()->asNestInset()->cell(0); + parse(p->cell(up), FLAG_ITEM, mode); + if (limits) { + p->limits(limits); + limits = 0; } - p->ensure(up); - parse_into(p->cell(up), FLAG_ITEM, mathmode); - p->limits(limits); - limits = 0; } - else if (t.character() == ']' && (flags & FLAG_BRACK_LAST)) + else if (t.character() == ']' && (flags & FLAG_BRACK_LAST)) { + //lyxerr << "finished reading option\n"; return; + } else if (t.cat() == catOther) cell->push_back(MathAtom(new MathCharInset(t.character()))); + else if (t.cat() == catComment) { + string s; + while (good()) { + Token const & t = getToken(); + if (t.cat() == catNewline) + break; + s += t.asString(); + } + cell->push_back(MathAtom(new MathCommentInset(s))); + skipSpaces(); + } + // // control sequences // + + else if (t.cs() == "lyxlock") { + if (cell->size()) + cell->back().nucleus()->lock(true); + } + + else if (t.cs() == "def" || t.cs() == "newcommand") { + string name; + int nargs = 0; + if (t.cs() == "def") { + // get name + name = getToken().cs(); + + // read parameter + string pars; + while (good() && nextToken().cat() != catBegin) { + pars += getToken().cs(); + ++nargs; + } + nargs /= 2; + //lyxerr << "read \\def parameter list '" << pars << "'\n"; + + } else { // t.cs() == "newcommand" + + if (getToken().cat() != catBegin) { + error("'{' in \\newcommand expected (1) \n"); + return; + } + + name = getToken().cs(); + + if (getToken().cat() != catEnd) { + error("'}' in \\newcommand expected\n"); + return; + } + + string arg = getArg('[', ']'); + if (!arg.empty()) + nargs = atoi(arg.c_str()); + + } + + MathArray ar1; + parse(ar1, FLAG_ITEM, MathInset::UNDECIDED_MODE); + + // we cannot handle recursive stuff at all + //MathArray test; + //test.push_back(createMathInset(name)); + //if (ar1.contains(test)) { + // error("we cannot handle recursive macros at all.\n"); + // return; + //} + + // is a version for display attached? + skipSpaces(); + MathArray ar2; + if (nextToken().cat() == catBegin) { + parse(ar2, FLAG_ITEM, MathInset::MATH_MODE); + } + + cell->push_back(MathAtom(new MathMacroTemplate(name, nargs, ar1, ar2))); + } + else if (t.cs() == "(") { cell->push_back(MathAtom(new MathHullInset("simple"))); - parse_into2(cell->back(), FLAG_SIMPLE2, true, false); + parse2(cell->back(), FLAG_SIMPLE2, MathInset::MATH_MODE, false); } else if (t.cs() == "[") { cell->push_back(MathAtom(new MathHullInset("equation"))); - parse_into2(cell->back(), FLAG_EQUATION, true, false); + parse2(cell->back(), FLAG_EQUATION, MathInset::MATH_MODE, false); } else if (t.cs() == "protect") @@ -807,11 +893,11 @@ void Parser::parse_into1(MathGridInset & grid, unsigned flags, cell = &grid.cell(grid.index(cellrow, cellcol)); } -#if 1 +#if 0 else if (t.cs() == "multicolumn") { // extract column count and insert dummy cells MathArray count; - parse_into(count, FLAG_ITEM, mathmode); + parse(count, FLAG_ITEM, mode); int cols = 1; if (!extractNumber(count, cols)) { lyxerr << " can't extract number of cells from " << count << "\n"; @@ -820,7 +906,7 @@ void Parser::parse_into1(MathGridInset & grid, unsigned flags, for (int i = 0; i < cols; ++i) { ++cellcol; if (cellcol == grid.ncols()) { - lyxerr << "adding column " << cellcol << "\n"; + //lyxerr << "adding column " << cellcol << "\n"; grid.addCol(cellcol - 1); } cell = &grid.cell(grid.index(cellrow, cellcol)); @@ -832,11 +918,11 @@ void Parser::parse_into1(MathGridInset & grid, unsigned flags, // read special alignment MathArray align; - parse_into(align, FLAG_ITEM, mathmode); + parse(align, FLAG_ITEM, mode); //grid.cellinfo(grid.index(cellrow, cellcol)).align_ = extractString(align); // parse the remaining contents into the "real" cell - parse_into(*cell, FLAG_ITEM, mathmode); + parse(*cell, FLAG_ITEM, mode); } #endif @@ -857,33 +943,41 @@ void Parser::parse_into1(MathGridInset & grid, unsigned flags, } else if (t.cs() == "hline") { - if (grid.asHullInset()) - grid.asHullInset()->rowinfo(cellrow + 1); + grid.rowinfo(cellrow).lines_ ++; } else if (t.cs() == "sqrt") { MathArray ar; - parse_into(ar, FLAG_OPTION, mathmode); + parse(ar, FLAG_OPTION, mode); if (ar.size()) { cell->push_back(MathAtom(new MathRootInset)); - cell->back()->cell(0) = ar; - parse_into(cell->back()->cell(1), FLAG_ITEM, mathmode); + cell->back().nucleus()->cell(0) = ar; + parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode); } else { cell->push_back(MathAtom(new MathSqrtInset)); - parse_into(cell->back()->cell(0), FLAG_ITEM, mathmode); + parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode); } } - else if (t.cs() == "ref") { - cell->push_back(MathAtom(new RefInset)); - parse_into(cell->back()->cell(1), FLAG_OPTION, mathmode); - parse_into(cell->back()->cell(0), FLAG_ITEM, mathmode); + else if (t.cs() == "xrightarrow" || t.cs() == "xleftarrow") { + cell->push_back(createMathInset(t.cs())); + parse(cell->back().nucleus()->cell(1), FLAG_OPTION, mode); + parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode); + } + + else if (t.cs() == "ref" || t.cs() == "prettyref" || + t.cs() == "pageref" || t.cs() == "vpageref" || t.cs() == "vref") { + cell->push_back(MathAtom(new RefInset(t.cs()))); + parse(cell->back().nucleus()->cell(1), FLAG_OPTION, mode); + parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode); } else if (t.cs() == "left") { + skipSpaces(); string l = getToken().asString(); MathArray ar; - parse_into(ar, FLAG_RIGHT, mathmode); + parse(ar, FLAG_RIGHT, mode); + skipSpaces(); string r = getToken().asString(); cell->push_back(MathAtom(new MathDelimInset(l, r, ar))); } @@ -898,82 +992,97 @@ void Parser::parse_into1(MathGridInset & grid, unsigned flags, else if (t.cs() == "begin") { string const name = getArg('{', '}'); + if (name == "array" || name == "subarray") { - string const valign = getArg('[', ']') + 'c'; - string const halign = getArg('{', '}'); + string const valign = parse_verbatim_option() + 'c'; + string const halign = parse_verbatim_item(); cell->push_back(MathAtom(new MathArrayInset(name, valign[0], halign))); - parse_into2(cell->back(), FLAG_END, mathmode, false); + parse2(cell->back(), FLAG_END, mode, false); + } + + else if (name == "tabular") { + string const valign = parse_verbatim_option() + 'c'; + string const halign = parse_verbatim_item(); + cell->push_back(MathAtom(new MathTabularInset(name, valign[0], halign))); + parse2(cell->back(), FLAG_END, MathInset::TEXT_MODE, false); } else if (name == "split" || name == "cases" || name == "gathered" || name == "aligned") { cell->push_back(createMathInset(name)); - parse_into2(cell->back(), FLAG_END, mathmode, false); + parse2(cell->back(), FLAG_END, mode, false); } else if (name == "math") { cell->push_back(MathAtom(new MathHullInset("simple"))); - parse_into2(cell->back(), FLAG_SIMPLE, true, true); + parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, true); } else if (name == "equation" || name == "equation*" || name == "displaymath") { cell->push_back(MathAtom(new MathHullInset("equation"))); - parse_into2(cell->back(), FLAG_END, true, (name == "equation")); + parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, (name == "equation")); } else if (name == "eqnarray" || name == "eqnarray*") { cell->push_back(MathAtom(new MathHullInset("eqnarray"))); - parse_into2(cell->back(), FLAG_END, true, !stared(name)); + parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name)); } else if (name == "align" || name == "align*") { cell->push_back(MathAtom(new MathHullInset("align"))); - parse_into2(cell->back(), FLAG_END, true, !stared(name)); + parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name)); + } + + else if (name == "flalign" || name == "flalign*") { + cell->push_back(MathAtom(new MathHullInset("flalign"))); + parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name)); } else if (name == "alignat" || name == "alignat*") { // ignore this for a while getArg('{', '}'); cell->push_back(MathAtom(new MathHullInset("alignat"))); - parse_into2(cell->back(), FLAG_END, true, !stared(name)); + parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name)); } else if (name == "xalignat" || name == "xalignat*") { // ignore this for a while getArg('{', '}'); cell->push_back(MathAtom(new MathHullInset("xalignat"))); - parse_into2(cell->back(), FLAG_END, true, !stared(name)); + parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name)); } else if (name == "xxalignat") { // ignore this for a while getArg('{', '}'); cell->push_back(MathAtom(new MathHullInset("xxalignat"))); - parse_into2(cell->back(), FLAG_END, true, !stared(name)); + parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name)); } else if (name == "multline" || name == "multline*") { cell->push_back(MathAtom(new MathHullInset("multline"))); - parse_into2(cell->back(), FLAG_END, true, !stared(name)); + parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name)); } else if (name == "gather" || name == "gather*") { cell->push_back(MathAtom(new MathHullInset("gather"))); - parse_into2(cell->back(), FLAG_END, true, !stared(name)); + parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name)); } - else { - latexkeys const * l = in_word_set(name); - if (l) { - if (l->inset == "matrix") { - cell->push_back(createMathInset(name)); - parse_into2(cell->back(), FLAG_END, mathmode, false); - } - } else { - lyxerr << "unknow math inset begin '" << name << "'\n"; + else if (latexkeys const * l = in_word_set(name)) { + if (l->inset == "matrix") { + cell->push_back(createMathInset(name)); + parse2(cell->back(), FLAG_END, mode, false); } } + + else { + //lyxerr << "unknow math inset begin '" << name << "'\n"; + // create generic environment inset + cell->push_back(MathAtom(new MathEnvInset(name))); + parse2(cell->back(), FLAG_END, mode, false); + } } else if (t.cs() == "kern") { @@ -981,7 +1090,7 @@ void Parser::parse_into1(MathGridInset & grid, unsigned flags, #warning A hack... #endif string s; - while (1) { + while (true) { Token const & t = getToken(); if (!good()) { putback(); @@ -995,39 +1104,59 @@ void Parser::parse_into1(MathGridInset & grid, unsigned flags, } else if (t.cs() == "label") { - if (grid.asHullInset()) - grid.asHullInset()->label(cellrow, getArg('{', '}')); + string label = parse_verbatim_item(); + if (grid.asHullInset()) { + grid.asHullInset()->label(cellrow, label); + } else { + cell->push_back(createMathInset(t.cs())); + cell->push_back(MathAtom(new MathBraceInset(asArray(label)))); + } } else if (t.cs() == "choose" || t.cs() == "over" || t.cs() == "atop") { - MathAtom p = createMathInset(t.cs()); - cell->swap(p->cell(0)); - parse_into(p->cell(1), flags, mathmode); - cell->push_back(p); + MathAtom at = createMathInset(t.cs()); + at.nucleus()->cell(0) = *cell; + cell->clear(); + parse(at.nucleus()->cell(1), flags, mode); + cell->push_back(at); return; } else if (t.cs() == "substack") { cell->push_back(createMathInset(t.cs())); - parse_into2(cell->back(), FLAG_ITEM, mathmode, false); + parse2(cell->back(), FLAG_ITEM, mode, false); } else if (t.cs() == "xymatrix") { cell->push_back(createMathInset(t.cs())); - parse_into2(cell->back(), FLAG_ITEM, mathmode, false); + parse2(cell->back(), FLAG_ITEM, mode, false); + } + + else if (t.cs() == "framebox") { + cell->push_back(createMathInset(t.cs())); + parse(cell->back().nucleus()->cell(0), FLAG_OPTION, MathInset::TEXT_MODE); + parse(cell->back().nucleus()->cell(1), FLAG_OPTION, MathInset::TEXT_MODE); + parse(cell->back().nucleus()->cell(2), FLAG_ITEM, MathInset::TEXT_MODE); } #if 0 + else if (t.cs() == "infer") { + MathArray ar; + parse(ar, FLAG_OPTION, mode); + cell->push_back(createMathInset(t.cs())); + parse2(cell->back(), FLAG_ITEM, mode, false); + } + // Disabled else if (1 && t.cs() == "ar") { MathXYArrowInset * p = new MathXYArrowInset; // try to read target - parse_into(p->cell(0), FLAG_OTPTION, mathmode); + parse(p->cell(0), FLAG_OTPTION, mode); // try to read label if (nextToken().cat() == catSuper || nextToken().cat() == catSub) { p->up_ = nextToken().cat() == catSuper; getToken(); - parse_into(p->cell(1), FLAG_ITEM, mathmode); + parse(p->cell(1), FLAG_ITEM, mode); //lyxerr << "read label: " << p->cell(1) << "\n"; } @@ -1040,56 +1169,56 @@ void Parser::parse_into1(MathGridInset & grid, unsigned flags, latexkeys const * l = in_word_set(t.cs()); if (l) { if (l->inset == "font") { - lyxerr << "starting font " << t.cs() << "\n"; - MathAtom p = createMathInset(t.cs()); - bool textmode = (t.cs()[0] == 't'); - parse_into(p->cell(0), FLAG_ITEM, !textmode); - cell->push_back(p); - //lyxerr << "ending font\n"; + cell->push_back(createMathInset(t.cs())); + parse(cell->back().nucleus()->cell(0), FLAG_ITEM, asMode(mode, l->extra)); } else if (l->inset == "oldfont") { cell->push_back(createMathInset(t.cs())); - parse_into(cell->back()->cell(0), flags, l->extra == "mathmode"); + parse(cell->back().nucleus()->cell(0), flags, asMode(mode, l->extra)); return; } - else if (l->inset == "mbox") { - // switch to text mode - cell->push_back(createMathInset(t.cs())); - parse_into(cell->back()->cell(0), FLAG_ITEM, mathmode); - } - else if (l->inset == "style") { cell->push_back(createMathInset(t.cs())); - parse_into(cell->back()->cell(0), flags, mathmode); + parse(cell->back().nucleus()->cell(0), flags, mode); return; } else if (l->inset == "parbox") { // read optional positioning and width - MathArray pos, width; - parse_into(pos, FLAG_OPTION, false); - parse_into(width, FLAG_ITEM, false); + string pos = parse_verbatim_option(); + string width = parse_verbatim_item(); cell->push_back(createMathInset(t.cs())); - parse_into(cell->back()->cell(0), FLAG_ITEM, false); - cell->back()->asParboxInset()->setPosition(asString(pos)); - cell->back()->asParboxInset()->setWidth(asString(width)); + parse(cell->back().nucleus()->cell(0), FLAG_ITEM, MathInset::TEXT_MODE); + cell->back().nucleus()->asParboxInset()->setPosition(pos); + cell->back().nucleus()->asParboxInset()->setWidth(width); } else { - MathAtom p = createMathInset(t.cs()); - for (MathInset::idx_type i = 0; i < p->nargs(); ++i) - parse_into(p->cell(i), FLAG_ITEM, l->extra == "mathmode"); - cell->push_back(p); + MathAtom at = createMathInset(t.cs()); + for (MathInset::idx_type i = 0; i < at->nargs(); ++i) + parse(at.nucleus()->cell(i), FLAG_ITEM, asMode(mode, l->extra)); + cell->push_back(at); } } else { - MathAtom p = createMathInset(t.cs()); - for (MathInset::idx_type i = 0; i < p->nargs(); ++i) - parse_into(p->cell(i), FLAG_ITEM, mathmode); - cell->push_back(p); + MathAtom at = createMathInset(t.cs()); + MathInset::mode_type m = mode; + if (m == MathInset::UNDECIDED_MODE) + m = at->currentMode(); + MathInset::idx_type start = 0; + // this fails on \bigg[...\bigg] + //MathArray opt; + //parse(opt, FLAG_OPTION, MathInset::VERBATIM_MODE); + //if (opt.size()) { + // start = 1; + // at.nucleus()->cell(0) = opt; + //} + for (MathInset::idx_type i = start; i < at->nargs(); ++i) + parse(at.nucleus()->cell(i), FLAG_ITEM, m); + cell->push_back(at); } } @@ -1115,45 +1244,31 @@ void mathed_parse_cell(MathArray & ar, string const & str) void mathed_parse_cell(MathArray & ar, istream & is) { - Parser(is).parse_into(ar, 0, true); + Parser(is).parse(ar, 0, MathInset::MATH_MODE); } - -bool mathed_parse_macro(string & name, string const & str) +bool mathed_parse_normal(MathAtom & t, string const & str) { istringstream is(str.c_str()); - return Parser(is).parse_macro(name); + return Parser(is).parse(t); } -bool mathed_parse_macro(string & name, istream & is) +bool mathed_parse_normal(MathAtom & t, istream & is) { - return Parser(is).parse_macro(name); + return Parser(is).parse(t); } -bool mathed_parse_macro(string & name, LyXLex & lex) +bool mathed_parse_normal(MathAtom & t, LyXLex & lex) { - return Parser(lex).parse_macro(name); + return Parser(lex).parse(t); } - -bool mathed_parse_normal(MathAtom & t, string const & str) +void mathed_parse_normal(MathGridInset & grid, string const & str) { istringstream is(str.c_str()); - return Parser(is).parse_normal(t); -} - - -bool mathed_parse_normal(MathAtom & t, istream & is) -{ - return Parser(is).parse_normal(t); -} - - -bool mathed_parse_normal(MathAtom & t, LyXLex & lex) -{ - return Parser(lex).parse_normal(t); + Parser(is).parse1(grid, 0, MathInset::MATH_MODE, false); }