improved function function argument detection for math-extern:

\sum_i{i=1}^n i^2 is now parsed properly.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@3025 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
André Pönitz 2001-11-13 18:33:48 +00:00
parent f3c27aa1f5
commit c80a4abde9
8 changed files with 176 additions and 86 deletions

View File

@ -6,11 +6,9 @@
using std::ostream; using std::ostream;
MathExFuncInset::MathExFuncInset(string const & name, MathArray const & arg) MathExFuncInset::MathExFuncInset(string const & name)
: MathNestInset(1), name_(name) : MathNestInset(1), name_(name)
{ {}
cell(0) = arg;
}
MathInset * MathExFuncInset::clone() const MathInset * MathExFuncInset::clone() const

View File

@ -10,7 +10,7 @@
class MathExFuncInset : public MathNestInset { class MathExFuncInset : public MathNestInset {
public: public:
/// ///
MathExFuncInset(string const & name, MathArray const & arg); explicit MathExFuncInset(string const & name);
/// ///
MathInset * clone() const; MathInset * clone() const;
/// ///

View File

@ -6,7 +6,7 @@
MathExIntInset::MathExIntInset(string const & name) MathExIntInset::MathExIntInset(string const & name)
: symbol_(name) : MathNestInset(2), symbol_(name)
{} {}
@ -16,18 +16,6 @@ MathInset * MathExIntInset::clone() const
} }
void MathExIntInset::index(MathArray const & ar)
{
index_ = ar;
}
void MathExIntInset::core(MathArray const & ar)
{
core_ = ar;
}
void MathExIntInset::scripts(MathAtom const & at) void MathExIntInset::scripts(MathAtom const & at)
{ {
scripts_ = at; scripts_ = at;
@ -55,12 +43,10 @@ bool MathExIntInset::hasScripts() const
void MathExIntInset::normalize(NormalStream & os) const void MathExIntInset::normalize(NormalStream & os) const
{ {
os << '[' << symbol_.c_str() << ' '; os << '[' << symbol_.c_str() << ' ' << cell(0) << ' ' << cell(1);
if (hasScripts()) if (hasScripts())
os << scripts_.nucleus(); os << scripts_.nucleus();
else os << ']';
os << "{}";
os << ' ' << core_ << ' ' << index_ << ']';
} }
@ -79,11 +65,11 @@ void MathExIntInset::draw(Painter &, int, int) const
void MathExIntInset::maplize(MapleStream & os) const void MathExIntInset::maplize(MapleStream & os) const
{ {
os << symbol_.c_str() << '('; os << symbol_.c_str() << '(';
if (core_.size()) if (cell(0).size())
os << core_; os << cell(0);
else else
os << '1'; os << '1';
os << ',' << index_; os << ',' << cell(1);
if (hasScripts()) { if (hasScripts()) {
MathScriptInset * p = scripts_->asScriptInset(); MathScriptInset * p = scripts_->asScriptInset();
os << '=' << p->down().data_ << ".." << p->up().data_; os << '=' << p->down().data_ << ".." << p->up().data_;
@ -100,9 +86,9 @@ void MathExIntInset::mathmlize(MathMLStream & os) const
else else
sym->mathmlize(os); sym->mathmlize(os);
delete sym; delete sym;
os << core_ << "<mo> &InvisibleTimes; </mo>" os << cell(0) << "<mo> &InvisibleTimes; </mo>"
<< MTag("mrow") << "<mo> &DifferentialD; </mo>" << MTag("mrow") << "<mo> &DifferentialD; </mo>"
<< index_ << ETag("mrow"); << cell(1) << ETag("mrow");
} }

View File

@ -2,22 +2,19 @@
#ifndef MATH_EXINTINSET_H #ifndef MATH_EXINTINSET_H
#define MATH_EXINTINSET_H #define MATH_EXINTINSET_H
// /\int_l^u f(x) dxin one block (as opposed to 'f','(','x',')' or 'f','x') // \int_l^u f(x) dx in one block (as opposed to 'f','(','x',')' or 'f','x')
// for interfacing external programs // or \sum, \prod... for interfacing external programs
#include "math_scriptinset.h" #include "math_scriptinset.h"
class MathExIntInset : public MathInset { // cell(0) is stuff before the 'd', cell(1) the stuff after
class MathExIntInset : public MathNestInset {
public: public:
/// ///
explicit MathExIntInset(string const & name_); explicit MathExIntInset(string const & name_);
/// ///
MathInset * clone() const; MathInset * clone() const;
/// ///
void index(MathArray const &);
///
void core(MathArray const &);
///
void scripts(MathAtom const &); void scripts(MathAtom const &);
/// ///
MathAtom & scripts(); MathAtom & scripts();
@ -44,10 +41,6 @@ private:
string symbol_; string symbol_;
/// ///
MathAtom scripts_; MathAtom scripts_;
///
MathArray core_;
///
MathArray index_;
}; };
#endif #endif

View File

@ -7,9 +7,11 @@
#include "math_charinset.h" #include "math_charinset.h"
#include "math_deliminset.h" #include "math_deliminset.h"
#include "math_diffinset.h"
#include "math_exfuncinset.h" #include "math_exfuncinset.h"
#include "math_exintinset.h" #include "math_exintinset.h"
#include "math_funcinset.h" #include "math_funcinset.h"
#include "math_fracinset.h"
#include "math_matrixinset.h" #include "math_matrixinset.h"
#include "math_mathmlstream.h" #include "math_mathmlstream.h"
#include "math_scriptinset.h" #include "math_scriptinset.h"
@ -26,6 +28,60 @@ std::ostream & operator<<(std::ostream & os, MathArray const & ar)
} }
// define a function for tests
typedef bool TestItemFunc(MathInset *);
// define a function for replacing subexpressions
typedef MathInset * ReplaceArgumentFunc(const MathArray & ar);
// try to extract an "argument" to some function.
// returns position behind the argument
MathArray::iterator extractArgument(MathArray & ar,
MathArray::iterator pos, MathArray::iterator last, string const & = "")
{
// nothing to get here
if (pos == last)
return pos;
// something deliminited _is_ an argument
if ((*pos)->asDelimInset()) {
ar.push_back(*pos);
return pos + 1;
}
// always take the first thing, no matter what it is
ar.push_back(*pos);
// go ahead if possible
++pos;
if (pos == last)
return pos;
// if the next item is a subscript, it most certainly belongs to the
// thing we have
if ((*pos)->asScriptInset()) {
ar.push_back(*pos);
// go ahead if possible
++pos;
if (pos == last)
return pos;
}
// but it might be more than that.
// FIXME: not implemented
//for (MathArray::iterator it = pos + 1; it != last; ++it) {
// // always take the first thing, no matter
// if (it == pos) {
// ar.push_back(*it);
// continue;
// }
//}
return pos;
}
MathScriptInset const * asScript(MathArray::const_iterator it) MathScriptInset const * asScript(MathArray::const_iterator it)
{ {
if (it->nucleus()->asScriptInset()) if (it->nucleus()->asScriptInset())
@ -94,10 +150,11 @@ void extractMatrices(MathArray & ar)
if (!arr || !arr->asArrayInset()) if (!arr || !arr->asArrayInset())
continue; continue;
*it = MathAtom(new MathMatrixInset(*(arr->asArrayInset()))); *it = MathAtom(new MathMatrixInset(*(arr->asArrayInset())));
lyxerr << "\nMatrices to: " << ar << "\n";
} }
lyxerr << "\nMatrices to: " << ar << "\n";
} }
// convert this inset somehow to a string // convert this inset somehow to a string
string extractString(MathInset * p) string extractString(MathInset * p)
{ {
@ -109,11 +166,10 @@ string extractString(MathInset * p)
} }
// define a function for tests bool stringTest(MathInset * p, const string & str)
typedef bool TestItemFunc(MathInset *); {
return extractString(p) == str;
// define a function for replacing subexpressions }
typedef MathInset * ReplaceArgumentFunc(const MathArray & ar);
// search end of nested sequence // search end of nested sequence
@ -173,13 +229,13 @@ void replaceNested(
bool openParanTest(MathInset * p) bool openParanTest(MathInset * p)
{ {
return extractString(p) == "("; return stringTest(p, "(");
} }
bool closeParanTest(MathInset * p) bool closeParanTest(MathInset * p)
{ {
return extractString(p) == ")"; return stringTest(p, ")");
} }
@ -192,7 +248,8 @@ MathInset * delimReplacement(const MathArray & ar)
// replace '('...')' sequences by a real MathDelimInset // replace '('...')' sequences by a real MathDelimInset
void extractDelims(MathArray & ar) { void extractDelims(MathArray & ar)
{
lyxerr << "\nDelims from: " << ar << "\n"; lyxerr << "\nDelims from: " << ar << "\n";
replaceNested(ar, openParanTest, closeParanTest, delimReplacement); replaceNested(ar, openParanTest, closeParanTest, delimReplacement);
lyxerr << "\nDelims to: " << ar << "\n"; lyxerr << "\nDelims to: " << ar << "\n";
@ -235,20 +292,17 @@ void extractFunctions(MathArray & ar)
continue; continue;
} }
// jt points now to the "argument". Since we had run "extractDelims" // create a proper inset as replacement
// before, this could be a single argument only. Get hold of this. MathExFuncInset * p = new MathExFuncInset(func->name());
MathArray arg;
MathDelimInset * del = (*jt)->asDelimInset(); // jt points to the "argument". Get hold of this.
if (del && del->isParanthesis()) MathArray::iterator st = extractArgument(p->cell(0), jt, ar.end());
arg = del->cell(0);
else
arg.push_back(*jt);
// replace the function name by a real function inset // replace the function name by a real function inset
(*it).reset(new MathExFuncInset(func->name(), arg)); (*it).reset(p);
// remove the source of the argument from the array // remove the source of the argument from the array
ar.erase(jt); ar.erase(jt, st);
lyxerr << "\nFunctions to: " << ar << "\n"; lyxerr << "\nFunctions to: " << ar << "\n";
} }
} }
@ -258,15 +312,21 @@ void extractFunctions(MathArray & ar)
// search integrals // search integrals
// //
bool intSymbolTest(MathInset * p) bool symbolTest(MathInset * p, string const & name)
{ {
return p->asSymbolInset() && p->asSymbolInset()->name() == "int"; return p->asSymbolInset() && p->asSymbolInset()->name() == name;
} }
bool differentialTest(MathInset * p) bool intSymbolTest(MathInset * p)
{ {
return extractString(p) == "d"; return symbolTest(p, "int");
}
bool intDiffTest(MathInset * p)
{
return stringTest(p, "d");
} }
@ -288,7 +348,7 @@ void extractIntegrals(MathArray & ar)
// search 'd' // search 'd'
MathArray::iterator jt = MathArray::iterator jt =
endNestSearch(it, ar.end(), intSymbolTest, differentialTest); endNestSearch(it, ar.end(), intSymbolTest, intDiffTest);
// something sensible found? // something sensible found?
if (jt == ar.end()) if (jt == ar.end())
@ -301,20 +361,16 @@ void extractIntegrals(MathArray & ar)
MathArray::iterator st = it + 1; MathArray::iterator st = it + 1;
if ((*st)->asScriptInset()) { if ((*st)->asScriptInset()) {
p->scripts(*st); p->scripts(*st);
p->core(MathArray(st + 1, jt)); p->cell(0) = MathArray(st + 1, jt);
} else { } else {
p->core(MathArray(st, jt)); p->cell(0) = MathArray(st, jt);
} }
// use the atom behind the 'd' as differential // use the atom behind the 'd' as differential
MathArray ind; MathArray::iterator tt = extractArgument(p->cell(1), jt + 1, ar.end());
if (jt + 1 != ar.end()) {
ind.push_back(*(jt + 1));
++jt;
}
ar.erase(it + 1, jt + 1);
p->index(ind); // remove used parts
ar.erase(it + 1, tt);
(*it).reset(p); (*it).reset(p);
} }
lyxerr << "\nIntegrals to: " << ar << "\n"; lyxerr << "\nIntegrals to: " << ar << "\n";
@ -333,7 +389,7 @@ bool sumSymbolTest(MathInset * p)
bool equalSign(MathInset * p) bool equalSign(MathInset * p)
{ {
return extractString(p) == "="; return stringTest(p, "=");
} }
@ -378,25 +434,21 @@ void extractSums(MathArray & ar)
if (it != ar.end()) { if (it != ar.end()) {
// we found a '=', use everything in front of that as index, // we found a '=', use everything in front of that as index,
// and everything behind as start value // and everything behind as start value
p->index(MathArray(ar.begin(), it)); p->cell(1) = MathArray(ar.begin(), it);
ar.erase(ar.begin(), it + 1); ar.erase(ar.begin(), it + 1);
} else { } else {
// use everything as summation index // use everything as summation index, don't use scripts.
p->index(ar); p->cell(1) = ar;
p->scripts().reset(0); p->scripts().reset(0);
} }
} }
} }
// use the atom behind the script as core // use some behind the script as core
MathArray ind; MathArray::iterator tt = extractArgument(p->cell(0), st, ar.end());
if (st != ar.end()) {
MathArray core; // cleanup
core.push_back(*st); ar.erase(it + 1, tt);
p->core(core);
++st;
}
ar.erase(it + 1, st);
(*it).reset(p); (*it).reset(p);
} }
lyxerr << "\nSums to: " << ar << "\n"; lyxerr << "\nSums to: " << ar << "\n";
@ -407,9 +459,60 @@ void extractSums(MathArray & ar)
// search differential stuff // search differential stuff
// //
// tests for 'd' or '\partial'
bool diffItemTest(MathInset * p)
{
return stringTest(p, "d");
}
bool diffItemTest(MathArray const & ar)
{
return ar.size() && diffItemTest(ar.front().nucleus());
}
bool diffFracTest(MathInset * p)
{
return
p->asFracInset() &&
diffItemTest(p->asFracInset()->cell(0)) &&
diffItemTest(p->asFracInset()->cell(1));
}
void extractDiff(MathArray & ar) void extractDiff(MathArray & ar)
{ {
lyxerr << "\nDiffs from: " << ar << "\n"; lyxerr << "\nDiffs from: " << ar << "\n";
for (MathArray::size_type i = 0; i < ar.size() - 1; ++i) {
MathArray::iterator it = ar.begin() + i;
// is this a "differential fraction"?
if (!diffFracTest(it->nucleus()))
continue;
MathFracInset * f = (*it)->asFracInset();
if (!f) {
lyxerr << "should not happen\n";
continue;
}
// create a proper diff inset
MathDiffInset * p = new MathDiffInset;
// collect function
MathArray::iterator jt = it + 1;
if (f->cell(0).size() > 1)
p->cell(0) = MathArray(f->cell(0).begin() + 1, f->cell(0).end());
else
jt = extractArgument(p->cell(0), jt, ar.end());
// collect denominator
// cleanup
ar.erase(it + 1, jt);
(*it).reset(p);
}
lyxerr << "\nDiffs to: " << ar << "\n"; lyxerr << "\nDiffs to: " << ar << "\n";
} }

