FLAG_END = 1 << 3, // next \\end ends the parsing process
FLAG_BRACK_END = 1 << 4, // next closing bracket ends the parsing process
FLAG_BOX = 1 << 5, // we are in a box
- FLAG_ITEM = 1 << 7, // read a (possibly braced token)
- FLAG_BLOCK = 1 << 8, // next block ends the parsing process
+ FLAG_ITEM = 1 << 6, // read a (possibly braced token)
+ FLAG_BLOCK = 1 << 7, // next block ends the parsing process
+ FLAG_BLOCK2 = 1 << 8, // next block2 ends the parsing process
FLAG_LEAVE = 1 << 9 // leave the loop at the end
};
return cs_.size() ? cs_ : string(1, char_);
}
-bool operator==(Token const & s, Token const & t)
-{
- return s.character() == t.character()
- && s.cat() == t.cat() && s.cs() == t.cs();
-}
-
-// Angus' compiler says this is not needed
+// Angus' compiler says these are not needed
+//bool operator==(Token const & s, Token const & t)
+//{
+// return s.character() == t.character()
+// && s.cat() == t.cat() && s.cs() == t.cs();
+//}
+//
//bool operator!=(Token const & s, Token const & t)
//{
// return !(s == t);
Parser(istream & is);
///
- string parse_macro();
+ bool parse_macro(string & name);
///
bool parse_normal(MathAtom &);
///
void putback();
private:
+ ///
+ void parse_into1(MathArray & array, unsigned flags, MathTextCodes);
///
string getArg(char lf, char rf);
///
void error(string const & msg);
///
bool parse_lines(MathAtom & t, bool numbered, bool outmost);
+ /// parses {... & ... \\ ... & ... }
+ bool parse_lines2(MathAtom & t);
private:
///
Token const & getToken();
/// skips spaces if any
void skipSpaces();
+ /// skips opening brace
+ void skipBegin();
+ /// skips closing brace
+ void skipEnd();
/// counts a sequence of hlines
int readHLines();
///
}
+void Parser::skipBegin()
+{
+ if (nextToken().cat() == catBegin)
+ getToken();
+ else
+ lyxerr << "'{' expected\n";
+}
+
+
+void Parser::skipEnd()
+{
+ if (nextToken().cat() == catEnd)
+ getToken();
+ else
+ lyxerr << "'}' expected\n";
+}
+
+
int Parser::readHLines()
{
int num = 0;
}
+
bool Parser::parse_lines(MathAtom & t, bool numbered, bool outmost)
{
MathGridInset * p = t->asGridInset();
return false;
}
- MathInset::col_type const cols = p->ncols();
-
// save global variables
bool const saved_num = curr_num_;
string const saved_label = curr_label_;
curr_label_.erase();
// reading a row
- for (MathInset::col_type col = 0; col < cols; ++col) {
+ for (MathInset::col_type col = 0; col < p->ncols(); ++col) {
//lyxerr << "reading cell " << row << " " << col << "\n";
- parse_into(p->cell(col + row * cols), FLAG_BLOCK);
+
+ MathArray & ar = p->cell(col + row * p->ncols());
+ parse_into(ar, FLAG_BLOCK);
+ // remove 'unnecessary' braces:
+ if (ar.size() == 1 && ar.back()->asBraceInset())
+ ar = ar.back()->asBraceInset()->cell(0);
// break if cell is not followed by an ampersand
if (nextToken().cat() != catAlign) {
}
-string Parser::parse_macro()
+bool Parser::parse_lines2(MathAtom & t)
+{
+ MathGridInset * p = t->asGridInset();
+ if (!p) {
+ lyxerr << "error in Parser::parse_lines() 1\n";
+ return false;
+ }
+
+ skipBegin();
+
+ for (int row = 0; true; ++row) {
+ // reading a row
+ for (MathInset::col_type col = 0; true; ++col) {
+ //lyxerr << "reading cell " << row << " " << col << " " << p->ncols() << "\n";
+
+ if (col >= p->ncols()) {
+ //lyxerr << "adding col " << col << "\n";
+ p->addCol(p->ncols());
+ }
+
+ parse_into(p->cell(col + row * p->ncols()), FLAG_BLOCK2);
+ //lyxerr << "read cell: " << p->cell(col + row * p->ncols()) << "\n";
+
+ // break if cell is not followed by an ampersand
+ if (nextToken().cat() != catAlign) {
+ //lyxerr << "less cells read than normal in row/col: " << row << " " << col << "\n";
+ break;
+ }
+
+ // skip the ampersand
+ getToken();
+ }
+
+ // is a \\ coming?
+ if (nextToken().isCR()) {
+ // skip the cr-token
+ getToken();
+ }
+
+ // we are finished if the next token is an '}'
+ if (nextToken().cat() == catEnd) {
+ // skip the end-token
+ getToken();
+ // leave the 'read a line'-loop
+ break;
+ }
+
+ // otherwise, we have to start a new row
+ p->appendRow();
+ }
+
+ return true;
+}
+
+
+
+bool Parser::parse_macro(string & name)
{
- string name = "{error}";
+ name = "{error}";
skipSpaces();
if (getToken().cs() != "newcommand") {
lyxerr << "\\newcommand expected\n";
- return name;
+ return false;
}
if (getToken().cat() != catBegin) {
lyxerr << "'{' in \\newcommand expected (1)\n";
- return name;
+ return false;
}
name = getToken().cs();
if (getToken().cat() != catEnd) {
lyxerr << "'}' expected\n";
- return name;
+ return false;
}
string arg = getArg('[', ']');
if (getToken().cat() != catBegin) {
lyxerr << "'{' in \\newcommand expected (2)\n";
- return name;
+ return false;
}
MathArray ar;
parse_into(ar, FLAG_BRACE_LAST);
+
+ // we cannot handle recursive stuff at all
+ MathArray test;
+ test.push_back(createMathInset(name));
+ if (ar.contains(test)) {
+ lyxerr << "we cannot handle recursive macros at all.\n";
+ return false;
+ }
+
MathMacroTable::create(name, narg, ar);
- return name;
+ return true;
}
string const name = getArg('{', '}');
+ if (name == "math") {
+ matrix = MathAtom(new MathHullInset(LM_OT_SIMPLE));
+ parse_into(matrix->cell(0), 0);
+ return true;
+ }
+
if (name == "equation" || name == "equation*" || name == "displaymath") {
curr_num_ = (name == "equation");
curr_label_.erase();
void Parser::parse_into(MathArray & array, unsigned flags, MathTextCodes code)
+{
+ parse_into1(array, flags, code);
+ // remove 'unnecessary' braces:
+ if (array.size() == 1 && array.back()->asBraceInset())
+ array = array.back()->asBraceInset()->cell(0);
+}
+
+
+void Parser::parse_into1(MathArray & array, unsigned flags, MathTextCodes code)
{
bool panic = false;
int limits = 0;
while (good()) {
Token const & t = getToken();
- //lyxerr << "t: " << t << " flags: " << flags << "'\n";
+ //lyxerr << "t: " << t << " flags: " << flags << "\n";
//array.dump(lyxerr);
//lyxerr << "\n";
}
}
+ if (flags & FLAG_BLOCK2) {
+ if (t.cat() == catAlign || t.isCR() || t.cs() == "end"
+ || t.cat() == catEnd) {
+ putback();
+ return;
+ }
+ }
+
//
// cat codes
//
else if (t.cat() == catParameter) {
Token const & n = getToken();
- array.push_back(MathAtom(new MathMacroArgument(n.character() - '0')));
+ array.push_back(MathAtom(new MathMacroArgument(n.character()-'0', code)));
}
else if (t.cat() == catBegin) {
#warning this might be wrong in general!
#endif
// ignore braces around simple items
- if (ar.size() == 1 || (ar.size() == 2 && ar.back()->asScriptInset())) {
+ if ((ar.size() == 1 && !ar.front()->needsBraces()
+ || (ar.size() == 2 && !ar.front()->needsBraces()
+ && ar.back()->asScriptInset()))
+ || (ar.size() == 0 && array.size() == 0))
+ {
array.push_back(ar);
} else {
array.push_back(MathAtom(new MathBraceInset));
return;
}
+ else if (t.cs() == "xymatrix") {
+ array.push_back(createMathInset(t.cs()));
+ parse_lines2(array.back());
+ }
+
// Disabled
#if 0
+ else if (0 && t.cs() == "ar") {
+ array.push_back(createMathInset(t.cs()));
+ parse_lines2(array.back());
+ }
+
else if (t.cs() == "mbox") {
array.push_back(createMathInset(t.cs()));
// slurp in the argument of mbox
-string mathed_parse_macro(string const & str)
+bool mathed_parse_macro(string & name, string const & str)
{
istringstream is(str.c_str());
Parser parser(is);
- return parser.parse_macro();
+ return parser.parse_macro(name);
}
-string mathed_parse_macro(istream & is)
+bool mathed_parse_macro(string & name, istream & is)
{
Parser parser(is);
- return parser.parse_macro();
+ return parser.parse_macro(name);
}
-string mathed_parse_macro(LyXLex & lex)
+bool mathed_parse_macro(string & name, LyXLex & lex)
{
Parser parser(lex);
- return parser.parse_macro();
+ return parser.parse_macro(name);
}