X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2Fmath_parser.C;h=d0d480743b0befe95c551f9f6f58b6fbf92b3650;hb=74124b4bf85af8e902b2ed844ab8b6349073e814;hp=a00cbb681bb6980e97806f2fa68380261614fc89;hpb=88b5d739b5f25ff9012be11620256e98ba3789bb;p=lyx.git diff --git a/src/mathed/math_parser.C b/src/mathed/math_parser.C index a00cbb681b..d0d480743b 100644 --- a/src/mathed/math_parser.C +++ b/src/mathed/math_parser.C @@ -26,39 +26,76 @@ #include "math_parser.h" #include "array.h" #include "math_inset.h" +#include "math_arrayinset.h" +#include "math_bigopinset.h" +#include "math_charinset.h" +#include "math_dotsinset.h" +#include "math_decorationinset.h" +#include "math_deliminset.h" +#include "math_fracinset.h" +#include "math_funcinset.h" +#include "math_funcliminset.h" #include "math_macro.h" #include "math_macrotable.h" #include "math_macrotemplate.h" -#include "math_root.h" -#include "math_arrayinset.h" -#include "math_sqrtinset.h" #include "math_matrixinset.h" -#include "math_accentinset.h" -#include "math_bigopinset.h" -#include "math_funcinset.h" -#include "math_spaceinset.h" +#include "math_noglyphinset.h" +#include "math_rootinset.h" +#include "math_scopeinset.h" +#include "math_sqrtinset.h" +#include "math_scriptinset.h" #include "math_sizeinset.h" -#include "math_dotsinset.h" -#include "math_fracinset.h" -#include "math_deliminset.h" -#include "math_decorationinset.h" +#include "math_spaceinset.h" +#include "math_sqrtinset.h" +#include "math_stackrelinset.h" +#include "math_symbolinset.h" #include "debug.h" #include "mathed/support.h" #include "lyxlex.h" +#include "support/lstrings.h" using std::istream; using std::endl; +namespace { + +MathScriptInset * prevScriptInset(MathArray const & array) +{ + MathInset * p = array.back(); + return (p && p->isScriptInset()) ? static_cast(p) : 0; +} + + +MathInset * lastScriptInset(MathArray & array, bool up, bool down, int limits) +{ + MathScriptInset * p = prevScriptInset(array); + if (!p) { + MathInset * b = array.back(); + if (b && b->isScriptable()) { + p = new MathScriptInset(up, down, b->clone()); + array.pop_back(); + } else { + p = new MathScriptInset(up, down); + } + array.push_back(p); + } + if (up) + p->up(true); + if (down) + p->down(down); + if (limits) + p->limits(limits); + return p; +} + // These are lexical codes, not semantic enum lexcode_enum { LexNone, LexESC, LexAlpha, - LexDigit, LexBOP, // Binary operators or relations - LexMathSpace, LexOpen, LexClose, LexComment, @@ -66,61 +103,30 @@ enum lexcode_enum { LexSpace, LexNewLine, LexOther, + LexMath, LexSelf }; lexcode_enum lexcode[256]; -char const * latex_special_chars = "#$%&_{}"; - - -/// Read TeX into data, flags give stop conditions -void mathed_parse(MathArray & data, unsigned flags); - - -namespace { - -unsigned char getuchar(std::istream * is) -{ - char c; - is->get(c); - return static_cast(c); -} - const unsigned char LM_TK_OPEN = '{'; const unsigned char LM_TK_CLOSE = '}'; enum { FLAG_BRACE = 1 << 0, // A { needed //} - FLAG_BRACE_OPT = 1 << 2, // Optional { - FLAG_BRACE_LAST = 1 << 3, // Last } ends the parsing process - FLAG_BRACK_ARG = 1 << 4, // Optional [ - FLAG_RIGHT = 1 << 5, // Next right ends the parsing process - FLAG_END = 1 << 6, // Next end ends the parsing process - FLAG_BRACE_FONT = 1 << 7, // Next } closes a font - FLAG_BRACK_END = 1 << 9, // Next ] ends the parsing process - FLAG_AMPERSAND = 1 << 10, // Next & ends the parsing process - FLAG_NEWLINE = 1 << 11 // Next \\ ends the parsing process + 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_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; -MathTextCodes yyvarcode; - - - struct latex_mathenv_type { char const * name; char const * basename; @@ -148,17 +154,11 @@ 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; -} - - -void LexInitCodes() +void lexInit() { for (int i = 0; i <= 255; ++i) { if (isdigit(i)) - lexcode[i] = LexDigit; + lexcode[i] = LexOther; else if (isspace(i)) lexcode[i] = LexSpace; else @@ -169,12 +169,10 @@ void LexInitCodes() lexcode['\n'] = LexNewLine; lexcode['%'] = LexComment; lexcode['#'] = LexArgument; + lexcode['$'] = LexMath; lexcode['+'] = lexcode['-'] = lexcode['*'] = lexcode['/'] = lexcode['<'] = lexcode['>'] = lexcode['='] = LexBOP; - lexcode['!'] = lexcode[','] = lexcode[':'] - = lexcode[';'] = LexMathSpace; - lexcode['('] = lexcode[')'] = lexcode['|'] = lexcode['.'] = lexcode['?'] = LexOther; @@ -189,142 +187,197 @@ void LexInitCodes() } -unsigned char LexGetArg(unsigned char lf, bool accept_spaces = false) + +// +// Helper class for parsing +// + + +class Parser { +public: + /// + Parser(LyXLex & lex) : is_(lex.getStream()), lineno_(lex.getLineNo()) {} + /// + Parser(istream & is) : is_(is), lineno_(0) {} + + /// + MathMacroTemplate * parse_macro(); + /// + MathMatrixInset * parse_normal(); + /// + void parse_into(MathArray & array, unsigned flags); + /// + int lineno() const { return lineno_; } + +private: + /// + int yylex(); + /// + string lexArg(unsigned char lf, bool accept_spaces = false); + /// + unsigned char getuchar(); + /// + void error(string const & msg); + /// + void parse_lines(MathGridInset * p, int col, bool numbered, bool outmost); + /// + latexkeys const * read_delim(); + +private: + /// + istream & is_; + /// + int lineno_; + + /// + int ival_; + /// + latexkeys const * lval_; + /// + string sval_; + + /// + bool curr_num_; + /// + string curr_label_; + /// + string curr_skip_; +}; + + +unsigned char Parser::getuchar() +{ + char c = 0; + if (!is_.good()) + lyxerr << "The input stream is not well..." << endl; + is_.get(c); + return static_cast(c); +} + + +string Parser::lexArg(unsigned char lf, bool accept_spaces = false) { - while (yyis->good()) { - unsigned char c = getuchar(yyis); - if (c > ' ') { - if (!lf) - lf = c; - else if (c != lf) { - lyxerr[Debug::MATHED] << "Math parse error: unexpected '" << c << "'" << endl; - return '\0'; - } + string result; + unsigned char c = 0; + while (is_.good()) { + c = getuchar(); + if (!isspace(c)) break; - } } + + if (c != lf) { + is_.putback(c); + return result; + } + unsigned char rg = 0; if (lf == '{') rg = '}'; if (lf == '[') rg = ']'; if (lf == '(') rg = ')'; if (!rg) { - lyxerr[Debug::MATHED] << "Math parse error: unknown bracket '" << lf << "'" << endl; - return '\0'; + lyxerr[Debug::MATHED] << "Math parse error: unknown bracket '" + << lf << "'" << endl; + return result; } - yytext.erase(); - int bcnt = 1; + + int depth = 1; do { - unsigned char c = getuchar(yyis); - if (c == lf) ++bcnt; - if (c == rg) --bcnt; - if ((c > ' ' || (c == ' ' && accept_spaces)) && bcnt > 0) - yytext += c; - } while (bcnt > 0 && yyis->good()); - - return rg; + unsigned char c = getuchar(); + if (c == lf) + ++depth; + if (c == rg) + --depth; + if ((!isspace(c) || (c == ' ' && accept_spaces)) && depth > 0) + result += c; + } while (depth > 0 && is_.good()); + + return result; } -int yylex() +int Parser::yylex() { static bool init_done = false; if (!init_done) { - LexInitCodes(); + lexInit(); init_done = true; } - while (yyis->good()) { - unsigned char c = getuchar(yyis); + while (is_.good()) { + unsigned char c = getuchar(); //lyxerr << "reading byte: '" << c << "' code: " << lexcode[c] << endl; - if (yyvarcode == LM_TC_TEXTRM && c == ' ') { - yylval.i = ' '; - return LM_TK_ALPHA; - } else if (lexcode[c] == LexNewLine) { - ++yylineno; + if (lexcode[c] == LexNewLine) { + ++lineno_; continue; } else if (lexcode[c] == LexComment) { do { - c = getuchar(yyis); - } while (c != '\n' && yyis->good()); // eat comments - } else if (lexcode[c] == LexDigit - || lexcode[c] == LexOther - || lexcode[c] == LexMathSpace) { - yylval.i = c; + c = getuchar(); + } while (c != '\n' && is_.good()); // eat comments + } else if (lexcode[c] == LexOther) { + ival_ = c; return LM_TK_STR; - } else if (lexcode[c] == LexAlpha) { - yylval.i = c; + } else if (lexcode[c] == LexAlpha || lexcode[c] == LexSpace) { + ival_ = c; return LM_TK_ALPHA; } else if (lexcode[c] == LexBOP) { - yylval.i = c; + ival_ = c; return LM_TK_BOP; + } else if (lexcode[c] == LexMath) { + ival_ = 0; + return LM_TK_MATH; } else if (lexcode[c] == LexSelf) { return c; } else if (lexcode[c] == LexArgument) { - c = getuchar(yyis); - yylval.i = c - '0'; + c = getuchar(); + ival_ = c - '0'; return LM_TK_ARGUMENT; } else if (lexcode[c] == LexOpen) { return LM_TK_OPEN; } else if (lexcode[c] == LexClose) { return LM_TK_CLOSE; } else if (lexcode[c] == LexESC) { - c = getuchar(yyis); - if (c == '\\') { - yylval.i = -1; - return LM_TK_NEWLINE; - } - if (c == '(') { - yylval.i = LM_OT_SIMPLE; - return LM_TK_BEGIN; - } - if (c == ')') { - yylval.i = LM_OT_SIMPLE; - return LM_TK_END; - } - if (c == '[') { - yylval.i = LM_OT_EQUATION; - return LM_TK_BEGIN; - } - if (c == ']') { - yylval.i = LM_OT_EQUATION; - return LM_TK_END; - } - 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(c) != latex_mathspace[i][0]; ++i) - ; - yylval.i = (i < 4) ? i : 0; - return LM_TK_SPACE; + c = getuchar(); + //lyxerr << "reading second byte: '" << c << "' code: " << lexcode[c] << endl; + string s; + s += c; + latexkeys const * l = in_word_set(s); + if (l) { + //lyxerr << "found key: " << l << endl; + //lyxerr << "found key name: " << l->name << endl; + //lyxerr << "found key token: " << l->token << endl; + lval_ = l; + ival_ = l->id; + return l->token; } - if (lexcode[c] == LexAlpha || lexcode[c] == LexDigit) { - yytext.erase(); - while (lexcode[c] == LexAlpha || lexcode[c] == LexDigit) { - yytext += c; - c = getuchar(yyis); + if (lexcode[c] == LexAlpha) { + sval_.erase(); + while (lexcode[c] == LexAlpha && is_.good()) { + sval_ += c; + c = getuchar(); } - if (yyis->good()) - yyis->putback(c); - lyxerr[Debug::MATHED] << "reading: text '" << yytext << "'\n"; - latexkeys const * l = in_word_set(yytext); - if (!l) + while (lexcode[c] == LexSpace && is_.good()) + c = getuchar(); + if (lexcode[c] != LexSpace) + is_.putback(c); + + //lyxerr[Debug::MATHED] << "reading: text '" << sval_ << "'\n"; + //lyxerr << "reading: text '" << sval_ << "'\n"; + latexkeys const * l = in_word_set(sval_); + if (!l) return LM_TK_UNDEF; if (l->token == LM_TK_BEGIN || l->token == LM_TK_END) { - LexGetArg('{'); + string name = lexArg('{'); int i = 0; - while (i < latex_mathenv_num && yytext != latex_mathenv[i].name) + while (i < latex_mathenv_num && name != latex_mathenv[i].name) ++i; - yylval.i = i; + ival_ = i; } else if (l->token == LM_TK_SPACE) - yylval.i = l->id; + ival_ = l->id; else - yylval.l = l; + lval_ = l; return l->token; } } @@ -333,472 +386,453 @@ int yylex() } -void handle_frac(MathArray & dat, string const & name) +void Parser::error(string const & msg) { - MathFracInset * p = new MathFracInset(name); - mathed_parse(p->cell(0), FLAG_BRACE | FLAG_BRACE_LAST); - mathed_parse(p->cell(1), FLAG_BRACE | FLAG_BRACE_LAST); - dat.push_back(p); + lyxerr << "Line ~" << lineno_ << ": Math parse error: " << msg << endl; } -MathScriptInset * lastScriptInset(MathArray & array) -{ - MathInset * p = array.back_inset(); - if (!p || !p->isScriptInset()) { - p = new MathScriptInset; - array.push_back(p); - } - return static_cast(p); -} - -} - - - -static bool curr_num; -static string curr_label; - -void mathed_parse_lines(MathInset * inset, int col, bool numbered, bool outmost) +void Parser::parse_lines(MathGridInset * p, int col, bool numbered, bool outmost) { // save global variables - bool saved_num = curr_num; - string saved_label = curr_label; + bool const saved_num = curr_num_; + string const saved_label = curr_label_; - MathGridInset * p = static_cast(inset); for (int row = 0; true; ++row) { // reset global variables - curr_num = numbered; - curr_label = string(); + curr_num_ = numbered; + curr_label_.erase(); // 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); + parse_into(p->cell(idx), FLAG_AMPERSAND); + parse_into(p->cell(idx), FLAG_NEWLINE | FLAG_END); if (outmost) { MathMatrixInset * m = static_cast(p); - m->numbered(row, curr_num); - m->label(row, curr_label); + m->numbered(row, curr_num_); + m->label(row, curr_label_); + if (curr_skip_.size()) { + m->vskip(LyXLength(curr_skip_), row); + curr_skip_.erase(); + } } - // Hack! +#ifdef WITH_WARNINGS +#warning Hack! +#endif // no newline - if (yylval.i != -1) + if (ival_ != -1) break; p->appendRow(); } - // restore global variables - curr_num = saved_num; - curr_label = saved_label; + // restore "global" variables + curr_num_ = saved_num; + curr_label_ = saved_label; } -MathInset * mathed_parse() +MathMacroTemplate * Parser::parse_macro() { - MathInset * p = 0; - int t = yylex(); + if (yylex() != LM_TK_NEWCOMMAND) { + lyxerr << "\\newcommand expected\n"; + return 0; + } - switch (t) { - case LM_TK_NEWCOMMAND: { - LexGetArg('{'); - string name = yytext.substr(1); - - int na = 0; - unsigned char const c = yyis->peek(); - if (c == '[') { - LexGetArg('['); - na = atoi(yytext.c_str()); - } + string name = lexArg('{').substr(1); + string arg = lexArg('['); + int narg = arg.empty() ? 0 : atoi(arg.c_str()); + MathMacroTemplate * p = new MathMacroTemplate(name, narg); + parse_into(p->cell(0), FLAG_BRACE | FLAG_BRACE_LAST); + return p; +} - p = new MathMacroTemplate(name, na); - mathed_parse(p->cell(0), FLAG_BRACE | FLAG_BRACE_LAST); - lyxerr[Debug::MATHED] << "LM_TK_NEWCOMMAND: name: " << name << " na: " << na << "\n"; - break; - } +MathMatrixInset * Parser::parse_normal() +{ + MathMatrixInset * p = 0; + int t = yylex(); + + switch (t) { + case LM_TK_MATH: case LM_TK_BEGIN: { - int i = yylval.i; - lyxerr[Debug::MATHED] << "reading math environment " << i << " " + int i = ival_; + lyxerr[Debug::MATHED] + << "reading math environment " << i << " " << latex_mathenv[i].name << "\n"; MathInsetTypes typ = latex_mathenv[i].typ; p = new MathMatrixInset(typ); + switch (typ) { case LM_OT_SIMPLE: { - curr_num = latex_mathenv[i].numbered; - curr_label = string(); - mathed_parse(p->cell(0), 0); - MathMatrixInset * m = static_cast(p); - m->numbered(0, curr_num); - m->label(0, curr_label); + curr_num_ = latex_mathenv[i].numbered; + curr_label_.erase(); + parse_into(p->cell(0), 0); + p->numbered(0, curr_num_); + p->label(0, curr_label_); break; } case LM_OT_EQUATION: { - curr_num = latex_mathenv[i].numbered; - curr_label = string(); - mathed_parse(p->cell(0), FLAG_END); - MathMatrixInset * m = static_cast(p); - m->numbered(0, curr_num); - m->label(0, curr_label); + curr_num_ = latex_mathenv[i].numbered; + curr_label_.erase(); + parse_into(p->cell(0), FLAG_END); + p->numbered(0, curr_num_); + p->label(0, curr_label_); break; } case LM_OT_EQNARRAY: { - mathed_parse_lines(p, 3, latex_mathenv[i].numbered, true); + parse_lines(p, 3, latex_mathenv[i].numbered, true); + break; + } + + case LM_OT_ALIGN: { + p->halign(lexArg('{')); + parse_lines(p, 2, latex_mathenv[i].numbered, true); break; } case LM_OT_ALIGNAT: { - LexGetArg('{'); - //int c = atoi(yytext.c_str()); - lyxerr[Debug::MATHED] << "LM_OT_ALIGNAT: not implemented\n"; - mathed_parse_lines(p, 2, latex_mathenv[i].numbered, true); - lyxerr[Debug::MATHED] << "LM_OT_ALIGNAT: par: " << *p << "\n"; + p->halign(lexArg('{')); + parse_lines(p, 2, latex_mathenv[i].numbered, true); break; } default: - lyxerr[Debug::MATHED] << "1: unknown math environment: " << typ << "\n"; + 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"; + lyxerr[Debug::MATHED] + << "2 unknown math environment: " << t << "\n"; } return p; } -void mathed_parse(MathArray & array, unsigned flags) +latexkeys const * Parser::read_delim() { - int t = yylex(); - int tprev = 0; - bool panic = false; - static int plevel = -1; - yyvarcode = LM_TC_VAR; - - int brace = 0; + int ld = yylex(); + //lyxerr << "found symbol: " << ld << "\n"; + latexkeys const * l = in_word_set("."); + switch (ld) { + case LM_TK_SYM: + case LM_TK_NOGLYPH: + case LM_TK_SPECIAL: + case LM_TK_BEGIN: { + l = lval_; + //lyxerr << "found key 1: '" << l << "'\n"; + //lyxerr << "found key 1: '" << l->name << "'\n"; + break; + } + case ']': + case '[': { + string s; + s += ld; + l = in_word_set(s); + //lyxerr << "found key 2: '" << l->name << "'\n"; + break; + } + case LM_TK_STR: { + string s; + s += ival_; + l = in_word_set(s); + //lyxerr << "found key 2: '" << l->name << "'\n"; + } + } + return l; +} + + +void Parser::parse_into(MathArray & array, unsigned flags) +{ + MathTextCodes yyvarcode = LM_TC_VAR; + + int t = yylex(); + bool panic = false; + int brace = 0; + int limits = 0; - ++plevel; while (t) { - //lyxerr << "t: " << t << " flags: " << flags; + //lyxerr << "t: " << t << " flags: " << flags << " i: " << ival_ + // << " '" << sval_ << "'\n"; //array.dump(lyxerr); //lyxerr << "\n"; - if ((flags & FLAG_BRACE) && t != LM_TK_OPEN) { - if (!(flags & FLAG_BRACK_ARG) || t != '[') { - mathPrintError( - "Expected {. Maybe you forgot to enclose an argument in {}"); - panic = true; - break; + 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 { + // regard only this single token + flags |= FLAG_LEAVE; } } + if ((flags & FLAG_BRACE) && t != LM_TK_OPEN) { + error( + "Expected {. Maybe you forgot to enclose an argument in {}"); + panic = true; + break; + } + switch (t) { case LM_TK_ALPHA: - array.push_back(yylval.i, yyvarcode); + if (!isspace(ival_) || yyvarcode == LM_TC_TEXTRM) + array.push_back(new MathCharInset(ival_, yyvarcode)); break; - case LM_TK_ARGUMENT: - array.push_back(new MathMacroArgument(yylval.i)); + case LM_TK_ARGUMENT: { + MathMacroArgument * p = new MathMacroArgument(ival_); + //p->code(yyvarcode); + array.push_back(p); break; + } case LM_TK_SPECIAL: - array.push_back(yylval.i, LM_TC_SPECIAL); + array.push_back(new MathCharInset(ival_, LM_TC_SPECIAL)); break; case LM_TK_STR: - array.push_back(yylval.i, LM_TC_CONST); + array.push_back(new MathCharInset(ival_, LM_TC_CONST)); break; case LM_TK_OPEN: - ++brace; - if (flags & FLAG_BRACE_OPT) { - flags &= ~FLAG_BRACE_OPT; - flags |= FLAG_BRACE; - } - - if (flags & FLAG_BRACE) - flags &= ~FLAG_BRACE; - else - array.push_back('{', LM_TC_TEX); + array.push_back(new MathScopeInset); + parse_into(array.back()->cell(0), FLAG_BRACE_LAST); break; case LM_TK_CLOSE: - --brace; - if (brace < 0) { - mathPrintError("Unmatching braces"); - panic = true; - break; - } - if (flags & FLAG_BRACE_FONT) { - yyvarcode = LM_TC_VAR; - flags &= ~FLAG_BRACE_FONT; - break; - } - if (brace == 0 && (flags & FLAG_BRACE_LAST)) { - --plevel; - return; + if (flags & FLAG_BRACE_LAST) { + flags |= FLAG_LEAVE; } - array.push_back('}', LM_TC_TEX); break; case '[': - if (flags & FLAG_BRACK_ARG) { - flags &= ~FLAG_BRACK_ARG; - unsigned char const rg = LexGetArg('['); - if (rg != ']') { - mathPrintError("Expected ']'"); - panic = true; - break; - } - } else - array.push_back('[', LM_TC_CONST); + array.push_back(new MathCharInset('[', LM_TC_CONST)); break; case ']': - if (flags & FLAG_BRACK_END) { - --plevel; - return; - } - array.push_back(']', LM_TC_CONST); + if (flags & FLAG_BRACK_END) + flags |= FLAG_LEAVE; + else + array.push_back(new MathCharInset(']', LM_TC_CONST)); break; case '^': - { - MathArray ar; - mathed_parse(ar, FLAG_BRACE_OPT | FLAG_BRACE_LAST); - MathScriptInset * p = lastScriptInset(array); - p->setData(ar, 0); - p->up(true); + parse_into( + lastScriptInset(array, true, false, limits)->cell(0), FLAG_ITEM); break; - } case '_': - { - MathArray ar; - mathed_parse(ar, FLAG_BRACE_OPT | FLAG_BRACE_LAST); - MathScriptInset * p = lastScriptInset(array); - p->setData(ar, 1); - p->down(true); + parse_into( + lastScriptInset(array, false, true, limits)->cell(1), FLAG_ITEM); break; - } case LM_TK_LIMIT: - { - MathScriptInset * p = lastScriptInset(array); - if (p) - p->limits(yylval.l->id ? 1 : -1); + limits = lval_->id; + //lyxerr << "setting limit to " << limits << "\n"; break; - } case '&': - { if (flags & FLAG_AMPERSAND) { flags &= ~FLAG_AMPERSAND; - --plevel; return; } - lyxerr[Debug::MATHED] << "found tab unexpectedly, array: '" << array << "'\n"; + lyxerr[Debug::MATHED] + << "found tab unexpectedly, array: '" << array << "'\n"; break; - } case LM_TK_NEWLINE: { + curr_skip_ = lexArg('['); if (flags & FLAG_NEWLINE) { flags &= ~FLAG_NEWLINE; - --plevel; return; } - lyxerr[Debug::MATHED] << "found newline unexpectedly, array: '" << array << "'\n"; + lyxerr[Debug::MATHED] + << "found newline unexpectedly, array: '" << array << "'\n"; break; } + case LM_TK_PROTECT: + break; + + case LM_TK_NOGLYPH: + case LM_TK_NOGLYPHB: + limits = 0; + array.push_back(new MathNoglyphInset(lval_)); + break; + case LM_TK_BIGSYM: - { - array.push_back(new MathBigopInset(yylval.l->name, yylval.l->id)); + limits = 0; + array.push_back(new MathBigopInset(lval_)); break; - } - + + case LM_TK_FUNCLIM: + limits = 0; + array.push_back(new MathFuncLimInset(lval_)); + break; + case LM_TK_SYM: - if (yylval.l->id < 256) { - 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)); + limits = 0; + array.push_back(new MathSymbolInset(lval_)); break; case LM_TK_BOP: - array.push_back(yylval.i, LM_TC_BOP); + array.push_back(new MathCharInset(ival_, LM_TC_BOP)); break; case LM_TK_SPACE: - if (yylval.i >= 0) - array.push_back(new MathSpaceInset(yylval.i)); + if (ival_ >= 0) + array.push_back(new MathSpaceInset(ival_)); break; case LM_TK_DOTS: - array.push_back(new MathDotsInset(yylval.l->name, yylval.l->id)); + array.push_back(new MathDotsInset(lval_)); break; - case LM_TK_CHOOSE: - handle_frac(array, "atop"); - break; - case LM_TK_STACK: - handle_frac(array, "stackrel"); + { + MathStackrelInset * p = new MathStackrelInset; + parse_into(p->cell(0), FLAG_ITEM); + parse_into(p->cell(1), FLAG_ITEM); + array.push_back(p); break; + } case LM_TK_FRAC: - handle_frac(array, "frac"); + { + MathFracInset * p = new MathFracInset; + parse_into(p->cell(0), FLAG_ITEM); + parse_into(p->cell(1), FLAG_ITEM); + array.push_back(p); break; + } case LM_TK_SQRT: - { - unsigned char c = getuchar(yyis); + { + unsigned char c = getuchar(); if (c == '[') { - MathRootInset * rt = new MathRootInset; - mathed_parse(rt->cell(0), FLAG_BRACK_END); - mathed_parse(rt->cell(1), FLAG_BRACE | FLAG_BRACE_LAST); - array.push_back(rt); + array.push_back(new MathRootInset); + parse_into(array.back()->cell(0), FLAG_BRACK_END); + parse_into(array.back()->cell(1), FLAG_ITEM); } else { - yyis->putback(c); - MathSqrtInset * sq = new MathSqrtInset; - mathed_parse(sq->cell(0), FLAG_BRACE | FLAG_BRACE_LAST); - array.push_back(sq); + is_.putback(c); + array.push_back(new MathSqrtInset); + parse_into(array.back()->cell(0), FLAG_ITEM); } break; } case LM_TK_LEFT: { - 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; - + latexkeys const * l = read_delim(); 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->setData(ar, 0); + parse_into(ar, FLAG_RIGHT); + latexkeys const * r = read_delim(); + MathDelimInset * dl = new MathDelimInset(l, r); + dl->cell(0) = ar; array.push_back(dl); break; } case LM_TK_RIGHT: - if (flags & FLAG_RIGHT) { - --plevel; + if (flags & FLAG_RIGHT) return; - } - mathPrintError("Unmatched right delimiter"); + error("Unmatched right delimiter"); // panic = true; break; case LM_TK_FONT: - yyvarcode = static_cast(yylval.l->id); - flags |= (FLAG_BRACE | FLAG_BRACE_FONT); + { + MathTextCodes t = static_cast(lval_->id); + MathArray ar; + parse_into(ar, FLAG_ITEM); + for (MathArray::iterator it = ar.begin(); it != ar.end(); ++it) + (*it)->handleFont(t); + array.push_back(ar); + break; + } + + case LM_TK_OLDFONT: + yyvarcode = static_cast(lval_->id); break; case LM_TK_STY: { lyxerr[Debug::MATHED] << "LM_TK_STY not implemented\n"; //MathArray tmp = array; - //MathSizeInset * p = new MathSizeInset(MathStyles(yylval.l->id)); + //MathSizeInset * p = new MathSizeInset(MathStyles(lval_->id)); //array.push_back(p); - //mathed_parse(p->cell(0), FLAG_BRACE_FONT); + //parse_into(p->cell(0), FLAG_BRACE_FONT); break; } - - case LM_TK_WIDE: + case LM_TK_DECORATION: { - MathDecorationInset * p = new MathDecorationInset(yylval.l->id); - mathed_parse(p->cell(0), FLAG_BRACE | FLAG_BRACE_LAST); - array.push_back(p); - break; - } - - case LM_TK_ACCENT: - { - MathAccentInset * p = new MathAccentInset(yylval.l->id); - mathed_parse(p->cell(0), FLAG_BRACE | FLAG_BRACE_LAST); + MathDecorationInset * p = new MathDecorationInset(lval_); + parse_into(p->cell(0), FLAG_ITEM); array.push_back(p); break; } case LM_TK_NONUM: - curr_num = false; + curr_num_ = false; break; - case LM_TK_PMOD: case LM_TK_FUNC: - //if (accent) - // array.push_back(t, LM_TC_CONST); - //else - array.push_back(new MathFuncInset(yylval.l->name)); + array.push_back(new MathSymbolInset(lval_)); break; - case LM_TK_FUNCLIM: - array.push_back(new MathFuncInset(yylval.l->name, LM_OT_FUNCLIM)); - break; - case LM_TK_UNDEF: - if (MathMacroTable::hasTemplate(yytext)) { - MathMacro * m = MathMacroTable::cloneTemplate(yytext); + if (MathMacroTable::hasTemplate(sval_)) { + MathMacro * m = MathMacroTable::cloneTemplate(sval_); for (int i = 0; i < m->nargs(); ++i) - mathed_parse(m->cell(i), FLAG_BRACE_OPT | FLAG_BRACE_LAST); + parse_into(m->cell(i), FLAG_ITEM); array.push_back(m); - m->Metrics(LM_ST_TEXT); + m->metrics(LM_ST_TEXT); } else - array.push_back(new MathFuncInset(yytext, LM_OT_UNDEF)); + array.push_back(new MathFuncInset(sval_)); break; + case LM_TK_MATH: case LM_TK_END: - --plevel; return; case LM_TK_BEGIN: { - int i = yylval.i; + int i = ival_; MathInsetTypes typ = latex_mathenv[i].typ; if (typ == LM_OT_MATRIX) { - string valign = "\0"; - unsigned char rg = LexGetArg(0); - if (rg == ']') { - valign = yytext; - rg = LexGetArg('{'); - } - - string halign = yytext; - MathArrayInset * mm = new MathArrayInset(halign.size(), 1); - valign += 'c'; - mm->valign(valign[0]); - mm->halign(halign); - - mathed_parse_lines(mm, halign.size(), latex_mathenv[i].numbered, false); - array.push_back(mm); - //lyxerr << "read matrix " << *mm << "\n"; + string const valign = lexArg('[') + 'c'; + string const halign = lexArg('{'); + //lyxerr << "valign: '" << valign << "'\n"; + //lyxerr << "halign: '" << halign << "'\n"; + MathArrayInset * m = new MathArrayInset(halign.size(), 1); + m->valign(valign[0]); + m->halign(halign); + + 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"; @@ -806,76 +840,109 @@ void mathed_parse(MathArray & array, unsigned flags) } case LM_TK_MACRO: - array.push_back(MathMacroTable::cloneTemplate(yylval.l->name)); + array.push_back(MathMacroTable::cloneTemplate(lval_->name)); break; case LM_TK_LABEL: - { - unsigned char const rg = LexGetArg('\0', true); - if (rg != '}') { - mathPrintError("Expected '{'"); - // debug info - lyxerr[Debug::MATHED] << "[" << yytext << "]" << endl; - panic = true; - break; - } - //lyxerr << " setting label to " << yytext << "\n"; - curr_label = yytext; + curr_label_ = lexArg('{', true); break; - } default: - mathPrintError("Unrecognized token"); - lyxerr[Debug::MATHED] << "[" << t << " " << yytext << "]" << endl; + error("Unrecognized token"); + lyxerr[Debug::MATHED] << "[" << t << " " << sval_ << "]" << endl; break; } // end of big switch - - tprev = t; + + if (flags & FLAG_LEAVE) { + flags &= ~FLAG_LEAVE; + break; + } + if (panic) { lyxerr << " Math Panic, expect problems!" << endl; // Search for the end command. do { t = yylex(); - } while (t != LM_TK_END && t); - } else + } while (is_.good() && t != LM_TK_END && t); + } else { t = yylex(); - - if (flags & FLAG_BRACE_OPT) { - flags &= ~FLAG_BRACE_OPT; - break; } } - --plevel; } -MathInset * mathed_parse(istream & is) +void parse_end(LyXLex & lex, int lineno) { - yyis = &is; - yylineno = 0; - return mathed_parse(); -} - - -MathInset * mathed_parse(LyXLex & lex) -{ - yyis = &lex.getStream(); - yylineno = lex.GetLineNo(); - - MathInset * p = mathed_parse(); - // Update line number - lex.setLineNo(yylineno); + lex.setLineNo(lineno); // reading of end_inset - while (lex.IsOK()) { + while (lex.isOK()) { lex.nextToken(); - if (lex.GetString() == "\\end_inset") + if (lex.getString() == "\\end_inset") break; lyxerr[Debug::MATHED] << "InsetFormula::Read: Garbage before \\end_inset," " or missing \\end_inset!" << endl; } +} +} // anonymous namespace + + + +MathArray mathed_parse_cell(string const & str) +{ + istringstream is(str.c_str()); + Parser parser(is); + MathArray ar; + parser.parse_into(ar, 0); + return ar; +} + + + +MathMacroTemplate * mathed_parse_macro(string const & str) +{ + istringstream is(str.c_str()); + Parser parser(is); + return parser.parse_macro(); +} + +MathMacroTemplate * mathed_parse_macro(istream & is) +{ + Parser parser(is); + return parser.parse_macro(); +} + +MathMacroTemplate * mathed_parse_macro(LyXLex & lex) +{ + Parser parser(lex); + MathMacroTemplate * p = parser.parse_macro(); + parse_end(lex, parser.lineno()); + return p; +} + + + +MathMatrixInset * mathed_parse_normal(string const & str) +{ + istringstream is(str.c_str()); + Parser parser(is); + return parser.parse_normal(); +} + +MathMatrixInset * mathed_parse_normal(istream & is) +{ + Parser parser(is); + return parser.parse_normal(); +} + +MathMatrixInset * mathed_parse_normal(LyXLex & lex) +{ + Parser parser(lex); + MathMatrixInset * p = parser.parse_normal(); + parse_end(lex, parser.lineno()); return p; } +