* 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
-
-
-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];
-boost::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]);
+
void mathPrintError(string const & msg)
{
+ //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))
+ 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 (
-#if 0
- strchr(latex_special_chars, c)
-#else
- contains(latex_special_chars, c)
-#endif
- ) {
+ 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);
- //lyxerr << "reading: '" << yytext.data() << "'\n";
- latexkeys const * l = in_word_set(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();
+ //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;
}
}
}
}
-#if 0
-int parse_align(char const * hor)
-{
- int nc = 0;
- for (char * c = hor; c && *c > ' '; ++c) ++nc;
- return nc;
-}
-#else
-int parse_align(string const & hor)
+MathInset * lastUpDownInset(MathArray & array, bool up, bool down)
{
- int nc = 0;
- string::const_iterator cit = hor.begin();
- string::const_iterator end = hor.end();
- for (; cit != end; ++cit)
- if (*cit > ' ') ++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;
}
-#endif
-// Accent hacks only for 0.12. Stolen from Cursor.
-int accent = 0;
-int nestaccent[8];
-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)
-{
- 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]);
- }
- accent = 0; // consumed!
-
- return ac;
-}
+static bool curr_num;
+static string curr_label;
-MathedInset * doAccent(MathedInset * p)
+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(p, 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;
}
-void do_insert(MathedIter & it, MathedInset * m, MathedTextCodes t)
+MathInset * mathed_parse()
{
- if (accent)
- it.insertInset(doAccent(m), t);
- else
- it.insertInset(m, t);
+ 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";
+ }
+
+ return p;
}
-void handle_frac(MathedIter & it, MathParInset * & par, MathedInsetTypes t)
+void handle_frac(MathArray & array, string const & name)
{
- MathFracInset fc(t);
- MathedArray num;
- mathed_parse(num, par, FLAG_BRACE|FLAG_BRACE_LAST);
- MathedArray den;
- mathed_parse(den, par, FLAG_BRACE|FLAG_BRACE_LAST);
- fc.SetData(num, den);
- it.insertInset(fc.Clone(), LM_TC_ACTIVE_INSET);
+ MathFracInset * p = new MathFracInset(name);
+ mathed_parse(p->cell(0), FLAG_ITEM);
+ mathed_parse(p->cell(1), FLAG_ITEM);
+ array.push_back(p);
}
-} // namespace anon
-
-/**
- */
-void mathed_parse(MathedArray & array, MathParInset * & par, unsigned flags)
+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;
+ yyvarcode = LM_TC_VAR;
- string last_label; // last label seen
- bool last_numbered = true; // have we seen '\nonumber' lately?
-
int brace = 0;
- int acc_brace = 0;
- int acc_braces[8];
++plevel;
- MathedIter data(&array);
while (t) {
- //lyxerr << "t: " << t << " par: " << par << " flags: " << flags;
- //lyxerr << "label: '" << last_label << "' ";
+ //lyxerr << "t: " << t << " flags: " << flags << " i: " << yylval.i << " "
+ // << " plevel: " << plevel << " ";
//array.dump(lyxerr);
//lyxerr << "\n";
- if ((flags & FLAG_BRACE) && t != LM_TK_OPEN) {
- if ((flags & FLAG_BRACK_ARG) && t == '[') {
+ 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;
}
}
+ 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:
- {
- data.insertInset(new MathMacroArgument(yylval.i), LM_TC_INSET);
+ array.push_back(new MathMacroArgument(yylval.i));
break;
- }
-
- case LM_TK_NEWCOMMAND:
- {
- int na = 0;
-
- LexGetArg('{');
- string name = &yytext[1];
-
- char const c = yyis->peek();
- if (c == '[') {
- LexGetArg('[');
- na = lyx::atoi(yytext.data());
- }
- //lyxerr << "LM_TK_NEWCOMMAND: name: " << name << " " << na << endl;
-#ifdef WITH_WARNINGS
-#warning dirty
-#endif
- par->SetName(name);
- par->xo(na); // abuse xo
- flags = FLAG_BRACE|FLAG_BRACE_LAST;
- 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;
- goto clean_up;
- }
- 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;
- goto clean_up;
- }
- 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, par, 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, par, 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
- data.insert('T', LM_TC_TAB);
-#ifdef WITH_WARNINGS
-#warning look here
-#endif
- data.setNumCols(par->GetColumns());
+ case '&':
+ {
+ if (flags & FLAG_AMPERSAND) {
+ flags &= ~FLAG_AMPERSAND;
+ --plevel;
+ return;
+ }
+ lyxerr[Debug::MATHED] << "found tab unexpectedly, array: '" << array << "'\n";
break;
+ }
case LM_TK_NEWLINE:
- //lyxerr << "reading line " << par->getRowSt().size() << "\n";
- if (flags & FLAG_END) {
- if (par->Permit(LMPF_ALLOW_CR)) {
- par->getRowSt().push_back();
- if (last_numbered) {
- //lyxerr << "line " << par->getRowSt().size() << " not numbered\n";
- par->getRowSt().back().setNumbered(false);
- last_numbered = true;
- }
- if (last_label.size()) {
- //lyxerr << "line " << par->getRowSt().size() << " labeled: "
- // << last_label << endl;
- par->getRowSt().back().setLabel(last_label);
- last_label.erase();
- }
- 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:
- par->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(data, par, LM_OT_ATOP);
+ handle_frac(array, "atop");
break;
case LM_TK_STACK:
- handle_frac(data, par, LM_OT_STACKREL);
+ handle_frac(array, "stackrel");
break;
case LM_TK_FRAC:
- handle_frac(data, par, LM_OT_FRAC);
+ handle_frac(array, "frac");
break;
case LM_TK_SQRT:
- {
- char c;
- yyis->get(c);
-
+ {
+ unsigned char c = getuchar(yyis);
if (c == '[') {
- MathRootInset rt(size);
-
- MathedArray ar1;
- mathed_parse(ar1, par, FLAG_BRACK_END);
- rt.setArgumentIdx(0);
- rt.setData(ar1); // I belive that line is not needed (Lgb)
-
- MathedArray ar2;
- mathed_parse(ar2, par, FLAG_BRACE|FLAG_BRACE_LAST);
-
- rt.setArgumentIdx(1);
- rt.setData(ar2); // I belive that this line is not needed (Lgb)
-
- data.insertInset(rt.Clone(), LM_TC_ACTIVE_INSET);
+ 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);
- MathSqrtInset rt(size);
- MathedArray ar;
- mathed_parse(ar, par, FLAG_BRACE|FLAG_BRACE_LAST);
- rt.setData(ar); // I belive that this line is not needed (Lgb)
- data.insertInset(rt.Clone(), LM_TC_ACTIVE_INSET);
+ array.push_back(new MathSqrtInset);
+ mathed_parse(array.back_inset()->cell(0), FLAG_ITEM);
}
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;
- mathed_parse(ar, par, 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 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 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;
}
case LM_TK_RIGHT:
if (flags & FLAG_RIGHT) {
--plevel;
- goto clean_up;
+ return;
}
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, par, 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:
- //lyxerr << "prepare line " << par->getRowSt().size()
- // << " not numbered\n";
- last_numbered = 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:
- {
- // save this value, yylval.s might get overwritten soon
- const string name = yylval.s;
- //lyxerr << "LM_TK_UNDEF: str = " << name << endl;
- if (MathMacroTable::hasTemplate(name)) {
- MathMacro * m = MathMacroTable::cloneTemplate(name);
- //lyxerr << "Macro: " << m->GetData() << endl;
- for (int i = 0; i < m->nargs(); ++i) {
- MathedArray ar;
- mathed_parse(ar, par, FLAG_BRACE|FLAG_BRACE_LAST);
- m->setData(ar, i);
- }
- do_insert(data, m, m->getTCode());
- } else {
- MathedInset * q = new MathFuncInset(name, LM_OT_UNDEF);
- do_insert(data, 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)) {
- // par.setData(array);
- // array.clear();
- //}
-#ifdef WITH_WARNINGS
-#warning Look here
-#endif
- goto clean_up;
+ return;
case LM_TK_BEGIN:
- if (yylval.i == LM_OT_MATRIX) {
- //lyxerr << "###### Reading LM_OT_MATRIX \n";
-#if 0
- char ar[120];
- char ar2[8];
- ar[0] = ar2[0] = '\0';
-#endif
- char rg = LexGetArg(0);
-#if 1
- string ar2;
-#endif
- if (rg == ']') {
-#if 0
- strcpy(ar2, yytext.data());
-#else
- ar2 = yytext.data();
-#endif
- rg = LexGetArg('{');
- }
-#if 0
- strcpy(ar, yytext.data());
- int const nc = parse_align(ar);
-#else
- string ar(yytext.data());
- int const nc = parse_align(ar);
-#endif
-
- MathParInset * mm = new MathMatrixInset(nc, 0);
- mm->SetAlign(ar2[0], ar);
- MathedArray dat;
- mathed_parse(dat, mm, FLAG_END);
- data.insertInset(mm, LM_TC_ACTIVE_INSET);
- mm->setData(dat);
-
- } else if (is_eqn_type(yylval.i)) {
- //lyxerr << "###### Reading is_eqn_type \n";
- if (plevel!= 0) {
- mathPrintError("Misplaced environment");
- break;
- }
-
- mathed_env = static_cast<MathedInsetTypes>(yylval.i);
- if (mathed_env != LM_OT_MIN) {
- //lyxerr << "###### Reading mathed_env != LM_OT_MIN \n";
- size = LM_ST_DISPLAY;
- if (is_multiline(mathed_env)) {
- //lyxerr << "###### Reading is_multiline(mathed_env) \n";
- int cols = 1;
- if (is_multicolumn(mathed_env)) {
- //lyxerr << "###### Reading is_multicolumn(mathed_env) \n";
- if (mathed_env != LM_OT_ALIGNAT &&
- mathed_env != LM_OT_ALIGNATN &&
- yyis->good()) {
- //lyxerr << "###### Reading is !align\n";
- char c;
- yyis->get(c);
- if (c != '%')
- lyxerr << "Math parse error: unexpected '"
- << c << "'" << endl;
- }
- LexGetArg('{');
- cols = strToInt(string(yytext.data()));
- }
-#ifdef WITH_WARNINGS
-#warning look here
-#endif
- //mt = create_multiline(mathed_env, cols);
- //if (mtx) *mtx = mt;
-
- //MathMatrixInset mat = create_multiline(mathed_env, cols);
- //data.insertInset(mat.Clone(), LM_TC_ACTIVE_INSET);
-
- par = new MathMatrixInset(create_multiline(mathed_env, cols));
- flags |= FLAG_END;
- }
- par->SetStyle(size);
- par->SetType(mathed_env);
- }
-
- lyxerr[Debug::MATHED] << "MATH BEGIN[" << mathed_env << "]" << endl;
- } else {
- MathMacro * m = MathMacroTable::cloneTemplate(yytext.data());
- data.insertInset(m, m->getTCode());
- MathedArray dat;
- mathed_parse(dat, par, FLAG_END);
- }
+ {
+ 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:
- {
- MathMacro * m = MathMacroTable::cloneTemplate(yylval.l->name);
- do_insert(data, m, m->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;
- }
- last_label = yytext.data();
- //lyxerr << "prepare line " << par->getRowSt().size()
- // << " label: " << last_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;
- break;
- }
+ t = yylex();
+
}
--plevel;
+}
-clean_up:
-
- if (last_numbered == false) {
- //lyxerr << "last line " << par->getRowSt().size() << " not numbered\n";
- if (par->getRowSt().size() == 0)
- par->getRowSt().push_back();
- par->getRowSt().back().setNumbered(false);
- }
- if (last_label.size()) {
- //lyxerr << "last line " << par->getRowSt().size() << " labeled: "
- // << last_label << endl;
- if (par->getRowSt().size() == 0)
- par->getRowSt().push_back();
- par->getRowSt().back().setLabel(last_label);
- }
}
-void mathed_parser_file(istream & is, int lineno)
+MathInset * mathed_parse(istream & is)
{
- yyis = &is;
- yylineno = lineno;
+ 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;
}
+
+//]})