Additional refactoring for eclipse
This commit is contained in:
		
							parent
							
								
									b875727361
								
							
						
					
					
						commit
						4ad31c0570
					
				| @ -1,10 +1,12 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <classpath> | <classpath> | ||||||
| 	<classpathentry kind="src" path="src"/> | 	<classpathentry kind="src" path="src"/> | ||||||
|  | 	<classpathentry kind="src" path="test"/> | ||||||
| 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"> | 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"> | ||||||
| 		<attributes> | 		<attributes> | ||||||
| 			<attribute name="owner.project.facets" value="java"/> | 			<attribute name="owner.project.facets" value="java"/> | ||||||
| 		</attributes> | 		</attributes> | ||||||
| 	</classpathentry> | 	</classpathentry> | ||||||
|  | 	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/> | ||||||
| 	<classpathentry kind="output" path="build/classes"/> | 	<classpathentry kind="output" path="build/classes"/> | ||||||
| </classpath> | </classpath> | ||||||
|  | |||||||
							
								
								
									
										13
									
								
								.project
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								.project
									
									
									
									
									
								
							| @ -15,6 +15,19 @@ | |||||||
| 			<arguments> | 			<arguments> | ||||||
| 			</arguments> | 			</arguments> | ||||||
| 		</buildCommand> | 		</buildCommand> | ||||||
|  | 		<buildCommand> | ||||||
|  | 			<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> | ||||||
|  | 			<arguments> | ||||||
|  | 				<dictionary> | ||||||
|  | 					<key>LaunchConfigHandle</key> | ||||||
|  | 					<value><project>/.externalToolBuilders/Ant_Builder.launch</value> | ||||||
|  | 				</dictionary> | ||||||
|  | 				<dictionary> | ||||||
|  | 					<key>incclean</key> | ||||||
|  | 					<value>true</value> | ||||||
|  | 				</dictionary> | ||||||
|  | 			</arguments> | ||||||
|  | 		</buildCommand> | ||||||
| 	</buildSpec> | 	</buildSpec> | ||||||
| 	<natures> | 	<natures> | ||||||
| 		<nature>org.eclipse.wst.common.project.facet.core.nature</nature> | 		<nature>org.eclipse.wst.common.project.facet.core.nature</nature> | ||||||
|  | |||||||
| @ -1,11 +1,12 @@ | |||||||
| <?xml version="1.0"?> | <?xml version="1.0"?> | ||||||
| 
 | 
 | ||||||
| <project name="LispInterpreter" basedir="." default="compile"> | <project name="LispInterpreter" basedir="." default="compile"> | ||||||
|     <property name="src.dir" value="." /> |     <property name="src.dir" value="src" /> | ||||||
|     <property name="build.dir" value="build" /> |     <property name="build.dir" value="build" /> | ||||||
|     <property name="classes.dir" value="${build.dir}/classes" /> |     <property name="classes.dir" value="${build.dir}/classes" /> | ||||||
|     <property name="jar.dir" value="jar" /> |     <property name="jar.dir" value="jar" /> | ||||||
|     <property name="doc.dir" value="doc" /> |     <property name="doc.dir" value="doc" /> | ||||||
|  | 	<property name="test.dir" value="test" /> | ||||||
|     <property name="jar-file" value="${jar.dir}/LispInterpreter.jar" /> |     <property name="jar-file" value="${jar.dir}/LispInterpreter.jar" /> | ||||||
|     <property name="main-class" value="main.LispInterpreter" /> |     <property name="main-class" value="main.LispInterpreter" /> | ||||||
| 
 | 
 | ||||||
| @ -16,11 +17,8 @@ | |||||||
|     </target> |     </target> | ||||||
| 
 | 
 | ||||||
|     <target name="compile"> |     <target name="compile"> | ||||||
|         <mkdir dir="${classes.dir}" /> |  | ||||||
|         <javac srcdir="${src.dir}" |         <javac srcdir="${src.dir}" | ||||||
|                destdir="${classes.dir}" |                includeantruntime="false" /> | ||||||
|                includeantruntime="false" |  | ||||||
|                excludes="main/LispInterpreter2.java" /> |  | ||||||
|     </target> |     </target> | ||||||
| 
 | 
 | ||||||
