[ create a new paste ] login | about

Link: http://codepad.org/FiYAEmG3    [ raw code | fork ]

ninwa - C++, pasted on Sep 13:
//////////////////////////////////////////////////// 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;
}


Create a new paste based on this one


Comments: