Professional Documents
Culture Documents
Evaluating expressions is a classic application context for both grammars and stacks Grammars permit parsing of the expressions and creating data structures that represent the expression semantics correctly Stacks are useful for evaluating many kinds of expressions, most obviously algebraic expressions a*b-c, a/b*c, ((c+16)/b)+42 Recall that humans most commonly use infix notation for these expressions, i.e. val op val Problem: infix grammar is not a complete specification of expression semantics Operator precedence and parentheses are also required EECS 268 2 Dr. Douglas Niehaus 2008
EECS 268
Introduction
Solution: use prefix or postfix notation since their grammars are definitive, unambiguous, without needing precedence rules or parentheses Simple Algebraic Expression Grammars (1) infix = infix operator infix | operand | ( infix ) (2) prefix = operator prefix prefix | operand (3) postfix = postfix postfix operator | operand Example: Infix Prefix Postfix a bc Prefix: abc Postfix: ab c a (bc) Prefix: abc Postfix: abc
EECS 268 3 Dr. Douglas Niehaus 2008
Introduction
We thus want to be able to (1) Evaluate postfix (prefix) expressions, and (2) Convert from infix to postfix (prefix) expression. Evaluating postfix using a stack is amazingly easy once the basic pattern is understood Using a stack to convert from infix to postfix is also fairly simple, but is complicated by the operator precedence and parenthesis semantics Postfix grammar:
<postfix> = <identifier>|<postfix><postfix><operator> <identifier> = a | b | | z <operator> = + | - | * | /
EECS 268 4 Dr. Douglas Niehaus 2008
Infix: ((ab)/c)*((d+e)f
ch f pop * action push pop op2 op1 calc & push pop op2 pop op1 calc & push stack (ab)/c (d+e) f (ab)/c (d+e) (ab)/c (ab)/c (d+e)f (ab)/c ((ab)/c)*((d+e)f)
EECS 268
EECS 268
EECS 268
12
Prefix Evaluation
Reverse prefix and evaluate it
reverse given prefix expression; scan the reversed prefix expression; for each symbol in reversed prefix if operand then push its value onto stack S; if operator then { pop operand1; pop operand2; compute result = operand1 op operand2; push result back onto stack S; } return value at top of stack;
EECS 268 14 Dr. Douglas Niehaus 2008
ch ( d + e f / g )
action op stack push *( output *( push *(+ output *(+ pop *( push *( output *( push *(/ output *(/ pop to ( * pop until empty stack
Postfix abc/ abc/d abc/d abc/de abc/de+ abc/de+ abc/de+f abc/de+f abc/de+fg abc/de+fg/ abc/de+fg/*
EECS 268
13
Reversed: fed+cba/*
ch / * action stack pop op1 ((d+e)f) c pop op2 ((d+e)f) calc & push ((d+e)f) ((ab)/c) pop op1 ((d+e)f) pop op2 calc & push ((ab)/c)*((d+e)f)
while ( ! empty(S) ) { pop op from S; append op to RPS; } reverse RPS; output Prefix String
EECS 268
Summary
Various uses if stacks connected to parsing algebraic expressions and evaluating them Unlikely to be something you write as fresh code as many libraries exist for doing expression evaluation and the problem can be approached in other ways But possible Good practice for imagining and tracing actions of code using stacks
Prefix: */abc+de/fg
EECS 268
17
EECS 268
18