|     <target name="jar" depends="compile"> |     <target name="jar" depends="compile"> | ||||||
|  | |||||||
| @ -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; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>ErrorManager</code> 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 <code>level >= CRITICAL_LEVEL</code> 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); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,3 +0,0 @@ | |||||||
| <body> |  | ||||||
|     Provides a class for managing errors in the Lisp Interpreter. |  | ||||||
| </body> |  | ||||||
| @ -1,74 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>APPLY</code> 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 <code>argList</code> |  | ||||||
|      */ |  | ||||||
|     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"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,38 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>ATOM</code> 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()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,46 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>CAR</code> 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"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,46 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>CDR</code> 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"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,73 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>COND</code> 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 |  | ||||||
|      *  <code>false</code> |  | ||||||
|      */ |  | ||||||
|     public boolean evaluateArguments() { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,44 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>CONS</code> 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); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,82 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 2 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| import java.util.HashMap; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>DEFUN</code> 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<String, LispFunction> 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 |  | ||||||
|      *  <code>false</code> |  | ||||||
|      */ |  | ||||||
|     public boolean evaluateArguments() { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,60 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>DIVIDE</code> 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"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
							
								
								
									
										45
									
								
								eval/EQ.java
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								eval/EQ.java
									
									
									
									
									
								
							| @ -1,45 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>EQ</code> 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()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,58 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>EQUAL</code> 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()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,55 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>EQUALSP</code> 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"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
							
								
								
									
										251
									
								
								eval/EVAL.java
									
									
									
									
									
								
							
							
						
						
									
										251
									
								
								eval/EVAL.java
									
									
									
									
									
								
							| @ -1,251 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| import java.util.HashMap; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>EVAL</code> 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<String, LispFunction> functionTable = |  | ||||||
|             new HashMap<String, LispFunction>(); |  | ||||||
| 
 |  | ||||||
|     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<String, LispFunction> 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 <code>functionName</code> 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 <code>symbolName</code> 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 |  | ||||||
|      *  <code>true</code> if <code>list</code> is dotted; <code>false</code> |  | ||||||
|      *  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 <code>sexpr</code> |  | ||||||
|      */ |  | ||||||
|     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()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -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; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,31 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 2 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>FUNCALL</code> 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); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,55 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>GREATERP</code> 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"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
							
								
								
									
										108
									
								
								eval/LAMBDA.java
									
									
									
									
									
								
							
							
						
						
									
										108
									
								
								eval/LAMBDA.java
									
									
									
									
									
								
							| @ -1,108 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 2 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>LAMBDA</code> 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 |  | ||||||
|      *  <code>true</code> if <code>sexpr</code> is a valid lambda expression; |  | ||||||
|      *  <code>false</code> 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 |  | ||||||
|      *  <code>lexpr</code> |  | ||||||
|      * @throws RuntimeException |  | ||||||
|      *  Indicates that <code>lexpr</code> 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 |  | ||||||
|      *  <code>false</code> |  | ||||||
|      */ |  | ||||||
|     public boolean evaluateArguments() { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,69 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>LENGTH</code> 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 <code>list</code> |  | ||||||
|      */ |  | ||||||
|     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); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,55 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>LESSP</code> 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"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
							
								
								
									
										116
									
								
								eval/LET.java
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								eval/LET.java
									
									
									
									
									
								
							| @ -1,116 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 2 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>LET</code> 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 |  | ||||||
