Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

Parser Class Reference

#include <texparser.h>

List of all members.

Public Types

typedef MathInset::mode_type mode_type

Public Methods

 Parser (LyXLex &lex)
 Parser (istream &is)
bool parse (MathAtom &at)
void parse (MathArray &array, unsigned flags, mode_type mode)
void parse1 (MathGridInset &grid, unsigned flags, mode_type mode, bool numbered)
MathArray parse (unsigned flags, mode_type mode)
int lineno () const
void putback ()
 Parser (std::istream &is)
 Parser (std::string const &s)
int lineno () const
void putback ()
void dump () const
 dump contents to screen. More...

std::string getArg (char left, char right)
std::string getOpt ()
 getArg('[', ']') including the brackets. More...

char getChar ()
void error (std::string const &msg)
void tokenize (std::istream &is)
void push_back (Token const &t)
void pop_back ()
Token const & prev_token () const
Token const & next_token () const
Token const & get_token ()
void skip_spaces ()
 skips spaces if any. More...

void lex (std::string const &s)
bool good () const
std::string verbatim_item ()
std::string verbatimOption ()
void setCatCode (char c, CatCode cat)
CatCode getCatCode (char c) const

Public Attributes

std::vector< Tokentokens_

Private Methods

void parse2 (MathAtom &at, unsigned flags, mode_type mode, bool numbered)
string getArg (char left, char right)
 get arg delimited by 'left' and 'right'. More...

char getChar ()
void error (string const &msg)
void dump () const
 dump contents to screen. More...

void tokenize (istream &is)
void tokenize (string const &s)
void skipSpaceTokens (istream &is, char c)
void push_back (Token const &t)
void pop_back ()
Token const & prevToken () const
Token const & nextToken () const
Token const & getToken ()
void skipSpaces ()
 skips spaces if any. More...

void lex (string const &s)
bool good () const
string parse_verbatim_item ()
string parse_verbatim_option ()

Private Attributes

int lineno_
vector< Tokentokens_
unsigned pos_


Member Typedef Documentation

typedef MathInset::mode_type Parser::mode_type
 

Definition at line 220 of file math_parser.C.


Constructor & Destructor Documentation

Parser::Parser LyXLex   lex
 

Definition at line 288 of file math_parser.C.

References tokenize.

Referenced by operator<<.

00289         : lineno_(lexer.getLineNo()), pos_(0)
00290 {
00291         tokenize(lexer.getStream());
00292         lexer.eatLine();
00293 }

Parser::Parser istream &    is
 

Definition at line 296 of file math_parser.C.

References tokenize.

00297         : lineno_(0), pos_(0)
00298 {
00299         tokenize(is);
00300 }

Parser::Parser std::istream &    is
 

Parser::Parser std::string const &    s
 

Definition at line 127 of file texparser.C.

References tokenize.

00128         : lineno_(0), pos_(0)
00129 {
00130         istringstream is(s);
00131         tokenize(is);
00132 }


Member Function Documentation

void Parser::dump   const
 

dump contents to screen.

void Parser::dump   const [private]
 

dump contents to screen.

Definition at line 492 of file math_parser.C.

References pos_, and tokens_.

Referenced by error, parse1, and tokenize.

00493 {
00494         lyxerr << "\nTokens: ";
00495         for (unsigned i = 0; i < tokens_.size(); ++i) {
00496                 if (i == pos_)
00497                         lyxerr << " <#> ";
00498                 lyxerr << tokens_[i];
00499         }
00500         lyxerr << " pos: " << pos_ << "\n";
00501 }

void Parser::error std::string const &    msg
 

void Parser::error string const &    msg [private]
 

Definition at line 504 of file math_parser.C.

References dump, and lineno_.

Referenced by getChar, parse1, parse_math, parse_table, parse_text, tokenize, and verbatim_item.

00505 {
00506         lyxerr << "Line ~" << lineno_ << ": Math parse error: " << msg << endl;
00507         dump();
00508         //exit(1);
00509 }

Token const & Parser::get_token  
 

Definition at line 161 of file texparser.C.

References good, pos_, and tokens_.

Referenced by handle_colalign, handle_comment, handle_tabular, parse_math, parse_preamble, parse_table, parse_text, read_hlines, skip_braces, skip_spaces, verbatim_item, and verbatimOption.

