Évaluateur d'expressions booléennes (bee)

Soyez le premier à donner votre avis sur cette source.

Vue 6 644 fois - Téléchargée 371 fois

Description

BEE(Boolean Expression Evaluator) permet d'évaluer des expressions booléennes.

Les opérateurs et symboles prédéfinis sont :
0 : faux
1 : vrai
& : opérateur et
| : opérateur ou
! : opérateur non
( : parenthèse gauche
) : parenthèse droite
Il est cependant possible de spécifier ses propres valeurs.

Des variables peuvent de plus être utilisées dans les expressions.

Les erreurs (de syntaxe, de parenthésage, de variable indéfinie) sont gérées et peuvent être récupérées en utilisant un bloc try catch autour de l'appel de la méthode eval (voir l'exemple "simple").
Il est possible de connaître la description de l'erreur et la position du caractère fautif dans l'expression normalisée.

Le code est commenté et documenté (la documentation est déjà générée et le fichier Doxyfile est fourni).

Deux exemples sont fournis avec le code :
- simple : permet d'évaluer des expressions booléenne avec variables et possibilité de choisir ses opérateurs.
- table : permet de générer la table de vérité d'une expression booléenne. (c'est celui qui est affiché ci-dessous)

Attention, le zip et le code fournis sur cette page ne sont pas forcément à jour ! Pour voir les dernières sources, rendez-vous ici : https://bitbucket.org/mcc/dev/src/tip/BEE/

Source / Exemple :


#include "../../src/BEE.hpp"
#include <iomanip>
#include <cmath>

int main(int argc, char** argv) {
	
	if(argc == 1) {
		std::cerr << "Usage : " << argv[0] << " expression booleenne"
				  << std::endl;
		return 1;
	}
	
	try {
		BEE bee(argv[1]);
		std::vector<std::string> vars = bee.vars();
		
		//Affichage de l'entête.
		for(unsigned int i = 0; i < vars.size(); i++) {
			std::cout << vars[i] << " ";
		}
		std::cout << argv[1] << std::endl;
		
		//On doit trouver toutes les valeurs possibles pour toutes les
		//variables. Ca revient à convertir en binaire les nombres de 0 à 
		//2 ^ nbVars. On prend ensuite chaque bit de ces nombres et on assigne
		//chacun d'eux à la variable associée.
		int nbVars = vars.size();
		int sizeType = 4 * sizeof(int);
		int nbLines = pow(2, nbVars);
		int maxType = pow(2, sizeType - 1);
			
		for(int l = 0; l < nbLines; l++) {
			//On se décale jusqu'aux bits utiles.
			int t = l << (sizeType - nbVars);
			
			//On affiche les bits.
			for(int i = 0; i < nbVars; i++) {
				bool valBit = t & maxType;
				bee.setVar(vars[i], valBit);
				t <<= 1;
				std::cout << valBit << std::setw(vars[i].length() + 1);
			}
			
			//On évalue l'expression avec les nouvelles valeurs.
			bool res = bee.eval();
			std::cout << res << std::endl;
		}
	} catch(BEE::Error err) {
		std::cout << std::endl;
		std::cout << err.src() << std::endl;
		std::cout << std::setw(err.ind() + 1) << "^" << std::endl;
		std::cout << std::setw(err.ind() + err.desc().length()) << err.desc()
				  << std::endl;
	}
	
	return 0;
}

Conclusion :


Cette source peut être utile notamment pour savoir comment convertir une expression (booléenne ou non) en notation polonaise inversée. (l'algorithme n'est pas entièrement de moi, sa structure provient d'une page Wikipédia mentionnée au dessus de la fonction concernée).

Il existe peut-être des bugs, si c'est le cas, merci de me les indiquer.

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
if(++i < n) ou if(i++ < n) strictement identique en perf pout tout compilo normalement constitué.

cas ++i:
add i, 1
cmp i, n
jge LABEL

cas i++:
cmp i, n
jge LBEL
add i, 1

Il n'y a fort heureusement pas besoin de recopie ni rien d'autre.
Messages postés
3833
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
11 juin 2021
122
@LeFauve42: Je suis d'accord avec toi, tout compilo moderne fera cette optimisation. Mais attention, je parlais de la différence dans le cas ou it est un "iterator", la classe iterator de la STL ! Et là, les types ont été redéfinis, et on a une réelle différence de performance.
Messages postés
45
Date d'inscription
mardi 20 mars 2007
Statut
Membre
Dernière intervention
28 juillet 2011

Ah oui, je vois, LeFauve42, merci pour l'astuce !
Messages postés
239
Date d'inscription
vendredi 20 octobre 2006
Statut
Membre
Dernière intervention
20 avril 2009

Tres bons conseils CptPingu !
J'aurai juste une remarque : meme si ++i est plus rapide que i++, je suis pratiquement sur que tous les compilateurs modernes un peu serieux sont capables d'optimiser ca tout seul, surtout si il n'y a rien autour (si tu vas par la, pourquoi ne pas declarer la variable en "register" :o) (c'est une blague, ne le faites pas ;o) )).
Et puis je crois que ton "pseudo code equivalent" devrait plutot etre : {itTmp it; it it + 1; return itTmp; }

Pour le xor, effectivement c'est un peu un outil de base.
Si tu veux faire un truc un peu plus marrant a coder, tu peux essayer d'implementer un DEFFN (definition de fonctions utilisateur) et modifier ton code pour charger un fichier d'initialisation au demarrage de ton parseur.

J'avais fait ca lors d'un de mes premier projets scolaires (et eu une bonne note pour l'originalite :o) ).
En gros, on devait coder une calculatrice scientifique avec plein de fonctions sin, cos, tan, etc.
Au lieu de tout coder en C, j'avais uniquement fait sin(x), puis dans mon fichier d'initialisation j'avais des trucs genre :
DEFFN cos(x)=sin(x+pi/2)
DEFFN tan(x)=sin(x)/cos(x)

Enfin, tu vois le genre. Avec ca, tu peux rajouter simplement les XOR, NAND, NOR, etc... a ton parseur.
Eric
Messages postés
45
Date d'inscription
mardi 20 mars 2007
Statut
Membre
Dernière intervention
28 juillet 2011

Encore merci pour ces conseils :).
Pour le XOR, il est vrai que j'aurais pu le mettre, mais il me semble que ce n'est pas un opérateur "de base" au sens où il peut être construit à partir des trois autres (!, &, |). Mais c'est vrai que ça pourrait simplifier de le mettre.
Pour ce qui est de la gestion des tokens, c'est vrai que c'est pas top.
Pour ce qui est le l'indice de la classe Error, je vois pas trop comment je pourrais retrouver le bon indice, mais je vais chercher.
Sinon, il faudra en effet que je regarde un peu ce que donne la méthode AST, ça peut être intéressant pour aller encore plus loin.
Voilà je vais voir ça et le reste prochainement !
Afficher les 7 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.