Computer Science 112 Fundamentals of Programming II Expression Trees.

39
Computer Science 112 Fundamentals of Programming II Expression Trees

Transcript of Computer Science 112 Fundamentals of Programming II Expression Trees.

Computer Science 112

Fundamentals of Programming IIExpression Trees

A Parse (Expression) Tree

Evaluator

Source language program

Syntax error messages

Ok or not OKParser

The value of the expression

Semantic error messages

A parse tree

Trees for Binary Expressions

• An expression tree for a number is a node containing the number

• Otherwise, the tree is a node containing an operator and links to left and right subtrees

• The subtrees contain the operands of the expression

Example Expression Trees

23 23

Example Expression Trees

23 23

3 + 5+

3 5

Root nodeRight subtreeLeft subtree

Example Expression Trees

23 23

3 + 5+

3 5

3 + 5 * 4 +

3 *

5 4

Root nodeRight subtreeLeft subtree

Example Expression Trees

23 23

3 + 5+

3 5

3 + 5 * 4 +

3 *

5 4

Root nodeRight subtreeLeft subtree

(3 + 5) * 4

+

3 5

*

4

Operator Precedence

3 + 5 * 4 +

3 *

5 4

(3 + 5) * 4

+

3 5

*

4

5 * 4 + 3 +

*

5 4

3

Operators with higher precedence appear lowerin the tree, unless overriddenby parentheses.

Operator Precedence

5 * 4 - 3 -

*

5 4

3

When operators have equalprecedence, the ones to theleft appear lower in the tree.

5 + 4 - 3 -

+

5 4

3

5 + 4 - 3 + 6 -

+

5 4

3

+

6

Expression Trees

5 * 4 - 3 -

*

5 4

3

5 + 4 - 3 -

+

5 4

3

5 + 4 - 3 + 6 -

+

5 4

3

+

6

33

Properties of Expression Trees

• Numbers are in leaf nodes

• Operators are in interior nodes

• All interior nodes have exactly two children

• Both types of nodes implement the same interface

Things We Might Want from an Expression Tree

• Its value

• Its prefix form

• Its infix form

• Its postfix form

Resources# The interface to all expression tree classes

value() # Returns the int value of the expression prefix() # Returns a string in prefixinfix() # Returns a string in infix (fully parenthesized)postfix() # Returns a string in postfix

# Implementing classes

LeafNode(data)

InteriorNode(opToken, leftOperandNode, rightOperandNode)

Evaluating an Expression Tree

• A leaf node returns the number contained in it

• An interior node evaluates its left and right subtrees, applies its operator to these values, and returns the result

Evaluate This One

3 + 5 * 4 +

3 *

5 4

Contains an operator, soevaluate left and right subtrees

Evaluate This One

3 + 5 * 4 +

3 *

5 4Contains anumber, soreturn 3

Evaluate This One

3 + 5 * 4 +

3 *

5 4

Contains an operator, soevaluate left and right subtrees

Evaluate This One

3 + 5 * 4 +

3 *

5 4

Contains anumber, soreturn 5

Evaluate This One

3 + 5 * 4 +

3 *

5 4

Contains anumber, soreturn 4

Evaluate This One

3 + 5 * 4 +

3 *

5 4

Return 5 * 4 = 20

Evaluate This One

3 + 5 * 4 +

3 *

5 4

Return 3 + 20 = 23

Evaluating a Leaf Nodeclass LeafNode(object):

def __init__(self, data): self.data = data

def value(self): return self.data

# Other methods go here

A LeafNode forms the base case for the recursive processing of expression trees

Evaluating an Interior Nodeclass InteriorNode(object):

def __init__(self, opToken, leftOperandNode, rightOperandNode): self.operator = opToken self.left = leftOperandNode self.right = rightOperandNode

def value(self): return self.computeValue(op, self.left.value() self.right.value()) # Other methods go here

The method computeValue is the same one we used in the stack-based evaluator

Tree Traversals

