S
sunil
Hello,
I am working on a problem where I will have a boolean expression
with
upto four variables: A,B,C,D and connected by basic operator &&,||and
may be XOR and NOT in future AND has higher precedence than OR and ()
(parenthesis) takes utmost precedence... I wrote a sample code that
uses interpretor pattern that uses composition pattern to repeatedly
call the evaluate() function, this works properly, however I need to
construct the expression object properly, I hardcoded this (as shown
in the sample code attached below) but would assume I should some
kind
of parsing technique to generate the proper top level expression
object, I have no background in Computer Science (am an electrical
enginner ) so would need some help here, how to build this parser,
I
GOGled quite a bit and found some info but nothing simple/straight
forward to understand, any pointers on simple layman tuorials/sample
code for this problem would be highly appreciated:
My other question is: is it an overkill to even think of using the
interpretor pattern for problem I am trying to solve, if its OK, is
it
overkill to try building parser is it enough to hardcode the
generation of expression object...
Thanks,
Sunil
P.S.: My interpretor pattern below doesnt need to pass around the
"context" as the object Variable is already updated externally...
Sample code:
//Variable: smallest thing that can be part of expression.
class Variable {
public:
Variable(bool value,string name):_value(value),_name(name) {
}
bool getValue() {
return _value;
}
void setValue(bool value) {
_value=value;
}
string getName() {
return _name;
}
private:
bool _value;
std::string _name;
};
enum
OperatorType{OPERATOR_NONE,AND_OPERATOR,OR_OPERATOR,NOT_OPERATOR};
//Expression is built using variables and symbols and it can be
recursive i.e.
//an expression can be having expression in itself. It can have 1 or
two
//operands but only one operator
class Expression {
public:
Expression(string exprName,OperatorType
operatorType) :_exprName(exprName),_operator(operatorType) {}
~Expression(){}
string getName() {
return _exprName;
}
virtual bool evaluate()=0;
protected:
string _exprName;
OperatorType _operator;
};
//Various basic expressions allowed: AND,OR
//AND
class AndExpression: public Expression {
public:
AndExpression(Expression* exp1,Expression* exp2,string exprName):
Expression(exprName,AND_OPERATOR),_exp1(exp1),_exp2(exp2) {
}
bool evaluate() {
bool retVal;
cout << "Evaluating variable AND expr: name=" << _exprName <<
endl;
retVal = (_exp1->evaluate() && _exp2->evaluate());
cout << "Result of AND expr:" << _exprName << "is:" <<retVal <<
endl;
return retVal;
}
private:
Expression * _exp1;
Expression * _exp2;
};
//OR
class ORExpression: public Expression {
public:
ORExpression(Expression* exp1,Expression *exp2,string exprName):
Expression(exprName,OR_OPERATOR),_exp1(exp1),_exp2(exp2) {
}
bool evaluate() {
bool retVal,exp1Val;
cout << "Evaluating variable OR expr: name=" << _exprName <<
endl;
retVal=(_exp1->evaluate() || _exp2->evaluate());
cout << "Result of OR expr:" << _exprName << " is:" << retVal <<
endl;
return retVal;
}
private:
Expression* _exp1;
Expression* _exp2;
};
//NOT
class NOTExpression: public Expression {
public:
NOTExpression(Expression* exp,string exprName):
Expression(exprName,NOT_OPERATOR),_exp(exp) {
}
bool evaluate() {
bool retVal;
cout << "Evaluating variable NOT expr: name=" << _exprName <<
endl;
retVal = !(_exp->evaluate());
cout << "Result of NOT expr:" << _exprName << " is " << retVal;
return retVal;
}
private:
Expression* _exp;
};
//VariableExpression: expression with variable.
class VariableExpression: public Expression {
public:
VariableExpression(Variable* var): Expression(var->getName()
+"expr",OPERATOR_NONE),_var(var) {
}
bool evaluate() {
cout << "Evaluating variable expr: name=" << _exprName
<< "value= "
<< _var->getValue() <<endl;
return _var->getValue();
}
private:
Variable* _var;
};
int main() {
Variable var1(false,"var1");
Variable var2(true,"var2");
Variable var3(true,"var3");
VariableExpression varExp1(&var1);
VariableExpression varExp2(&var2);
VariableExpression varExp3(&var3);
//(varExp1 || varExp2) && varExp3
Expression *exp = new AndExpression(new
ORExpression(&varExp1,&varExp2,"inexp"),&varExp3,"outexp");
cout << "Result of evaluation=" << exp->evaluate() << endl;
var2.setValue(false);
cout << "Result of evaluation=" << exp->evaluate() << endl;
//Advantage of this approach A||B&C factored in when expression
created.
I am working on a problem where I will have a boolean expression
with
upto four variables: A,B,C,D and connected by basic operator &&,||and
may be XOR and NOT in future AND has higher precedence than OR and ()
(parenthesis) takes utmost precedence... I wrote a sample code that
uses interpretor pattern that uses composition pattern to repeatedly
call the evaluate() function, this works properly, however I need to
construct the expression object properly, I hardcoded this (as shown
in the sample code attached below) but would assume I should some
kind
of parsing technique to generate the proper top level expression
object, I have no background in Computer Science (am an electrical
enginner ) so would need some help here, how to build this parser,
I
GOGled quite a bit and found some info but nothing simple/straight
forward to understand, any pointers on simple layman tuorials/sample
code for this problem would be highly appreciated:
My other question is: is it an overkill to even think of using the
interpretor pattern for problem I am trying to solve, if its OK, is
it
overkill to try building parser is it enough to hardcode the
generation of expression object...
Thanks,
Sunil
P.S.: My interpretor pattern below doesnt need to pass around the
"context" as the object Variable is already updated externally...
Sample code:
//Variable: smallest thing that can be part of expression.
class Variable {
public:
Variable(bool value,string name):_value(value),_name(name) {
}
bool getValue() {
return _value;
}
void setValue(bool value) {
_value=value;
}
string getName() {
return _name;
}
private:
bool _value;
std::string _name;
};
enum
OperatorType{OPERATOR_NONE,AND_OPERATOR,OR_OPERATOR,NOT_OPERATOR};
//Expression is built using variables and symbols and it can be
recursive i.e.
//an expression can be having expression in itself. It can have 1 or
two
//operands but only one operator
class Expression {
public:
Expression(string exprName,OperatorType
operatorType) :_exprName(exprName),_operator(operatorType) {}
~Expression(){}
string getName() {
return _exprName;
}
virtual bool evaluate()=0;
protected:
string _exprName;
OperatorType _operator;
};
//Various basic expressions allowed: AND,OR
//AND
class AndExpression: public Expression {
public:
AndExpression(Expression* exp1,Expression* exp2,string exprName):
Expression(exprName,AND_OPERATOR),_exp1(exp1),_exp2(exp2) {
}
bool evaluate() {
bool retVal;
cout << "Evaluating variable AND expr: name=" << _exprName <<
endl;
retVal = (_exp1->evaluate() && _exp2->evaluate());
cout << "Result of AND expr:" << _exprName << "is:" <<retVal <<
endl;
return retVal;
}
private:
Expression * _exp1;
Expression * _exp2;
};
//OR
class ORExpression: public Expression {
public:
ORExpression(Expression* exp1,Expression *exp2,string exprName):
Expression(exprName,OR_OPERATOR),_exp1(exp1),_exp2(exp2) {
}
bool evaluate() {
bool retVal,exp1Val;
cout << "Evaluating variable OR expr: name=" << _exprName <<
endl;
retVal=(_exp1->evaluate() || _exp2->evaluate());
cout << "Result of OR expr:" << _exprName << " is:" << retVal <<
endl;
return retVal;
}
private:
Expression* _exp1;
Expression* _exp2;
};
//NOT
class NOTExpression: public Expression {
public:
NOTExpression(Expression* exp,string exprName):
Expression(exprName,NOT_OPERATOR),_exp(exp) {
}
bool evaluate() {
bool retVal;
cout << "Evaluating variable NOT expr: name=" << _exprName <<
endl;
retVal = !(_exp->evaluate());
cout << "Result of NOT expr:" << _exprName << " is " << retVal;
return retVal;
}
private:
Expression* _exp;
};
//VariableExpression: expression with variable.
class VariableExpression: public Expression {
public:
VariableExpression(Variable* var): Expression(var->getName()
+"expr",OPERATOR_NONE),_var(var) {
}
bool evaluate() {
cout << "Evaluating variable expr: name=" << _exprName
<< "value= "
<< _var->getValue() <<endl;
return _var->getValue();
}
private:
Variable* _var;
};
int main() {
Variable var1(false,"var1");
Variable var2(true,"var2");
Variable var3(true,"var3");
VariableExpression varExp1(&var1);
VariableExpression varExp2(&var2);
VariableExpression varExp3(&var3);
//(varExp1 || varExp2) && varExp3
Expression *exp = new AndExpression(new
ORExpression(&varExp1,&varExp2,"inexp"),&varExp3,"outexp");
cout << "Result of evaluation=" << exp->evaluate() << endl;
var2.setValue(false);
cout << "Result of evaluation=" << exp->evaluate() << endl;
//Advantage of this approach A||B&C factored in when expression
created.