COP 4020 Programming Assignment 6: Calc2Lisp

Educational Objectives: After completing this assignment, the student should be able to do the following:

Operational Objectives: Implement a calculator-to-lisp application in Java using the abstract syntax tree class defined in AST.java

Deliverables: Two files AST2.java and Calc2Lisp.java

Copy (and download if needed) the CalcAST.java and AST.java source files from

~cop4020p/fall08/examples/

The CalcAST program constructs an abstract syntax tree (AST) representation of arithmetic expressions. For example, when the expression that you input is 1+2; the program constructs the following AST:

  +
 / \
1   2

This tree structure is constructed with the AST class, which has a tree node structure that contains an optional operator (e.g. +), an optional value (e.g. 1), and optional left and right subnodes for the operands to unary and binary operators. The AST class has a toLisp method. When invoked it will output the expression in Lisp form, such as (+ 1 2) for example.

Compile the sources on linprog with:

javac CalcAST.java

And run the resulting program:

java CalcAST

The program will wait for input from the command line, so type 1+2;<enter> for example. The program output will be the Lisp equivalent of this expression (+ 1 2). (Note that the toLisp method does a preorder traversal of the AST, implemented recursively. See COP 4530 Lecture Notes.)

Modify the CalcAST.java program to pre-evaluate parts of expressions when possible. That is, all arithmetic operations are performed when the operands are numeric. When one of the operands is non-numeric (symbolic), an AST node is created. The output of the program will be partially evaluated expressions translated into Lisp.

In addition, add productions and code to implement the power operator ^ (see also Programming Assignment 4). For the implementation, you need to use the static Math.pow method of class Math to compute powers. This operator must be evaluated when possible, along with the other arithmetic operators.

You may find it convenient to strengthen the AST class. Whether you do or not, copy the file AST.java to AST2.java and rename the class to AST2. Your Calc2Lisp should be a client of AST2. Both files hould be turned in (using a submit script).

Examples:

java Calc2Lisp
2*(1+3)-2^3+xyz;
 xyz
java Calc2Lisp
2*(1+3)-2^3+x*y*z;
 (* (* x y) z)

The outputs are simplified Lisp expressions - xyz is an identifier while (* (* x y) z) is the product of x, y, z.

Note that the AST node structure includes a val member that can be used to store a node's value and to pass values as part of the AST instances that are returned from methods (as synthesized attribute values) and passed to methods (as inherited attribute values). The type of val is Object, so to create an AST node with an integer value, say 7, you need: new AST(new Integer(7)).

Here are some sample calculations you can use to test your caclulator:

1+2+3;
 6

1*2*3;
 6

1*-2*(3-6);
 6

1+2+x+3;
 (+ (+ 3 x) 3)

x+1+2;
 (+ (+ x 1) 2)

x+0;
 x

1*x;
 x

x^1;
 x

--2;
 2

--x;
(-(- x))

2+3+x+4+5; 
 (+ (+ (+ 5 x) 4) 5)

2*3*x*4*5;
 (* (* (* 6 x) 4) 5)

2^3^x^4^5;
 (^ 2 (^ 3 (^ x 1024)))

Note that the semantic rules of the grammar enforce associativity, so 1+2+x+3 is evaluated from the left. The evaluation process does not consider commutativity, so the expression does not simplify to x+6.

Turn in the files AST2.java and Calc2Lisp.java using the submit script pr6submit.sh.