This tutorial builds on the Numerical Expression Solver tutorial, adding textual variables such as "e" or "pi", and custom ones. Then you will create an applet that takes advantage of this new functionality by creating a graphical representation of an arbitrary expression at each point in space. This applet is shown below.

Starting with the Expression.java file you created last time, add the following variable:

`/* * Used for getting variables */ Variable get;`

This is an object of a type we haven't defined yet, which will serve to return numerical values for variables.

Insert the following `variable()`

function:

`/* * Evaluates variable terms. */ double variable(){ double a; StringBuffer buf = new StringBuffer(); while( s.length() > 0 && Character.isLetter( s.charAt( 0 ) ) ){ buf.append( s.charAt( 0 ) ); s = s.substring( 1 ); } String v = buf.toString(); if( v.compareTo( "e" ) == 0 ){ a = Math.E; } else if( v.compareTo( "pi" ) == 0 ){ a = Math.PI; } else { a = get.variable( v ); } return a; }`

For our purposes, a "variable" is defined as any contiguous sequence of alphabetic characters. This function firsts collects all the contiguous letters, and then checks to see if it recognizes them as one of its built-in constants, "e" or "pi". If not, it makes a call to the *get* object, which hopefully will recognize the variable and return the appropriate value.

This function is not being called yet, so we need to modify the `term()`

function as follows:

`double term(){ double ans = 0; StringBuffer temp = new StringBuffer(); if( Character.isLetter( s.charAt( 0 ) ) ){ // new lines return variable(); // ... } // end new lines while( s.length() > 0 && Character.isDigit( s.charAt( 0 ) ) ){ temp.append(Integer.parseInt( "" + s.charAt( 0 ) )); s = s.substring( 1 ); } ... }`

These newly inserted lines check to see whether the term is a number or a variable. If it starts with a letter, we assume it is a variable and deal with it by calling `variable()`

. Otherwise, we continue as we did before, assuming it is a number.

Now we need to modify the constructor `Expression()`

by changing the first couple lines:

`public Expression( String s, Variable v ){ get = v; // remove white space, assume only spaces or tabs StringBuffer b = new StringBuffer(); ... }`

We changed the declaration to accept a *Variable* object as an additional argument, and then assigned it to our variable *get*. If you know that your expression will contain know variables, you may pass *null* as the second argument.

Finally, in order to run this from the command-line, you will have to change the `main()`

function to pass *null* as a second argument to the `Expression()`

constructor:

`public static void main( String[] args ){ Expression e = new Expression( args[0], null ); System.out.println( e + " = " + e.evaluate() ); }`

These are all the changes that we need to make to *Expression.java*. However, you can't compile it until we create the interface declaration *Variable.java*, given below in its entirety:

`public interface Variable{ /* * Returns the value of given variable. */ public double variable( String s ); }`

This interface allows any object to respond to the `variable()`

function called by an *Expression* instance when it encounters an unknown variable.

You can now compile and run *Expression.java* as before. You can now enter "e" for the number 2.718... or "pi" for 3.141... These two "variables" function as numbers now.

Now let's create the graphical plotter that uses this new functionality. Create the file *ExpressionApplet.java* as follows:

`import java.awt.*; import java.awt.event.*; import java.awt.image.*; public class ExpressionApplet extends java.applet.Applet implements Variable{ Image img; // image buffer used to draw plot Expression exp; // the Expression we wish to draw TextField input; // the user input field for the Expression double x, y; // the currently evaluated variables double left = -Math.PI, right = Math.PI, top = Math.PI, bottom = - Math.PI; // our bounds /* * Set up the interface, create an initial Expression, * and draw it. */ public void init(){ input = new TextField("x^2+y^2",20); Button b = new Button( "Draw" ); final Variable v = this; input.addActionListener( new ActionListener(){ public void actionPerformed( ActionEvent e ){ exp = new Expression( input.getText(), v ); img = null; repaint(); } } ); b.addActionListener( new ActionListener(){ public void actionPerformed( ActionEvent e ){ exp = new Expression( input.getText(), v ); img = null; repaint(); } } ); add( input ); add( b ); exp = new Expression("x^2+y^2", this); repaint(); } }`