• An expression tree supports three types of traversals– preorder (visit the node, then go left, then go right)– inorder (go left, then visit the node, then go right)– postorder (go left, then go right, then the visit node

Tree Traversals

• An expression tree supports three types of traversals– preorder (visit the node, then go left, then go right)– inorder (go left, then visit the node, then go right)– postorder (go left, then go right, then visit the node

• These traversals can generate the prefix, infix, and postfix notations of an expression

Code for postfixclass LeafNode(object):

def __init__(self, data): self.data = data

def postfix(self): return str(self.data)

# Other methods go here

class InteriorNode(object):

def __init__(self, opToken, leftOperandNode, rightOperandNode): self.operator = opToken self.left = leftOperandNode self.right = rightOperandNode

def postfix(self): return self.left.postfix() + " " + self.right.postfix() \ + " " + str(self.operator)

Generate Postfix

3 + 5 * 4 +

3 *

5 4

Node an operator, so go left

def postfix(self): return str(self.data)

def postfix(self): return self.left.postfix() + " " + self.right.postfix() \ + " " + str(self.operator)

Generate Postfix

3 + 5 * 4 +

3 *

5 4

Node an operand, return "3"

def postfix(self): return str(self.data)

def postfix(self): return self.left.postfix() + " " + self.right.postfix() \ + " " + str(self.operator)

Generate Postfix

3 + 5 * 4 +

3 *

5 4

Now go right

3

def postfix(self): return str(self.data)

def postfix(self): return self.left.postfix() + " " + self.right.postfix() \ + " " + str(self.operator)

Generate Postfix

3 + 5 * 4 +

3 *

5 4

Node an operator, so go left

3

def postfix(self): return str(self.data)

def postfix(self): return self.left.postfix() + " " + self.right.postfix() \ + " " + str(self.operator)

Generate Postfix

3 + 5 * 4 +

3 *

5 4

Node an operand, return "5"

3 5

def postfix(self): return str(self.data)

def postfix(self): return self.left.postfix() + " " + self.right.postfix() \ + " " + str(self.operator)

Generate Postfix

3 + 5 * 4 +

3 *

5 4

Now go right

3 5

def postfix(self): return str(self.data)

def postfix(self): return self.left.postfix() + " " + self.right.postfix() \ + " " + str(self.operator)

Generate Postfix

3 + 5 * 4 +

3 *

5 4

Node an operand, return "4"

3 5 4

def postfix(self): return str(self.data)

def postfix(self): return self. left.postfix() + " " + self. right.postfix() \ + " " + str(self.operator)

Generate Postfix

3 + 5 * 4 +

3 *

5 4

Return "*"

3 5 4 *

def postfix(self): return str(self.data)

def postfix(self): return self.left.postfix() + " " + self.right.postfix() \ + " " + str(self.operator)

Generate Postfix

3 + 5 * 4 +

3 *

5 4

Return "+"

3 5 4 * +

def postfix(self): return str(self.data)

def postfix(self): return self.left.postfix() + " " + self.right.postfix() \ + " " + str(self.operator)

Building an Expression Tree

• Each parsing method builds a tree that represents the portion of the expression for which it is responsible

• Each parsing method returns its tree to the caller

Build a Tree for Primaries# primary = number | "(" expression ")"def primary(self): token = scanner.get() if token.getType() == Token.INT: tree = LeafNode(token.getValue()) scanner.next() elif token.getType() == Token.L_PAR: scanner.next() tree = self.expression() self._accept(scanner.get(), Token.R_PAR, "')' expected") scanner.next() else: tree = LeafNode(token.getValue()) fatalError (token, "unexpected token") return tree

Build a Tree for Expressions

# expression = term { addingOperator term }def expression(self): tree = self.term() token = scanner.get() while token.getType() in (Token.PLUS, Token.MINUS): scanner.next() tree = InteriorNode(token, tree, self.term()) token = scanner.get() return tree

For Friday

Heaps