infix

23
Infix Expression Evaluation Postfix expressions are easy to evaluate: no subexpressions precedence among operators already accounted for t this is not the case for infix expressions! e.g. 9 + (2 – 3) * 8 Two approaches to evaluate an infix expression: Use two stacks within one scan. Convert to equivalent postfix expression and then call the infix expression evaluator.

Transcript of infix

Page 1: infix

Infix Expression Evaluation

Postfix expressions are easy to evaluate:

no subexpressions

precedence among operators already accounted for

But this is not the case for infix expressions!

e.g. 9 + (2 – 3) * 8

Two approaches to evaluate an infix expression:

Use two stacks within one scan.

Convert to equivalent postfix expression and then call the infix expression evaluator.

Page 2: infix

Infix Expression Attributes

Left associative: +, -, /, %

Right associative: ^

2^7^6 + (3 – 2 * 4) % 5

2^(7^6) + ((3 – (2 * 4)) % 5)

Decreasing order of precedence:

() > ^ > * = % = / > + = –

Page 3: infix

Rank of ExpressionBinary operators only.

Evaluates an infix expression based on rank.

1 for any operand-1 for +, -, *, /, %, ^0 for (, )

Cumulative rank: sum of the ranks of individual terms.

2 ^ 7 ^ 6 + ( 3 – 2 * 4 ) % 5

1 0 1 0 1 0 0 1 0 1 0 1 1 0 1cumulativerank:

Cumulative rank for the entire expression is always 1. (exactly one more operand than operator)

Invalid expression if c.r. 1 (e.g. 2 4 + 3)

Page 4: infix

Infix-to-Postfix Conversion

An operand is immediately written to the output string.

During the scan of an expression:

No need to maintain an operand stack.

Stores operators and left-parenthesis symbols as soon as they appear.

Operator stack

Manages the order of precedence and associativity of operators.

Handles subexpressions.

Page 5: infix

Example 1

The stack temporally stores operators awaiting theirright-hand-side operand.

a + b * c

+

OperatorStack:

Postfix string:

a cb +*

*

* has higher priority than + add to the stack

Page 6: infix

Example 2

Use the stack to handle operators with same or lowerprecedence.

a * b / c + d

*

OperatorStack:

Postfix string:

a *b /c

/

* has the same priority as / pop * and write it to the postfix string before adding / to the stack.

d

+

+

/ has higher priority than +

Page 7: infix

Example 3 Use precedence values to handle ^ (right associative).

a ^ b ^ c

^

OperatorStack:

Postfix string:

a cb ^^

2nd ^ has precedence 4 but 1st ^ has only 3

2nd ^ goes to operator stack (so

it will be popped before 1st ^)

input precedence 4 when ^ is the input.

stack precedence 3 when ^ resides on the stack.

^

Page 8: infix

