/*
* Created by yvesb on 12/12/2016.
*/
/*
* MathGraph32 Javascript : Software for animating online dynamic mathematics figures
* https://www.mathgraph32.org/
* @version 5.1.2
* @Author Yves Biton (yves.biton@sesamath.net)
* @License: GNU AGPLv3 https://www.gnu.org/licenses/agpl-3.0.html
*/
import CCbGlob from './CCbGlob'
import Pointeur from '../types/Pointeur'
import Ope from '../types/Ope'
import Opef4v from '../types/Opef4v'
import Opef5v from '../types/Opef5v'
import Fonte from '../types/Fonte'
import CalcR from '../kernel/CalcR'
import { erreurCalculException } from '../kernel/kernel'
import CAppelFonctionComplexe from '../objets/CAppelFonctionComplexeBase'
import CAppelFonctionComplexeNVar from '../objets/CAppelFonctionComplexeNVar'
import CConstante from '../objets/CConstante'
import CConstantei from '../objets/CConstantei'
import CFonction from '../objets/CFonction'
import CFonction2Var from '../objets/CFonction2Var'
import CFonction3Var from '../objets/CFonction3Var'
import CIntegraleDansFormule from '../objets/CIntegraleDansFormule'
import CPrimitive from '../objets/CPrimitive'
import CMoinsUnaire from '../objets/CMoinsUnaire'
import CVariableFormelle from '../objets/CVariableFormelle'
import CSommeDansFormule from '../objets/CSommeDansFormule'
import COp from '../objets/COperation'
import CProduitDansFormule from '../objets/CProduitDansFormule'
import CPuissance from '../objets/CPuissance'
import CResultatValeurComplexe from '../objets/CResultatValeurComplexe'
import CTermMat from '../objets/CTermMat'
import CCbNull from '../objets/CCbNull'
/**
* Fonction statique récursive créant un arbre binaire de calcul à partir de la chaîne
* de caractères ch représentant le calcul, la chaîne étant interprétée de pdebut à pfin.
* nomsVariablesFormelles est un array dont les éléments représentent les noms éventuels des variables
* formelles quand le calcul évalué représente une fonction.
* Le calcul renvoie un résultat complexe.
* @param {string} ch La chaîne décrivant le calcul.
* @param {CListeObjets} ptListe La liste propriétaire du calcul à créer
* @param {number} pdebut L'indice du début de l'interprétationde la chaîne
* @param {number} pfin L'indice de la fin de l'interprétationde la chaîne
* @param {string[]} nomsVariablesFormelles Un tableau donnant les noms des variables
* formelles dans le cas où le calcul est utilisé à l'intérieur d'une focntion de
* une ou plusieurs variables.
* @param {CListeObjets} listeSource La liste source des objets utilisables (ne diffère de ptListe que pour les exercices de construction)
* @returns {CCb}
*/
function ccbComp (ch, ptListe, pdebut, pfin, nomsVariablesFormelles, listeSource) {
if (arguments.length <= 5) listeSource = ptListe
try {
// Spécial JavaScript car pas d'erreur levée par charAt si pdebut > pFin
if (pdebut > pfin) throw new Error()
let ptr
const info = { x: 0, y: 0 } // Contiendra dans x l'indice du caractère
// précédent
// et dans y l'opérateur trouvé (correspond au ptPrecedent et
// operateurInegalite
// de la version C++
// int ptPrecedent;
// int operateurInegalite;
let car
let op
const nomF = new Pointeur(null)
const ptVa = new Pointeur(null)
const parametreTrouve = new Pointeur(0)
const nombreVar = new Pointeur(0)
const complexeiTrouve = new Pointeur(false)
// On élimine les blancs de début
car = ch.charAt(pdebut)
while ((car === ' ') && (pdebut < pfin)) {
pdebut++
car = ch.charAt(pdebut)
}
// On recherche d'abord les opérateurs de ou logique
ptr = CCbGlob.premierOperateurLogique('|', ch, pdebut, pfin, info)
if (ptr !== -1) {
return new COp(ptListe, CalcC.ccbComp(ch, ptListe, pdebut,
info.x, nomsVariablesFormelles, listeSource), CalcC.ccbComp(ch, ptListe, ptr + 1,
pfin, nomsVariablesFormelles, listeSource), info.y)
}
// On recherche ensuite les opérateurs de et logique
ptr = CCbGlob.premierOperateurLogique('&', ch, pdebut, pfin, info)
if (ptr !== -1) {
return new COp(ptListe, CalcC.ccbComp(ch, ptListe, pdebut,
info.x, nomsVariablesFormelles, listeSource), CalcC.ccbComp(ch, ptListe, ptr + 1,
pfin, nomsVariablesFormelles, listeSource), info.y)
}
ptr = CCbGlob.premiereInegalite(ch, pdebut, pfin, info)
if (ptr !== -1) {
return new COp(
ptListe,
ccbComp(ch, ptListe, pdebut, info.x, nomsVariablesFormelles, listeSource),
ccbComp(ch, ptListe, ptr + 1, pfin, nomsVariablesFormelles, listeSource),
info.y
)
}
// On recherche ensuite les operateurs d'addition ou soustraction
ptr = CCbGlob.premiereSomme(ch, pdebut, pfin)
if (ptr !== -1) {
// On regarde d'abord si la chaine commence par un signe - ou
// un signe +
car = ch.charAt(ptr)
if (car === '+') { op = Ope.Plus } else { op = Ope.Moin }
if (ptr === pdebut) {
car = ch.charAt(ptr)
if (car === '+') {
return ccbComp(ch, ptListe, pdebut + 1, pfin, nomsVariablesFormelles, listeSource)
}
return new CMoinsUnaire(ptListe, ccbComp(ch,
ptListe, pdebut + 1, pfin, nomsVariablesFormelles, listeSource))
}
return new COp(
ptListe,
ccbComp(ch, ptListe, pdebut, ptr - 1, nomsVariablesFormelles, listeSource),
ccbComp(ch, ptListe, ptr + 1, pfin, nomsVariablesFormelles, listeSource),
op
)
}
ptr = CCbGlob.premierProduit(ch, pdebut, pfin)
if (ptr !== -1) {
car = ch.charAt(ptr)
if (car === '*') { op = Ope.Mult } else { op = Ope.Divi }
return new COp(
ptListe,
ccbComp(ch, ptListe, pdebut, ptr - 1, nomsVariablesFormelles, listeSource),
ccbComp(ch, ptListe, ptr + 1, pfin, nomsVariablesFormelles, listeSource),
op
)
}
// Le calcul ne contient ni addition, ni différence, ni produit
// ni quotient}
// Attention : par rapport à la version C++ 1.8, autorisation
// du symbole ² d'élévation au carré.
ptr = CCbGlob.premierePuissance(ch, pdebut, pfin)
if (ptr !== -1) {
if (ch.charAt(ptr) === '²') {
return new CPuissance(ptListe, ccbComp(ch, ptListe, pdebut, ptr - 1, nomsVariablesFormelles, listeSource), new CConstante(ptListe, 2))
}
return new CPuissance(
ptListe,
ccbComp(ch, ptListe, pdebut, ptr - 1, nomsVariablesFormelles, listeSource),
ccbComp(ch, ptListe, ptr + 1, pfin, nomsVariablesFormelles, listeSource)
)
}
// On regarde si la chaine commence par le nom d'une fonction
// ou d'une valeur déjà définie
const longNom = ptListe.commenceParNomFonctionOuValeurOuParametreComplexe(
ch.substring(pdebut), nomsVariablesFormelles, ptVa, nomF, parametreTrouve, complexeiTrouve, nombreVar)
if (longNom > 0) {
if (complexeiTrouve.getValue()) {
return new CConstantei(ptListe)
}
if (parametreTrouve.getValue() !== -1) {
return new CVariableFormelle(ptListe, parametreTrouve.getValue())
}
if (ptVa.getValue() === null) {
// Modification version 3.0. Il faut regarder si la fonction
// est une fonction de plusieurs paramètres ou non
// Ajouté version 4.7.4.1
if (CCbGlob.parentheseFermante(ch, pdebut + longNom) === -1) throw new Error(erreurCalculException)
if (nombreVar.getValue() === 1) {
return new CFonction(ptListe, nomF.getValue(),
ccbComp(ch, ptListe, pdebut + longNom,
pfin, nomsVariablesFormelles, listeSource))
}
if (nombreVar.getValue() === 2) {
const indicePremiereVirg = CCbGlob.premiereVirgule(ch, pdebut +
longNom + 1)
const operande1 = ccbComp(ch, ptListe, pdebut + longNom + 1, indicePremiereVirg - 1, nomsVariablesFormelles, listeSource)
const indiceParF = CCbGlob.parentheseFermanteApresVirgule(ch, indicePremiereVirg + 1)
// A revoir plus tard si on crée des fonctions de trois
// variables ou plus
const operande2 = ccbComp(ch, ptListe, indicePremiereVirg + 1, indiceParF - 1, nomsVariablesFormelles, listeSource)
return new CFonction2Var(ptListe, nomF.getValue(), operande1, operande2)
}
if (nombreVar.getValue() === 3) { // 3 variables
const indicePremiereVirg = CCbGlob.premiereVirgule(ch, pdebut + longNom + 1)
// Traitement de syntaxe particulier pour un calcul
// d'intégrale de fonction, le premier argument devant
// être le nom
// d'une fonction prédéfinie
const operande1 = ccbComp(ch, ptListe,
pdebut + longNom + 1, indicePremiereVirg - 1,
nomsVariablesFormelles, listeSource)
const indiceDeuxiemeVirg = CCbGlob.premiereVirgule(ch,
indicePremiereVirg + 1)
const operande2 = ccbComp(ch,
ptListe, indicePremiereVirg + 1,
indiceDeuxiemeVirg - 1, nomsVariablesFormelles, listeSource)
const indiceParF = CCbGlob.parentheseFermanteApresVirgule(ch, indiceDeuxiemeVirg + 1)
// A revoir plus tard si on crée des fonctions de
// trois variables ou plus
const operande3 = ccbComp(ch, ptListe, indiceDeuxiemeVirg + 1, indiceParF - 1, nomsVariablesFormelles, listeSource)
return new CFonction3Var(ptListe, nomF.getValue(), operande1, operande2, operande3)
}
// Pas de calcul d'intégrale dans un calcul complexe
if (nombreVar.getValue() === 4) { // Calcul d'intégrale
// Si les bornes ne sont pas réelles, c'est leur
// partie réelle qui sera utilisée
const indicePremiereVirg = CCbGlob.premiereVirgule(ch, pdebut + longNom + 1)
const indiceDeuxiemeVirg = CCbGlob.premiereVirgule(ch, indicePremiereVirg + 1)
const indiceTroisiemeVirg = CCbGlob.premiereVirgule(ch, indiceDeuxiemeVirg + 1)
const indiceParF = CCbGlob.parentheseFermanteApresVirgule(ch, indiceTroisiemeVirg + 1)
const nomVariableSommation = ch.substring(indicePremiereVirg + 1, indiceDeuxiemeVirg).trim()
// Un seul paramètre autorisé pour un calcul
// d'intégrale dans un calcul complexe : la variable
// formelle
const nomVariableFormelle3 = new Array(1)
nomVariableFormelle3[0] = nomVariableSommation
const Classef4var = (nomF.getValue() === Opef4v.integrale) ? CIntegraleDansFormule : CPrimitive
return new Classef4var(ptListe,
CalcR.ccb(ch, ptListe, pdebut + longNom + 1, indicePremiereVirg - 1, nomVariableFormelle3, listeSource),
ccbComp(ch, ptListe, indiceDeuxiemeVirg + 1, indiceTroisiemeVirg - 1, null, listeSource),
ccbComp(ch, ptListe, indiceTroisiemeVirg + 1, indiceParF - 1, null, listeSource),
nomVariableSommation,
true
)
}
// Fonction à 5 variables : la somme indicée et le
// produit indicé
const indicePremiereVirg = CCbGlob.premiereVirgule(ch, pdebut + longNom + 1)
const indiceDeuxiemeVirg = CCbGlob.premiereVirgule(ch, indicePremiereVirg + 1)
const indiceTroisiemeVirg = CCbGlob.premiereVirgule(ch, indiceDeuxiemeVirg + 1)
const indiceQuatriemeVirg = CCbGlob.premiereVirgule(ch, indiceTroisiemeVirg + 1)
const indiceParF = CCbGlob.parentheseFermanteApresVirgule(ch, indiceQuatriemeVirg + 1)
const nomVariableSommation = ch.substring(indicePremiereVirg + 1, indiceDeuxiemeVirg).trim()
let n = 0
if (nomsVariablesFormelles !== null) n = nomsVariablesFormelles.length
const nomVariableFormelle2 = new Array(n + 1)
for (let j = 0; j < n; j++) { nomVariableFormelle2[j] = nomsVariablesFormelles[j] }
nomVariableFormelle2[n] = nomVariableSommation
if (nomF.getValue() === Opef5v.sommeC) {
return new CSommeDansFormule(ptListe,
ccbComp(ch, ptListe, pdebut +
longNom + 1, indicePremiereVirg - 1, nomVariableFormelle2, listeSource),
ccbComp(ch, ptListe,
indiceDeuxiemeVirg + 1, indiceTroisiemeVirg - 1,
nomVariableFormelle2, listeSource),
ccbComp(ch, ptListe,
indiceTroisiemeVirg + 1, indiceQuatriemeVirg - 1,
nomVariableFormelle2, listeSource),
ccbComp(ch, ptListe,
indiceQuatriemeVirg + 1, indiceParF - 1,
nomVariableFormelle2, listeSource), nomVariableSommation)
}
return new CProduitDansFormule(ptListe,
ccbComp(ch, ptListe, pdebut + longNom + 1, indicePremiereVirg - 1, nomVariableFormelle2, listeSource),
ccbComp(ch, ptListe, indiceDeuxiemeVirg + 1, indiceTroisiemeVirg - 1, nomVariableFormelle2, listeSource),
ccbComp(ch, ptListe, indiceTroisiemeVirg + 1, indiceQuatriemeVirg - 1, nomVariableFormelle2, listeSource),
ccbComp(ch, ptListe, indiceQuatriemeVirg + 1, indiceParF - 1, nomVariableFormelle2),
nomVariableSommation,
listeSource
)
}
if (ptVa.getValue().estFonctionOuSuite()) {
const calc = ptVa.getValue()
const nbvar = calc.nombreVariables()
if (nbvar === 1) {
return new CAppelFonctionComplexe(ptListe, ptVa.getValue(), ccbComp(ch, ptListe, pdebut + longNom, pfin, nomsVariablesFormelles, listeSource))
}
const tabcal = new Array(nbvar)
let deb = pdebut + longNom
let fin = 0
for (let i = 0; i < nbvar - 1; i++) {
fin = CCbGlob.premiereVirgule(ch, deb + 1)
tabcal[i] = ccbComp(ch, ptListe,
deb + 1, fin - 1, nomsVariablesFormelles, listeSource)
deb = fin
}
deb++
fin = CCbGlob.parentheseFermanteApresVirgule(ch, deb)
tabcal[nbvar - 1] = ccbComp(ch, ptListe,
deb, fin - 1, nomsVariablesFormelles, listeSource)
return new CAppelFonctionComplexeNVar(ptListe, nbvar, ptVa.getValue(), tabcal)
}
if (ptVa.getValue().estMatrice() && ch.charAt(pdebut + longNom) === '(') {
const tabcal = new Array(2)
let deb = pdebut + longNom
let fin = CCbGlob.premiereVirgule(ch, deb + 1)
tabcal[0] = CalcR.ccb(ch, ptListe, deb + 1, fin - 1, nomsVariablesFormelles, listeSource)
deb = fin + 1
fin = CCbGlob.parentheseFermanteApresVirgule(ch, deb)
tabcal[1] = CalcR.ccb(ch, ptListe, deb,
fin - 1, nomsVariablesFormelles, listeSource)
return new CTermMat(ptListe, tabcal[0], tabcal[1], ptVa.getValue())
}
return new CResultatValeurComplexe(ptListe, ptVa.getValue())
}
// Dans le cas où l'expression commence par une parenthèse
// ouvrante, elle finit par une fermante et il suffit
// d'évaluer ce que la parenthèse contient
car = ch.charAt(pdebut)
// Si le premier caractère est une parenthèse ouvrante
// il faut faire attention car le dernier peut être
// un espace.
// Cela a donné un bug dans la version 16 bits
if (car === '(') {
if (CCbGlob.parentheseFermante(ch, pdebut) === -1) throw new Error()
return ccbComp(ch, ptListe, pdebut + 1,
CCbGlob.parentheseFermante(ch, pdebut) - 1, nomsVariablesFormelles, listeSource)
}
// Le résultat ne peut être que numérique}
let chaineNombre = ''
let ptch = pdebut
while ((Fonte.chiffre(car) || (car === '.')) && (ptch <= pfin)) {
car = ch.charAt(ptch)
chaineNombre = chaineNombre + car
ptch++
}
if (chaineNombre === '') throw new Error() // Spécial JavaScript
const f = parseFloat(chaineNombre)
if (isNaN(f)) throw new Error()
return new CConstante(ptListe, f)
} catch (e) {
// Amélioration version 4.7.4.1 : Même si l'expression est incorrecte, on remplace les * de multiplication par des \times
// Supprimé version 4.9.3
const ch1 = ch.substring(pdebut, pfin + 1)
// Amélioration version 4.9.3
if ((ch1.charAt(0) === '(') && (ch1.length >= 1)) { // Cas d'une parenthèse ouvrante non fermée
return ccbComp(ch, ptListe, pdebut + 1, pfin, nomsVariablesFormelles, listeSource)
}
//
return new CCbNull(ch1)
}
}
/**
* Fonction récursive vérifiant la syntaxe de l'expression réelle contenue dans ch en
* tenant compte du fait qu'elle ne doit pas utiliser de valeur dont l'indice
* dans ptListe est strictement supérieur à indiceMaxiDansListe.
* Le calcul est complexe mais peut utiliser des résultats réels.
* @param {CListeObjets} ptListe La listeProprietaire du calcul analysé.
* @param {string} ch La chaîne dans laquelle se fait la recherche.
* @param {Pointeur} indiceErreur getValeur renverra l'indice de l'erreur
* de syntaxe dans la chapine s'il y en a une.
* @param {number} indiceMaxiDansListe L'indice maxi d'interprétation dans la chaîne ch
* @param {string[]} parametreFormel Un tableau représentant les noms de la ou des variables formelles
* d'une fonction de une ou plusieurs variables.
* @returns {boolean} : true si la syntaxe est correcte, false sinon.
*/
function verifieSyntaxeComplexe (ptListe, ch, indiceErreur, indiceMaxiDansListe,
parametreFormel) {
let i, nvirg
let indiceDansListe
let pdebut
let car, carSuivant
let erreur
let itemPrecedent
let itemSuivant = 0
let pointDecimalRencontre
let sommeParentheses
let longNom
const nomF = new Pointeur()
const ptVa = new Pointeur()
let queDesBlancs
const complexei = new Pointeur(false)
const parametreTrouve = new Pointeur(0)
const nombreVariables = new Pointeur(0)
let nivPar = 0 // Niveau de parenthèses
const appelFonction = new Array(CCbGlob.nombreMaxParentheses + 1) // 64 niveaux de parenthèses imbriqués maxi
for (let j = 0; j <= CCbGlob.nombreMaxParentheses; j++) appelFonction[j] = false
erreur = false
const longueurCh = ch.length
// On vérifie d'abord qu'il n'y a pas d'erreur de parenthèse
if (longueurCh === 0) {
indiceErreur.setValue(0)
return false
}
i = 0
sommeParentheses = 0
while ((i < longueurCh) && (sommeParentheses >= 0)) {
car = ch.charAt(i)
switch (car) {
case '(':
sommeParentheses++
break
case ')':
sommeParentheses--
} // switch
i++
}
if (sommeParentheses !== 0) {
indiceErreur.setValue(i)
return false
}
if (ch === '.') {
indiceErreur.setValue(0)
return false
}
i = 0
itemPrecedent = CCbGlob.ParOuvrante
while ((i < longueurCh) && !erreur) {
car = ch.charAt(i)
pointDecimalRencontre = false
if (Fonte.chiffre(car) || (car === '.')) {
while ((Fonte.chiffre(car) || (car === '.')) && (i < longueurCh) &&
!erreur) {
if (car === '.') {
if (pointDecimalRencontre) {
erreur = true
indiceErreur.setValue(i - 1)
// IndiceMessageErreur = IDE_SYNTAXE1;
} else { pointDecimalRencontre = true }
}
i++
if (i < longueurCh) { car = ch.charAt(i) }
} // while
if (!erreur) { itemSuivant = CCbGlob.Nombre }
} else {
// cas où le caractère en cours n'est pas un nombre
// le caractère en cours n'est pas un chiffre ou un point décimal}
pdebut = i
// On regarde si cela commence par le nom d'une fonction ou
// une valeur déjà définie
longNom = ptListe.commenceParNomFonctionOuValeurOuParametreComplexe(
ch.substring(pdebut), parametreFormel, ptVa, nomF, parametreTrouve,
complexei, nombreVariables)
if (longNom > 0) {
if (complexei.getValue()) {
itemSuivant = CCbGlob.Valeur
i = i + longNom
} else {
if (parametreTrouve.getValue() !== -1) {
itemSuivant = CCbGlob.Valeur
i = i + longNom
} else {
appelFonction[nivPar + 1] = true
if (ptVa.getValue() === null) {
if (((i + longNom) < ch.length) &&
ch.charAt(i + longNom) !== '(') {
erreur = true
indiceErreur.setValue(i + longNom)
} else {
itemSuivant = CCbGlob.Fonction
// Ajout version 4.5.2 pour corriger un bug
if (!CCbGlob.autorisationSyntaxe(itemPrecedent, itemSuivant)) {
erreur = true
indiceErreur.setValue(i)
break
}
nvirg = CCbGlob.NombreVirgules(ch, i + longNom + 1)
if (nvirg !== nombreVariables.getValue() - 1) {
if (nvirg <= nombreVariables.getValue() - 1) {
indiceErreur.setValue(CCbGlob.indiceCaractereVirgule(ch, i +
longNom + 1, nvirg))
} else {
indiceErreur.setValue(CCbGlob.indiceCaractereVirgule(ch, i +
longNom + 1, nombreVariables.getValue() - 1) - 1)
}
erreur = true
} else {
// Seule fonction complexe à 4 variables ou plus : le calcul
// de somme indicée
if (nombreVariables.getValue() >= 4) {
nivPar++
const indicePremVirg = CCbGlob.premiereVirgule(ch, i + longNom + 1)
const chformuleASommer = ch.substring(i + longNom + 1, indicePremVirg)
const indiceDeuxiemeVirg = CCbGlob.premiereVirgule(ch, indicePremVirg + 1)
let nomVariableSommation = ch.substring(indicePremVirg + 1, indiceDeuxiemeVirg)
nomVariableSommation = nomVariableSommation.trim()
if (!ptListe.validationNomCalculSansMessage(nomVariableSommation) ||
ptListe.egalNomValeurOuFonctionOuMesure(
nomVariableSommation, -1)) {
erreur = true
indiceErreur.setValue(indiceDeuxiemeVirg)
} else {
// On vérifie si la syntaxe du calcul à sommer est
// correct.
// Pour cela on appelle à nouveau vérifieSyntaxe
const indiceErreur2 = new Pointeur(0)
let n = 0
if (parametreFormel !== null) n = parametreFormel.length
const parametreFormel2 = new Array(n + 1)
for (let j = 0; j < n; j++) parametreFormel2[j] = parametreFormel[j]
parametreFormel2[n] = nomVariableSommation
let b
if ((nombreVariables.getValue() === 4) && (nomF.getValue() === Opef4v.integraleC)) {
// Cas d'un calcul d'intégrale
// Ne doit utiliser que fonctions ou valeurs réelles
// On ne passe donc comme variable formelle que
// nomVariableSommation
const parametreFormel3 = new Array(1)
parametreFormel3[0] = nomVariableSommation
b = CalcR.verifieSyntaxe(ptListe, chformuleASommer,
indiceErreur2, indiceMaxiDansListe, parametreFormel3)
} else {
b = verifieSyntaxeComplexe(ptListe, chformuleASommer,
indiceErreur2, indiceMaxiDansListe, parametreFormel2)
}
if (!b) {
erreur = true
indiceErreur.setValue(i + longNom + 1 + indiceErreur2.getValue())
} else {
i = indiceDeuxiemeVirg + 1
itemPrecedent = CCbGlob.Valeur
itemSuivant = CCbGlob.Virgule
}
}
} else { i += longNom }
}
}
} else {
const vd = ptVa.getValue()
indiceDansListe = ptListe.indexOf(vd)
if (indiceDansListe > indiceMaxiDansListe) {
erreur = true
indiceErreur.setValue(i)
} else {
i += longNom
if (vd.estFonctionOuSuite()) {
if ((i < ch.length) && ch.charAt(i) !== '(') {
erreur = true
indiceErreur.setValue(i + longNom)
} else {
itemSuivant = CCbGlob.Fonction
const nbvar = vd.nombreVariables()
if (nbvar >= 2) {
nvirg = CCbGlob.NombreVirgules(ch, i + 1)
if (nvirg !== nombreVariables.getValue() - 1) {
if (nvirg <= nombreVariables.getValue() - 1) { indiceErreur.setValue(CCbGlob.indiceCaractereVirgule(ch, i + 1, nvirg)) } else {
indiceErreur.setValue(CCbGlob.indiceCaractereVirgule(ch, i + 1,
nombreVariables.getValue() - 1) - 1)
}
erreur = true
}
} else {
// Bug corrigé version 4.6 : Il ne faut pas qu'un appel de fonction d'une variable comprenne des virgules
if (CCbGlob.NombreVirgules(ch, i + 1) > 0) {
indiceErreur.setValue(ch.indexOf(',', i + 1))
erreur = true
}
}
}
} else {
if (vd.estMatrice()) {
if ((i < ch.length) && ch.charAt(i) === '(') {
// Un nom de matrice suivi de deux paramètres fait référence à un terme de la matrice
itemSuivant = CCbGlob.Fonction
nvirg = CCbGlob.NombreVirgules(ch, i + 1)
if (nvirg !== 1) {
if (nvirg <= 1) {
indiceErreur.setValue(CCbGlob.indiceCaractereVirgule(ch,
i + 1, nvirg))
} else {
indiceErreur.setValue(CCbGlob.indiceCaractereVirgule(ch,
i + 1, 1) - 1)
}
erreur = true
}
} else {
erreur = true
indiceErreur.setValue(i)
}
} else {
itemSuivant = CCbGlob.Valeur
}
}
}
}
}
}
} else {
switch (car) {
case '+':
case '-':
itemSuivant = CCbGlob.Addition
i++
break
case '*':
case '/':
itemSuivant = CCbGlob.Multiplication
i++
break
case '(':
if (nivPar >= CCbGlob.nombreMaxParentheses - 1) {
erreur = true
indiceErreur.setValue(i)
} else {
itemSuivant = CCbGlob.ParOuvrante
i++
nivPar++
}
break
case ')':
appelFonction[nivPar] = false
nivPar--
itemSuivant = CCbGlob.ParFermante
i++
break
case '^':
itemSuivant = CCbGlob.Puissance
i++
break
// Ajout par rapport à la version C++ 1.8, autorisation du carré ²
case '²':
itemSuivant = CCbGlob.Carre
i++
break
// ni nombre ni opérateur}
case '<':
itemSuivant = CCbGlob.Inegalite
i++
if (i <= longueurCh - 2) {
carSuivant = ch.charAt(i)
if ((carSuivant === '=') || (carSuivant === '>')) { i++ }
}
break
case '>':
itemSuivant = CCbGlob.Inegalite
i++
if (i <= longueurCh - 2) {
carSuivant = ch.charAt(i)
if (carSuivant === '=') { i++ }
}
break
case '&':
case '|':
case '=':
itemSuivant = CCbGlob.Inegalite
i++
break
case ' ':
itemSuivant = CCbGlob.Blanc
i++
break
case ',':
if (!appelFonction[nivPar]) {
erreur = true
indiceErreur.setValue(i)
} else {
itemSuivant = CCbGlob.Virgule
i++
}
break
default: // switch Car
erreur = true
indiceErreur.setValue(i - 1)
} // switch Car
}// else du if LongNom > 0
} // else du if Chiffre(Car) || (Car === '.'))
if (!erreur) {
if (CCbGlob.autorisationSyntaxe(itemPrecedent, itemSuivant)) {
if (itemSuivant !== CCbGlob.Blanc) itemPrecedent = itemSuivant
} else {
erreur = true
// IndiceMessageErreur = IDE_SYNTAXE1;
indiceErreur.setValue(i - 1)
}
}
} // while
// Il faut aussi regarder si la fin de l'expression est correcte
itemSuivant = CCbGlob.ParFermante
if (!erreur) {
if (!CCbGlob.autorisationSyntaxe(itemPrecedent, itemSuivant)) {
erreur = true
indiceErreur.setValue(longueurCh)
}
}
if (indiceErreur.getValue() < 0) indiceErreur.setValue(0)
else if (indiceErreur.getValue() > longueurCh) indiceErreur.setValue(longueurCh)
i = 0
queDesBlancs = true
while ((i <= longueurCh - 1) && queDesBlancs) {
car = ch.charAt(i)
if (car !== ' ') { queDesBlancs = false } else { i++ }
}
if (queDesBlancs) {
// MessageBeep(0);
erreur = true
indiceErreur.setValue(longueurCh)
// IndiceMessageErreur = IDE_SYNTAXE1;
}
// if (Erreur) MessageBeep(0);
return !erreur
}
const CalcC = {
ccbComp,
verifieSyntaxeComplexe
}
export default CalcC