As you can see, we have a good number of instance variables. The `init()`

function takes care of setting things up for us, including creating an initial *Expression*, and calling `repaint()`

, which draws the results of evaluating the *Expression*.

If you looked carefully at the above code, you would have noticed that the string passed to the *Expression* to evaluate includes "x" and "y", which it can't evaluate. This is where the *Variable* interface comes into play. *Expression* recognizes that "x" and "y" are variables, but doesn't know what they are, so it calls its `get.variable()`

function to evaluate them. As you might have guessed since the declaration of *ExpressionApplet* says that it implements the *Variable* interface, and in fact the applet is passed to the *Expression* constructor, we will implement that function here:

`/* * Looks for variables we define, and returns them * appropriately. Otherwise, returns NaN. */ public double variable( String s ){ if( s.compareTo( "x" ) == 0 || s.compareTo( "X" ) == 0 ) return x; if( s.compareTo( "y" ) == 0 || s.compareTo( "Y" ) == 0 ) return y; return Math.log(-1); }`

This function is what makes the graphical element possible. In the `paint()`

function which follows, we will go through every pixel, setting the instance variables *x* and *y* appropriately, and then evaluating the *Expression*. If it contains "x" or "y", our `variable()`

function will be called.

Now add the `paint()`

function, which does the actual evaluation and drawing of the *Expression*:

`/* * Evaluate and draw the Expression at every pixel. */ public void paint( Graphics g ){ double min = 0, max = 0; if( img != null ){ g.drawImage( img, 0, 0, this ); return; } for( int y = 0; y < getSize().height; y++ ){ for( int x = 0; x < getSize().width; x++ ){ mapToVirtual( x, y ); double a = exp.evaluate(); if( a > max ) max = a; else if( a < min ) min = a; } } int pix[] = new int[ getSize().width * getSize().height ]; int index = 0; for( int y = 0; y < getSize().height; y++ ){ for( int x = 0; x < getSize().width; x++ ){ mapToVirtual( x, y ); pix[ index++ ] = Color.getHSBColor( (float)(exp.evaluate()/(max-min) - min/(max-min)), 1, 1 ).getRGB(); } } img = createImage( new MemoryImageSource( getSize().width, getSize().height, pix, 0, getSize().width ) ); g.drawImage( img, 0, 0, this ); }`

The first thing to notice is that we check to see if the *img* variable is already defined before we do anything else. If it is defined, then `paint()`

is being called simply because it was obscured, and now needs to be refreshed. If we didn't test for this case, we would have to re-evaluate the expression at every pixel every time something happened to require the applet to refresh. The reason this works is that when the user enters a new expression, we set the *img* variable to *null*.

Next we run through every pixel in our applet, calling `mapToVirtual()`

, which sets the instance variables *x* and *y* to the appropriate values to be returned to the *Expression*, since most of the time the pixel index won't correspond to the coordinate we want it to. We then evaluate the expression and find the minimum and maximum values.

Once we have done this, we create an array of integers to hold our pixel color information, and reiterate through the pixels, this time setting them to colors. We have also scaled them to values between 0 and 1 because that is what the function `Color.getHSBColor()`

needs. Once we have filled the pixel array, we create a *MemoryImageSource* with it, and draw the image. The instance variable *img* is now non-null, so if the applet needs to refresh, it won't have to go through all that calculation again.

Now we just need the function `mapToVirtual()`

:

`/* * Map a pixel coordinate to a virtual coordinate. */ public void mapToVirtual( int x, int y ){ this.x = ( (right-left)/getSize().width )*x + left; this.y = ( (bottom-top)/getSize().height )*y + top; }`

This function simply maps pixels linearly from their actual coordinates to assumed coordinates, according to the *right, left, top, bottom* variables declared at the beginning of the class. It sets the instance variables *x, y* to the virtual coordinates, as required for the `variable()`

function.

You can now compile *ExpressionApplet.java* and include it in an HTML page as I have done here. If you wish, you may add text fields to set the virtual boundaries, so that you can move around and zoom in and out, instead of being always confined to one view, as here.

Here is the finished file Expression.java.

Here is the finished file Variable.java.

Here is the finished file ExpressionApplet.java.