Example 4 Two precedence values for left parenthese ( :

a * ( b + c )

*

OperatorStack:

Postfix string:

a cb *+

( has precedence 5 it goes to the operator stack.

input precedence 5 which is higher than that of any operator.(all operators on the stack must remain because a new subexpression begins.)

stack precedence -1 which is lower than that of any opeartor.(no operator in the subexpression may remove ( until ) shows up.)

(+ ( now has precedence -1

it stays on the operator stack.

Page 9: infix

Input and Stack Precedence

Input Precedence

Stack Precedence RankSymbol

+ - 1 1 -1* / % 2 2 -1^ 4 3 -1( 5 -1 0) 0 0 0

Page 10: infix

Rules for Evaluation

Check the cumulative rank after each symbol (must be in the range from 0 to 1).

Write the input to the postfix string if it is an operand.

Upon input of an operator or a (, compare its precedence with the stack precedence of the top operator on the stack. Pop the top if the stack precedence is higher or equal, andwrite it to the postfix string. Repeat until the top operator has a lower rank, push the input onto the stack.

If the input is ), pop all operators from the stack until ( and write

them to the postfix string. Pop (.

At the end of the infix expression, pop all remaining operators from the stack and write them to the postfix string.

Page 11: infix

An Example

3 * (4 – 2 ^ 5) + 6

Operator stack

postfix 3

* [2]

3

( [-1]

* [2]

3

( [-1]

* [2]

3 4

( [-1]

* [2]

- [1]

3 4

( [-1]

* [2]

- [1]

3 4 2

( [-1]

* [2]

- [1]

^ [3]

3 4 2

( [-1]

* [2]

- [1]

^ [3]

3 4 2 5

( [-1]

* [2]

3 4 2 5 ^ -

Page 12: infix

cont’d

* [2]

3 4 2 5 ^ -

Pop (

+ [1]

3 4 2 5 ^ - * 3 4 2 5 ^ - * 6

+ [1]

3 4 2 5 ^ - * 6 +

3 * (4 – 2 ^ 5) + 6

Page 13: infix

Class for the Symbols

class expressionSymbol{

public:expressionSymbol(); // default constructorexpressionSymbol(char ch); // initializes the object for operator ch

friend bool operator>= (const expressionSymbol& left, const expressionSymbol& right);// return true if stackPrecedence of left is// >= inputPrecedence of right. determines whether// operator left on the stack should be output before// pushing operator right on the stack

char getOp() const;// return operator

private:char op; // operatorint inputPrecedence; // input precedence of opint stackPrecedence; // stack precedence of op

};

Encapsulate each symbol along with the associated input and output precedence.

Page 14: infix

Class for ConversionThe infix2Postfix class uses a stack to store expressionSymbol objectsthat correspond to operators.

const char lParen = '(', rParen = ')';

class infix2Postfix{

public:infix2Postfix();

// default constructor. infix expression is NULL stringinfix2Postfix(const string& infixExp);

// initialize the infix expression

void setInfixExp(const string& infixExp);// change the infix expression

string postfix();// return a string that contains the equivalent postfix// expression. the function throws expressionError if an// error occurs during conversion

Page 15: infix

infix2Postfix cont’d

private:

string infixExpression;// the infix expression to convert

string postfixExpression;// built to contain the postfix equivalent of infixExpression

stack<expressionSymbol> operatorStack;// stack of expressionSymbol objects

void outputHigherOrEqual(const expressionSymbol& op);// the expressionSymbol object op holds the current// symbol. pop the stack and output as long as the symbol// on the top of the stack has a precedence >= that of// the current operator

bool isOperator(char ch) const;// is ch one of '+','-','*','/','%','^'

};

Page 16: infix

Output Stack SymbolsPop symbols on the stack with stack precedence input precendence of the new symbol.

void infix2Postfix::outputHigherOrEqual(const expressionSymbol& op){

expressionSymbol op2;

while(!operatorStack.empty() &&(op2 = operatorStack.top()) >= op)

{operatorStack.pop();postfixExpression += op2.getOp();postfixExpression += ' ';

}}

Page 17: infix

Function for Infix-to-Postfix Conversion

Skips a whitespace character.

Writes an operand to the postfix string.

Calls outputHigherOrEqual() with an operator.

postfix() does the following:

Also calls outputHigherOrEqual() when the input is ).

Terminates at the end of the expression or if an error occurs.

expressionSymbol op;// maintain rank for error checkingint rank = 0, i;char ch;

Declarations:

Page 18: infix

Processing an Operand// process until end of the expressionfor (i=0; i < infixExpression.length(); i++){

ch = infixExpression[i];

// ******** process an operand ********// an operand is a single digit non-negative integerif (isdigit(ch)){

// just add operand to output expression, followed by// a blankpostfixExpression += ch;postfixExpression += ' ';// rank of an operand is 1, accumulated rank// must be 1rank++;if (rank > 1) throw expressionError("infix2Postfix: Operator expected");

}

Page 19: infix

Processing an Operator// ********* process an operator or '(' **********else if (isOperator(ch) || ch == '('){

// rank of an operator is -1. rank of '(' is 0.// accumulated rank should be 0if (ch != '(')

rank--;

if (rank < 0) throw expressionError("infix2Postfix: Operand expected"); elseelse

{// output the operators on the stack with higher// or equal precedence. push the current operator// on the stackop = expressionSymbol(ch);outputHigherOrEqual(op);operatorStack.push(op);

}}

Page 20: infix

Processing a Right Parenthesis

else if (ch == rParen){

// build an expressionSymbol object holding ')', which// has precedence lower than the stack precedence// of any operator except '('. pop the operator stack// and output operators from the subexpression until// '(' surfaces or the stack is empty. if the stack is// empty, a '(' is missing; otherwise, pop off '('.op = expressionSymbol(ch);outputHigherOrEqual(op);if (operatorStack.empty())

throw expressionError("infix2Postfix: Missing '('");else

operatorStack.pop(); // get rid of '('}

// ********* make sure ch is whitespace **********else if (!isspace(ch))

throw expressionError("infix2Postfix: Invalid input");}

Page 21: infix

Finish Processing// outside the for loopif (rank != 1)

throw expressionError("infix2Postfix: Operand expected");else{

// flush operator stack and complete expression evaluation.// if find left parenthesis, a right parenthesis is missingwhile (!operatorStack.empty()){

op = operatorStack.top();operatorStack.pop();if (op.getOp() == lParen)

throw expressionError("infix2Postfix: Missing ')'");else{

postfixExpression += op.getOp();postfixExpression += ' ';

}}

}

return postfixExpression;}

Page 22: infix

Evaluating an Infix Expression

void main(){

// use iexp for infix to postfix conversioninfix2Postfix iexp;// infix expression input and postfix expression outputstring infixExp, postfixExp;// use pexp to evaluate postfix expressionspostfixEval pexp;

// input and evaluate infix expressions until the// user enters an empty string

// get the first expressioncout << "Enter an infix expression: ";getline(cin, infixExp);

while (infixExp != ""){

// an exception may occur. enclose the conversion// to postfix and the output of the expression// value in a try block

Page 23: infix

try{

// convert to postfixiexp.setInfixExp(infixExp);postfixExp = iexp.postfix();

// output the postfix expressioncout << "The postfix form is " << postfixExp << endl;

// use pexp to evaluate the postfix expressionpexp.setPostfixExp(postfixExp);

cout << "Value of the expression = " << pexp.evaluate() << endl << endl;

}

// catch an exception and output the errorcatch (const expressionError& ee){

cout << ee.what() << endl << endl;}// input another expressioncout << "Enter an infix expression: ";getline(cin, infixExp);

}}