Initial Commit

This commit is contained in:
2018-10-15 12:47:14 -06:00
commit 0c531ffff9
55 changed files with 7285 additions and 0 deletions
+271
View File
@@ -0,0 +1,271 @@
/* basic application to be extended
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
public class Basic extends JFrame implements Runnable, KeyListener,
MouseListener,
MouseMotionListener,
WindowListener
{
protected static int FPS = 50; // desired frames per second
private int stepNumber;
// part of the basic framework
private Thread theThread; //to control the animation
private boolean waiting;
protected int pixelWidth, pixelHeight; // dimensions of window in pixels
private int ulcX, ulcY; // location of upper left corner of window on screen
private Color backgroundColor; // background color of entire window
private double mouseX, mouseY; // maintain correct mouse location
private int whichCamera; // maintain which camera's pixel grid region mouse is in
private Graphics dbg;
private Image dbImage = null;
protected ArrayList<Camera> cameras;
public Basic( String title, int ulx, int uly, int pw, int ph )
{
super( title ); // call JFrame
ulcX = ulx; ulcY = uly;
pixelWidth = pw; pixelHeight = ph;
setBounds(ulcX, ulcY, pixelWidth, pixelHeight );
setResizable( false );
addKeyListener(this);
// setFocusable(true);
// requestFocus();
addMouseListener(this);
addMouseMotionListener(this);
addWindowListener(this);
cameras = new ArrayList<Camera>();
stepNumber = 0;
// force mouse to be in center of window at start
mouseX = pixelWidth/2;
mouseY = pixelHeight/2;
}
public void start()
{
setVisible(true);
// physically draw the mouse cursor where we want it
try{
Robot rob = new Robot();
rob.mouseMove( ulcX+pixelWidth/2, ulcY+pixelHeight/2 );
}catch(Exception e){}
if (theThread == null)
theThread = new Thread(this);
theThread.start();
}
public void run()
{
while (true)
{
stepNumber++;
long startTime = System.nanoTime();
render();
paintScreen();
long stopTime = System.nanoTime();
double elapsed = (stopTime-startTime)/1000000.0; // milliseconds
int waitTime = 1000/FPS - (int) Math.round( elapsed );
if( waitTime < 1 )
waitTime = 1;
try {
Thread.sleep(waitTime);
}
catch (InterruptedException ie)
{System.err.println("OOPS");}
}
}
private void render()
{
if( dbImage == null )
{// create the buffer
dbImage = createImage( pixelWidth, pixelHeight );
if( dbImage == null )
{
System.out.println("dbImage is null???");
return;
}
else
{// dbg is created, tell Camera
dbg = dbImage.getGraphics();
Camera.setGraphicsContext( dbg );
}
}
// clear the background of entire window
dbg.setColor( backgroundColor );
dbg.fillRect(0,0,pixelWidth,pixelHeight);
// give app a chance to update its instance variables
// and then draw stuff to dbg
step();
}
private void paintScreen()
{
Graphics gr;
try{
gr = this.getGraphics();
if( gr != null && dbImage != null )
gr.drawImage(dbImage,0,0,null);
Toolkit.getDefaultToolkit().sync(); // maybe not needed?
gr.dispose();
}
catch(Exception e)
{
System.out.println("graphics context error" + e );
System.exit(1);
}
}
// override this method with code to display stuff
// and update app instance variables
public void step()
{
System.out.println("Step number: " + getStepNumber() );
}
public int getStepNumber()
{
return stepNumber;
}
// implement KeyListener:
// ******************************************************************
public void keyPressed(KeyEvent e){}
public void keyReleased(KeyEvent e){}
public void keyTyped(KeyEvent e){}
// implement MouseListener:
// ******************************************************************
public void mouseClicked(MouseEvent e)
{
updateMouse(e);
}
public void mouseEntered(MouseEvent e)
{
updateMouse(e);
}
public void mouseExited(MouseEvent e)
{
updateMouse(e);
}
public void mousePressed(MouseEvent e)
{
updateMouse(e);
}
public void mouseReleased(MouseEvent e)
{
updateMouse(e);
}
// implement MouseMotionListener:
// ******************************************************************
public void mouseDragged(MouseEvent e)
{
updateMouse(e);
}
public void mouseMoved(MouseEvent e)
{
updateMouse(e);
}
private void updateMouse( MouseEvent e )
{
int ix = e.getX(), iy = e.getY();
// determine which camera this mouse event hits
// and compute mouseX, mouseY in that camera's graph paper coords
whichCamera = -1;
Camera ac=null, temp;
for( int k=0; k<cameras.size(); k++ )
{
temp = cameras.get(k);
if( temp.hits(ix,iy) )
{
ac = temp;
whichCamera = k;
}
}
if( whichCamera == -1 )
{
mouseX=0; mouseY=0;
whichCamera = -1;
}
else
{// mouse event happened in an active camera, update coords for that cam
mouseX = ac.invMapX( ix );
mouseY = ac.invMapY( iy );
}
}
// -----------------------------------------------------------------
// These can be called, but don't override
protected double getMouseX()
{
return mouseX;
}
protected double getMouseY()
{
return mouseY;
}
protected int getMouseCamera()
{
return whichCamera;
}
// set background color of entire window
protected void setBackgroundColor( Color color )
{
backgroundColor = color;
}
// implement WindowListener:
// ******************************************************************^M
public void windowActivated(WindowEvent e){}
public void windowClosed(WindowEvent e){}
public void windowClosing(WindowEvent e)
{
System.exit(0);
} // end of windowClosing()
public void windowDeactivated(WindowEvent e){}
public void windowDeiconified(WindowEvent e){}
public void windowIconified(WindowEvent e){}
public void windowOpened(WindowEvent e){}
}
+330
View File
@@ -0,0 +1,330 @@
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
public class Camera
{
// whenever graphics context is changed by Basic, all
// cameras get shared access to that context
// *******************************************************************
private static Graphics gc; // the graphics context
public static void setGraphicsContext( Graphics g )
{
gc = g;
}
// instance variables
// *******************************************************************
private Color backgroundColor;
private int px, py, pw, ph; // the pixel grid rectangle where draw
private double left, right, bottom, top; // the visible rectangle in the
// virtual graph paper
private Font currentFont; // the current font
private int currentFontHeight; // height of a typical char in current font
// methods for creating and changing camera properties
// *******************************************************************
// construct a camera with both rectangles (pixelgrid and graph paper)
// specified, and background color
// Note: the top coordinate of the visible region is computed so that
// the visible region has the same aspect ratio as the pixel
// grid region (can change if desired by using setRegion)
public Camera( int vx, int vy, int vw, int vh,
double l, double r, double b,
Color bc )
{
px=vx; py=vy; pw=vw; ph=vh;
left=l; right=r; bottom=b; top=bottom + ph*(right-left)/pw;
backgroundColor=bc;
}
// construct a camera with both rectangles specified, and back color
// Note: this constructor lets you select coordinates each way,
// dangerous to draw geometrical entities
public Camera( int vx, int vy, int vw, int vh,
double l, double r, double b, double t,
Color bc )
{
px=vx; py=vy; pw=vw; ph=vh;
left=l; right=r; bottom=b; top=t;
backgroundColor=bc;
}
// set the background color
// (might want to change it after camera is first built)
public void setBackgroundColor( Color color )
{
backgroundColor = color;
}
// move the graph paper viewing rectangle
public void setRegion( double l, double r, double b, double t )
{
left=l; right=r; bottom=b; top=t;
}
// shift the graph paper rectangle by given fractions in x and y
public void shiftRegion( double fx, double fy )
{
double dx = fx*(right-left);
double dy = fy*(top-bottom);
left += dx; right += dx;
bottom += dy; top += dy;
}
// scale the graph paper rectangle by given fractions in x and y,
// keeping the center fixed
public void scaleRegion( double sx, double sy )
{
double cx = (left+right)/2, cy = (bottom+top)/2;
double dx = sx*(right-left);
double dy = sy*(top-bottom);
left = cx - dx/2; right = cx + dx/2;
bottom = cy - dy/2; top = cy + dy/2;
}
public double getRegionLeft()
{
return left;
}
public double getRegionBottom()
{
return bottom;
}
public double getRegionWidth()
{
return right-left;
}
public double getRegionHeight()
{
return top-bottom;
}
// methods for drawing things used by application
// *******************************************************************
// prepare pixel grid for this camera to draw in its region
public void activate()
{
// set up clipping so no drawing can occur outside this camera's
// pixel grid region
gc.setClip(null);
gc.clipRect( px, py, pw, ph );
// clear the background of entire window
gc.setColor( backgroundColor );
gc.fillRect( px, py, pw, ph );
}
// set the drawing color
public void setColor( Color color )
{
gc.setColor( color );
}
// draw a rectangle---just the border---with lower left corner (x,y),
// width w, height h, in graph paper coords
public void drawRect( double x, double y, double w, double h )
{
rect( false, x, y, w, h );
}
// draw a filled rectangle with lower left corner (x,y),
// width w, height h, in graph paper coords
public void fillRect( double x, double y, double w, double h )
{
rect( true, x, y, w, h );
}
public void drawCircle( double x, double y, double r )
{
circle( false, x, y, r );
}
public void fillCircle( double x, double y, double r )
{
circle( true, x, y, r );
}
public void drawTri( double x1, double y1,
double x2, double y2,
double x3, double y3 )
{
tri( false, x1, y1, x2, y2, x3, y3 );
}
public void fillTri( double x1, double y1,
double x2, double y2,
double x3, double y3 )
{
tri( true, x1, y1, x2, y2, x3, y3 );
}
public void drawLine( double x1, double y1,
double x2, double y2 )
{
gc.drawLine( mapX(x1), mapY(y1), mapX(x2), mapY(y2) );
}
public void drawText( String text, double x, double y )
{
gc.drawString( text, mapX(x), mapY(y) );
}
public void setFont( Font f )
{
currentFont = f;
Rectangle r = figureBounds( "e", currentFont );
currentFontHeight = r.height;
gc.setFont( f );
}
// compute the width of the text in the current font
// in the visible region
public double getWidth( String text )
{
FontMetrics fm = gc.getFontMetrics();
double w = invMapX( fm.stringWidth( text ) );
return w;
}
// compute the height of the current font
// in the visible region
public double getHeight()
{
FontMetrics fm = gc.getFontMetrics();
double h = invMapY( fm.getHeight() );
return h;
}
// draw the text centered about (x,y)
// using height of typical char (as in setFont) for vertical centering
public void drawCenteredText( String text, double x, double y )
{
FontMetrics fm = gc.getFontMetrics();
int w = fm.stringWidth( text );
gc.drawString( text, mapX(x)-w/2, mapY(y) + currentFontHeight/2 );
}
// figure bounds of the given string
private Rectangle figureBounds( String s, Font font )
{
Graphics2D g2 = (Graphics2D) gc;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setFont( font );
FontRenderContext frc = g2.getFontRenderContext();
GlyphVector gv = g2.getFont().createGlyphVector(frc, s);
return gv.getPixelBounds(null, 0, 0);
}
// draw the text horizontally centered about x,
// with baseline at y
public void drawHorizCenteredText( String text, double x, double y )
{
FontMetrics fm = gc.getFontMetrics();
int w = fm.stringWidth( text );
gc.drawString( text, mapX(x)-w/2, mapY(y) );
}
// draw the text vertically centered about y,
// with left edge at x
public void drawVertCenteredText( String text, double x, double y )
{
gc.drawString( text, mapX(x), mapY(y) + currentFontHeight/2 );
}
// use these carefully!
// -----------------------------------------------------------------
public int mapX( double x )
{
return px + nicefy( ((x-left)/(right-left))*pw );
}
public int mapY( double y )
{
return py + ph - nicefy( ((y-bottom)/(top-bottom))*ph );
}
// does the mouse location in pixel grid (ix,iy) hit this
// camera's pixel grid region
public boolean hits( int ix, int iy )
{
boolean result = px<=ix && ix<=px+pw && py<=iy && iy<=py+ph;
return result;
}
public double invMapX( int ix )
{
return left + (right-left)*(ix-px)/pw;
}
public double invMapY( int iy )
{
return bottom + (top-bottom)*(ph-(iy-py))/ph;
}
// -----------------------------------------------------------------
// methods used internally
private int nicefy( double a )
{
return (int) Math.round(a);
}
// draw or fill a rectangle
private void rect( boolean fill, double x, double y, double w, double h )
{
int x1, x2, y1, y2;
x1 = mapX(x); x2 = mapX(x+w);
y1 = mapY(y); y2 = mapY(y+h);
if( fill )
gc.fillRect( x1, y2, x2-x1, y1-y2 );
else
gc.drawRect( x1, y2, x2-x1, y1-y2 );
}
private void circle( boolean fill, double x, double y, double r )
{
int x1=mapX(x-r), y1=mapY(y+r), x2=mapX(x+r);
if( fill )
gc.fillOval( x1, y1, x2-x1, x2-x1 );
else
gc.drawOval( x1, y1, x2-x1, x2-x1 );
}
private void tri( boolean fill, double x1, double y1,
double x2, double y2,
double x3, double y3 )
{
int[] x = new int[3]; x[0]=mapX(x1); x[1]=mapX(x2); x[2]=mapX(x3);
int[] y = new int[3]; y[0]=mapY(y1); y[1]=mapY(y2); y[2]=mapY(y3);
if( fill )
gc.fillPolygon( x, y, 3 );
else
gc.drawPolygon( x, y, 3 );
}
}
+25
View File
@@ -0,0 +1,25 @@
import java.util.Scanner;
public class Corgi {
public static void main(String[] args) {
System.out.print("Enter name of Corgi program file: ");
Scanner keys = new Scanner( System.in );
String name = keys.nextLine();
Lexer lex = new Lexer( name );
Parser parser = new Parser( lex );
// start with <statements>
Node root = parser.parseProgram();
// display parse tree for debugging/testing:
TreeViewer viewer = new TreeViewer("Parse Tree", 0, 0, 800, 500, root );
// execute the parse tree
// root.execute();
}// main
}
+275
View File
@@ -0,0 +1,275 @@
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Scanner;
import java.util.Stack;
public class Lexer {
public static String margin = "";
// holds any number of tokens that have been put back
private Stack<Token> stack;
// the source of physical symbols
// (use BufferedReader instead of Scanner because it can
// read a single physical symbol)
private BufferedReader input;
// one lookahead physical symbol
private int lookahead;
// construct a Lexer ready to produce tokens from a file
public Lexer( String fileName ) {
try {
input = new BufferedReader( new FileReader( fileName ) );
}
catch(Exception e) {
error("Problem opening file named [" + fileName + "]" );
}
stack = new Stack<Token>();
lookahead = 0; // indicates no lookahead symbol present
}// constructor
// produce the next token
private Token getNext() {
if( ! stack.empty() ) {
// produce the most recently putback token
Token token = stack.pop();
return token;
}
else {
// produce a token from the input source
int state = 1; // state of FA
String data = ""; // specific info for the token
boolean done = false;
int sym; // holds current symbol
do {
sym = getNextSymbol();
// System.out.println("current symbol: " + sym + " state = " + state );
if ( state == 1 ) {
if ( sym == 9 || sym == 10 || sym == 13 ||
sym == 32 ) {// whitespace
state = 1;
}
else if ( 'a'<=sym && sym<='z' ) {// lowercase
data += (char) sym;
state = 2;
}
else if ( digit( sym ) ) {
data += (char) sym;
state = 3;
}
else if ( sym == '.' ) {
data += (char) sym;
state = 5;
}
else if ( sym == '\"' ) {
state = 6;
}
else if ( sym == '+' || sym == '-' || sym == '*' ||
sym == '/' || sym == '(' || sym == ')' ||
sym == ',' || sym == '='
) {
data += (char) sym;
state = 8;
done = true;
}
else if ( sym == -1 ) {// end of file
state = 9;
done = true;
}
else {
error("Error in lexical analysis phase with symbol "
+ sym + " in state " + state );
}
}
else if ( state == 2 ) {
if ( letter(sym) || digit(sym) ) {
data += (char) sym;
state = 2;
}
else {// done with variable token
putBackSymbol( sym );
done = true;
}
}
else if ( state == 3 ) {
if ( digit(sym) ) {
data += (char) sym;
state = 3;
}
else if ( sym == '.' ) {
data += (char) sym;
state = 4;
}
else {// done with number token
putBackSymbol( sym );
done = true;
}
}
else if ( state == 4 ) {
if ( digit(sym) ) {
data += (char) sym;
state = 4;
}
else {// done with number token
putBackSymbol( sym );
done = true;
}
}
else if ( state == 5 ) {
if ( digit(sym) ) {
data += (char) sym;
state = 4;
}
else {
error("Error in lexical analysis phase with symbol "
+ sym + " in state " + state );
}
}
else if ( state == 6 ) {
if ( (' '<=sym && sym<='~') && sym != '\"' ) {
data += (char) sym;
state = 6;
}
else if ( sym == '\"' ) {
state = 7;
done = true;
}
}
// note: states 7, 8, and 9 are accepting states with
// no arcs out of them, so they are handled
// in the arc going into them
}while( !done );
// generate token depending on stopping state
Token token;
if ( state == 2 ) {
// see if data matches any special words
if ( data.equals("input") ) {
return new Token( "bif0", data );
}
else if ( data.equals("sqrt") || data.equals("cos") ||
data.equals("sin") || data.equals("atan")
) {
return new Token( "bif1", data );
}
else if ( data.equals("pow") ) {
return new Token( "bif2", data );
}
else if ( data.equals("print") ) {
return new Token( "print", "" );
}
else if ( data.equals("newline") ) {
return new Token( "newline", "" );
}
else {// is just a variable
return new Token( "var", data );
}
}
else if ( state == 3 || state == 4 ) {
return new Token( "num", data );
}
else if ( state == 7 ) {
return new Token( "string", data );
}
else if ( state == 8 ) {
return new Token( "single", data );
}
else if ( state == 9 ) {
return new Token( "eof", data );
}
else {// Lexer error
error("somehow Lexer FA halted in bad state " + state );
return null;
}
}// else generate token from input
}// getNext
public Token getNextToken() {
Token token = getNext();
System.out.println(" got token: " + token );
return token;
}
public void putBackToken( Token token )
{
System.out.println( margin + "put back token " + token.toString() );
stack.push( token );
}
// next physical symbol is the lookahead symbol if there is one,
// otherwise is next symbol from file
private int getNextSymbol() {
int result = -1;
if( lookahead == 0 ) {// is no lookahead, use input
try{ result = input.read(); }
catch(Exception e){}
}
else {// use the lookahead and consume it
result = lookahead;
lookahead = 0;
}
return result;
}
private void putBackSymbol( int sym ) {
if( lookahead == 0 ) {// sensible to put one back
lookahead = sym;
}
else {
System.out.println("Oops, already have a lookahead " + lookahead +
" when trying to put back symbol " + sym );
System.exit(1);
}
}// putBackSymbol
private boolean letter( int code ) {
return 'a'<=code && code<='z' ||
'A'<=code && code<='Z';
}
private boolean digit( int code ) {
return '0'<=code && code<='9';
}
private boolean printable( int code ) {
return ' '<=code && code<='~';
}
private static void error( String message ) {
System.out.println( message );
System.exit(1);
}
public static void main(String[] args) {
System.out.print("Enter file name: ");
Scanner keys = new Scanner( System.in );
String name = keys.nextLine();
Lexer lex = new Lexer( name );
Token token;
do{
token = lex.getNext();
System.out.println( token.toString() );
}while( ! token.getKind().equals( "eof" ) );
}
}
+75
View File
@@ -0,0 +1,75 @@
/*
store variable names with stored value
*/
import java.util.ArrayList;
public class MemTable {
private ArrayList<String> names;
private ArrayList<Double> values;
public MemTable() {
names = new ArrayList<String>();
values = new ArrayList<Double>();
}
public String toString() {
String s = "----\n";
for( int k=0; k<names.size(); k++ ) {
s += names.get(k) + " " + values.get(k) + "\n";
}
return s;
}
public int size() {
return names.size();
}
// store value for name, adding name if not already
// there
public void store( String name, double value ) {
int loc = findName( name );
if ( loc < 0 ) {// add new pair
names.add( name );
values.add( value );
}
else {// change value for existing pair
values.set( loc, value );
}
}// store
// retrieve value for given name
public double retrieve( String name ) {
int loc = findName( name );
if ( loc >= 0 ) {// add new pair
return values.get( loc );
}
else {
System.out.println("variable [" + name + "] not found");
System.exit(1);
return 0;
}
}// retrieve
// return index of name in names, or -1 if
// not found
private int findName( String name ) {
// locate name
int loc = -1;
for (int k=0; k<names.size() && loc<0; k++) {
if ( names.get(k).equals(name) ) {
loc = k;
}
}
return loc;
}// findName
}
+223
View File
@@ -0,0 +1,223 @@
/* a Node holds one node of a parse tree
with several pointers to children used
depending on the kind of node
*/
import java.awt.*;
import java.util.Scanner;
public class Node {
public static int count = 0; // maintain unique id for each node
private int id;
private String kind; // non-terminal or terminal category for the node
private String info; // extra information about the node such as
// the actual identifier for an I
// references to children in the parse tree
private Node first, second, third;
// memory table shared by all nodes
private static MemTable table = new MemTable();
private static Scanner keys = new Scanner( System.in );
// construct a common node with no info specified
public Node( String k, Node one, Node two, Node three ) {
kind = k; info = "";
first = one; second = two; third = three;
id = count;
count++;
System.out.println( this );
}
// construct a node with specified info
public Node( String k, String inf, Node one, Node two, Node three ) {
kind = k; info = inf;
first = one; second = two; third = three;
id = count;
count++;
System.out.println( this );
}
// construct a node that is essentially a token
public Node( Token token ) {
kind = token.getKind(); info = token.getDetails();
first = null; second = null; third = null;
id = count;
count++;
System.out.println( this );
}
public String toString() {
return "#" + id + "[" + kind + "," + info + "]<" + nice(first) +
" " + nice(second) + ">";
}
public String nice( Node node ) {
if ( node == null ) {
return "";
}
else {
return "" + node.id;
}
}
// produce array with the non-null children
// in order
private Node[] getChildren() {
int count = 0;
if( first != null ) count++;
if( second != null ) count++;
if( third != null ) count++;
Node[] children = new Node[count];
int k=0;
if( first != null ) { children[k] = first; k++; }
if( second != null ) { children[k] = second; k++; }
if( third != null ) { children[k] = third; k++; }
return children;
}
//******************************************************
// graphical display of this node and its subtree
// in given camera, with specified location (x,y) of this
// node, and specified distances horizontally and vertically
// to children
public void draw( Camera cam, double x, double y, double h, double v ) {
System.out.println("draw node " + id );
// set drawing color
cam.setColor( Color.black );
String text = kind;
if( ! info.equals("") ) text += "(" + info + ")";
cam.drawHorizCenteredText( text, x, y );
// positioning of children depends on how many
// in a nice, uniform manner
Node[] children = getChildren();
int number = children.length;
System.out.println("has " + number + " children");
double top = y - 0.75*v;
if( number == 0 ) {
return;
}
else if( number == 1 ) {
children[0].draw( cam, x, y-v, h/2, v ); cam.drawLine( x, y, x, top );
}
else if( number == 2 ) {
children[0].draw( cam, x-h/2, y-v, h/2, v ); cam.drawLine( x, y, x-h/2, top );
children[1].draw( cam, x+h/2, y-v, h/2, v ); cam.drawLine( x, y, x+h/2, top );
}
else if( number == 3 ) {
children[0].draw( cam, x-h, y-v, h/2, v ); cam.drawLine( x, y, x-h, top );
children[1].draw( cam, x, y-v, h/2, v ); cam.drawLine( x, y, x, top );
children[2].draw( cam, x+h, y-v, h/2, v ); cam.drawLine( x, y, x+h, top );
}
else {
System.out.println("no Node kind has more than 3 children???");
System.exit(1);
}
}// draw
public static void error( String message ) {
System.out.println( message );
System.exit(1);
}
// ask this node to execute itself
// (for nodes that don't return a value)
public void execute() {
if ( kind.equals("stmts") ) {
// insert code here for Exercise 15
}
else if ( kind.equals("prtstr") ) {
System.out.print( info );
}
else if ( kind.equals("prtexp") ) {
// insert code here for Exercise 15
}
else if ( kind.equals("nl") ) {
System.out.print( "\n" );
}
else if ( kind.equals("sto") ) {
// insert code here for Exercise 15
}
else {
error("Unknown kind of node [" + kind + "]");
}
}// execute
// compute and return value produced by this node
public double evaluate() {
if ( kind.equals("num") ) {
return Double.parseDouble( info );
}
else if ( kind.equals("var") ) {
// insert code here for Exercise 15
}
else if ( kind.equals("+") || kind.equals("-") ) {
// insert code here for Exercise 15
}
else if ( kind.equals("*") || kind.equals("/") ) {
// insert code here for Exercise 15
}
else if ( kind.equals("input") ) {
return keys.nextDouble();
}
else if ( kind.equals("sqrt") || kind.equals("cos") ||
kind.equals("sin") || kind.equals("atan")
) {
double value = first.evaluate();
if ( kind.equals("sqrt") )
return Math.sqrt(value);
else if ( kind.equals("cos") )
return Math.cos( Math.toRadians( value ) );
else if ( kind.equals("sin") )
return Math.sin( Math.toRadians( value ) );
else if ( kind.equals("atan") )
return Math.toDegrees( Math.atan( value ) );
else {
error("unknown function name [" + kind + "]");
return 0;
}
}
else if ( kind.equals("pow") ) {
// insert code here for Exercise 15
}
else if ( kind.equals("opp") ) {
// insert code here for Exercise 15
}
else {
error("Unknown node kind [" + kind + "]");
return 0;
}
}// evaluate
}// Node
+202
View File
@@ -0,0 +1,202 @@
/*
This class provides a recursive descent parser
for Corgi (a simple calculator language),
creating a parse tree which can be interpreted
to simulate execution of a Corgi program
*/
public class Parser {
private Lexer lex;
public Parser( Lexer lexer ) {
lex = lexer;
}
public Node parseProgram() {
return parseStatements();
}
private Node parseStatements() {
System.out.println("-----> parsing <statements>:");
Node first = parseStatement();
// look ahead to see if there are more statement's
Token token = lex.getNextToken();
if ( token.isKind("eof") ) {
return new Node( "stmts", first, null, null );
}
else {
lex.putBackToken( token );
Node second = parseStatements();
return new Node( "stmts", first, second, null );
}
}// <statements>
private Node parseStatement() {
System.out.println("-----> parsing <statement>:");
Token token = lex.getNextToken();
// ---------------->>> print <string> or print <expr>
if ( token.isKind("print") ) {
token = lex.getNextToken();
if ( token.isKind("string") ) {// print <string>
return new Node( "prtstr", token.getDetails(),
null, null, null );
}
else {// must be first token in <expr>
// put back the token we looked ahead at
lex.putBackToken( token );
Node first = parseExpr();
return new Node( "prtexp", first, null, null );
}
// ---------------->>> newline
}
else if ( token.isKind("newline") ) {
return new Node( "nl", null, null, null );
}
// --------------->>> <var> = <expr>
else if ( token.isKind("var") ) {
String varName = token.getDetails();
token = lex.getNextToken();
errorCheck( token, "single", "=" );
Node first = parseExpr();
return new Node( "sto", varName, first, null, null );
}
else {
System.out.println("Token " + token +
" can't begin a statement");
System.exit(1);
return null;
}
}// <statement>
private Node parseExpr() {
System.out.println("-----> parsing <expr>");
Node first = parseTerm();
// look ahead to see if there's an addop
Token token = lex.getNextToken();
if ( token.matches("single", "+") ||
token.matches("single", "-")
) {
Node second = parseExpr();
return new Node( token.getDetails(), first, second, null );
}
else {// is just one term
lex.putBackToken( token );
return first;
}
}// <expr>
private Node parseTerm() {
System.out.println("-----> parsing <term>");
Node first = parseFactor();
// look ahead to see if there's a multop
Token token = lex.getNextToken();
if ( token.matches("single", "*") ||
token.matches("single", "/")
) {
Node second = parseTerm();
return new Node( token.getDetails(), first, second, null );
}
else {// is just one factor
lex.putBackToken( token );
return first;
}
}// <term>
private Node parseFactor() {
System.out.println("-----> parsing <factor>");
Token token = lex.getNextToken();
if ( token.isKind("num") ) {
return new Node("num", token.getDetails(), null, null, null );
}
else if ( token.isKind("var") ) {
return new Node("var", token.getDetails(), null, null, null );
}
else if ( token.matches("single","(") ) {
Node first = parseExpr();
token = lex.getNextToken();
errorCheck( token, "single", ")" );
return first;
}
else if ( token.isKind("bif0") ) {
String bifName = token.getDetails();
token = lex.getNextToken();
errorCheck( token, "single", "(" );
token = lex.getNextToken();
errorCheck( token, "single", ")" );
return new Node( bifName, null, null, null );
}
else if ( token.isKind("bif1") ) {
String bifName = token.getDetails();
token = lex.getNextToken();
errorCheck( token, "single", "(" );
Node first = parseExpr();
token = lex.getNextToken();
errorCheck( token, "single", ")" );
return new Node( bifName, first, null, null );
}
else if ( token.isKind("bif2") ) {
String bifName = token.getDetails();
token = lex.getNextToken();
errorCheck( token, "single", "(" );
Node first = parseExpr();
token = lex.getNextToken();
errorCheck( token, "single", "," );
Node second = parseExpr();
token = lex.getNextToken();
errorCheck( token, "single", ")" );
return new Node( bifName, first, second, null );
}
else if ( token.matches("single","-") ) {
Node first = parseFactor();
return new Node("opp", first, null, null );
}
else {
System.out.println("Can't have factor starting with " + token );
System.exit(1);
return null;
}
}// <factor>
// check whether token is correct kind
private void errorCheck( Token token, String kind ) {
if( ! token.isKind( kind ) ) {
System.out.println("Error: expected " + token +
" to be of kind " + kind );
System.exit(1);
}
}
// check whether token is correct kind and details
private void errorCheck( Token token, String kind, String details ) {
if( ! token.isKind( kind ) ||
! token.getDetails().equals( details ) ) {
System.out.println("Error: expected " + token +
" to be kind=" + kind +
" and details=" + details );
System.exit(1);
}
}
}
+20
View File
@@ -0,0 +1,20 @@
main()
def fact( n )
if lt(n 1)
return 1
else
temp = fact( n-1 )
return n * temp
end
end
def main()
"enter n: "
n = input()
print( fact(n) )
end
+23
View File
@@ -0,0 +1,23 @@
main()
def main()
"enter a:"
a = input()
"enter b:"
b = input()
"enter c:"
c = input()
disc = pow(b,2) - 4*a*c
x1 = (-b - sqrt(disc) ) / (2*a)
x2 = (-b + sqrt(disc) ) / (2*a)
"x1: " print(x1) "\n"
"x2: " print(x2 ) "\n"
end
+31
View File
@@ -0,0 +1,31 @@
public class Token
{
private String kind;
private String details;
public Token( String k, String d )
{
kind = k; details = d;
}
public boolean isKind( String s )
{
return kind.equals( s );
}
public String getKind()
{ return kind; }
public String getDetails()
{ return details; }
public boolean matches( String k, String d ) {
return kind.equals(k) && details.equals(d);
}
public String toString()
{
return "[" + kind + "," + details + "]";
}
}
+78
View File
@@ -0,0 +1,78 @@
/* this class allows interactive
viewing of a tree built from
Node instances
*/
import java.awt.*;
import java.awt.event.KeyEvent;
public class TreeViewer extends Basic
{
// instance variables for the application:
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
private Node root; // root of tree to be viewed
private String keyInput;
private double horizGap = 2, vertGap = .5;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
public TreeViewer( String title, int ulx, int uly, int pw, int ph,
Node tree )
{
super(title,ulx,uly,pw,ph);
setBackgroundColor( new Color( 128, 128, 200 ) );
// tree display
cameras.add( new Camera( 25, 45, pw-55, ph-75,
0, 10, 0, 5,
new Color( 200, 200, 200 ) ) );
root = tree;
super.start();
}
public void step()
{
// tree display
Camera cam = cameras.get(0);
cam.activate();
cam.setColor( Color.black );
root.draw( cam, 5.0, 4.0, horizGap, vertGap );
}// step
public void keyTyped( KeyEvent e ) {
char key = e.getKeyChar();
if( key == 'w' ){
horizGap *= 1.2;
}
else if( key == 'n' ){
horizGap /= 1.2;
}
}// keyTyped
public void keyPressed( KeyEvent e ) {
int code = e.getKeyCode();
if( code == KeyEvent.VK_LEFT ){
cameras.get(0).shiftRegion( -0.25, 0 );
}
else if( code == KeyEvent.VK_RIGHT ){
cameras.get(0).shiftRegion( 0.25, 0 );
}
else if( code == KeyEvent.VK_UP ){
cameras.get(0).shiftRegion( 0, 0.25 );
}
else if( code == KeyEvent.VK_DOWN ){
cameras.get(0).shiftRegion( 0, -0.25 );
}
}// keyPressed
}// TreeViewer
+66
View File
@@ -0,0 +1,66 @@
Note: this is the draft grammar, with notes and some thoughts,
for the Project 2 version of Corgi
------------------
<program> -> <funcCall> <funcDefs>
<funcDefs> -> <funcDef> | <funcDef> <funcDefs>
<funcDef> -> def <funcName> ( ) end |
def <funcName> ( <params> ) end |
def <funcName> ( ) <statements> end
def <funcName> ( <params> ) <statements> end
<funcName> -> <var>
<params> -> <var> | <var> <params>
<statements> -> <statement> |
<statement> <statements>
<funcCall> -> <var> ( ) |
<var> ( <args> )
<args> -> <expr> | <expr> <args>
<statement> -> <string> |
<var> = <expr> |
<funcCall> |
if <expr> else end |
if <expr> else <statements> end |
if <expr> <statements> else end |
if <expr> <statements> else <statements> end |
return <expr>
<expr> -> <term> | <term> + <expr> | <term> - <expr>
<term> -> <factor> | <factor> * <term> | <factor> / <term>
<factor> -> <number> | <var> |
( <expr> ) |
- <factor> |
<funcCall>
Notes:
slightly bizarre but cool: in Corgi you can just type a string anywhere
as a statement and it gets sent to the console (still have to use
print( <expr> ) to send a number)
no boolean type---use "non-zero is true, 0 is false"
there's only the if-else---always have to use it
no loop statements---use recursion!
the built-in functions fit the grammar just like user-defined functions---
will execute differently
change the Lexer to remove /* ..... */ type of comments---no tokens
produced
change Lexer to allow \n inside a string---put \\ in the Java string
Need to agree on names for all the many BIF's---see upcoming document
+19
View File
@@ -0,0 +1,19 @@
<program> -> <statements>
<statements> -> <statement> |
<statement> <statements>
<statement> -> print <string> |
print <expr> |
newline |
<var> = <expr>
<expr> -> <term> | <term> <addop> <expr>
<term> -> <factor> | <factor> <multop> <term>
<factor> -> <number> | <var> |
( <expr> ) |
<bif0> () |
<bif1> ( <expr> ) |
<bif2> ( <expr>, <expr> ) |
- <factor>
+87
View File
@@ -0,0 +1,87 @@
// ask this node to execute itself
// (for nodes that don't return a value)
public void execute() {
if ( kind.equals("stmts") ) {
// insert code here for Exercise 15
}
else if ( kind.equals("prtstr") ) {
System.out.print( info );
}
else if ( kind.equals("prtexp") ) {
// insert code here for Exercise 15
}
else if ( kind.equals("nl") ) {
System.out.print( "\n" );
}
else if ( kind.equals("sto") ) {
// insert code here for Exercise 15
}
else {
error("Unknown kind of node [" + kind + "]");
}
}// execute
// compute and return value produced by this node
public double evaluate() {
if ( kind.equals("num") ) {
return Double.parseDouble( info );
}
else if ( kind.equals("var") ) {
// insert code here for Exercise 15
}
else if ( kind.equals("+") || kind.equals("-") ) {
// insert code here for Exercise 15
}
else if ( kind.equals("*") || kind.equals("/") ) {
// insert code here for Exercise 15
}
else if ( kind.equals("input") ) {
return keys.nextDouble();
}
else if ( kind.equals("sqrt") || kind.equals("cos") ||
kind.equals("sin") || kind.equals("atan")
) {
double value = first.evaluate();
if ( kind.equals("sqrt") )
return Math.sqrt(value);
else if ( kind.equals("cos") )
return Math.cos( Math.toRadians( value ) );
else if ( kind.equals("sin") )
return Math.sin( Math.toRadians( value ) );
else if ( kind.equals("atan") )
return Math.toDegrees( Math.atan( value ) );
else {
error("unknown function name [" + kind + "]");
return 0;
}
}
else if ( kind.equals("pow") ) {
// insert code here for Exercise 15
}
else if ( kind.equals("opp") ) {
// insert code here for Exercise 15
}
else {
error("Unknown node kind [" + kind + "]");
return 0;
}
}// evaluate
+16
View File
@@ -0,0 +1,16 @@
print "enter a:"
a = input()
print "enter b:"
b = input()
print "enter c:"
c = input()
disc = pow(b,2) - 4*a*c
x1 = (-b - sqrt(disc) ) / (2*a)
x2 = (-b + sqrt(disc) ) / (2*a)
print "x1: " print x1 newline
print "x2: " print x2 newline