Initial Commit
This commit is contained in:
Executable
+271
@@ -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){}
|
||||
|
||||
}
|
||||
Executable
+330
@@ -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 );
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+25
@@ -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
|
||||
|
||||
}
|
||||
Executable
+275
@@ -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" ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+75
@@ -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
|
||||
|
||||
}
|
||||
Executable
+223
@@ -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
|
||||
Executable
+202
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+20
@@ -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
|
||||
Executable
+23
@@ -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
|
||||
Executable
+31
@@ -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 + "]";
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+78
@@ -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
|
||||
Executable
+66
@@ -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
|
||||
|
||||
Executable
+19
@@ -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>
|
||||
Executable
+87
@@ -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
|
||||
Executable
+16
@@ -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
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
Announcements
|
||||
(I'll try to keep this file current with any due dates, corrections to
|
||||
the course notes, corrections to
|
||||
Exercises and Projects, and so on)
|
||||
=======================================
|
||||
|
||||
Exercise 2:
|
||||
|
||||
The command (occurring two places):
|
||||
|
||||
2 1001 1
|
||||
|
||||
is misleading, because the "1" is a conceptual error
|
||||
(in an earlier version of VPL, I though the call had
|
||||
to speciy how many arguments had been passed, but now
|
||||
we just say that the command 3's have to immediately
|
||||
precede the command 2)
|
||||
but I didn't notice this issue because the loader
|
||||
sees opcode 2, reads one further argument (1001), and
|
||||
tosses the rest of the line---it's just as if the "1"
|
||||
is a comment.
|
||||
---------------------------------------
|
||||
|
||||
Project 1 is due September 10 (target)
|
||||
|
||||
Executable
BIN
Binary file not shown.
Executable
+757
@@ -0,0 +1,757 @@
|
||||
\input pictex
|
||||
\input /Users/Shared/TeX/defs
|
||||
|
||||
\advance \hoffset 0.25 true in
|
||||
|
||||
\def\inclassexercise{\item{$\Rightarrow$\quad\quad} {\bf In-Class Exercise:}\quad}
|
||||
\def\borderline{\medskip\hrule\bigskip}
|
||||
|
||||
\startDoc{CS 3210 Fall 2018}{25}{Implementing a Programming Language}
|
||||
|
||||
{\bigboldfont A Brief Look at More Serious Language Implementation}
|
||||
\bigskip
|
||||
|
||||
We have already played some with language design and implementation---you were asked in Project 1
|
||||
to implement VPL, and I suffered greatly implementing Jive. But, those languages have relatively simple
|
||||
structure and can be described just
|
||||
using finite automata. Now we want to learn a little about implementing a language that is described using
|
||||
a {\it context free grammar}. It turns out that if a language is described using a finite automaton to describe
|
||||
its meaningful chunks, and a context free grammar of the right form to describe its main structure,
|
||||
then we can implement the language using {\it recursive descent parsing}.
|
||||
\bigskip
|
||||
|
||||
\Indent{.5}
|
||||
Not that long ago,
|
||||
probably every computer science program had a rather nasty required course known as
|
||||
``the compiler course.'' As this technology became more well-known and accepted, this
|
||||
course gradually disappeared from the curriculum, but scraps of it remain in this course.
|
||||
\medskip
|
||||
|
||||
We will make our work much easier by mostly
|
||||
ignoring issues of {\it efficiency}, both in space and time.
|
||||
For example, a real compiler tries to recover from errors and go on to report other errors, but
|
||||
we will be happy to detect one error and stop. And, a real compiler tries to generate code that
|
||||
uses as little memory as is reasonable, and runs as quickly as is reasonable.
|
||||
We won't be crazy about it in our upcoming work, but we will compromise efficiency whenever it saves us
|
||||
work.
|
||||
\medskip
|
||||
\Outdent
|
||||
|
||||
{\bigboldfont Language Specification}
|
||||
\bigskip
|
||||
|
||||
To specify a programming language, we have to specify its {\it grammar}---what sequences of symbols
|
||||
(or diagrammatic elements, if it's a non-textual language) form a syntactically legal program, and its
|
||||
{\it semantics}---the meaning of those sequences of symbols.
|
||||
\medskip
|
||||
|
||||
To precisely specify the grammar of our language, we need to do some fairly abstract work (all of which overlaps the
|
||||
CS 3240 course, but with a more practical focus).
|
||||
\medskip
|
||||
|
||||
We have already seen a little of both finite automata and context free grammars, but the following will be
|
||||
more detailed and organized.
|
||||
\medskip
|
||||
|
||||
As we do the abstract stuff, we will have in mind two languages. The first will be a
|
||||
simple calculator language. The second will be the language that you will be asked to
|
||||
implement in Project 2. Both of these languages will be designed and specified in the
|
||||
upcoming work. The implementation of the simple calculator language through
|
||||
a lexical phase and
|
||||
recursive descent parsing will be worked out fully as an example, leaving you to do
|
||||
the same things on Project 2.
|
||||
\border
|
||||
|
||||
{\bf Definition of a Language}
|
||||
\medskip
|
||||
|
||||
Given a finite set, which is known as an {\it alphabet} (and can be thought of as some set
|
||||
of ordinary symbols), we define a {\it string\/}
|
||||
to be any finite sequence of members of the alphabet, and we define a {\it language\/} to
|
||||
be any set of strings over the alphabet.
|
||||
\medskip
|
||||
|
||||
\In
|
||||
For this course, we are interested in situations where a single string is a program in some
|
||||
programming language, and the language is the set of all syntactically legal programs.
|
||||
\medskip
|
||||
\Out
|
||||
\border
|
||||
|
||||
{\bf Finite Automata}
|
||||
\medskip
|
||||
|
||||
We already introduced finite automata, so let's do some examples that will
|
||||
be used in the simple calculator language.
|
||||
\border
|
||||
|
||||
{\bf Exercise 9}
|
||||
\medskip
|
||||
|
||||
Working in your small group, draw a finite automaton for each of the following languages:
|
||||
\medskip
|
||||
|
||||
\Indent{1}
|
||||
\item{a.} all strings that start with a lowercase letter, followed by zero or more letters or digits
|
||||
\medskip
|
||||
|
||||
\item{b.} all strings that represent a real number in the way usually
|
||||
used by humans (no scientific notation allowed), say in a math class.
|
||||
|
||||
\border
|
||||
\Outdent
|
||||
|
||||
{\bf The Concept of Lexical Analysis as Just a First Step in Parsing}
|
||||
\medskip
|
||||
|
||||
It turns out that the FA technique is not expressive enough to describe the syntax we want
|
||||
to have for a typical programming language.
|
||||
\medskip
|
||||
|
||||
\In
|
||||
Here's a proof of this fact: we clearly want to have, in a typical
|
||||
imperative language, the ability to write expressions
|
||||
such as $((((((a))))))$, where the number of extra parentheses is unlimited. Our parser needs
|
||||
to be able to check whether there are as many left parentheses as right. But, the FA technique
|
||||
can't say this. Suppose to the contrary that we have an FA that accepts all strings that
|
||||
have $n$ left parentheses followed by {\tt a} followed by $n$ right parentheses. Imagine that
|
||||
you are looking at this wonderful diagram. Since it is a {\it finite\/} state automaton, it has a
|
||||
finite number of states, say $M$. Now, feed this machine a string that has more than $M$
|
||||
left parentheses, followed by an {\tt a}, followed by the same number of right parentheses.
|
||||
Since there are only $M$ states, in processing the left parentheses, we will visit some state
|
||||
twice, and there will be a loop in the machine that processes just one or more left parentheses.
|
||||
Clearly this loop means that the machine will accept strings that it shouldn't accept.
|
||||
\medskip
|
||||
\Out
|
||||
|
||||
Since the FA technique can't describe all the syntactic features we want in a programming
|
||||
language, we will be forced to develop a more powerful approach. But, the FA technique
|
||||
is still useful, because we will use it for the first phase of parsing, known as {\it lexical analysis}.
|
||||
This is a very simple idea: we take the stream of physical symbols and use an FA to
|
||||
process them, producing either an error message or a stream of {\it tokens}. A token is simply
|
||||
a higher-level symbol that is composed of one or more physical symbols. Then the
|
||||
remaining parsing takes place on the sequence of tokens. This is done purely as a
|
||||
matter of convenience and efficiency, because the technique we will develop to do the parsing
|
||||
is fully capable of doing the tokenizing part as well.
|
||||
\border
|
||||
|
||||
\vfil\eject
|
||||
|
||||
{\bigboldfont Formal Grammars and Parsing}
|
||||
\medskip
|
||||
|
||||
We will now learn a technique for specifying the syntax of a language that is more powerful
|
||||
than the FA approach. One limited version of this approach will let us specify most of the
|
||||
syntax of a typical programming language.
|
||||
\bigskip
|
||||
|
||||
A {\it formal grammar\/} consists of a set of {\it non-terminal symbols}, a set of {\it terminal symbols},
|
||||
and a set of {\it production rules}. One non-terminal symbol is designated as the {\it start symbol}.
|
||||
\medskip
|
||||
|
||||
\Indent{1}
|
||||
As we saw in my specification of Jive, we will often use symbols written between angle brackets,
|
||||
like {\tt <expr>}, to represent
|
||||
non-terminal symbols.
|
||||
Terminal symbols will be tokens produced by the lexical analysis phase.
|
||||
\medskip
|
||||
|
||||
For our early example we will tend to use uppercase letters for non-terminal symbols and
|
||||
lowercase letters for terminal symbols.
|
||||
\Outdent
|
||||
|
||||
A production rule has one or more symbols (both terminal and non-terminal allowed) known
|
||||
as the ``left hand side,'' followed
|
||||
by a right arrow, followed by one or more symbols known as the ``right hand side.''
|
||||
\medskip
|
||||
|
||||
A {\it derivation\/} starts with the start symbol and proceeds by replacing any substring of
|
||||
the current string that occurs as the left hand side of a rule by the right hand side of that rule,
|
||||
continuing until a string is reached that has only terminal symbols in it. At this point, that
|
||||
string of terminal symbols has been proven to be in the language accepted by the grammar.
|
||||
\medskip
|
||||
|
||||
{\bf A Simple Example}
|
||||
\medskip
|
||||
|
||||
Here is a simple grammar, where the non-terminals are $S$, $A$, and $B$, and the
|
||||
$S$ is the start symbol,
|
||||
and the terminal symbols are $a$, $b$, $c$, and $d$.
|
||||
\medskip
|
||||
|
||||
$ S \rightarrow AB $
|
||||
|
||||
$ A \rightarrow a A b $
|
||||
|
||||
$ A \rightarrow c $
|
||||
|
||||
$ B \rightarrow d $
|
||||
|
||||
$ B \rightarrow d B $
|
||||
\medskip
|
||||
|
||||
Here is a sample derivation of a string from this grammar, where each line
|
||||
involves one substitution:
|
||||
\medskip
|
||||
|
||||
$S$
|
||||
|
||||
$AB$
|
||||
|
||||
$ a A b B$
|
||||
|
||||
$ a a A b b B$
|
||||
|
||||
$ a a c b b B $
|
||||
|
||||
$ a a c b b d B $
|
||||
|
||||
$ a a c b b d d B $
|
||||
|
||||
$ a a c b b d d d $
|
||||
|
||||
\medskip
|
||||
|
||||
This derivation shows that {\tt aacbbddd} is in the language accepted by this grammar.
|
||||
\medskip
|
||||
|
||||
\doit Determine the language accepted by this grammar. Note that it
|
||||
has parts that could have been accomplished by the FA technique, and parts that
|
||||
could not.
|
||||
\border
|
||||
|
||||
{\bf Context Free Grammars}
|
||||
\medskip
|
||||
|
||||
This formal grammar technique
|
||||
is a very general tool, but we will focus on a special version known as a
|
||||
{\it context free grammar} where the left hand side of a rule can only be a single non-terminal
|
||||
symbol.
|
||||
\medskip
|
||||
|
||||
Context free grammars are nice because on each step of a derivation, the only question is,
|
||||
which non-terminal symbol in the current string should we replace by using a rule where
|
||||
it occurs as the left hand side.
|
||||
\medskip
|
||||
|
||||
We can now think of what we really mean by parsing. For a context free grammar, the
|
||||
challenge is to take a given string---an alleged program---and try to find a derivation.
|
||||
\medskip
|
||||
|
||||
Context free grammars are used because they are powerful enough to specify most of
|
||||
what we want in the syntax of a language, but are still amenable to being parsed {\it efficiently}.
|
||||
\medskip
|
||||
|
||||
It is also important to note that for the languages people tend to use, apparently, the
|
||||
semantics (meaning) of a program are closely related to the syntactic structure.
|
||||
\medskip
|
||||
|
||||
\Indent{1}
|
||||
Here is a feature of a typical programming language that isn't captured, typically, by the
|
||||
context free grammar that specifies the syntax of the language: local variables in Java
|
||||
have to be defined before they are used. Typically the context free grammar
|
||||
says that the body of a method consists of a sequence of one or more statements, and
|
||||
statements are things like {\tt int x;} and {\tt x = 3;}, but the grammar doesn't specify that
|
||||
one has to occur before the other. Those rules of the language have to be handled in
|
||||
some other way.
|
||||
\medskip
|
||||
\Outdent
|
||||
|
||||
For context free grammars, we can improve on the notation of a derivation a lot by
|
||||
the {\it parse tree\/} concept. Instead of recopying the current string on each step, we
|
||||
show the replacement of a left hand side non-terminal symbol by writing a child in the
|
||||
tree for each symbol in the right hand side. Here is a parse tree for the first example
|
||||
given:
|
||||
\medskip
|
||||
|
||||
$$
|
||||
\beginpicture
|
||||
\setcoordinatesystem units <1true pt,1true pt>
|
||||
\put {S} at 150.0 120.0
|
||||
\put {A} at 60.0 90.0
|
||||
\put {B} at 210.0 90.0
|
||||
\put {a} at 0.0 60.0
|
||||
\put {A} at 60.0 60.0
|
||||
\put {b} at 120.0 60.0
|
||||
\put {d} at 180.0 60.0
|
||||
\put {B} at 270.0 60.0
|
||||
\put {a} at 30.0 30.0
|
||||
\put {A} at 60.0 30.0
|
||||
\put {b} at 90.0 30.0
|
||||
\put {d} at 240.0 30.0
|
||||
\put {B} at 300.0 30.0
|
||||
\put {c} at 60.0 0.0
|
||||
\put {d} at 300.0 0.0
|
||||
% Edge from 1 to 2:
|
||||
\plot 141.0 117.0 68.0 92.0 /
|
||||
\put {} at 141.0 117.0
|
||||
% Edge from 1 to 3:
|
||||
\plot 158.0 115.0 201.0 94.0 /
|
||||
\put {} at 158.0 115.0
|
||||
% Edge from 2 to 4:
|
||||
\plot 51.0 85.0 8.0 64.0 /
|
||||
\put {} at 51.0 85.0
|
||||
% Edge from 2 to 5:
|
||||
\plot 60.0 81.0 60.0 69.0 /
|
||||
\put {} at 60.0 81.0
|
||||
% Edge from 2 to 6:
|
||||
\plot 68.0 85.0 111.0 64.0 /
|
||||
\put {} at 68.0 85.0
|
||||
% Edge from 3 to 7:
|
||||
\plot 203.0 83.0 186.0 66.0 /
|
||||
\put {} at 203.0 83.0
|
||||
% Edge from 3 to 8:
|
||||
\plot 218.0 85.0 261.0 64.0 /
|
||||
\put {} at 218.0 85.0
|
||||
% Edge from 5 to 9:
|
||||
\plot 53.0 53.0 36.0 36.0 /
|
||||
\put {} at 53.0 53.0
|
||||
% Edge from 5 to 10:
|
||||
\plot 60.0 51.0 60.0 39.0 /
|
||||
\put {} at 60.0 51.0
|
||||
% Edge from 5 to 11:
|
||||
\plot 66.0 53.0 83.0 36.0 /
|
||||
\put {} at 66.0 53.0
|
||||
% Edge from 8 to 12:
|
||||
\plot 263.0 53.0 246.0 36.0 /
|
||||
\put {} at 263.0 53.0
|
||||
% Edge from 8 to 13:
|
||||
\plot 276.0 53.0 293.0 36.0 /
|
||||
\put {} at 276.0 53.0
|
||||
% Edge from 10 to 14:
|
||||
\plot 60.0 21.0 60.0 9.0 /
|
||||
\put {} at 60.0 21.0
|
||||
% Edge from 13 to 15:
|
||||
\plot 300.0 21.0 300.0 9.0 /
|
||||
\put {} at 300.0 21.0
|
||||
\endpicture
|
||||
$$
|
||||
\border
|
||||
|
||||
\vfil\eject
|
||||
|
||||
{\bf A Bad Way to Try to Express Expressions}
|
||||
\medskip
|
||||
|
||||
Consider the following grammar, where $E$ is the start symbol, and
|
||||
$V$ and $N$ are viewed as terminal symbols namely tokens representing
|
||||
variables and numeric literals, and other symbols that are not uppercase letters
|
||||
are viewed as tokens.
|
||||
\medskip
|
||||
|
||||
$ E \rightarrow N$
|
||||
|
||||
$ E \rightarrow V$
|
||||
|
||||
$ E \rightarrow E + E $
|
||||
|
||||
$ E \rightarrow E * E $
|
||||
|
||||
$ E \rightarrow (E)$
|
||||
\medskip
|
||||
|
||||
This grammar seems reasonable, but it turns out to be a rather poor way to specify
|
||||
a language consisting of all mathematical expressions using variables, numeric literals,
|
||||
addition, multiplication, and parentheses. For one thing, the grammar is ambiguous---there
|
||||
are strings that have significantly different parse trees. For another, the grammar has no
|
||||
concept of operator precedence.
|
||||
\medskip
|
||||
|
||||
\doit Come up with some expressions and produce parse trees for them.
|
||||
Verify the complaints just made.
|
||||
\border
|
||||
|
||||
{\bf A Classic Example of a Context Free Grammar}
|
||||
\medskip
|
||||
|
||||
Now consider this grammar for the language of simple expressions,
|
||||
where $E$ is the start symbol, and
|
||||
$V$ and $N$ are viewed as terminal symbols, namely tokens representing
|
||||
variables and numeric literals, and other symbols that are not uppercase letters
|
||||
are viewed as tokens.
|
||||
\medskip
|
||||
|
||||
$E \rightarrow T$
|
||||
|
||||
$E \rightarrow T+E$
|
||||
|
||||
$T \rightarrow F$
|
||||
|
||||
$ T \rightarrow F * T$
|
||||
|
||||
$F \rightarrow V$
|
||||
|
||||
$F \rightarrow N$
|
||||
|
||||
$F \rightarrow (E)$
|
||||
\medskip
|
||||
|
||||
\doit This grammar captures the syntax of an {\it expression} involving two
|
||||
binary operators with different precedence. Produce parse trees for some expressions and
|
||||
note that the grammar is not ambiguous and enforces operator precedence.
|
||||
\border
|
||||
|
||||
{\bf Parse Trees as Code}
|
||||
\medskip
|
||||
|
||||
The previous example suggests a powerful idea: if someone gives you a parse tree for an
|
||||
expression, and values for all the variables occurring, you can easily compute the value
|
||||
of the expression---and you can easily write code that interprets the parse tree.
|
||||
\medskip
|
||||
|
||||
Thus, in a very real sense, the tree structure is a better programming language than
|
||||
the language described by the context free grammar, except for one big catch: it's hard to
|
||||
read and write parse trees, compared to reading and writing strings.
|
||||
\border
|
||||
|
||||
{\bf Exercise 10}
|
||||
\medskip
|
||||
|
||||
Working in your small group, produce a parse tree for the following expression, using the good
|
||||
expression grammar.
|
||||
Then, assuming that $a=12$, $b=7$, and $c=2$, show how the parse tree can be used to
|
||||
compute the value of the expression---note how the value of each node in the parse tree
|
||||
is obtained from the values of its children.
|
||||
\medskip
|
||||
|
||||
Use this expression:
|
||||
|
||||
$$ 7*a + (c*a*c+4*a)*b $$
|
||||
\border
|
||||
|
||||
{\bf Designing and Specifying the Simple Calculator Language}
|
||||
\medskip
|
||||
|
||||
Now we want to design (and then implement) a language that allows the user to
|
||||
perform a sequence of computations such as a person could do on a calculator.
|
||||
But, we want the language to allow use of expressions and assignment statements.
|
||||
\medskip
|
||||
|
||||
\doit As a whole group, invent a name for this language, and write some example programs
|
||||
so everyone will see the sorts of things we want to allow, and the sorts of things we don't want
|
||||
to allow.
|
||||
\border
|
||||
|
||||
{\bf Exercise 11}
|
||||
\medskip
|
||||
|
||||
Working in your small group, specify the simple calculator language by determining its
|
||||
tokens (categories of conceptual symbols, such as probably {\tt <var>} for variable),
|
||||
drawing an FA for each kind of token, and writing a context free grammar for the
|
||||
language.
|
||||
\medskip
|
||||
|
||||
Use {\tt <program>} for the start variable, which should produce any possible program in the
|
||||
language.
|
||||
\border
|
||||
|
||||
\doit Working back together as a whole group, write down the final specification
|
||||
for the simple calculator language.
|
||||
\border
|
||||
|
||||
{\bf Implementing the Lexical Phase}
|
||||
\medskip
|
||||
|
||||
\doit As a whole group, produce a Java class named {\tt Lexer} that
|
||||
will take a file containing a program in the simple calculator language as input and produce a sequence of tokens.
|
||||
In addition to producing this stream of tokens, {\tt Lexer} should have the ability to ``put back'' a token, for convenience
|
||||
in the recursive descent parsing phase. The point is that we will produce a grammar that will allow us to
|
||||
look ahead at the next token, thinking it will be part of the entity we are producing, and then realize from that next token
|
||||
that we are done with the entity we were producing, so it is convenient to put back the look ahead token.
|
||||
|
||||
\vfil\eject
|
||||
%\bye
|
||||
|
||||
{\bf Implementing The Simple Calculator Language}
|
||||
\medskip
|
||||
|
||||
\doit
|
||||
Working as a whole group,
|
||||
finish the draft design of the simple calculator language,
|
||||
and write down a context free grammar to specify it.
|
||||
\medskip
|
||||
|
||||
\Indent{1}
|
||||
As we do this, we want to try to write the rules so that they process symbols on the
|
||||
left, leaving the recursive parts on the right.
|
||||
For example, if we want to say ``1 or more {\tt a}'s'' we could either use the
|
||||
rules
|
||||
$$ A \rightarrow Aa \; \vert \; a $$
|
||||
or we could say
|
||||
$$ A \rightarrow aA \; \vert \; a $$
|
||||
|
||||
with the same result from a theoretical perspective.
|
||||
But, because we want to use the {\it recursive descent parsing\/} technique (there are other
|
||||
parsing techniques that we will not study that like grammars in different forms),
|
||||
we will want to use the second approach.
|
||||
\medskip
|
||||
\Outdent
|
||||
|
||||
\border
|
||||
|
||||
\doit Working as a whole group, begin work on a class {\tt Parser} that will take
|
||||
a {\tt Lexer} as a source of tokens and produce a {\it parse tree\/} that represents a simple calculator
|
||||
language program in a way that it can be directly executed.
|
||||
\medskip
|
||||
|
||||
\Indent{1}
|
||||
As a practical matter, to save some time
|
||||
we will begin with some old code that I produced for a different language and modify it massively
|
||||
to do the job for our new language.
|
||||
\medskip
|
||||
|
||||
Note that along with the {\tt Lexer} and {\tt Parser} classes, this old code includes {\tt Token} and
|
||||
{\tt Node} classes that will be used extensively in our work.
|
||||
\medskip
|
||||
|
||||
The classes {\tt Basic}, {\tt Camera}, and {\tt TreeViewer} support visualizing a parse tree for
|
||||
debugging and testing purposes.
|
||||
\medskip
|
||||
\Outdent
|
||||
|
||||
As we will see, the recursive descent parsing technique involves writing a method for every non-terminal
|
||||
symbol in the grammar. Each of these methods will consume a sequence of tokens and produce a
|
||||
node that is the root of a tree that is the translation of the corresponding chunk of code.
|
||||
\medskip
|
||||
|
||||
Also, these methods will return {\tt null} if they realize that the next few tokens don't fit what they are
|
||||
expecting to see.
|
||||
\medskip
|
||||
|
||||
We will not take the time to be very careful about detecting and reporting errors in the source code.
|
||||
We will basically assume that the source code is correct. But, when it makes sense to do so, we will
|
||||
notice errors and halt the parsing process with some error message to the programmer.
|
||||
\border
|
||||
|
||||
\vfil\eject
|
||||
|
||||
{\bf Final (?) Finite Automata for Lexer for Corgi}
|
||||
\bigskip
|
||||
|
||||
\epsfbox{../Secret/Corgi/Figures/corgiFA.1}
|
||||
\border
|
||||
|
||||
\doit Instructor will briefly discuss {\tt Lexer} and {\tt Parser} in preparation for Exercises 12 and 13.
|
||||
\border
|
||||
|
||||
{\bf Exercise 12}
|
||||
Working in your small group, write the code for state 3, 4, and 5 in the {\tt Lexer.java} file for Corgi.
|
||||
To help you understand {\tt Lexer} and do this Exercise effectively, a number of trees have been
|
||||
killed to provide you with a printout of the existing code on the next pages.
|
||||
\vfil\eject
|
||||
|
||||
\count255 1
|
||||
\numberedListing{../Corgi/Lexer.java}{\tt}
|
||||
\border
|
||||
|
||||
{\bf Exercise 13}
|
||||
Working in your small group, write the code for {\tt parseFactor} in
|
||||
the class {\tt Parser}, listed on the next few pages.
|
||||
\bigskip
|
||||
|
||||
Here is the draft context free grammar for Corgi (note some changes from our earlier version):
|
||||
\medskip
|
||||
|
||||
{\baselineskip 0.95 \baselineskip
|
||||
\listing{../Corgi/corgiCFG.txt}
|
||||
|
||||
\border}
|
||||
|
||||
\count255 1
|
||||
\numberedListing{../Corgi/Parser.java}{\tt}
|
||||
|
||||
\vfil\eject
|
||||
|
||||
\doit Instructor will discuss the minor changes to {\tt Parser} (listed in its entirety below)
|
||||
and draw a parse tree for
|
||||
a Corgi program.
|
||||
\border
|
||||
|
||||
{\bf Exercise 14}
|
||||
Working in your small groups, construct the parse tree for {\tt quadroots} following the final (I hope!)
|
||||
version of {\tt Parser}.
|
||||
\border
|
||||
|
||||
{\baselineskip 0.75\baselineskip
|
||||
\count255 1
|
||||
\font \smalltt cmtt10 scaled 800
|
||||
\numberedListing{../Corgi/Parser.java}{\smalltt}
|
||||
\border
|
||||
}
|
||||
|
||||
{\bf Exercise 15}
|
||||
Below you will find a partial listing of the {\tt Node} class, namely the partially completed
|
||||
{\tt execute} and {\tt evaluate} methods.
|
||||
Working in your small groups,
|
||||
write the missing code.
|
||||
\medskip
|
||||
|
||||
Note that nodes have instance variables {\tt kind}, {\tt info} (both strings), and
|
||||
{\tt first} and {\tt second} (both nodes).
|
||||
\medskip
|
||||
|
||||
Also, there is a {\tt MemTable} class that has public methods
|
||||
|
||||
{\tt void store( String name, double value)}
|
||||
|
||||
and
|
||||
|
||||
{\tt double retrieve( String name)}
|
||||
\medskip
|
||||
|
||||
If you need further details about any of the classes in the {\tt Corgi} project
|
||||
(namely {\tt Corgi}, {\tt Token}, {\tt Lexer}, {\tt Parser}, {\tt Node}, and {\tt MemTable},
|
||||
you should look at them online (assuming someone in your group has a computer in class).
|
||||
|
||||
\vfil\eject
|
||||
|
||||
\count255 136
|
||||
\numberedListing{../Corgi/partialNode.java}{\tt}
|
||||
|
||||
\vfil\eject
|
||||
|
||||
{\bigboldfont Designing Project 2}
|
||||
\medskip
|
||||
|
||||
To keep Project 2 manageable (a first serious submission for Project 2 must be submitted by the time of Test 2---October 29),
|
||||
I have decided to make this project be to simply (we hope!) add some
|
||||
features to Corgi as follows.
|
||||
\medskip
|
||||
|
||||
\Indent{1}
|
||||
First, we want to give the Corgi programmer the ability to define functions, and of course to call them.
|
||||
\medskip
|
||||
|
||||
Second, we want to add branching to Corgi.
|
||||
\medskip
|
||||
\Outdent
|
||||
|
||||
\doit Working as a whole group, design the finite automata for the Corgi {\tt Lexer}, and the
|
||||
context free grammar for the Corgi {\tt Parser}.
|
||||
Discuss the features we are not adding to Corgi, and perhaps decide to add some of them.
|
||||
As part of this design process, write some sample Corgi programs (these will also provide a
|
||||
starting point for testing your Project 2 work).
|
||||
\medskip
|
||||
|
||||
\doit Once the syntax of the language is specified, try to specify the {\it semantics\/} of the language,
|
||||
and think about how execution/evaluation of the parse tree will be done.
|
||||
\bigskip
|
||||
|
||||
{\bf Note:} after we have made decisions about the new and improved Corgi,
|
||||
henceforth to be known as ``Corgi,'' I will document them.
|
||||
But, you should be able to start working on Project 2 right away, based on the informal
|
||||
documentation recorded during this class session.
|
||||
\border
|
||||
|
||||
{\bigboldfont Project 2} [10 points] [first serious submission absolutely due by October 29]
|
||||
\medskip
|
||||
|
||||
Implement the extended Corgi language as specified in class and in upcoming documents.
|
||||
Be alert for corrections to the Corgi specification that may need to be made as work proceeds.
|
||||
\medskip
|
||||
|
||||
Be sure to test your implementation thoroughly.
|
||||
\medskip
|
||||
|
||||
Email me your group's submission with a single {\tt zip} or {\tt jar} file attached, named either
|
||||
{\tt corgi.jar} or {\tt corgi.zip}. This single file must contain all the source code files.
|
||||
Be sure to CC all group members on the email that submits your work.
|
||||
\medskip
|
||||
|
||||
I must be able to extract all the Java source files from your submitted file into a folder, and then simply
|
||||
type at the command prompt:
|
||||
\medskip
|
||||
|
||||
{\tt javac Corgi.java}
|
||||
|
||||
{\tt java Corgi test3}
|
||||
\medskip
|
||||
|
||||
in order to run the Corgi program in the file named {\tt test3}.
|
||||
\border
|
||||
|
||||
\vfil\eject
|
||||
|
||||
\bye
|
||||
|
||||
{\bf Designing Project 2}
|
||||
\medskip
|
||||
|
||||
\doit Discuss possibilities for Project 2 and decide what it should be.
|
||||
% Then, we'll apply CYK and/or recursive descent to it
|
||||
\vfil\eject
|
||||
|
||||
{\bigboldfont Course Policy Change}
|
||||
\medskip
|
||||
Test 2 is canceled, due to the facts that we haven't covered enough material suitable for fair assessment,
|
||||
and we have just barely gotten to the main topics of language implementation.
|
||||
\medskip
|
||||
|
||||
The test scheduled for April 13 will cover the material we have been and are still working on, along
|
||||
with some functional programming topics, about equally weighted. The test at the time of the final exam
|
||||
will cover Clojure and Prolog topics.
|
||||
\medskip
|
||||
|
||||
Your course grade will be figured with the 68\% for Tests divided either into 3 or 4, with the next test counting
|
||||
as two tests or one, and taking the maximum of the two calculations.
|
||||
\border
|
||||
|
||||
{\bigboldfont Otter}
|
||||
\medskip
|
||||
|
||||
I had been thinking Project 2 would be to finish implementing Otter, but now I'm thinking Project 2 will be
|
||||
to implement the ``simple example'' we started on February 28th. We will spend a few more class periods
|
||||
working through implementation of Otter together (with me, unfortunately, doing most of the work outside of
|
||||
class).
|
||||
\border
|
||||
|
||||
{\bigboldfont Project 2}
|
||||
\medskip
|
||||
|
||||
Implement the simple calculator language (let's call it ``CalcLang'') designed in class, with that design
|
||||
documented (including the finite automaton for the lexical part of the language, the context free grammar,
|
||||
and an informal description of the language semantics) in the folder {\tt Project2} at the course web stie.
|
||||
\medskip
|
||||
|
||||
When you are done, you will have an application consisting of several Java classes. You must submit your
|
||||
work to me as follows:
|
||||
\medskip
|
||||
|
||||
\In
|
||||
Make sure that the main class---the one that contains the {\tt main} method at which execution starts---is
|
||||
named exactly {\tt CalcLang}.
|
||||
\medskip
|
||||
|
||||
Clean up your source files for submission by removing all non-portable {\tt package} statements and
|
||||
all extraneous output.
|
||||
\medskip
|
||||
|
||||
Put all your source files in a folder, named {\tt Project2}.
|
||||
Create a {\tt jar} file from the command line by moving into the folder that contains the folder {\tt Project2}
|
||||
and entering
|
||||
\smallskip
|
||||
{\tt jar cvfM proj2.jar Project2}
|
||||
\medskip
|
||||
|
||||
Test your work by making a temporary folder somewhere, copying {\tt proj2.jar} into it, moving into it,
|
||||
and entering
|
||||
\smallskip
|
||||
{\tt jar xf proj2.jar}
|
||||
\smallskip
|
||||
This should make a folder {\tt Project2} that contains all your source code. Move into it and compile and
|
||||
run your application.
|
||||
\medskip
|
||||
|
||||
Email me your submission with {\tt proj2.jar} attached at {\tt shultzj@msudenver.edu}
|
||||
\bigskip
|
||||
|
||||
If you are somehow incapable of doing the previous work, you may as a slightly irritating (to me) alternative
|
||||
make a {\tt zip} file of the folder containing your source code instead of a {\tt jar} file.
|
||||
\medskip
|
||||
\Out
|
||||
|
||||
|
||||
|
||||
\vfil\eject
|
||||
\bye
|
||||
|
||||
Executable
BIN
Binary file not shown.
Executable
+1945
File diff suppressed because it is too large
Load Diff
Executable
+143
@@ -0,0 +1,143 @@
|
||||
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 a factor starting with " + token );
|
||||
System.exit(1);
|
||||
return null;
|
||||
}
|
||||
|
||||
}// <factor>
|
||||
Executable
BIN
Binary file not shown.
Executable
+262
@@ -0,0 +1,262 @@
|
||||
\input /Users/Shared/TeX/defs
|
||||
\input pictex
|
||||
\input /Users/Shared/TeX/ruled
|
||||
|
||||
%\advance \voffset by 1true in
|
||||
|
||||
\pageno -1
|
||||
\parindent 0true in
|
||||
|
||||
\datestartup{CS 3210 Fall 2018}{-1} % crucial for all later handouts
|
||||
|
||||
\line{\bf CS 3210 Principles of Programming Languages \hfil Fall 2018}
|
||||
\medskip
|
||||
\hrule
|
||||
\bigskip
|
||||
Instructor: Jerry Shultz
|
||||
\medskip
|
||||
\hrule
|
||||
\medskip
|
||||
\line{Office: {AES Building, Room 200Z}\hfil Phone: {\bf 303 615 1161}}
|
||||
\medskip
|
||||
\line{Email: {\bf shultzj@msudenver.edu}\hfil Website: {\bf rowdysites.msudenver.edu/$\sim$shultzj}}
|
||||
\medskip
|
||||
\hrule
|
||||
\medskip
|
||||
|
||||
\input schedule
|
||||
\medskip
|
||||
\hrule
|
||||
\medskip
|
||||
|
||||
The times listed as ``Office Hours'' are times that I will be sitting in my office waiting to help you when you call or come by (barring emergencies and
|
||||
quick trips away and back, and travel time from and to classes).
|
||||
\medskip
|
||||
You are
|
||||
welcome to stop by any time on the chance that I'll be there and will be able to meet with you.
|
||||
Finally, if those times are not convenient for you, we can arrange a mutually convenient time
|
||||
to meet.
|
||||
\bigskip
|
||||
|
||||
\vfil\eject
|
||||
|
||||
\line{\bf Text:\hfil}
|
||||
|
||||
Written materials provided by instructor and online resources
|
||||
|
||||
\medskip
|
||||
|
||||
\line{\bf Prerequisites\hfil}
|
||||
CS 2050, CS 2400, CS 3250, and MTH 3170, all with a grade of C or better, or permission of instructor
|
||||
\medskip
|
||||
|
||||
%\line{\bf Official Syllabus\hfil}
|
||||
|
||||
%You can find the official syllabus for this course at {\tt https://mcs.msudenver.edu/syllabi}
|
||||
%\medskip
|
||||
|
||||
|
||||
{\bf Withdrawal dates} for FULL-TERM courses are:
|
||||
\medskip
|
||||
|
||||
\ruledtable
|
||||
100\% refund: | Sunday, August 26 \nr
|
||||
50\% refund: | Wednesday, September 5 \nr
|
||||
Last Day for W: | Wednesday, November 2
|
||||
\endruledtable
|
||||
\medskip
|
||||
|
||||
{\advance \leftskip .5true in
|
||||
For all full-term and part-term courses, you can confirm withdrawal dates on your
|
||||
|
||||
$\underline{\hbox{Student Detail Schedule}}$
|
||||
\medskip
|
||||
}
|
||||
|
||||
{\bf Holiday information:}
|
||||
|
||||
Labor Day: September 3 (campus closed)
|
||||
|
||||
Fall Break: November 19--25 (no classes, campus open except on 11/22 and 11/23)
|
||||
\medskip
|
||||
|
||||
{\bf University Policies}
|
||||
\medskip
|
||||
|
||||
Students are responsible for full knowledge of the provisions and regulations pertaining
|
||||
to all aspects of their attendance at MSU Denver, and should familiarize themselves with
|
||||
the following policies:
|
||||
|
||||
{\advance \leftskip .5true in
|
||||
\item{1.} GENERAL UNIVERSITY POLICIES
|
||||
|
||||
\item{2.} GRADES AND NOTATIONS including WITHDRAWAL FROM A COURSE,\hfil\break ADMINISTRATIVE
|
||||
WITHDRAWAL, and INCOMPLETE POLICY
|
||||
|
||||
\item{} Students should be aware that any kind of withdrawal can have a negative impact on some
|
||||
types of financial aid, including scholarships.
|
||||
|
||||
\item{3.} ACADEMIC INTEGRITY
|
||||
|
||||
\item{4.} POLICY STATEMENTS ON SEXUAL MISCONDUCT
|
||||
|
||||
\item{5.} ACCOMMODATIONS TO ASSIST INDIVIDUALS WITH DISABILITIES
|
||||
|
||||
\item{6.} CLASS ATTENDANCE
|
||||
|
||||
\item{7.} ELECTRONIC COMMUNICATION (STUDENT EMAIL) POLICY
|
||||
\medskip
|
||||
}
|
||||
|
||||
For a complete description of these policies go to
|
||||
{\tt msudenver.edu/math/policies}
|
||||
|
||||
\border
|
||||
|
||||
{\bf Additional Policies for this Course}
|
||||
\medskip
|
||||
|
||||
If you must miss a class session, it is your
|
||||
responsibility to find out what you missed and make up work if possible.
|
||||
If you miss a test due to an appropriate cause (illness, unavoidable family or work conflicts,
|
||||
religious holiday, etc.), you
|
||||
are responsible for arranging with me a time to take a make-up exam.
|
||||
\border
|
||||
|
||||
\vfil\eject
|
||||
|
||||
\font \smallerfont cmr10 scaled 800
|
||||
\font \smallertt cmtt10 scaled 800
|
||||
|
||||
\line{\bf Course Organization and Rules\hfil}
|
||||
\medskip
|
||||
|
||||
In a typical class session I will present some new material---Mini-Lectures---with that material written up
|
||||
in the
|
||||
course notes. Then students will work on Exercises giving hands-on work with the new material.
|
||||
Some Exercises will involve hand-written solutions and should be done, ideally, working in groups of
|
||||
four or five using a section of whiteboard. Other Exercises will involve writing code on a computer and
|
||||
should be done, ideally, working in groups of two or three with at least one laptop computer brought in
|
||||
by a student.
|
||||
As students work on these Exercises, the instructor and two Learning Assistants will be available to
|
||||
discuss issues that come up.
|
||||
\medskip
|
||||
|
||||
Note that these Exercises are designed to provide a more effective alternative to listening to lectures all
|
||||
the time. The Exercises are not graded, but if you do not complete them during class time (especially if
|
||||
you are not in class) you should complete them outside of class. If you are unable to do the Exercises,
|
||||
you will probably not do well on the corresponding questions on the Tests.
|
||||
It is strongly encouraged that you work in groups, because for most people this is helpful, but it is not
|
||||
required.
|
||||
\medskip
|
||||
|
||||
At times we will discuss Exercises as a whole group after students have had time to work on them separately.
|
||||
\medskip
|
||||
|
||||
I will post all course materials, including the written ``course notes'' corresponding to the
|
||||
mini-lectures, and any summaries of whole group discussions of Exercises,
|
||||
at\hfil\break
|
||||
{\tt rowdysites.msudenver.edu/$\sim$shultzj}
|
||||
\bigskip
|
||||
|
||||
Your ``homework'' for this course will be to go over the new material and corresponding Exercises as needed,
|
||||
and to complete a number of programming Projects.
|
||||
\medskip
|
||||
|
||||
You are encouraged to discuss the course
|
||||
material, the Exercises, and even the Projects
|
||||
with other students, me, the Learning Assistants, or whomever you wish,
|
||||
but you may not receive any help from anyone on the Tests.
|
||||
Also, while you are encouraged to discuss the Projects
|
||||
with others, you may not directly copy the work of
|
||||
others---any work that you submit should, at a minimum,
|
||||
be ``written in your own words.''
|
||||
\medskip
|
||||
|
||||
It is okay, even encouraged, to do the Projects as a group effort with at most three people participating fully.
|
||||
If your work on a Project is part of a group effort, the group must turn in one submission,
|
||||
with the two or three group members clearly identified. If you do this, be sure that it is an
|
||||
actual meaningful collaboration, not just giving the work of one person to the others. And,
|
||||
when one group member emails me the group submission, be sure to ``CC'' the other
|
||||
one or two group members so they also receive the feedback email from me.
|
||||
\medskip
|
||||
|
||||
Each project will be worth some number of project points, varying somewhat from project to project to
|
||||
reflect the work involved in each one.
|
||||
If your project does not fully meet the specifications, you will be given feedback and will have the
|
||||
opportunity, with no penalty, to fix the problems and resubmit your work.
|
||||
Only very limited partial credit will be given for work that is not correct and complete, and this will
|
||||
happen only when you do not resubmit your work, typically at the end of the semester when you simply
|
||||
run out of time.
|
||||
\medskip
|
||||
|
||||
Each Project will have a due date by which your first serious submission must be made.
|
||||
When a Project is specified its tentative due date will be given, but sometimes we will adjust that
|
||||
date to a later date.
|
||||
You will be allowed to fix/complete work on projects later as long as you make a first
|
||||
meaningful submission on time.
|
||||
Projects not submitted by the due date
|
||||
will not be accepted.
|
||||
\bigskip
|
||||
|
||||
We will have three in-class Tests, each covering roughly the previous five weeks of material.
|
||||
You will be allowed to use any written materials during the Tests, but you will not be allowed to
|
||||
use any electronic devices.
|
||||
\medskip
|
||||
|
||||
Here is the schedule for the tests:
|
||||
\medskip
|
||||
|
||||
\ruledtable
|
||||
Test Number | Date | Class Periods Covered \cr
|
||||
Test 1 | September 26 | 1--8 \nr
|
||||
| (class period 11) | \cr
|
||||
Test 2 | October 29 | 9, 10, 12--17 \nr
|
||||
| (class period 20) | \cr
|
||||
Test 3 | December 10 or 12 | 18, 19, 21--27 \nr
|
||||
| (scheduled final exam time) |
|
||||
\endruledtable
|
||||
\bigskip}
|
||||
|
||||
Here is how course grades will be figured:
|
||||
\medskip
|
||||
|
||||
{\advance \leftskip 0.5true in
|
||||
|
||||
Your {\tt testScore} will be computed by averaging your three test scores. Each test score is computed by dividing the points you got by the
|
||||
number of points possible (so test ``points'' have different values on each test---they are just a convenient way of doing the partial credit
|
||||
accounting on each problem).
|
||||
\medskip
|
||||
|
||||
Your {\tt projectScore} will be the number of project points you got divided by the number of
|
||||
project points possible.
|
||||
\medskip
|
||||
|
||||
Your course score is then computed as
|
||||
\smallskip
|
||||
{\tt 0.4 * projectScore + 0.6 * testScore}
|
||||
\medskip
|
||||
|
||||
Your course grade is then computed according to this chart:
|
||||
\medskip
|
||||
}
|
||||
|
||||
%\TightTables
|
||||
|
||||
\def\tablespace{\hskip 0.05true in}
|
||||
\def\tw{.35true in}
|
||||
|
||||
\font \tinytt cmtt10 scaled 500
|
||||
\ruledtable
|
||||
\bf Score in: | \rtitem{\tw}{\tinytt [0,60)} | \rtitem{\tw}{\tinytt [60,63)} | \rtitem{\tw}{\tinytt [63,67)} | \rtitem{\tw}{\tinytt [67,70)} | \rtitem{\tw}{\tinytt [70,73)} | \rtitem{\tw}{\tinytt [73,77)} | \rtitem{\tw}{\tinytt [77,80)} | \rtitem{\tw}{\tinytt [80,83)} | \rtitem{\tw}{\tinytt [83,87)} | \rtitem{\tw}{\tinytt [87,90)} | \rtitem{\tw}{\tinytt [90,93)} | \rtitem{\tw}{\tinytt [93,100]} \cr
|
||||
\bf Grade: | \rtitem{\tw}{F} | \rtitem{\tw}{D-} | \rtitem{\tw}{D} | \rtitem{\tw}{D+} | \rtitem{\tw}{C-} | \rtitem{\tw}{C} | \rtitem{\tw}{C+} | \rtitem{\tw}{B-} | \rtitem{\tw}{B} | \rtitem{\tw}{B+} | \rtitem{\tw}{A-} | \rtitem{\tw}{A}
|
||||
\endruledtable
|
||||
\medskip
|
||||
|
||||
{\advance \leftskip .5true in
|
||||
with the additional rule that I will improve your grade by one level (one column farther to the right) if you have good attendance and participation.
|
||||
\bigskip
|
||||
}
|
||||
|
||||
\vfil\eject
|
||||
\bye
|
||||
Executable
+89
@@ -0,0 +1,89 @@
|
||||
% PiCTeX schedule generated by Scheduler.java
|
||||
% if not already loaded, decomment 2 lines below:
|
||||
%\input pictex
|
||||
%\input latexpicobjs
|
||||
{\font \schedfont cmr10 scaled 750
|
||||
{\font \boldschedfont cmbx10 scaled 750
|
||||
\schedfont
|
||||
$$
|
||||
\beginpicture
|
||||
\setcoordinatesystem units <0.75pt, 0.75pt>
|
||||
\put{{\boldschedfont 9:00}--9:30} <22.5pt, 7.5pt> at 0.0 360.0
|
||||
\putrectangle corners at 0.0 380.0 and 60.0 360.0
|
||||
\put{9:30--10:00} <22.5pt, 7.5pt> at 0.0 340.0
|
||||
\putrectangle corners at 0.0 360.0 and 60.0 340.0
|
||||
\put{{\boldschedfont 10:00}--10:30} <22.5pt, 7.5pt> at 0.0 320.0
|
||||
\putrectangle corners at 0.0 340.0 and 60.0 320.0
|
||||
\put{10:30--11:00} <22.5pt, 7.5pt> at 0.0 300.0
|
||||
\putrectangle corners at 0.0 320.0 and 60.0 300.0
|
||||
\put{{\boldschedfont 11:00}--11:30} <22.5pt, 7.5pt> at 0.0 280.0
|
||||
\putrectangle corners at 0.0 300.0 and 60.0 280.0
|
||||
\put{11:30--12:00} <22.5pt, 7.5pt> at 0.0 260.0
|
||||
\putrectangle corners at 0.0 280.0 and 60.0 260.0
|
||||
\put{{\boldschedfont 12:00}--12:30} <22.5pt, 7.5pt> at 0.0 240.0
|
||||
\putrectangle corners at 0.0 260.0 and 60.0 240.0
|
||||
\put{12:30--1:00} <22.5pt, 7.5pt> at 0.0 220.0
|
||||
\putrectangle corners at 0.0 240.0 and 60.0 220.0
|
||||
\put{{\boldschedfont 1:00}--1:30} <22.5pt, 7.5pt> at 0.0 200.0
|
||||
\putrectangle corners at 0.0 220.0 and 60.0 200.0
|
||||
\put{1:30--2:00} <22.5pt, 7.5pt> at 0.0 180.0
|
||||
\putrectangle corners at 0.0 200.0 and 60.0 180.0
|
||||
\put{{\boldschedfont 2:00}--2:30} <22.5pt, 7.5pt> at 0.0 160.0
|
||||
\putrectangle corners at 0.0 180.0 and 60.0 160.0
|
||||
\put{2:30--3:00} <22.5pt, 7.5pt> at 0.0 140.0
|
||||
\putrectangle corners at 0.0 160.0 and 60.0 140.0
|
||||
\put{{\boldschedfont 3:00}--3:30} <22.5pt, 7.5pt> at 0.0 120.0
|
||||
\putrectangle corners at 0.0 140.0 and 60.0 120.0
|
||||
\put{3:30--4:00} <22.5pt, 7.5pt> at 0.0 100.0
|
||||
\putrectangle corners at 0.0 120.0 and 60.0 100.0
|
||||
\put{{\boldschedfont 4:00}--4:30} <22.5pt, 7.5pt> at 0.0 80.0
|
||||
\putrectangle corners at 0.0 100.0 and 60.0 80.0
|
||||
\put{4:30--5:00} <22.5pt, 7.5pt> at 0.0 60.0
|
||||
\putrectangle corners at 0.0 80.0 and 60.0 60.0
|
||||
\put{{\boldschedfont 5:00}--5:30} <22.5pt, 7.5pt> at 0.0 40.0
|
||||
\putrectangle corners at 0.0 60.0 and 60.0 40.0
|
||||
\put{5:30--6:00} <22.5pt, 7.5pt> at 0.0 20.0
|
||||
\putrectangle corners at 0.0 40.0 and 60.0 20.0
|
||||
\put{{\boldschedfont 6:00}--6:30} <22.5pt, 7.5pt> at 0.0 0.0
|
||||
\putrectangle corners at 0.0 20.0 and 60.0 0.0
|
||||
\put{CS 3510} <29.400000000000002pt, 29.400000000000002pt> at 60.8 260.8
|
||||
\putrectangle corners at 60.8 339.20000000000005 and 139.2 260.8
|
||||
\put{CS 3510} <29.400000000000002pt, 29.400000000000002pt> at 220.8 260.8
|
||||
\putrectangle corners at 220.8 339.20000000000005 and 299.20000000000005 260.8
|
||||
\put{CS 3210} <29.400000000000002pt, 29.400000000000002pt> at 60.8 180.8
|
||||
\putrectangle corners at 60.8 259.20000000000005 and 139.2 180.8
|
||||
\put{CS 3210} <29.400000000000002pt, 29.400000000000002pt> at 220.8 180.8
|
||||
\putrectangle corners at 220.8 259.20000000000005 and 299.20000000000005 180.8
|
||||
\put{CS 3240} <29.400000000000002pt, 29.400000000000002pt> at 140.8 20.8
|
||||
\putrectangle corners at 140.8 99.2 and 219.20000000000002 20.8
|
||||
\put{CS 3240} <29.400000000000002pt, 29.400000000000002pt> at 300.8 20.8
|
||||
\putrectangle corners at 300.8 99.2 and 379.20000000000005 20.8
|
||||
\put{Office Hours} <29.400000000000002pt, 14.399999999999999pt> at 60.8 140.8
|
||||
\putrectangle corners at 60.8 179.20000000000002 and 139.2 140.8
|
||||
\put{Office Hours} <29.400000000000002pt, 14.399999999999999pt> at 220.8 140.8
|
||||
\putrectangle corners at 220.8 179.20000000000002 and 299.20000000000005 140.8
|
||||
\put{Office Hours} <29.400000000000002pt, 14.399999999999999pt> at 140.8 100.8
|
||||
\putrectangle corners at 140.8 139.2 and 219.20000000000002 100.8
|
||||
\put{Office Hours} <29.400000000000002pt, 14.399999999999999pt> at 300.8 100.8
|
||||
\putrectangle corners at 300.8 139.2 and 379.20000000000005 100.8
|
||||
\put{Office Hours} <29.400000000000002pt, 14.399999999999999pt> at 220.8 100.8
|
||||
\putrectangle corners at 220.8 139.2 and 299.20000000000005 100.8
|
||||
\put{CS Meetings} <29.400000000000002pt, 21.9pt> at 380.8 280.8
|
||||
\putrectangle corners at 380.8 339.2 and 459.20000000000005 280.8
|
||||
\put{Dept. Meetings} <29.400000000000002pt, 21.9pt> at 380.8 160.8
|
||||
\putrectangle corners at 380.8 219.20000000000002 and 459.20000000000005 160.8
|
||||
\put{L.A. Meeting} <29.400000000000002pt, 14.399999999999999pt> at 220.8 60.8
|
||||
\putrectangle corners at 220.8 99.19999999999999 and 299.20000000000005 60.8
|
||||
\put{Monday} <30.0pt, 8.25pt> at 60.0 380.0
|
||||
\putrectangle corners at 60.0 402.0 and 140.0 380.0
|
||||
\put{Tuesday} <30.0pt, 8.25pt> at 140.0 380.0
|
||||
\putrectangle corners at 140.0 402.0 and 220.0 380.0
|
||||
\put{Wednesday} <30.0pt, 8.25pt> at 220.0 380.0
|
||||
\putrectangle corners at 220.0 402.0 and 300.0 380.0
|
||||
\put{Thursday} <30.0pt, 8.25pt> at 300.0 380.0
|
||||
\putrectangle corners at 300.0 402.0 and 380.0 380.0
|
||||
\put{Friday} <30.0pt, 8.25pt> at 380.0 380.0
|
||||
\putrectangle corners at 380.0 402.0 and 460.0 380.0
|
||||
\endpicture
|
||||
$$
|
||||
}
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
public class IntPair
|
||||
{
|
||||
public int first, second;
|
||||
|
||||
public IntPair( int a, int b )
|
||||
{ first = a; second = b; }
|
||||
|
||||
}
|
||||
Executable
+948
@@ -0,0 +1,948 @@
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Jive {
|
||||
|
||||
private static Scanner keys = new Scanner( System.in );
|
||||
private static Scanner input;
|
||||
private static PrintWriter output;
|
||||
private static PrintWriter output2;
|
||||
|
||||
// "global" info --- applies across entire program
|
||||
// ------------------------------------------------
|
||||
|
||||
// holds the vpl code as it is produced
|
||||
private static ArrayList<Integer> vpl = new ArrayList<Integer>();
|
||||
|
||||
// holds the name and starting index of all functions
|
||||
private static ArrayList<StringIntPair> funcStart = new ArrayList<StringIntPair>();
|
||||
|
||||
// string at given index is name of function called at hole -index
|
||||
private static ArrayList<String> callHoles = new ArrayList<String>();
|
||||
|
||||
// stores for entire program the start label assigned to each
|
||||
// given function name
|
||||
private static ArrayList<StringIntPair> callInfo = new ArrayList<StringIntPair>();
|
||||
|
||||
|
||||
// little info for actual globals in VPL:
|
||||
// ----------------------------------------
|
||||
// holds all the global variables for entire program
|
||||
private static ArrayList<String> globsList;
|
||||
|
||||
|
||||
// "local" info --- used separately for each function
|
||||
// --------------------------------------------------
|
||||
|
||||
// holds the local variables and literals temporarily for each function
|
||||
private static ArrayList<String> locsList = new ArrayList<String>();
|
||||
|
||||
// once have a locsList for a function, store it in allLocs for output2
|
||||
private static ArrayList<String> allLocs = new ArrayList<String>();
|
||||
|
||||
// holds the locations of the holes and the corresponding labels in current function
|
||||
private static ArrayList<StringIntPair> labelHoles = new ArrayList<StringIntPair>();
|
||||
|
||||
// holds the label and corresponding index for all labels in current function
|
||||
private static ArrayList<StringIntPair> labelInfo = new ArrayList<StringIntPair>();
|
||||
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length != 1) {
|
||||
System.out.println("Usage: java Jive <fileName>");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
String fileName = args[0];
|
||||
|
||||
input = new Scanner( new File( fileName ) );
|
||||
output = new PrintWriter( new File( fileName + ".vpl" ) );
|
||||
output2 = new PrintWriter( new File( fileName + ".doc" ) );
|
||||
|
||||
// scan Jive file one word at a time
|
||||
// (line breaks mean nothing more than a space)
|
||||
|
||||
// start anonymous "main" function
|
||||
// since human readability is not a big issue, go ahead
|
||||
// and treat the "main" function like all others, even
|
||||
// though the label at the top is meaningless, since it
|
||||
// can't be called
|
||||
// (all other functions do these things when "Def" is encountered)
|
||||
|
||||
vpl.add( 1 );
|
||||
vpl.add( nextLabel(true) ); // all functions start with a 1 command
|
||||
|
||||
// note index where command 4 will be inserted
|
||||
// (can change if there's a Globs command)
|
||||
funcStart.add( new StringIntPair( "?", 2 ) );
|
||||
|
||||
// note label for start of the function
|
||||
callInfo.add( new StringIntPair( "?", currentLabel ) );
|
||||
|
||||
// make scratch cell (local cell 0) for scratch space for main
|
||||
locsList.add( "-" );
|
||||
int scratch = 0;
|
||||
|
||||
String rememberWord = "huh?"; // used a little to pass word to next state
|
||||
|
||||
callHoles.add("---"); // waste spot 0 so call holes -1, -2, -3, ..
|
||||
// match nicely to positions in list
|
||||
|
||||
int state = 1;
|
||||
|
||||
while ( input.hasNext() ) {
|
||||
|
||||
String word = input.next();
|
||||
|
||||
System.out.println("--------------------->>>" +
|
||||
"\nIn state " + state + " processing [" + word + "]" );
|
||||
|
||||
if ( state == 1 ) {
|
||||
if ( word.equals("/*") ) {
|
||||
state = 2;
|
||||
}
|
||||
else if ( word.equals("Halt") ) {
|
||||
vpl.add( 26 );
|
||||
state = 1;
|
||||
}
|
||||
else if ( word.equals("NL") ) {
|
||||
vpl.add( 29 );
|
||||
state = 1;
|
||||
}
|
||||
else if ( word.equals("Def") ) {// starting a function definition
|
||||
|
||||
// stuff to do when see Def, also when see end of input file
|
||||
finishFunctionDef();
|
||||
|
||||
// initialize things for the upcoming function definition
|
||||
locsList = new ArrayList<String>();
|
||||
labelHoles = new ArrayList<StringIntPair>();
|
||||
labelInfo = new ArrayList<StringIntPair>();
|
||||
|
||||
// move on to see the function name
|
||||
state = 3;
|
||||
}
|
||||
else if ( isLabel( word ) ) {// process a label
|
||||
|
||||
int label = nextLabel(false);
|
||||
|
||||
labelInfo.add( new StringIntPair( word, label ) );
|
||||
|
||||
vpl.add( 1 );
|
||||
vpl.add( label );
|
||||
|
||||
state = 1;
|
||||
|
||||
}
|
||||
else if ( word.equals("Globs") ) {// global declarations section
|
||||
// global declarations must be first command in program, if there at all
|
||||
if ( vpl.size() == 2 ) {// have only put in the command 1 for "main"
|
||||
// so still at start
|
||||
vpl.add( 0, 32 );
|
||||
|
||||
globsList = new ArrayList<String>();
|
||||
|
||||
state = 6;
|
||||
}
|
||||
else {
|
||||
error( "Globals declaration must occur at very beginning of a Jive program");
|
||||
}
|
||||
}
|
||||
else if ( word.equals("Jmp") ) {
|
||||
vpl.add( 7 );
|
||||
state = 7;
|
||||
}
|
||||
|
||||
else if ( findBIF2( word ) >= 0 ) {// is built-in function with 2 args
|
||||
// cheaply get opcode corresponding to word
|
||||
|
||||
int op;
|
||||
if ( word.equals("Get") ) {
|
||||
op = 24;
|
||||
}
|
||||
else {
|
||||
op = findBIF2(word) + 9;
|
||||
}
|
||||
|
||||
vpl.add( op ); // the binary op
|
||||
vpl.add( scratch ); // where to put the result
|
||||
state = 8;
|
||||
}
|
||||
|
||||
else if ( findBIF1( word ) >= 0 ) {// is built-in function with 1 arg
|
||||
if ( word.equals( "Not" ) )
|
||||
vpl.add( 20 );
|
||||
else if ( word.equals( "Opp" ) )
|
||||
vpl.add( 21 );
|
||||
else if ( word.equals( "New" ) )
|
||||
vpl.add( 31 );
|
||||
else
|
||||
error("[" + word + "] is not a valid one argument built-in function");
|
||||
|
||||
vpl.add( scratch );
|
||||
|
||||
state = 11;
|
||||
}
|
||||
|
||||
else if ( word.equals("Keys") ) {// is built-in function with 0 args
|
||||
vpl.add( 27 );
|
||||
state = 13;
|
||||
}
|
||||
|
||||
else if ( word.equals("Fet") ) {// have to look for built-in Fet before user-def
|
||||
state = 16;
|
||||
}
|
||||
|
||||
else if ( isFuncName( word ) ) {
|
||||
rememberWord = word;
|
||||
state = 14;
|
||||
}
|
||||
|
||||
else if ( isVar( word ) ) {
|
||||
// can put in entire part 1 code here
|
||||
vpl.add( 23 );
|
||||
vpl.add( scratch );
|
||||
vpl.add( processVar( word, locsList ) );
|
||||
|
||||
state = 15;
|
||||
}
|
||||
|
||||
}// state 1
|
||||
|
||||
else if ( state == 2 ) {
|
||||
if ( word.equals("*/") ) {// reached end of comment
|
||||
state = 1; // start a new command
|
||||
}
|
||||
else {// part of comment
|
||||
// consume the word and stay in state 2
|
||||
}
|
||||
}
|
||||
|
||||
else if ( state == 3 ) {
|
||||
if ( ! isFuncName( word ) ) {
|
||||
error( "[" + word + "] is not a valid function name");
|
||||
}
|
||||
|
||||
vpl.add( 1 );
|
||||
vpl.add( nextLabel(true) ); // all functions start with a 1 command
|
||||
|
||||
// note index where command 4 will be inserted
|
||||
funcStart.add( new StringIntPair( word, vpl.size() ) );
|
||||
|
||||
// note label for start of the function
|
||||
callInfo.add( new StringIntPair( word, currentLabel ) );
|
||||
|
||||
state = 5;
|
||||
}
|
||||
|
||||
// state 4 lost in change from f ( a b c ) to f a b c .
|
||||
|
||||
else if ( state == 5 ) {
|
||||
if ( word.equals( "." ) ) {
|
||||
|
||||
// make scratch cell for this function after params cells
|
||||
locsList.add( "-" );
|
||||
scratch = locsList.size()-1;
|
||||
|
||||
state = 1; // go on to body of function
|
||||
|
||||
}
|
||||
else if ( isParam( word ) ) {
|
||||
// note another parameter
|
||||
locsList.add( word );
|
||||
// loop back to stay in state 5
|
||||
}
|
||||
}
|
||||
|
||||
else if ( state == 6 ) {
|
||||
if ( word.equals( "." ) ) {
|
||||
// done creating list of globals, generate VPL code for command 32
|
||||
vpl.add( 1, globsList.size() );
|
||||
|
||||
// adjust start index of "main" to be 2 farther
|
||||
funcStart.get( 0 ).x += 2;
|
||||
|
||||
state = 1;
|
||||
}
|
||||
else if ( isParam( word ) ) {
|
||||
// add global
|
||||
globsList.add( word );
|
||||
// stay in state 6
|
||||
}
|
||||
else {
|
||||
error("[" + word + "] is not a valid global variable name");
|
||||
}
|
||||
}
|
||||
|
||||
else if ( state == 7 ) {
|
||||
if ( isLabel( word ) ) {
|
||||
// add the hole
|
||||
vpl.add( -1 );
|
||||
labelHoles.add( new StringIntPair( word, vpl.size()-1 ) );
|
||||
|
||||
state = 1;
|
||||
}
|
||||
else {
|
||||
error( "[" + word + "] is not a valid label");
|
||||
}
|
||||
}
|
||||
|
||||
else if ( state == 8 ) {
|
||||
if ( isVar( word ) ) {
|
||||
vpl.add( processVar( word, locsList ) ); // first arg
|
||||
state = 9;
|
||||
}
|
||||
else {
|
||||
error( "[" + word + "] is not a valid variable or literal");
|
||||
}
|
||||
}
|
||||
|
||||
else if ( state == 9 ) {
|
||||
if ( isVar( word ) ) {
|
||||
vpl.add( processVar( word, locsList ) ); // second arg
|
||||
state = 10;
|
||||
}
|
||||
else {
|
||||
error( "[" + word + "] is not a valid variable or literal");
|
||||
}
|
||||
}
|
||||
|
||||
else if ( state == 10 ) {
|
||||
if ( word.equals("->") ) {
|
||||
state = 100;
|
||||
}
|
||||
else {
|
||||
error("a part 1 must be followed by ->");
|
||||
}
|
||||
}
|
||||
|
||||
else if ( state == 11 ) {
|
||||
if ( isVar( word ) ) {
|
||||
vpl.add( processVar( word, locsList ) );
|
||||
state = 12;
|
||||
}
|
||||
else {
|
||||
error( "[" + word + "] is not a valid variable or literal");
|
||||
}
|
||||
}
|
||||
|
||||
else if ( state == 12 ) {
|
||||
if ( word.equals("->") ) {
|
||||
state = 100;
|
||||
}
|
||||
else {
|
||||
error("a part 1 must be followed by ->");
|
||||
}
|
||||
}
|
||||
|
||||
else if ( state == 13 ) {
|
||||
if ( word.equals("->") ) {
|
||||
vpl.add( scratch );
|
||||
|
||||
state = 100;
|
||||
}
|
||||
else {
|
||||
error("a part 1 must be followed by ->");
|
||||
}
|
||||
}
|
||||
|
||||
else if ( state == 14 ) {
|
||||
if ( isVar( word ) ) {
|
||||
vpl.add( 3 );
|
||||
vpl.add( processVar( word, locsList ) );
|
||||
// state loops to 14
|
||||
}
|
||||
else if ( word.equals("->") ) {
|
||||
// done with function call, send out the vpl code
|
||||
|
||||
vpl.add( 2 );
|
||||
vpl.add( - nextCallHole() ); // leave a hole
|
||||
callHoles.add( rememberWord );
|
||||
|
||||
// followed by command 6 for when return from doing called function
|
||||
vpl.add( 6 );
|
||||
vpl.add( scratch );
|
||||
|
||||
state = 100;
|
||||
}
|
||||
else {
|
||||
error("a part 1 must be followed by ->");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if ( state == 15 ) {
|
||||
if ( word.equals("->") ) {
|
||||
state = 100;
|
||||
}
|
||||
else {
|
||||
error("a part 1 must be followed by ->");
|
||||
}
|
||||
}
|
||||
|
||||
else if ( state == 16 ) {
|
||||
if ( isParam( word ) ) {
|
||||
vpl.add( 34 );
|
||||
vpl.add( scratch );
|
||||
vpl.add( processVar( word, globsList ) );
|
||||
|
||||
state = 17;
|
||||
}
|
||||
else {
|
||||
error("[" + word + "] is not a valid argument for Fet");
|
||||
}
|
||||
}
|
||||
|
||||
else if ( state == 17 ) {
|
||||
if ( word.equals("->") ) {
|
||||
state = 100;
|
||||
}
|
||||
else {
|
||||
error("a part 1 must be followed by ->");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// end of part 1 states
|
||||
|
||||
// begin part 2 states
|
||||
|
||||
else if ( state == 100 ) {// start state for part 2
|
||||
|
||||
if ( word.equals(".") ) {
|
||||
// do nothing with the value in scratch cell from part 1
|
||||
state = 1;
|
||||
}
|
||||
|
||||
else if ( word.equals("Prt") ) {
|
||||
// generate code to print the value in the scratch cell
|
||||
vpl.add( 28 );
|
||||
vpl.add( scratch );
|
||||
state = 1;
|
||||
}
|
||||
|
||||
else if ( word.equals("Sym") ) {
|
||||
// generate code to print the value in the scratch cell
|
||||
vpl.add( 30 );
|
||||
vpl.add( scratch );
|
||||
state = 1;
|
||||
}
|
||||
|
||||
else if ( word.equals("Ret") ) {
|
||||
// generate code to return the value in scratch cell
|
||||
vpl.add( 5 );
|
||||
vpl.add( scratch );
|
||||
state = 1;
|
||||
}
|
||||
|
||||
else if ( isParam( word ) ) {
|
||||
vpl.add( 23 );
|
||||
vpl.add( processVar( word, locsList ) );
|
||||
vpl.add( scratch );
|
||||
state = 1;
|
||||
}
|
||||
|
||||
else if ( word.equals("Jmp") ) {
|
||||
state = 101;
|
||||
}
|
||||
|
||||
else if ( word.equals("Put") ) {
|
||||
state = 102;
|
||||
}
|
||||
|
||||
else if ( word.equals("Sto") ) {
|
||||
state = 104;
|
||||
}
|
||||
|
||||
else {// unknown first word in a part 2
|
||||
error("[" + word + "] is invalid as start of a part 2");
|
||||
}
|
||||
|
||||
}// start state for part 2 (100)
|
||||
|
||||
else if ( state == 101 ) {
|
||||
if ( isLabel( word ) ) {
|
||||
vpl.add( 8 );
|
||||
vpl.add( -1 ); // hole for target of jump
|
||||
labelHoles.add( new StringIntPair( word, vpl.size()-1 ) );
|
||||
vpl.add( scratch );
|
||||
|
||||
state = 1;
|
||||
}
|
||||
else {
|
||||
error("[" + word + "] is not a valid label to use after conditional Jmp");
|
||||
}
|
||||
}
|
||||
|
||||
else if ( state == 102 ) {// processing first <var> for Put
|
||||
if ( isVar( word ) ) {// have valid first argument
|
||||
vpl.add( 25 );
|
||||
vpl.add( processVar( word, locsList ) );
|
||||
|
||||
state = 103;
|
||||
}
|
||||
else {
|
||||
error("[" + word + "] is not a valid first argument for Put");
|
||||
}
|
||||
}
|
||||
|
||||
else if ( state == 103 ) {// processing second <var> for Put
|
||||
if ( isVar( word ) ) {// have valid second argument
|
||||
vpl.add( processVar( word, locsList ) );
|
||||
|
||||
vpl.add( scratch );
|
||||
|
||||
state = 1;
|
||||
}
|
||||
else {
|
||||
error("[" + word + "] is not a valid first argument for Put");
|
||||
}
|
||||
}
|
||||
|
||||
else if ( state == 104 ) {
|
||||
if ( isParam( word ) ) {// valid argument for Sto
|
||||
// generate VPL code 33 n a
|
||||
vpl.add( 33 );
|
||||
vpl.add( processVar( word, globsList ) );
|
||||
vpl.add( scratch );
|
||||
|
||||
state = 1;
|
||||
}
|
||||
else {
|
||||
error("[" + word + "] is not a valid argument for Sto");
|
||||
}
|
||||
}
|
||||
|
||||
}// loop to scan all words in Jive source file
|
||||
|
||||
// finish off last function definition
|
||||
|
||||
finishFunctionDef();
|
||||
|
||||
System.out.println("vpl before filling call holes:");
|
||||
for ( int k=0; k<vpl.size(); k++) {
|
||||
System.out.printf("%4d %6d\n", k, vpl.get(k) );
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
// display the holes and info:
|
||||
System.out.println("Call holes:");
|
||||
for (int k=0; k<callHoles.size(); k++) {
|
||||
System.out.println( callHoles.get(k) );
|
||||
}
|
||||
|
||||
// scan vpl to line-oriented output file
|
||||
// and to doc file
|
||||
// and fill call holes
|
||||
|
||||
int funcNumber = 0;
|
||||
|
||||
int ip = 0;
|
||||
while ( ip < vpl.size() ) {
|
||||
|
||||
int op = vpl.get( ip );
|
||||
|
||||
System.out.println("at ip: " + ip + ", sending op: " + op + " to vpl file");
|
||||
|
||||
if ( op==26 || op==29 ) {// operations with 0 arguments
|
||||
output2.printf("[%5d] ", ip );
|
||||
out( op + "\n" ); ip++;
|
||||
}
|
||||
else if ( op==4 ) {
|
||||
System.out.println("function number is " + funcNumber);
|
||||
output2.println("\n------------ " + funcStart.get(funcNumber).s + " -------------");
|
||||
output2.print( allLocs.get( funcNumber ) ); funcNumber++;
|
||||
output2.println();
|
||||
output2.printf("[%5d] ", ip );
|
||||
out( op + " " ); ip++;
|
||||
out( vpl.get(ip) + "\n" ); ip++;
|
||||
}
|
||||
else if ( op== 2 ) {
|
||||
// before send to files, replace call hole with actual label
|
||||
String fName = callHoles.get( - vpl.get( ip+1 ) );
|
||||
// now search callInfo for the label
|
||||
int label = -1;
|
||||
for (int k=0; k<callInfo.size() && label < 0; k++) {
|
||||
if ( callInfo.get(k).s.equals( fName ) ) {
|
||||
label = callInfo.get(k).x;
|
||||
}
|
||||
}
|
||||
if ( label == -1 )
|
||||
error("Could not find function [" + fName + "] in callInfo");
|
||||
|
||||
output2.printf("[%5d] ", ip );
|
||||
out( op + " " ); ip++;
|
||||
out( label + "\n" ); ip++;
|
||||
}
|
||||
else if ( op==1 || op==3 || op==5 || op==6 || op==7 ||
|
||||
op==27 || op==28 || op==30 || op==32 ) {// ops with 1 arg
|
||||
output2.printf("[%5d] ", ip );
|
||||
out( op + " " ); ip++;
|
||||
out( vpl.get(ip) + "\n" ); ip++;
|
||||
}
|
||||
else if ( op==8 || op==20 || op==21 || op==22 || op==23 ||
|
||||
op==31 || op==33 || op==34 ) {// ops with 2 args
|
||||
output2.printf("[%5d] ", ip );
|
||||
out( op + " " ); ip++;
|
||||
out( vpl.get(ip) + " " ); ip++;
|
||||
out( vpl.get(ip) + "\n" ); ip++;
|
||||
}
|
||||
else if ( (9<=op && op<=19) || op==24 || op==25 ) {
|
||||
output2.printf("[%5d] ", ip );
|
||||
out( op + " " ); ip++;
|
||||
out( vpl.get(ip) + " " ); ip++;
|
||||
out( vpl.get(ip) + " " ); ip++;
|
||||
out( vpl.get(ip) + "\n" ); ip++;
|
||||
}
|
||||
else {
|
||||
output2.printf("[%5d] ", ip );
|
||||
System.out.println( op + " is invalid op code, stop translation");
|
||||
ip = vpl.size()+1; // just to stop it
|
||||
//error("[" + op + "] is an invalid operation code");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
output.close();
|
||||
output2.close();
|
||||
input.close();
|
||||
|
||||
}// main
|
||||
|
||||
// return whether w starts with lowercase,
|
||||
// followed by 0 or more letters or digits
|
||||
private static boolean isParam( String w ) {
|
||||
|
||||
if ( w.length() == 0 ) return false;
|
||||
|
||||
if ( ! ( 'a' <= w.charAt(0) && w.charAt(0) <= 'z' ) ) return false;
|
||||
|
||||
if ( w.length() ==1 ) return true;
|
||||
|
||||
for (int k=1; k<w.length(); k++) {
|
||||
char x = w.charAt(k);
|
||||
if ( !letter(x) && !digit(x) ) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// return whether w starts with uppercase,
|
||||
// followed by 0 or more letters or digits
|
||||
private static boolean isFuncName( String w ) {
|
||||
|
||||
if ( w.length() == 0 ) return false;
|
||||
|
||||
if ( ! ( 'A' <= w.charAt(0) && w.charAt(0) <= 'Z' ) ) return false;
|
||||
|
||||
if ( w.length() == 1 ) return true;
|
||||
|
||||
for (int k=1; k<w.length(); k++) {
|
||||
char x = w.charAt(k);
|
||||
if ( !letter(x) && !digit(x) ) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private static boolean isLabel( String w ) {
|
||||
if ( ! w.endsWith( ":" ) ) {
|
||||
return false;
|
||||
}
|
||||
else if ( w.length() < 2 || ! lowercase( w.charAt(0) ) ) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
for (int k=1; k<w.length()-1; k++) {
|
||||
char x = w.charAt(k);
|
||||
if ( !letter(x) && !digit(x) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean lowercase( char x ) {
|
||||
return 'a'<=x && x<='z';
|
||||
}
|
||||
|
||||
private static boolean uppercase( char x ) {
|
||||
return 'A'<=x && x<='Z';
|
||||
}
|
||||
|
||||
private static boolean letter( char x ) {
|
||||
return lowercase(x) || uppercase(x);
|
||||
}
|
||||
|
||||
private static boolean digit( char x ) {
|
||||
return '0'<=x && x<='9';
|
||||
}
|
||||
|
||||
private static String[] bifs2 = { "Add", "Sub", "Mult", "Quot", "Rem",
|
||||
"Eq", "NotEq", "Less", "LessEq",
|
||||
"And", "Or",
|
||||
"Get" };
|
||||
|
||||
private static String[] bifs1 = { "Not", "Opp", "New" };
|
||||
|
||||
private static int findBIF2( String word ) {
|
||||
int loc = -1;
|
||||
for (int k=0; k<bifs2.length && loc < 0; k++) {
|
||||
if ( word.equals( bifs2[k] ) ) {
|
||||
loc = k;
|
||||
}
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
private static int findBIF1( String word ) {
|
||||
int loc = -1;
|
||||
for (int k=0; k<bifs1.length && loc < 0; k++) {
|
||||
if ( word.equals( bifs1[k] ) ) {
|
||||
loc = k;
|
||||
}
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
// return whether word is an int literal or
|
||||
// a parameter
|
||||
private static boolean isVar( String word ) {
|
||||
return isParam(word) || isInt(word);
|
||||
}
|
||||
|
||||
// given word which is a variable name or an int
|
||||
// literal, search for it in list (which will be
|
||||
// either locsList or globsList) and if found, just
|
||||
// return its location, otherwise append to end,
|
||||
// and if is an int literal, add to litsList the 22 command to
|
||||
// create the literal, and return its location
|
||||
private static int processVar( String word, ArrayList<String> list ) {
|
||||
|
||||
for (int k=0; k<list.size(); k++) {
|
||||
if ( word.equals( list.get(k) ) ) {
|
||||
// found word in the list
|
||||
return k;
|
||||
}
|
||||
}
|
||||
|
||||
// if still here, word was not found, process it further
|
||||
if ( isInt(word) ) {// is an int literal, not in list
|
||||
list.add( word );
|
||||
return list.size()-1;
|
||||
}
|
||||
else {// is a newly discovered variable
|
||||
list.add( word );
|
||||
return list.size()-1;
|
||||
}
|
||||
|
||||
}// processVar
|
||||
|
||||
private static boolean isInt( String s ) {
|
||||
boolean result;
|
||||
try {
|
||||
int x = Integer.parseInt( s );
|
||||
result = true;
|
||||
}
|
||||
catch( Exception e ) {
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void showLocals() {
|
||||
for (int k=0; k<locsList.size(); k++) {
|
||||
System.out.printf("%4d %s\n", k, locsList.get(k) );
|
||||
}
|
||||
}
|
||||
|
||||
// find item in list with string matching w, and return
|
||||
// its matching integer,
|
||||
// or report error
|
||||
private static int findString( String w, ArrayList<StringIntPair> list ) {
|
||||
for (int k=0; k<list.size(); k++) {
|
||||
if (list.get(k).s.equals(w) ) {
|
||||
return list.get(k).x;
|
||||
}
|
||||
}
|
||||
// if still here, didn't find
|
||||
error("could not find info with string [" + w + "]");
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static void out( String s ) {
|
||||
output.print( s );
|
||||
output2.print( s );
|
||||
}
|
||||
|
||||
private static void error( String message ) {
|
||||
System.out.println( message );
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
public static void main2(String[] args) {
|
||||
String w = "A37";
|
||||
System.out.println("func?" + isFuncName( w ) );
|
||||
System.out.println("var?" + isVar( w ) );
|
||||
System.out.println("param?" + isParam( w ) );
|
||||
System.out.println("label?" + isLabel( w ) );
|
||||
}
|
||||
|
||||
// do everything that needs to be done when realize
|
||||
// we've reached the end of a function definition
|
||||
private static void finishFunctionDef() {
|
||||
|
||||
System.out.println("Start finishFunctionDef:");
|
||||
|
||||
System.out.println(" vpl at start: " );
|
||||
showVPL();
|
||||
|
||||
showTables();
|
||||
|
||||
// get name of function being finished, just for convenience
|
||||
String funcName = funcStart.get( funcStart.size()-1).s;
|
||||
|
||||
// debug output
|
||||
System.out.println("Local cells for function just finished, " + funcName + ":" );
|
||||
showLocals();
|
||||
|
||||
// for output2, store locsList for this function
|
||||
String s = "";
|
||||
for (int k=0; k<locsList.size(); k++) {
|
||||
s += k + ": " + locsList.get(k) + "\n";
|
||||
}
|
||||
allLocs.add( s );
|
||||
|
||||
// insert command 4 with correct count
|
||||
|
||||
// first find number of params by searching for scratch cell named "-"
|
||||
int numParams = -1;
|
||||
for (int k=0; k<locsList.size() && numParams < 0; k++) {
|
||||
if ( locsList.get(k).equals("-") ) {
|
||||
numParams = k;
|
||||
}
|
||||
}
|
||||
|
||||
if (numParams == -1) {
|
||||
error("Something wrong in finishFunctionDef, no scratch cell found");
|
||||
}
|
||||
|
||||
// get index in vpl for insertion of command 4
|
||||
// (just 2 more than where the label for the function starts)
|
||||
int start = funcStart.get( funcStart.size()-1 ).x;
|
||||
|
||||
// insert the command 4
|
||||
vpl.add( start, 4 );
|
||||
vpl.add( start+1, locsList.size()-numParams );
|
||||
|
||||
// insert the command 22's for each literal in locsList
|
||||
int count = 2; // have to count the two cells used by command 4
|
||||
int index = start + 2;
|
||||
|
||||
for (int k=0; k<locsList.size(); k++) {
|
||||
if ( isInt( locsList.get(k) ) ) {// is a literal
|
||||
vpl.add( index, 22 ); index++;
|
||||
vpl.add( index, k ); index++;
|
||||
vpl.add( index, Integer.parseInt( locsList.get(k) ) ); index++;
|
||||
|
||||
count += 3; // inserting 3 additional values for each int literal
|
||||
}
|
||||
}
|
||||
|
||||
//System.out.println("finishFunctionDef, vpl after insertions: " );
|
||||
//showVPL();
|
||||
|
||||
// shift hole locations due to insertions of command 4 and command 22's
|
||||
for (int k=0; k<labelHoles.size(); k++) {
|
||||
StringIntPair pair = labelHoles.get(k);
|
||||
pair.x += count;
|
||||
}
|
||||
|
||||
System.out.println("after shifting locations for insertions, tables are: ");
|
||||
showTables();
|
||||
|
||||
// fill in all label holes
|
||||
for (int k=0; k<labelHoles.size(); k++) {
|
||||
StringIntPair pair = labelHoles.get(k);
|
||||
// find location of this label from info:
|
||||
int loc = -1;
|
||||
for (int j=0; j<labelInfo.size() && loc < 0; j++) {
|
||||
if ( labelInfo.get(j).s.equals( pair.s ) ) {// found it
|
||||
loc = labelInfo.get(j).x;
|
||||
}
|
||||
}
|
||||
|
||||
// important error check---Jive program might be missing the label
|
||||
if ( loc == -1 )
|
||||
error("couldn't find label [" + pair.s + "]");
|
||||
|
||||
System.out.println("filling label hole [" + pair.s + "," + pair.x + "] with " + loc );
|
||||
vpl.set( pair.x, loc );
|
||||
}
|
||||
|
||||
}// finishFunctionDef
|
||||
|
||||
private static void showVPL() {
|
||||
for (int k=0; k<vpl.size(); k++) {
|
||||
System.out.println(k + ": " + vpl.get(k) );
|
||||
}
|
||||
}
|
||||
|
||||
private static void showTables() {
|
||||
System.out.println("Label holes: ");
|
||||
for (int k=0; k<labelHoles.size(); k++) {
|
||||
System.out.println(labelHoles.get(k));
|
||||
}
|
||||
|
||||
System.out.println("Label info: ");
|
||||
for (int k=0; k<labelInfo.size(); k++) {
|
||||
System.out.println(labelInfo.get(k));
|
||||
}
|
||||
|
||||
System.out.println("Call holes: ");
|
||||
for (int k=0; k<callHoles.size(); k++) {
|
||||
System.out.println(callHoles.get(k));
|
||||
}
|
||||
System.out.println("Function starts: ");
|
||||
for (int k=0; k<funcStart.size(); k++) {
|
||||
System.out.println(funcStart.get(k));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// label generating scheme:
|
||||
|
||||
// functions are numbered while being scanned
|
||||
private static int functionNumber = 0;
|
||||
private static int spread = 1000;
|
||||
private static int currentLabel = 0;
|
||||
|
||||
// generate next label, incrementing by 1
|
||||
// if not starting a function, otherwise
|
||||
// starting with multiple of spread
|
||||
private static int nextLabel( boolean startingFunction ) {
|
||||
if ( startingFunction ) {
|
||||
functionNumber++;
|
||||
currentLabel = spread*functionNumber;
|
||||
return currentLabel;
|
||||
}
|
||||
else {
|
||||
currentLabel++;
|
||||
return currentLabel;
|
||||
}
|
||||
}
|
||||
|
||||
// call hole stuff:
|
||||
private static int currentCallHole = 0;
|
||||
private static int nextCallHole() {
|
||||
currentCallHole++;
|
||||
return currentCallHole;
|
||||
}
|
||||
|
||||
}// Jive
|
||||
Executable
+67
@@ -0,0 +1,67 @@
|
||||
Have begin implementation of Jive, working on state 8.
|
||||
|
||||
Through Tuesday, 9/11 made good progress, but still
|
||||
some problems.
|
||||
|
||||
JiveVPL.save can be copied to JiveVPL.class to
|
||||
allow running my VPL interpreter (version that
|
||||
takes the memory produced by Jive.java) on
|
||||
a given VPL file produced by Jive.
|
||||
|
||||
As of Sunday, 9/16/2018, at noon, Jive is initially
|
||||
implemented, testing on a few test cases
|
||||
(may still have errors, of course, but is useable
|
||||
for demonstrating the desired translation from
|
||||
Jive to VPL)
|
||||
|
||||
All the tests in the folder Tests seem to be working.
|
||||
|
||||
To run my VPL simulator on a VPL program produced by
|
||||
Jive, you need to compile IntPair.java and
|
||||
then
|
||||
|
||||
copy VPL.save to VPL.class
|
||||
|
||||
(I'm hiding my VPL source code so Project 1 isn't ruined).
|
||||
|
||||
September 17:
|
||||
|
||||
in class we wrote a little Jive program, named "sept17",
|
||||
that was supposed to ask the user for n and
|
||||
then store in an array n followed by the first n
|
||||
Fibonacci numbers (we left off the first 1, which was
|
||||
fine for our purposes), and then
|
||||
display that array.
|
||||
|
||||
When we translated the Jive program to VPL and then
|
||||
ran the VPL program, the behavior was weird.
|
||||
|
||||
After class I found the following errors in the
|
||||
Jive program (yay---not in Jive.java, my translator):
|
||||
|
||||
first, we forgot to put a Halt command in the
|
||||
"main" at the end, so after doing whatever work
|
||||
was in "main", it continued into the next function,
|
||||
or something. At any rate, it was bad, and was
|
||||
cured by putting in the Halt command.
|
||||
|
||||
second, nothing was displaying. I figured out
|
||||
after a while that we had forgotten to store
|
||||
the value n at offset 0 in the array. When I
|
||||
put in the code:
|
||||
|
||||
size -> Put array 0,
|
||||
|
||||
the program behaved as desired, except at the end
|
||||
it crashed. After some work, I realized that I
|
||||
(with no one else to blame), should have done
|
||||
|
||||
n -> Put array 0
|
||||
|
||||
With that change, sept17 worked perfectly
|
||||
(up to n==45---for larger n, integer
|
||||
overflow produced nonsensical results at the
|
||||
end the sequence).
|
||||
|
||||
The punchline is, we didn't find a problem with
|
||||
Jive.java!
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
/* pair up a string and
|
||||
an int,
|
||||
used for holes and info
|
||||
*/
|
||||
|
||||
public class StringIntPair {
|
||||
|
||||
public String s;
|
||||
public int x;
|
||||
|
||||
public StringIntPair( String sIn, int xIn ) {
|
||||
s = sIn;
|
||||
x = xIn;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "[" + s + "," + x + "]";
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
/* do some function
|
||||
definitions and calls
|
||||
in various orders
|
||||
*/
|
||||
|
||||
Keys -> x
|
||||
|
||||
F 2 x -> a
|
||||
|
||||
a -> Prt
|
||||
NL
|
||||
|
||||
Halt
|
||||
|
||||
Def G a b c .
|
||||
|
||||
Mult a b -> x
|
||||
Mult x c -> x
|
||||
|
||||
x -> Ret
|
||||
|
||||
Def F a b .
|
||||
|
||||
Add a 1 -> c
|
||||
Sub b 1 -> d
|
||||
|
||||
G c d 5 -> r
|
||||
|
||||
r -> Ret
|
||||
|
||||
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
/* main function
|
||||
for computing
|
||||
factorial of
|
||||
input value
|
||||
*/
|
||||
|
||||
Keys -> n
|
||||
Fact n -> f
|
||||
f -> Prt NL
|
||||
Halt
|
||||
|
||||
Def Fact n .
|
||||
|
||||
Less n 2 -> Jmp small:
|
||||
|
||||
Sub n 1 -> temp
|
||||
Fact temp -> f
|
||||
Mult n f -> Ret
|
||||
|
||||
small:
|
||||
1 -> Ret
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
[ 0] 1 1000
|
||||
|
||||
------------ ? -------------
|
||||
0: -
|
||||
1: n
|
||||
2: f
|
||||
|
||||
[ 2] 4 3
|
||||
[ 4] 27 0
|
||||
[ 6] 23 1 0
|
||||
[ 9] 3 1
|
||||
[ 11] 2 2000
|
||||
[ 13] 6 0
|
||||
[ 15] 23 2 0
|
||||
[ 18] 23 0 2
|
||||
[ 21] 28 0
|
||||
[ 23] 29
|
||||
[ 24] 26
|
||||
[ 25] 1 2000
|
||||
|
||||
------------ Fact -------------
|
||||
0: n
|
||||
1: -
|
||||
2: 2
|
||||
3: 1
|
||||
4: temp
|
||||
5: f
|
||||
|
||||
[ 27] 4 5
|
||||
[ 29] 22 2 2
|
||||
[ 32] 22 3 1
|
||||
[ 35] 16 1 0 2
|
||||
[ 39] 8 2001 1
|
||||
[ 42] 10 1 0 3
|
||||
[ 46] 23 4 1
|
||||
[ 49] 3 4
|
||||
[ 51] 2 2000
|
||||
[ 53] 6 1
|
||||
[ 55] 23 5 1
|
||||
[ 58] 11 1 0 5
|
||||
[ 62] 5 1
|
||||
[ 64] 1 2001
|
||||
[ 66] 23 1 3
|
||||
[ 69] 5 1
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
1 1000
|
||||
4 3
|
||||
27 0
|
||||
23 1 0
|
||||
3 1
|
||||
2 2000
|
||||
6 0
|
||||
23 2 0
|
||||
23 0 2
|
||||
28 0
|
||||
29
|
||||
26
|
||||
1 2000
|
||||
4 5
|
||||
22 2 2
|
||||
22 3 1
|
||||
16 1 0 2
|
||||
8 2001 1
|
||||
10 1 0 3
|
||||
23 4 1
|
||||
3 4
|
||||
2 2000
|
||||
6 1
|
||||
23 5 1
|
||||
11 1 0 5
|
||||
5 1
|
||||
1 2001
|
||||
23 1 3
|
||||
5 1
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
Keys -> x
|
||||
|
||||
top:
|
||||
|
||||
x -> Prt NL
|
||||
|
||||
Eq x 1 -> Jmp exit:
|
||||
|
||||
Rem x 2 -> r
|
||||
Eq r 0 -> Jmp even:
|
||||
Jmp odd:
|
||||
|
||||
even:
|
||||
Quot x 2 -> x
|
||||
|
||||
Jmp top:
|
||||
|
||||
odd:
|
||||
Mult 3 x -> x
|
||||
Add x 1 -> x
|
||||
|
||||
Jmp top:
|
||||
|
||||
exit:
|
||||
|
||||
Halt
|
||||
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
/* unit tests, sort of,
|
||||
on global stuff
|
||||
*/
|
||||
|
||||
Globs a b c .
|
||||
|
||||
17 -> Sto a
|
||||
23 -> Sto b
|
||||
41 -> Sto c
|
||||
|
||||
Fet a -> Prt NL
|
||||
Fet b -> Prt NL
|
||||
Fet c -> Prt NL
|
||||
|
||||
Halt
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
|
||||
GetList -> a
|
||||
PutList a -> .
|
||||
|
||||
Halt
|
||||
|
||||
/*--------------------------------------*/
|
||||
Def GetList .
|
||||
|
||||
Keys -> size
|
||||
|
||||
Add size 1 -> objSize /* 1 extra cell for size */
|
||||
|
||||
New objSize -> list
|
||||
|
||||
size -> Put list 0 /* store size at index 0 */
|
||||
|
||||
1 -> index
|
||||
|
||||
top:
|
||||
|
||||
Less size index -> Jmp exit:
|
||||
Keys -> input
|
||||
input -> Put list index
|
||||
Add index 1 -> index
|
||||
|
||||
Jmp top:
|
||||
|
||||
exit:
|
||||
|
||||
list -> Ret
|
||||
|
||||
/*--------------------------------------*/
|
||||
Def PutList list .
|
||||
|
||||
0 -> index /* get size of list */
|
||||
Get list index -> size
|
||||
|
||||
1 -> index
|
||||
|
||||
top:
|
||||
|
||||
Less size index -> Jmp exit:
|
||||
Get list index -> value
|
||||
value -> Prt 32 -> Sym
|
||||
Add index 1 -> index
|
||||
|
||||
Jmp top:
|
||||
exit:
|
||||
|
||||
0 -> Ret
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
ShowSyms -> .
|
||||
Halt
|
||||
|
||||
Def ShowSyms .
|
||||
|
||||
65 -> Sym
|
||||
33 -> Sym
|
||||
97 -> Sym
|
||||
NL
|
||||
0 -> Ret
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
Keys -> row
|
||||
Keys -> col
|
||||
|
||||
PasTri row col -> Prt
|
||||
|
||||
Halt
|
||||
|
||||
Def PasTri row col .
|
||||
|
||||
Eq col 0 -> temp1
|
||||
Eq row col -> temp2
|
||||
Or temp1 temp2 -> easy
|
||||
easy -> Jmp easy:
|
||||
|
||||
Sub col 1 -> upLeft
|
||||
Sub row 1 -> rowAbove
|
||||
PasTri rowAbove upLeft -> res1
|
||||
PasTri rowAbove col -> res2
|
||||
Add res1 res2 -> Ret
|
||||
|
||||
easy:
|
||||
1 -> Ret
|
||||
Executable
+71
@@ -0,0 +1,71 @@
|
||||
Globs p rowSize .
|
||||
|
||||
Main -> .
|
||||
|
||||
/* ------------------------------------ */
|
||||
Def Pastri2 row col .
|
||||
|
||||
GetArray2d row col -> temp
|
||||
|
||||
NotEq temp 0 -> Jmp easy:
|
||||
|
||||
Eq col 0 -> Jmp onEdge:
|
||||
Eq col row -> Jmp onEdge:
|
||||
|
||||
Sub col 1 -> col1
|
||||
Sub row 1 -> row1
|
||||
|
||||
Pastri2 row1 col1 -> temp1
|
||||
Pastri2 row1 col -> temp2
|
||||
Add temp1 temp2 -> result
|
||||
PutArray2d row col result -> .
|
||||
result -> Ret
|
||||
|
||||
onEdge:
|
||||
PutArray2d row col 1 -> .
|
||||
1 -> Ret
|
||||
|
||||
easy:
|
||||
temp -> Ret
|
||||
|
||||
/* ------------------------------------ */
|
||||
Def Main .
|
||||
|
||||
Keys -> row
|
||||
Keys -> col
|
||||
|
||||
Add row 1 -> rowsize
|
||||
Add col 1 -> colsize
|
||||
Mult rowsize colsize -> n
|
||||
New n -> Sto p
|
||||
|
||||
colsize -> Sto rowSize
|
||||
|
||||
Pastri2 row col -> Prt NL
|
||||
|
||||
Halt
|
||||
|
||||
/* ------------------------------------ */
|
||||
Def GetArray2d r c .
|
||||
|
||||
Fet p -> array
|
||||
Fet rowSize -> cols
|
||||
|
||||
Mult r cols -> index
|
||||
Add c index -> index
|
||||
|
||||
Get array index -> result
|
||||
result -> Ret
|
||||
|
||||
/* ------------------------------------ */
|
||||
Def PutArray2d r c value .
|
||||
|
||||
Fet p -> array
|
||||
Fet rowSize -> cols
|
||||
|
||||
Mult r cols -> index
|
||||
Add c index -> index
|
||||
|
||||
value -> Put array index
|
||||
|
||||
0 -> Ret
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
Keys -> x
|
||||
Keys -> y
|
||||
Keys -> z
|
||||
|
||||
Add3 x y z -> Prt NL
|
||||
|
||||
Halt
|
||||
|
||||
Def Add3 a b c .
|
||||
|
||||
Add a b -> x
|
||||
Add x c -> x
|
||||
x -> Ret
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
Globs a b c .
|
||||
|
||||
17 -> Sto b
|
||||
|
||||
Fet b -> Prt
|
||||
|
||||
Halt
|
||||
Executable
BIN
Binary file not shown.
Executable
+77
@@ -0,0 +1,77 @@
|
||||
/* ask the user for n,
|
||||
create in an array the
|
||||
first n fibonacci numbers
|
||||
(1,1,2,3,5,8,...)
|
||||
total them up and display
|
||||
*/
|
||||
|
||||
Keys -> n
|
||||
|
||||
Fib n -> array
|
||||
|
||||
PutList array -> .
|
||||
|
||||
/* forgot this on Sept. 17,
|
||||
caused weird behavior,
|
||||
running into the next function?!
|
||||
*/
|
||||
Halt
|
||||
|
||||
/* given n,
|
||||
create a heap array with n+1 spaces,
|
||||
store n in space 0,
|
||||
compute fib numbers and store them in
|
||||
spaces 1, 2, ... n
|
||||
Return starting index of the array
|
||||
*/
|
||||
|
||||
Def Fib n .
|
||||
|
||||
Add n 1 -> size
|
||||
New size -> array
|
||||
|
||||
/* forgot this on Sept. 17---
|
||||
have to store n at
|
||||
offset 0
|
||||
*/
|
||||
n -> Put array 0
|
||||
|
||||
0 -> temp1
|
||||
1 -> temp2
|
||||
|
||||
1 -> k
|
||||
|
||||
top:
|
||||
Less n k -> Jmp exit:
|
||||
Add temp1 temp2 -> temp
|
||||
temp -> Put array k
|
||||
temp2 -> temp1
|
||||
Get array k -> temp2
|
||||
|
||||
Add k 1 -> k
|
||||
|
||||
Jmp top:
|
||||
exit:
|
||||
|
||||
array -> Ret
|
||||
|
||||
/*--------------------------------------*/
|
||||
Def PutList list .
|
||||
|
||||
0 -> index /* get size of list */
|
||||
Get list index -> size
|
||||
|
||||
1 -> index
|
||||
|
||||
top:
|
||||
|
||||
Less size index -> Jmp exit:
|
||||
Get list index -> value
|
||||
value -> Prt 32 -> Sym
|
||||
Add index 1 -> index
|
||||
|
||||
Jmp top:
|
||||
exit:
|
||||
|
||||
0 -> Ret
|
||||
|
||||
Executable
+101
@@ -0,0 +1,101 @@
|
||||
[ 0] 1 1000
|
||||
|
||||
------------ ? -------------
|
||||
0: -
|
||||
1: n
|
||||
2: array
|
||||
|
||||
[ 2] 4 3
|
||||
[ 4] 27 0
|
||||
[ 6] 23 1 0
|
||||
[ 9] 3 1
|
||||
[ 11] 2 2000
|
||||
[ 13] 6 0
|
||||
[ 15] 23 2 0
|
||||
[ 18] 3 2
|
||||
[ 20] 2 3000
|
||||
[ 22] 6 0
|
||||
[ 24] 26
|
||||
[ 25] 1 2000
|
||||
|
||||
------------ Fib -------------
|
||||
0: n
|
||||
1: -
|
||||
2: 1
|
||||
3: size
|
||||
4: array
|
||||
5: 0
|
||||
6: temp1
|
||||
7: temp2
|
||||
8: k
|
||||
9: temp
|
||||
|
||||
[ 27] 4 9
|
||||
[ 29] 22 2 1
|
||||
[ 32] 22 5 0
|
||||
[ 35] 9 1 0 2
|
||||
[ 39] 23 3 1
|
||||
[ 42] 31 1 3
|
||||
[ 45] 23 4 1
|
||||
[ 48] 23 1 0
|
||||
[ 51] 25 4 5 1
|
||||
[ 55] 23 1 5
|
||||
[ 58] 23 6 1
|
||||
[ 61] 23 1 2
|
||||
[ 64] 23 7 1
|
||||
[ 67] 23 1 2
|
||||
[ 70] 23 8 1
|
||||
[ 73] 1 2001
|
||||
[ 75] 16 1 0 8
|
||||
[ 79] 8 2002 1
|
||||
[ 82] 9 1 6 7
|
||||
[ 86] 23 9 1
|
||||
[ 89] 23 1 9
|
||||
[ 92] 25 4 8 1
|
||||
[ 96] 23 1 7
|
||||
[ 99] 23 6 1
|
||||
[ 102] 24 1 4 8
|
||||
[ 106] 23 7 1
|
||||
[ 109] 9 1 8 2
|
||||
[ 113] 23 8 1
|
||||
[ 116] 7 2001
|
||||
[ 118] 1 2002
|
||||
[ 120] 23 1 4
|
||||
[ 123] 5 1
|
||||
[ 125] 1 3000
|
||||
|
||||
------------ PutList -------------
|
||||
0: list
|
||||
1: -
|
||||
2: 0
|
||||
3: index
|
||||
4: size
|
||||
5: 1
|
||||
6: value
|
||||
7: 32
|
||||
|
||||
[ 127] 4 7
|
||||
[ 129] 22 2 0
|
||||
[ 132] 22 5 1
|
||||
[ 135] 22 7 32
|
||||
[ 138] 23 1 2
|
||||
[ 141] 23 3 1
|
||||
[ 144] 24 1 0 3
|
||||
[ 148] 23 4 1
|
||||
[ 151] 23 1 5
|
||||
[ 154] 23 3 1
|
||||
[ 157] 1 3001
|
||||
[ 159] 16 1 4 3
|
||||
[ 163] 8 3002 1
|
||||
[ 166] 24 1 0 3
|
||||
[ 170] 23 6 1
|
||||
[ 173] 23 1 6
|
||||
[ 176] 28 1
|
||||
[ 178] 23 1 7
|
||||
[ 181] 30 1
|
||||
[ 183] 9 1 3 5
|
||||
[ 187] 23 3 1
|
||||
[ 190] 7 3001
|
||||
[ 192] 1 3002
|
||||
[ 194] 23 1 2
|
||||
[ 197] 5 1
|
||||
Executable
+71
@@ -0,0 +1,71 @@
|
||||
1 1000
|
||||
4 3
|
||||
27 0
|
||||
23 1 0
|
||||
3 1
|
||||
2 2000
|
||||
6 0
|
||||
23 2 0
|
||||
3 2
|
||||
2 3000
|
||||
6 0
|
||||
26
|
||||
1 2000
|
||||
4 9
|
||||
22 2 1
|
||||
22 5 0
|
||||
9 1 0 2
|
||||
23 3 1
|
||||
31 1 3
|
||||
23 4 1
|
||||
23 1 0
|
||||
25 4 5 1
|
||||
23 1 5
|
||||
23 6 1
|
||||
23 1 2
|
||||
23 7 1
|
||||
23 1 2
|
||||
23 8 1
|
||||
1 2001
|
||||
16 1 0 8
|
||||
8 2002 1
|
||||
9 1 6 7
|
||||
23 9 1
|
||||
23 1 9
|
||||
25 4 8 1
|
||||
23 1 7
|
||||
23 6 1
|
||||
24 1 4 8
|
||||
23 7 1
|
||||
9 1 8 2
|
||||
23 8 1
|
||||
7 2001
|
||||
1 2002
|
||||
23 1 4
|
||||
5 1
|
||||
1 3000
|
||||
4 7
|
||||
22 2 0
|
||||
22 5 1
|
||||
22 7 32
|
||||
23 1 2
|
||||
23 3 1
|
||||
24 1 0 3
|
||||
23 4 1
|
||||
23 1 5
|
||||
23 3 1
|
||||
1 3001
|
||||
16 1 4 3
|
||||
8 3002 1
|
||||
24 1 0 3
|
||||
23 6 1
|
||||
23 1 6
|
||||
28 1
|
||||
23 1 7
|
||||
30 1
|
||||
9 1 3 5
|
||||
23 3 1
|
||||
7 3001
|
||||
1 3002
|
||||
23 1 2
|
||||
5 1
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
public class IntPair
|
||||
{
|
||||
public int first, second;
|
||||
|
||||
public IntPair( int a, int b )
|
||||
{ first = a; second = b; }
|
||||
|
||||
}
|
||||
Executable
+309
@@ -0,0 +1,309 @@
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Scanner;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
public class VPL
|
||||
{
|
||||
static String fileName;
|
||||
static Scanner keys;
|
||||
|
||||
static int max;
|
||||
static int[] mem;
|
||||
static int ip, bp, sp, rv, hp, numPassed, gp;
|
||||
static int step;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
keys = new Scanner( System.in );
|
||||
|
||||
if( args.length != 2 ) {
|
||||
System.out.println("Usage: java VPL <vpl program> <memory size>" );
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
fileName = args[0];
|
||||
|
||||
max = Integer.parseInt( args[1] );
|
||||
mem = new int[max];
|
||||
|
||||
// load the program into the front part of
|
||||
// memory
|
||||
Scanner input = new Scanner( new File( fileName ) );
|
||||
String line;
|
||||
StringTokenizer st;
|
||||
int opcode;
|
||||
|
||||
ArrayList<IntPair> labels, holes;
|
||||
labels = new ArrayList<IntPair>();
|
||||
holes = new ArrayList<IntPair>();
|
||||
int label;
|
||||
|
||||
// load the code
|
||||
|
||||
int k=0;
|
||||
while ( input.hasNextLine() ) {
|
||||
line = input.nextLine();
|
||||
System.out.println("parsing line [" + line + "]");
|
||||
if( line != null )
|
||||
{// extract any tokens
|
||||
st = new StringTokenizer( line );
|
||||
if( st.countTokens() > 0 )
|
||||
{// have a token, so must be an instruction (as opposed to empty line)
|
||||
|
||||
opcode = Integer.parseInt(st.nextToken());
|
||||
|
||||
// load the instruction into memory:
|
||||
|
||||
if( opcode == labelCode )
|
||||
{// note index that comes where label would go
|
||||
label = Integer.parseInt(st.nextToken());
|
||||
labels.add( new IntPair( label, k ) );
|
||||
}
|
||||
else if( opcode == noopCode ){
|
||||
}
|
||||
else
|
||||
{// opcode actually gets stored
|
||||
mem[k] = opcode; k++;
|
||||
|
||||
if( opcode == callCode || opcode == jumpCode ||
|
||||
opcode == condJumpCode )
|
||||
{// note the hole immediately after the opcode to be filled in later
|
||||
label = Integer.parseInt( st.nextToken() );
|
||||
mem[k] = label; holes.add( new IntPair( k, label ) );
|
||||
++k;
|
||||
}
|
||||
|
||||
// load correct number of arguments (following label, if any):
|
||||
for( int j=0; j<numArgs(opcode); ++j )
|
||||
{
|
||||
mem[k] = Integer.parseInt(st.nextToken());
|
||||
++k;
|
||||
}
|
||||
|
||||
}// not a label
|
||||
|
||||
}// have a token, so must be an instruction
|
||||
}// have a line
|
||||
}// loop to load code
|
||||
|
||||
//System.out.println("after first scan:");
|
||||
//showMem( 0, k-1 );
|
||||
|
||||
// fill in all the holes:
|
||||
int index;
|
||||
for( int m=0; m<holes.size(); ++m )
|
||||
{
|
||||
label = holes.get(m).second;
|
||||
index = -1;
|
||||
for( int n=0; n<labels.size(); ++n )
|
||||
if( labels.get(n).first == label )
|
||||
index = labels.get(n).second;
|
||||
mem[ holes.get(m).first ] = index;
|
||||
}
|
||||
|
||||
System.out.println("after replacing labels:");
|
||||
showMem( 0, k-1 );
|
||||
|
||||
// initialize registers:
|
||||
bp = k; sp = k+2; ip = 0; rv = -1; hp = max;
|
||||
numPassed = 0;
|
||||
|
||||
int codeEnd = bp-1;
|
||||
|
||||
System.out.println("Code is " );
|
||||
showMem( 0, codeEnd );
|
||||
|
||||
gp = codeEnd + 1;
|
||||
|
||||
// start execution:
|
||||
boolean done = false;
|
||||
int op, a=0, b=0, c=0;
|
||||
int actualNumArgs;
|
||||
|
||||
int step = 0;
|
||||
|
||||
int oldIp = 0;
|
||||
|
||||
// repeatedly execute a single operation
|
||||
// *****************************************************************
|
||||
|
||||
do {
|
||||
|
||||
/* // show details of current step
|
||||
System.out.println("--------------------------");
|
||||
System.out.println("Step of execution with IP = " + ip + " opcode: " +
|
||||
mem[ip] +
|
||||
" bp = " + bp + " sp = " + sp + " hp = " + hp + " rv = " + rv );
|
||||
System.out.println(" chunk of code: " + mem[ip] + " " +
|
||||
mem[ip+1] + " " + mem[ip+2] + " " + mem[ip+3] );
|
||||
System.out.println("--------------------------");
|
||||
System.out.println( " memory from " + (codeEnd+1) + " up: " );
|
||||
showMem( codeEnd+1, sp+3 );
|
||||
System.out.println("hit <enter> to go on" );
|
||||
keys.nextLine();
|
||||
*/
|
||||
|
||||
oldIp = ip;
|
||||
|
||||
op = mem[ ip ]; ip++;
|
||||
// extract the args into a, b, c for convenience:
|
||||
a = -1; b = -2; c = -3;
|
||||
|
||||
// numArgs is wrong for these guys, need one more!
|
||||
if( op == callCode || op == jumpCode ||
|
||||
op == condJumpCode )
|
||||
{
|
||||
actualNumArgs = numArgs( op ) + 1;
|
||||
}
|
||||
else
|
||||
actualNumArgs = numArgs( op );
|
||||
|
||||
if( actualNumArgs == 1 )
|
||||
{ a = mem[ ip ]; ip++; }
|
||||
else if( actualNumArgs == 2 )
|
||||
{ a = mem[ ip ]; ip++; b = mem[ ip ]; ip++; }
|
||||
else if( actualNumArgs == 3 )
|
||||
{ a = mem[ ip ]; ip++; b = mem[ ip ]; ip++; c = mem[ ip ]; ip++; }
|
||||
|
||||
// implement all operations here:
|
||||
// ********************************************
|
||||
|
||||
// put your work right here!
|
||||
|
||||
if ( op == oppCode ) {
|
||||
mem[ bp+2 + a ] = - mem[ bp+2 + b ];
|
||||
}
|
||||
|
||||
|
||||
else
|
||||
{
|
||||
System.out.println("Fatal error: unknown opcode [" + op + "]" );
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
step++;
|
||||
|
||||
}while( !done );
|
||||
|
||||
|
||||
}// main
|
||||
|
||||
// use symbolic names for all opcodes:
|
||||
|
||||
// op to produce comment
|
||||
private static final int noopCode = 0;
|
||||
|
||||
// ops involved with registers
|
||||
private static final int labelCode = 1;
|
||||
private static final int callCode = 2;
|
||||
private static final int passCode = 3;
|
||||
private static final int allocCode = 4;
|
||||
private static final int returnCode = 5; // return a means "return and put
|
||||
// copy of value stored in cell a in register rv
|
||||
private static final int getRetvalCode = 6;//op a means "copy rv into cell a"
|
||||
private static final int jumpCode = 7;
|
||||
private static final int condJumpCode = 8;
|
||||
|
||||
// arithmetic ops
|
||||
private static final int addCode = 9;
|
||||
private static final int subCode = 10;
|
||||
private static final int multCode = 11;
|
||||
private static final int divCode = 12;
|
||||
private static final int remCode = 13;
|
||||
private static final int equalCode = 14;
|
||||
private static final int notEqualCode = 15;
|
||||
private static final int lessCode = 16;
|
||||
private static final int lessEqualCode = 17;
|
||||
private static final int andCode = 18;
|
||||
private static final int orCode = 19;
|
||||
private static final int notCode = 20;
|
||||
private static final int oppCode = 21;
|
||||
|
||||
// ops involving transfer of data
|
||||
private static final int litCode = 22; // litCode a b means "cell a gets b"
|
||||
private static final int copyCode = 23;// copy a b means "cell a gets cell b"
|
||||
private static final int getCode = 24; // op a b means "cell a gets
|
||||
// contents of cell whose
|
||||
// index is stored in b"
|
||||
private static final int putCode = 25; // op a b means "put contents
|
||||
// of cell b in cell whose offset is stored in cell a"
|
||||
|
||||
// system-level ops:
|
||||
private static final int haltCode = 26;
|
||||
private static final int inputCode = 27;
|
||||
private static final int outputCode = 28;
|
||||
private static final int newlineCode = 29;
|
||||
private static final int symbolCode = 30;
|
||||
private static final int newCode = 31;
|
||||
|
||||
// global variable ops:
|
||||
private static final int allocGlobalCode = 32;
|
||||
private static final int toGlobalCode = 33;
|
||||
private static final int fromGlobalCode = 34;
|
||||
|
||||
// debug ops:
|
||||
private static final int debugCode = 35;
|
||||
|
||||
// return the number of arguments after the opcode,
|
||||
// except ops that have a label return number of arguments
|
||||
// after the label, which always comes immediately after
|
||||
// the opcode
|
||||
private static int numArgs( int opcode )
|
||||
{
|
||||
// highlight specially behaving operations
|
||||
if( opcode == labelCode ) return 1; // not used
|
||||
else if( opcode == jumpCode ) return 0; // jump label
|
||||
else if( opcode == condJumpCode ) return 1; // condJump label expr
|
||||
else if( opcode == callCode ) return 0; // call label
|
||||
|
||||
// for all other ops, lump by count:
|
||||
|
||||
else if( opcode==noopCode ||
|
||||
opcode==haltCode ||
|
||||
opcode==newlineCode ||
|
||||
opcode==debugCode
|
||||
)
|
||||
return 0; // op
|
||||
|
||||
else if( opcode==passCode || opcode==allocCode ||
|
||||
opcode==returnCode || opcode==getRetvalCode ||
|
||||
opcode==inputCode ||
|
||||
opcode==outputCode || opcode==symbolCode ||
|
||||
opcode==allocGlobalCode
|
||||
)
|
||||
return 1; // op arg1
|
||||
|
||||
else if( opcode==notCode || opcode==oppCode ||
|
||||
opcode==litCode || opcode==copyCode || opcode==newCode ||
|
||||
opcode==toGlobalCode || opcode==fromGlobalCode
|
||||
|
||||
)
|
||||
return 2; // op arg1 arg2
|
||||
|
||||
else if( opcode==addCode || opcode==subCode || opcode==multCode ||
|
||||
opcode==divCode || opcode==remCode || opcode==equalCode ||
|
||||
opcode==notEqualCode || opcode==lessCode ||
|
||||
opcode==lessEqualCode || opcode==andCode ||
|
||||
opcode==orCode || opcode==getCode || opcode==putCode
|
||||
)
|
||||
return 3;
|
||||
|
||||
else
|
||||
{
|
||||
System.out.println("Fatal error: unknown opcode [" + opcode + "]" );
|
||||
System.exit(1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}// numArgs
|
||||
|
||||
private static void showMem( int a, int b )
|
||||
{
|
||||
for( int k=a; k<=b; ++k )
|
||||
{
|
||||
System.out.println( k + ": " + mem[k] );
|
||||
}
|
||||
}// showMem
|
||||
|
||||
}// VPL
|
||||
@@ -0,0 +1,17 @@
|
||||
32 1 allocate one global cell named "0"
|
||||
|
||||
4 10 make plenty of scratch space in the "main" stack frame
|
||||
|
||||
22 0 17 local cell 0 <- constant 17
|
||||
33 0 0 global cell 0 <- local cell 0
|
||||
|
||||
27 1 local cell 1 <- input from keyboard
|
||||
|
||||
34 2 0 local cell 2 <- global cell 0
|
||||
|
||||
9 3 1 2 local cell 3 <- input + copy of global value
|
||||
|
||||
28 3 display the final answer
|
||||
29 newline
|
||||
|
||||
26 halt
|
||||
@@ -0,0 +1,33 @@
|
||||
0 Here's the map between local cells and names:
|
||||
0 Local cell: Name:
|
||||
0 0 n (input value)
|
||||
0 1 2 (literal)
|
||||
0 2 1 (literal)
|
||||
0 3 n % 2
|
||||
|
||||
4 4 allocate space for 4 local cells
|
||||
|
||||
27 0 local cell 0 <- input value (n)
|
||||
|
||||
22 1 2 local cell 1 <- literal 2
|
||||
22 2 1 local cell 2 <- literal 1
|
||||
|
||||
13 3 0 1 local cell 3 <- n % 2 (conveniently 0 or 1
|
||||
|
||||
8 1001 3 if n%2 is not 0 jump to 1001
|
||||
|
||||
0 case that n is even
|
||||
|
||||
28 1 display 2 to say that n is even
|
||||
29
|
||||
|
||||
7 1002 hop over code for odd case
|
||||
|
||||
1 1001 case that n is odd
|
||||
|
||||
28 2 display 1 to say that n is odd
|
||||
29
|
||||
|
||||
1 1002
|
||||
|
||||
26
|
||||
@@ -0,0 +1,28 @@
|
||||
0 Local cell: Name:
|
||||
0 0 n (display 1..n)
|
||||
0 1 j (index in loop
|
||||
0 2 1 (literal)
|
||||
0 3 n < j
|
||||
|
||||
4 4 allocate space for 4 local cells
|
||||
|
||||
27 0 n = keyboard input
|
||||
|
||||
22 1 1 j <- 1
|
||||
22 2 1
|
||||
|
||||
1 1001 top of loop
|
||||
|
||||
16 3 0 1 if n < j exit loop
|
||||
8 1002 3
|
||||
|
||||
28 1 println j
|
||||
29
|
||||
|
||||
9 1 1 2 j = j+1
|
||||
|
||||
7 1001 go up to top of loop
|
||||
|
||||
1 1002 exit loop
|
||||
|
||||
26 halt
|
||||
@@ -0,0 +1,43 @@
|
||||
0 Local cell: Name:
|
||||
0 0 x
|
||||
0 1 1
|
||||
0 2 2
|
||||
0 3 3
|
||||
0 4 x==1, x % 2
|
||||
|
||||
4 5 allocate local cells in main stack frame
|
||||
|
||||
22 1 1 set the literals
|
||||
22 2 2
|
||||
22 3 3
|
||||
|
||||
27 0 x <- input
|
||||
|
||||
1 1001 top of loop
|
||||
14 4 0 1 local cell 4 <- x == 1
|
||||
|
||||
8 1002 4 if x==1 exit loop
|
||||
|
||||
28 0 println x
|
||||
29
|
||||
|
||||
13 4 0 2 local cell 4 <- x%2, so is 0 if x even, 1 if x odd
|
||||
|
||||
8 1003 4 if x is odd jump
|
||||
|
||||
0 didn't jump so x is even
|
||||
12 0 0 2 x <- x / 2
|
||||
|
||||
7 1004 skip over x odd code
|
||||
1 1003 start of x odd case
|
||||
|
||||
11 0 0 3 x <- x*3
|
||||
9 0 0 1 x <- x+1
|
||||
|
||||
1 1004
|
||||
|
||||
7 1001 jump to top of loop
|
||||
|
||||
1 1002 exit loop
|
||||
|
||||
26
|
||||
@@ -0,0 +1,23 @@
|
||||
4 3
|
||||
27 0
|
||||
3 0
|
||||
2 1001
|
||||
6 1
|
||||
28 1
|
||||
29
|
||||
26
|
||||
|
||||
1 1001
|
||||
4 6
|
||||
22 2 2
|
||||
22 1 1
|
||||
16 6 0 2
|
||||
8 2001 6
|
||||
10 3 0 1
|
||||
3 3
|
||||
2 1001
|
||||
6 4
|
||||
11 5 0 4
|
||||
5 5
|
||||
1 2001
|
||||
5 1
|
||||
@@ -0,0 +1,103 @@
|
||||
0 main subprogram
|
||||
0 cells used:
|
||||
0
|
||||
0 0 holds starting index of list
|
||||
0 1 holds n=# of items in list
|
||||
|
||||
4 2
|
||||
|
||||
27 1
|
||||
|
||||
3 1
|
||||
2 100000
|
||||
|
||||
6 0
|
||||
|
||||
28 0
|
||||
29
|
||||
|
||||
3 0
|
||||
2 200000
|
||||
|
||||
29
|
||||
|
||||
26
|
||||
|
||||
0 list input subprogram
|
||||
0 cells used
|
||||
|
||||
0 0 parameter (n=desired number of items in list)
|
||||
0 1 literal 1
|
||||
0 2 n+1
|
||||
0 3 index (k) in loop
|
||||
0 4 holds starting point (a) of list
|
||||
0 5 boolean result of n < k
|
||||
0 6 input value
|
||||
|
||||
1 100000
|
||||
|
||||
4 6
|
||||
|
||||
22 1 1 create 1
|
||||
9 2 0 1 cell 2 = n+1
|
||||
|
||||
31 4 2 a = new int[n+1]
|
||||
|
||||
22 3 0 k=0
|
||||
25 4 3 0 a[k] = n
|
||||
|
||||
22 3 1 k=1
|
||||
|
||||
1 102 top of loop
|
||||
|
||||
16 5 0 3 cell 5 = n < k
|
||||
8 101 5 if n < k jump to 101
|
||||
|
||||
27 6 cell 6 = input value
|
||||
|
||||
25 4 3 6 a[k] = input value
|
||||
|
||||
9 3 3 1 k=k+1
|
||||
|
||||
7 102 jump to top of loop
|
||||
1 101 exit point of loop
|
||||
|
||||
5 4 return a
|
||||
|
||||
0 list display subprogram
|
||||
0 cells used:
|
||||
0 0 index of start of object (a)
|
||||
0 1 literal 1
|
||||
0 2 number of items in list (n)
|
||||
0 3 index k
|
||||
0 4 ascii code for a space (32)
|
||||
0 5 n < k
|
||||
0 6 temp
|
||||
|
||||
1 200000
|
||||
|
||||
4 5
|
||||
|
||||
22 1 1
|
||||
22 4 32
|
||||
|
||||
22 3 0 k=0
|
||||
24 2 0 3 n=a[0]
|
||||
|
||||
22 3 1 k=1
|
||||
|
||||
1 201 top of loop
|
||||
16 5 2 3 cell 5 = n < k
|
||||
8 202 5 if n < k exit loop
|
||||
|
||||
24 6 0 3 temp = a[k]
|
||||
|
||||
28 6 print temp
|
||||
30 4 print a space
|
||||
|
||||
9 3 3 1 k=k+1
|
||||
|
||||
7 201 jump to top of loop
|
||||
1 202 exit loop
|
||||
|
||||
5 0 return (value stored in RV irrelevant)
|
||||
@@ -0,0 +1,32 @@
|
||||
4 3
|
||||
27 0
|
||||
27 1
|
||||
3 0
|
||||
3 1
|
||||
2 101
|
||||
6 2
|
||||
28 2
|
||||
29
|
||||
26
|
||||
1 101
|
||||
4 6
|
||||
22 2 1
|
||||
22 5 0
|
||||
14 6 1 5
|
||||
8 102 6
|
||||
14 6 1 0
|
||||
8 102 6
|
||||
10 3 0 2
|
||||
10 4 1 2
|
||||
3 3
|
||||
3 4
|
||||
2 101
|
||||
6 6
|
||||
3 3
|
||||
3 1
|
||||
2 101
|
||||
6 7
|
||||
9 6 6 7
|
||||
5 6
|
||||
1 102
|
||||
5 2
|
||||
Executable
+93
@@ -0,0 +1,93 @@
|
||||
4 5
|
||||
|
||||
|
||||
|
||||
27 0
|
||||
|
||||
28 0
|
||||
|
||||
29
|
||||
|
||||
|
||||
|
||||
22 0 23
|
||||
|
||||
22 1 17
|
||||
|
||||
22 3 0
|
||||
|
||||
22 4 1
|
||||
|
||||
|
||||
|
||||
9 2 0 1
|
||||
|
||||
28 2
|
||||
|
||||
29
|
||||
|
||||
|
||||
|
||||
10 2 0 1
|
||||
|
||||
28 2
|
||||
|
||||
29
|
||||
|
||||
|
||||
|
||||
11 2 0 1
|
||||
|
||||
28 2
|
||||
|
||||
29
|
||||
|
||||
|
||||
|
||||
12 2 0 1
|
||||
|
||||
28 2
|
||||
|
||||
29
|
||||
|
||||
|
||||
|
||||
13 2 0 1
|
||||
|
||||
28 2
|
||||
|
||||
29
|
||||
|
||||
|
||||
|
||||
14 2 0 1
|
||||
|
||||
28 2
|
||||
|
||||
14 2 1 1
|
||||
|
||||
28 2
|
||||
|
||||
29
|
||||
|
||||
|
||||
|
||||
15 2 1 1
|
||||
|
||||
28 2
|
||||
|
||||
15 2 0 1
|
||||
|
||||
28 2
|
||||
|
||||
29
|
||||
|
||||
|
||||
|
||||
16 2 1 0
|
||||
|
||||
28 2
|
||||
|
||||
16 2 0 1
|
||||
|
||||
28 2
|
||||
Reference in New Issue
Block a user