css342: stacks and compilers

30
CSS342: Stacks and Compil ers 1 CSS342: Stacks and Compilers Professor: Munehiro Fukuda

Upload: marcos

Post on 25-Feb-2016

63 views

Category:

Documents


0 download

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 Presentation

TRANSCRIPT

Page 1: CSS342: Stacks and Compilers

CSS342: Stacks and Compilers 1

CSS342: Stacks and Compilers

Professor: Munehiro Fukuda

Page 2: CSS342: Stacks and Compilers

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)

Page 3: CSS342: Stacks and Compilers

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

Page 4: CSS342: Stacks and Compilers

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

Page 5: CSS342: Stacks and Compilers

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

Page 6: CSS342: Stacks and Compilers

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

Page 7: CSS342: Stacks and Compilers

CSS342: Stacks and Compilers 7

Stack Implementation

• Array-based implementation• Pointer-based implementation• Linked list reuse

– Data member– Inheritance

Implementation

Page 8: CSS342: Stacks and Compilers

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

Page 9: CSS342: Stacks and Compilers

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

Page 10: CSS342: Stacks and Compilers

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

Page 11: CSS342: Stacks and Compilers

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

Page 12: CSS342: Stacks and Compilers

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

Page 13: CSS342: Stacks and Compilers

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

Page 14: CSS342: Stacks and Compilers

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

Page 15: CSS342: Stacks and Compilers

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=!}

Page 16: CSS342: Stacks and Compilers

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?

Page 17: CSS342: Stacks and Compilers

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

Page 18: CSS342: Stacks and Compilers

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

Page 19: CSS342: Stacks and Compilers

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

Page 20: CSS342: Stacks and Compilers

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

Page 21: CSS342: Stacks and Compilers

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

Page 22: CSS342: Stacks and Compilers

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

Page 23: CSS342: Stacks and Compilers

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

Page 24: CSS342: Stacks and Compilers

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

Page 25: CSS342: Stacks and Compilers

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

Page 26: CSS342: Stacks and Compilers

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.

Page 27: CSS342: Stacks and Compilers

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

Page 28: CSS342: Stacks and Compilers

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

Page 29: CSS342: Stacks and Compilers

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+

*

/

Page 30: CSS342: Stacks and Compilers

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( )