00162 {
00163         static const Token dummy;
00164         //cerr << "looking at token " << tokens_[pos_] << " pos: " << pos_ << '\n';
00165         return good() ? tokens_[pos_++] : dummy;
00166 }

std::string Parser::getArg char    left,
char    right
 

string Parser::getArg char    left,
char    right
[private]
 

get arg delimited by 'left' and 'right'.

Definition at line 364 of file math_parser.C.

References getChar, good, putback, and skipSpaces.

Referenced by getOpt, parse1, parse_math, parse_preamble, parse_table, and parse_text.

00365 {
00366         skipSpaces();
00367 
00368         string result;
00369         char c = getChar();
00370 
00371         if (c != left)
00372                 putback();
00373         else
00374                 while ((c = getChar()) != right && good())
00375                         result += c;
00376 
00377         return result;
00378 }

CatCode Parser::getCatCode char    c const
 

Definition at line 375 of file texparser.C.

References theCatcode.

00376 {
00377         return theCatcode[c];
00378 }

char Parser::getChar  
 

char Parser::getChar   [private]
 

Definition at line 356 of file math_parser.C.

References error, good, pos_, and tokens_.

Referenced by getArg.

00357 {
00358         if (!good())
00359                 error("The input stream is not well...");
00360         return tokens_[pos_++].character();
00361 }

string Parser::getOpt  
 

getArg('[', ']') including the brackets.

Definition at line 220 of file texparser.C.

References getArg.

Referenced by handle_tabular, parse_preamble, and parse_text.

00221 {
00222         string const res = getArg('[', ']');
00223         return res.size() ? '[' + res + ']' : string();
00224 }

Token const & Parser::getToken   [private]
 

Definition at line 329 of file math_parser.C.

References good, pos_, and tokens_.

Referenced by parse1, parse_verbatim_item, parse_verbatim_option, and skipSpaces.

00330 {
00331         static const Token dummy;
00332         //lyxerr << "looking at token " << tokens_[pos_] << " pos: " << pos_ << '\n';
00333         return good() ? tokens_[pos_++] : dummy;
00334 }

bool Parser::good   const
 

bool Parser::good   const [private]
 

Definition at line 350 of file math_parser.C.

References pos_, and tokens_.

Referenced by get_token, getArg, getChar, getToken, handle_colalign, handle_comment, handle_tabular, next_token, nextToken, parse1, parse_math, parse_preamble, parse_table, parse_text, parse_verbatim_item, parse_verbatim_option, read_hlines, verbatim_item, and verbatimOption.

00351 {
00352         return pos_ < tokens_.size();
00353 }

void Parser::lex std::string const &    s
 

void Parser::lex string const &    s [private]
 

int Parser::lineno   const [inline]
 

Definition at line 104 of file texparser.h.

References lineno_.

00104 { return lineno_; }

int Parser::lineno   const [inline]
 

Definition at line 237 of file math_parser.C.

References lineno_.

00237 { return lineno_; }

Token const & Parser::next_token   const
 

Definition at line 154 of file texparser.C.

References good, pos_, and tokens_.

Referenced by handle_tabular, parse_preamble, parse_text, read_hlines, skip_braces, skip_spaces, verbatim_item, and verbatimOption.

00155 {
00156         static const Token dummy;
00157         return good() ? tokens_[pos_] : dummy;
00158 }

Token const & Parser::nextToken   const [private]
 

Definition at line 322 of file math_parser.C.

References good, pos_, and tokens_.

Referenced by parse1, parse_verbatim_item, parse_verbatim_option, and skipSpaces.

00323 {
00324         static const Token dummy;
00325         return good() ? tokens_[pos_] : dummy;
00326 }

MathArray Parser::parse unsigned    flags,
mode_type    mode
 

Definition at line 568 of file math_parser.C.

References mode_type, and parse.

00569 {
00570         MathArray ar;
00571         parse(ar, flags, mode);
00572         return ar;
00573 }

void Parser::parse MathArray   array,
unsigned    flags,
mode_type    mode
 

Definition at line 576 of file math_parser.C.

References MathNestInset::cell, mode_type, and parse1.

00577 {
00578         MathGridInset grid(1, 1);
00579         parse1(grid, flags, mode, false);
00580         array = grid.cell(0);
00581 }

bool Parser::parse MathAtom   at
 

Definition at line 512 of file math_parser.C.

