]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/MathParser.cpp
revert last patch. there's something wrong, possibly unrelated to this
[lyx.git] / src / mathed / MathParser.cpp
index 9193e666a74998c05d87e778ce19824d1dd58889..1f7db010c182063042b2dc03fa3dc2a3fef08e88 100644 (file)
@@ -63,28 +63,18 @@ following hack as starting point to write some macros:
 #include "MathSupport.h"
 
 #include "Lexer.h"
-#include "debug.h"
 
+#include "support/debug.h"
 #include "support/convert.h"
 #include "support/docstream.h"
 
 #include <sstream>
 
-
-namespace lyx {
-
-using std::endl;
-using std::fill;
-
-using std::string;
-using std::ios;
-using std::istream;
-using std::ostream;
-using std::vector;
-
-
 //#define FILEDEBUG
 
+using namespace std;
+
+namespace lyx {
 
 namespace {
 
@@ -317,7 +307,7 @@ public:
        ///
        Parser(Lexer & lex);
        /// Only use this for reading from .lyx file format, for the reason
-       /// see Parser::tokenize(std::istream &).
+       /// see Parser::tokenize(istream &).
        Parser(istream & is);
        ///
        Parser(docstring const & str);
@@ -902,55 +892,186 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                                cell->back().nucleus()->lock(true);
                }
 
-               else if (t.cs() == "def" ||
-                       t.cs() == "newcommand" ||
-                       t.cs() == "renewcommand")
-               {
-                       docstring const type = t.cs();
-                       docstring name;
+               else if ((t.cs() == "global" && nextToken().cs() == "def") ||
+                        t.cs() == "def") {
+                       if (t.cs() == "global")
+                               getToken();
+                       
+                       // get name
+                       docstring name = getToken().cs();
+                       
+                       // read parameters
                        int nargs = 0;
+                       docstring pars;
+                       while (good() && nextToken().cat() != catBegin) {
+                               pars += getToken().cs();
+                               ++nargs;
+                       }
+                       nargs /= 2;
+                       
+                       // read definition
+                       MathData def;
+                       parse(def, FLAG_ITEM, InsetMath::UNDECIDED_MODE);
+                       
+                       // is a version for display attached?
+                       skipSpaces();
+                       MathData display;
+                       if (nextToken().cat() == catBegin)
+                               parse(display, FLAG_ITEM, InsetMath::MATH_MODE);
+                       
+                       cell->push_back(MathAtom(new MathMacroTemplate(name, nargs,
+                              0, MacroTypeDef, vector<MathData>(), def, display)));
+               }
+               
+               else if (t.cs() == "newcommand" ||
+                        t.cs() == "renewcommand" ||
+                        t.cs() == "newlyxcommand") {
+                       // get name
+                       if (getToken().cat() != catBegin) {
+                               error("'{' in \\newcommand expected (1) ");
+                               return;
+                       }
+                       docstring name = getToken().cs();
+                       if (getToken().cat() != catEnd) {
+                               error("'}' in \\newcommand expected");
+                               return;
+                       }
+                               
+                       // get arity
+                       docstring const arg = getArg('[', ']');
+                       int nargs = 0;
+                       if (!arg.empty())
+                               nargs = convert<int>(arg);
+                               
+                       // optional argument given?
+                       skipSpaces();
                        int optionals = 0;
-                       std::vector<MathData> optionalValues;
-                       if (t.cs() == "def") {
-                               // get name
-                               name = getToken().cs();
-
-                               // read parameter
-                               docstring pars;
-                               while (good() && nextToken().cat() != catBegin) {
-                                       pars += getToken().cs();
-                                       ++nargs;
-                               }
-                               nargs /= 2;
-                               //lyxerr << "read \\def parameter list '" << pars << "'" << endl;
-
-                       } else { // t.cs() == "newcommand" || t.cs() == "renewcommand"
-                               if (getToken().cat() != catBegin) {
-                                       error("'{' in \\newcommand expected (1) ");
-                                       return;
-                               }
-
+                       vector<MathData> optionalValues;
+                       while (nextToken().character() == '[') {
+                               getToken();
+                               optionalValues.push_back(MathData());
+                               parse(optionalValues[optionals], FLAG_BRACK_LAST, mode);
+                               ++optionals;
+                       }
+                       
+                       MathData def;
+                       parse(def, FLAG_ITEM, InsetMath::UNDECIDED_MODE);
+                       
+                       // is a version for display attached?
+                       skipSpaces();
+                       MathData display;
+                       if (nextToken().cat() == catBegin)
+                               parse(display, FLAG_ITEM, InsetMath::MATH_MODE);
+                       
+                       cell->push_back(MathAtom(new MathMacroTemplate(name, nargs,
+                               optionals, MacroTypeNewcommand, optionalValues, def, display)));
+                       
+               }
+               
+               else if (t.cs() == "newcommandx" ||
+                        t.cs() == "renewcommandx") {
+                       // \newcommandx{\foo}[2][usedefault, addprefix=\global,1=default]{#1,#2}
+                       // get name
+                       docstring name;
+                       if (nextToken().cat() == catBegin) {
+                               getToken();
                                name = getToken().cs();
-
                                if (getToken().cat() != catEnd) {
-                                       error("'}' in \\newcommand expected");
+                                       error("'}' in \\newcommandx expected");
                                        return;
                                }
-
-                               docstring const arg = getArg('[', ']');
-                               if (!arg.empty())
-                                       nargs = convert<int>(arg);
-
-                               // optional argument given?
+                       } else
+                               name = getToken().cs();
+                               
+                       // get arity
+                       docstring const arg = getArg('[', ']');
+                       if (arg.empty()) {
+                               error("[num] in \\newcommandx expected");
+                               return;
+                       }
+                       int nargs = convert<int>(arg);
+                       
+                       // get options
+                       int optionals = 0;
+                       vector<MathData> optionalValues;
+                       if (nextToken().character() == '[') {
+                               // skip '['
+                               getToken();
+                                       
+                               // handle 'opt=value' options, separated by ','.
                                skipSpaces();
-                               while (nextToken().character() == '[') {
-                                       getToken();
-                                       optionalValues.push_back(MathData());
-                                       parse(optionalValues[optionals], FLAG_BRACK_LAST, mode);
-                                       ++optionals;
+                               while (nextToken().character() != ']' && good()) {
+                                       if (nextToken().character() >= '1'
+                                           && nextToken().character() <= '9') {
+                                               // optional value -> get parameter number
+                                               int n = getChar() - '0';
+                                               if (n > nargs) {
+                                                       error("Arity of \\newcommandx too low "
+                                                             "for given optional parameter.");
+                                                       return;
+                                               }
+                                               
+                                               // skip '='
+                                               if (getToken().character() != '=') {
+                                                       error("'=' and optional parameter value "
+                                                             "expected for \\newcommandx");
+                                                       return;
+                                               }
+                                               
+                                               // get value
+                                               int optNum = max(size_t(n), optionalValues.size());
+                                               optionalValues.resize(optNum);
+                                               optionalValues[n - 1].clear();
+                                               while (nextToken().character() != ']'
+                                                      && nextToken().character() != ',') {
+                                                       MathData data;
+                                                       parse(data, FLAG_ITEM, InsetMath::UNDECIDED_MODE);
+                                                       optionalValues[n - 1].append(data);
+                                               }
+                                               optionals = max(n, optionals);
+                                       } else if (nextToken().cat() == catLetter) {
+                                               // we in fact ignore every non-optional
+                                               // parameter
+                                               
+                                               // get option name
+                                               docstring opt;
+                                               while (nextToken().cat() == catLetter)
+                                                       opt += getChar();
+                                       
+                                               // value?
+                                               skipSpaces();
+                                               MathData value;
+                                               if (nextToken().character() == '=') {
+                                                       getToken();
+                                                       while (nextToken().character() != ']'
+                                                               && nextToken().character() != ',')
+                                                               parse(value, FLAG_ITEM, 
+                                                                     InsetMath::UNDECIDED_MODE);
+                                               }
+                                       } else {
+                                               error("option for \\newcommandx expected");
+                                               return;
+                                       }
+                                       
+                                       // skip komma
+                                       skipSpaces();
+                                       if (nextToken().character() == ',') {
+                                               getChar();
+                                               skipSpaces();
+                                       } else if (nextToken().character() != ']') {
+                                               error("Expecting ',' or ']' in options "
+                                                     "of \\newcommandx");
+                                               return;
+                                       }
                                }
+                               
+                               // skip ']'
+                               if (!good())
+                                       return;
+                               getToken();
                        }
 
+                       // get definition
                        MathData def;
                        parse(def, FLAG_ITEM, InsetMath::UNDECIDED_MODE);
 
@@ -960,8 +1081,9 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                        if (nextToken().cat() == catBegin)
                                parse(display, FLAG_ITEM, InsetMath::MATH_MODE);
 
-                       cell->push_back(MathAtom(new MathMacroTemplate(name, nargs, optionals, type, 
-                                                                                                                                                                                                                optionalValues, def, display)));
+                       cell->push_back(MathAtom(new MathMacroTemplate(name, nargs,
+                               optionals, MacroTypeNewcommandx, optionalValues, def, 
+                               display)));
                }
 
                else if (t.cs() == "(") {
@@ -1177,14 +1299,16 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                        if (name == "array" || name == "subarray") {
                                docstring const valign = parse_verbatim_option() + 'c';
                                docstring const halign = parse_verbatim_item();
-                               cell->push_back(MathAtom(new InsetMathArray(name, (char)valign[0], halign)));
+                               cell->push_back(MathAtom(new InsetMathArray(name,
+                                       InsetMathGrid::guessColumns(halign), 1, (char)valign[0], halign)));
                                parse2(cell->back(), FLAG_END, mode, false);
                        }
 
                        else if (name == "tabular") {
                                docstring const valign = parse_verbatim_option() + 'c';
                                docstring const halign = parse_verbatim_item();
-                               cell->push_back(MathAtom(new InsetMathTabular(name, (char)valign[0], halign)));
+                               cell->push_back(MathAtom(new InsetMathTabular(name,
+                                       InsetMathGrid::guessColumns(halign), 1, (char)valign[0], halign)));
                                parse2(cell->back(), FLAG_END, InsetMath::TEXT_MODE, false);
                        }
 
@@ -1273,7 +1397,7 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                                               << to_utf8(l->inset) << "'." << endl;
                                        // create generic environment inset
                                        cell->push_back(MathAtom(new InsetMathEnv(name)));
-                                       parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+                                       parse(cell->back().nucleus()->cell(0), FLAG_END, mode);
                                }
                        }
 
@@ -1283,7 +1407,7 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                                        << "'" << endl;
                                // create generic environment inset
                                cell->push_back(MathAtom(new InsetMathEnv(name)));
-                               parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+                               parse(cell->back().nucleus()->cell(0), FLAG_END, mode);
                        }
                }
 
@@ -1316,7 +1440,9 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                        }
                }
 
-               else if (t.cs() == "choose" || t.cs() == "over" || t.cs() == "atop") {
+               else if (t.cs() == "choose" || t.cs() == "over"
+                               || t.cs() == "atop" || t.cs() == "brace"
+                               || t.cs() == "brack") {
                        MathAtom at = createInsetMath(t.cs());
                        at.nucleus()->cell(0) = *cell;
                        cell->clear();