From 4ad31c0570c4add0a104aa04a953e0e3a6ba0a5d Mon Sep 17 00:00:00 2001 From: Mike Cifelli Date: Wed, 7 Dec 2016 16:40:08 -0500 Subject: [PATCH] Additional refactoring for eclipse --- .classpath | 2 + .project | 13 + build.xml | 8 +- error/ErrorManager.java | 50 ---- error/package.html | 3 - eval/APPLY.java | 74 ------ eval/ATOM.java | 38 --- eval/CAR.java | 46 ---- eval/CDR.java | 46 ---- eval/COND.java | 73 ------ eval/CONS.java | 44 ---- eval/DEFUN.java | 82 ------ eval/DIVIDE.java | 60 ----- eval/EQ.java | 45 ---- eval/EQUAL.java | 58 ---- eval/EQUALSP.java | 55 ---- eval/EVAL.java | 251 ------------------ eval/EXIT.java | 26 -- eval/FUNCALL.java | 31 --- eval/GREATERP.java | 55 ---- eval/LAMBDA.java | 108 -------- eval/LENGTH.java | 69 ----- eval/LESSP.java | 55 ---- eval/LET.java | 116 -------- eval/LIST.java | 40 --- eval/LISTP.java | 38 --- eval/LOAD.java | 87 ------ eval/LambdaExpression.java | 73 ------ eval/LispFunction.java | 44 ---- eval/MINUS.java | 60 ----- eval/MULTIPLY.java | 34 --- eval/NULL.java | 38 --- eval/PLUS.java | 34 --- eval/PRINT.java | 40 --- eval/QUOTE.java | 47 ---- eval/SETF.java | 112 -------- eval/SYMBOL_FUNCTION.java | 65 ----- eval/SymbolTable.java | 90 ------- eval/UDFunction.java | 122 --------- eval/package.html | 4 - main/LispInterpreter.java | 91 ------- main/LispInterpreter2.java | 50 ---- main/LispParserDriver.java | 65 ----- main/LispScannerDriver.java | 69 ----- main/package.html | 3 - parser/Atom.java | 46 ---- parser/Cons.java | 111 -------- parser/LispNumber.java | 67 ----- parser/LispParser.java | 192 -------------- parser/LispString.java | 34 --- parser/Nil.java | 104 -------- parser/SExpression.java | 122 --------- parser/Symbol.java | 37 --- parser/package.html | 4 - scanner/LispFilterStream.java | 160 ------------ scanner/LispScanner.java | 320 ----------------------- scanner/Token.java | 126 --------- scanner/package.html | 4 - src/scanner/LispFilterStream.class | Bin 682 -> 829 bytes src/scanner/LispFilterStream.java | 148 ++--------- test/scanner/LispFilterStreamTester.java | 17 +- 61 files changed, 39 insertions(+), 4067 deletions(-) delete mode 100644 error/ErrorManager.java delete mode 100644 error/package.html delete mode 100644 eval/APPLY.java delete mode 100644 eval/ATOM.java delete mode 100644 eval/CAR.java delete mode 100644 eval/CDR.java delete mode 100644 eval/COND.java delete mode 100644 eval/CONS.java delete mode 100644 eval/DEFUN.java delete mode 100644 eval/DIVIDE.java delete mode 100644 eval/EQ.java delete mode 100644 eval/EQUAL.java delete mode 100644 eval/EQUALSP.java delete mode 100644 eval/EVAL.java delete mode 100644 eval/EXIT.java delete mode 100644 eval/FUNCALL.java delete mode 100644 eval/GREATERP.java delete mode 100644 eval/LAMBDA.java delete mode 100644 eval/LENGTH.java delete mode 100644 eval/LESSP.java delete mode 100644 eval/LET.java delete mode 100644 eval/LIST.java delete mode 100644 eval/LISTP.java delete mode 100644 eval/LOAD.java delete mode 100644 eval/LambdaExpression.java delete mode 100644 eval/LispFunction.java delete mode 100644 eval/MINUS.java delete mode 100644 eval/MULTIPLY.java delete mode 100644 eval/NULL.java delete mode 100644 eval/PLUS.java delete mode 100644 eval/PRINT.java delete mode 100644 eval/QUOTE.java delete mode 100644 eval/SETF.java delete mode 100644 eval/SYMBOL_FUNCTION.java delete mode 100644 eval/SymbolTable.java delete mode 100644 eval/UDFunction.java delete mode 100644 eval/package.html delete mode 100644 main/LispInterpreter.java delete mode 100644 main/LispInterpreter2.java delete mode 100644 main/LispParserDriver.java delete mode 100644 main/LispScannerDriver.java delete mode 100644 main/package.html delete mode 100644 parser/Atom.java delete mode 100644 parser/Cons.java delete mode 100644 parser/LispNumber.java delete mode 100644 parser/LispParser.java delete mode 100644 parser/LispString.java delete mode 100644 parser/Nil.java delete mode 100644 parser/SExpression.java delete mode 100644 parser/Symbol.java delete mode 100644 parser/package.html delete mode 100644 scanner/LispFilterStream.java delete mode 100644 scanner/LispScanner.java delete mode 100644 scanner/Token.java delete mode 100644 scanner/package.html diff --git a/.classpath b/.classpath index 1938c4d..b52a479 100644 --- a/.classpath +++ b/.classpath @@ -1,10 +1,12 @@ + + diff --git a/.project b/.project index d1cb933..883a7f1 100644 --- a/.project +++ b/.project @@ -15,6 +15,19 @@ + + org.eclipse.ui.externaltools.ExternalToolBuilder + + + LaunchConfigHandle + <project>/.externalToolBuilders/Ant_Builder.launch + + + incclean + true + + + org.eclipse.wst.common.project.facet.core.nature diff --git a/build.xml b/build.xml index 5756cd6..a28a61a 100644 --- a/build.xml +++ b/build.xml @@ -1,11 +1,12 @@ - + + @@ -16,11 +17,8 @@ - + includeantruntime="false" /> diff --git a/error/ErrorManager.java b/error/ErrorManager.java deleted file mode 100644 index 255c61d..0000000 --- a/error/ErrorManager.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter Phase 1 - Lexical Analysis - */ - -package error; - -import java.text.MessageFormat; - -/** - * ErrorManager is an error handling class for a Lisp interpreter. - */ -public class ErrorManager { - - /** - * The lowest "criticality" level of an error that will cause the currently - * running program to terminate. - */ - public static final int CRITICAL_LEVEL = 3; - - public static final String ANSI_RESET = "\u001B[0m"; - public static final String ANSI_RED = "\u001B[31m"; - public static final String ANSI_YELLOW = "\u001B[33m"; - public static final String ANSI_PURPLE = "\u001B[35m"; - - /** - * Prints out the specified error message to the console and decides - * whether or not to terminate the currently running program. - * - * @param message - * the error message - * @param level - * the "criticality" level of the error - * @postcondition - * If level >= CRITICAL_LEVEL the currently running - * program has been terminated. - */ - public static void generateError(String message, int level) { - String color = (level >= CRITICAL_LEVEL) ? ANSI_PURPLE : ANSI_RED; - String formattedMessage = MessageFormat.format("{0}error: {1}{2}", color, message, ANSI_RESET); - - System.out.println(formattedMessage); - - if (level >= CRITICAL_LEVEL) { - System.exit(1); - } - } - -} diff --git a/error/package.html b/error/package.html deleted file mode 100644 index b8e7489..0000000 --- a/error/package.html +++ /dev/null @@ -1,3 +0,0 @@ - - Provides a class for managing errors in the Lisp Interpreter. - diff --git a/eval/APPLY.java b/eval/APPLY.java deleted file mode 100644 index f7fa819..0000000 --- a/eval/APPLY.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * APPLY represents the APPLY function in Lisp. - */ -public class APPLY extends LispFunction { - - /** - * Call APPLY with the specified argument list. - * - * @param argList - * the list of arguments to be sent to APPLY (MUST BE A PROPER LIST) - * @return - * the result of evaluating APPLY on argList - */ - public static SExpression apply(Cons argList) { - return new APPLY().call(argList); - } - - // The number of arguments that APPLY takes. - private static final int NUM_ARGS = 2; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to APPLY - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("APPLY"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to APPLY: " + originalSExpr; - - throw new RuntimeException(errMsg); - } - - SExpression car = argList.getCar(); // function name - Cons cdr = (Cons) argList.getCdr(); - SExpression cadr = cdr.getCar(); // argument list - - // make sure the second argument is a list - if (cadr.listp()) { - LispFunction function = EVAL.lookupFunction(car.toString()); - - if (function == null) { - // check if the car of the list is a lambda expression - if (car.functionp()) { - function = ((LambdaExpression) car).getFunction(); - } else if (LAMBDA.isLambdaExpression(car)) { - Cons lexpr = (Cons) car; - - function = LAMBDA.createFunction(lexpr); - } else { - throw new RuntimeException("undefined function " + car); - } - } - - // apply the given function to the given argument list - return function.call((Cons) cadr); - } - - // the second argument is not a list - throw new RuntimeException("APPLY: " + cadr + " is not a list"); - } - -} diff --git a/eval/ATOM.java b/eval/ATOM.java deleted file mode 100644 index fbee068..0000000 --- a/eval/ATOM.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * ATOM represents the ATOM function in Lisp. - */ -public class ATOM extends LispFunction { - - // The number of arguments that ATOM takes. - private static final int NUM_ARGS = 1; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to ATOM - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("ATOM"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to ATOM: " + originalSExpr; - - throw new RuntimeException(errMsg); - } - - SExpression arg = argList.getCar(); - - return (arg.atomp() ? Symbol.T : Nil.getUniqueInstance()); - } - -} diff --git a/eval/CAR.java b/eval/CAR.java deleted file mode 100644 index 3b75078..0000000 --- a/eval/CAR.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * CAR represents the CAR function in Lisp. - */ -public class CAR extends LispFunction { - - // The number of arguments that CAR takes. - private static final int NUM_ARGS = 1; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to CAR - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("CAR"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to CAR: " + originalSExpr; - - throw new RuntimeException(errMsg); - } - - SExpression argCar = argList.getCar(); - - // make sure that the argument is a list - if (argCar.listp()) { - Cons arg = (Cons) argCar; - - return arg.getCar(); - } - - // the argument is not a list - throw new RuntimeException("CAR: " + argCar + " is not a list"); - } - -} diff --git a/eval/CDR.java b/eval/CDR.java deleted file mode 100644 index 0cc281e..0000000 --- a/eval/CDR.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * CDR represents the CDR function in Lisp. - */ -public class CDR extends LispFunction { - - // The number of arguments that CDR takes. - private static final int NUM_ARGS = 1; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to CDR - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("CDR"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to CDR: " + originalSExpr; - - throw new RuntimeException(errMsg); - } - - SExpression argCar = argList.getCar(); - - // make sure that the argument is a list - if (argCar.listp()) { - Cons arg = (Cons) argCar; - - return arg.getCdr(); - } - - // the argument is not a list - throw new RuntimeException("CDR: " + argCar + " is not a list"); - } - -} diff --git a/eval/COND.java b/eval/COND.java deleted file mode 100644 index 9bd4e79..0000000 --- a/eval/COND.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * COND represents the COND form in Lisp. - */ -public class COND extends LispFunction { - - public SExpression call(Cons argList) { - if (argList.nullp()) { - // return NIL if there are were no arguments passed to COND - return Nil.getUniqueInstance(); - } - - SExpression argCar = argList.getCar(); // first clause - Cons argCdr = (Cons) argList.getCdr(); // list of remaining clauses - - // make sure the first clause is a list and is not NIL - if (argCar.consp()) { - Cons clause = (Cons) argCar; - SExpression test = EVAL.eval(clause.getCar()); - - if (test != Nil.getUniqueInstance()) { - // the car of this clause is true, so we evaluate its cdr - - SExpression cdr = clause.getCdr(); - SExpression retval = test; - - // evaluate all the S-expressions in the cdr of the clause - while (cdr.consp()) { - retval = EVAL.eval(((Cons) cdr).getCar()); - cdr = ((Cons) cdr).getCdr(); - } - - // return the value of the last S-expression evaluated - return retval; - } - - // the car of this clause is false, so we test any remaining - // clauses - - // check if the list of remaining clauses is a list and is not NIL - if (argCdr.consp()) { - return call(argCdr); - } - - // there are no remaining clauses, so we return NIL - return Nil.getUniqueInstance(); - } - - throw new RuntimeException("COND: clause " + argCar + - " should be a list"); - } - - /** - * Determine if the arguments passed to this Lisp function should be - * evaluated. - * - * @return - * false - */ - public boolean evaluateArguments() { - return false; - } - -} diff --git a/eval/CONS.java b/eval/CONS.java deleted file mode 100644 index db967a7..0000000 --- a/eval/CONS.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * CONS represents the CONS function in Lisp. - */ -public class CONS extends LispFunction { - - // The number of arguments that CONS takes. - private static final int NUM_ARGS = 2; - - public Cons call(Cons argList) { - // retrieve the number of arguments passed to CONS - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("CONS"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to CONS: " + originalSExpr; - - throw new RuntimeException(errMsg); - } - - // the car of the CONS cell we are going to create - SExpression argOne = argList.getCar(); - - Cons cdr = (Cons) argList.getCdr(); - - // the cdr of the CONS cell we are going to create - SExpression argTwo = cdr.getCar(); - - return new Cons(argOne, argTwo); - } - -} diff --git a/eval/DEFUN.java b/eval/DEFUN.java deleted file mode 100644 index c435737..0000000 --- a/eval/DEFUN.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 2 - */ - -package eval; - -import parser.*; -import java.util.HashMap; - -/** - * DEFUN represents the DEFUN form in Lisp. - */ -public class DEFUN extends LispFunction { - - // The minimum number of arguments that DEFUN takes. - private static final int MIN_ARGS = 3; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to DEFUN - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength < MIN_ARGS) { - Cons originalSExpr = new Cons(new Symbol("DEFUN"), argList); - String errMsg = "too few arguments given to DEFUN: " + - originalSExpr; - - throw new RuntimeException(errMsg); - } - - SExpression name = argList.getCar(); // name of the function - - // make sure the function name is a symbol - if (! name.symbolp()) { - throw new RuntimeException("DEFUN: " + name + " is not a symbol"); - } - - Cons cdr = (Cons) argList.getCdr(); - SExpression cadr = cdr.getCar(); - - // make sure the list of arguments (lambda list) is a proper list - if (! cadr.listp()) { - throw new RuntimeException("DEFUN: " + cadr + " is not a list"); - } else if (EVAL.isDotted((Cons) cadr)) { - throw new RuntimeException("DEFUN: " + cadr + - " is not a proper list"); - } - - Cons lambdaList = (Cons) cadr; // lambda list of the function - - // list of S-expressions making up the body of the function - Cons body = (Cons) cdr.getCdr(); - - HashMap functionTable = EVAL.getFunctionTable(); - - // give a warning if this function has already been defined - if (functionTable.containsKey(name.toString())) { - System.out.println("WARNING: redefining function " + - name.toString()); - } - - // place the function in the function table - functionTable.put(name.toString(), - new UDFunction(name.toString(), lambdaList, body)); - - return name; - } - - /** - * Determine if the arguments passed to this Lisp function should be - * evaluated. - * - * @return - * false - */ - public boolean evaluateArguments() { - return false; - } - -} diff --git a/eval/DIVIDE.java b/eval/DIVIDE.java deleted file mode 100644 index 0794f57..0000000 --- a/eval/DIVIDE.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * DIVIDE represents the '/' function in Lisp. - */ -public class DIVIDE extends LispFunction { - - public SExpression call(Cons argList) { - // make sure we have received at least one argument - if (argList.nullp()) { - Cons originalSExpr = new Cons(new Symbol("/"), argList); - - throw new RuntimeException("too few arguments given to /: " + - originalSExpr); - } - - SExpression argFirst = argList.getCar(); - Cons argRest = (Cons) argList.getCdr(); - - // make sure that the first argument is a number - if (argFirst.numberp()) { - LispNumber num1 = (LispNumber) argFirst; - - if (argRest.nullp()) { - // there is only one argument, so return the multiplicative - // inverse of the number - return new LispNumber(1 / num1.getValue()); - } - - SExpression argSecond = argRest.getCar(); - - // make sure that the next argument is a number as well - if (argSecond.numberp()) { - LispNumber num2 = (LispNumber) argSecond; - LispNumber quotient = new LispNumber(num1.getValue() / - num2.getValue()); - SExpression argCddr = argRest.getCdr(); - - if (argCddr.consp()) { - return call(new Cons(quotient, argCddr)); - } - - return quotient; - } - - throw new RuntimeException("/: " + argSecond + " is not a number"); - } - - throw new RuntimeException("/: " + argFirst + " is not a number"); - } - -} diff --git a/eval/EQ.java b/eval/EQ.java deleted file mode 100644 index 0227525..0000000 --- a/eval/EQ.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * EQ represents the EQ function in Lisp. - */ -public class EQ extends LispFunction { - - // The number of arguments that EQ takes. - private static final int NUM_ARGS = 2; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to EQ - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("EQ"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to EQ: " + originalSExpr; - - throw new RuntimeException(errMsg); - } - - SExpression argOne = argList.getCar(); // first argument - Cons cdr = (Cons) argList.getCdr(); - SExpression argTwo = cdr.getCar(); // second argumnet - - if (argOne.atomp() && argTwo.atomp()) { - return ((argOne.toString().equals(argTwo.toString())) - ? Symbol.T : Nil.getUniqueInstance()); - } - - return ((argOne == argTwo) ? Symbol.T : Nil.getUniqueInstance()); - } - -} diff --git a/eval/EQUAL.java b/eval/EQUAL.java deleted file mode 100644 index 0e4e02e..0000000 --- a/eval/EQUAL.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * EQUAL represents the EQUAL function in Lisp. - */ -public class EQUAL extends LispFunction { - - // The number of arguments that EQUAL takes. - private static final int NUM_ARGS = 2; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to EQUAL - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("EQUAL"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to EQUAL: " + originalSExpr; - - throw new RuntimeException(errMsg); - } - - SExpression argOne = argList.getCar(); // first argument - Cons cdr = (Cons) argList.getCdr(); - SExpression argTwo = cdr.getCar(); // second argumnet - - if (argOne.consp() && argTwo.consp()) { - Cons listOne = (Cons) argOne; - Cons listTwo = (Cons) argTwo; - SExpression listOneCar = listOne.getCar(); - SExpression listTwoCar = listTwo.getCar(); - SExpression listOneCdr = listOne.getCdr(); - SExpression listTwoCdr = listTwo.getCdr(); - - SExpression carEqual = - call(new Cons(listOneCar, LIST.makeList(listTwoCar))); - SExpression cdrEqual = - call(new Cons(listOneCdr, LIST.makeList(listTwoCdr))); - - return (((carEqual == Symbol.T) && (cdrEqual == Symbol.T)) - ? Symbol.T : Nil.getUniqueInstance()); - } - - return ((argOne.toString().equals(argTwo.toString())) - ? Symbol.T : Nil.getUniqueInstance()); - } - -} diff --git a/eval/EQUALSP.java b/eval/EQUALSP.java deleted file mode 100644 index 1c6fb65..0000000 --- a/eval/EQUALSP.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * EQUALSP represents the '=' function in Lisp. - */ -public class EQUALSP extends LispFunction { - - public SExpression call(Cons argList) { - // make sure we have received at least one argument - if (argList.nullp()) { - Cons originalSExpr = new Cons(new Symbol("="), argList); - - throw new RuntimeException("too few arguments given to =: " + - originalSExpr); - } - - SExpression firstArg = argList.getCar(); - Cons argRest = (Cons) argList.getCdr(); - - // make sure that the first argument is a number - if (firstArg.numberp()) { - LispNumber num1 = (LispNumber) firstArg; - - if (argRest.nullp()) { - return Symbol.T; - } - - SExpression secondArg = argRest.getCar(); - - // make sure that the second argument is a number as well - if (secondArg.numberp()) { - LispNumber num2 = (LispNumber) secondArg; - - if (num1.getValue() == num2.getValue()) { - return call(argRest); - } - - return Nil.getUniqueInstance(); - } - - throw new RuntimeException("=: " + secondArg + " is not a number"); - } - - throw new RuntimeException("=: " + firstArg + " is not a number"); - } - -} diff --git a/eval/EVAL.java b/eval/EVAL.java deleted file mode 100644 index 2eacfc2..0000000 --- a/eval/EVAL.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; -import java.util.HashMap; - -/** - * EVAL represents the EVAL function in Lisp. - */ -public class EVAL extends LispFunction { - - // A table to contain all the built-in and user-defined Lisp functions. - private static HashMap functionTable = - new HashMap(); - - static { - // place all of the built-in functions into the function table - functionTable.put("*", new MULTIPLY()); - functionTable.put("+", new PLUS()); - functionTable.put("-", new MINUS()); - functionTable.put("/", new DIVIDE()); - functionTable.put("<", new LESSP()); - functionTable.put("=", new EQUALSP()); - functionTable.put(">", new GREATERP()); - functionTable.put("APPLY", new APPLY()); - functionTable.put("ATOM", new ATOM()); - functionTable.put("CAR", new CAR()); - functionTable.put("CDR", new CDR()); - functionTable.put("COND", new COND()); - functionTable.put("CONS", new CONS()); - functionTable.put("DEFUN", new DEFUN()); - functionTable.put("EQ", new EQ()); - functionTable.put("EQUAL", new EQUAL()); - functionTable.put("EVAL", new EVAL()); - functionTable.put("EXIT", new EXIT()); - functionTable.put("FIRST", new CAR()); - functionTable.put("FUNCALL", new FUNCALL()); - functionTable.put("GREATERP", new GREATERP()); - functionTable.put("LAMBDA", new LAMBDA()); - functionTable.put("LENGTH", new LENGTH()); - functionTable.put("LET", new LET()); - functionTable.put("LIST", new LIST()); - functionTable.put("LISTP", new LISTP()); - functionTable.put("LOAD", new LOAD()); - functionTable.put("NULL", new NULL()); - functionTable.put("PRINT", new PRINT()); - functionTable.put("QUOTE", new QUOTE()); - functionTable.put("REST", new CDR()); - functionTable.put("SETF", new SETF()); - functionTable.put("SYMBOL-FUNCTION", new SYMBOL_FUNCTION()); - } - - /** - * Retrieve the function table. - * - * @return - * the function table - */ - public static HashMap getFunctionTable() { - return functionTable; - } - - /** - * Look up a function by its name. - * - * @param functionName - * the name of the function to look up - * @return - * the function with the name functionName if it exists; null - * otherwise - */ - public static LispFunction lookupFunction(String functionName) { - return functionTable.get(functionName); - } - - /** - * Look up a symbol's value using its name. - * - * @param symbolName - * the name of the symbol to look up (must not be null) - * @return - * the value of symbolName if it has one; null otherwise - */ - public static SExpression lookupSymbol(String symbolName) { - if (symbolName.equals("NIL")) { - return Nil.getUniqueInstance(); - } else if (symbolName.equals("T")) { - return Symbol.T; - } else if (symbolName.startsWith(":")) { - return new Symbol(symbolName); - } - - return SETF.lookup(symbolName); - } - - /** - * Determine if the given list is dotted. - * - * @param list - * the list to be tested (must not be null) - * @return - * true if list is dotted; false - * otherwise - */ - public static boolean isDotted(Cons list) { - if (list.nullp()) { - return false; - } - - SExpression cdr = list.getCdr(); - - if (cdr.listp()) { - return isDotted((Cons) cdr); - } - - // the cdr of 'list' is not a list, therefore it is dotted - return true; - } - - /** - * Evaluate the given S-expression. - * - * @param sexpr - * the S-expression to evaluate - * @return - * the value of sexpr - */ - public static SExpression eval(SExpression sexpr) { - Cons expList = LIST.makeList(sexpr); - EVAL evalFunction = new EVAL(); - - return evalFunction.call(expList); - } - - // The number of arguments that EVAL takes. - private static final int NUM_ARGS = 1; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to EVAL - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("EVAL"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to EVAL: " + originalSExpr; - - throw new RuntimeException(errMsg); - } - - SExpression arg = argList.getCar(); - - if (arg.listp()) { - if (arg.consp()) { - return evaluateList((Cons) arg); - } - - return arg; // 'arg' is NIL - } - - if (arg.symbolp()) { - SExpression symbolValue = lookupSymbol(arg.toString()); - - if (symbolValue != null) { - return symbolValue; - } - - throw new RuntimeException("variable " + arg + " has no value"); - } - - return arg; // 'arg' is a NUMBER or a STRING - } - - // Evaluate the specified list. - // - // Parameters: list - the list to evaluate - // Returns: the value of 'list' - // Precondition: 'list' must not be null. - private SExpression evaluateList(Cons list) { - SExpression car = list.getCar(); - SExpression cdr = list.getCdr(); - - LispFunction function = lookupFunction(car.toString()); - - if (function == null) { - // check if the car of the list is a lambda expression - if (car.functionp()) { - function = ((LambdaExpression) car).getFunction(); - } else if (LAMBDA.isLambdaExpression(car)) { - Cons lexpr = (Cons) car; - - function = LAMBDA.createFunction(lexpr); - } else { - throw new RuntimeException("undefined function " + car); - } - } - - // make sure the list of arguments for 'function' is a list - if (cdr.listp()) { - Cons args = (Cons) cdr; - - // make sure the list of arguments is not dotted - if (isDotted(args)) { - throw new RuntimeException("argument list given to " + car + - " is dotted: " + list); - } - - // determine if we should evaluate the arguments that will be - // passed to 'function' - if (function.evaluateArguments()) { - args = evaluateArgList(args); - } - - return function.call(args); - } - - // the list of arguments is not a list! - throw new RuntimeException("argument list given to " + car + - " is dotted: " + list); - } - - // Evaluate a list of arguments for a function. - // - // Parameters: arguments - a list of arguments for a function - // Returns: a list consisting of the values of the S-expressions found in - // 'arguments' - // Precondition: 'arguments' must not be null. - private Cons evaluateArgList(Cons arguments) { - if (arguments.nullp()) { - return Nil.getUniqueInstance(); - } - - SExpression car = eval(arguments.getCar()); - SExpression cdr = arguments.getCdr(); - - if (cdr.listp()) { - return new Cons(car, evaluateArgList((Cons) cdr)); - } - - // remove any parameters found after a dot (put here in case the check - // for a dotted parameter list is not done prior to this call) - return new Cons(car, Nil.getUniqueInstance()); - } - -} diff --git a/eval/EXIT.java b/eval/EXIT.java deleted file mode 100644 index 1def13f..0000000 --- a/eval/EXIT.java +++ /dev/null @@ -1,26 +0,0 @@ -package eval; - -import parser.*; - -public class EXIT extends LispFunction { - - // The number of arguments that EXIT takes. - private static final int NUM_ARGS = 0; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to EXIT - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength > NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("EXIT"), argList); - String errMsg = "too many arguments given to EXIT: " + originalSExpr; - - throw new RuntimeException(errMsg); - } - - System.exit(0); - return null; - } - -} diff --git a/eval/FUNCALL.java b/eval/FUNCALL.java deleted file mode 100644 index 395dd88..0000000 --- a/eval/FUNCALL.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 2 - */ - -package eval; - -import parser.*; - -/** - * FUNCALL represents the FUNCALL function in Lisp. - */ -public class FUNCALL extends LispFunction { - - public SExpression call(Cons argList) { - // make sure we have received at least one argument - if (argList.nullp()) { - Cons originalSExpr = new Cons(new Symbol("FUNCALL"), argList); - - throw new RuntimeException("too few arguments given to FUNCALL: " + - originalSExpr); - } - - SExpression cdr = argList.getCdr(); - Cons applyArgs = new Cons(argList.getCar(), LIST.makeList(cdr)); - - return APPLY.apply(applyArgs); - } - -} diff --git a/eval/GREATERP.java b/eval/GREATERP.java deleted file mode 100644 index 2dfc7aa..0000000 --- a/eval/GREATERP.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * GREATERP represents the '>' function in Lisp. - */ -public class GREATERP extends LispFunction { - - public SExpression call(Cons argList) { - // make sure we have received at least one argument - if (argList.nullp()) { - Cons originalSExpr = new Cons(new Symbol(">"), argList); - - throw new RuntimeException("too few arguments given to >: " + - originalSExpr); - } - - SExpression firstArg = argList.getCar(); - Cons argRest = (Cons) argList.getCdr(); - - // make sure that the first argument is a number - if (firstArg.numberp()) { - LispNumber num1 = (LispNumber) firstArg; - - if (argRest.nullp()) { - return Symbol.T; - } - - SExpression secondArg = argRest.getCar(); - - // make sure that the second argument is a number as well - if (secondArg.numberp()) { - LispNumber num2 = (LispNumber) secondArg; - - if (num1.getValue() > num2.getValue()) { - return call(argRest); - } - - return Nil.getUniqueInstance(); - } - - throw new RuntimeException(">: " + secondArg + " is not a number"); - } - - throw new RuntimeException(">: " + firstArg + " is not a number"); - } - -} diff --git a/eval/LAMBDA.java b/eval/LAMBDA.java deleted file mode 100644 index eaec557..0000000 --- a/eval/LAMBDA.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 2 - */ - -package eval; - -import parser.*; - -/** - * LAMBDA represents the LAMBDA form in Lisp. - */ -public class LAMBDA extends LispFunction { - - /** - * Determine if the given S-expression is a lambda expression. - * - * @param sexpr - * the S-expression to test (must not be null) - * @return - * true if sexpr is a valid lambda expression; - * false otherwise - */ - public static boolean isLambdaExpression(SExpression sexpr) { - if (sexpr.consp()) { - SExpression first = ((Cons) sexpr).getCar(); - - return "LAMBDA".equals(first.toString()); - } - - return false; - } - - /** - * Create an internal representation of a user-defined function from the - * specified lambda expression. - * - * @param lexpr - * the lambda expression to create the function from (must not be null) - * @return - * an internal representation of a user-defined function created from - * lexpr - * @throws RuntimeException - * Indicates that lexpr is not a valid lambda expression. - */ - public static UDFunction createFunction(Cons lexpr) { - LAMBDA lambda = new LAMBDA(); - SExpression cdr = lexpr.getCdr(); - - // make sure lexpr is a proper list - if (! cdr.consp()) { - throw new RuntimeException("invalid lambda expression"); - } else if (EVAL.isDotted((Cons) cdr)) { - throw new RuntimeException("dotted lambda expression " + lexpr); - } - - Cons rest = (Cons) cdr; - - return lambda.call(rest).getFunction(); - } - - // The minimum number of arguments that LAMBDA takes. - private static final int MIN_ARGS = 2; - - public LambdaExpression call(Cons argList) { - // retrieve the number of arguments passed to LAMBDA - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength < MIN_ARGS) { - Cons originalSExpr = new Cons(new Symbol("LAMBDA"), argList); - String errMsg = "too few arguments given to LAMBDA: " + - originalSExpr; - - throw new RuntimeException(errMsg); - } - - SExpression car = argList.getCar(); - - // make sure the list of arguments is a proper list - if (! car.listp()) { - throw new RuntimeException("LAMBDA: " + car + " is not a list"); - } else if (EVAL.isDotted((Cons) car)) { - throw new RuntimeException("LAMBDA: " + car + - " must be a proper list"); - } - - Cons lambdaList = (Cons) car; - Cons body = (Cons) argList.getCdr(); - Cons lexpr = new Cons(new Symbol("LAMBDA"), argList); - UDFunction function = new UDFunction(":LAMBDA", lambdaList, body); - - return new LambdaExpression(lexpr, function); - } - - /** - * Determine if the arguments passed to this Lisp function should be - * evaluated. - * - * @return - * false - */ - public boolean evaluateArguments() { - return false; - } - -} diff --git a/eval/LENGTH.java b/eval/LENGTH.java deleted file mode 100644 index dcab21b..0000000 --- a/eval/LENGTH.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * LENGTH represents the LENGTH function in Lisp. - */ -public class LENGTH extends LispFunction { - - /** - * Returns the length of the given list. - * - * @param list - * the list to determine the length of - * @return - * the length of list - */ - public static int getLength(Cons list) { - LENGTH lengthFunction = new LENGTH(); - LispNumber length = lengthFunction.call(LIST.makeList(list)); - - return length.getValue(); - } - - public LispNumber call(Cons argList) { - // make sure we have received at least one argument - if (argList.nullp()) { - Cons originalSExpr = new Cons(new Symbol("LENGTH"), argList); - - throw new RuntimeException("too few arguments given to LENGTH: " + - originalSExpr); - } - - SExpression argCar = argList.getCar(); - SExpression argCdr = argList.getCdr(); - - // make sure we have received only one argument - if (! argCdr.nullp()) { - Cons originalSExpr = new Cons(new Symbol("LENGTH"), argList); - - throw new RuntimeException("too many arguments given to LENGTH: " + - originalSExpr); - } - - // make sure that the argument is a list - if (argCar.listp()) { - Cons arg = (Cons) argCar; - - if (arg.nullp()) { - return new LispNumber(0); - } - - Cons cdr = LIST.makeList(arg.getCdr()); - LispNumber cdrLength = call(cdr); - - return new LispNumber(1 + cdrLength.getValue()); - } - - throw new RuntimeException("LENGTH: a proper list must not end with " + - argCar); - } - -} diff --git a/eval/LESSP.java b/eval/LESSP.java deleted file mode 100644 index 162d8c6..0000000 --- a/eval/LESSP.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * LESSP represents the '<' function in Lisp. - */ -public class LESSP extends LispFunction { - - public SExpression call(Cons argList) { - // make sure we have received at least one argument - if (argList.nullp()) { - Cons originalSExpr = new Cons(new Symbol("<"), argList); - - throw new RuntimeException("too few arguments given to <: " + - originalSExpr); - } - - SExpression firstArg = argList.getCar(); - Cons argRest = (Cons) argList.getCdr(); - - // make sure that the first argument is a number - if (firstArg.numberp()) { - LispNumber num1 = (LispNumber) firstArg; - - if (argRest.nullp()) { - return Symbol.T; - } - - SExpression secondArg = argRest.getCar(); - - // make sure that the second argument is a number as well - if (secondArg.numberp()) { - LispNumber num2 = (LispNumber) secondArg; - - if (num1.getValue() < num2.getValue()) { - return call(argRest); - } - - return Nil.getUniqueInstance(); - } - - throw new RuntimeException("<: " + secondArg + " is not a number"); - } - - throw new RuntimeException("<: " + firstArg + " is not a number"); - } - -} diff --git a/eval/LET.java b/eval/LET.java deleted file mode 100644 index becdbdd..0000000 --- a/eval/LET.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 2 - */ - -package eval; - -import parser.*; - -/** - * LET represents the LET form in Lisp. - */ -public class LET extends LispFunction { - - public SExpression call(Cons argList) { - // make sure we have received at least one argument - if (argList.nullp()) { - throw new RuntimeException("too few arguments given to LET"); - } - - // create a new symbol table on top of the current environment to add - // all the local variables to - SymbolTable environment = new SymbolTable(SETF.getEnvironment()); - - SExpression car = argList.getCar(); - Cons cdr = (Cons) argList.getCdr(); - - addVariablesToTable(environment, car); - SETF.setEnvironment(environment); - - SExpression retval = Nil.getUniqueInstance(); - - // evaluate all S-expression in the body - while (cdr.consp()) { - retval = EVAL.eval(cdr.getCar()); - cdr = (Cons) cdr.getCdr(); - } - - // restore the environment to its original value - SETF.setEnvironment(environment.getParent()); - - return retval; - } - - // Add a list of variables and their values to the specified symbol table. - // - // Parameters: environment - the symbol table to add the variables and - // their values to (must not be null) - // vars - a list of variable/value pairs (must be either a - // proper list of pairs or NIL) - // Throws: RuntimeException - Indicates that 'vars' is not a proper list or - // that it contains an member that is not a - // variable/value pair. - // Precondition: 'environment' and 'vars' must not be null. - // Postcondition: All of the variables in 'vars' have been placed into - // 'environment' with their values. - private void addVariablesToTable(SymbolTable environment, - SExpression vars) { - // makes sure the list of variable/value pairs is a list - if (! vars.listp()) { - throw new RuntimeException("LET: " + vars + - " is not a properly formatted" + - " variable/value pair list"); - } - - // add all variables in 'vars' to 'environment' - while (vars.consp()) { - Cons varList = (Cons) vars; - SExpression varListCar = varList.getCar(); - - // make sure this variable/value pair is a list - if (! varListCar.consp()) { - throw new RuntimeException("LET: " + varListCar + - " is not a properly formatted" + - " variable/value pair"); - } - - Cons varSpec = (Cons) varListCar; - SExpression symbol = varSpec.getCar(); - SExpression varSpecCdr = varSpec.getCdr(); - - // make sure this variable pair has a value associated with it - if (! varSpecCdr.consp()) { - throw new RuntimeException("LET: illegal variable " + - "specification " + varSpec); - } - - Cons varValue = (Cons) varSpecCdr; - SExpression value = varValue.getCar(); - - // make sure there are no more members of this variable/value pair - // and that 'symbol' is actually a symbol - if ((! varValue.getCdr().nullp()) || (! symbol.symbolp())) { - throw new RuntimeException("LET: illegal variable " + - "specification " + varSpec); - } - - environment.put(symbol.toString(), value); - - vars = varList.getCdr(); - } - } - - /** - * Determine if the arguments passed to this Lisp function should be - * evaluated. - * - * @return - * false - */ - public boolean evaluateArguments() { - return false; - } - -} diff --git a/eval/LIST.java b/eval/LIST.java deleted file mode 100644 index d801e6e..0000000 --- a/eval/LIST.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * LIST represents the LIST function in Lisp. - */ -public class LIST extends LispFunction { - - /** - * Places the given S-expression into a list. - * - * @param sexpr - * the S-expression to be placed into a list - * @return - * a list with sexpr as the car and NIL as the cdr. - */ - public static Cons makeList(SExpression sexpr) { - return new Cons(sexpr, Nil.getUniqueInstance()); - } - - public Cons call(Cons argList) { - if (argList.nullp()) { - // return NIL if there were no arguments passed to LIST - return Nil.getUniqueInstance(); - } - - SExpression argCar = argList.getCar(); - Cons argCdr = (Cons) argList.getCdr(); - - return new Cons(argCar, call(argCdr)); - } - -} diff --git a/eval/LISTP.java b/eval/LISTP.java deleted file mode 100644 index b2ad0ce..0000000 --- a/eval/LISTP.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * LISTP represents the LISTP function in Lisp. - */ -public class LISTP extends LispFunction { - - // The number of arguments that LISTP takes. - private static final int NUM_ARGS = 1; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to LISTP - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("LISTP"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to LISTP: " + originalSExpr; - - throw new RuntimeException(errMsg); - } - - SExpression arg = argList.getCar(); - - return (arg.listp() ? Symbol.T : Nil.getUniqueInstance()); - } - -} diff --git a/eval/LOAD.java b/eval/LOAD.java deleted file mode 100644 index 4a94235..0000000 --- a/eval/LOAD.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 2 - */ - -package eval; - -import parser.*; -import java.io.*; - -/** - * LOAD represents the LOAD function in Lisp. - */ -public class LOAD extends LispFunction { - // The number of arguments that LOAD takes. - private static final int NUM_ARGS = 1; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to LOAD - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("LOAD"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to LOAD: " + originalSExpr; - - throw new RuntimeException(errMsg); - } - - SExpression argCar = argList.getCar(); - - // make sure the argument is a string - if (! argCar.stringp()) { - throw new RuntimeException("LOAD: " + argCar + " is not a string"); - } - - LispString quotedName = (LispString) argCar; - String fileName = quotedName.toString(); - - // remove the surrounding quotes from the file name - fileName = fileName.substring(1, (fileName.length() - 1)); - - return processFile(fileName); - } - - // Evaluate all the S-expressions found in the file with the specified - // name. - // - // Parameters: fileName - the name of the file to be evaluated - // Returns: 'T' if the file was processed successfully; 'NIL' otherwise - private SExpression processFile(String fileName) { - LispParser parser = null; - - // attempt to create a new 'LispParser' on the specified file - try { - parser = new LispParser(new FileInputStream(fileName), fileName); - } catch (FileNotFoundException e) { - System.out.println("LOAD: could not open " + fileName); - - return Nil.getUniqueInstance(); - } - - // attempt to evaluate all the S-expressions contained in the file - while (! parser.eof()) { - try { - SExpression sexpr = parser.getSExpr(); - - EVAL.eval(sexpr); - } catch (RuntimeException e) { - System.out.println("LOAD: " + e.getMessage()); - - return Nil.getUniqueInstance(); - } catch (IOException e) { - System.out.println("LOAD: " + e.getMessage()); - - return Nil.getUniqueInstance(); - } - } - - // success! - return Symbol.T; - } - -} diff --git a/eval/LambdaExpression.java b/eval/LambdaExpression.java deleted file mode 100644 index 570d162..0000000 --- a/eval/LambdaExpression.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 2 - */ - -package eval; - -import parser.*; - -/** - * This class represents a Lisp FUNCTION in the PL-Lisp implementation. - */ -public class LambdaExpression extends SExpression { - - private Cons lexpr; - private UDFunction function; - - /** - * Create a new FUNCTION with the specified lambda expression and - * internal representation. - * - * @param lexpr - * the lambda expression of this FUNCTION - * @param function - * the internal representation of this FUNCTION - */ - public LambdaExpression(Cons lexpr, UDFunction function) { - this.lexpr = lexpr; - this.function = function; - } - - /** - * Test if this S-expression is a FUNCTION. - * - * @return - * true - */ - public boolean functionp() { - return true; - } - - /** - * Retrieve the lambda expression of this FUNCTION. - * - * @return - * the lambda expression of this FUNCTION - */ - public Cons getLExpression() { - return lexpr; - } - - /** - * Retrieve the internal representation of this FUNCTION. - * - * @return - * the user-defined function of this FUNCTION - */ - public UDFunction getFunction() { - return function; - } - - /** - * Returns a string representation of this FUNCTION. - * - * @return - * a string representation of this FUNCTION - */ - public String toString() { - return lexpr.toString(); - } - -} diff --git a/eval/LispFunction.java b/eval/LispFunction.java deleted file mode 100644 index c861fa2..0000000 --- a/eval/LispFunction.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * A LispFunction is an internal representation of a built-in - * function in the Lisp programming language. - */ -public abstract class LispFunction { - - /** - * Call this Lisp function with the given list of arguments. - * - * @param argList - * the list of arguments to pass to this function (MUST BE A PROPER LIST) - * @return - * the resulting S-expression of calling this function with the specified - * arguments - * @throws RuntimeException - * Indicates that an incorrect number of arguments has been passed to this - * function or that one of the arguments is not of the expected type. - */ - public abstract SExpression call(Cons argList); - - /** - * Determine if the arguments passed to this Lisp function should be - * evaluated. A subclass should override this method to return - * false if it does not want its arguments to be evaluated - * prior to being passed. - * - * @return - * true - */ - public boolean evaluateArguments() { - return true; - } - -} diff --git a/eval/MINUS.java b/eval/MINUS.java deleted file mode 100644 index a913624..0000000 --- a/eval/MINUS.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * MINUS represents the '-' function in Lisp. - */ -public class MINUS extends LispFunction { - - public SExpression call(Cons argList) { - // make sure we have received at least one argument - if (argList.nullp()) { - Cons originalSExpr = new Cons(new Symbol("-"), argList); - - throw new RuntimeException("too few arguments given to -: " + - originalSExpr); - } - - SExpression argFirst = argList.getCar(); - Cons argRest = (Cons) argList.getCdr(); - - // make sure that the first argument is a number - if (argFirst.numberp()) { - LispNumber num1 = (LispNumber) argFirst; - - if (argRest.nullp()) { - // there is only one argument, so return the additive - // inverse of the number - return new LispNumber(- num1.getValue()); - } - - SExpression argSecond = argRest.getCar(); - - // make sure that the next argument is a number as well - if (argSecond.numberp()) { - LispNumber num2 = (LispNumber) argSecond; - LispNumber difference = new LispNumber(num1.getValue() - - num2.getValue()); - SExpression argCddr = argRest.getCdr(); - - if (argCddr.consp()) { - return call(new Cons(difference, argCddr)); - } - - return difference; - } - - throw new RuntimeException("-: " + argSecond + " is not a number"); - } - - throw new RuntimeException("-: " + argFirst + " is not a number"); - } - -} diff --git a/eval/MULTIPLY.java b/eval/MULTIPLY.java deleted file mode 100644 index ac15950..0000000 --- a/eval/MULTIPLY.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * MULTIPLY represents the '*' function in Lisp. - */ -public class MULTIPLY extends LispFunction { - - public LispNumber call(Cons argList) { - if (argList.nullp()) { - return new LispNumber(1); - } - - SExpression argFirst = argList.getCar(); - Cons argRest = (Cons) argList.getCdr(); - - if (argFirst.numberp()) { - LispNumber num1 = (LispNumber) argFirst; - LispNumber num2 = call(argRest); - - return new LispNumber(num1.getValue() * num2.getValue()); - } - - throw new RuntimeException("*: " + argFirst + " is not a number"); - } - -} diff --git a/eval/NULL.java b/eval/NULL.java deleted file mode 100644 index fd30367..0000000 --- a/eval/NULL.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 2 - */ - -package eval; - -import parser.*; - -/** - * NULL represents the NULL function in Lisp. - */ -public class NULL extends LispFunction { - - // The number of arguments that NULL takes. - private static final int NUM_ARGS = 1; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to NULL - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("NULL"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to NULL: " + originalSExpr; - - throw new RuntimeException(errMsg); - } - - SExpression arg = argList.getCar(); - - return (arg.nullp() ? Symbol.T : Nil.getUniqueInstance()); - } - -} diff --git a/eval/PLUS.java b/eval/PLUS.java deleted file mode 100644 index 144f46c..0000000 --- a/eval/PLUS.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * PLUS represents the '+' function in Lisp. - */ -public class PLUS extends LispFunction { - - public LispNumber call(Cons argList) { - if (argList.nullp()) { - return new LispNumber(0); - } - - SExpression argFirst = argList.getCar(); - Cons argRest = (Cons) argList.getCdr(); - - if (argFirst.numberp()) { - LispNumber num1 = (LispNumber) argFirst; - LispNumber num2 = call(argRest); - - return new LispNumber(num1.getValue() + num2.getValue()); - } - - throw new RuntimeException("+: " + argFirst + " is not a number"); - } - -} diff --git a/eval/PRINT.java b/eval/PRINT.java deleted file mode 100644 index f9fedb5..0000000 --- a/eval/PRINT.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 2 - */ - -package eval; - -import parser.*; - -/** - * PRINT represents the PRINT function in Lisp. - */ -public class PRINT extends LispFunction { - - // The number of arguments that PRINT takes. - private static final int NUM_ARGS = 1; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to PRINT - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("PRINT"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to PRINT: " + originalSExpr; - - throw new RuntimeException(errMsg); - } - - SExpression arg = argList.getCar(); - - System.out.println(arg); - - return arg; - } - -} diff --git a/eval/QUOTE.java b/eval/QUOTE.java deleted file mode 100644 index 960ab3e..0000000 --- a/eval/QUOTE.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package eval; - -import parser.*; - -/** - * QUOTE represents the QUOTE form in Lisp. - */ -public class QUOTE extends LispFunction { - - // The number of arguments that QUOTE takes. - private static final int NUM_ARGS = 1; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to QUOTE - int argListLength = LENGTH.getLength(argList); - - // make sure we have received exactly one argument - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("QUOTE"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to QUOTE: " + originalSExpr; - - throw new RuntimeException(errMsg); - } - - return argList.getCar(); - } - - /** - * Determine if the arguments passed to this Lisp function should be - * evaluated. - * - * @return - * false - */ - public boolean evaluateArguments() { - return false; - } - -} diff --git a/eval/SETF.java b/eval/SETF.java deleted file mode 100644 index 90c25d4..0000000 --- a/eval/SETF.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 2 - */ - -package eval; - -import parser.*; - -/** - * SETF represents the SETF form in Lisp. - */ -public class SETF extends LispFunction { - - private static SymbolTable environment = new SymbolTable(); - - /** - * Look up the value of a symbol using its name. - * - * @param symbolName - * the name of the symbol to look up - * @return - * the value of symbolName if it has one; null otherwise - */ - public static SExpression lookup(String symbolName) { - SymbolTable current = environment; - - while (current != null) { - if (current.contains(symbolName)) { - return current.get(symbolName); - } - - current = current.getParent(); - } - - return null; - } - - /** - * Set the current environment to the specified value. - * - * @param newEnvironment - * the value to set the environment to - */ - public static void setEnvironment(SymbolTable newEnvironment) { - environment = newEnvironment; - } - - /** - * Retrieve the current environment. - * - * @return - * the current environment - */ - public static SymbolTable getEnvironment() { - return environment; - } - - // The number of arguments that SETF takes. - private static final int NUM_ARGS = 2; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to SETF - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("SETF"), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to SETF: " + originalSExpr; - - throw new RuntimeException(errMsg); - } - - SExpression symbol = argList.getCar(); - - // make sure the first argument is a symbol - if (! symbol.symbolp()) { - throw new RuntimeException("SETF: " + symbol + " is not a symbol"); - } - - Cons cdr = (Cons) argList.getCdr(); - SExpression value = EVAL.eval(cdr.getCar()); - - SymbolTable current = environment; - - // set 'current' to the symbol table that contains 'symbol' or the - // global symbol table if 'symbol' is not in the environment - while ((! current.contains(symbol.toString())) && - (current.getParent() != null)) { - current = current.getParent(); - } - - current.put(symbol.toString(), value); - - return value; - } - - /** - * Determine if the arguments passed to this Lisp function should be - * evaluated. - * - * @return - * false - */ - public boolean evaluateArguments() { - return false; - } - -} diff --git a/eval/SYMBOL_FUNCTION.java b/eval/SYMBOL_FUNCTION.java deleted file mode 100644 index 4a591ee..0000000 --- a/eval/SYMBOL_FUNCTION.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 2 - */ - -package eval; - -import parser.*; - -/** - * SYMBOL_FUNCTION represents the SYMBOL-FUNCTION function in - * Lisp. - */ -public class SYMBOL_FUNCTION extends LispFunction { - - // The number of arguments that SYMBOL-FUNCTION takes. - private static final int NUM_ARGS = 1; - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to SYMBOL-FUNCTION - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("SYMBOL-FUNCTION"), - argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to SYMBOL-FUNCTION: " + - originalSExpr; - - throw new RuntimeException(errMsg); - } - - SExpression arg = argList.getCar(); - - // make sure the argument is a symbol - if (arg.symbolp()) { - LispFunction function = EVAL.lookupFunction(arg.toString()); - - // make sure the function actually exists - if (function != null) { - if (function instanceof UDFunction) { - // this is a user-defined function - - UDFunction udFunction = (UDFunction) function; - - return udFunction.getLexpr(); - } - - // this is a built-in function - - return new Symbol("SUBR-" + arg.toString()); - } - - throw new RuntimeException("SYMBOL-FUNCTION: undefined function " + - arg); - } - - throw new RuntimeException("SYMBOL-FUNCTION: " + arg + - " is not a symbol"); - } - -} diff --git a/eval/SymbolTable.java b/eval/SymbolTable.java deleted file mode 100644 index aa72b28..0000000 --- a/eval/SymbolTable.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 2 - */ - -package eval; - -import parser.*; -import java.util.HashMap; - -/** - * A SymbolTable maps symbol names to values. - */ -public class SymbolTable { - - private HashMap table; - private SymbolTable parent; - - /** - * Create a new symbol table with no parent. - */ - public SymbolTable() { - this(null); - } - - /** - * Create a new symbol table with the specified parent. - * - * @param parent - * the parent of this symbol table - */ - public SymbolTable(SymbolTable parent) { - this.table = new HashMap(); - this.parent = parent; - } - - /** - * Determine if the specified symbol name is in this symbol table. - * - * @param symbolName - * the name of the symbol to look up - * @return - * true if the symbol is in this symbol table; - * false otherwise - */ - public boolean contains(String symbolName) { - return table.containsKey(symbolName); - } - - /** - * Returns the value to which the specified symbol name is mapped in this - * symbol table. - * - * @param symbolName - * the name of the symbol whose associated value is to be returned - * @return - * the value to which this symbol table maps symbolName, or - * null if no mapping exists - */ - public SExpression get(String symbolName) { - return table.get(symbolName); - } - - /** - * Associates the specified symbol name with the specified value in this - * symbol table. If the symbol table previously contained a mapping for - * this symbol name, the old value has been replaced. - * - * @param symbolName - * the name of the symbol with which the specified value is to be - * associated - * @param value - * the value to be associated with the specified symbol name - */ - public void put(String symbolName, SExpression value) { - table.put(symbolName, value); - } - - /** - * Returns the parent of this symbol table. - * - * @return - * the parent of this symbol table - */ - public SymbolTable getParent() { - return parent; - } - -} diff --git a/eval/UDFunction.java b/eval/UDFunction.java deleted file mode 100644 index 44e02c8..0000000 --- a/eval/UDFunction.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 2 - */ - -package eval; - -import parser.*; -import java.util.ArrayList; - -/** - * A UDFunction is an internal representation of a user-defined - * function in the Lisp programming language. - */ -public class UDFunction extends LispFunction { - - // the number of arguments that this user-defined function takes. - private final int NUM_ARGS; - - private String name; - private Cons body; - private Cons lexpr; - private SymbolTable environment; - private ArrayList parameters; - - /** - * Create a new user-defined function with the specified name, lambda list - * and body. - * - * @param name - * the name of this user-defined function - * @param lambdaList - * a list of the formal parameters of this user-defined function (MUST BE - * A PROPER LIST) - * @param body - * the body of this user-defined function (MUST BE A PROPER LIST) - */ - public UDFunction(String name, Cons lambdaList, Cons body) { - this.name = name; - this.body = body; - this.lexpr = new Cons(new Symbol(name), new Cons(lambdaList, body)); - this.environment = SETF.getEnvironment(); - this.parameters = new ArrayList(); - - // retrieve the names of all the formal parameters of this function - while (lambdaList.consp()) { - this.parameters.add(lambdaList.getCar().toString()); - - lambdaList = (Cons) lambdaList.getCdr(); - } - - this.NUM_ARGS = this.parameters.size(); - } - - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to this function - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol(name), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to " + name + ": " + - originalSExpr; - - throw new RuntimeException(errMsg); - } - - // push a new symbol table onto this function's environment (for its - // parameters) - environment = new SymbolTable(environment); - - // bind the values of the arguments to the formal parameter names - for (String param : parameters) { - SExpression currentArg = argList.getCar(); - - environment.put(param, currentArg); - - argList = (Cons) argList.getCdr(); - } - - // store the environment of the S-expression that called this function - // (the current environment) - SymbolTable currentEnvironment = SETF.getEnvironment(); - - // replace the current environment with the environment of this - // function - SETF.setEnvironment(environment); - - Cons currentSExpression = body; - SExpression retval = null; - - // evaluate all the S-expressions making up this function's body - while (currentSExpression.consp()) { - retval = EVAL.eval(currentSExpression.getCar()); - currentSExpression = (Cons) currentSExpression.getCdr(); - } - - // replace the environment of the S-expression that called this - // function - SETF.setEnvironment(currentEnvironment); - - // remove the bindings of the arguments to the formal parameter names - // in the environment of this function - environment = new SymbolTable(environment.getParent()); - - return retval; - } - - /** - * Return the lambda expression that represents this user-defined function. - * - * @return - * the lambda expression that represents this user-defined function - */ - public Cons getLexpr() { - return lexpr; - } - -} diff --git a/eval/package.html b/eval/package.html deleted file mode 100644 index e9c971d..0000000 --- a/eval/package.html +++ /dev/null @@ -1,4 +0,0 @@ - - Provides functions and forms to be used during the evaluation of an - S-expression. - diff --git a/main/LispInterpreter.java b/main/LispInterpreter.java deleted file mode 100644 index 3fbb5d6..0000000 --- a/main/LispInterpreter.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter 1 - */ - -package main; - -import parser.*; -import eval.*; -import error.ErrorManager; -import java.io.*; -import java.text.MessageFormat; - -/** - * LispInterpreter is an interpreter for the Lisp programming - * language. It takes the name of a file as a command-line argument, evaluates - * the S-expressions found in the file and then prints the results to the - * console. If no file name is provided at the command-line, this program will - * read from standard input. - */ -public class LispInterpreter { - - private static final String GREETING = "SUNY Potsdam Lisp Interpreter - Version 1.0.1"; - private static final String PROMPT = "~ "; - - public static final String ANSI_RESET = "\u001B[0m"; - public static final String ANSI_GREEN = "\u001B[32m"; - - /** - * Evaluate the S-expressions found in the file given as a command-line - * argument and print the results to the console. If no file name was - * given, retrieve the S-expressions from standard input. - * - * @param args - * the command-line arguments: - *
    - *
  • args[0] - file name (optional)
  • - *
- */ - public static void main(String[] args) { - LispParser parser = null; - boolean interactive = false; - - if (args.length > 0) { - // a file name was given at the command-line, attempt to create a - // 'LispParser' on it - try { - parser = new LispParser(new FileInputStream(args[0]), args[0]); - } catch (FileNotFoundException e) { - ErrorManager.generateError(e.getMessage(), ErrorManager.CRITICAL_LEVEL); - } - } else { - // no file name was given, create a 'LispParser' on standard input - parser = new LispParser(System.in, "System.in"); - interactive = true; - - System.out.println(GREETING); - System.out.println(); - System.out.print(PROMPT); - } - - while (! parser.eof()) { - try { - SExpression sexpr = parser.getSExpr(); - String result = MessageFormat.format("{0}{1}{2}", ANSI_GREEN, EVAL.eval(sexpr), ANSI_RESET); - - LispInterpreter.erasePrompt(interactive); - System.out.println(result); - } catch (RuntimeException e) { - LispInterpreter.erasePrompt(interactive); - ErrorManager.generateError(e.getMessage(), 2); - } catch (IOException e) { - ErrorManager.generateError(e.getMessage(), ErrorManager.CRITICAL_LEVEL); - } - - if (interactive) { - System.out.print(PROMPT); - } - } - } - - private static void erasePrompt(boolean interactive) { - if (interactive) { - for (int i = 0; i < PROMPT.length(); i++) { - System.out.print("\b"); - } - } - } - -} diff --git a/main/LispInterpreter2.java b/main/LispInterpreter2.java deleted file mode 100644 index 0c6726a..0000000 --- a/main/LispInterpreter2.java +++ /dev/null @@ -1,50 +0,0 @@ -package main; - -import parser.*; -import eval.*; -import error.ErrorManager; -import java.io.*; -import java.net.*; -import remotefs.RemoteFileInputStream; - -public class LispInterpreter2 { - - public static final String HOST_NAME = "localhost"; - public static final int PORT_NUM = 5150; - - public static void main(String[] args) { - LispParser parser = null; - - if (args.length > 0) { - try { - InetAddress host = InetAddress.getByName(HOST_NAME); - RemoteFileInputStream remoteIn = - new RemoteFileInputStream(host, PORT_NUM, args[0]); - - parser = new LispParser(remoteIn, args[0]); - } catch (UnknownHostException e) { - ErrorManager.generateError(e.getMessage(), - ErrorManager.CRITICAL_LEVEL); - } catch (FileNotFoundException e) { - ErrorManager.generateError(e.getMessage(), - ErrorManager.CRITICAL_LEVEL); - } - } else { - parser = new LispParser(System.in, "System.in"); - } - - while (! parser.eof()) { - try { - SExpression sexpr = parser.getSExpr(); - - System.out.println(EVAL.eval(sexpr)); - } catch (RuntimeException e) { - ErrorManager.generateError(e.getMessage(), 2); - } catch (IOException e) { - ErrorManager.generateError(e.getMessage(), - ErrorManager.CRITICAL_LEVEL); - } - } - } - -} diff --git a/main/LispParserDriver.java b/main/LispParserDriver.java deleted file mode 100644 index d0ffc46..0000000 --- a/main/LispParserDriver.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Parser - */ - -package main; - -import parser.*; -import error.ErrorManager; -import java.io.*; - -/** - * LispParserDriver is a program that takes the name of a file - * as a command-line argument, creates an internal representation of the - * S-expressions found in the file and prints them to the console. If no file - * name is provided at the command-line, this program will read from standard - * input. - */ -public class LispParserDriver { - - /** - * Create internal representations of the S-expressions found in the file - * whose name was given as a command-line argument and print them to the - * console. If no file name was given, retrieve the S-expressions from - * standard input. - * - * @param args - * the command-line arguments: - *
    - *
  • args[0] - file name (optional)
  • - *
- */ - public static void main(String[] args) { - LispParser parser = null; - - if (args.length > 0) { - // a file name was given at the command-line, attempt to create a - // 'LispParser' on it - try { - parser = new LispParser(new FileInputStream(args[0]), args[0]); - } catch (FileNotFoundException e) { - ErrorManager.generateError(e.getMessage(), - ErrorManager.CRITICAL_LEVEL); - } - } else { - // no file name was given, create a 'LispParser' on standard input - parser = new LispParser(System.in, "System.in"); - } - - while (! parser.eof()) { - try { - SExpression sexpr = parser.getSExpr(); - - System.out.println(sexpr.toString()); - } catch (RuntimeException e) { - ErrorManager.generateError(e.getMessage(), 2); - } catch (IOException e) { - ErrorManager.generateError(e.getMessage(), - ErrorManager.CRITICAL_LEVEL); - } - } - } - -} diff --git a/main/LispScannerDriver.java b/main/LispScannerDriver.java deleted file mode 100644 index 13447c3..0000000 --- a/main/LispScannerDriver.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter Phase 1 - Lexical Analysis - */ - -package main; - -import scanner.*; -import error.ErrorManager; -import java.io.*; - -/** - * LispScannerDriver is a program that takes the name of a file - * as a command-line argument, retrieves all of the Lisp tokens from the file - * and prints them to the console. If no file name is provided at the - * command-line, this program will read from standard input. - */ -public class LispScannerDriver { - - /** - * Obtain the Lisp tokens from the file whose name was given as a - * command-line argument and print them to the console. If no file name was - * given, retrieve the tokens from standard input. - * - * @param args - * the command-line arguments: - *
    - *
  • args[0] - file name (optional)
  • - *
- */ - public static void main(String[] args) { - LispScanner in = null; - - if (args.length > 0) { - // a file name was given at the command-line, attempt to create a - // 'LispScanner' on it - try { - in = new LispScanner(new FileInputStream(args[0]), args[0]); - } catch (FileNotFoundException e) { - ErrorManager.generateError(e.getMessage(), - ErrorManager.CRITICAL_LEVEL); - } - } else { - // no file name was given, create a 'LispScanner' on standard input - in = new LispScanner(System.in, "System.in"); - } - - Token t = null; - - do { - try { - t = in.nextToken(); - - System.out.printf("%-15s%-25s%5d%5d%25s\n", t.getType(), - t.getText(), - t.getLine(), - t.getColumn(), - t.getFName()); - } catch (RuntimeException e) { - ErrorManager.generateError(e.getMessage(), 2); - } catch (IOException e) { - ErrorManager.generateError(e.getMessage(), - ErrorManager.CRITICAL_LEVEL); - } - } while ((t == null) || (t.getType() != Token.Type.EOF)); - } - -} diff --git a/main/package.html b/main/package.html deleted file mode 100644 index bfdbdab..0000000 --- a/main/package.html +++ /dev/null @@ -1,3 +0,0 @@ - - Provides test drivers for the various stages of the Lisp Interpreter. - diff --git a/parser/Atom.java b/parser/Atom.java deleted file mode 100644 index 465de81..0000000 --- a/parser/Atom.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Parser - */ - -package parser; - -/** - * This class represents an ATOM in the PL-Lisp implementation. - */ -public class Atom extends SExpression { - - private String text; - - /** - * Create a new ATOM with the specified text. - * - * @param text - * the text representing this ATOM - */ - public Atom(String text) { - this.text = text; - } - - /** - * Test if this S-expression is an ATOM. - * - * @return - * true - */ - public boolean atomp() { - return true; - } - - /** - * Returns a string representation of this ATOM. - * - * @return - * a string representation of this ATOM - */ - public String toString() { - return text; - } - -} diff --git a/parser/Cons.java b/parser/Cons.java deleted file mode 100644 index 2402a99..0000000 --- a/parser/Cons.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Parser - */ - -package parser; - -/** - * This class represents a Lisp CONS cell in the PL-Lisp implementation. - */ -public class Cons extends SExpression { - - private SExpression car; - private SExpression cdr; - - /** - * Create a new CONS cell with the specified car and cdr. - * - * @param car - * the car of this CONS cell - * @param cdr - * the cdr of this CONS cell - */ - public Cons(SExpression car, SExpression cdr) { - this.car = car; - this.cdr = cdr; - } - - /** - * Retrieve the car of this CONS cell. - * - * @return - * the car of this CONS cell - */ - public SExpression getCar() { - return car; - } - - /** - * Retrieve the cdr of this CONS cell. - * - * @return - * the cdr of this CONS cell - */ - public SExpression getCdr() { - return cdr; - } - - /** - * Set the car of this CONS cell to the specified value. - * - * @param newCar - * the value to assign to the car of this CONS cell - */ - public void setCar(SExpression newCar) { - car = newCar; - } - - /** - * Set the cdr of this CONS cell to the specified value. - * - * @param newCdr - * the value to assign to the cdr of this CONS cell - */ - public void setCdr(SExpression newCdr) { - cdr = newCdr; - } - - /** - * Test if this S-expression is a CONS cell. - * - * @return - * true - */ - public boolean consp() { - return true; - } - - /** - * Returns a string representation of this CONS cell. - * - * @return - * a string representation of this CONS cell - */ - public String toString() { - return ("(" + toStringAux()); - } - - // Returns a string representation of the car of a CONS cell followed by - // its cdr. If the cdr of this CONS cell is not a CONS cell itself, this - // method places a ')' at the end of its return value. Also, if the cdr of - // this CONS cell is NIL, it will not be included in the return value of - // this method. When used in conjunction with the 'toString' method of this - // class, this method provides a means for creating the correct string - // representation of a list. - // - // Returns: a string representation of the car of a CONS cell followed by - // its cdr - private String toStringAux() { - if (cdr.nullp()) { - return (car.toString() + ")"); - } else if (cdr.consp()) { - return (car.toString() + " " + ((Cons) cdr).toStringAux()); - } - - // the cdr of this CONS cell is not a list - return (car.toString() + " . " + cdr.toString() + ")"); - } - -} diff --git a/parser/LispNumber.java b/parser/LispNumber.java deleted file mode 100644 index 34c3bde..0000000 --- a/parser/LispNumber.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Parser - */ - -package parser; - -/** - * This class represents a NUMBER in the PL-Lisp implementation. - */ -public class LispNumber extends Atom { - - private int value; - - /** - * Create a new NUMBER with the specified text. - * - * @param text - * the text representing this NUMBER - * @throws IllegalArgumentException - * Indicates that text does not represent a valid integer. - */ - public LispNumber(String text) { - super(text.replaceFirst("^0+(?!$)", "")); - - try { - this.value = Integer.parseInt(text); - } catch (NumberFormatException e) { - throw new IllegalArgumentException(text + - " is not a valid integer"); - } - } - - /** - * Create a new NUMBER with the specified value. - * - * @param value - * the integer value of this NUMBER - */ - public LispNumber(int value) { - super(Integer.toString(value)); - - this.value = value; - } - - /** - * Test if this S-expression is a NUMBER. - * - * @return - * true - */ - public boolean numberp() { - return true; - } - - /** - * Retrieve the integer value of this NUMBER. - * - * @return - * the integer value of this NUMBER - */ - public int getValue() { - return value; - } - -} diff --git a/parser/LispParser.java b/parser/LispParser.java deleted file mode 100644 index 9a7733f..0000000 --- a/parser/LispParser.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Parser - */ - -package parser; - -import scanner.*; -import java.io.*; - -/** - * A LispParser converts a stream of bytes into internal - * representations of Lisp S-expressions. When the end of stream has been - * reached the eof method of this parser will return true. - */ -public class LispParser { - - private LispScanner scanner; - private Token nextToken; - - // A field to store an exception that has been thrown in the 'eof' method - // as a result of reading in the next token from 'scanner'. - private Exception delayedException; - - // A field to notify us if the next token has already been stored in - // 'nextToken' by the 'eof' method. - private boolean nextTokenStored; - - /** - * Create a new LispParser that produces S-expressions from - * the specified input stream. - * - * @param in - * the input stream to obtain S-expressions from (must not be - * null) - * @param fileName - * the name of the file that in is reading from - */ - public LispParser(InputStream in, String fileName) { - scanner = new LispScanner(in, fileName); - nextToken = null; - delayedException = null; - nextTokenStored = false; - } - - /** - * Determing if this parser has reached the end of its underlying input - * stream. - * - * @return - * true if this parser has reached the end of its underlying - * input stream; false otherwise - */ - public boolean eof() { - if (! nextTokenStored) { - // attempt to read the next token from 'scanner' and store it in - // 'nextToken' - try { - nextToken = scanner.nextToken(); - nextTokenStored = true; - } catch (Exception e) { - // this method should give the illusion of not actually reading - // a token, so we store any exceptions thrown as a result of - // reading in the next token from 'scanner' (it will be thrown - // the next time the 'getSExpr' method is called) - delayedException = e; - - if (nextToken == null) { - // we have not successfully read in any tokens yet, so we - // could not have read in an end-of-file token - - return false; - } - } - } - - return (nextToken.getType() == Token.Type.EOF); - } - - /** - * Returns the next S-expression from this parser. - * - * @return - * the next S-expression from this parser - * @throws RuntimeException - * Indicates that an illegal S-expression was encountered in the - * underlying input stream. - * @throws IOException - * Indicates that an I/O error has occurred. - */ - public SExpression getSExpr() throws IOException { - if (delayedException != null) { - // the 'eof' method has stored an exception for us to throw - - // determine the type of the stored exception and throw it! - if (delayedException instanceof IOException) { - IOException e = (IOException) delayedException; - - // remove the exception from 'delayedException' - delayedException = null; - - throw e; - } else if (delayedException instanceof RuntimeException) { - RuntimeException e = (RuntimeException) delayedException; - - // remove the exception from 'delayedException' - delayedException = null; - - throw e; - } - } - - if (! nextTokenStored) { - // the next token has not been stored in 'nextToken' by the 'eof' - // method - - nextToken = scanner.nextToken(); - } else { - // the 'eof' method has been called and has read in the next token - // already to determine if we have reached the end-of-file - - nextTokenStored = false; - } - - return sExpr(); - } - - // sExpr ::= NUMBER | IDENTIFIER | RESERVED | STRING | QUOTE_MARK sExpr | - // LEFT_PAREN sExprTail - // - // Returns: an S-expression that matches the rules given above - // Throws: RuntimeException - Indicates that an illegal S-expression was - // encountered in the underlying input stream. - // Throws: IOException - Indicates that an I/O error has occurred. - // Precondition: 'nextToken' is not null. - private SExpression sExpr() throws IOException { - // determine the type of 'nextToken' and create the appropriate - // S-expression - switch (nextToken.getType()) { - case NUMBER: - return new LispNumber(nextToken.getText()); - case IDENTIFIER: - case RESERVED: - return new Symbol(nextToken.getText()); - case STRING: - return new LispString(nextToken.getText()); - case QUOTE_MARK: - nextToken = scanner.nextToken(); - SExpression arg = sExpr(); - - return new Cons(new Symbol("QUOTE"), - new Cons(arg, Nil.getUniqueInstance())); - case LEFT_PAREN: - return sExprTail(); - case RIGHT_PAREN: - throw new RuntimeException("expression begins with \')\'" + - " - line " + nextToken.getLine() + - " column " + nextToken.getColumn()); - case EOF: - throw new RuntimeException("end-of-file encountered" + - " - line " + nextToken.getLine() + - " column " + nextToken.getColumn()); - default: // unrecognized token type - throw new RuntimeException("unrecognizable token" + - " - line " + nextToken.getLine() + - " column " + nextToken.getColumn()); - } - } - - // sExprTail ::= RIGHT_PAREN | sExpr sExprTail - // - // Returns: an S-expression that matches the rules given above - // Throws: IOException - Indicates that an I/O error has occurred. - // Precondition: 'scanner' is not null. - private SExpression sExprTail() throws IOException { - nextToken = scanner.nextToken(); - - // determine the type of 'nextToken' and create the appropriate - // S-expression - switch (nextToken.getType()) { - case RIGHT_PAREN: - return Nil.getUniqueInstance(); - default: - SExpression car = sExpr(); - SExpression cdr = sExprTail(); - - return new Cons(car, cdr); - } - } - -} diff --git a/parser/LispString.java b/parser/LispString.java deleted file mode 100644 index 66b56a3..0000000 --- a/parser/LispString.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Parser - */ - -package parser; - -/** - * This class represents a STRING in the PL-Lisp implementation. - */ -public class LispString extends Atom { - - /** - * Create a new STRING with the specified text. - * - * @param text - * the text representing this STRING - */ - public LispString(String text) { - super(text); - } - - /** - * Test if this S-expression is a STRING. - * - * @return - * true - */ - public boolean stringp() { - return true; - } - -} diff --git a/parser/Nil.java b/parser/Nil.java deleted file mode 100644 index 5344053..0000000 --- a/parser/Nil.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Parser - */ - -package parser; - -/** - * This class represents NIL in the PL-Lisp implementation. - */ -public class Nil extends Cons { - - private static Nil uniqueInstance = new Nil(); - - /** - * Retrieve the single unique instance of NIL. - * - * @return - * the single unique instance of NIL - */ - public static Nil getUniqueInstance() { - return uniqueInstance; - } - - // We are using the Singleton pattern, so the constructor for 'Nil' is - // private. - private Nil() { - super(null, null); - - // the car and cdr of NIL both refer to NIL - super.setCar(this); - super.setCdr(this); - } - - /** - * Test if this S-expression is NULL. - * - * @return - * true - */ - public boolean nullp() { - return true; - } - - /** - * Test if this S-expression is an ATOM. - * - * @return - * true - */ - public boolean atomp() { - return true; - } - - /** - * Test if this S-expression is a CONS cell. - * - * @return - * false - */ - public boolean consp() { - return false; - } - - /** - * Test if this S-expression is a SYMBOL. - * - * @return - * true - */ - public boolean symbolp() { - return true; - } - - /** - * Set the car of this CONS cell to the specified value. This method does - * nothing (the car of NIL can not be changed). - * - * @param newCar - * the value to assign to the car of this CONS cell - */ - public void setCar(SExpression newCar) {} - - /** - * Set the cdr of this CONS cell to the specified value. This method does - * nothing (the cdr of NIL can not be changed). - * - * @param newCdr - * the value to assign to the cdr of this CONS cell - */ - public void setCdr(SExpression newCdr) {} - - /** - * Returns a string representation of NIL. - * - * @return - * a string representation of NIL - */ - public String toString() { - return "NIL"; - } - -} diff --git a/parser/SExpression.java b/parser/SExpression.java deleted file mode 100644 index bb8aaa4..0000000 --- a/parser/SExpression.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Parser - */ - -package parser; - -/** - * This is the base class for memory in the PL-Lisp implementation. - */ -public class SExpression { - - // for mark and sweep garbage collection - private boolean marked = false; - - /** - * Determine if this SExpression is marked. - * - * @return - * true if this SExpression is marked; - * false otherwise - */ - public final boolean isMarked() { - return marked; - } - - /** - * Set the marked status of this S-expression to the specified value. - * - * @param value - * the value to assign to this S-expression's marked status - */ - public final void setMarked(final boolean value) { - marked = value; - } - - // Lisp type predicates; - // by default, all return false (an SExpression effectively has NO type); - // overridden in subclasses to describe their Lisp type - - /** - * Test if this S-expression is NULL. - * - * @return - * false - */ - public boolean nullp() { - return false; - } - - /** - * Test if this S-expression is an ATOM. - * - * @return - * false - */ - public boolean atomp() { - return false; - } - - /** - * Test if this S-expression is a CONS cell. - * - * @return - * false - */ - public boolean consp() { - return false; - } - - /** - * Test if this S-expression is a LIST. - * - * @return - * the value of (consp() || nullp()) - */ - public boolean listp() { - return (consp() || nullp()); - } - - /** - * Test if this S-expression is a NUMBER. - * - * @return - * false - */ - public boolean numberp() { - return false; - } - - /** - * Test if this S-expression is a SYMBOL. - * - * @return - * false - */ - public boolean symbolp() { - return false; - } - - /** - * Test if this S-expression is a FUNCTION. - * - * @return - * false - */ - public boolean functionp() { - return false; - } - - /** - * Test if this S-expression is a STRING. - * - * @return - * false - */ - public boolean stringp() { - return false; - } - -} diff --git a/parser/Symbol.java b/parser/Symbol.java deleted file mode 100644 index 96f1a96..0000000 --- a/parser/Symbol.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Parser - */ - -package parser; - -/** - * This class represents a SYMBOL in the PL-Lisp implementation. - */ -public class Symbol extends Atom { - - /** This SYMBOL represents TRUE in the PL-Lisp implementation. */ - public static final Symbol T = new Symbol("T"); - - /** - * Create a new SYMBOL with the specified text. - * - * @param text - * the text representing this SYMBOL - */ - public Symbol(String text) { - super(text.toUpperCase()); - } - - /** - * Test if this S-expression is a SYMBOL. - * - * @return - * true - */ - public boolean symbolp() { - return true; - } - -} diff --git a/parser/package.html b/parser/package.html deleted file mode 100644 index ed4dbdd..0000000 --- a/parser/package.html +++ /dev/null @@ -1,4 +0,0 @@ - - Provides the classes necessary for creating an internal representation of - the Lisp programming language. - diff --git a/scanner/LispFilterStream.java b/scanner/LispFilterStream.java deleted file mode 100644 index d9838dc..0000000 --- a/scanner/LispFilterStream.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter Phase 1 - Lexical Analysis - */ - -package scanner; - -import java.io.InputStream; -import java.io.FilterInputStream; -import java.io.IOException; - -/** - * A LispFilterStream is an input stream that returns the bytes - * from an underlying input stream with all Lisp comments removed and replaced - * with newlines. - */ -public class LispFilterStream extends FilterInputStream { - - private boolean inQuote; - - /** - * Creates a LispFilterStream with the specified underlying - * InputStream. - * - * @param in - * the underlying input stream (must not be null) - */ - public LispFilterStream(InputStream in) { - super(in); - - inQuote = false; - } - - /** - * Reads the next byte of data from this input stream. The value byte is - * returned as an int in the range 0 to - * 255. If no byte is available because the end of the stream - * has been reached, the value -1 is returned. - * - * @return - * the next byte of data, or -1 if the end of the stream has - * been reached. - * @throws IOException - * Indicates that an I/O error has occurred. - */ - @Override - public int read() throws IOException { - int next = super.read(); - - if ((next == ';') && (! inQuote)) { - // we have entered a comment, consume all the bytes from the - // underlying input stream until we reach a newline character or - // the end of the stream - while ((next != '\n') && (next != -1)) { - next = super.read(); - } - } else if (next == '\n') { - inQuote = false; - } else if (next == '\"') { // we have entered or left a quoted string - inQuote = (! inQuote); - } - - return next; - } - - /** - * Reads up to the specified number of data bytes from this input stream - * into an array of bytes starting at the specified offset. If no bytes are - * available because the end of this stream has been reached then - * -1 is returned. Also, If the specified number of bytes is - * more than the number of remaining data bytes in this input stream, then - * only the number of remaining data bytes are copied into the byte array. - * - * @param b - * the buffer into which the data bytes are read (must not be - * null) - * @param off - * the start offset in b at which the data is written (must - * be >= 0 and < b.length) - * @param len - * the maximum number of bytes to read into b (len + - * off must be < b.length) - * @return - * the total number of bytes read into the buffer, or -1 if - * there is no more data because the end of the stream has been reached - * @throws IOException - * Indicates that the first byte could not be read into b - * for some reason other than reaching the end of the stream. - * @throws IndexOutOfBoundsException - * Indicates that this method attempted to access an index in - * b that was either negative or greater than or equal to - * b.length as a result of the given parameters. - * @throws NullPointerException - * Indicates that b is null. - */ - @Override - public int read(byte[] b, int off, int len) throws IOException { - int bytesRead = 0; - - // make sure we are supposed to read at least one byte into 'b' - if (len > 0) { - int next = read(); - - if (next == -1) { - // there are no more bytes to read from this input stream - - return -1; - } - - int i = off; - - while (next != -1) { - ++bytesRead; - - b[i++] = (byte) next; - - if (i >= (off + len)) { // we have read 'len' bytes into 'b' - break; - } - - try { - next = read(); - } catch (IOException e) { - // treat this exception like an end of stream - - break; - } - } - } - - return bytesRead; - } - - /** - * Skip over and discard the specified number of bytes from this input - * stream. This method may, for a variety of reasons, end up skipping some - * smaller number of bytes, possibly 0. The actual number of - * bytes skipped is returned. - * - * @param n - * the number of bytes to be skipped - * @return - * the actual number of bytes skipped - * @throws IOException - * Indicates that an I/O error has occurred. - */ - @Override - public long skip (long n) throws IOException { - long bytesSkipped = 0; - - while ((n > 0) && (read() != -1)) { - ++bytesSkipped; - --n; - } - - return bytesSkipped; - } - -} diff --git a/scanner/LispScanner.java b/scanner/LispScanner.java deleted file mode 100644 index df6df9b..0000000 --- a/scanner/LispScanner.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter Phase 1 - Lexical Analysis - */ - -package scanner; - -import java.io.InputStream; -import java.io.BufferedInputStream; -import java.io.IOException; - -/** - * A LispScanner converts a stream of bytes into a stream of Lisp - * tokens. When the end of stream has been reached a token with a type of - * Token.Type.EOF is returned from the nextToken - * method of this scanner. - */ -public class LispScanner { - - private LispFilterStream inStream; - private Token currToken; - private String fileName; - private int line; - private int column; - - /** - * Create a new LispScanner that produces Lisp tokens from the - * specified input stream. - * - * @param in - * the input stream to obtain Lisp tokens from (must not be - * null) - * @param fileName - * the name of the file that in is reading from - */ - public LispScanner(InputStream in, String fileName) { - this.inStream = new LispFilterStream(new BufferedInputStream(in)); - this.currToken = null; - this.fileName = fileName; - this.line = 1; - this.column = 0; - } - - /** - * Returns the same Lisp token returned from the last call to the - * nextToken method of this scanner. In the case that no calls - * to nextToken have been made yet, this method returns - * null. - * - * @return - * the last Lisp token returned from this scanner or null (if - * no tokens have been returned from this scanner yet) - */ - public Token getCurrToken() { - return currToken; - } - - /** - * Returns the next Lisp token from this scanner. - * - * @return - * the next Lisp token from this scanner. - * @throws RuntimeException - * Indicates that an illegal character or an unterminated quoted string - * was encountered in the input stream (not counting comments). - * @throws IOException - * Indicates that an I/O error has occurred. - */ - public Token nextToken() throws IOException { - currToken = retrieveNextToken(); - - return currToken; - } - - // Retrieve the next Lisp token from 'inStream'. - // - // Returns: the next Lisp token found in 'inStream' - // Precondition: 'inStream' must not be null. - // Throws: RuntimeException - Indicates that an illegal character or an - // unterminated quoted string was encountered in - // 'inStream'. - // Throws: IOException - Indicates that an I/O error has occurred. - private Token retrieveNextToken() throws IOException { - int c; - - while ((c = inStream.read()) != -1) { - char nextChar = (char) c; - - ++column; - - // determine the type of the Lisp token from the character obtained - // from 'inStream' - switch (nextChar) { - case '\n': - // we have hit a new line so increment 'line' and reset - // 'column' - ++line; - column = 0; - - break; - case '(': - return new Token(Token.Type.LEFT_PAREN, - "(", - fileName, - line, - column); - case ')': - return new Token(Token.Type.RIGHT_PAREN, - ")", - fileName, - line, - column); - case '\'': - return new Token(Token.Type.QUOTE_MARK, - "\'", - fileName, - line, - column); - case '\"': - return retrieveString(nextChar); - default: - if (Character.isWhitespace(nextChar)) { // skip whitespace - continue; - } else if (Character.isDigit(nextChar)) { // number - return retrieveNumber(nextChar); - } else if (isLegalIdChar(nextChar)) { // identifier - return retrieveIdentifier(nextChar); - } else { - // 'nextChar' can not start any Lisp token - - throw new RuntimeException("illegal character " + - "\'" + nextChar + "\'" + - " - line " + line + - " column " + column); - } - } - } - - // we have reached the end of 'inStream' so we return an end-of-file - // token - return new Token(Token.Type.EOF, "EOF", fileName, line, column); - } - - // Retrieve a quoted string token from 'inStream'. - // - // Parameters: firstDoubleQuote - the opening double quote of this quoted - // string - // Returns: a quoted string token obtained from 'instream' - // Throws: RuntimeException - Indicates that this quoted string was - // missing its terminating double quote. - // Throws: IOException - Indicates that an I/O error has occurred. - // Precondition: 'firstDoubleQuote' must be the leading double quote - // character of this quoted string and 'inStream' must not - // be null. - private Token retrieveString(char firstDoubleQuote) throws IOException { - StringBuffer text = new StringBuffer(); - int startLine = line; - int startColumn = column; - char prevChar = firstDoubleQuote; - - text.append(firstDoubleQuote); - - int c; - - while ((c = inStream.read()) != -1) { - char nextChar = (char) c; - - ++column; - text.append(nextChar); - - switch(nextChar) { - case '\n': - ++line; - column = 0; - - break; - case '\"': - if (prevChar != '\\') { - // we have found the terminating double quote - - return new Token(Token.Type.STRING, - text.toString(), - fileName, - startLine, - startColumn); - } - - // this is an escaped double quote - } - - prevChar = nextChar; - } - - // the end of 'inStream' was reached before the terminating double - // quote - - throw new RuntimeException("unterminated quoted string" + - " - line " + startLine + - " column " + startColumn); - } - - // Retrieve a number token from 'inStream'. - // - // Parameters: firstDigit - the first digit of this number - // Returns: a number token obtained from 'inStream' - // Throws: IOException - Indicates that an I/O error has occurred. - // Precondition: 'firstDigit' must be the first digit of this number and - // 'inStream' must not be null. - private Token retrieveNumber(char firstDigit) throws IOException { - StringBuffer text = new StringBuffer(); - int startColumn = column; - - text.append(firstDigit); - inStream.mark(1); - - int c; - - while ((c = inStream.read()) != -1) { - char nextChar = (char) c; - - if (Character.isDigit(nextChar)) { - // 'nextChar' is a digit in this number - - text.append(nextChar); - ++column; - } else { - // we have reached the end of the number - - inStream.reset(); // unread the last character - - return new Token(Token.Type.NUMBER, - text.toString(), - fileName, - line, - startColumn); - } - - inStream.mark(1); - } - - // there are no more bytes to be read from 'inStream' after this number - // token - - return new Token(Token.Type.NUMBER, - text.toString(), - fileName, - line, - startColumn); - } - - // Retrieve an identifier token from 'inStream'. - // - // Parameters: firstChar - the first character of this identifier - // Returns: an identifier token obtained from 'inStream' - // Throws: IOException - Indicates that an I/O error has occurred. - // Precondition: 'firsChar' must be the first character of this identifier - // and 'inStream' must not be null. - private Token retrieveIdentifier(char firstChar) throws IOException { - StringBuffer text = new StringBuffer(); - int startColumn = column; - - text.append(firstChar); - inStream.mark(1); - - int c; - - while ((c = inStream.read()) != -1) { - char nextChar = (char) c; - - if (isLegalIdChar(nextChar)) { - // 'nextChar' is part of the identifier - - text.append(nextChar); - ++column; - } else { - // we have reached the end of this identifier - - inStream.reset(); // unread the last character - - return new Token(Token.Type.IDENTIFIER, - text.toString(), - fileName, - line, - startColumn); - } - - inStream.mark(1); - } - - // there are no more bytes to be read from 'inStream' after this - // identifier token - - return new Token(Token.Type.IDENTIFIER, - text.toString(), - fileName, - line, - startColumn); - } - - // Test if a character is legal to be contained within an identifier in - // Lisp. - // - // Returns: 'true' if the character can be found within an identifier in - // Lisp; 'false' otherwise - private boolean isLegalIdChar(char c) { - return ((! Character.isWhitespace(c)) && (c != '\"') - && (c != '\'') - && (c != '\\') - && (c != '`') - && (c != '(') - && (c != ')') - && (c != '[') - && (c != ']') - && (c != '#') - && (c != '.') - && (c != ';')); - } - -} diff --git a/scanner/Token.java b/scanner/Token.java deleted file mode 100644 index c410102..0000000 --- a/scanner/Token.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter Phase 1 - Lexical Analysis - */ - -package scanner; - -/** - * A Token represents a token in Common Lisp. - */ -public class Token { - - /** - * An enumeration representing all of the types of tokens found in Common - * Lisp. - */ - public enum Type { - /** A left parenthesis token */ - LEFT_PAREN, - - /** A right parenthesis token */ - RIGHT_PAREN, - - /** A quoted string token */ - STRING, - - /** A quote mark */ - QUOTE_MARK, - - /** A number token */ - NUMBER, - - /** A reserved word token */ - RESERVED, - - /** An identifier token */ - IDENTIFIER, - - /** An end-of-file token */ - EOF - } - - private Type type; - private String text; - private String fName; - private int line; - private int column; - - /** - * Create a new token with the specified type, text, file name, line number - * and column number. - * - * @param type - * the type of this token - * @param text - * the text associated with this token - * @param fName - * the name of the file that this token is located in - * @param line - * the line number that this token is found on - * @param column - * the column number that this token is found on - */ - public Token(Type type, String text, String fName, int line, int column) { - this.type = type; - this.text = text; - this.fName = fName; - this.line = line; - this.column = column; - } - - /** - * Accessor method to determine the type of this token. - * - * @return - * the type of this token - */ - public Type getType() { - return type; - } - - /** - * Accessor method to determine the text associated with this token. - * - * @return - * the text associated with this token - */ - public String getText() { - return text; - } - - /** - * Accessor method to determine the name of the file that this token was - * located in. - * - * @return - * the name of the file that this token was located in - */ - public String getFName() { - return fName; - } - - /** - * Accessor method to determine the line number that this token was found - * on. - * - * @return - * the line number this token was found on - */ - public int getLine() { - return line; - } - - /** - * Accessor method to determine the column number that this token was found - * on. - * - * @return - * the column number this token was found on - */ - public int getColumn() { - return column; - } - -} diff --git a/scanner/package.html b/scanner/package.html deleted file mode 100644 index 6be4f13..0000000 --- a/scanner/package.html +++ /dev/null @@ -1,4 +0,0 @@ - - Provides the classes necessary to perform a lexical analysis of the Lisp - programming language. - diff --git a/src/scanner/LispFilterStream.class b/src/scanner/LispFilterStream.class index 4abccba6e8c81f79a275432bc128c9a7379d1d2f..c520c13a5801b8b40a006b9b16557020049e48fb 100644 GIT binary patch literal 829 zcmZuu-A)rh6#izrbYF#pklj5n;7pfMrkl7dNLdjaw$%HrsWV)rJXo zOt@>pJqMc(?h81fe$$T=B_Q?%3R)c{jRV=0L87|sH3jldLmej11Qx5ipX8yehjG2B zJN;xY=_=XYs=XJm8*z&iHXAL0T(w4AVK0%v=U1}xPJW0K^#t6Vqd;|%FxEW>RWb&w z`fc?hinfmv)obcT+-@tKq#Wce_L4A)uC{4&_COx09Zid>b%|ITHG{Z6I-tE!f86G_ zCA-HSW>E5Q9iE2*iXLWB_OOZ-4~tmxux6@dtk6_1kXoy5eK+iNUWO4>MmH5$8sC4^ zo_Ga;^7yRz`tp`o=Tp1<7>kS2X+?GBJcMz?c!RsubOI>(56&U{+;>7%Q+VZyn5Em<}^6 z24S%e*koUz1|KC;tYwO2a$g&uI2ImW{5JLk45gh8PZIDgd1fp>$_N%{Dpzt(Fk=eq yB(wL=*A%Sz=YrGxmJIta!&Xx4)+yyDZgvGamqPiE8FVv)rfQ{))Bnj8h{0cj$&h6L literal 682 zcmYjNJ#W)c6g}_x;}JJ0X@b)P$Ev~5aQD$Bd~oqO&%=e_TLzkUO-fw}>KN)9?!Wmh$* zs|wTvt_oNTB8qp9duhnP9y93eD2~z_4Ath&^WbIBih3yg9Hl0Td>aE@Z z(NzKt7?h^tGZgmHpnLcrNcMwgMKPddKu_+(6*gTpAH(%g2o z^DwZK$0g+QC}5ePd|~_WLV)57xOY1p47VyOLJn86Ea(V({q`UM6q z9jH^OCqp{(bXz5yQ(bb`&%j*eGx$fk$_2_oBT0HaC*60?ptP;x<_Na?3H%)@R?!$@ z!{S4aI}r*;VEL}lxyexfr|d$Vuqb^Gai z=owaK^lb9uy2zlI>X^hmv~hE4BSV#;{ej8YIXJWL36y_Rip4BfV9v96G|_0q&UMyu jZ%g2xMFoMpS5pHFZpN$VhV35iJoJ7^?f*Sq-L`!wu diff --git a/src/scanner/LispFilterStream.java b/src/scanner/LispFilterStream.java index d9838dc..3758442 100644 --- a/src/scanner/LispFilterStream.java +++ b/src/scanner/LispFilterStream.java @@ -1,9 +1,3 @@ -/* - * Name: Mike Cifelli - * Course: CIS 443 - Programming Languages - * Assignment: Lisp Interpreter Phase 1 - Lexical Analysis - */ - package scanner; import java.io.InputStream; @@ -11,150 +5,48 @@ import java.io.FilterInputStream; import java.io.IOException; /** - * A LispFilterStream is an input stream that returns the bytes - * from an underlying input stream with all Lisp comments removed and replaced - * with newlines. + * Replaces Lisp comments with newlines in an input stream. */ public class LispFilterStream extends FilterInputStream { private boolean inQuote; + private int nextCharacter; - /** - * Creates a LispFilterStream with the specified underlying - * InputStream. - * - * @param in - * the underlying input stream (must not be null) - */ public LispFilterStream(InputStream in) { super(in); - inQuote = false; + nextCharacter = 0; } - /** - * Reads the next byte of data from this input stream. The value byte is - * returned as an int in the range 0 to - * 255. If no byte is available because the end of the stream - * has been reached, the value -1 is returned. - * - * @return - * the next byte of data, or -1 if the end of the stream has - * been reached. - * @throws IOException - * Indicates that an I/O error has occurred. - */ @Override public int read() throws IOException { - int next = super.read(); + nextCharacter = super.read(); - if ((next == ';') && (! inQuote)) { - // we have entered a comment, consume all the bytes from the - // underlying input stream until we reach a newline character or - // the end of the stream - while ((next != '\n') && (next != -1)) { - next = super.read(); - } - } else if (next == '\n') { - inQuote = false; - } else if (next == '\"') { // we have entered or left a quoted string - inQuote = (! inQuote); + if (haveEnteredComment()) { + consumeAllBytesInComment(); + } else if (haveEncounteredStringBoundary()) { + inQuote = (!inQuote); } - return next; + return nextCharacter; } - /** - * Reads up to the specified number of data bytes from this input stream - * into an array of bytes starting at the specified offset. If no bytes are - * available because the end of this stream has been reached then - * -1 is returned. Also, If the specified number of bytes is - * more than the number of remaining data bytes in this input stream, then - * only the number of remaining data bytes are copied into the byte array. - * - * @param b - * the buffer into which the data bytes are read (must not be - * null) - * @param off - * the start offset in b at which the data is written (must - * be >= 0 and < b.length) - * @param len - * the maximum number of bytes to read into b (len + - * off must be < b.length) - * @return - * the total number of bytes read into the buffer, or -1 if - * there is no more data because the end of the stream has been reached - * @throws IOException - * Indicates that the first byte could not be read into b - * for some reason other than reaching the end of the stream. - * @throws IndexOutOfBoundsException - * Indicates that this method attempted to access an index in - * b that was either negative or greater than or equal to - * b.length as a result of the given parameters. - * @throws NullPointerException - * Indicates that b is null. - */ - @Override - public int read(byte[] b, int off, int len) throws IOException { - int bytesRead = 0; - - // make sure we are supposed to read at least one byte into 'b' - if (len > 0) { - int next = read(); - - if (next == -1) { - // there are no more bytes to read from this input stream - - return -1; - } - - int i = off; - - while (next != -1) { - ++bytesRead; - - b[i++] = (byte) next; - - if (i >= (off + len)) { // we have read 'len' bytes into 'b' - break; - } - - try { - next = read(); - } catch (IOException e) { - // treat this exception like an end of stream - - break; - } - } + private void consumeAllBytesInComment() throws IOException { + while (stillInComment()) { + nextCharacter = super.read(); } - - return bytesRead; } - /** - * Skip over and discard the specified number of bytes from this input - * stream. This method may, for a variety of reasons, end up skipping some - * smaller number of bytes, possibly 0. The actual number of - * bytes skipped is returned. - * - * @param n - * the number of bytes to be skipped - * @return - * the actual number of bytes skipped - * @throws IOException - * Indicates that an I/O error has occurred. - */ - @Override - public long skip (long n) throws IOException { - long bytesSkipped = 0; + private boolean stillInComment() { + return (nextCharacter != '\n') && (nextCharacter != -1); + } - while ((n > 0) && (read() != -1)) { - ++bytesSkipped; - --n; - } + private boolean haveEnteredComment() { + return (nextCharacter == ';') && (!inQuote); + } - return bytesSkipped; + private boolean haveEncounteredStringBoundary() { + return nextCharacter == '\"'; } } diff --git a/test/scanner/LispFilterStreamTester.java b/test/scanner/LispFilterStreamTester.java index 3de7dc6..bf27687 100644 --- a/test/scanner/LispFilterStreamTester.java +++ b/test/scanner/LispFilterStreamTester.java @@ -8,7 +8,7 @@ import org.junit.Test; public class LispFilterStreamTester { private LispFilterStream lispFilterStream; - + @Before public void setUp() throws Exception { lispFilterStream = new LispFilterStream(null); @@ -19,19 +19,4 @@ public class LispFilterStreamTester { fail("Not yet implemented"); } - @Test - public void testReadByteArrayIntInt() { - fail("Not yet implemented"); - } - - @Test - public void testSkip() { - fail("Not yet implemented"); - } - - @Test - public void testLispFilterStream() { - fail("Not yet implemented"); - } - }