References skipSpaces, and MathInset::UNDECIDED_MODE.

Referenced by parse, and parse1.

00513 {
00514         skipSpaces();
00515         MathArray ar;
00516         parse(ar, false, MathInset::UNDECIDED_MODE);
00517         if (ar.size() != 1 || ar.front()->getType() == "none") {
00518                 lyxerr << "unusual contents found: " << ar << endl;
00519                 at = MathAtom(new MathParInset(ar));
00520                 //if (at->nargs() > 0)
00521                 //      at.nucleus()->cell(0) = ar;
00522                 //else
00523                 //      lyxerr << "unusual contents found: " << ar << endl;
00524                 return true;
00525         }
00526         at = ar[0];
00527         return true;
00528 }

void Parser::parse1 MathGridInset   grid,
unsigned    flags,
mode_type    mode,
bool    numbered
 

Definition at line 591 of file math_parser.C.

References MathGridInset::addCol, MathGridInset::addRow, MathArray::append, asArray, MathInset::asHullInset, asMode, Token::asString, lyx::support::atoi, Token::cat, catActive, catAlign, catBegin, catComment, catEnd, catLetter, catMath, catNewline, catOther, catParameter, catSpace, catSub, catSuper, MathInset::cell, MathNestInset::cell, MathGridInset::cellinfo, Token::character, InsetBase::col_type, lyx::count, createMathInset, Token::cs, dump, MathArray::dump, error, latexkeys::extra, extractNumber, FLAG_BRACE_LAST, FLAG_BRACED, FLAG_BRACK_LAST, FLAG_END, FLAG_EQUATION, FLAG_ITEM, FLAG_LEAVE, FLAG_OPTION, FLAG_RIGHT, FLAG_SIMPLE, FLAG_SIMPLE2, getArg, getToken, good, InsetBase::idx_type, in_word_set, MathGridInset::index, latexkeys::inset, isValidLength, MathHullInset::label, MathScriptInset::limits, MathInset::MATH_MODE, MathInset::mode_type, mode_type, MathGridInset::ncols, nextToken, MathGridInset::nrows, MathAtom::nucleus, MathHullInset::numbered, parse, parse2, parse_verbatim_item, parse_verbatim_option, putback, InsetBase::row_type, MathGridInset::rowinfo, skipSpaces, stared, lyx_gui::start, MathInset::TEXT_MODE, MathInset::UNDECIDED_MODE, MathXYArrowInset::up_, and MathGridInset::vcrskip.

Referenced by parse, and parse2.

