css342: stacks and compilers
DESCRIPTION
CSS342: Stacks and Compilers. Professor: Munehiro Fukuda. Topics. Basic concepts of stacks Stack implementation Applying to language processing Example 1: Balance-symbol checker Example 2: Algebraic expressions Calculator design (lab/home work). Basic Concepts. abcc ddde ef. - PowerPoint PPT PresentationTRANSCRIPT
CSS342: Stacks and Compilers 1
CSS342: Stacks and Compilers
Professor: Munehiro Fukuda
CSS342: Stacks and Compilers 2
Topics
• Basic concepts of stacks• Stack implementation• Applying to language processing
– Example 1: Balance-symbol checker– Example 2: Algebraic expressions
• Calculator design (lab/home work)
CSS342: Stacks and Compilers 3
Concepts of Stack• Stack of cafeteria dishes
– Inherently unfair in day-by-day situations
• Useful problem-solving techniques in Computer Science– Using a backspace key to
correct typos– Checking for balanced braces
push pop
abcc ddde ef
add d
c cb
e
e
f
a cb
da cb
a c cb
dd d ea cb
push
pop
push
pushpush
pushpushpushpush
pop pop pop
pushpush
Basic Concepts
CSS342: Stacks and Compilers 4
Stack Specification
template<class Object>class stack{public: stack(); bool empty( ) const; void push( const Object &newItem ); void pop( ); void pop( Object &stackTop ); // not in STL const Object top( ) const;}
abcc
a pop (): remove from the toppush to the top
pop(stacktop): remove and get the top item
retrieve the top itembut do not remove it
Axiom: (aStack.push(newItem)).pop() is equal to aStack
Basic Concepts
CSS342: Stacks and Compilers 5
STL Class stack#include <stack>stack();Creates an empty stack. You can convert a list into a new stack. See your text page 249 (Sec. 7.6.2)Example: stack<int>, vector<int>> aStack; stack<int> bStack;bool empty( ) const;Returns if the stack is empty.Example: while ( aStack.empty( ) == false ) { … }size_type size( ) const;Returns the number of elements. Size_type is an integral type. You can compare it with an integer.Example: while (aStack.size( ) > 0) { … }T &top( );Returns a reference to the top of the stack.Example: while( !aStack.empty() ) { cout << aStack.top() << endl; aStack.pop(); } void pop();Remove the top item from the stack.Example: See the top( ) example.void push(const T& value)Adds an item with value to the top of the stack.Example: stack<int> aStack; for( int i=0; i < 10; i++ ) aStack.push(i);
Basic Concepts
CSS342: Stacks and Compilers 6
STL Class stackExample
#include <stack>#include <iostream>using namespace std;
int main( ) { stack<int> aStack; int item;
for ( int j = 0; j < 5; j++ ) aStack.push( j );
while ( !aStack.empty( ) ) { cout << aStack.top( ) << endl; aStack.pop( ); }}
Results:43210
Basic Concepts
CSS342: Stacks and Compilers 7
Stack Implementation
• Array-based implementation• Pointer-based implementation• Linked list reuse
– Data member– Inheritance
Implementation
CSS342: Stacks and Compilers 8
An Array-Based Implementation
k …..g…..cbatop 0 1 2 k (MAX_STACK-1)
template <class Object>class stack{public: stack(); bool isEmpty( ) const; void push( const Object &newItem ); void pop( ); void pop( const Object &stackTop ); const Object top( ) const;private: vector<Object> theArray; //Object theArray[MAX_STACK–1]; in an ordinary array int top;}
Implementation
CSS342: Stacks and Compilers 9
k …..g…..cbatop 0 1 2 k theArray.Size( ) - 1
pop(Object &topItem) push(const Object &newItem)
Stack( ) : top( -1), theArray( 1 ) { }
if (top == theArray.size( ) - 1) theArray.resize( theArray.size( ) * 2 + 1 );item[++top] = newItem;
if (top < 0) throw “empty stack”;else { topItem = theArray[top]; --top;}
An Array-Based ImplementationImplementation
CSS342: Stacks and Compilers 10
A Pointer-Based Implementation
a b c g NULL………topPtr
#include<iostream>
template<class Object>class Stack{ public: Stack( ) : topPtr( NULL ) { }; Stack( const Stack &rhs ); ~Stack( ) { flush( ); }; bool isEmpty( ) const; void push( const Object &newItem ); const Object top( ) const; void pop( ); void pop( Object &stackTop ); void flush( ); const Stack &operator=( const Stack &rhs ); private: struct StackNode { Object item; StackNode *next; }; StackNode *topPtr;};#include "stackPointer.cpp"
Implementation
CSS342: Stacks and Compilers 11
A Pointer-Based Implementation
a b c g NULL………topPtr
template<class Object>void Stack<Object>::push( const Object &newItem ){ StackNode *newPtr = new StackNode; if ( newPtr == NULL ) throw "out of memory"; else { newPtr->item = newItem; newPtr->next = topPtr; topPtr = newPtr; }}
template<class Object>bool Stack<Object>::isEmpty( ) const { return topPtr == NULL;}
template<class Object>void Stack<Object>::flush( ) { while ( !isEmpty( ) ) pop( );}
template<class Object>const Object Stack<Object>::top( ) const { if ( isEmpty( ) ) throw "empty stack"; return topPtr->item;}
template<class Object>void Stack<Object>::pop( ) { if ( isEmpty( ) ) throw "empty stack"; StackNode *oldTop = topPtr; topPtr = topPtr->next; delete oldTop;}
template<class Object>void Stack<Object>::pop( Object &stackTop ) { stackTop = top( ); pop( );}
Stack( ) : topPtr( NULL ) { };
Implementation
CSS342: Stacks and Compilers 12
Copy Constructor• Stack( const Stack<Object>& rhs )
– Implicit called upon passing, returning, and assigning an object.
• Shallow copy: C++ copies an object’s data members.
• Deep copy: Java copies all traversable pointer variables.
20 45 51 76 NULLstackTop
rhs.stackTop
20 45 51 76 NULLstackTop
Rhs.stackTop 20 45 51 76 NULL
Implementation
CSS342: Stacks and Compilers 13
Deep Copytemplate<class Object> // copy constructorStack<Object>::Stack( const Stack<Object> &rhs ) { topPtr = NULL; *this = rhs;}
template<class Object> // operator = (deep copy)const Stack<Object> &Stack<Object>::operator=( const Stack<Object> &rhs ) { if ( this != &rhs ) { // why 1 flush( ); // why 2 if ( rhs.isEmpty( ) ) return *this; StackNode rptr = rhs.topPtr; StackNode ptr = new StackNode; ptr->item = rptr->item; topPtr = ptr;
for ( StackNode rptr = rptr->next; rPtr != NULL; rPtr = rPtr->next ) { ptr->next = new StackNode; ptr->next->element = rptr->element; ptr = ptr->next; } return *this; }}
topPtr
rhs.topPtr 4520 51
20 45
Repeat!
Implementation
CSS342: Stacks and Compilers 14
Implementation by List Reuse• Why not reuse the Linked List class we studied?• Contain a linked list instance in our stack implementation
Implementation
#include <iostream>#include "llist.h“
template<class Object>class Stack { public: // the same as previous private: LList<Object> list;};
template<class Object>bool Stack<Object>::isEmpty( ) const { return list.isEmpty( );}
template<class Object>void Stack<Object>::push( const Object &newItem ) { list.insert( newItem, 0 ); // insert after 0th dummy}
template<class Object>const Object Stack<Object>::top( ) const { return list.retrieve( 1 ); // retrieve 1st list item}
stack.h stack.cpp
CSS342: Stacks and Compilers 15
Implementation by List Reuse(code continued)
Implementation
template<class Object>void Stack<Object>::pop( ) { if ( list.size( ) > 0 ) list.remove( list.retrieve( 1 ) ); // remove the 1st item}
template<class Object>void Stack<Object>::pop( Object &stackTop ) { if ( list.size( ) > 0 ) list.remove( ( stackTop = list.retrieve( 1 ) ) );}
template<class Object>void Stack<Object>::flush( ) { return list.clear( );}
template<class Object>const Stack<Object>& Stack<Object>::operator=( const Stack &rhs ) { list = rhs.list; // just reuse list’s operator=!}
CSS342: Stacks and Compilers 16
Comparing Implementations• The Array-Based Stack
– Pros. Easy implementation– Cons.
– Fixed size (if we use a fixed array)– Capacity or stack duplication overhead (if we use a dynamic
array like vector) – Good for small objects
• The Pointer-Based Stack.– Pros. Dynamic size (not wasting space)– Cons.Necessity to take care of pointers– Good for large objects
• Reuse of Linked List.– Pros.
– Easy Implementation– All advantages inherent to pointer-based stack.
– Cons. May be a bit slower.
Implementation
So which is the best?
CSS342: Stacks and Compilers 17
Example 1: Balanced-Symbol Checker
abc{defg(ijk)(l[mn])op}qr abc{def})(ghij[kl]m)
1. {2. {(3. {4. {(5. {([6. {(7. {
1.push 3.pop2.push4.push
5.push6.pop
7.pop 8.pop 1. {2. 3. empty!!
1.push 2.pop3.pop
abc{(def) ghijklm
1. {2. {(3. {Stack is not empty!!
1.push 3.pop2.push
• Check if stack is empty in prior to a pop• Check if stack is empty at the end of string
Example 1
CSS342: Stacks and Compilers 18
Balanced-Symbol Checker
char getNextSymbol( ) { // gets the next ( ) [ ] { and } char ch; do { if ( !cin.get( ch ) ) return '\0'; // EOF } while ( ch != '(' && ch != ')' && ch != '[' &&
ch != ']' && ch != '{' && ch != '}' ); return ch;}
bool checkMatch( const char &openSym, const char &closeSym ) {// check if openSym nad closeSym matches each other
if ( openSym == '(' && closeSym != ')' || openSym == '[' && closeSym != ']' || openSym == '{' && closeSym != '}' ) { cout << "Found " << closeSym << "; does not match " << openSym << endl; return false; } return true;}
Simplified code of textbook p411 - 419 It does not care about comments nor prints out detailed error messages.
Example 1
CSS342: Stacks and Compilers 19
Balanced-Symbol Checker(code continued)
bool checkBalance( ) { char ch, match; int errors = 0; stack<char> pendingTokens; // a stack while( ( ch = getNextSymbol( ) ) != '\0' ) { // keep reading a new symbol till EOF switch( ch ) { case '(': case '[': case '{': // push an open symbol into the stack pendingTokens.push( ch ); break; case ')': case ']': case '}': // has encountered a close symbol if ( pendingTokens.empty( ) ) { // check if the stack is empty
cout << "Extraneous " << ch << endl;return false;
} else {match = pendingTokens.top( ); // get the top (i.e., the last symbol)pendingTokens.pop( ); // on the stackif ( ! checkMatch( match, ch ) ) // check this pair of open and close return false; // symbol
} } } while ( !pendingTokens.empty( ) ) { // if the stack still has symbols match = pendingTokens.top( ); // flush out all. pendingTokens.pop( ); cout << "Unmatched " << match << endl; errors++; } return ( errors > 0 ) ? false : true;}
Example 1
CSS342: Stacks and Compilers 20
• Infix expressions:– Every binary operator appears between its operands.– a + b– a + b * c, if you want to compute a + b first, then (a + b) * c
• Prefix expressions:– Every binary operator appears before its operands. No parentheses needed– a + b => + a b– (a + b) * c => * + a b c
• Postfix expressions– Every binary operator appears after its operands. No parentheses need– a + b => a b +– (a + b) * c => a b + c * Easy to evaluate using a stack
Example 2: Algebraic ExpressionsExample 2
CSS342: Stacks and Compilers 21
How to Evaluate a Postfix Expression
for ( (c = cin.get( )) != ‘\n’) {if ( c >= ‘0’ && c <= ‘9’ )
aStack.push(atoi(c));else {
aStack.pop(op2);aStack.pop(op1);switch (c) {case ‘+’: aStack.push(op1 + op2); break;case ‘-’; aStack.push(op1 – op2); break;….;default: cerr << “panic!”; break;}
}}
Assumptions: syntactically correct, no unary operations, and single digit operands
2 3 4 + *Operations Stackpush 2: 2push 3: 2 3push 4: 2 3 4pop 2 3pop 2Sum of 3&4push 7 2 7PopPopMult of 2&7Push 14
Example 2
CSS342: Stacks and Compilers 22
Converting Infix to Equivalent PostfixAbstract code:for ( (c = cin.get( )) != ‘\n’) {
siwtch(c) {case operand: postfixExp += c; // Order of operands in both infix and postfix is the same
break;
case ‘(‘: aStack.push(‘(‘); // Simply push ‘(‘ for matching ‘)’ later break;
case operator: while(!aStack.isEmpty() && ch of aStack.getTop(ch) !=‘(‘&& precedence(c) <= precedence(ch)) {posfixExp += ch;aStack.pop( );
} aStack.push(c);
(3)Infix: a - b + cPostfix: a bStack: -
(4)Infix: a - b + cPostfix: a b -Stack: +
Infix: a + b Postfix: a b +the same order
(2)Infix: a - b + cPostfix: aStack: -
(1)Infix: a - b + cPostfix: aStack:
Example 2
CSS342: Stacks and Compilers 23
Converting Infix to Equivalent PostfixAbstract code (Continued):for ( (c = cin.get( )) != ‘\n’) {
switch(c) {…… // See the previous slide
case ‘)’: while (ch of aStack.getTop(ch) != ‘(‘) {postfixExp += ch;aStack.pop( );
} aStack.pop( ) break;
} } While (!aStack.isEmpty( )) {
aStack.pop(ch);postfixExp += ch;
}
(1)Infix: x - (a - b + c)Postfix: x a b - c Stack: - ( +
(2)Infix: x - (a - b + c)Postfix: x a b c - +Stack: -
(3)Infix: x - (a - b + c)Postfix: x a b c - + -Stack:
“-” is put on the stack,It is added to Postfix upon encountering “+”,“+”is put on the stack.Upon a “)”, all operators before “(“ are put on Postfix
Example 2
CSS342: Stacks and Compilers 24
Converting Infix to Equivalent Postfixint precedence( char op ) { switch( op ) { case '+': return 0; case '-': return 0; case '*': return 1; case '/': return 1; default: return 1; }}
string convert( const string& infix ) { stack<char> opStack; char stackTop; string postfixExp;
for ( int i = 0; i < infix.size( ); i++ ) { char c = infix[i]; switch( c ) { case '(': opStack.push( c ); break; case '+': case '-': case '*': case '/': if ( !opStack.empty( ) ) {
stackTop = opStack.top( );if ( stackTop != '(' &&
precedence( c ) <= precedence( stackTop ) ) {
postfixExp += stackTop; opStack.pop( );}
} opStack.push( c ); break;
case ')': while ( !opStack.empty( ) ) {
stackTop = opStack.top( );if ( stackTop != '(' ) { postfixExp += stackTop; opStack.pop( ); continue;}break;
} opStack.pop( ); break; default: // operand postfixExp += c; break; } } while ( !opStack.empty( ) ) { stackTop = opStack.top( ); opStack.pop( ); postfixExp += stackTop; }
return postfixExp;}
Example 2
CSS342: Stacks and Compilers 25
Converting Infix to Equivalent PostfixCh Stack postFixExp Remark
A A Postfix += A
- - A Push -
( -( A Push (
B -( A B Postfix += B
+ -(+ A B Push +
C -(+ A B C Postfix += C
* -(+* A B C Push * where pr(*) > pr(-)
D -(+* A B C D Postfix += D
) -(+ A B C D * Pop *, Postfix += *
-( A B C D * + Pop +, Postfix += +
- A B C D * + Pop (
/ -/ A B C D * + Push / where pr(/) > pr(-)
E -/ A B C D * + E Postfix += E
A B C D * + E / - PostFix += /-
A – (B + C * D) / E
Example 2
CSS342: Stacks and Compilers 26
ExerciseA*B+C-D/(E+F)
Example 2
Postfix += FA B * C + D E F-/(+F
Push + where top( ) = (A B * C + D E-/(++
Postfix += EA B * C + D E-/(E
Push (A B * C + D-/((
Push / where pr(/) > pr(-)A B * C + D-//
Postfix += DA B * C + D-D
Push ---
Pop +, Postfix += +A B * C +
Postfix += CA B * C+C
Push +A B*++
Pop *, Postfix += *A B*
Postfix += BABB
Push *A**
Postfix += AAA
RemarkpostFixExpStackCh
Pop +, Postfix += +A B * C + D E F+-/()
Pop (A B * C + D E F+-/)
Pop /, Postfix += /A B * C + D E F+/-
A B * C + D E F+/- Pop -, Postfix += -
First try to solve it without looking at the answer.
CSS342: Stacks and Compilers 27
Calculator Design• The code is located at:
– http://courses.washington.edu/css342/fukuda/code/stack/evaluator/• Three main components (in a typical language processor
format)1. Lexical analyzer
token.h tokenizer.h, and tokenizer.cpp.hRead a line of characters and return tokens.
2. Syntax analyzerevaluator.h’s PREC_TABLE[] and evaluator.cpp.h’s processToken( )In general, analyze a structure of an arithmetic expression.Convert an infix expression to postfix as checking the syntax.
3. Evaluatorevaluator.cpp’s binaryOp( )Interprets an analyzed (or postfix) expression.
Calculator Design
CSS342: Stacks and Compilers 28
Lexical Analyzer Calculator Design
1. Text Example 2. Lab/Home Work 3. LEX
i
* – val
getc( ) == ‘*’
getc( ) == ‘0’ ~’9’
i
* > val
getc( ) == ‘*’
getc( ) == ‘0’ ~’9’
>= >>
(
‘>’‘–’
–
–
(MULT OPARENMINUS
VALUEVALUEOPAREN
UN_MINUS
MINUS
MULT
GT
GE SHIFT_R
DIGIT [0-9]ID [a-z][a-z0-9]
%%
{DIGIT}+ { printf( “int = %d\n”, atoi( yytex ) );
{DIGIT}+”.”{DIGIT}* { printf( “float = %g\n”, atof( yytex ) );}
{ID} { printf( “identifier = %s”, yytext );
if|else|while|for|case { printf( “keyword = %s”, yytext );}
From Unix shell:[fukuda@home] Lex pascal.tex[fukuda@home] lslex.yy.c pascal.lex[fukuda@home] gcc lex.yy.c
http://dinosaur.compilertools.net/lex/index.html
CSS342: Stacks and Compilers 29
Syntax Analyzer• Text example and lab/home
work– Infix to prefix algorithm
• In general– Syntactic tree
– Postfix: Traversing a tree from left to right, as printing the left, the right, and the parent of each node from bottom to root.
– Prefix: Traversing a tree from left to right, as printing the parent, the left, and the right of each node from top to bottom
Calculator Design
A – (B + C * D) / E
A
B
C D
E+
–
*
/
CSS342: Stacks and Compilers 30
Syntax Analyze• Then how can you make such a tree?• YACC http://dinosaur.compilertools.net/yacc/index.html
Calculator Design
expression : primary| unary_expr| binary_expr;
primary: ID
{ $$=(int)maketree( ID, id, NULL ); }: VALUE
{ $$=(int)maketree( VALUE, value, NULL ); };
unary_expr: MINUS expression
{ $$=(int)maketree( UN_MINUS, (TREE)$2, NULL ); };
Binary_expr: expression STAR expression
{ $$=(int)maketree( MULT, (TREE)$1, (TREE)$3 ); }| expression SLASH expression
{ $$=(int)maketree( DIV, (TREE)$1, (TREE)$3 ); };
Need 1. yylex( ) provided by LEX2. All grammar definition in parse.y( )