|      *  <code>false</code> |  | ||||||
|      */ |  | ||||||
|     public boolean evaluateArguments() { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,40 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>LIST</code> 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 <code>sexpr</code> 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)); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,38 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>LISTP</code> 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()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,87 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 2 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| import java.io.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>LOAD</code> 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; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -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 |  | ||||||
|      *  <code>true</code> |  | ||||||
|      */ |  | ||||||
|     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(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,44 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * A <code>LispFunction</code> 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 |  | ||||||
|      * <code>false</code> if it does not want its arguments to be evaluated |  | ||||||
|      * prior to being passed. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  <code>true</code> |  | ||||||
|      */ |  | ||||||
|     public boolean evaluateArguments() { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,60 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>MINUS</code> 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"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,34 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>MULTIPLY</code> 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"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,38 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 2 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>NULL</code> 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()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,34 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>PLUS</code> 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"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,40 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 2 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>PRINT</code> 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; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,47 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 1 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>QUOTE</code> 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 |  | ||||||
|      *  <code>false</code> |  | ||||||
|      */ |  | ||||||
|     public boolean evaluateArguments() { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
							
								
								
									
										112
									
								
								eval/SETF.java
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								eval/SETF.java
									
									
									
									
									
								
							| @ -1,112 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 2 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>SETF</code> 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 <code>symbolName</code> 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 |  | ||||||
|      *  <code>false</code> |  | ||||||
|      */ |  | ||||||
|     public boolean evaluateArguments() { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,65 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter 2 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package eval; |  | ||||||
| 
 |  | ||||||
| import parser.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>SYMBOL_FUNCTION</code> 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"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -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 <code>SymbolTable</code> maps symbol names to values. |  | ||||||
|  */ |  | ||||||
| public class SymbolTable { |  | ||||||
| 
 |  | ||||||
|     private HashMap<String, SExpression> 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<String, SExpression>(); |  | ||||||
|         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 |  | ||||||
|      *  <code>true</code> if the symbol is in this symbol table; |  | ||||||
|      *  <code>false</code> 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 <code>symbolName</code>, 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; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -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 <code>UDFunction</code> 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<String> 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<String>(); |  | ||||||
| 
 |  | ||||||
|         // 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; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,4 +0,0 @@ | |||||||
| <body> |  | ||||||
|     Provides functions and forms to be used during the evaluation of an |  | ||||||
|     S-expression. |  | ||||||
| </body> |  | ||||||
| @ -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; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>LispInterpreter</code> 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: |  | ||||||
|      *  <ul> |  | ||||||
|      *      <li><code>args[0]</code> - file name (optional)</li> |  | ||||||
|      *  </ul> |  | ||||||
|      */ |  | ||||||
|     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"); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -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); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -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.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>LispParserDriver</code> 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: |  | ||||||
|      *  <ul> |  | ||||||
|      *      <li><code>args[0]</code> - file name (optional)</li> |  | ||||||
|      *  </ul> |  | ||||||
|      */ |  | ||||||
|     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); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -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.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * <code>LispScannerDriver</code> 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: |  | ||||||
|      *  <ul> |  | ||||||
|      *      <li><code>args[0]</code> - file name (optional)</li> |  | ||||||
|      *  </ul> |  | ||||||
|      */ |  | ||||||
|     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)); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,3 +0,0 @@ | |||||||
| <body> |  | ||||||
|     Provides test drivers for the various stages of the Lisp Interpreter. |  | ||||||
| </body> |  | ||||||
| @ -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 |  | ||||||
|      *  <code>true</code> |  | ||||||
|      */ |  | ||||||
|     public boolean atomp() { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Returns a string representation of this ATOM. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  a string representation of this ATOM |  | ||||||
|      */ |  | ||||||
|     public String toString() { |  | ||||||
|         return text; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
							
								
								
									
										111
									
								
								parser/Cons.java
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								parser/Cons.java
									
									
									
									
									
								
							| @ -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 |  | ||||||
|      *  <code>true</code> |  | ||||||
|      */ |  | ||||||
|     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() + ")"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -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 <code>text</code> 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 |  | ||||||
|      *  <code>true</code> |  | ||||||
|      */ |  | ||||||
|     public boolean numberp() { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Retrieve the integer value of this NUMBER. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  the integer value of this NUMBER |  | ||||||
|      */ |  | ||||||
|     public int getValue() { |  | ||||||
|         return value; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,192 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Parser |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package parser; |  | ||||||
| 
 |  | ||||||
| import scanner.*; |  | ||||||
| import java.io.*; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * A <code>LispParser</code> converts a stream of bytes into internal |  | ||||||
|  * representations of Lisp S-expressions. When the end of stream has been |  | ||||||
|  * reached the <code>eof</code> 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 <code>LispParser</code> that produces S-expressions from |  | ||||||
|      * the specified input stream. |  | ||||||
|      * |  | ||||||
|      * @param in |  | ||||||
|      *  the input stream to obtain S-expressions from (must not be |  | ||||||
|      *  <code>null</code>) |  | ||||||
|      * @param fileName |  | ||||||
|      *  the name of the file that <code>in</code> 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 |  | ||||||
|      *  <code>true</code> if this parser has reached the end of its underlying |  | ||||||
|      *  input stream; <code>false</code> 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); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -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 |  | ||||||
|      *  <code>true</code> |  | ||||||
|      */ |  | ||||||
|     public boolean stringp() { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
							
								
								
									
										104
									
								
								parser/Nil.java
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								parser/Nil.java
									
									
									
									
									
								
							| @ -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 |  | ||||||
|      *  <code>true</code> |  | ||||||
|      */ |  | ||||||
|     public boolean nullp() { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Test if this S-expression is an ATOM. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  <code>true</code> |  | ||||||
|      */ |  | ||||||
|     public boolean atomp() { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Test if this S-expression is a CONS cell. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  <code>false</code> |  | ||||||
|      */ |  | ||||||
|     public boolean consp() { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Test if this S-expression is a SYMBOL. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  <code>true</code> |  | ||||||
|      */ |  | ||||||
|     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"; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -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 <code>SExpression</code> is marked. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  <code>true</code> if this <code>SExpression</code> is marked; |  | ||||||
|      *  <code>false</code> 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 |  | ||||||
|      *  <code>false</code> |  | ||||||
|      */ |  | ||||||
|     public boolean nullp() { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Test if this S-expression is an ATOM. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  <code>false</code> |  | ||||||
|      */ |  | ||||||
|     public boolean atomp() { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Test if this S-expression is a CONS cell. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  <code>false</code> |  | ||||||
|      */ |  | ||||||
|     public boolean consp() { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Test if this S-expression is a LIST. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  the value of <code>(consp() || nullp())</code> |  | ||||||
|      */ |  | ||||||
|     public boolean listp() { |  | ||||||
|         return (consp() || nullp()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Test if this S-expression is a NUMBER. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  <code>false</code> |  | ||||||
|      */ |  | ||||||
|     public boolean numberp() { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Test if this S-expression is a SYMBOL. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  <code>false</code> |  | ||||||
|      */ |  | ||||||
|     public boolean symbolp() { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Test if this S-expression is a FUNCTION. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  <code>false</code> |  | ||||||
|      */ |  | ||||||
|     public boolean functionp() { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Test if this S-expression is a STRING. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  <code>false</code> |  | ||||||
|      */ |  | ||||||
|     public boolean stringp() { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -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 |  | ||||||
|      *  <code>true</code> |  | ||||||
|      */ |  | ||||||
|     public boolean symbolp() { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,4 +0,0 @@ | |||||||
| <body> |  | ||||||
|     Provides the classes necessary for creating an internal representation of |  | ||||||
|     the Lisp programming language. |  | ||||||
| </body> |  | ||||||
| @ -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 <code>LispFilterStream</code> 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 <code>LispFilterStream</code> with the specified underlying |  | ||||||
|      * <code>InputStream</code>. |  | ||||||
|      * |  | ||||||
|      * @param in |  | ||||||
|      *  the underlying input stream (must not be <code>null</code>) |  | ||||||
|      */ |  | ||||||
|     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 <code>int</code> in the range <code>0</code> to |  | ||||||
|      * <code>255</code>. If no byte is available because the end of the stream |  | ||||||
|      * has been reached, the value <code>-1</code> is returned.  |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  the next byte of data, or <code>-1</code> 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 |  | ||||||
|      * <code>-1</code> 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 |  | ||||||
|      *  <code>null</code>) |  | ||||||
|      * @param off |  | ||||||
|      *  the start offset in <code>b</code> at which the data is written (must |  | ||||||
|      *  be <code>>= 0</code> and <code>< b.length</code>) |  | ||||||
|      * @param len |  | ||||||
|      *  the maximum number of bytes to read into <code>b</code> (<code>len + |  | ||||||
|      *  off</code> must be <code>< b.length</code>) |  | ||||||
|      * @return |  | ||||||
|      *  the total number of bytes read into the buffer, or <code>-1</code> 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 <code>b</code> |  | ||||||
|      *  for some reason other than reaching the end of the stream. |  | ||||||
|      * @throws IndexOutOfBoundsException |  | ||||||
|      *  Indicates that this method attempted to access an index in |  | ||||||
|      *  <code>b</code> that was either negative or greater than or equal to |  | ||||||
|      *  <code>b.length</code> as a result of the given parameters. |  | ||||||
|      * @throws NullPointerException |  | ||||||
|      *  Indicates that <code>b</code> is <code>null</code>. |  | ||||||
|      */ |  | ||||||
|     @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 <code>0</code>. 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; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -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 <code>LispScanner</code> 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 |  | ||||||
|  * <code>Token.Type.EOF</code> is returned from the <code>nextToken</code> |  | ||||||
|  * 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 <code>LispScanner</code> that produces Lisp tokens from the |  | ||||||
|      * specified input stream. |  | ||||||
|      * |  | ||||||
|      * @param in |  | ||||||
|      *  the input stream to obtain Lisp tokens from (must not be |  | ||||||
|      *  <code>null</code>) |  | ||||||
|      * @param fileName |  | ||||||
|      *  the name of the file that <code>in</code> 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 |  | ||||||
|      * <code>nextToken</code> method of this scanner. In the case that no calls |  | ||||||
|      * to <code>nextToken</code> have been made yet, this method returns |  | ||||||
|      * <code>null</code>. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  the last Lisp token returned from this scanner or <code>null</code> (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 != ';')); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,126 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter Phase 1 - Lexical Analysis |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package scanner; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * A <code>Token</code> 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; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,4 +0,0 @@ | |||||||
| <body> |  | ||||||
|     Provides the classes necessary to perform a lexical analysis of the Lisp |  | ||||||
|     programming language. |  | ||||||
| </body> |  | ||||||
										
											Binary file not shown.
										
									
								
							| @ -1,9 +1,3 @@ | |||||||
| /* |  | ||||||
|  * Name: Mike Cifelli |  | ||||||
|  * Course: CIS 443 - Programming Languages |  | ||||||
|  * Assignment: Lisp Interpreter Phase 1 - Lexical Analysis |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| package scanner; | package scanner; | ||||||
| 
 | 
 | ||||||
| import java.io.InputStream; | import java.io.InputStream; | ||||||
| @ -11,150 +5,48 @@ import java.io.FilterInputStream; | |||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * A <code>LispFilterStream</code> is an input stream that returns the bytes |  * Replaces Lisp comments with newlines in an input stream. | ||||||
|  * from an underlying input stream with all Lisp comments removed and replaced |  | ||||||
|  * with newlines. |  | ||||||
|  */ |  */ | ||||||
| public class LispFilterStream extends FilterInputStream { | public class LispFilterStream extends FilterInputStream { | ||||||
| 
 | 
 | ||||||
|     private boolean inQuote; |     private boolean inQuote; | ||||||
|  |     private int nextCharacter; | ||||||
| 
 | 
 | ||||||
|     /** |  | ||||||
|      * Creates a <code>LispFilterStream</code> with the specified underlying |  | ||||||
|      * <code>InputStream</code>. |  | ||||||
|      * |  | ||||||
|      * @param in |  | ||||||
|      *  the underlying input stream (must not be <code>null</code>) |  | ||||||
|      */ |  | ||||||
|     public LispFilterStream(InputStream in) { |     public LispFilterStream(InputStream in) { | ||||||
|         super(in); |         super(in); | ||||||
| 
 |  | ||||||
|         inQuote = false; |         inQuote = false; | ||||||
|  |         nextCharacter = 0; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |  | ||||||
|      * Reads the next byte of data from this input stream. The value byte is |  | ||||||
|      * returned as an <code>int</code> in the range <code>0</code> to |  | ||||||
|      * <code>255</code>. If no byte is available because the end of the stream |  | ||||||
|      * has been reached, the value <code>-1</code> is returned.  |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *  the next byte of data, or <code>-1</code> if the end of the stream has |  | ||||||
|      *  been reached. |  | ||||||
|      * @throws IOException |  | ||||||
|      *  Indicates that an I/O error has occurred. |  | ||||||
|      */ |  | ||||||
|     @Override |     @Override | ||||||
|     public int read() throws IOException { |     public int read() throws IOException { | ||||||
|         int next = super.read(); |         nextCharacter = super.read(); | ||||||
| 
 | 
 | ||||||
|         if ((next == ';') && (! inQuote)) { |         if (haveEnteredComment()) { | ||||||
|             // we have entered a comment, consume all the bytes from the |             consumeAllBytesInComment(); | ||||||
|             // underlying input stream until we reach a newline character or |         } else if (haveEncounteredStringBoundary()) { | ||||||
|             // the end of the stream |             inQuote = (!inQuote); | ||||||
|             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; |         return nextCharacter; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     private void consumeAllBytesInComment() throws IOException { | ||||||
|      * Reads up to the specified number of data bytes from this input stream |         while (stillInComment()) { | ||||||
|      * into an array of bytes starting at the specified offset. If no bytes are |             nextCharacter = super.read(); | ||||||
|      * available because the end of this stream has been reached then |  | ||||||
|      * <code>-1</code> 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 |  | ||||||
|      *  <code>null</code>) |  | ||||||
|      * @param off |  | ||||||
|      *  the start offset in <code>b</code> at which the data is written (must |  | ||||||
|      *  be <code>>= 0</code> and <code>< b.length</code>) |  | ||||||
|      * @param len |  | ||||||
|      *  the maximum number of bytes to read into <code>b</code> (<code>len + |  | ||||||
|      *  off</code> must be <code>< b.length</code>) |  | ||||||
|      * @return |  | ||||||
|      *  the total number of bytes read into the buffer, or <code>-1</code> 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 <code>b</code> |  | ||||||
|      *  for some reason other than reaching the end of the stream. |  | ||||||
|      * @throws IndexOutOfBoundsException |  | ||||||
|      *  Indicates that this method attempted to access an index in |  | ||||||
|      *  <code>b</code> that was either negative or greater than or equal to |  | ||||||
|      *  <code>b.length</code> as a result of the given parameters. |  | ||||||
|      * @throws NullPointerException |  | ||||||
|      *  Indicates that <code>b</code> is <code>null</code>. |  | ||||||
|      */ |  | ||||||
|     @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; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     private boolean stillInComment() { | ||||||
|      * Skip over and discard the specified number of bytes from this input |         return (nextCharacter != '\n') && (nextCharacter != -1); | ||||||
|      * stream. This method may, for a variety of reasons, end up skipping some |     } | ||||||
|      * smaller number of bytes, possibly <code>0</code>. 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)) { |     private boolean haveEnteredComment() { | ||||||
|             ++bytesSkipped; |         return (nextCharacter == ';') && (!inQuote); | ||||||
|             --n; |     } | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         return bytesSkipped; |     private boolean haveEncounteredStringBoundary() { | ||||||
|  |         return nextCharacter == '\"'; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -19,19 +19,4 @@ public class LispFilterStreamTester { | |||||||
|         fail("Not yet implemented"); |         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"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user