X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2FMathParser.cpp;h=05ceed80f251bf6d78f210276f8a03e8cf8b1b01;hb=f6d505c1ee494ab0d30eebba86082c86a915e1df;hp=bd66b0b5e2ba4b499c835df267f4a1678ffcf15e;hpb=7049447fd70cc14d30deb641e76550c010a3e29f;p=lyx.git diff --git a/src/mathed/MathParser.cpp b/src/mathed/MathParser.cpp index bd66b0b5e2..05ceed80f2 100644 --- a/src/mathed/MathParser.cpp +++ b/src/mathed/MathParser.cpp @@ -42,6 +42,7 @@ following hack as starting point to write some macros: #include "InsetMathArray.h" #include "InsetMathBig.h" #include "InsetMathBrace.h" +#include "InsetMathCancelto.h" #include "InsetMathChar.h" #include "InsetMathColor.h" #include "InsetMathComment.h" @@ -55,9 +56,11 @@ following hack as starting point to write some macros: #include "InsetMathRef.h" #include "InsetMathRoot.h" #include "InsetMathScript.h" +#include "InsetMathSideset.h" #include "InsetMathSpace.h" #include "InsetMathSplit.h" #include "InsetMathSqrt.h" +#include "InsetMathStackrel.h" #include "InsetMathString.h" #include "InsetMathTabular.h" #include "MathMacroTemplate.h" @@ -248,9 +251,11 @@ void delEmptyLastRow(InsetMathGrid & grid) */ bool innerHull(docstring const & name) { + // For [bB]matrix, [vV]matrix, and pmatrix we can check the suffix only return name == "array" || name == "cases" || name == "aligned" || name == "alignedat" || name == "gathered" || name == "split" - || name == "tabular"; + || name == "subarray" || name == "tabular" || name == "matrix" + || name == "smallmatrix" || name.substr(1) == "matrix"; } @@ -331,9 +336,9 @@ public: /// char_type character() const { return char_; } /// - docstring asString() const { return cs_.size() ? cs_ : docstring(1, char_); } + docstring asString() const { return !cs_.empty() ? cs_ : docstring(1, char_); } /// - docstring asInput() const { return cs_.size() ? '\\' + cs_ : docstring(1, char_); } + docstring asInput() const { return !cs_.empty() ? '\\' + cs_ : docstring(1, char_); } private: /// @@ -347,7 +352,7 @@ private: ostream & operator<<(ostream & os, Token const & t) { - if (t.cs().size()) { + if (!t.cs().empty()) { docstring const & cs = t.cs(); // FIXME: For some strange reason, the stream operator instanciate // a new Token before outputting the contents of t.cs(). @@ -533,7 +538,6 @@ char_type Parser::getChar() { if (!good()) { error("The input stream is not well..."); - putback(); return 0; } return tokens_[pos_++].character(); @@ -542,9 +546,12 @@ char_type Parser::getChar() docstring Parser::getArg(char_type left, char_type right) { + docstring result; skipSpaces(); - docstring result; + if (!good()) + return result; + char_type c = getChar(); if (c != left) @@ -847,9 +854,16 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, Token const & n = getToken(); if (n.cat() == catMath) { // TeX's $$...$$ syntax for displayed math - cell->push_back(MathAtom(new InsetMathHull(buf, hullEquation))); - parse2(cell->back(), FLAG_SIMPLE, InsetMath::MATH_MODE, false); - getToken(); // skip the second '$' token + if (mode == InsetMath::UNDECIDED_MODE) { + cell->push_back(MathAtom(new InsetMathHull(buf, hullEquation))); + parse2(cell->back(), FLAG_SIMPLE, InsetMath::MATH_MODE, false); + getToken(); // skip the second '$' token + } else { + // This is not an outer hull and display math is + // not allowed inside text mode environments. + error("bad math environment"); + break; + } } else { // simple $...$ stuff putback(); @@ -870,8 +884,19 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, } else { - error("something strange in the parser"); - break; + Token const & n = getToken(); + if (n.cat() == catMath) { + error("something strange in the parser"); + break; + } else { + // This is inline math ($...$), but the parser thinks we are + // already in math mode and latex would issue an error, unless we + // are inside a text mode user macro. We have no way to tell, so + // let's play safe by using \ensuremath, as it will work in any case. + putback(); + cell->push_back(MathAtom(new InsetMathEnsureMath(buf))); + parse(cell->back().nucleus()->cell(0), FLAG_SIMPLE, InsetMath::MATH_MODE); + } } } @@ -894,7 +919,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, } else if (t.cat() == catActive) - cell->push_back(MathAtom(new InsetMathChar(t.character()))); + cell->push_back(MathAtom(new InsetMathSpace(string(1, t.character()), ""))); else if (t.cat() == catBegin) { MathData ar; @@ -928,7 +953,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, bool up = (t.cat() == catSuper); // 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()) + if (cell->empty()) cell->push_back(MathAtom(new InsetMathScript(buf, up))); else if (cell->back()->asScriptInset() && !cell->back()->asScriptInset()->has(up)) @@ -995,7 +1020,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, Token const & t = getToken(); if (t.cat() == catNewline) break; - s += t.asString(); + s += t.asInput(); } cell->push_back(MathAtom(new InsetMathComment(buf, s))); skipSpaces(); @@ -1006,7 +1031,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, // else if (t.cs() == "lyxlock") { - if (cell->size()) + if (!cell->empty()) cell->back().nucleus()->lock(true); } @@ -1215,12 +1240,8 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, } else if (t.cs() == "(") { - if (mode == InsetMath::MATH_MODE) { - error("bad math environment"); - break; - } - cell->push_back(MathAtom(new InsetMathHull(buf, hullSimple))); - parse2(cell->back(), FLAG_SIMPLE2, InsetMath::MATH_MODE, false); + cell->push_back(MathAtom(new InsetMathEnsureMath(buf))); + parse(cell->back().nucleus()->cell(0), FLAG_SIMPLE2, InsetMath::MATH_MODE); } else if (t.cs() == "[") { @@ -1332,7 +1353,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, #endif else if (t.cs() == "limits" || t.cs() == "nolimits") { - CatCode cat = nextToken().cat(); + CatCode const cat = nextToken().cat(); if (cat == catSuper || cat == catSub) limits = t.cs() == "limits" ? 1 : -1; else { @@ -1358,7 +1379,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, else if (t.cs() == "sqrt") { MathData ar; parse(ar, FLAG_OPTION, mode); - if (ar.size()) { + 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); @@ -1368,11 +1389,19 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, } } + else if (t.cs() == "cancelto") { + MathData ar; + parse(ar, FLAG_ITEM, mode); + cell->push_back(MathAtom(new InsetMathCancelto(buf))); + cell->back().nucleus()->cell(1) = ar; + parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode); + } + else if (t.cs() == "unit") { // Allowed formats \unit[val]{unit} MathData ar; parse(ar, FLAG_OPTION, mode); - if (ar.size()) { + if (!ar.empty()) { cell->push_back(MathAtom(new InsetMathFrac(buf, InsetMathFrac::UNIT))); cell->back().nucleus()->cell(0) = ar; parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode); @@ -1386,7 +1415,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, // Here allowed formats are \unitfrac[val]{num}{denom} MathData ar; parse(ar, FLAG_OPTION, mode); - if (ar.size()) { + if (!ar.empty()) { cell->push_back(MathAtom(new InsetMathFrac(buf, InsetMathFrac::UNITFRAC, 3))); cell->back().nucleus()->cell(2) = ar; } else { @@ -1414,6 +1443,45 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode); } + else if (t.cs() == "sideset") { + // Here allowed formats are \sideset{_{bl}^{tl}}{_{br}^{tr}}{operator} + MathData ar[2]; + InsetMathScript * script[2] = {0, 0}; + for (int i = 0; i < 2; ++i) { + parse(ar[i], FLAG_ITEM, mode); + if (ar[i].size() == 1) + script[i] = ar[i][0].nucleus()->asScriptInset(); + } + bool const hasscript[2] = {script[0] ? true : false, script[1] ? true : false}; + cell->push_back(MathAtom(new InsetMathSideset(buf, hasscript[0], hasscript[1]))); + if (hasscript[0]) { + if (script[0]->hasDown()) + cell->back().nucleus()->cell(1) = script[0]->down(); + if (script[0]->hasUp()) + cell->back().nucleus()->cell(2) = script[0]->up(); + } else + cell->back().nucleus()->cell(1) = ar[0]; + if (hasscript[1]) { + if (script[1]->hasDown()) + cell->back().nucleus()->cell(2 + hasscript[0]) = script[1]->down(); + if (script[1]->hasUp()) + cell->back().nucleus()->cell(3 + hasscript[0]) = script[1]->up(); + } else + cell->back().nucleus()->cell(2 + hasscript[0]) = ar[1]; + parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode); + } + + else if (t.cs() == "stackrel") { + // Here allowed formats are \stackrel[subscript]{superscript}{operator} + MathData ar; + parse(ar, FLAG_OPTION, mode); + 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); + } + else if (t.cs() == "xrightarrow" || t.cs() == "xleftarrow") { cell->push_back(createInsetMath(t.cs(), buf)); parse(cell->back().nucleus()->cell(1), FLAG_OPTION, mode); @@ -1492,12 +1560,8 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, } else if (name == "math") { - if (mode == InsetMath::MATH_MODE) { - error("bad math environment"); - break; - } - cell->push_back(MathAtom(new InsetMathHull(buf, hullSimple))); - parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, true); + cell->push_back(MathAtom(new InsetMathEnsureMath(buf))); + parse(cell->back().nucleus()->cell(0), FLAG_END, InsetMath::MATH_MODE); } else if (name == "equation" || name == "equation*" @@ -1715,6 +1779,14 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, delEmptyLastRow(subgrid); } + else if (t.cs() == "Diagram") { + odocstringstream os; + while (good() && nextToken().cat() != catBegin) + os << getToken().asInput(); + cell->push_back(createInsetMath(t.cs() + os.str(), buf)); + parse2(cell->back(), FLAG_ITEM, mode, false); + } + else if (t.cs() == "framebox" || t.cs() == "makebox") { cell->push_back(createInsetMath(t.cs(), buf)); parse(cell->back().nucleus()->cell(0), FLAG_OPTION, InsetMath::TEXT_MODE); @@ -1731,12 +1803,17 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, parse(cell->back().nucleus()->cell(0), FLAG_ITEM, InsetMath::TEXT_MODE); } - else if (t.cs() == "hspace" && nextToken().character() != '*') { + else if (t.cs() == "hspace") { + bool const prot = nextToken().character() == '*'; + if (prot) + getToken(); docstring const name = t.cs(); docstring const arg = parse_verbatim_item(); Length length; - if (isValidLength(to_utf8(arg), &length)) - cell->push_back(MathAtom(new InsetMathSpace(length))); + if (prot && arg == "\\fill") + cell->push_back(MathAtom(new InsetMathSpace("hspace*{\\fill}", ""))); + else if (isValidLength(to_utf8(arg), &length)) + cell->push_back(MathAtom(new InsetMathSpace(length, prot))); else { // Since the Length class cannot use length variables // we must not create an InsetMathSpace. @@ -1794,29 +1871,35 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, error("'}' expected in \\" + t.cs()); return success_; } + bool termination; docstring rem; do { - cmd = Encodings::fromLaTeXCommand(cmd, rem); + cmd = Encodings::fromLaTeXCommand(cmd, + Encodings::MATH_CMD | Encodings::TEXT_CMD, + termination, rem); for (size_t i = 0; i < cmd.size(); ++i) cell->push_back(MathAtom(new InsetMathChar(cmd[i]))); - if (rem.size()) { + if (!rem.empty()) { char_type c = rem[0]; cell->push_back(MathAtom(new InsetMathChar(c))); cmd = rem.substr(1); rem.clear(); } else cmd.clear(); - } while (cmd.size()); + } while (!cmd.empty()); } - else if (t.cs().size()) { + else if (!t.cs().empty()) { bool const no_mhchem = - (t.cs() == "ce" || t.cs() == "cf") && buf - && buf->params().use_mhchem == BufferParams::package_off; + (t.cs() == "ce" || t.cs() == "cf") + && buf && buf->params().use_package("mhchem") == + BufferParams::package_off; + bool const is_user_macro = no_mhchem || (buf && (mode_ & Parse::TRACKMACRO - ? buf->usermacros.count(t.cs()) != 0 - : buf->getMacro(t.cs(), false) != 0)); + ? buf->usermacros.count(t.cs()) != 0 + : buf->getMacro(t.cs(), false) != 0)); + latexkeys const * l = in_word_set(t.cs()); if (l && !is_user_macro) { if (l->inset == "big") { @@ -1885,8 +1968,10 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, } } bool is_combining; - char_type c = - Encodings::fromLaTeXCommand(cmd, is_combining); + bool termination; + char_type c = Encodings::fromLaTeXCommand(cmd, + Encodings::MATH_CMD | Encodings::TEXT_CMD, + is_combining, termination); if (is_combining) { if (cat == catLetter) cmd += '{'; @@ -1894,9 +1979,26 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, ++num_tokens; if (cat == catLetter) cmd += '}'; - c = Encodings::fromLaTeXCommand(cmd, is_combining); + c = Encodings::fromLaTeXCommand(cmd, + Encodings::MATH_CMD | Encodings::TEXT_CMD, + is_combining, termination); } if (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; + } + } + } is_unicode_symbol = true; cell->push_back(MathAtom(new InsetMathChar(c))); } else { @@ -1918,7 +2020,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, // this fails on \bigg[...\bigg] //MathData opt; //parse(opt, FLAG_OPTION, InsetMath::VERBATIM_MODE); - //if (opt.size()) { + //if (!opt.empty()) { // start = 1; // at.nucleus()->cell(0) = opt; //}