CS152: Labs

Essential software includes: The software has been installed under Linux. Paths are provided below because there are now two versions of java on the systems (the older one can't be removed as there are dependencies on it).

Java compiler (javac) and other executables are in the following directory:
/usr/csshare/pkgs/jdk1.5.0_05/bin

The .jar file for CUP is in:
/usr/csshare/pkgs/jdk1.5.0_05/jre/lib/ext/java-cup-v11a.jar

The package directory for jflex is:
/usr/csshare/pkgs/jflex-1.4.1

Java Documentation has been installed to:
/usr/csshare/pkgs/jdk-1.5.0-doc/docs/index.html

The /bin directory for JDK needs to be added to the PATH, and the share needs to be added to the CLASSPATH. Since the systems people intend on moving to mandatory profiles, this will be included in the profile for all CS majors.

The tools are used with the command line. The commands:
java java_cup/Main < [input]
java JLex/Main [input]
are used to access the corresponding tools.

Lab 1

Topics: This class will require plenty of programming in Java; I hope most of you worked in Java before. For those who have never encountered Java, Norman Matloff's
A Quick, Painless Introduction to the Java Programming Language is not a bad place to start. If need be, I can dedicate a lab and/or some extra out-of-lab time to bring everyone to the same page. Java is not a difficult language to learn, and the subset of Java that is necessary to do well in this class is largely similar to C++, albeit easier to comprehend at first and more intuitive. In my oppinion, of course.

Two other tools that will be used in this class are JFlex, a lexical analyzer (aka lexer, aka scanner) generator written in Java, and CUP, a parser generator written in Java. At this point it is too early to give elaborate demonstrations of the two progrmas, but do browse through their home pages and their manuals.

Java Documentation:

Very useful link to have in your bookmarks is Sun's Java Documentation web page. If you are using it very often (and I predict that you will), you might find it convenient to download it localy onto the machine you will be working on. A work of caution though: last time I downloaded it, once uncompressed it was about 200Mb big.

Reading: Downloads:

All packages needed for the labs will be installed in the computer labs; however, if you wish to install it on your home machines or laptops, here are the links to the downloads: In Lab Exercises:
  1. MiniJava is basically a subset of JAVA. Write a GCD calculator in MiniJava (not in JAVA!), referring to the MiniJava's language specification.
  2. Compile your program and familiarize yourself w/ the javac and java compiler and byte-code-interpreter usage.
  3. Write a recursive MiniJava program that would compute the Fibonacci sum of a given number (reminder: Fib(n) = Fib(n-1) + Fib(n-2)).

Lab 2

Topics: Reading:
In Lab Exercise:
  1. Generate a lexer (using jflex) that would count the number of lines, words and number of characters in a given text file. Words are consisted of characters and are separated w/ white space only. The generated lexer should report the line, word and character count information once, when the EOF symbol is reached. No use of yyline is allowed in this exercise.
  2. You may copy and modify the MiniJava.jflex template file for this exercise.

Lab 3

Topics: Reading:
In Lab Exercise:
  1. You may copy and modify the MiniJava.jflex file you're developing for Assignment 1 for this exercise
  2. Try to bring the MiniJava.jflex file you copied to a compilable state (It needs not to define the complete MiniJava lexical specification). Some compilable state of your code is good enough for this exercise.
  3. Add the following line at the very beginning of your .jflex file.
    import java_cup.runtime.*;
    
    JFlex is built to be integrated with CUP parser generator (which is the tool to be used in Assignment 2), so the statement above imports the CUP classes into our lexer.
  4. In the section that follows the first %%, we need to add the following list of directives.
    %cupsym Sym
    %cup
    %cupdebug
    
    As also stated in the JFlex manual:
    %cup
    The %cup directive enables the CUP compatibility.

    %cupsym "classname"
    Customizes the name of the CUP generated class/interface containing the names of terminal tokens. The directive should not be used after %cup directive, but before.

    %cupdebug
    Creates a main function in the generated class that expects the name of an input file on the command line and then runs the scanner on this input file. Prints line, column, matched text, and CUP symbol name for each returned token to standard out.

  5. Sym is the name of the class where we define the names of our token classes. For every terminal you have used in MiniJava.jflex, you need to add a constant to the file Sym.java. Download this file and compile it. This file will be automatically generated by the CUP parser generator in Assignment #2.
  6. Next, into the first %{ ... %} section of your MiniJava.jflex file insert the following methods.
      Sym sym;
    
      private Symbol symbol(int type) {
        return new Symbol(type, yyline, yycolumn);
      }
      private Symbol symbol(int type, Object value) {
        return new Symbol(type, yyline, yycolumn, value);
      }
    
    The above two methods creates the tokens that are communicated to the parser. Out of the two methods first one defines a token with no semantic value, whereas the second one defines a token with some semantic value.
  7. Finally, modify all your action statements from
    reg_exp_1 		{ System.out.println("SOME_TOKEN"); }
    reg_exp_2 		{ System.out.println("TOKEN_W_SEMANTIC_VALUE(" + yytext() + ")" ); }
    
    to
    reg_exp_1 		{ return symbol(sym.SOME_TOKEN); }
    reg_exp_2 		{ return symbol(sym.TOKEN_W_SEMANTIC_VALUE, new SOME_CLASS_CONSTRUCTOR( yytext() )); }
    
    In order to return a Java String or a Java Integer object, you need to replace the new SOME_CLASS_CONSTRUCTOR() with new String() or with new Integer() as applicable.
  8. Compile and build the lexer. However, to get this to compile, you must have the path to CUP classes in your CLASSPATH. One way to accomplish this is to pass the CLASSPATH as an argument to the Java compiler:
     /usr/csshare/pkgs/jdk1.5.0_05/bin/javac -classpath /usr/csshare/pkgs/jdk1.5.0_05/jre/lib/ext/java-cup-v11a.jar:. Lexer.java Sym.java
    
  9. Test the Lexer class on several test programs:
    /usr/csshare/pkgs/jdk1.5.0_05/bin/java -classpath /usr/csshare/pkgs/jdk1.5.0_05/jre/lib/ext/java-cup-v11a.jar:. Lexer <YOUR TEST FILE>
    
    Due to the %cupdebug directive in the MiniJava.jflex file, no actions (i.e. return of tokens in our case) will get executed; instead, the lexer will output the token, the actual text and line and column where the token was found.

Lab 4

Topics: Reading:
Important Note: In Lab Exercise:
  1. Write a lexer and a parser for the below provided calculator grammar.
  2. You may download the jflex skeleton file from Assignment 1, and the cup skeleton file from Assignment 2 for this exercise.
  3. Calculator grammar is given as follows:
    	program		->	vardec* statement*
    
    	vardec		->	type ID ;
    
    	type		-> 	INT
    			->	REAL
    
    	statement  	-> 	print ( exp ) ;
    		  	-> 	ID = exp ;
    
    	exp		->	exp op exp
    		 	->	INTEGER_LITERAL
    			->	REAL_LITERAL
    			->	ID
    			->	( exp )
    
  4. Lexical Issues:
  5. Compile and build your parser. You may use the compile and run_parser scripts posted for Assignment 2.
  6. Test your parser w/ several sample files. Expected output of your parser is a print out of the production rules reduced in order upon parsing a given calculator source file. The actual values of identifier names, integer and string literals should be printed on the output rather than the token names that correspond to the respective token classes.
Important Note:

Lab 5

Topics: Reading:
In Lab Exercise:
  1. No in-lab exercise today. To get a credit for today's lab, you need to be there in lab the entire time and need to be working on assignment #2.

Lab 6

Topics: In Lab Exercise:
  1. Design abstract syntax tree nodes for the Calculator grammar used in Lab4.
  2. You may use MiniJava's Syntax Tree classes definitions as a reference in designing the AST for the Calculator grammar. For the time being do not add any accept methods to your AST nodes although they are there defined in MiniJava's AST nodes.
  3. When you're done coding your AST node classes, open your .cup file for the Calculator language and modify the semantic action for each production rule to return an instance of the appropriate AST class suitable for that production rule.
  4. Compile and build your parser. You may use the compile and run_parser scripts posted for Assignment 2.
  5. Test your parser w/ several sample files. Expected output of your parser is your parser exiting gracefully upon parsing a given lexically and syntactically correct calculator source file.

Lab 7

Topics: In Lab Exercise:
  1. Update every one of your AST classes to include the following method:
    	public void accept(Visitor v){
    	    v.visit(this);
    	}
    
  2. Define a visitor interface, which includes a visit method for every concrete class in your AST class collection.
    	public interface Visitor {
    	   public void visit(Program n);
    	   // ...
    	   // A VISIT METHOD PER AST CLASS GOES HERE
    	   // ...
    	}
    
  3. Define a PrettyPrintVisitor class, which implements the Visitor interface defined above.
    	public class PrettyPrintVisitor implements Visitor {
    
    		public void visit(Program n) {
    		   // YOUR IMPLEMENTATION GOES HERE
    		}
    		
    		// IMPLEMENTATION OF REMAINING VISIT METHODS GOES HERE
    
    	}
    
  4. Modify the main() method in your .cup file as follows:
       public static void main(String[] args){
          try{
           Parser p = new Parser(new Lexer(new FileReader(args[0])));
           Program prog = p.parse().value;
    
           prog.accept(new PrettyPrintVisitor());
          }catch(Exception e ){} 
       }
    
    Above code assumes that you have an AST class named Program. If the name of your AST class for the production:
     
    	program -> vardec* statements* 
    
    is Foo, then the above code should look like this:
       public static void main(String[] args){
          try{
           Parser p = new Parser(new Lexer(new FileReader(args[0])));
           Foo prog = p.parse().value;
    
           prog.accept(new PrettyPrintVisitor());
          }catch(Exception e ){}
       }
    
  5. You may compile and test your parser using the compile and run_parser scripts posted for Assignment 2.
  6. The output of your visitor should be the original source code printed back on the System.out. However, make sure the lists (i.e. vardec* and statement*) in your grammar print in the correct order.

Lab 8

Topics: In Lab Exercise:
  1. You may find the working solution to Lab 7 in here.
  2. Update every one of your AST classes to include the following method:
    	public Type accept(TypeVisitor v){
    	    return v.visit(this);
    	}
    
  3. Define a visitor interface, which includes a visit method for every concrete class in your AST class collection.
    	public interface TypeVisitor {
    	   public Type visit(Program n);
    	   // ...
    	   // A VISIT METHOD PER AST CLASS GOES HERE
    	   // ...
    	}
    
  4. Define a BuildSymbolTableVisitor class, which implements the Visitor interface defined in Lab 7.
    	public class BuildSymbolTableVisitor implements Visitor {
    	
    		SymbolTable symTable;
    
    		BuildSymbolTableVisitor(){
                       symTable = new SymbolTable();
        		}
    
        		public SymbolTable getSymbolTable(){
                       return symTable;
        		}
    
    		public void visit(Program n) {
    		   // YOUR IMPLEMENTATION GOES HERE
    		}
    		
    		// IMPLEMENTATION OF REMAINING VISIT METHODS GOES HERE
    
    	}
    
  5. Define a TypeCheckVisitor class, which implements the TypeVisitor interface defined above.
    	public class TypeCheckVisitor implements TypeVisitor {
    
    		SymbolTable symTable;
    
    		TypeCheckVisitor(SymbolTable s){
          		  symTable = s;
        		}
    
    		public Type visit(Program n) {
    		   // YOUR IMPLEMENTATION GOES HERE
    		}
    		
    		// IMPLEMENTATION OF REMAINING VISIT METHODS GOES HERE
    
    	}
    
  6. Modify the main() method in your .cup file as follows:
       public static void main(String[] args){
          try{
           Parser p = new Parser(new Lexer(new FileReader(args[0])));
           Program prog = p.parse().value;
    
           BuildSymbolTableVisitor symTabVisitor = new BuildSymbolTableVisitor();
           prog.accept(symTabVisitor); 
           prog.accept(new TypeCheckVisitor(symTabVisitor.getSymbolTable())); 
          }catch(Exception e ){} 
       }
    
  7. You may compile and test your parser using the compile and run_parser scripts posted for Assignment 2.
  8. The symbol table building phase of your semantic analyzer should add every declared variable to the SymbolTable. No duplicate declarations of the same name is allowed.
  9. The type cheking phase should check for the following.
  10. Make sure your program catches all possible type errors and prints explanatory error messages for them.
  11. Last but not least, make sure you test your programs before having them checked out.

Lab 9

Topics: In Lab Exercise:
  1. No in-lab exercise today. To get a credit for today's lab, you need to be there in lab the entire time and need to be working on assignment #4 or on assignment #5.

Lab 10

Topics: In Lab Exercise:
  1. No in-lab exercise today. To get a credit for today's lab, you need to be there in lab the entire time and need to be working on Assignment #5.