* the GNU General Public Licence version 2 or later.
*/
+// {[(
+
#include <config.h>
#include <cctype>
#include "math_parser.h"
#include "array.h"
-#include "math_rowst.h"
-#include "math_iter.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_matrixinset.h"
-#include "math_accentinset.h"
-#include "math_bigopinset.h"
-#include "math_funcinset.h"
+#include "math_rootinset.h"
+#include "math_scriptinset.h"
+#include "math_sizeinset.h"
#include "math_spaceinset.h"
-#include "math_dotsinset.h"
-#include "math_fracinset.h"
-#include "math_deliminset.h"
-#include "math_decorationinset.h"
+#include "math_sqrtinset.h"
#include "debug.h"
-#include "support/lyxlib.h"
#include "mathed/support.h"
-#include "boost/array.hpp"
+#include "lyxlex.h"
using std::istream;
using std::endl;
-extern MathMatrixInset * create_multiline(short int type, int cols);
-
-namespace {
-
-enum {
- FLAG_BRACE = 1, // A { needed
- FLAG_BRACE_ARG = 2, // Next { is argument
- FLAG_BRACE_OPT = 4, // Optional {
- FLAG_BRACE_LAST = 8, // Last } ends the parsing process
- FLAG_BRACK_ARG = 16, // Optional [
- FLAG_RIGHT = 32, // Next right ends the parsing process
- FLAG_END = 64, // Next end ends the parsing process
- FLAG_BRACE_FONT = 128, // Next } closes a font
- FLAG_BRACK_END = 256 // Next ] ends the parsing process
-};
-
-
-///
-union YYSTYPE {
- ///
- unsigned char c;
- ///
- char const * s;
- ///
- int i;
- ///
- latexkeys const * l;
-};
-
-
-YYSTYPE yylval;
-
-
-MathedInsetTypes mathed_env = LM_OT_MIN;
-
-
-} // namespace anon
-
-
-string mathed_label;
-
-
-int const latex_mathenv_num = 12;
-char const * latex_mathenv[latex_mathenv_num] = {
- "math",
- "displaymath",
- "equation",
- "eqnarray*",
- "eqnarray",
- "align*",
- "align",
- "alignat*",
- "alignat",
- "multline*",
- "multline",
- "array"
-};
-
-
-char const * latex_special_chars = "#$%&_{}";
-
-
-namespace {
// These are lexical codes, not semantic
enum lexcode_enum {
LexSelf
};
-
lexcode_enum lexcode[256];
-#ifdef WITH_WARNINGS
-#warning Replace with string
-#endif
-//char yytext[256];
-array<char, 256> yytext;
+
+
+char const * latex_special_chars = "#$%&_{}";
+
+
+namespace {
+
+void mathed_parse(MathArray & array, unsigned flags);
+
+unsigned char getuchar(std::istream * is)
+{
+ char c;
+ is->get(c);
+ return static_cast<unsigned char>(c);
+}
+
+const unsigned char LM_TK_OPEN = '{';
+const unsigned char LM_TK_CLOSE = '}';
+
+enum {
+ FLAG_BRACE = 1 << 0, // A { needed //}
+ 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 {
+ ///
+ int i;
+ ///
+ latexkeys const * l;
+} yylval;
+
+
+
+string yytext;
int yylineno;
istream * yyis;
-bool yy_mtextmode= false;
+MathTextCodes yyvarcode;
+
+
+
+struct latex_mathenv_type {
+ char const * name;
+ char const * basename;
+ MathInsetTypes typ;
+ bool numbered;
+ bool ams;
+};
+
+latex_mathenv_type latex_mathenv[] = {
+ {"math", "math", LM_OT_SIMPLE, 0, 0},
+ {"equation*", "equation", LM_OT_EQUATION, 0, 0},
+ {"equation", "equation", LM_OT_EQUATION, 1, 0},
+ {"eqnarray*", "eqnarray", LM_OT_EQNARRAY, 0, 0},
+ {"eqnarray", "eqnarray", LM_OT_EQNARRAY, 1, 0},
+ {"align*", "align", LM_OT_ALIGN, 0, 1},
+ {"align", "align", LM_OT_ALIGN, 1, 1},
+ {"alignat*", "alignat", LM_OT_ALIGNAT, 0, 1},
+ {"alignat", "alignat", LM_OT_ALIGNAT, 1, 1},
+ {"multline*", "multline", LM_OT_MULTLINE, 0, 1},
+ {"multline", "multline", LM_OT_MULTLINE, 1, 1},
+ {"array", "array", LM_OT_MATRIX, 0, 1}
+};
+
+int const latex_mathenv_num = sizeof(latex_mathenv)/sizeof(latex_mathenv[0]);
+
-inline
void mathPrintError(string const & msg)
{
- lyxerr << "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 (isalpha(i))
- lexcode[i] = LexAlpha;
- else if (isdigit(i))
+ for (int i = 0; i <= 255; ++i) {
+ if (isdigit(i))
lexcode[i] = LexDigit;
else if (isspace(i))
lexcode[i] = LexSpace;
else
- lexcode[i] = LexNone;
+ lexcode[i] = LexAlpha;
}
lexcode['\t'] = lexcode['\f'] = lexcode[' '] = LexSpace;
}
-char LexGetArg(char lf, bool accept_spaces = false)
+string lexArg(unsigned char lf, bool accept_spaces = false)
{
- // unsigned char c;
- // char cc;
+ string result;
+ unsigned char c = 0;
while (yyis->good()) {
- char cc;
- yyis->get(cc);
- unsigned char c = cc;
- if (c > ' ') {
- if (!lf)
- lf = c;
- else if (c != lf) {
- lyxerr << "Math parse error: unexpected '"
- << c << "'" << endl;
- return '\0';
- }
+ c = getuchar(yyis);
+ if (!isspace(c))
break;
- }
}
- char const rg =
- (lf == '{') ? '}' :
- ((lf == '[') ? ']'
- : ((lf == '(') ? ')' : 0));
+
+ if (c != lf) {
+ yyis->putback(c);
+ return result;
+ }
+
+ unsigned char rg = 0;
+ if (lf == '{') rg = '}';
+ if (lf == '[') rg = ']';
+ if (lf == '(') rg = ')';
if (!rg) {
- lyxerr << "Math parse error: unknown bracket '"
- << lf << "'" << endl;
- return '\0';
+ lyxerr[Debug::MATHED] << "Math parse error: unknown bracket '"
+ << lf << "'" << endl;
+ return result;
}
- char * p = &yytext[0];
- int bcnt = 1;
+
+ int depth = 1;
do {
- char cc;
- yyis->get(cc);
- unsigned char c = cc;
- if (c == lf) ++bcnt;
- if (c == rg) --bcnt;
- if ((c > ' ' || (c == ' ' && accept_spaces)) && bcnt > 0)
- *(p++) = c;
- } while (bcnt > 0 && yyis->good() && p - yytext.data() < 255);
-
- *p = '\0';
- return rg;
+ unsigned char c = getuchar(yyis);
+ 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(void)
+int yylex()
{
- static int init_done = 0;
+ static bool init_done = false;
- if (!init_done) LexInitCodes();
+ if (!init_done) {
+ lexInit();
+ init_done = true;
+ }
- unsigned char c;
- char cc;
while (yyis->good()) {
- yyis->get(cc);
- c = cc;
+ unsigned char c = getuchar(yyis);
+ //lyxerr << "reading byte: '" << c << "' code: " << lexcode[c] << endl;
- if (yy_mtextmode && c == ' ') {
- yylval.i= ' ';
+ if (yyvarcode == LM_TC_TEXTRM && c == ' ') {
+ yylval.i = ' ';
return LM_TK_ALPHA;
} else if (lexcode[c] == LexNewLine) {
++yylineno;
continue;
} else if (lexcode[c] == LexComment) {
do {
- yyis->get(cc);
- c = cc;
- } while (c != '\n' % yyis->good()); // eat comments
+ c = getuchar(yyis);
+ } while (c != '\n' && yyis->good()); // eat comments
} else if (lexcode[c] == LexDigit
|| lexcode[c] == LexOther
|| lexcode[c] == LexMathSpace) {
yylval.i = c;
return LM_TK_STR;
} else if (lexcode[c] == LexAlpha) {
- yylval.i= c;
+ yylval.i = c;
return LM_TK_ALPHA;
} else if (lexcode[c] == LexBOP) {
- yylval.i= c;
+ yylval.i = c;
return LM_TK_BOP;
} else if (lexcode[c] == LexSelf) {
return c;
} else if (lexcode[c] == LexArgument) {
- yyis->get(cc);
- c = cc;
+ c = getuchar(yyis);
yylval.i = c - '0';
return LM_TK_ARGUMENT;
} else if (lexcode[c] == LexOpen) {
} else if (lexcode[c] == LexClose) {
return LM_TK_CLOSE;
} else if (lexcode[c] == LexESC) {
- yyis->get(cc);
- c = cc;
+ c = getuchar(yyis);
if (c == '\\') {
+ yylval.i = -1;
return LM_TK_NEWLINE;
}
if (c == '(') {
- yylval.i = LM_OT_MIN;
+ yylval.i = LM_OT_SIMPLE;
return LM_TK_BEGIN;
}
if (c == ')') {
- yylval.i = LM_OT_MIN;
+ yylval.i = LM_OT_SIMPLE;
return LM_TK_END;
}
if (c == '[') {
- yylval.i = LM_OT_PAR;
+ yylval.i = LM_OT_EQUATION;
return LM_TK_BEGIN;
}
if (c == ']') {
- yylval.i = LM_OT_PAR;
+ yylval.i = LM_OT_EQUATION;
return LM_TK_END;
}
- if (strchr(latex_special_chars, c)) {
+ if (contains(latex_special_chars, c)) {
yylval.i = c;
return LM_TK_SPECIAL;
}
if (lexcode[c] == LexMathSpace) {
int i;
- for (i = 0; i < 4 && static_cast<int>(c) != latex_mathspace[i][0]; ++i);
+ for (i = 0; i < 4 && static_cast<int>(c) != latex_mathspace[i][0]; ++i)
+ ;
yylval.i = (i < 4) ? i : 0;
return LM_TK_SPACE;
}
- if (lexcode[c] == LexAlpha || lexcode[c] == LexDigit) {
- char * p = &yytext[0];
- while ((lexcode[c] == LexAlpha || lexcode[c] == LexDigit)
- && p - yytext.data() < 255) {
- *p = c;
- yyis->get(cc);
- c = cc;
- ++p;
+ if (lexcode[c] == LexAlpha) {
+ yytext.erase();
+ while (lexcode[c] == LexAlpha) {
+ yytext += c;
+ c = getuchar(yyis);
}
- *p = '\0';
- if (yyis->good()) yyis->putback(c);
- latexkeys const * l = in_word_set (yytext.data(), strlen(yytext.data()));
- if (l) {
- if (l->token == LM_TK_BEGIN || l->token == LM_TK_END) {
- int i;
- LexGetArg('{');
-// for (i = 0; i < 5 && compare(yytext, latex_mathenv[i],
-// strlen(latex_mathenv[i])); ++i);
-
- for (i = 0;
- i < latex_mathenv_num
- && compare(yytext.data(), latex_mathenv[i]); ++i);
- yylval.i = i;
- } else if (l->token == LM_TK_SPACE)
- yylval.i = l->id;
- else
- yylval.l = l;
- return l->token;
- } else {
- yylval.s = yytext.data();
+ if (yyis->good())
+ yyis->putback(c);
+ //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) {
+ string name = lexArg('{');
+ int i = 0;
+ while (i < latex_mathenv_num && name != latex_mathenv[i].name)
+ ++i;
+ yylval.i = i;
+ } else if (l->token == LM_TK_SPACE)
+ yylval.i = l->id;
+ else
+ yylval.l = l;
+ return l->token;
}
}
}
}
-inline
-int parse_align(char * hor, char *)
+MathInset * lastUpDownInset(MathArray & array, bool up, bool down)
{
- int nc = 0;
- for (char * c = hor; c && *c > ' '; ++c) ++nc;
- return nc;
+ MathInset * p = array.back_inset();
+ if (!p || !p->isUpDownInset()) {
+ p = new MathScriptInset(up, down);
+ array.push_back(p);
+ }
+ MathUpDownInset * q = static_cast<MathScriptInset *>(p);
+ if (up)
+ q->up(true);
+ if (down)
+ q->down(down);
+ return p;
}
-// Accent hacks only for 0.12. Stolen from Cursor.
-int accent = 0;
-int nestaccent[8];
-
-inline
-void setAccent(int ac)
+MathBigopInset * lastBigopInset(MathArray & array)
{
- if (ac > 0 && accent < 8) {
- nestaccent[accent++] = ac;
- } else
- accent = 0; // consumed!
+ MathInset * p = array.back_inset();
+ return (p && p->isBigopInset()) ? static_cast<MathBigopInset *>(p) : 0;
}
-MathedInset * doAccent(byte c, MathedTextCodes t)
+
+static bool curr_num;
+static string curr_label;
+
+void mathed_parse_lines(MathInset * inset, int col, bool numbered, bool outmost)
{
- MathedInset * 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]);
+ // save global variables
+ bool saved_num = curr_num;
+ string saved_label = curr_label;
+
+ MathGridInset * p = static_cast<MathGridInset *>(inset);
+ for (int row = 0; true; ++row) {
+ // reset global variables
+ curr_num = numbered;
+ curr_label = string();
+
+ // reading a row
+ int idx = p->nargs() - p->ncols();
+ for (int i = 0; i < col - 1; ++i, ++idx)
+ mathed_parse(p->cell(idx), FLAG_AMPERSAND);
+ mathed_parse(p->cell(idx), FLAG_NEWLINE | FLAG_END);
+
+ if (outmost) {
+ MathMatrixInset * m = static_cast<MathMatrixInset *>(p);
+ m->numbered(row, curr_num);
+ m->label(row, curr_label);
+ }
+
+ // Hack!
+ // no newline
+ if (yylval.i != -1)
+ break;
+
+ p->appendRow();
}
- accent = 0; // consumed!
-
- return ac;
+
+ // restore global variables
+ curr_num = saved_num;
+ curr_label = saved_label;
}
-MathedInset * doAccent(MathedInset * p)
+MathInset * mathed_parse()
{
- MathedInset * 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 = 0;
+ int t = yylex();
+
+ switch (t) {
+ case LM_TK_NEWCOMMAND: {
+ 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 << " nargs: " << narg << "\n";
+ break;
+ }
+
+ case LM_TK_BEGIN: {
+ int i = yylval.i;
+ //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<MathMatrixInset *>(p);
+ switch (typ) {
+
+ case LM_OT_SIMPLE: {
+ curr_num = latex_mathenv[i].numbered;
+ curr_label = string();
+ mathed_parse(m->cell(0), 0);
+ m->numbered(0, curr_num);
+ m->label(0, curr_label);
+ break;
+ }
+
+ case LM_OT_EQUATION: {
+ curr_num = latex_mathenv[i].numbered;
+ curr_label = string();
+ 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(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: {
+ m->halign(lexArg('{'));
+ mathed_parse_lines(m, 2, latex_mathenv[i].numbered, true);
+ break;
+ }
+
+ default:
+ lyxerr[Debug::MATHED] << "1: unknown math environment: " << typ << "\n";
+ }
+
+ p->SetName(latex_mathenv[i].basename);
+
+ break;
+ }
+
+ default:
+ lyxerr[Debug::MATHED] << "2 unknown math environment: " << t << "\n";
}
- accent = 0; // consumed!
-
- return ac;
+
+ return p;
}
-} // namespace anon
+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(MathedArray & array, unsigned flags = 0,
- MathParInset ** mtx = 0)
+
+void mathed_parse(MathArray & array, unsigned flags)
{
int t = yylex();
- int tprev = 0;
bool panic = false;
static int plevel = -1;
- static int size = LM_ST_TEXT;
- MathedTextCodes varcode = LM_TC_VAR;
- MathedInset * binset = 0;
- static MathMacroTemplate * macro = 0;
+ yyvarcode = LM_TC_VAR;
int brace = 0;
- int acc_brace = 0;
- int acc_braces[8];
- MathParInset * mt = (mtx) ? *mtx : 0;
++plevel;
- MathedIter data(&array);
while (t) {
- if ((flags & FLAG_BRACE) && t != LM_TK_OPEN) {
- if ((flags & FLAG_BRACK_ARG) && t == '[') {
+ //lyxerr << "t: " << t << " flags: " << flags << " i: " << yylval.i << " "
+ // << " plevel: " << plevel << " ";
+ //array.dump(lyxerr);
+ //lyxerr << "\n";
+
+ 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 {
- mathPrintError("Expected {. Maybe you forgot to enclose an argument in {}");
- panic = true;
- break;
+ // regard only this single token
+ flags |= FLAG_LEAVE;
}
}
- MathedInsetTypes fractype = LM_OT_FRAC;
+
+ 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:
- if (accent) {
- data.insertInset(doAccent(yylval.i, varcode),
- LM_TC_INSET);
- } else
- data.insert(yylval.i, varcode); //LM_TC_VAR);
+ array.push_back(yylval.i, yyvarcode);
break;
case LM_TK_ARGUMENT:
- if (macro) {
- data.insertInset(macro
- ->getMacroPar(yylval.i - 1),
- LM_TC_INSET);
- } else {
- lyxerr[Debug::MATHED] << "mathed_parse: macro arg outside macro def." << endl;
- }
-
+ array.push_back(new MathMacroArgument(yylval.i));
break;
- case LM_TK_NEWCOMMAND:
- {
- int na = 0;
-
- LexGetArg('{');
- string const name(&yytext[1]);
-
- // ugly trick to be removed soon (lyx3)
- char const c = yyis->peek();
- if (c == '[') {
- LexGetArg('[');
- na = lyx::atoi(yytext.data());
- }
- macro = new MathMacroTemplate(name, na);
- flags = FLAG_BRACE|FLAG_BRACE_LAST;
-
- *mtx = macro;
- macro->setData(array);
- break;
- }
-
case LM_TK_SPECIAL:
- data.insert(yylval.i, LM_TC_SPECIAL);
+ array.push_back(yylval.i, LM_TC_SPECIAL);
break;
case LM_TK_STR:
- if (accent) {
- data.insertInset(doAccent(yylval.i, LM_TC_CONST), LM_TC_INSET);
- } else
- data.insert(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 {
- data.insert('{', LM_TC_TEX);
- }
+ else
+ array.push_back('{', LM_TC_TEX);
break;
case LM_TK_CLOSE:
panic = true;
break;
}
- if (acc_brace && brace == acc_braces[acc_brace - 1] - 1) {
- --acc_brace;
- break;
- }
if (flags & FLAG_BRACE_FONT) {
- varcode = LM_TC_VAR;
- yy_mtextmode = false;
+ yyvarcode = LM_TC_VAR;
flags &= ~FLAG_BRACE_FONT;
break;
}
- if (brace == 0 && (flags & FLAG_BRACE_LAST)) {
- --plevel;
- return;
- } else {
- data.insert('}', 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;
- char const rg = LexGetArg('[');
- if (rg != ']') {
- mathPrintError("Expected ']'");
- panic = true;
- break;
- }
- // if (arg) strcpy(arg, yytext);
- } else
- data.insert('[', LM_TC_CONST);
+ array.push_back('[', LM_TC_CONST);
break;
case ']':
- if (flags & FLAG_BRACK_END) {
- --plevel;
- return;
- } else
- data.insert(']', LM_TC_CONST);
+ if (flags & FLAG_BRACK_END)
+ flags |= FLAG_LEAVE;
+ else
+ array.push_back(']', LM_TC_CONST);
break;
case '^':
- {
- MathParInset * p = new MathParInset(size, "",
- LM_OT_SCRIPT);
- MathedArray ar;
- mathed_parse(ar, FLAG_BRACE_OPT|FLAG_BRACE_LAST);
- p->setData(ar);
- // lyxerr << "UP[" << p->GetStyle() << "]" << endl;
- data.insertInset(p, LM_TC_UP);
+ mathed_parse(lastUpDownInset(array, true, false)->cell(0), FLAG_ITEM);
break;
- }
case '_':
- {
- MathParInset * p = new MathParInset(size, "",
- LM_OT_SCRIPT);
- MathedArray ar;
- mathed_parse(ar, FLAG_BRACE_OPT|FLAG_BRACE_LAST);
- p->setData(ar);
- data.insertInset(p, LM_TC_DOWN);
+ mathed_parse(lastUpDownInset(array, false, true)->cell(1), FLAG_ITEM);
break;
- }
case LM_TK_LIMIT:
- if (binset) {
- binset->SetLimits(bool(yylval.l->id));
- binset = 0;
- }
+ {
+ MathBigopInset * p = lastBigopInset(array);
+ if (p)
+ p->limits(yylval.l->id ? 1 : -1);
break;
+ }
- case '&': // Tab
- if ((flags & FLAG_END) && mt
- && data.getCol()<mt->GetColumns() - 1) {
- data.setNumCols(mt->GetColumns());
- data.insert('T', LM_TC_TAB);
- } else
- mathPrintError("Unexpected tab");
- // debug info. [made that conditional -JMarc]
- if (lyxerr.debugging(Debug::MATHED))
- lyxerr << data.getCol() << " "
- << mt->GetColumns() << endl;
+ case '&':
+ {
+ if (flags & FLAG_AMPERSAND) {
+ flags &= ~FLAG_AMPERSAND;
+ --plevel;
+ return;
+ }
+ lyxerr[Debug::MATHED] << "found tab unexpectedly, array: '" << array << "'\n";
break;
+ }
case LM_TK_NEWLINE:
- if (mt && (flags & FLAG_END)) {
- if (mt->Permit(LMPF_ALLOW_CR)) {
- mt->getRowSt().push_back();
- data.insert('K', LM_TC_CR);
- } else
- mathPrintError("Unexpected newline");
+ {
+ if (flags & FLAG_NEWLINE) {
+ flags &= ~FLAG_NEWLINE;
+ --plevel;
+ return;
}
+ lyxerr[Debug::MATHED] << "found newline unexpectedly, array: '" << array << "'\n";
break;
-
+ }
+
case LM_TK_BIGSYM:
{
- binset = new MathBigopInset(yylval.l->name, yylval.l->id);
- data.insertInset(binset, LM_TC_INSET);
+ array.push_back(new MathBigopInset(yylval.l->name, yylval.l->id));
break;
}
case LM_TK_SYM:
if (yylval.l->id < 256) {
- MathedTextCodes tc = MathIsBOPS(yylval.l->id) ? LM_TC_BOPS: LM_TC_SYMB;
- if (accent) {
- data.insertInset(doAccent(yylval.l->id, tc), LM_TC_INSET);
- } else
- data.insert(yylval.l->id, tc);
- } else {
- MathFuncInset * bg = new MathFuncInset(yylval.l->name);
- if (accent) {
- data.insertInset(doAccent(bg), LM_TC_INSET);
- } else {
-#ifdef WITH_WARNINGS
-#warning This is suspisious! (Lgb)
-#endif
- // it should not take a bool as second arg (Lgb)
- data.insertInset(bg, true);
- }
-
- }
+ MathTextCodes tc = MathIsBOPS(yylval.l->id) ? LM_TC_BOPS : LM_TC_SYMB;
+ array.push_back(yylval.l->id, tc);
+ } else
+ array.push_back(new MathFuncInset(yylval.l->name));
break;
case LM_TK_BOP:
- if (accent) {
- data.insertInset(doAccent(yylval.i, LM_TC_BOP), LM_TC_INSET);
- } else
- data.insert(yylval.i, LM_TC_BOP);
+ array.push_back(yylval.i, LM_TC_BOP);
break;
- case LM_TK_STY:
- if (mt) {
- mt->UserSetSize(yylval.l->id);
- }
- break;
-
case LM_TK_SPACE:
- if (yylval.i >= 0) {
- MathSpaceInset * sp = new MathSpaceInset(yylval.i);
- data.insertInset(sp, LM_TC_INSET);
- }
+ if (yylval.i >= 0)
+ array.push_back(new MathSpaceInset(yylval.i));
break;
case LM_TK_DOTS:
- {
- MathDotsInset * p = new MathDotsInset(yylval.l->name, yylval.l->id);
- data.insertInset(p, LM_TC_INSET);
+ array.push_back(new MathDotsInset(yylval.l->name, yylval.l->id));
break;
- }
+ case LM_TK_CHOOSE:
+ handle_frac(array, "atop");
+ break;
+
case LM_TK_STACK:
- fractype = LM_OT_STACKREL;
- // fallthru
+ handle_frac(array, "stackrel");
+ break;
+
case LM_TK_FRAC:
- {
- MathFracInset * fc = new MathFracInset(fractype);
- MathedArray num;
- mathed_parse(num, FLAG_BRACE|FLAG_BRACE_LAST);
- MathedArray den;
- mathed_parse(den, FLAG_BRACE|FLAG_BRACE_LAST);
- fc->SetData(num, den);
- data.insertInset(fc, LM_TC_ACTIVE_INSET);
+ handle_frac(array, "frac");
break;
- }
-
+
case LM_TK_SQRT:
- {
- MathParInset * rt;
-
- char c;
- yyis->get(c);
-
+ {
+ unsigned char c = getuchar(yyis);
if (c == '[') {
- rt = new MathRootInset(size);
- rt->setArgumentIdx(0);
- MathedArray ar;
- mathed_parse(ar, FLAG_BRACK_END, &rt);
- rt->setData(ar); // I belive that line is not needed (Lgb)
- rt->setArgumentIdx(1);
+ 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);
- rt = new MathSqrtInset(size);
+ array.push_back(new MathSqrtInset);
+ mathed_parse(array.back_inset()->cell(0), FLAG_ITEM);
}
- MathedArray ar;
- mathed_parse(ar, FLAG_BRACE|FLAG_BRACE_LAST, &rt);
- rt->setData(ar); // I belive that this line is not needed (Lgb)
- data.insertInset(rt, LM_TC_ACTIVE_INSET);
break;
}
case LM_TK_LEFT:
{
- int lfd = yylex();
- if (lfd == LM_TK_SYM || lfd == LM_TK_STR || lfd == LM_TK_BOP|| lfd == LM_TK_SPECIAL)
- lfd = (lfd == LM_TK_SYM) ? yylval.l->id: yylval.i;
-// lyxerr << "L[" << lfd << " " << lfd << "]";
- MathedArray ar;
+ int ld = yylex();
+ if (ld == LM_TK_SYM)
+ ld = yylval.l->id;
+ else if (ld == LM_TK_STR || ld == LM_TK_BOP || ld == LM_TK_SPECIAL)
+ ld = yylval.i;
+
+ MathArray ar;
mathed_parse(ar, FLAG_RIGHT);
- int rgd = yylex();
-// lyxerr << "R[" << rgd << "]";
- if (rgd == LM_TK_SYM || rgd == LM_TK_STR || rgd == LM_TK_BOP || rgd == LM_TK_SPECIAL)
- rgd = (rgd == LM_TK_SYM) ? yylval.l->id: yylval.i;
- MathDelimInset * dl = new MathDelimInset(lfd, rgd);
- dl->setData(ar);
- data.insertInset(dl, LM_TC_ACTIVE_INSET);
-// lyxerr << "RL[" << lfd << " " << rgd << "]";
+
+ int rd = yylex();
+ if (rd == LM_TK_SYM)
+ rd = yylval.l->id;
+ else if (rd == LM_TK_STR || rd == LM_TK_BOP || rd == LM_TK_SPECIAL)
+ rd = yylval.i;
+
+ MathDelimInset * dl = new MathDelimInset(ld, rd);
+ dl->cell(0) = ar;
+ array.push_back(dl);
break;
}
if (flags & FLAG_RIGHT) {
--plevel;
return;
- } else {
- mathPrintError("Unmatched right delimiter");
-// panic = true;
}
+ mathPrintError("Unmatched right delimiter");
+// panic = true;
break;
case LM_TK_FONT:
- varcode = static_cast<MathedTextCodes>(yylval.l->id);
- yy_mtextmode = bool(varcode == LM_TC_TEXTRM);
- flags |= (FLAG_BRACE|FLAG_BRACE_FONT);
+ yyvarcode = static_cast<MathTextCodes>(yylval.l->id);
+ flags |= (FLAG_BRACE | FLAG_BRACE_FONT);
break;
- case LM_TK_WIDE:
+ case LM_TK_STY:
+ {
+ lyxerr[Debug::MATHED] << "LM_TK_STY not implemented\n";
+ //MathArray tmp = array;
+ //MathSizeInset * p = new MathSizeInset(MathStyles(yylval.l->id));
+ //array.push_back(p);
+ //mathed_parse(p->cell(0), FLAG_BRACE_FONT);
+ break;
+ }
+
+
+ case LM_TK_DECORATION:
{
- MathDecorationInset * sq = new MathDecorationInset(yylval.l->id,
- size);
- MathedArray ar;
- mathed_parse(ar, FLAG_BRACE|FLAG_BRACE_LAST);
- sq->setData(ar);
- data.insertInset(sq, LM_TC_ACTIVE_INSET);
+ 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:
- if (mt) {
- if (!mt->getRowSt().size())
- mt->getRowSt().push_back();
- mt->getRowSt().back().setNumbered(false);
- }
+ curr_num = false;
break;
case LM_TK_PMOD:
case LM_TK_FUNC:
- if (accent) {
- data.insert(t, LM_TC_CONST);
- } else {
- MathedInset * bg = new MathFuncInset(yylval.l->name);
- data.insertInset(bg, LM_TC_INSET);
- }
+ array.push_back(new MathFuncInset(yylval.l->name));
break;
case LM_TK_FUNCLIM:
- data.insertInset(new MathFuncInset(yylval.l->name, LM_OT_FUNCLIM),
- LM_TC_INSET);
+ array.push_back(new MathFuncInset(yylval.l->name, LM_OT_FUNCLIM));
break;
- case LM_TK_UNDEF:
- {
-
- MathMacro * p =
- MathMacroTable::mathMTable.createMacro(yylval.s);
- if (p) {
- if (accent)
- data.insertInset(doAccent(p), p->getTCode());
- else
- data.insertInset(p, p->getTCode());
- for (int i = 0; p->setArgumentIdx(i); ++i) {
- MathedArray ar;
- mathed_parse(ar, FLAG_BRACE|FLAG_BRACE_LAST);
- p->setData(ar);
- }
- } else {
- MathedInset * q = new MathFuncInset(yylval.s, LM_OT_UNDEF);
- if (accent) {
- data.insertInset(doAccent(q), LM_TC_INSET);
- } else {
- data.insertInset(q, LM_TC_INSET);
- }
- }
+ case LM_TK_UNDEF:
+ if (MathMacroTable::hasTemplate(yytext)) {
+ MathMacro * m = MathMacroTable::cloneTemplate(yytext);
+ for (int i = 0; i < m->nargs(); ++i)
+ mathed_parse(m->cell(i), FLAG_ITEM);
+ array.push_back(m);
+ m->Metrics(LM_ST_TEXT);
+ } else
+ array.push_back(new MathFuncInset(yytext, LM_OT_UNDEF));
break;
- }
case LM_TK_END:
- if (mathed_env != yylval.i && yylval.i != LM_OT_MATRIX)
- mathPrintError("Unmatched environment");
- // debug info [made that conditional -JMarc]
- if (lyxerr.debugging(Debug::MATHED))
- lyxerr << "[" << yylval.i << "]" << endl;
--plevel;
- if (mt) { // && (flags & FLAG_END)) {
- mt->setData(array);
- array.clear();
- }
return;
case LM_TK_BEGIN:
- if (yylval.i == LM_OT_MATRIX) {
- char ar[120];
- char ar2[8];
- ar[0] = ar2[0] = '\0';
- char rg = LexGetArg(0);
- if (rg == ']') {
- strcpy(ar2, yytext.data());
- rg = LexGetArg('{');
- }
- strcpy(ar, yytext.data());
- int const nc = parse_align(ar, ar2);
- MathParInset * mm = new MathMatrixInset(nc, 0);
- mm->SetAlign(ar2[0], ar);
- data.insertInset(mm, LM_TC_ACTIVE_INSET);
- MathedArray dat;
- mathed_parse(dat, FLAG_END, &mm);
- } else if (is_eqn_type(yylval.i)) {
- if (plevel!= 0) {
- mathPrintError("Misplaced environment");
- break;
- }
- if (!mt) {
- mathPrintError("0 paragraph.");
- panic = true;
- }
-
- mathed_env = static_cast<MathedInsetTypes>(yylval.i);
- if (mathed_env != LM_OT_MIN) {
- size = LM_ST_DISPLAY;
- if (is_multiline(mathed_env)) {
- int cols = 1;
- if (is_multicolumn(mathed_env)) {
- if (mathed_env != LM_OT_ALIGNAT &&
- mathed_env != LM_OT_ALIGNATN &&
- yyis->good()) {
- char c;
- yyis->get(c);
- if (c != '%')
- lyxerr << "Math parse error: unexpected '"
- << c << "'" << endl;
- }
- LexGetArg('{');
- cols = strToInt(string(yytext.data()));
- }
- mt = create_multiline(mathed_env, cols);
- if (mtx) *mtx = mt;
- flags |= FLAG_END;
-// data.Insert(' ', LM_TC_TAB);
-// data.Insert(' ', LM_TC_TAB);
-// data.Reset();
- }
- mt->SetStyle(size);
- mt->SetType(mathed_env);
- }
-
- lyxerr[Debug::MATHED] << "MATH BEGIN[" << mathed_env << "]" << endl;
- } else {
-// lyxerr << "MATHCRO[" << yytext << "]";
- MathMacro * p =
- MathMacroTable::mathMTable.createMacro(yytext.data());
- if (p) {
- data.insertInset(p, p->getTCode());
- p->setArgumentIdx(0);
- //mathed_parse(p->GetData(), FLAG_END, reinterpret_cast<MathParInset**>(&p));
- MathedArray dat;
- mathed_parse(dat, FLAG_END, reinterpret_cast<MathParInset**>(&p));
-// for (int i = 0; p->setArgumentIdx(i); ++i)
-// p->SetData(mathed_parse(FLAG_BRACE|FLAG_BRACE_LAST));
- } else
- mathPrintError("Unrecognized environment");
- }
+ {
+ int i = yylval.i;
+ MathInsetTypes typ = latex_mathenv[i].typ;
+
+ if (typ == LM_OT_MATRIX) {
+ 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";
break;
-
+ }
+
case LM_TK_MACRO:
- {
- MathedInset * p =
- MathMacroTable::mathMTable.createMacro(yylval.l->name);
-
- if (p) {
- if (accent) {
- data.insertInset(doAccent(p), LM_TC_INSET);
- } else
- data.insertInset(p, static_cast<MathMacro*>(p)->getTCode());
- }
+ array.push_back(MathMacroTable::cloneTemplate(yylval.l->name));
break;
- }
case LM_TK_LABEL:
- {
- char const rg = LexGetArg('\0', true);
- if (rg != '}') {
- mathPrintError("Expected '{'");
- // debug info
- lyxerr << "[" << yytext.data() << "]" << endl;
- panic = true;
- break;
- }
- if (mt) {
- if (!mt->getRowSt().size())
- mt->getRowSt().push_back();
- mt->getRowSt().back().setLabel(yytext.data());
- } else {
- mathed_label = yytext.data();
- }
- lyxerr[Debug::MATHED] << "Label[" << mathed_label << "]" << endl;
+ curr_label = lexArg('{', true);
break;
- }
default:
mathPrintError("Unrecognized token");
- // debug info
- lyxerr << "[" << t << " " << yytext.data() << "]" << endl;
+ lyxerr[Debug::MATHED] << "[" << t << " " << yytext << "]" << endl;
break;
- } // end of switch
-
- tprev = t;
+
+ } // end of big switch
+
+ if (flags & FLAG_LEAVE) {
+ flags &= ~FLAG_LEAVE;
+ break;
+ }
+
if (panic) {
lyxerr << " Math Panic, expect problems!" << endl;
// Search for the end command.
do {
- t = yylex ();
+ t = yylex();
} while (t != LM_TK_END && t);
} else
- t = yylex ();
-
- if ((flags & FLAG_BRACE_OPT)/* && t!= '^' && t!= '_'*/) {
- flags &= ~FLAG_BRACE_OPT;
- //data.Insert (LM_TC_CLOSE);
- break;
- }
+ t = yylex();
+
}
--plevel;
}
+}
-void mathed_parser_file(istream & is, int lineno)
+
+MathInset * mathed_parse(istream & is)
{
- yyis = &is;
- yylineno = lineno;
- if (!MathMacroTable::built)
- MathMacroTable::mathMTable.builtinMacros();
+ yyis = &is;
+ yylineno = 0;
+ return mathed_parse();
}
-int mathed_parser_lineno()
+MathInset * mathed_parse(LyXLex & lex)
{
- return yylineno;
+ yyis = &lex.getStream();
+ yylineno = lex.GetLineNo();
+
+ MathInset * p = mathed_parse();
+
+ // Update line number
+ lex.setLineNo(yylineno);
+
+ // reading of end_inset
+ while (lex.IsOK()) {
+ lex.nextToken();
+ if (lex.GetString() == "\\end_inset")
+ break;
+ lyxerr[Debug::MATHED] << "InsetFormula::Read: Garbage before \\end_inset,"
+ " or missing \\end_inset!" << endl;
+ }
+
+ return p;
}
+
+//]})