//////////////////////////////////////////////////// BoolExprParser.h
#pragma once
#include <map>
#include <string>
class BoolExprParser
{
std::map<std::string, bool> _vars;
std::string _expr;
bool _eval(std::string expr);
static const char _reserved[5];
public:
BoolExprParser();
BoolExprParser(std::string expr);
BoolExprParser(std::string expr, std::map<std::string, bool> vars);
~BoolExprParser();
void setVar(char varname, bool val);
void setVar(std::string varname, bool val);
bool getVar(std::string varname);
void clearVars();
void setExpr(std::string expr);
std::string getExpr();
bool eval();
};
//////////////////////////////////////////////////// BoolExprParser.cpp
#include "BoolExprParser.h"
#include <iostream>
#include <algorithm>
#include "boost/algorithm/string.hpp"
const char BoolExprParser::_reserved[5] = {'(', ')', '!', '*', '+'};
BoolExprParser::BoolExprParser()
{
}
BoolExprParser::BoolExprParser(std::string expr)
{
_expr = expr;
}
BoolExprParser::BoolExprParser(std::string expr, std::map<std::string, bool> vars)
{
_vars = vars;
_expr = expr;
}
BoolExprParser::~BoolExprParser()
{
}
void BoolExprParser::setVar(std::string varname, bool value)
{
if(varname.length() == 0)
{
throw std::string("Empty string is an invalid variable name");
}
if(varname.length() == 1)
{
for(unsigned i = 0; i < sizeof(BoolExprParser::_reserved) * sizeof(char); i++)
{
if(BoolExprParser::_reserved[i] == varname[0])
{
throw std::string("Variable name '" + varname + "' is reserved");
}
}
}
_vars[varname] = value;
}
void BoolExprParser::setVar(char varname, bool value)
{
setVar(std::string("")+varname, value);
}
bool BoolExprParser::getVar(std::string varname)
{
if(_vars.find(varname) == _vars.end())
{
throw std::string("Attempted to acces unset variable '" + varname + "'");
}
return _vars[varname];
}
void BoolExprParser::clearVars()
{
_vars.clear();
}
void BoolExprParser::setExpr(std::string expr)
{
// Remove all whitespace
boost::replace_all(expr, " ", "");
_expr = expr;
}
std::string BoolExprParser::getExpr()
{
return _expr;
}
bool BoolExprParser::_eval(std::string expr)
{
unsigned paren_count = 0;
int open_paren = -1;
int closed_paren = -1;
for(size_t i = 0; i < expr.length(); i++)
{
if(expr[i] == '(')
{
if(paren_count == 0)
open_paren = i;
paren_count++;
}
if(expr[i] == ')')
{
paren_count--;
if(paren_count == 0)
{
closed_paren = i;
}
}
if(closed_paren != -1 && open_paren != -1 && paren_count == 0)
{
std::string expr_in_parens = expr.substr(open_paren+1, closed_paren-open_paren-1);
std::string replacement_str = (_eval(expr_in_parens)) ? "1" : "0";
boost::replace_all(expr, "("+expr_in_parens+")", replacement_str);
open_paren = closed_paren = -1;
i = 0;
}
}
boost::replace_all(expr, "!0", "1");
boost::replace_all(expr, "!1", "0");
while(std::string::npos != expr.find("0*0") ||
std::string::npos != expr.find("0*1") ||
std::string::npos != expr.find("1*0") ||
std::string::npos != expr.find("1*1"))
{
boost::replace_all(expr, "0*0", "0");
boost::replace_all(expr, "0*1", "0");
boost::replace_all(expr, "1*0", "0");
boost::replace_all(expr, "1*1", "1");
}
while(std::string::npos != expr.find("0+0") ||
std::string::npos != expr.find("0+1") ||
std::string::npos != expr.find("1+0") ||
std::string::npos != expr.find("1+1"))
{
boost::replace_all(expr, "0+0", "0");
boost::replace_all(expr, "0+1", "1");
boost::replace_all(expr, "1+0", "1");
boost::replace_all(expr, "1+1", "1");
}
if(expr.length() == 1)
{
return (bool)(expr[0]-48);
}
return false;
}
bool BoolExprParser::eval()
{
std::string expr = _expr;
// Replace all variables with their associated values
auto vars_end = _vars.end();
for(auto it = _vars.begin(); it != vars_end; it++)
{
boost::replace_all(expr, it->first, ((it->second)?"1":"0"));
}
return _eval(expr);
}
//////////////////////////////////////////////////// main.cpp
#include <iostream>
#include "BoolExprParser.h"
int main(int argc, char* argv[])
{
BoolExprParser boolParser;
try
{
boolParser.setVar('!', true);
}
catch(std::string e)
{
std::cout << e << std::endl;
}
try
{
boolParser.setVar('x', true);
boolParser.setVar('y', false);
}
catch(std::string e)
{
std::cout << e << std::endl;
}
boolParser.setExpr("y+y+y+y+(x+y+y+y+y)+(((y+y+y+y)+y+y)+x)");
try
{
std::cout << "Expression: " << boolParser.getExpr() << " evalutes to " << boolParser.eval() << std::endl;
}
catch(std::string e)
{
std::cout << e << std::endl;
}
return 0;
}