The Visitor Design Pattern and Java Tree Builder

Slides:



Advertisements
Similar presentations
Semantic Analysis Chapter 4. Role of Semantic Analysis Following parsing, the next two phases of the "typical" compiler are – semantic analysis – (intermediate)
Advertisements

Introduction to Design Patterns What is Design Pattern? The Container Pattern. The Visitor Pattern. The SearchableContainer Pattern. The Enumeration Pattern.
The Visitor Design Pattern and Java Tree Builder
SENG 531: Labs TA: Brad Cossette Office Hours: Monday, Wednesday.
CS 206 Introduction to Computer Science II 02 / 20 / 2009 Instructor: Michael Eckmann.
Inheritance and Class Hierarchies Chapter 3. Chapter 3: Inheritance and Class Hierarchies2 Chapter Objectives To understand inheritance and how it facilitates.
Using Java Tree Builder Professor Yihjia Tsai Tamkang University.
CS 206 Introduction to Computer Science II 10 / 01 / 2008 Instructor: Michael Eckmann.
CS 206 Introduction to Computer Science II 10 / 14 / 2009 Instructor: Michael Eckmann.
Visitor Pattern Jeff Schott CS590L Spring What is the Purpose of the Visitor Pattern ? n Represent an operation to be performed on the elements.
Design Patterns 2 Fawzi Emad Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
Visitor Matt G. Ellis. Intent Metsker: Let developers define a new operation for a hierarchy without changing the hierarchy classes. GoF: Represent an.
Information Hiding and Encapsulation
Introduction to Design Patterns What is Design Pattern? The Container Pattern. The Visitor Pattern. The SearchableContainer Pattern. The Iterator Pattern.
Introduction to Design Patterns What is Design Pattern? The Container Pattern. The Iterator Pattern. The Visitor Pattern. The SearchableContainer Pattern.
Guide To UNIX Using Linux Third Edition
The Visitor Design Pattern and Java Tree Builder
Interpreter By: Mahmoodreza Jahanseir Amirkabir University of Technology Computer Engineering Department Fall 2010.
ECE450 - Software Engineering II1 ECE450 – Software Engineering II Today: Design Patterns VI Composite, Iterator, and Visitor Patterns.
CSC 8310 Programming Languages Meeting 2 September 2/3, 2014.
CSE 331 Software Design & Implementation Hal Perkins Winter 2013 Design Patterns Part 3 (Slides by Mike Ernst and David Notkin) 1.
Sumant Tambe, et. al LEESA DSPD 2008 An Embedded Declarative Language for Hierarchical Object Structure Traversal Sumant Tambe* Aniruddha Gokhale Vanderbilt.
Sumant Tambe, et. al LEESA DSPD 2008 An Embedded Declarative Language for Hierarchical Object Structure Traversal Sumant Tambe* Aniruddha Gokhale Vanderbilt.
1 Object-Oriented Software Engineering CS Interfaces Interfaces are contracts Contracts between software groups Defines how software interacts with.
Polymorphism, Inheritance Pt. 1 COMP 401, Fall 2014 Lecture 7 9/9/2014.
Programming in Java Unit 2. Class and variable declaration A class is best thought of as a template from which objects are created. You can create many.
CreatingClasses-part11 Creating Classes part 1 Barb Ericson Georgia Institute of Technology Dec 2009.
1 Computer Systems -- Introduction  Chapter 1 focuses on:  the structure of a Java application  basic program elements  preparing and executing a program.
Go4 Visitor Pattern Presented By: Matt Wilson. Introduction 2  This presentation originated out of casual talk between former WMS “C++ Book Club” (defunct.
Chap. 1 Classes, Types, and Objects. How Classes Are Declared [ ] class [extends ] [implements,, … ] { // class methods and instance variable definitions.
Hello.java Program Output 1 public class Hello { 2 public static void main( String [] args ) 3 { 4 System.out.println( “Hello!" ); 5 } // end method main.
Chris Kiekintveld CS 2401 (Fall 2010) Elementary Data Structures and Algorithms Inheritance and Polymorphism.
CS412/413 Introduction to Compilers and Translators Spring ’99 Lecture 8: Semantic Analysis and Symbol Tables.
Interpretation Environments and Evaluation. CS 354 Spring Translation Stages Lexical analysis (scanning) Parsing –Recognizing –Building parse tree.
Lexi case study (Part 2) Presentation by Matt Deckard.
Design Patterns – II Lecture IV. Singleton Pattern Intent – Ensure a class only has one instance, and provide a global point of access to it Motivation.
Recursive data structures noter ch.3 Modeling recursive structure by class hierarchy Recursive traversal of structure.
2Object-Oriented Program Development Using C++ 3 Basic Loop Structures Loops repeat execution of an instruction set Three repetition structures: while,
....and other creepy things from John Vlissides The Visitor Pattern EXISTS! And its INTENT is to represent an operation to be performed on the elements.
11/25/2015© Hal Perkins & UW CSEH-1 CSE P 501 – Compilers Implementing ASTs (in Java) Hal Perkins Winter 2008.
1 Languages and Compilers (SProg og Oversættere) Bent Thomsen Department of Computer Science Aalborg University With acknowledgement to Wei-Tek Tsai who’s.
Semantics (1).
Basic Scheme February 8, 2007 Compound expressions Rules of evaluation Creating procedures by capturing common patterns.
Application development with Java Lecture 21. Inheritance Subclasses Overriding Object class.
The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1.
Interfaces and Inner Classes
1/33 Basic Scheme February 8, 2007 Compound expressions Rules of evaluation Creating procedures by capturing common patterns.
Iterators ITI 1121 N. El Kadri. Motivation Given a (singly) linked-list implementation of the interface List, defined as follows, public interface List.
DJ: traversal-visitor-style programming in Java Josh Marshall/ Doug Orleans Want to add more on traversal through collections and Aspectual Components.
Inheritance and Class Hierarchies Chapter 3. Chapter 3: Inheritance and Class Hierarchies2 Chapter Objectives To understand inheritance and how it facilitates.
Inheritance and Class Hierarchies Chapter 3. Chapter Objectives  To understand inheritance and how it facilitates code reuse  To understand how Java.
Chapter 1 Java Programming Review. Introduction Java is platform-independent, meaning that you can write a program once and run it anywhere. Java programs.
CSE 332: Design Patterns (Part II) Last Time: Part I, Familiar Design Patterns We’ve looked at patterns related to course material –Singleton: share a.
CMSC 330: Organization of Programming Languages Operational Semantics.
Syntax-Directed Definitions CS375 Compilers. UT-CS. 1.
Java Programming: Guided Learning with Early Objects Chapter 9 Inheritance and Polymorphism.
Basic Scheme February 8, 2007 Compound expressions Rules of evaluation
Behavioral Design Patterns
Variables and Arithmetic Operators in JavaScript
Implementing ASTs (in Java) Hal Perkins Autumn 2009
Subroutines Idea: useful code can be saved and re-used, with different data values Example: Our function to find the largest element of an array might.
Design Pattern: Visitor
Introduction to Java Programming
Implementing ASTs (in Java) Hal Perkins Autumn 2011
The Recursive Descent Algorithm
16. Visitors SE2811 Software Component Design
16. Visitors SE2811 Software Component Design
Visitor Pattern Intent
Presentation transcript:

The Visitor Design Pattern and Java Tree Builder Cheng-Chia Chen

The Visitor Pattern A design pattern enabling the definitions of new operations on an object structure without the requirement to change the classes of the objects. Separate (the specification of) extrinsic operations on an object structure from the structure of objects.

UML Representation of Visitor Pattern

Visitor Structure Element Visitor accept () visitA () = 0; visitB () = 0; ConcreteVisitor ElementA ElementB visitA (); visitB (); accept (); A_method (); accept (); B_method (); Different elements have different concrete interfaces Element abstract base class adds accept interface Double hand-shake between concrete element and visitor allows visitor to call the appropriate concrete element method

Visitor Interactions ElementA ElementB ConcreteVisitor accept (); visitA (); A_method (); accept (); visitB (); B_method ();

Example : integer List public abstract class List { } public class NullList extends List {} class ConsList extends List { int head; List tail; }

Operation : summing an integer list First Approach: Instanceof and Type Casts List l; // The List-object int sum = 0; boolean proceed = true; while (proceed) { if (l instanceof NullList) proceed = false; else if (l instanceof ConsList) { sum = sum + ((ConsList) l).head; l = ((ConsList) l).tail; // Notice the two type casts! }} Advantage: The code is written without touching the classes NullList and ConsList. Drawback: The code constantly uses type casts and instanceof to determine what class of object it is considering.

2nd approach : attach a method to each class The first approach is not object-oriented! To access parts of an object, the classical approach is to use dedicated methods which both access and act on the subobjects. abstract class List { int sum(); } We can now compute the sum of all components of a given List-object l by writing l.sum().

2nd approach (continued) class NullList extends List { public int sum() { return 0; } } class ConsList extends List { int head; List tail; public int sum() { return head + tail.sum(); } } Advantage: The type casts and instanceof operations have disappeared, and the code can be written in a systematic way. Disadvantage: For each new operation (say, multiply all integers, count #integers, print all integers,…) on List-objects, new dedicated methods have to be written, and all classes must be recompiled.

Third Approach: The Visitor Pattern The Idea: Divide the code into an object structure and a Visitor Insert an accept method in each class. Each accept method takes a Visitor as argument. A Visitor contains a method visit(C x) for each possible object class C. (overloading!). abstract List { void accept(Visitor v); } interface Visitor { void visit(NullList x); void visit(ConsList x); }

Third Approach (continued) The purpose of the accept methods is to invoke the visit method in the Visitor which can handle the current object. class NullList extends List { public void accept(Visitor v) { v.visit(this); } //1 } class ConsList extends List { int head; List tail; public void accept(Visitor v) { v.visit(this); } //2 Note: 1 and 2 are the same and can be lifted to parent List. class List { public void accept(Visitor v) // default accept implem. { v.visit(this); } }

Third Approach : (continued) The control flow goes back and forth between the visit methods in the Visitor and the accept methods in the object structure. class SumVisitor implements Visitor { int sum = 0; public void visit(NullList x) {} public void visit(ConsList x) { sum = sum + x.head; x.tail.accept(this); }} ..... SumVisitor sv = new SumVisitor(); l.accept(sv); System.out.println(sv.sum); Notice: The visit methods describe both (1) actions, and (2) access of subobjects. (2) can in fact be determined by object class instead of visitor.

Third Approach : (Continued) Extend your List applications to permit multiplying all integers in a list or counting the number of integers in a list printing out all integers, …. Each can be implemented by defining a new visitor. without the need to change code of List (and NullList and ConsList …).  main advantage of the visitor pattern. class ProductVisitor implements Visitor { int prod = 1; public void visit(NullList x) {} public void visit(ConsList x) { prod = prod * x.head; x.tail.accept(this); }}

class CountVisitor implements Visitor { int count = 0; public void visit(NullList x) {} public void visit(ConsList x) { count++; x.tail.accept(this); }} class PrintVisitor implements Visitor { String result = “”; if( “”.equals(result) ){ result = result + x.head; } else { result = rersult + “ ,” + x.head ;} x.tail.accept(this); }}… CountVisitor cv = new CountVisitor(); PrintVisitor pv = new CountVisitor(); cv.accept(l); System.out.println(cv.count); pv.accept(l); System.out.println(“[“ + pv.result +”]”);

Comarision The Visitor pattern combines the advantages of the two other approaches. Frequent Frequent type casts? recompilation? Instanceof and type casts Yes No Dedicated methods No Yes The Visitor pattern No No The advantage of Visitors: New methods without recompilation! Requirement for using Visitors: All classes must have an accept method. Tools that use the Visitor pattern: JJTree (from Sun Microsystems) and the Java Tree Builder (from Purdue University), both frontends for The Java Compiler Compiler from Sun Microsystems. -SableCC

Visitor: Summary Visitor makes adding new operations easy. Simply write a new visitor. A visitor gathers related operations. It also separates unrelated ones. Adding new classes to the object structure is hard. Key consideration: are you most likely to change the algorithm applied over an object structure, or are you most like to change the classes of objects that make up the structure. As to compiler design, it requires many operations on syntax tree, which is the main object structure of compiler and is relatively stable. Visitors can accumulate state/information. Visitor can break encapsulation. Visitor’s approach assumes that the interface of the data structure classes is powerful enough to let visitors do their job. As a result, the pattern often forces you to provide public operations that access internal state, which may compromise its encapsulation.

The Java Tree Builder (JTB) Developed at Purdue University. http://www.cs.purdue.edu/jtb/ A frontend for The Java Compiler Compiler. Supports the building of syntax trees which can be traversed using visitors. JTB transforms a bare JavaCC grammar into three components: a JavaCC grammar with embedded Java code for building a syntax tree; one class for every form of syntax tree node; and a default visitor which can do a depth-first traversal of a syntax tree.

JTB (continued) The produced JavaCC grammar can then be processed by the Java Compiler Compiler to give a parser which produces syntax trees. The produced syntax trees can now be traversed by a Java program by writing subclasses of the default visitor. Bare JavaCC Grammar Default Visitor JTB Parser JavaCC JavaCC Grammar with embeded code Program SyntaxTree Node Classes SyntaxTree with accept methods MyApplicationVisitor

Using JTB jtb myGrammar.jj // will generates many files: jtb.out.jj -- the original grammar file with syntaxTree building code inserted. /syntaxtree/**.java -- a class for each production /visitor/** Visitor.java, DepthFirstVisitor -- the interface and implemenation ObjectVisitor.java, ObjectDepthFirstVisitor.java -- the visitor interface (& implementation) with return value and argument javacc jtb.out.jj // generates a parser with a specified name javac Main.java // Main.java contains a call of the parser and calls to visitors java Main < prog.f // builds a syntax tree for prog.f, and executes the visitors

Example For the java production void Assignment() : {} { PrimaryExpression() AssignmentOperator() Expression() } JTB produces: Assignment Assignment () : { PrimaryExpression n0; AssignmentOperator n1; Expression n2; {} } { n0= PrimaryExpression() n1=AssignmentOperator() n2=Expression() { return new Assignment(n0,n1,n2); } } Notice that the production returns a syntax tree represented as an Assignment object.

Example (continued) JTB produces a syntax-tree-node class for Assignment: public class Assignment implements Node { PrimaryExpression f0; AssignmentOperator f1; Expression f2; public Assignment(PrimaryExpression n0, AssignmentOperator n1, Expression n2) { f0 = n0; f1 = n1; f2 = n2; } public void accept(visitor.Visitor v) { v.visit(this); } } Notice the accept method; it invokes the method visit for Assignment in the default visitor.

Example : The default visitor looks like this: public class DepthFirstVisitor implements Visitor { ... // // f0 -> PrimaryExpression() // f1 -> AssignmentOperator() // f2 -> Expression() public void visit(Assignment n) { n.f0.accept(this); n.f1.accept(this); n.f2.accept(this); } } Notice the body of the method which visits each of the three subtrees of the Assignment node.

Example: A visitor which operates on syntax trees for Java programs. The program prints the right-hand side of every assignment. public class VprintAssignRHS extends DepthFirstVisitor { void visit(Assignment n) { PrettyPrinter v = new PrettyPrinter(); n.f2.accept(v); v.out.println(); n.f2.accept(this); } } When this visitor is passed to the root of the syntax tree, the depth-first traversal will begin, and when Assignment nodes are reached, the method visit in VprintAssignRHS is executed. Notice the use of PrettyPrinter. It is a visitor which pretty prints Java 1.1 programs. JTB is bootstrapped (JTB written using JTB)