/* Jaxe - Editeur XML en Java Copyright (C) 2003 Observatoire de Paris-Meudon Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le modifier conformément aux dispositions de la Licence Publique Générale GNU, telle que publiée par la Free Software Foundation ; version 2 de la licence, ou encore (à votre choix) toute version ultérieure. Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE GARANTIE ; sans même la garantie implicite de COMMERCIALISATION ou D'ADAPTATION A UN OBJET PARTICULIER. Pour plus de détail, voir la Licence Publique Générale GNU . Vous devez avoir reçu un exemplaire de la Licence Publique Générale GNU en même temps que ce programme ; si ce n'est pas le cas, écrivez à la Free Software Foundation Inc., 675 Mass Ave, Cambridge, MA 02139, Etats-Unis. */ package jaxe.equations; import java.util.Vector; import jaxe.equations.element.MathElement; import jaxe.equations.element.MathFrac; import jaxe.equations.element.MathIdentifier; import jaxe.equations.element.MathNumber; import jaxe.equations.element.MathOperator; import jaxe.equations.element.MathOver; import jaxe.equations.element.MathRootElement; import jaxe.equations.element.MathRow; import jaxe.equations.element.MathSqrt; import jaxe.equations.element.MathSub; import jaxe.equations.element.MathSubSup; import jaxe.equations.element.MathSup; import jaxe.equations.element.MathTable; import jaxe.equations.element.MathTableData; import jaxe.equations.element.MathTableRow; import jaxe.equations.element.MathText; import jaxe.equations.element.MathUnder; import jaxe.equations.element.MathUnderOver; /** * Constructeur pour une expression mathématique linéaire (style maple) */ public class StringMathBuilder { private MathRootElement rootElement; // opérateurs remplacés en premier, avant l'analyse de la syntaxe private static String[][] special = {{"<==", "\u21D0"}, {"==>", "\u21D2"}, {"<=>", "\u21D4"}, {"!=", "\u2260"}, {"~=", "\u2248"}, {"<=", "\u2264"}, {">=", "\u2265"}, {"<<", "\u226A"}, {">>", "\u226B"}, // "->" kepts for backward-compatibility {"-->", "\u2192"}, {"<->", "\u2194"}, {"->", "\u2192"}, {"<--", "\u2190"}, {"forall", "\u2200"}, {"quelquesoit", "\u2200"}, {"exists", "\u2203"}, {"ilexiste", "\u2203"}, {"part", "\u2202"}, {"drond", "\u2202"}, {"nabla", "\u2207"}, {"prop", "\u221D"}, {"cross", "×"}, {"croix", "×"}, {"plusmn", "±"}, {"plusoumoins", "±"}, {"plusminus", "±"}}; // opérateurs private static String sops = "_^*/\u2207±\u2213-+\u2200\u2203=\u2260\u2248<>\u2264\u2265\u226A\u226B\u221D" + "\u2190\u2192\u2194\u21D0\u21D2\u21D4"; private static String[][] symbols = { // grec-minuscule {"alpha", "\u03B1"}, {"beta", "\u03B2"}, {"gamma", "\u03B3"}, {"delta", "\u03B4"}, {"epsilon", "\u03B5"}, {"zeta", "\u03B6"}, {"eta", "\u03B7"}, {"theta", "\u03B8"}, {"iota", "\u03B9"}, {"kappa", "\u03BA"}, {"lambda", "\u03BB"}, {"mu", "\u03BC"}, {"nu", "\u03BD"}, {"xi", "\u03BE"}, {"omicron", "\u03BF"}, {"pi", "\u03C0"}, {"rho", "\u03C1"}, {"sigma", "\u03C3"}, {"tau", "\u03C4"}, {"upsilon", "\u03C5"}, {"phi", "\u03C6"}, {"chi", "\u03C7"}, {"psi", "\u03C8"}, {"omega", "\u03C9"}, // grec-majuscule {"Alpha", "\u0391"}, {"Beta", "\u0392"}, {"Gamma", "\u0393"}, {"Delta", "\u0394"}, {"Epsilon", "\u0395"}, {"Zeta", "\u0396"}, {"Eta", "\u0397"}, {"Theta", "\u0398"}, {"Iota", "\u0399"}, {"Kappa", "\u039A"}, {"Lambda", "\u039B"}, {"Mu", "\u039C"}, {"Nu", "\u039D"}, {"Xi", "\u039E"}, {"Omicron", "\u039F"}, {"Pi", "\u03A0"}, {"Rho", "\u03A1"}, {"Sigma", "\u03A3"}, {"Tau", "\u03A4"}, {"Upsilon", "\u03A5"}, {"Phi", "\u03A6"}, {"Chi", "\u03A7"}, {"Psi", "\u03A8"}, {"Omega", "\u03A9"}, // autre grec {"thetasym", "\u03D1"}, {"upsih", "\u03D2"}, {"piv", "\u03D6"}, // autres caractères {"infin", "\u221E"}, {"infty", "\u221E"}, {"infini", "\u221E"}, {"sun", "\u2609"}, {"soleil", "\u2609"}, {"star", "\u2605"}, {"étoile", "\u2605"}, {"earth", "\u2641"}, {"terre", "\u2641"}, {"planck", "\u210F"}, {"angstrom", "\u212B"}, {"angström", "\u212B"}, {"petitl", "\u2113"}, {"asterisk", "*"}, {"astérisque", "*"}, // \uFF0A ? /*{"grandg", "\u1D4A2"},*/ }; // fonctions qui peuvent se passer de parenthèses quand il n'y a qu'un argument simple private static String[] fctnopar = {"sin", "cos", "tan", "acos", "asin", "atan"}; public StringMathBuilder(String s) { rootElement = new MathRootElement(); String s2 = ajParentheses(replaceSpecial(s)); if (!s.equals("")) { MathElement me = parser(s2, false); rootElement.addMathElement(me); } } /** * Return the root element of a math tree * * @return Root element */ public MathRootElement getMathRootElement() { return rootElement; } public String replaceSpecial(String s) { for (int i=0; i f((a+1);b;c) int indop = s.indexOf(';'); while (indop != -1) { // vers la gauche du ; int pp = 0; boolean yaop = false; char c; for (int i=indop-1; i>=0 && pp>=0; i--) { c = s.charAt(i); if (c == ';' && pp == 0) break; // les parenthèses sont déjà ajoutées if (c == '(') pp--; else if (c == ')') pp++; else if (sops.indexOf(c) != -1) yaop = true; if (pp < 0 && yaop) { s = s.substring(0,i) + '(' + s.substring(i,indop) + ')' + s.substring(indop); indop += 2; } } // vers la droite du ; pp = 0; yaop = false; for (int i=indop+1; i=0; i++) { c = s.charAt(i); if (c == '(') pp++; else if (c == ')') pp--; else if (sops.indexOf(c) != -1) yaop = true; if ((pp < 0 || (pp == 0 && c == ';')) && yaop) s = s.substring(0,indop+1) + '(' + s.substring(indop+1,i) + ')' + s.substring(i); if (c == ';' && pp == 0) break; } int indop2 = s.substring(indop+1).indexOf(';'); if (indop2 == -1) indop = indop2; else indop += indop2 + 1; } // les autres parenthèses for (int iops=0; iops= 0) cm = s.charAt(im); pp = 0; while (im >= 0 && (pp != 0 || cm != '(') && (pp != 0 || sops.indexOf(cm) == -1)) { if (cm == ')') pp++; else if (cm == '(') pp--; im--; if (im >= 0) cm = s.charAt(im); } if (im < 0 || sops.indexOf(cm) != -1) ajp = true; ip = indop + 1; if (ip >= 0 && ip <= s.length()-1) cp = s.charAt(ip); pp = 0; while (ip < s.length() && (pp != 0 || cp != ')') && (pp != 0 || sops.indexOf(cp) == -1)) { if (cp == '(') pp++; else if (cp == ')') pp--; ip++; if (ip < s.length()) cp = s.charAt(ip); } if (ip >= s.length() || sops.indexOf(cp) != -1) ajp = true; if (ajp) { s = s.substring(0, im+1) + "(" + s.substring(im+1, ip) + ")" + s.substring(ip); indop++; } nindop = s.substring(indop+1).indexOf(cops); indop = nindop + indop+1; } } return(s); } public MathElement parser(String s, boolean parentheses) { if (s == null || "".equals(s)) return(null); boolean ajparentheses = false; if (s.charAt(0) == '(' && s.charAt(s.length()-1) == ')') { int pp = 0; for (int i=1; i 0) p1 = (MathElement)vp.get(0); else p1 = null; if (vp.size() > 1) p2 = (MathElement)vp.get(1); else p2 = null; if (vp.size() > 2) p3 = (MathElement)vp.get(2); else p3 = null; if (vp.size() > 3) p4 = (MathElement)vp.get(3); else p4 = null; MathElement me; if ("sqrt".equals(nomfct) || "racine".equals(nomfct)) { me = new MathSqrt(); me.addMathElement(p1); } else if ("exp".equals(nomfct)) { me = new MathSup(); MathIdentifier mi = new MathIdentifier(); mi.addText("e"); me.addMathElement(mi); me.addMathElement(p1); } else if ("abs".equals(nomfct)) { me = new MathRow(); MathOperator mo = new MathOperator(); mo.addText("|"); me.addMathElement(mo); me.addMathElement(p1); mo = new MathOperator(); mo.addText("|"); me.addMathElement(mo); } else if ("fact".equals(nomfct) || "factorielle".equals(nomfct) || "factorial".equals(nomfct)) { me = new MathRow(); MathOperator mo; if (!(p1 instanceof MathIdentifier || p1 instanceof MathNumber)) { mo = new MathOperator(); mo.addText("("); me.addMathElement(mo); } me.addMathElement(p1); if (!(p1 instanceof MathIdentifier || p1 instanceof MathNumber)) { mo = new MathOperator(); mo.addText(")"); me.addMathElement(mo); } mo = new MathOperator(); mo.addText("!"); me.addMathElement(mo); } else if ("int".equals(nomfct) || "intégrale".equals(nomfct)) { me = new MathRow(); MathOperator mo = new MathOperator(); mo.addText("\u222B"); mo.setStretchy(true); if (p3 != null && p4 != null) { MathUnderOver munderover = new MathUnderOver(); munderover.addMathElement(mo); munderover.addMathElement(elemOrQuestion(p3)); munderover.addMathElement(elemOrQuestion(p4)); me.addMathElement(munderover); } else if (p3 != null) { MathUnder munder = new MathUnder(); munder.addMathElement(mo); munder.addMathElement(elemOrQuestion(p3)); me.addMathElement(munder); } else if (p4 != null) { MathOver mover = new MathOver(); mover.addMathElement(mo); mover.addMathElement(elemOrQuestion(p4)); me.addMathElement(mover); } else me.addMathElement(mo); MathRow mrow = new MathRow(); mrow.addMathElement(elemOrQuestion(p1)); // if (p2 != null) { mo = new MathOperator(); mo.addText("d"); // ⅆ mrow.addMathElement(mo); mrow.addMathElement(p2); } me.addMathElement(mrow); } else if ("prod".equals(nomfct) || "sum".equals(nomfct) || "produit".equals(nomfct) || "somme".equals(nomfct)) { me = new MathRow(); MathUnderOver munderover = new MathUnderOver(); MathOperator mo = new MathOperator(); if ("prod".equals(nomfct) || "produit".equals(nomfct)) mo.addText("\u220F"); else if ("sum".equals(nomfct) || "somme".equals(nomfct)) mo.addText("\u2211"); mo.setStretchy(true); munderover.addMathElement(mo); munderover.addMathElement(elemOrQuestion(p2)); munderover.addMathElement(elemOrQuestion(p3)); me.addMathElement(munderover); MathRow mrow = new MathRow(); mrow.addMathElement(elemOrQuestion(p1)); me.addMathElement(mrow); } else if ("over".equals(nomfct) || "dessus".equals(nomfct)) { MathOver mover = new MathOver(); mover.addMathElement(elemOrQuestion(p1)); mover.addMathElement(elemOrQuestion(p2)); me = mover; } else if ("subsup".equals(nomfct)) { MathSubSup msubsup = new MathSubSup(); msubsup.addMathElement(elemOrQuestion(p1)); msubsup.addMathElement(elemOrQuestion(p2)); msubsup.addMathElement(elemOrQuestion(p3)); me = msubsup; } else if ("accent".equals(nomfct)) { MathOver mover = new MathOver(); mover.setAccent(true); mover.addMathElement(elemOrQuestion(p1)); mover.addMathElement(elemOrQuestion(p2)); me = mover; } else if ("matrix".equals(nomfct) || "matrice".equals(nomfct)) { me = new MathRow(); MathOperator mo = new MathOperator(); mo.addText("("); me.addMathElement(mo); MathTable mtable = new MathTable(); for (int i=0; i 1) dernierDansP1 = dernierDansP1.getMathElement( dernierDansP1.getMathElementCount()-1); boolean p1nombre = dernierDansP1 instanceof MathNumber; MathElement premierDansP2 = p2; if (p2 != null) while (premierDansP2.getMathElementCount() > 1) premierDansP2 = premierDansP2.getMathElement(0); boolean p2nombre = premierDansP2 instanceof MathNumber; if (p1nombre && p2nombre) { MathOperator mo = new MathOperator(); mo.addText("×"); mrow.addMathElement(mo); } // else mrow.addMathElement(elemOrQuestion(p2)); return(mrow); } else { MathRow mrow = new MathRow(); if (p1 != null) mrow.addMathElement(p1); MathOperator mo = new MathOperator(); mo.addText(""+op); if ("=\u2260\u2248\u2264\u2265\u226A\u226B".indexOf(op) != -1) { // espace autour des opérateurs d'égalité mo.setLspace(0.5); mo.setRspace(0.5); } mrow.addMathElement(mo); if (p2 != null) mrow.addMathElement(p2); return(mrow); } } } private static MathElement elemOrQuestion(MathElement me) { if (me != null) return(me); else { MathText mtext = new MathText(); mtext.addText("?"); return(mtext); } } }