X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2FMathParser.cpp;h=00f7e99004fb25bf9c469190d27112c16c17567c;hb=3ee1bcad041f29256df7132292de2592e8fc7ab6;hp=f19480b4b73e1f947110b6b37a1099230f572f1c;hpb=9c55af4a223ce4db29d643251109e245665344bd;p=features.git diff --git a/src/mathed/MathParser.cpp b/src/mathed/MathParser.cpp index f19480b4b7..00f7e99004 100644 --- a/src/mathed/MathParser.cpp +++ b/src/mathed/MathParser.cpp @@ -51,7 +51,7 @@ following hack as starting point to write some macros: #include "InsetMathEnv.h" #include "InsetMathFrac.h" #include "InsetMathKern.h" -#include "MathMacro.h" +#include "InsetMathMacro.h" #include "InsetMathPar.h" #include "InsetMathRef.h" #include "InsetMathRoot.h" @@ -63,9 +63,10 @@ following hack as starting point to write some macros: #include "InsetMathStackrel.h" #include "InsetMathString.h" #include "InsetMathTabular.h" -#include "MathMacroTemplate.h" +#include "InsetMathMacroTemplate.h" +#include "MathExtern.h" #include "MathFactory.h" -#include "MathMacroArgument.h" +#include "InsetMathMacroArgument.h" #include "MathSupport.h" #include "Buffer.h" @@ -73,9 +74,10 @@ following hack as starting point to write some macros: #include "Encoding.h" #include "Lexer.h" -#include "support/debug.h" #include "support/convert.h" +#include "support/debug.h" #include "support/docstream.h" +#include "support/unique_ptr.h" #include @@ -160,7 +162,7 @@ docstring escapeSpecialChars(docstring const & str, bool textmode) * environments like "equation" that have a fixed number of rows. */ bool addRow(InsetMathGrid & grid, InsetMathGrid::row_type & cellrow, - docstring const & vskip, bool allow_newpage_ = true) + docstring const & vskip, bool allow_newpage = true) { ++cellrow; if (cellrow == grid.nrows()) { @@ -177,14 +179,14 @@ bool addRow(InsetMathGrid & grid, InsetMathGrid::row_type & cellrow, lyxerr << "ignoring extra row"; if (!vskip.empty()) lyxerr << " with extra space " << to_utf8(vskip); - if (!allow_newpage_) + if (!allow_newpage) lyxerr << " with no page break allowed"; lyxerr << '.' << endl; return false; } } grid.vcrskip(Length(to_utf8(vskip)), cellrow - 1); - grid.rowinfo(cellrow - 1).allow_newpage_ = allow_newpage_; + grid.rowinfo(cellrow - 1).allow_newpage = allow_newpage; return true; } @@ -228,6 +230,8 @@ bool addCol(InsetMathGrid & grid, InsetMathGrid::col_type & cellcol) * \endverbatim * will result in a grid with 3 rows (+ the dummy row that is always present), * because the last '\\' opens a new row. + * Do never delete a row that contains a multicolumn, even if all cells empty, + * since the multicolumn information would get lost otherwise. * Note that this is only needed for inner-hull grid types, such as array * or aligned, but not for outer-hull grid types, such as eqnarray or align. */ @@ -235,7 +239,9 @@ void delEmptyLastRow(InsetMathGrid & grid) { InsetMathGrid::row_type const row = grid.nrows() - 1; for (InsetMathGrid::col_type col = 0; col < grid.ncols(); ++col) { - if (!grid.cell(grid.index(row, col)).empty()) + InsetMathGrid::idx_type const idx = grid.index(row, col); + if (!grid.cell(idx).empty() || + grid.cellinfo(idx).multi != InsetMathGrid::CELL_NORMAL) return; } // Copy the row information of the empty row (which would contain the @@ -395,8 +401,6 @@ public: bool parse1(InsetMathGrid & grid, unsigned flags, mode_type mode, bool numbered); /// - MathData parse(unsigned flags, mode_type mode); - /// int lineno() const { return lineno_; } /// void putback(); @@ -429,8 +433,6 @@ private: /// void push_back(Token const & t); /// - void pop_back(); - /// Token const & prevToken() const; /// Token const & nextToken() const; @@ -495,12 +497,6 @@ void Parser::push_back(Token const & t) } -void Parser::pop_back() -{ - tokens_.pop_back(); -} - - Token const & Parser::prevToken() const { static const Token dummy; @@ -626,7 +622,7 @@ void Parser::tokenize(istream & is) void Parser::tokenize(docstring const & buffer) { - idocstringstream is(mode_ & Parse::VERBATIM + idocstringstream is((mode_ & Parse::VERBATIM) ? escapeSpecialChars(buffer, mode_ & Parse::TEXTMODE) : buffer, ios::in | ios::binary); @@ -748,7 +744,8 @@ docstring Parser::parse_verbatim_option() skipSpaces(); docstring res; if (nextToken().character() == '[') { - Token t = getToken(); + // eat [ + getToken(); for (Token t = getToken(); t.character() != ']' && good(); t = getToken()) { if (t.cat() == catBegin) { putback(); @@ -766,7 +763,8 @@ docstring Parser::parse_verbatim_item() skipSpaces(); docstring res; if (nextToken().cat() == catBegin) { - Token t = getToken(); + // eat catBegin + getToken(); for (Token t = getToken(); t.cat() != catEnd && good(); t = getToken()) { if (t.cat() == catBegin) { putback(); @@ -780,14 +778,6 @@ docstring Parser::parse_verbatim_item() } -MathData Parser::parse(unsigned flags, mode_type mode) -{ - MathData ar(buffer_); - parse(ar, flags, mode); - return ar; -} - - bool Parser::parse(MathData & array, unsigned flags, mode_type mode) { InsetMathGrid grid(buffer_, 1, 1); @@ -941,8 +931,13 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, } else if (t.cat() == catParameter) { - Token const & n = getToken(); - cell->push_back(MathAtom(new MathMacroArgument(n.character()-'0'))); + Token const & n = nextToken(); + char_type c = n.character(); + if (c && '0' < c && c <= '9') { + cell->push_back(MathAtom(new InsetMathMacroArgument(c - '0'))); + getToken(); + } else + cell->push_back(MathAtom(new InsetMathHash())); } else if (t.cat() == catActive) @@ -1024,7 +1019,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, else if (t.cat() == catOther) { char_type c = t.character(); - if (isAsciiOrMathAlpha(c) + if (!Encodings::isUnicodeTextOnly(c) || mode_ & Parse::VERBATIM || !(mode_ & Parse::USETEXT) || mode == InsetMath::TEXT_MODE) { @@ -1033,7 +1028,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, MathAtom at = createInsetMath("text", buf); at.nucleus()->cell(0).push_back(MathAtom(new InsetMathChar(c))); while (nextToken().cat() == catOther - && !isAsciiOrMathAlpha(nextToken().character())) { + && Encodings::isUnicodeTextOnly(nextToken().character())) { c = getToken().character(); at.nucleus()->cell(0).push_back(MathAtom(new InsetMathChar(c))); } @@ -1044,10 +1039,10 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, else if (t.cat() == catComment) { docstring s; while (good()) { - Token const & t = getToken(); - if (t.cat() == catNewline) + Token const & tt = getToken(); + if (tt.cat() == catNewline) break; - s += t.asInput(); + s += tt.asInput(); } cell->push_back(MathAtom(new InsetMathComment(buf, s))); skipSpaces(); @@ -1089,7 +1084,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, if (nextToken().cat() == catBegin) parse(display, FLAG_ITEM, InsetMath::MATH_MODE); - cell->push_back(MathAtom(new MathMacroTemplate(buf, + cell->push_back(MathAtom(new InsetMathMacroTemplate(buf, name, nargs, 0, MacroTypeDef, vector(), def, display))); @@ -1137,7 +1132,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, if (nextToken().cat() == catBegin) parse(display, FLAG_ITEM, InsetMath::MATH_MODE); - cell->push_back(MathAtom(new MathMacroTemplate(buf, + cell->push_back(MathAtom(new InsetMathMacroTemplate(buf, name, nargs, optionals, MacroTypeNewcommand, optionalValues, def, display))); @@ -1258,7 +1253,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, if (nextToken().cat() == catBegin) parse(display, FLAG_ITEM, InsetMath::MATH_MODE); - cell->push_back(MathAtom(new MathMacroTemplate(buf, + cell->push_back(MathAtom(new InsetMathMacroTemplate(buf, name, nargs, optionals, MacroTypeNewcommandx, optionalValues, def, display))); @@ -1374,38 +1369,43 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, } } -#if 0 - else if (t.cs() == "multicolumn") { - // extract column count and insert dummy cells + else if (t.cs() == "multicolumn" && grid.handlesMulticolumn()) { + // if the columns are specified numerically, + // extract column count and insert dummy cells, + // otherwise parse it as an user macro MathData count; parse(count, FLAG_ITEM, mode); - int cols = 1; - if (!extractNumber(count, cols)) { - success_ = false; - lyxerr << " can't extract number of cells from " << count << endl; - } - // resize the table if necessary - for (int i = 0; i < cols; ++i) { - if (addCol(grid, cellcol)) { - cell = &grid.cell(grid.index( - cellrow, cellcol)); - // mark this as dummy - grid.cellinfo(grid.index( - cellrow, cellcol)).dummy_ = true; + int cols; + // limit arbitrarily to 100 columns + if (extractNumber(count, cols) && cols > 0 && cols < 100) { + // resize the table if necessary + size_t first = grid.index(cellrow, cellcol); + for (int i = 1; i < cols; ++i) { + if (addCol(grid, cellcol)) { + size_t const idx = grid.index(cellrow, cellcol); + grid.cellinfo(idx).multi = + InsetMathGrid::CELL_PART_OF_MULTICOLUMN; + } } - } - // the last cell is the real thing, not a dummy - grid.cellinfo(grid.index(cellrow, cellcol)).dummy_ = false; - // read special alignment - MathData align; - parse(align, FLAG_ITEM, mode); - //grid.cellinfo(grid.index(cellrow, cellcol)).align_ = extractString(align); + // the first cell is the real thing, not a dummy + cell = &grid.cell(first); + grid.cellinfo(first).multi = + InsetMathGrid::CELL_BEGIN_OF_MULTICOLUMN; - // parse the remaining contents into the "real" cell - parse(*cell, FLAG_ITEM, mode); + // read special alignment + MathData align; + parse(align, FLAG_ITEM, mode); + grid.cellinfo(first).align = asString(align); + + // parse the remaining contents into the "real" cell + parse(*cell, FLAG_ITEM, mode); + } else { + MathAtom at = MathAtom(new InsetMathMacro(buf, t.cs())); + cell->push_back(at); + cell->push_back(MathAtom(new InsetMathBrace(count))); + } } -#endif else if (t.cs() == "limits" || t.cs() == "nolimits") { CatCode const cat = nextToken().cat(); @@ -1426,7 +1426,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, grid.asHullInset()->numbered(cellrow, true); else if (t.cs() == "hline") { - grid.rowinfo(cellrow).lines_ ++; + grid.rowinfo(cellrow).lines++; } else if (t.cs() == "sqrt") { @@ -1434,12 +1434,10 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, parse(ar, FLAG_OPTION, mode); if (!ar.empty()) { cell->push_back(MathAtom(new InsetMathRoot(buf))); - cell->back().nucleus()->cell(0) = ar; - parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode); - } else { + cell->back().nucleus()->cell(1) = ar; + } else cell->push_back(MathAtom(new InsetMathSqrt(buf))); - parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode); - } + parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode); } else if (t.cs() == "cancelto") { @@ -1531,8 +1529,8 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, cell->push_back(MathAtom(new InsetMathStackrel(buf, !ar.empty()))); if (!ar.empty()) cell->back().nucleus()->cell(2) = ar; - parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode); parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode); + parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode); } else if (t.cs() == "xrightarrow" || t.cs() == "xleftarrow") { @@ -1554,7 +1552,8 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, } else if (t.cs() == "ref" || t.cs() == "eqref" || t.cs() == "prettyref" - || t.cs() == "pageref" || t.cs() == "vpageref" || t.cs() == "vref") { + || t.cs() == "nameref" || t.cs() == "pageref" + || t.cs() == "vpageref" || t.cs() == "vref") { cell->push_back(MathAtom(new InsetMathRef(buf, t.cs()))); docstring const opt = parse_verbatim_option(); docstring const ref = parse_verbatim_item(); @@ -1607,7 +1606,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, docstring const halign = parse_verbatim_item(); cell->push_back(MathAtom(new InsetMathArray(buf, name, InsetMathGrid::guessColumns(halign), 1, (char)valign[0], halign))); - parse2(cell->back(), FLAG_END, mode, false); + parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, false); } else if (name == "tabular") { @@ -1759,7 +1758,8 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, else { success_ = false; - if (!(mode_ & Parse::QUIET)) { + if (!(mode_ & Parse::QUIET) && + !(mode_ & Parse::TRACKMACRO)) { dump(); lyxerr << "found unknown math environment '" << to_utf8(name) << "'" << endl; @@ -1770,12 +1770,12 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, } } - else if (t.cs() == "kern") { + else if (t.cs() == "kern" || t.cs() == "mkern") { // FIXME: A hack... docstring s; int num_tokens = 0; while (true) { - Token const & t = getToken(); + Token const & tt = getToken(); ++num_tokens; if (!good()) { s.clear(); @@ -1783,12 +1783,12 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, putback(); break; } - s += t.character(); + s += tt.character(); if (isValidLength(to_utf8(s))) break; } if (s.empty()) - cell->push_back(MathAtom(new InsetMathKern)); + cell->push_back(MathAtom(new InsetMathMacro(buf, t.cs()))); else cell->push_back(MathAtom(new InsetMathKern(s))); } @@ -1800,6 +1800,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, asArray(label, ar); if (grid.asHullInset()) { grid.asHullInset()->label(cellrow, label); + grid.asHullInset()->numbered(cellrow, true); } else { cell->push_back(createInsetMath(t.cs(), buf)); cell->push_back(MathAtom(new InsetMathBrace(ar))); @@ -1897,7 +1898,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, else { // Since the Length class cannot use length variables // we must not create an InsetMathSpace. - cell->push_back(MathAtom(new MathMacro(buf, name))); + cell->push_back(MathAtom(new InsetMathMacro(buf, name))); MathData ar; mathed_parse_cell(ar, '{' + arg + '}', mode_); cell->append(ar); @@ -1916,7 +1917,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode); } else { docstring const arg = parse_verbatim_item(); - cell->push_back(MathAtom(new MathMacro(buf, t.cs()))); + cell->push_back(MathAtom(new InsetMathMacro(buf, t.cs()))); MathData ar; mathed_parse_cell(ar, '[' + opt + ']', mode_); cell->append(ar); @@ -1938,23 +1939,6 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, cell->push_back(createInsetMath(t.cs(), buf)); parse2(cell->back(), FLAG_ITEM, mode, false); } - - // Disabled - else if (1 && t.cs() == "ar") { - auto_ptr p(new InsetMathXYArrow); - // try to read target - 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(p->cell(1), FLAG_ITEM, mode); - //lyxerr << "read label: " << p->cell(1) << endl; - } - - cell->push_back(MathAtom(p.release())); - //lyxerr << "read cell: " << cell << endl; - } #endif else if (t.cs() == "lyxmathsym") { @@ -2003,7 +1987,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, BufferParams::package_off; bool const is_user_macro = no_mhchem || - (buf && (mode_ & Parse::TRACKMACRO + (buf && ((mode_ & Parse::TRACKMACRO) ? buf->usermacros.count(t.cs()) != 0 : buf->getMacro(t.cs(), false) != 0)); @@ -2017,7 +2001,10 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, new InsetMathBig(t.cs(), delim))); else { cell->push_back(createInsetMath(t.cs(), buf)); - putback(); + // For some reason delim.empty() + // is always false here + if (delim.at(0)) + putback(); } } @@ -2047,6 +2034,12 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, putback(); } + else if (l->inset == "underset" || l->inset == "overset") { + cell->push_back(createInsetMath(t.cs(), buf)); + parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode); + parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode); + } + else { MathAtom at = createInsetMath(t.cs(), buf); for (InsetMath::idx_type i = 0; i < at->nargs(); ++i) @@ -2090,19 +2083,17 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, Encodings::MATH_CMD | Encodings::TEXT_CMD, is_combining, termination); } - if (c) { + if (c && buf && buf->params().encoding().encodable(c)) { if (termination) { if (nextToken().cat() == catBegin) { getToken(); if (nextToken().cat() == catEnd) { getToken(); - num_tokens += 2; } else putback(); } else { while (nextToken().cat() == catSpace) { getToken(); - ++num_tokens; } } } @@ -2115,7 +2106,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, } if (!is_unicode_symbol) { MathAtom at = is_user_macro ? - MathAtom(new MathMacro(buf, t.cs())) + MathAtom(new InsetMathMacro(buf, t.cs())) : createInsetMath(t.cs(), buf); InsetMath::mode_type m = mode; //if (m == InsetMath::UNDECIDED_MODE) @@ -2143,7 +2134,6 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, if (flags & FLAG_LEAVE) { - flags &= ~FLAG_LEAVE; break; } } @@ -2166,14 +2156,14 @@ char const * latexkeys::MathMLtype() const bool mathed_parse_cell(MathData & ar, docstring const & str, Parse::flags f) { - return Parser(str, f, ar.buffer()).parse(ar, 0, f & Parse::TEXTMODE ? + return Parser(str, f, ar.buffer()).parse(ar, 0, (f & Parse::TEXTMODE) ? InsetMath::TEXT_MODE : InsetMath::MATH_MODE); } bool mathed_parse_cell(MathData & ar, istream & is, Parse::flags f) { - return Parser(is, f, ar.buffer()).parse(ar, 0, f & Parse::TEXTMODE ? + return Parser(is, f, ar.buffer()).parse(ar, 0, (f & Parse::TEXTMODE) ? InsetMath::TEXT_MODE : InsetMath::MATH_MODE); } @@ -2195,7 +2185,7 @@ bool mathed_parse_normal(Buffer * buf, MathAtom & t, Lexer & lex, bool mathed_parse_normal(InsetMathGrid & grid, docstring const & str, Parse::flags f) { - return Parser(str, f, &grid.buffer()).parse1(grid, 0, f & Parse::TEXTMODE ? + return Parser(str, f, &grid.buffer()).parse1(grid, 0, (f & Parse::TEXTMODE) ? InsetMath::TEXT_MODE : InsetMath::MATH_MODE, false); }