View File

@ -19,6 +19,12 @@ MathInset * MathFracInset::clone() const
} }
MathFracInset * MathFracInset::asFracInset()
{
return atop_ ? 0 : this;
}
void MathFracInset::metrics(MathMetricsInfo const & mi) const void MathFracInset::metrics(MathMetricsInfo const & mi) const
{ {
MathMetricsInfo m = mi; MathMetricsInfo m = mi;

View File

@ -21,6 +21,8 @@ public:
void metrics(MathMetricsInfo const & st) const; void metrics(MathMetricsInfo const & st) const;
/// ///
void draw(Painter &, int x, int y) const; void draw(Painter &, int x, int y) const;
///
MathFracInset * asFracInset();
/// ///
void write(WriteStream & os) const; void write(WriteStream & os) const;

View File

@ -44,6 +44,7 @@ class MathCharInset;
class MathDelimInset; class MathDelimInset;
class MathFuncInset; class MathFuncInset;
class MathGridInset; class MathGridInset;
class MathFracInset;
class MathHullInset; class MathHullInset;
class MathMatrixInset; class MathMatrixInset;
class MathNestInset; class MathNestInset;
@ -179,6 +180,7 @@ public:
virtual MathDelimInset * asDelimInset() { return 0; } virtual MathDelimInset * asDelimInset() { return 0; }
virtual MathDelimInset const * asDelimInset() const { return 0; } virtual MathDelimInset const * asDelimInset() const { return 0; }
virtual MathFuncInset * asFuncInset() { return 0; } virtual MathFuncInset * asFuncInset() { return 0; }
virtual MathFracInset * asFracInset() { return 0; }
virtual MathGridInset * asGridInset() { return 0; } virtual MathGridInset * asGridInset() { return 0; }
virtual MathHullInset * asHullInset() { return 0; } virtual MathHullInset * asHullInset() { return 0; }
virtual MathHullInset const * asHullInset() const { return 0; } virtual MathHullInset const * asHullInset() const { return 0; }