Lab 2: Recursive-Descent Compilers

Lab Assigned Lab Due
(Start of class)
4 Feb 20 Feb


Abstract: Using two parsing methods, you will implement a simple expression evaluator.

Overview


Setup

  1. Download the following files for use the rest of the semester.

    Make sure they are saved as .jar files! Internet Explorer tried to save them as zip files in CEC

    Put them in a reliable place (for example,
    WindowsLinuxMac OS X
    C:\CS431Tools\/usr/lib//Library/431Tools/
    because you'll need to reference them from the ant build file.
  2. Now download and install the eclipse project for this lab:
    1. Download this hw2.zip file and put it in a temporary but handy spot (like your Desktop).
    2. From eclipse, click File → Import … and choose Existing Projects into Workspace
    3. Click Select archive file and browse to select the hw2.zip archive file you downloaded
    4. The project CSE431hw2 should appear and be selected for installation. Click Finish
  3. In the Package Explorer, open the CSE431hw2 project.

    Eclipse, in its eagerness, has probably already tried to compile your project, but there are some automatically generated files that are missing, because we haven't really built the project yet.

    Silly eclipse.
    So don't worry about problems just yet.
  4. In the Package Explorer, open the build.xml file for editing, because we are going to use eclipse's ant facility to build projects this semester; eclipse's built-in project builder doesn't know about the tools we're using.
    1. You must change the value of the toolpath property (currently "YourToolPath") to the directory or folder containing the CUP and JFlex jar files you've installed.
    2. Save your work on the build.xmlfile.
  5. In some of the files for this lab, including some of the automatically generated Java files, there are references to CUP's runtime library, in the package java_cup.runtime. We must make eclipse aware of this:

    1. Click on the CSE431hw2 in the Package Explorer
    2. Click FileProperties
    3. Click Java Build Path
    4. Select the Libraries tab
    5. Click Add External JARs
    6. Add the java-cup-11a.jar file to the list by browsing for the location at which you stored the file. You do not need the JFlex jar file.
  6. Now we will build the project using eclipse's ant facility:
    1. From the Package Explorer, right-click build.xml and select Run as → Ant build
    2. On the JRE tab, click Run in the same JRE as the workspace.
      This makes eclipse's internal Java compiler available to the build process.
    3. On the Refresh tab, click Refresh resources on completion
      This makes eclipse aware of the new files generated by the build process (the scanner and parser).
    4. Click Run to execute the build file. If all goes well, you should see in the Console window:
      1. cup output showing code written to Parser.java and sym.java
      2. jflex output showing Yylex.java was generated
      3. javac showing that files were compiled.

  7. Next let's try executing the project, even though it won't do much yet.
    1. Select the tdn or bup class from the default package (you may have to expand the package to see the classes) in the Package Explorer.
    2. Right-click the file, select Run as → Run…
    3. Choose Java Application
      • In the Classpath tab add java-cup-11a.jar to the list as an External Jar File
      • In the Arguments tab, specify the input file, such as TestFiles/good1
    4. Click Run
    You can rerun the application using the green arrow button without having to respecify the above information.

Assignment

Here is a summary of the files for this project:
RecursiveDescent.java The skeleton for your predictive parser.
addhaque.cup The CUP grammar specification file.
TestFiles The directory of test files for this project
tdn.java Contains the main for your top-down (recursive-descent) parser
bup.java Contains the main for your bottom-up parser
  1. Design a grammar free of left-recursion for the language Add Haque. The final grammar you use for your top-down parser should be placed in the RecursiveDescent.java file, as indicated by the comments, as your answer for this part. Your implementation must agree with your stated grammar for this part or points will be deducted.
  2. Compute the First() and Follow() sets for each nonterminal in the grammar. Place your answer in the RecursiveDescent.java file, as indicated by the comments.
  3. Implement a recursive-descent, predictive parser for this language. Your implementation must agree with the grammar you provided as your answer for question (1). For each "outermost" expression in a file, print the value associated with the expression. For this part, you will modify only the file RecursiveDescent.java.

    Something you need to know: A Symbol type has two components:

    sym
    is the int reflecting the type of the symbol as defined in sym.java
    value
    is the object associated with the symbol. For example, for the number type, this is an Integer object
  4. Document how you treated the result of a (mean ...) expression. Place your answer in the RecursiveDescent.java file, as indicated by the comments.
    To turn in this part, send mail to legrand@cs.wustl.edu with the subject line 'homework 2a lastname_firstname', and attach your RecursiveDescent.java
  5. [To be done in studio on 18 February 2008] Augment the given CUP grammar specification to include actions that compute the values of the expressions bottom-up. For each ``outermost'' expression, print the value associated with the expression. For this part, you will modify only the file addhaque.cup. Note that this file is already suitable for bottom-up parsing: you need not use your top-down grammar for this part. However, some modification of this file will make your job substantially easier.
    To turn in this part, send mail to legrand@cs.wustl.edu with the subject line 'homework 2b lastname_firstname', and attach your addhaque.cup

Notes


Appendix: Grammar for addhaque calculator

CUP specification for AddHaque: addhaque.cup
import java_cup.runtime.*;
import hw2.*;
import Common.Listing;

terminal Integer number;
terminal         plus, minus, sum, product, times, negate, mean;
terminal         lparen, rparen;

non terminal Integer  Program, File, Lists, List, Expression;
non terminal Integer  Atom, Operand, Operands;

start with Program;
Program
	::= File
	;

File   
	::= Lists
	;

Lists
	::= Lists List
	|   List
	;

List
	::= lparen Expression rparen
	;

Expression
	::= plus    Operand Operand
	|   minus   Operand Operand
	|   times   Operand Operand
	|   negate  Operand
	|   sum     Operands
	|   product Operands
	|   mean    Operands
	;

Operand
	::= Atom
	;

Operands
	::= Operands Operand
	|   Operand
	;

Atom
	::= List
	|   number
	;