#include "InsetMathRef.h"
#include "InsetMathRoot.h"
#include "InsetMathScript.h"
+#include "InsetMathSideset.h"
#include "InsetMathSpace.h"
#include "InsetMathSplit.h"
#include "InsetMathSqrt.h"
int lineno() const { return lineno_; }
///
void putback();
+ /// store current position
+ void pushPosition();
+ /// restore previous position
+ void popPosition();
+ /// forget last saved position
+ void dropPosition();
private:
///
vector<Token> tokens_;
///
unsigned pos_;
+ ///
+ std::vector<unsigned> positions_;
/// Stack of active environments
vector<docstring> environments_;
///
}
+void Parser::pushPosition()
+{
+ positions_.push_back(pos_);
+}
+
+
+void Parser::popPosition()
+{
+ pos_ = positions_.back();
+ positions_.pop_back();
+}
+
+
+void Parser::dropPosition()
+{
+ positions_.pop_back();
+}
+
+
bool Parser::good() const
{
return pos_ < tokens_.size();
} else {
// This is not an outer hull and display math is
// not allowed inside text mode environments.
- error("bad math environment");
+ error("bad math environment $$");
break;
}
} else {
t.cs() == "def") {
if (t.cs() == "global")
getToken();
-
+
// get name
docstring name = getToken().cs();
-
+
// read parameters
int nargs = 0;
docstring pars;
++nargs;
}
nargs /= 2;
-
+
// read definition
MathData def;
parse(def, FLAG_ITEM, InsetMath::UNDECIDED_MODE);
-
+
// is a version for display attached?
skipSpaces();
MathData display;
if (nextToken().cat() == catBegin)
parse(display, FLAG_ITEM, InsetMath::MATH_MODE);
-
+
cell->push_back(MathAtom(new MathMacroTemplate(buf,
name, nargs, 0, MacroTypeDef,
vector<MathData>(), def, display)));
if (buf && (mode_ & Parse::TRACKMACRO))
buf->usermacros.insert(name);
}
-
+
else if (t.cs() == "newcommand" ||
t.cs() == "renewcommand" ||
t.cs() == "newlyxcommand") {
error("'}' in \\newcommand expected");
return success_;
}
-
+
// get arity
docstring const arg = getArg('[', ']');
int nargs = 0;
if (!arg.empty())
nargs = convert<int>(arg);
-
+
// optional argument given?
skipSpaces();
int optionals = 0;
parse(optionalValues[optionals], FLAG_BRACK_LAST, mode);
++optionals;
}
-
+
MathData def;
parse(def, FLAG_ITEM, InsetMath::UNDECIDED_MODE);
-
+
// is a version for display attached?
skipSpaces();
MathData display;
if (nextToken().cat() == catBegin)
parse(display, FLAG_ITEM, InsetMath::MATH_MODE);
-
+
cell->push_back(MathAtom(new MathMacroTemplate(buf,
name, nargs, optionals, MacroTypeNewcommand,
optionalValues, def, display)));
if (buf && (mode_ & Parse::TRACKMACRO))
buf->usermacros.insert(name);
}
-
+
else if (t.cs() == "newcommandx" ||
t.cs() == "renewcommandx") {
// \newcommandx{\foo}[2][usedefault, addprefix=\global,1=default]{#1,#2}
}
} else
name = getToken().cs();
-
+
// get arity
docstring const arg = getArg('[', ']');
if (arg.empty()) {
return success_;
}
int nargs = convert<int>(arg);
-
+
// get options
int optionals = 0;
vector<MathData> optionalValues;
if (nextToken().character() == '[') {
// skip '['
getToken();
-
+
// handle 'opt=value' options, separated by ','.
skipSpaces();
while (nextToken().character() != ']' && good()) {
"for given optional parameter.");
return success_;
}
-
+
// skip '='
if (getToken().character() != '=') {
error("'=' and optional parameter value "
"expected for \\newcommandx");
return success_;
}
-
+
// get value
int optNum = max(size_t(n), optionalValues.size());
optionalValues.resize(optNum);
} else if (nextToken().cat() == catLetter) {
// we in fact ignore every non-optional
// parameter
-
+
// get option name
docstring opt;
while (nextToken().cat() == catLetter)
opt += getChar();
-
+
// value?
skipSpaces();
MathData value;
getToken();
while (nextToken().character() != ']'
&& nextToken().character() != ',')
- parse(value, FLAG_ITEM,
+ parse(value, FLAG_ITEM,
InsetMath::UNDECIDED_MODE);
}
} else {
error("option for \\newcommandx expected");
return success_;
}
-
+
// skip komma
skipSpaces();
if (nextToken().character() == ',') {
return success_;
}
}
-
+
// skip ']'
if (!good())
return success_;
}
else if (t.cs() == "(") {
- cell->push_back(MathAtom(new InsetMathEnsureMath(buf)));
- parse(cell->back().nucleus()->cell(0), FLAG_SIMPLE2, InsetMath::MATH_MODE);
+ if (mode == InsetMath::UNDECIDED_MODE) {
+ cell->push_back(MathAtom(new InsetMathHull(buf, hullSimple)));
+ parse2(cell->back(), FLAG_SIMPLE2, InsetMath::MATH_MODE, false);
+ } else {
+ // Don't create nested math hulls (bug #5392)
+ cell->push_back(MathAtom(new InsetMathEnsureMath(buf)));
+ parse(cell->back().nucleus()->cell(0), FLAG_SIMPLE2, InsetMath::MATH_MODE);
+ }
}
else if (t.cs() == "[") {
if (mode != InsetMath::UNDECIDED_MODE) {
- error("bad math environment");
+ error("bad math environment [");
break;
}
cell->push_back(MathAtom(new InsetMathHull(buf, hullEquation)));
else if (t.cs() == "\\") {
if (flags & FLAG_ALIGN)
return success_;
- bool added = false;
+ bool starred = false;
+ docstring arg;
if (nextToken().asInput() == "*") {
getToken();
- added = addRow(grid, cellrow, docstring(), false);
- } else if (good())
- added = addRow(grid, cellrow, getArg('[', ']'));
- else
+ starred = true;
+ } else if (nextToken().asInput() == "[")
+ arg = getArg('[', ']');
+ else if (!good())
error("missing token after \\\\");
+ // skip "{}" added in front of "[" (the
+ // counterpart is in InsetMathGrid::eolString())
+ // skip spaces because formula could come from tex2lyx
+ bool skipBraces = false;
+ pushPosition();
+ if (nextToken().cat() == catBegin) {
+ getToken();
+ if (nextToken().cat() == catEnd) {
+ getToken();
+ pushPosition();
+ skipSpaces();
+ if (nextToken().asInput() == "[")
+ skipBraces = true;
+ popPosition();
+ }
+ }
+ if (skipBraces)
+ dropPosition();
+ else
+ popPosition();
+ bool const added = addRow(grid, cellrow, arg, !starred);
if (added) {
cellcol = 0;
if (grid.asHullInset())
}
}
- else if (t.cs() == "nonumber") {
- if (grid.asHullInset())
- grid.asHullInset()->numbered(cellrow, false);
- }
+ // \notag is the same as \nonumber if amsmath is used
+ else if ((t.cs() == "nonumber" || t.cs() == "notag") &&
+ grid.asHullInset())
+ grid.asHullInset()->numbered(cellrow, false);
- else if (t.cs() == "number") {
- if (grid.asHullInset())
- grid.asHullInset()->numbered(cellrow, true);
- }
+ else if (t.cs() == "number" && grid.asHullInset())
+ grid.asHullInset()->numbered(cellrow, true);
else if (t.cs() == "hline") {
grid.rowinfo(cellrow).lines_ ++;
else if (t.cs() == "cfrac") {
// allowed formats are \cfrac[pos]{num}{denom}
docstring const arg = getArg('[', ']');
- //lyxerr << "got so far: '" << arg << "'" << endl;
+ //lyxerr << "got so far: '" << arg << "'" << endl;
if (arg == "l")
cell->push_back(MathAtom(new InsetMathFrac(buf, InsetMathFrac::CFRACLEFT)));
else if (arg == "r")
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(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
}
+ else if (t.cs() == "xhookrightarrow" || t.cs() == "xhookleftarrow" ||
+ t.cs() == "xRightarrow" || t.cs() == "xLeftarrow" ||
+ t.cs() == "xleftrightarrow" || t.cs() == "xLeftrightarrow" ||
+ t.cs() == "xrightharpoondown" || t.cs() == "xrightharpoonup" ||
+ t.cs() == "xleftharpoondown" || t.cs() == "xleftharpoonup" ||
+ t.cs() == "xleftrightharpoons" || t.cs() == "xrightleftharpoons" ||
+ t.cs() == "xmapsto") {
+ cell->push_back(createInsetMath(t.cs(), buf));
+ 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() == "eqref" || t.cs() == "prettyref"
|| t.cs() == "pageref" || t.cs() == "vpageref" || t.cs() == "vref") {
cell->push_back(MathAtom(new InsetMathRef(buf, t.cs())));
else if (t.cs() == "begin") {
docstring const name = getArg('{', '}');
+
+ if (name.empty()) {
+ success_ = false;
+ error("found invalid environment");
+ return success_;
+ }
+
environments_.push_back(name);
if (name == "array" || name == "subarray") {
}
else if (name == "math") {
- cell->push_back(MathAtom(new InsetMathEnsureMath(buf)));
- parse(cell->back().nucleus()->cell(0), FLAG_END, InsetMath::MATH_MODE);
+ if (mode == InsetMath::UNDECIDED_MODE) {
+ cell->push_back(MathAtom(new InsetMathHull(buf, hullSimple)));
+ parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, false);
+ } else {
+ // Don't create nested math hulls (bug #5392)
+ cell->push_back(MathAtom(new InsetMathEnsureMath(buf)));
+ parse(cell->back().nucleus()->cell(0), FLAG_END, InsetMath::MATH_MODE);
+ }
}
else if (name == "equation" || name == "equation*"
|| name == "displaymath") {
if (mode != InsetMath::UNDECIDED_MODE) {
- error("bad math environment");
+ error("bad math environment " + name);
break;
}
cell->push_back(MathAtom(new InsetMathHull(buf, hullEquation)));
else if (name == "eqnarray" || name == "eqnarray*") {
if (mode != InsetMath::UNDECIDED_MODE) {
- error("bad math environment");
+ error("bad math environment " + name);
break;
}
cell->push_back(MathAtom(new InsetMathHull(buf, hullEqnArray)));
}
else if (name == "align" || name == "align*") {
- if (mode != InsetMath::UNDECIDED_MODE) {
- error("bad math environment");
- break;
+ if (mode == InsetMath::UNDECIDED_MODE) {
+ cell->push_back(MathAtom(new InsetMathHull(buf, hullAlign)));
+ parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
+ } else {
+ cell->push_back(MathAtom(new InsetMathSplit(buf, name,
+ 'c', !stared(name))));
+ parse2(cell->back(), FLAG_END, mode, !stared(name));
}
- cell->push_back(MathAtom(new InsetMathHull(buf, hullAlign)));
- parse2(cell->back(), FLAG_END, InsetMath::MATH_MODE, !stared(name));
}
else if (name == "flalign" || name == "flalign*") {
if (mode != InsetMath::UNDECIDED_MODE) {
- error("bad math environment");
+ error("bad math environment " + name);
break;
}
cell->push_back(MathAtom(new InsetMathHull(buf, hullFlAlign)));
else if (name == "alignat" || name == "alignat*") {
if (mode != InsetMath::UNDECIDED_MODE) {
- error("bad math environment");
+ error("bad math environment " + name);
break;
}
// ignore this for a while
else if (name == "xalignat" || name == "xalignat*") {
if (mode != InsetMath::UNDECIDED_MODE) {
- error("bad math environment");
+ error("bad math environment " + name);
break;
}
// ignore this for a while
else if (name == "xxalignat") {
if (mode != InsetMath::UNDECIDED_MODE) {
- error("bad math environment");
+ error("bad math environment " + name);
break;
}
// ignore this for a while
else if (name == "multline" || name == "multline*") {
if (mode != InsetMath::UNDECIDED_MODE) {
- error("bad math environment");
+ error("bad math environment " + name);
break;
}
cell->push_back(MathAtom(new InsetMathHull(buf, hullMultline)));
else if (name == "gather" || name == "gather*") {
if (mode != InsetMath::UNDECIDED_MODE) {
- error("bad math environment");
+ error("bad math environment " + name);
break;
}
cell->push_back(MathAtom(new InsetMathHull(buf, hullGather)));
lyxerr << "found math environment `"
<< to_utf8(name)
<< "' in symbols file with unsupported inset `"
- << to_utf8(l->inset)
+ << l->inset
<< "'." << endl;
}
// create generic environment inset
}
}
+ else if (t.cs() == "smash") {
+ skipSpaces();
+ if (nextToken().asInput() == "[") {
+ // Since the phantom inset cannot handle optional arguments
+ // other than b and t, we must not create an InsetMathPhantom
+ // if opt is different from b and t (bug 8967).
+ docstring const opt = parse_verbatim_option();
+ if (opt == "t" || opt == "b") {
+ cell->push_back(createInsetMath(t.cs() + opt, buf));
+ 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())));
+ MathData ar;
+ mathed_parse_cell(ar, '[' + opt + ']', mode_);
+ cell->append(ar);
+ ar = MathData();
+ mathed_parse_cell(ar, '{' + arg + '}', mode_);
+ cell->append(ar);
+ }
+ }
+ else {
+ cell->push_back(createInsetMath(t.cs(), buf));
+ parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+ }
+ }
+
#if 0
else if (t.cs() == "infer") {
MathData ar;
//}
for (InsetMath::idx_type i = start; i < at->nargs(); ++i) {
parse(at.nucleus()->cell(i), FLAG_ITEM, m);
- skipSpaces();
+ if (mode == InsetMath::MATH_MODE)
+ skipSpaces();
}
cell->push_back(at);
}
} // anonymous namespace
+// FIXME This will likely need some work.
+char const * latexkeys::MathMLtype() const
+{
+ if (extra == "mathord")
+ return "mi";
+ return "mo";
+}
+
+
bool mathed_parse_cell(MathData & ar, docstring const & str, Parse::flags f)
{
return Parser(str, f, ar.buffer()).parse(ar, 0, f & Parse::TEXTMODE ?