Evaluer une expression à partir d'une chaine de caractère

Soyez le premier à donner votre avis sur cette source.

Vue 6 167 fois - Téléchargée 354 fois

Description

Cette Source est surtout un exercice de style. Elle permet d'évaluer une expression par exemple :
2 + 4 ou encore 2*5 = 10. Elle supporte les opérateurs suivants :
+,-,*,/, %(->modulo),^(->Puissance), &(->Concaténation) AINSI QUE LES OPERATEURS DE COMPARAISON SUIVANTS
=, <>,<,>, ||, &&. Elle gère l'ordre des parenthèses({,(,),}) ainsi que l'ordre d'exécution des expressions.

J'ai mis deux versions de la classe. Une qui utilise la fonction EVAL, et l'autre uniquement du PHP. Si vous trouvez une moyen d'optimiser ces class. Merci de me le faire savoir, je les utilise pour un moteur de template dans un de mes projets personels.

Source / Exemple :


<?php
	/*------------------------------------------------------------
						EXERCICE DE STYLE
	------------------------------------------------------------*/
	function calcul_execution() {
		list($msec, $sec) = explode(' ', microtime());
		return ((float) $sec + (float) $msec) * 1000000;
	}
	
	
	include("Class_Evaluer.php"); //N'utilise pas la méthode Eval
	//include("Class_EvaluerB.php"); //Utilise la méthode Eval
	
	
	function Evaluer_Chaine($Chaine){
		$test=new Evaluation();
		$tab=$test->Evaluer($Chaine);
		echo "-->Evaluation de la Chaine : <b>".$Chaine."</b><br />\r\n";
	
		if(is_bool($tab)){
			if($tab){
				echo "---->Résultat : <b>VRAI</b> <br />\r\n&nbsp;<br />\r\n";
			}else{
				echo "---->Résultat : <b>FAUX</b> <br />\r\n&nbsp;<br />\r\n";
			}
		}else{
			echo "---->Résultat : <b>".$tab."</b> <br />\r\n&nbsp;<br />\r\n";
		}
	}

	$debut_calcul = calcul_execution();
	
	 Evaluer_Chaine(" 4^2^3 ");
	 Evaluer_Chaine(" 4^2^3 -42 ");
	 Evaluer_Chaine(" 'Salut' & ' tout le monde c\\'est chouette hein ?'");
	 Evaluer_Chaine(" 1+(3+2)*5 = 26");
	 Evaluer_Chaine(" 6*6 > 35 && 2>3");
	 Evaluer_Chaine(" 6*6 > 35 || 2>3");
	 Evaluer_Chaine(" (9%2) = 1");
	
	$fin_calcul = calcul_execution();	
	echo '<br />Temps execution: ',($fin_calcul-$debut_calcul)/1000000,' secondes.<br></span></center>'; 
?>

Conclusion :


J'attends vos remarques d'amélioration ainsi que tout autre remarques constructive.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Messages postés
6
Date d'inscription
samedi 10 octobre 2009
Statut
Membre
Dernière intervention
21 février 2019

Un bel exercice, mais le code n'est pas re-entrant
En pratique on utilise un compilateur de compilateur genre LEX et YACC (ou BISON) ou ANTLR

va voir sur http://www.linux-france.org/article/devl/lexyacc/minimanlexyacc-4.html pour un exemple

On doit créer un fichier de syntaxe et un fichier de définition et le compilateur génère le code source. Il existe une version de Lex et de Yacc pour PHP ou de ou de ANTLR pour PHP https://github.com/beberlei/antlr-php-runtime
Messages postés
385
Date d'inscription
lundi 27 février 2006
Statut
Membre
Dernière intervention
21 août 2015
2
L'arbre binaire c'est la méthode la plus viable.
Il y a déjà une source ici qui exploite cette méthode,
Messages postés
3
Date d'inscription
jeudi 29 novembre 2007
Statut
Membre
Dernière intervention
20 juin 2009

correction pour le tableau $tabSignes, j'avais oublié une valeur (ce que c'est de ne pas tester!)
le bon code:
$tabSignes=array("=","<>","&&","||","<",">","+","-","%","/","^","&","*","|");
Messages postés
3
Date d'inscription
jeudi 29 novembre 2007
Statut
Membre
Dernière intervention
20 juin 2009

à la place de
$tabSignes=array();
$tabSignes[0]="=";
$tabSignes[1]="<>";
$tabSignes[2]="&&";
$tabSignes[3]="||";
$tabSignes[4]="<";
$tabSignes[5]=">";
$tabSignes[6]="+";
$tabSignes[7]="-";
$tabSignes[8]="%";
$tabSignes[9]="/";
$tabSignes[10]="^";
$tabSignes[11]="&";
$tabSignes[12]="*";

perso, je mettrai:
$tabSignes=array("=","<>","&&","||","<",">","+","-","%","/","^","&","*");
on s'est évité n fois de rentrer au clavier
$tabSignes[n]="une valeur";

pour un tableau multi dimensionné:
$Montab = array(
"Champ0"=>"valeur0",
"Champ1"=>"valeur1",
"ChampN=>"valeurN"
);

je ne sais pas s'il y a une différence de rapidité d'exécution entre
if($var=="quelque chose")
ou
if($var==="quelque chose")
par contre l'instruction de comparaison == vérifie l'égalité mais ne vérifie pas le type des variables
alors que === vérifie que les deux termes de la condition sont strictement identiques et de même type.
exemple:
$var = 0;
if($var == '0') renvoie true // c'est nul, c'est tout.
if($var==='0') renvoie false // le nombre zéro n'est pas identique au caractère zéro

Dans l'évaluation de chaînes, ça peut avoir son importance.

autre exemple de l'intérêt des comparateurs stricts

$myvar = '0'; // variable avec une valeur non nulle affectée
if(!empty($myvar)) {
// faire ceci
}
else {
// faire cela
}
c'est "faire cela" qui va s'exécuter alors que je considère pour ma part que c'est "faire ceci" qui devrait s'exécuter;

avec les comparateurs stricts il n'y a pas de confusion possible:
if($myvar !==NULL) // si une valeur quelconque affectée
echo" faire ceci";
}
else {
echo "faire cela";
}
Messages postés
40
Date d'inscription
mercredi 19 mars 2008
Statut
Membre
Dernière intervention
25 août 2009

Je vais répondre rapidement par faute de temps !

Alors pour la première condition! En fait il s'agit d'un exercice de style c'est donc au développeur de changer cette valeur !

Tu parles d'une manière moins fastidieuse de remplir un tableau ? je suis prenneur de toute nouvelle méthode !!!
Tu soulèves une intérrogation le est plus rapide que le simple ???

Merci de tes remarques.
Bien Cordialement
Afficher les 9 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.