00593 {
00594         int limits = 0;
00595         MathGridInset::row_type cellrow = 0;
00596         MathGridInset::col_type cellcol = 0;
00597         MathArray * cell = &grid.cell(grid.index(cellrow, cellcol));
00598 
00599         if (grid.asHullInset())
00600                 grid.asHullInset()->numbered(cellrow, numbered);
00601 
00602         //dump();
00603         //lyxerr << " flags: " << flags << "\n";
00604         //lyxerr << " mode: " << mode  << "\n";
00605         //lyxerr << "grid: " << grid << endl;
00606 
00607         while (good()) {
00608                 Token const & t = getToken();
00609 
00610 #ifdef FILEDEBUG
00611                 lyxerr << "t: " << t << " flags: " << flags << "\n";
00612                 lyxerr << "mode: " << mode  << "\n";
00613                 cell->dump();
00614                 lyxerr << "\n";
00615 #endif
00616 
00617                 if (flags & FLAG_ITEM) {
00618 
00619                 if (t.cat() == catBegin) {
00620                                 // skip the brace and collect everything to the next matching
00621                                 // closing brace
00622                                 parse1(grid, FLAG_BRACE_LAST, mode, numbered);
00623                                 return;
00624                         }
00625 
00626                         // handle only this single token, leave the loop if done
00627                         flags = FLAG_LEAVE;
00628                 }
00629 
00630 
00631                 if (flags & FLAG_BRACED) {
00632                         if (t.cat() == catSpace)
00633                                 continue;
00634 
00635                         if (t.cat() != catBegin) {
00636                                 error("opening brace expected");
00637                                 return;
00638                         }
00639 
00640                         // skip the brace and collect everything to the next matching
00641                         // closing brace
00642                         flags = FLAG_BRACE_LAST;
00643                 }
00644 
00645 
00646                 if (flags & FLAG_OPTION) {
00647                         if (t.cat() == catOther && t.character() == '[') {
00648                                 MathArray ar;
00649                                 parse(ar, FLAG_BRACK_LAST, mode);
00650                                 cell->append(ar);
00651                         } else {
00652                                 // no option found, put back token and we are done
00653                                 putback();
00654                         }
00655                         return;
00656                 }
00657 
00658                 //
00659                 // cat codes
00660                 //
00661                 if (t.cat() == catMath) {
00662                         if (mode != MathInset::MATH_MODE) {
00663                                 // we are inside some text mode thingy, so opening new math is allowed
00664                                 Token const & n = getToken();
00665                                 if (n.cat() == catMath) {
00666                                         // TeX's $$...$$ syntax for displayed math
00667                                         cell->push_back(MathAtom(new MathHullInset("equation")));
00668                                         parse2(cell->back(), FLAG_SIMPLE, MathInset::MATH_MODE, false);
00669                                         getToken(); // skip the second '$' token
00670                                 } else {
00671                                         // simple $...$  stuff
00672                                         putback();
00673                                         cell->push_back(MathAtom(new MathHullInset("simple")));
00674                                         parse2(cell->back(), FLAG_SIMPLE, MathInset::MATH_MODE, false);
00675                                 }
00676                         }
00677 
00678                         else if (flags & FLAG_SIMPLE) {
00679                                 // this is the end of the formula
00680                                 return;
00681                         }
00682 
00683                         else {
00684                                 error("something strange in the parser\n");
00685                                 break;
00686                         }
00687                 }
00688 
00689                 else if (t.cat() == catLetter)
00690                         cell->push_back(MathAtom(new MathCharInset(t.character())));
00691 
00692                 else if (t.cat() == catSpace && mode != MathInset::MATH_MODE) {
00693                         if (cell->empty() || cell->back()->getChar() != ' ')
00694                                 cell->push_back(MathAtom(new MathCharInset(t.character())));
00695                 }
00696 
00697                 else if (t.cat() == catNewline && mode != MathInset::MATH_MODE) {
00698                         if (cell->empty() || cell->back()->getChar() != ' ')
00699                                 cell->push_back(MathAtom(new MathCharInset(' ')));
00700                 }
00701 
00702                 else if (t.cat() == catParameter) {
00703                         Token const & n = getToken();
00704                         cell->push_back(MathAtom(new MathMacroArgument(n.character()-'0')));
00705                 }
00706 
00707                 else if (t.cat() == catActive)
00708                         cell->push_back(MathAtom(new MathCharInset(t.character())));
00709 
00710                 else if (t.cat() == catBegin) {
00711                         MathArray ar;
00712                         parse(ar, FLAG_BRACE_LAST, mode);
00713                         // do not create a BraceInset if they were written by LyX
00714                         // this helps to keep the annoyance of  "a choose b"  to a minimum
00715                         if (ar.size() == 1 && ar[0]->extraBraces())
00716                                 cell->append(ar);
00717                         else
00718                                 cell->push_back(MathAtom(new MathBraceInset(ar)));
00719                 }
00720 
00721                 else if (t.cat() == catEnd) {
00722                         if (flags & FLAG_BRACE_LAST)
00723                                 return;
00724                         error("found '}' unexpectedly");
00725                         //lyx::Assert(0);
00726                         //add(cell, '}', LM_TC_TEX);
00727                 }
00728 
00729                 else if (t.cat() == catAlign) {
00730                         ++cellcol;
00731                         //lyxerr << " column now " << cellcol << " max: " << grid.ncols() << "\n";
00732                         if (cellcol == grid.ncols()) {
00733                                 //lyxerr << "adding column " << cellcol << "\n";
00734                                 grid.addCol(cellcol - 1);
00735                         }
00736                         cell = &grid.cell(grid.index(cellrow, cellcol));
00737                 }
00738 
00739                 else if (t.cat() == catSuper || t.cat() == catSub) {
00740                         bool up = (t.cat() == catSuper);
00741                         // we need no new script inset if the last thing was a scriptinset,
00742                         // which has that script already not the same script already
00743                         if (!cell->size())
00744                                 cell->push_back(MathAtom(new MathScriptInset(up)));
00745                         else if (cell->back()->asScriptInset() &&
00746                                         !cell->back()->asScriptInset()->has(up))
00747                                 cell->back().nucleus()->asScriptInset()->ensure(up);
00748                         else if (cell->back()->asScriptInset())
00749                                 cell->push_back(MathAtom(new MathScriptInset(up)));
00750                         else
00751                                 cell->back() = MathAtom(new MathScriptInset(cell->back(), up));
00752                         MathScriptInset * p = cell->back().nucleus()->asScriptInset();
00753                         // special handling of {}-bases
00754                         // is this always correct?
00755                         // It appears that this is wrong (Dekel)
00756                         //if (p->nuc().size() == 1 && p->nuc().back()->asNestInset() &&
00757                         //    p->nuc().back()->extraBraces())
00758                         //      p->nuc() = p->nuc().back()->asNestInset()->cell(0);
00759                         parse(p->cell(up), FLAG_ITEM, mode);
00760                         if (limits) {
00761                                 p->limits(limits);
00762                                 limits = 0;
00763                         }
00764                 }
00765 
00766                 else if (t.character() == ']' && (flags & FLAG_BRACK_LAST)) {
00767                         //lyxerr << "finished reading option\n";
00768                         return;
00769                 }
00770 
00771                 else if (t.cat() == catOther)
00772                         cell->push_back(MathAtom(new MathCharInset(t.character())));
00773 
00774                 else if (t.cat() == catComment) {
00775                         string s;
00776                         while (good()) {
00777                                 Token const & t = getToken();
00778                                 if (t.cat() == catNewline)
00779                                         break;
00780                                 s += t.asString();
00781                         }
00782                         cell->push_back(MathAtom(new MathCommentInset(s)));
00783                         skipSpaces();
00784                 }
00785 
00786                 //
00787                 // control sequences
00788                 //
00789 
00790                 else if (t.cs() == "lyxlock") {
00791                         if (cell->size())
00792                                 cell->back().nucleus()->lock(true);
00793                 }
00794 
00795                 else if (t.cs() == "def" ||
00796                         t.cs() == "newcommand" ||
00797                         t.cs() == "renewcommand")
00798                 {
00799                         string const type = t.cs();
00800                         string name;
00801                         int nargs = 0;
00802                         if (t.cs() == "def") {
00803                                 // get name
00804                                 name = getToken().cs();
00805 
00806                                 // read parameter
00807                                 string pars;
00808                                 while (good() && nextToken().cat() != catBegin) {
00809                                         pars += getToken().cs();
00810                                         ++nargs;
00811                                 }
00812                                 nargs /= 2;
00813                                 //lyxerr << "read \\def parameter list '" << pars << "'\n";
00814 
00815                         } else { // t.cs() == "newcommand" || t.cs() == "renewcommand"
00816 
00817                                 if (getToken().cat() != catBegin) {
00818                                         error("'{' in \\newcommand expected (1) \n");
00819                                         return;
00820                                 }
00821 
00822                                 name = getToken().cs();
00823 
00824                                 if (getToken().cat() != catEnd) {
00825                                         error("'}' in \\newcommand expected\n");
00826                                         return;
00827                                 }
00828 
00829                                 string arg  = getArg('[', ']');
00830                                 if (!arg.empty())
00831                                         nargs = atoi(arg.c_str());
00832 
00833                         }
00834 
00835                         MathArray ar1;
00836                         parse(ar1, FLAG_ITEM, MathInset::UNDECIDED_MODE);
00837 
00838                         // we cannot handle recursive stuff at all
00839                         //MathArray test;
00840                         //test.push_back(createMathInset(name));
00841                         //if (ar1.contains(test)) {
00842                         //      error("we cannot handle recursive macros at all.\n");
00843                         //      return;
00844                         //}
00845 
00846                         // is a version for display attached?
00847                         skipSpaces();
00848                         MathArray ar2;
00849                         if (nextToken().cat() == catBegin)
00850                                 parse(ar2, FLAG_ITEM, MathInset::MATH_MODE);
00851 
00852                         cell->push_back(MathAtom(new MathMacroTemplate(name, nargs, type,
00853                                 ar1, ar2)));
00854                 }
00855 
00856                 else if (t.cs() == "(") {
00857                         cell->push_back(MathAtom(new MathHullInset("simple")));
00858                         parse2(cell->back(), FLAG_SIMPLE2, MathInset::MATH_MODE, false);
00859                 }
00860 
00861                 else if (t.cs() == "[") {
00862                         cell->push_back(MathAtom(new MathHullInset("equation")));
00863                         parse2(cell->back(), FLAG_EQUATION, MathInset::MATH_MODE, false);
00864                 }
00865 
00866                 else if (t.cs() == "protect")
00867                         // ignore \\protect, will hopefully be re-added during output
00868                         ;
00869 
00870                 else if (t.cs() == "end") {
00871                         if (flags & FLAG_END) {
00872                                 // eat environment name
00873                                 //string const name =
00874                                 getArg('{', '}');
00875                                 // FIXME: check that we ended the correct environment
00876                                 return;
00877                         }
00878                         error("found 'end' unexpectedly");
00879                 }
00880 
00881                 else if (t.cs() == ")") {
00882                         if (flags & FLAG_SIMPLE2)
00883                                 return;
00884                         error("found '\\)' unexpectedly");
00885                 }
00886 
00887                 else if (t.cs() == "]") {
00888                         if (flags & FLAG_EQUATION)
00889                                 return;
00890                         error("found '\\]' unexpectedly");
00891                 }
00892 
00893                 else if (t.cs() == "\\") {
00894                         grid.vcrskip(LyXLength(getArg('[', ']')), cellrow);
00895                         ++cellrow;
00896                         cellcol = 0;
00897                         if (cellrow == grid.nrows())
00898                                 grid.addRow(cellrow - 1);
00899                         if (grid.asHullInset())
00900                                 grid.asHullInset()->numbered(cellrow, numbered);
00901                         cell = &grid.cell(grid.index(cellrow, cellcol));
00902                 }
00903 
00904 #if 0
00905                 else if (t.cs() == "multicolumn") {
00906                         // extract column count and insert dummy cells
00907                         MathArray count;
00908                         parse(count, FLAG_ITEM, mode);
00909                         int cols = 1;
00910                         if (!extractNumber(count, cols)) {
00911                                 lyxerr << " can't extract number of cells from " << count << "\n";
00912                         }
00913                         // resize the table if necessary
00914                         for (int i = 0; i < cols; ++i) {
00915                                 ++cellcol;
00916                                 if (cellcol == grid.ncols()) {
00917                                         //lyxerr << "adding column " << cellcol << "\n";
00918                                         grid.addCol(cellcol - 1);
00919                                 }
00920                                 cell = &grid.cell(grid.index(cellrow, cellcol));
00921                                 // mark this as dummy
00922                                 grid.cellinfo(grid.index(cellrow, cellcol)).dummy_ = true;
00923                         }
00924                         // the last cell is the real thng, not a dummy
00925                         grid.cellinfo(grid.index(cellrow, cellcol)).dummy_ = false;
00926 
00927                         // read special alignment
00928                         MathArray align;
00929                         parse(align, FLAG_ITEM, mode);
00930                         //grid.cellinfo(grid.index(cellrow, cellcol)).align_ = extractString(align);
00931 
00932                         // parse the remaining contents into the "real" cell
00933                         parse(*cell, FLAG_ITEM, mode);
00934                 }
00935 #endif
00936 
00937                 else if (t.cs() == "limits")
00938                         limits = 1;
00939 
00940                 else if (t.cs() == "nolimits")
00941                         limits = -1;
00942 
00943                 else if (t.cs() == "nonumber") {
00944                         if (grid.asHullInset())
00945                                 grid.asHullInset()->numbered(cellrow, false);
00946                 }
00947 
00948                 else if (t.cs() == "number") {
00949                         if (grid.asHullInset())
00950                                 grid.asHullInset()->numbered(cellrow, true);
00951                 }
00952 
00953                 else if (t.cs() == "hline") {
00954                         grid.rowinfo(cellrow).lines_ ++;
00955                 }
00956 
00957                 else if (t.cs() == "sqrt") {
00958                         MathArray ar;
00959                         parse(ar, FLAG_OPTION, mode);
00960                         if (ar.size()) {
00961                                 cell->push_back(MathAtom(new MathRootInset));
00962                                 cell->back().nucleus()->cell(0) = ar;
00963                                 parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode);
00964                         } else {
00965                                 cell->push_back(MathAtom(new MathSqrtInset));
00966                                 parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
00967                         }
00968                 }
00969 
00970                 else if (t.cs() == "xrightarrow" || t.cs() == "xleftarrow") {
00971                         cell->push_back(createMathInset(t.cs()));
00972                         parse(cell->back().nucleus()->cell(1), FLAG_OPTION, mode);
00973                         parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
00974                 }
00975 
00976                 else if (t.cs() == "ref" || t.cs() == "prettyref" ||
00977                                 t.cs() == "pageref" || t.cs() == "vpageref" || t.cs() == "vref") {
00978                         cell->push_back(MathAtom(new RefInset(t.cs())));
00979                         parse(cell->back().nucleus()->cell(1), FLAG_OPTION, mode);
00980                         parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
00981                 }
00982 
00983                 else if (t.cs() == "left") {
00984                         skipSpaces();
00985                         string l = getToken().asString();
00986                         MathArray ar;
00987                         parse(ar, FLAG_RIGHT, mode);
00988                         skipSpaces();
00989                         string r = getToken().asString();
00990                         cell->push_back(MathAtom(new MathDelimInset(l, r, ar)));
00991                 }
00992 
00993                 else if (t.cs() == "right") {
00994                         if (flags & FLAG_RIGHT)
00995                                 return;
00996                         //lyxerr << "got so far: '" << cell << "'\n";
00997                         error("Unmatched right delimiter");
00998                         return;
00999                 }
01000 
01001                 else if (t.cs() == "begin") {
01002                         string const name = getArg('{', '}');
01003 
01004                         if (name == "array" || name == "subarray") {
01005                                 string const valign = parse_verbatim_option() + 'c';
01006                                 string const halign = parse_verbatim_item();
01007                                 cell->push_back(MathAtom(new MathArrayInset(name, valign[0], halign)));
01008                                 parse2(cell->back(), FLAG_END, mode, false);
01009                         }
01010 
01011                         else if (name == "tabular") {
01012                                 string const valign = parse_verbatim_option() + 'c';
01013                                 string const halign = parse_verbatim_item();
01014                                 cell->push_back(MathAtom(new MathTabularInset(name, valign[0], halign)));
01015                                 parse2(cell->back(), FLAG_END, MathInset::TEXT_MODE, false);
01016                         }
01017 
01018                         else if (name == "split" || name == "cases" ||
01019                                          name == "gathered" || name == "aligned") {
01020                                 cell->push_back(createMathInset(name));
01021                                 parse2(cell->back(), FLAG_END, mode, false);
01022                         }
01023 
01024                         else if (name == "math") {
01025                                 cell->push_back(MathAtom(new MathHullInset("simple")));
01026                                 parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, true);
01027                         }
01028 
01029                         else if (name == "equation" || name == "equation*"
01030                                         || name == "displaymath") {
01031                                 cell->push_back(MathAtom(new MathHullInset("equation")));
01032                                 parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, (name == "equation"));
01033                         }
01034 
01035                         else if (name == "eqnarray" || name == "eqnarray*") {
01036                                 cell->push_back(MathAtom(new MathHullInset("eqnarray")));
01037                                 parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name));
01038                         }
01039 
01040                         else if (name == "align" || name == "align*") {
01041                                 cell->push_back(MathAtom(new MathHullInset("align")));
01042                                 parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name));
01043                         }
01044 
01045                         else if (name == "flalign" || name == "flalign*") {
01046                                 cell->push_back(MathAtom(new MathHullInset("flalign")));
01047                                 parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name));
01048                         }
01049 
01050                         else if (name == "alignat" || name == "alignat*") {
01051                                 // ignore this for a while
01052                                 getArg('{', '}');
01053                                 cell->push_back(MathAtom(new MathHullInset("alignat")));
01054                                 parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name));
01055                         }
01056 
01057                         else if (name == "xalignat" || name == "xalignat*") {
01058                                 // ignore this for a while
01059                                 getArg('{', '}');
01060                                 cell->push_back(MathAtom(new MathHullInset("xalignat")));
01061                                 parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name));
01062                         }
01063 
01064                         else if (name == "xxalignat") {
01065                                 // ignore this for a while
01066                                 getArg('{', '}');
01067                                 cell->push_back(MathAtom(new MathHullInset("xxalignat")));
01068                                 parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name));
01069                         }
01070 
01071                         else if (name == "multline" || name == "multline*") {
01072                                 cell->push_back(MathAtom(new MathHullInset("multline")));
01073                                 parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name));
01074                         }
01075 
01076                         else if (name == "gather" || name == "gather*") {
01077                                 cell->push_back(MathAtom(new MathHullInset("gather")));
01078                                 parse2(cell->back(), FLAG_END, MathInset::MATH_MODE, !stared(name));
01079                         }
01080 
01081                         else if (latexkeys const * l = in_word_set(name)) {
01082                                 if (l->inset == "matrix") {
01083                                         cell->push_back(createMathInset(name));
01084                                         parse2(cell->back(), FLAG_END, mode, false);
01085                                 }
01086                         }
01087 
01088                         else {
01089                                 dump();
01090                                 lyxerr << "found unknown math environment '" << name << "'\n";
01091                                 // create generic environment inset
01092                                 cell->push_back(MathAtom(new MathEnvInset(name)));
01093                                 parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
01094                         }
01095                 }
01096 
01097                 else if (t.cs() == "kern") {
01098 #ifdef WITH_WARNINGS
01099 #warning A hack...
01100 #endif
01101                         string s;
01102                         while (true) {
01103                                 Token const & t = getToken();
01104                                 if (!good()) {
01105                                         putback();
01106                                         break;
01107                                 }
01108                                 s += t.character();
01109                                 if (isValidLength(s))
01110                                         break;
01111                         }
01112                         cell->push_back(MathAtom(new MathKernInset(s)));
01113                 }
01114 
01115                 else if (t.cs() == "label") {
01116                         string label = parse_verbatim_item();
01117                         MathArray ar;
01118                         asArray(label, ar);
01119                         if (grid.asHullInset()) {
01120                                 grid.asHullInset()->label(cellrow, label);
01121                         } else {
01122                                 cell->push_back(createMathInset(t.cs()));
01123                                 cell->push_back(MathAtom(new MathBraceInset(ar)));
01124                         }
01125                 }
01126 
01127                 else if (t.cs() == "choose" || t.cs() == "over" || t.cs() == "atop") {
01128                         MathAtom at = createMathInset(t.cs());
01129                         at.nucleus()->cell(0) = *cell;
01130                         cell->clear();
01131                         parse(at.nucleus()->cell(1), flags, mode);
01132                         cell->push_back(at);
01133                         return;
01134                 }
01135 
01136                 else if (t.cs() == "substack") {
01137                         cell->push_back(createMathInset(t.cs()));
01138                         parse2(cell->back(), FLAG_ITEM, mode, false);
01139                 }
01140 
01141                 else if (t.cs() == "framebox" || t.cs() == "makebox") {
01142                         cell->push_back(createMathInset(t.cs()));
01143                         parse(cell->back().nucleus()->cell(0), FLAG_OPTION, MathInset::TEXT_MODE);
01144                         parse(cell->back().nucleus()->cell(1), FLAG_OPTION, MathInset::TEXT_MODE);
01145                         parse(cell->back().nucleus()->cell(2), FLAG_ITEM, MathInset::TEXT_MODE);
01146                 }
01147 
01148 #if 0
01149                 else if (t.cs() == "infer") {
01150                         MathArray ar;
01151                         parse(ar, FLAG_OPTION, mode);
01152                         cell->push_back(createMathInset(t.cs()));
01153                         parse2(cell->back(), FLAG_ITEM, mode, false);
01154                 }
01155 
01156                 // Disabled
01157                 else if (1 && t.cs() == "ar") {
01158                         MathXYArrowInset * p = new MathXYArrowInset;
01159                         // try to read target
01160                         parse(p->cell(0), FLAG_OTPTION, mode);
01161                         // try to read label
01162                         if (nextToken().cat() == catSuper || nextToken().cat() == catSub) {
01163                                 p->up_ = nextToken().cat() == catSuper;
01164                                 getToken();
01165                                 parse(p->cell(1), FLAG_ITEM, mode);
01166                                 //lyxerr << "read label: " << p->cell(1) << "\n";
01167                         }
01168 
01169                         cell->push_back(MathAtom(p));
01170                         //lyxerr << "read cell: " << cell << "\n";
01171                 }
01172 #endif
01173 
01174                 else if (t.cs().size()) {
01175                         latexkeys const * l = in_word_set(t.cs());
01176                         if (l) {
01177                                 if (l->inset == "font") {
01178                                         cell->push_back(createMathInset(t.cs()));
01179