Minor cleaning in the eval pacakge, added unit tests for the sexpression package

This commit is contained in:
Mike Cifelli 2016-12-15 15:33:48 -05:00
parent 7b7556cc65
commit 62a509eb4b
34 changed files with 244 additions and 546 deletions

View File

@ -1,15 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>APPLY</code> represents the APPLY function in Lisp. * <code>APPLY</code> represents the APPLY function in Lisp.
@ -21,8 +12,7 @@ public class APPLY extends LispFunction {
* *
* @param argList * @param argList
* the list of arguments to be sent to APPLY (MUST BE A PROPER LIST) * the list of arguments to be sent to APPLY (MUST BE A PROPER LIST)
* @return * @return the result of evaluating APPLY on <code>argList</code>
* the result of evaluating APPLY on <code>argList</code>
*/ */
public static SExpression apply(Cons argList) { public static SExpression apply(Cons argList) {
return new APPLY().call(argList); return new APPLY().call(argList);
@ -38,9 +28,8 @@ public class APPLY extends LispFunction {
// make sure we have received the proper number of arguments // make sure we have received the proper number of arguments
if (argListLength != NUM_ARGS) { if (argListLength != NUM_ARGS) {
Cons originalSExpr = new Cons(new Symbol("APPLY"), argList); Cons originalSExpr = new Cons(new Symbol("APPLY"), argList);
String errMsg = "too " + String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to APPLY: "
((argListLength > NUM_ARGS) ? "many" : "few") + + originalSExpr;
" arguments given to APPLY: " + originalSExpr;
throw new RuntimeException(errMsg); throw new RuntimeException(errMsg);
} }

View File

@ -1,16 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>ATOM</code> represents the ATOM function in Lisp. * <code>ATOM</code> represents the ATOM function in Lisp.
@ -27,9 +17,8 @@ public class ATOM extends LispFunction {
// make sure we have received the proper number of arguments // make sure we have received the proper number of arguments
if (argListLength != NUM_ARGS) { if (argListLength != NUM_ARGS) {
Cons originalSExpr = new Cons(new Symbol("ATOM"), argList); Cons originalSExpr = new Cons(new Symbol("ATOM"), argList);
String errMsg = "too " + String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to ATOM: "
((argListLength > NUM_ARGS) ? "many" : "few") + + originalSExpr;
" arguments given to ATOM: " + originalSExpr;
throw new RuntimeException(errMsg); throw new RuntimeException(errMsg);
} }

View File

@ -1,15 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>CAR</code> represents the CAR function in Lisp. * <code>CAR</code> represents the CAR function in Lisp.

View File

@ -1,15 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>CDR</code> represents the CDR function in Lisp. * <code>CDR</code> represents the CDR function in Lisp.

View File

@ -1,15 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression;
/** /**
* <code>COND</code> represents the COND form in Lisp. * <code>COND</code> represents the COND form in Lisp.
@ -58,16 +49,13 @@ public class COND extends LispFunction {
return Nil.getUniqueInstance(); return Nil.getUniqueInstance();
} }
throw new RuntimeException("COND: clause " + argCar + throw new RuntimeException("COND: clause " + argCar + " should be a list");
" should be a list");
} }
/** /**
* Determine if the arguments passed to this Lisp function should be * Determine if the arguments passed to this Lisp function should be evaluated.
* evaluated.
* *
* @return * @return <code>false</code>
* <code>false</code>
*/ */
public boolean evaluateArguments() { public boolean evaluateArguments() {
return false; return false;

View File

@ -1,15 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>CONS</code> represents the CONS function in Lisp. * <code>CONS</code> represents the CONS function in Lisp.
@ -26,9 +17,8 @@ public class CONS extends LispFunction {
// make sure we have received the proper number of arguments // make sure we have received the proper number of arguments
if (argListLength != NUM_ARGS) { if (argListLength != NUM_ARGS) {
Cons originalSExpr = new Cons(new Symbol("CONS"), argList); Cons originalSExpr = new Cons(new Symbol("CONS"), argList);
String errMsg = "too " + String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to CONS: "
((argListLength > NUM_ARGS) ? "many" : "few") + + originalSExpr;
" arguments given to CONS: " + originalSExpr;
throw new RuntimeException(errMsg); throw new RuntimeException(errMsg);
} }

View File

@ -1,18 +1,9 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 2
*/
package eval; package eval;
import parser.*;
import sexpression.Cons;
import sexpression.SExpression;
import sexpression.Symbol;
import java.util.HashMap; import java.util.HashMap;
import sexpression.*;
/** /**
* <code>DEFUN</code> represents the DEFUN form in Lisp. * <code>DEFUN</code> represents the DEFUN form in Lisp.
*/ */
@ -28,8 +19,7 @@ public class DEFUN extends LispFunction {
// make sure we have received the proper number of arguments // make sure we have received the proper number of arguments
if (argListLength < MIN_ARGS) { if (argListLength < MIN_ARGS) {
Cons originalSExpr = new Cons(new Symbol("DEFUN"), argList); Cons originalSExpr = new Cons(new Symbol("DEFUN"), argList);
String errMsg = "too few arguments given to DEFUN: " + String errMsg = "too few arguments given to DEFUN: " + originalSExpr;
originalSExpr;
throw new RuntimeException(errMsg); throw new RuntimeException(errMsg);
} }
@ -37,7 +27,7 @@ public class DEFUN extends LispFunction {
SExpression name = argList.getCar(); // name of the function SExpression name = argList.getCar(); // name of the function
// make sure the function name is a symbol // make sure the function name is a symbol
if (! name.symbolp()) { if (!name.symbolp()) {
throw new RuntimeException("DEFUN: " + name + " is not a symbol"); throw new RuntimeException("DEFUN: " + name + " is not a symbol");
} }
@ -45,11 +35,10 @@ public class DEFUN extends LispFunction {
SExpression cadr = cdr.getCar(); SExpression cadr = cdr.getCar();
// make sure the list of arguments (lambda list) is a proper list // make sure the list of arguments (lambda list) is a proper list
if (! cadr.listp()) { if (!cadr.listp()) {
throw new RuntimeException("DEFUN: " + cadr + " is not a list"); throw new RuntimeException("DEFUN: " + cadr + " is not a list");
} else if (EVAL.isDotted((Cons) cadr)) { } else if (EVAL.isDotted((Cons) cadr)) {
throw new RuntimeException("DEFUN: " + cadr + throw new RuntimeException("DEFUN: " + cadr + " is not a proper list");
" is not a proper list");
} }
Cons lambdaList = (Cons) cadr; // lambda list of the function Cons lambdaList = (Cons) cadr; // lambda list of the function
@ -61,23 +50,19 @@ public class DEFUN extends LispFunction {
// give a warning if this function has already been defined // give a warning if this function has already been defined
if (functionTable.containsKey(name.toString())) { if (functionTable.containsKey(name.toString())) {
System.out.println("WARNING: redefining function " + System.out.println("WARNING: redefining function " + name.toString());
name.toString());
} }
// place the function in the function table // place the function in the function table
functionTable.put(name.toString(), functionTable.put(name.toString(), new UserDefinedFunction(name.toString(), lambdaList, body));
new UserDefinedFunction(name.toString(), lambdaList, body));
return name; return name;
} }
/** /**
* Determine if the arguments passed to this Lisp function should be * Determine if the arguments passed to this Lisp function should be evaluated.
* evaluated.
* *
* @return * @return <code>false</code>
* <code>false</code>
*/ */
public boolean evaluateArguments() { public boolean evaluateArguments() {
return false; return false;

View File

@ -1,16 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.LispNumber;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>DIVIDE</code> represents the '/' function in Lisp. * <code>DIVIDE</code> represents the '/' function in Lisp.
@ -22,8 +12,7 @@ public class DIVIDE extends LispFunction {
if (argList.nullp()) { if (argList.nullp()) {
Cons originalSExpr = new Cons(new Symbol("/"), argList); Cons originalSExpr = new Cons(new Symbol("/"), argList);
throw new RuntimeException("too few arguments given to /: " + throw new RuntimeException("too few arguments given to /: " + originalSExpr);
originalSExpr);
} }
SExpression argFirst = argList.getCar(); SExpression argFirst = argList.getCar();
@ -44,8 +33,7 @@ public class DIVIDE extends LispFunction {
// make sure that the next argument is a number as well // make sure that the next argument is a number as well
if (argSecond.numberp()) { if (argSecond.numberp()) {
LispNumber num2 = (LispNumber) argSecond; LispNumber num2 = (LispNumber) argSecond;
LispNumber quotient = new LispNumber(num1.getValue() / LispNumber quotient = new LispNumber(num1.getValue() / num2.getValue());
num2.getValue());
SExpression argCddr = argRest.getCdr(); SExpression argCddr = argRest.getCdr();
if (argCddr.consp()) { if (argCddr.consp()) {

View File

@ -1,16 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>EQ</code> represents the EQ function in Lisp. * <code>EQ</code> represents the EQ function in Lisp.
@ -27,9 +17,8 @@ public class EQ extends LispFunction {
// make sure we have received the proper number of arguments // make sure we have received the proper number of arguments
if (argListLength != NUM_ARGS) { if (argListLength != NUM_ARGS) {
Cons originalSExpr = new Cons(new Symbol("EQ"), argList); Cons originalSExpr = new Cons(new Symbol("EQ"), argList);
String errMsg = "too " + String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to EQ: "
((argListLength > NUM_ARGS) ? "many" : "few") + + originalSExpr;
" arguments given to EQ: " + originalSExpr;
throw new RuntimeException(errMsg); throw new RuntimeException(errMsg);
} }
@ -39,8 +28,7 @@ public class EQ extends LispFunction {
SExpression argTwo = cdr.getCar(); // second argumnet SExpression argTwo = cdr.getCar(); // second argumnet
if (argOne.atomp() && argTwo.atomp()) { if (argOne.atomp() && argTwo.atomp()) {
return ((argOne.toString().equals(argTwo.toString())) return ((argOne.toString().equals(argTwo.toString())) ? Symbol.T : Nil.getUniqueInstance());
? Symbol.T : Nil.getUniqueInstance());
} }
return ((argOne == argTwo) ? Symbol.T : Nil.getUniqueInstance()); return ((argOne == argTwo) ? Symbol.T : Nil.getUniqueInstance());

View File

@ -1,16 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>EQUAL</code> represents the EQUAL function in Lisp. * <code>EQUAL</code> represents the EQUAL function in Lisp.
@ -27,9 +17,8 @@ public class EQUAL extends LispFunction {
// make sure we have received the proper number of arguments // make sure we have received the proper number of arguments
if (argListLength != NUM_ARGS) { if (argListLength != NUM_ARGS) {
Cons originalSExpr = new Cons(new Symbol("EQUAL"), argList); Cons originalSExpr = new Cons(new Symbol("EQUAL"), argList);
String errMsg = "too " + String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to EQUAL: "
((argListLength > NUM_ARGS) ? "many" : "few") + + originalSExpr;
" arguments given to EQUAL: " + originalSExpr;
throw new RuntimeException(errMsg); throw new RuntimeException(errMsg);
} }
@ -46,17 +35,13 @@ public class EQUAL extends LispFunction {
SExpression listOneCdr = listOne.getCdr(); SExpression listOneCdr = listOne.getCdr();
SExpression listTwoCdr = listTwo.getCdr(); SExpression listTwoCdr = listTwo.getCdr();
SExpression carEqual = SExpression carEqual = call(new Cons(listOneCar, LIST.makeList(listTwoCar)));
call(new Cons(listOneCar, LIST.makeList(listTwoCar))); SExpression cdrEqual = call(new Cons(listOneCdr, LIST.makeList(listTwoCdr)));
SExpression cdrEqual =
call(new Cons(listOneCdr, LIST.makeList(listTwoCdr)));
return (((carEqual == Symbol.T) && (cdrEqual == Symbol.T)) return (((carEqual == Symbol.T) && (cdrEqual == Symbol.T)) ? Symbol.T : Nil.getUniqueInstance());
? Symbol.T : Nil.getUniqueInstance());
} }
return ((argOne.toString().equals(argTwo.toString())) return ((argOne.toString().equals(argTwo.toString())) ? Symbol.T : Nil.getUniqueInstance());
? Symbol.T : Nil.getUniqueInstance());
} }
} }

View File

@ -1,17 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.LispNumber;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>EQUALSP</code> represents the '=' function in Lisp. * <code>EQUALSP</code> represents the '=' function in Lisp.
@ -23,8 +12,7 @@ public class EQUALSP extends LispFunction {
if (argList.nullp()) { if (argList.nullp()) {
Cons originalSExpr = new Cons(new Symbol("="), argList); Cons originalSExpr = new Cons(new Symbol("="), argList);
throw new RuntimeException("too few arguments given to =: " + throw new RuntimeException("too few arguments given to =: " + originalSExpr);
originalSExpr);
} }
SExpression firstArg = argList.getCar(); SExpression firstArg = argList.getCar();

View File

@ -1,27 +1,16 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*;
import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
import java.util.HashMap; import java.util.HashMap;
import sexpression.*;
/** /**
* <code>EVAL</code> represents the EVAL function in Lisp. * <code>EVAL</code> represents the EVAL function in Lisp.
*/ */
public class EVAL extends LispFunction { public class EVAL extends LispFunction {
// A table to contain all the built-in and user-defined Lisp functions. // A table to contain all the built-in and user-defined Lisp functions.
private static HashMap<String, LispFunction> functionTable = private static HashMap<String, LispFunction> functionTable = new HashMap<String, LispFunction>();
new HashMap<String, LispFunction>();
static { static {
// place all of the built-in functions into the function table // place all of the built-in functions into the function table
@ -63,8 +52,7 @@ public class EVAL extends LispFunction {
/** /**
* Retrieve the function table. * Retrieve the function table.
* *
* @return * @return the function table
* the function table
*/ */
public static HashMap<String, LispFunction> getFunctionTable() { public static HashMap<String, LispFunction> getFunctionTable() {
return functionTable; return functionTable;
@ -75,9 +63,7 @@ public class EVAL extends LispFunction {
* *
* @param functionName * @param functionName
* the name of the function to look up * the name of the function to look up
* @return * @return the function with the name <code>functionName</code> if it exists; null otherwise
* the function with the name <code>functionName</code> if it exists; null
* otherwise
*/ */
public static LispFunction lookupFunction(String functionName) { public static LispFunction lookupFunction(String functionName) {
return functionTable.get(functionName); return functionTable.get(functionName);
@ -88,8 +74,7 @@ public class EVAL extends LispFunction {
* *
* @param symbolName * @param symbolName
* the name of the symbol to look up (must not be null) * the name of the symbol to look up (must not be null)
* @return * @return the value of <code>symbolName</code> if it has one; null otherwise
* the value of <code>symbolName</code> if it has one; null otherwise
*/ */
public static SExpression lookupSymbol(String symbolName) { public static SExpression lookupSymbol(String symbolName) {
if (symbolName.equals("NIL")) { if (symbolName.equals("NIL")) {
@ -108,9 +93,7 @@ public class EVAL extends LispFunction {
* *
* @param list * @param list
* the list to be tested (must not be null) * the list to be tested (must not be null)
* @return * @return <code>true</code> if <code>list</code> is dotted; <code>false</code> otherwise
* <code>true</code> if <code>list</code> is dotted; <code>false</code>
* otherwise
*/ */
public static boolean isDotted(Cons list) { public static boolean isDotted(Cons list) {
if (list.nullp()) { if (list.nullp()) {
@ -132,8 +115,7 @@ public class EVAL extends LispFunction {
* *
* @param sexpr * @param sexpr
* the S-expression to evaluate * the S-expression to evaluate
* @return * @return the value of <code>sexpr</code>
* the value of <code>sexpr</code>
*/ */
public static SExpression eval(SExpression sexpr) { public static SExpression eval(SExpression sexpr) {
Cons expList = LIST.makeList(sexpr); Cons expList = LIST.makeList(sexpr);
@ -152,9 +134,8 @@ public class EVAL extends LispFunction {
// make sure we have received the proper number of arguments // make sure we have received the proper number of arguments
if (argListLength != NUM_ARGS) { if (argListLength != NUM_ARGS) {
Cons originalSExpr = new Cons(new Symbol("EVAL"), argList); Cons originalSExpr = new Cons(new Symbol("EVAL"), argList);
String errMsg = "too " + String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to EVAL: "
((argListLength > NUM_ARGS) ? "many" : "few") + + originalSExpr;
" arguments given to EVAL: " + originalSExpr;
throw new RuntimeException(errMsg); throw new RuntimeException(errMsg);
} }
@ -212,8 +193,7 @@ public class EVAL extends LispFunction {
// make sure the list of arguments is not dotted // make sure the list of arguments is not dotted
if (isDotted(args)) { if (isDotted(args)) {
throw new RuntimeException("argument list given to " + car + throw new RuntimeException("argument list given to " + car + " is dotted: " + list);
" is dotted: " + list);
} }
// determine if we should evaluate the arguments that will be // determine if we should evaluate the arguments that will be
@ -226,8 +206,7 @@ public class EVAL extends LispFunction {
} }
// the list of arguments is not a list! // the list of arguments is not a list!
throw new RuntimeException("argument list given to " + car + throw new RuntimeException("argument list given to " + car + " is dotted: " + list);
" is dotted: " + list);
} }
// Evaluate a list of arguments for a function. // Evaluate a list of arguments for a function.

View File

@ -1,9 +1,6 @@
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.SExpression;
import sexpression.Symbol;
public class EXIT extends LispFunction { public class EXIT extends LispFunction {

View File

@ -1,15 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 2
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>FUNCALL</code> represents the FUNCALL function in Lisp. * <code>FUNCALL</code> represents the FUNCALL function in Lisp.
@ -21,8 +12,7 @@ public class FUNCALL extends LispFunction {
if (argList.nullp()) { if (argList.nullp()) {
Cons originalSExpr = new Cons(new Symbol("FUNCALL"), argList); Cons originalSExpr = new Cons(new Symbol("FUNCALL"), argList);
throw new RuntimeException("too few arguments given to FUNCALL: " + throw new RuntimeException("too few arguments given to FUNCALL: " + originalSExpr);
originalSExpr);
} }
SExpression cdr = argList.getCdr(); SExpression cdr = argList.getCdr();

View File

@ -1,17 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.LispNumber;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>GREATERP</code> represents the '&gt;' function in Lisp. * <code>GREATERP</code> represents the '&gt;' function in Lisp.
@ -23,8 +12,7 @@ public class GREATERP extends LispFunction {
if (argList.nullp()) { if (argList.nullp()) {
Cons originalSExpr = new Cons(new Symbol(">"), argList); Cons originalSExpr = new Cons(new Symbol(">"), argList);
throw new RuntimeException("too few arguments given to >: " + throw new RuntimeException("too few arguments given to >: " + originalSExpr);
originalSExpr);
} }
SExpression firstArg = argList.getCar(); SExpression firstArg = argList.getCar();

View File

@ -1,15 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 2
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>LAMBDA</code> represents the LAMBDA form in Lisp. * <code>LAMBDA</code> represents the LAMBDA form in Lisp.
@ -21,8 +12,7 @@ public class LAMBDA extends LispFunction {
* *
* @param sexpr * @param sexpr
* the S-expression to test (must not be null) * the S-expression to test (must not be null)
* @return * @return <code>true</code> if <code>sexpr</code> is a valid lambda expression;
* <code>true</code> if <code>sexpr</code> is a valid lambda expression;
* <code>false</code> otherwise * <code>false</code> otherwise
*/ */
public static boolean isLambdaExpression(SExpression sexpr) { public static boolean isLambdaExpression(SExpression sexpr) {
@ -36,14 +26,12 @@ public class LAMBDA extends LispFunction {
} }
/** /**
* Create an internal representation of a user-defined function from the * Create an internal representation of a user-defined function from the specified lambda
* specified lambda expression. * expression.
* *
* @param lexpr * @param lexpr
* the lambda expression to create the function from (must not be null) * the lambda expression to create the function from (must not be null)
* @return * @return an internal representation of a user-defined function created from <code>lexpr</code>
* an internal representation of a user-defined function created from
* <code>lexpr</code>
* @throws RuntimeException * @throws RuntimeException
* Indicates that <code>lexpr</code> is not a valid lambda expression. * Indicates that <code>lexpr</code> is not a valid lambda expression.
*/ */
@ -52,7 +40,7 @@ public class LAMBDA extends LispFunction {
SExpression cdr = lexpr.getCdr(); SExpression cdr = lexpr.getCdr();
// make sure lexpr is a proper list // make sure lexpr is a proper list
if (! cdr.consp()) { if (!cdr.consp()) {
throw new RuntimeException("invalid lambda expression"); throw new RuntimeException("invalid lambda expression");
} else if (EVAL.isDotted((Cons) cdr)) { } else if (EVAL.isDotted((Cons) cdr)) {
throw new RuntimeException("dotted lambda expression " + lexpr); throw new RuntimeException("dotted lambda expression " + lexpr);
@ -73,8 +61,7 @@ public class LAMBDA extends LispFunction {
// make sure we have received the proper number of arguments // make sure we have received the proper number of arguments
if (argListLength < MIN_ARGS) { if (argListLength < MIN_ARGS) {
Cons originalSExpr = new Cons(new Symbol("LAMBDA"), argList); Cons originalSExpr = new Cons(new Symbol("LAMBDA"), argList);
String errMsg = "too few arguments given to LAMBDA: " + String errMsg = "too few arguments given to LAMBDA: " + originalSExpr;
originalSExpr;
throw new RuntimeException(errMsg); throw new RuntimeException(errMsg);
} }
@ -82,11 +69,10 @@ public class LAMBDA extends LispFunction {
SExpression car = argList.getCar(); SExpression car = argList.getCar();
// make sure the list of arguments is a proper list // make sure the list of arguments is a proper list
if (! car.listp()) { if (!car.listp()) {
throw new RuntimeException("LAMBDA: " + car + " is not a list"); throw new RuntimeException("LAMBDA: " + car + " is not a list");
} else if (EVAL.isDotted((Cons) car)) { } else if (EVAL.isDotted((Cons) car)) {
throw new RuntimeException("LAMBDA: " + car + throw new RuntimeException("LAMBDA: " + car + " must be a proper list");
" must be a proper list");
} }
Cons lambdaList = (Cons) car; Cons lambdaList = (Cons) car;
@ -98,11 +84,9 @@ public class LAMBDA extends LispFunction {
} }
/** /**
* Determine if the arguments passed to this Lisp function should be * Determine if the arguments passed to this Lisp function should be evaluated.
* evaluated.
* *
* @return * @return <code>false</code>
* <code>false</code>
*/ */
public boolean evaluateArguments() { public boolean evaluateArguments() {
return false; return false;

View File

@ -1,16 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.LispNumber;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>LENGTH</code> represents the LENGTH function in Lisp. * <code>LENGTH</code> represents the LENGTH function in Lisp.

View File

@ -1,17 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.LispNumber;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>LESSP</code> represents the '&lt;' function in Lisp. * <code>LESSP</code> represents the '&lt;' function in Lisp.
@ -23,8 +12,7 @@ public class LESSP extends LispFunction {
if (argList.nullp()) { if (argList.nullp()) {
Cons originalSExpr = new Cons(new Symbol("<"), argList); Cons originalSExpr = new Cons(new Symbol("<"), argList);
throw new RuntimeException("too few arguments given to <: " + throw new RuntimeException("too few arguments given to <: " + originalSExpr);
originalSExpr);
} }
SExpression firstArg = argList.getCar(); SExpression firstArg = argList.getCar();

View File

@ -1,15 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 2
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression;
/** /**
* <code>LET</code> represents the LET form in Lisp. * <code>LET</code> represents the LET form in Lisp.
@ -58,13 +49,10 @@ public class LET extends LispFunction {
// Precondition: 'environment' and 'vars' must not be null. // Precondition: 'environment' and 'vars' must not be null.
// Postcondition: All of the variables in 'vars' have been placed into // Postcondition: All of the variables in 'vars' have been placed into
// 'environment' with their values. // 'environment' with their values.
private void addVariablesToTable(SymbolTable environment, private void addVariablesToTable(SymbolTable environment, SExpression vars) {
SExpression vars) {
// makes sure the list of variable/value pairs is a list // makes sure the list of variable/value pairs is a list
if (! vars.listp()) { if (!vars.listp()) {
throw new RuntimeException("LET: " + vars + throw new RuntimeException("LET: " + vars + " is not a properly formatted" + " variable/value pair list");
" is not a properly formatted" +
" variable/value pair list");
} }
// add all variables in 'vars' to 'environment' // add all variables in 'vars' to 'environment'
@ -73,10 +61,9 @@ public class LET extends LispFunction {
SExpression varListCar = varList.getCar(); SExpression varListCar = varList.getCar();
// make sure this variable/value pair is a list // make sure this variable/value pair is a list
if (! varListCar.consp()) { if (!varListCar.consp()) {
throw new RuntimeException("LET: " + varListCar + throw new RuntimeException("LET: " + varListCar + " is not a properly formatted"
" is not a properly formatted" + + " variable/value pair");
" variable/value pair");
} }
Cons varSpec = (Cons) varListCar; Cons varSpec = (Cons) varListCar;
@ -84,9 +71,8 @@ public class LET extends LispFunction {
SExpression varSpecCdr = varSpec.getCdr(); SExpression varSpecCdr = varSpec.getCdr();
// make sure this variable pair has a value associated with it // make sure this variable pair has a value associated with it
if (! varSpecCdr.consp()) { if (!varSpecCdr.consp()) {
throw new RuntimeException("LET: illegal variable " + throw new RuntimeException("LET: illegal variable " + "specification " + varSpec);
"specification " + varSpec);
} }
Cons varValue = (Cons) varSpecCdr; Cons varValue = (Cons) varSpecCdr;
@ -94,9 +80,8 @@ public class LET extends LispFunction {
// make sure there are no more members of this variable/value pair // make sure there are no more members of this variable/value pair
// and that 'symbol' is actually a symbol // and that 'symbol' is actually a symbol
if ((! varValue.getCdr().nullp()) || (! symbol.symbolp())) { if ((!varValue.getCdr().nullp()) || (!symbol.symbolp())) {
throw new RuntimeException("LET: illegal variable " + throw new RuntimeException("LET: illegal variable " + "specification " + varSpec);
"specification " + varSpec);
} }
environment.put(symbol.toString(), value); environment.put(symbol.toString(), value);
@ -106,11 +91,9 @@ public class LET extends LispFunction {
} }
/** /**
* Determine if the arguments passed to this Lisp function should be * Determine if the arguments passed to this Lisp function should be evaluated.
* evaluated.
* *
* @return * @return <code>false</code>
* <code>false</code>
*/ */
public boolean evaluateArguments() { public boolean evaluateArguments() {
return false; return false;

View File

@ -1,15 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression;
/** /**
* <code>LIST</code> represents the LIST function in Lisp. * <code>LIST</code> represents the LIST function in Lisp.

View File

@ -1,16 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>LISTP</code> represents the LISTP function in Lisp. * <code>LISTP</code> represents the LISTP function in Lisp.
@ -27,9 +17,8 @@ public class LISTP extends LispFunction {
// make sure we have received the proper number of arguments // make sure we have received the proper number of arguments
if (argListLength != NUM_ARGS) { if (argListLength != NUM_ARGS) {
Cons originalSExpr = new Cons(new Symbol("LISTP"), argList); Cons originalSExpr = new Cons(new Symbol("LISTP"), argList);
String errMsg = "too " + String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to LISTP: "
((argListLength > NUM_ARGS) ? "many" : "few") + + originalSExpr;
" arguments given to LISTP: " + originalSExpr;
throw new RuntimeException(errMsg); throw new RuntimeException(errMsg);
} }

View File

@ -1,19 +1,10 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 2
*/
package eval; package eval;
import parser.*; import java.io.FileInputStream;
import sexpression.Cons; import java.io.FileNotFoundException;
import sexpression.LispString;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
import java.io.*; import parser.LispParser;
import sexpression.*;
/** /**
* <code>LOAD</code> represents the LOAD function in Lisp. * <code>LOAD</code> represents the LOAD function in Lisp.

View File

@ -1,12 +1,5 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 2
*/
package eval; package eval;
import parser.*;
import sexpression.Cons; import sexpression.Cons;
import sexpression.SExpression; import sexpression.SExpression;
@ -19,8 +12,7 @@ public class LambdaExpression extends SExpression {
private UserDefinedFunction function; private UserDefinedFunction function;
/** /**
* Create a new FUNCTION with the specified lambda expression and * Create a new FUNCTION with the specified lambda expression and internal representation.
* internal representation.
* *
* @param lexpr * @param lexpr
* the lambda expression of this FUNCTION * the lambda expression of this FUNCTION
@ -35,8 +27,7 @@ public class LambdaExpression extends SExpression {
/** /**
* Test if this S-expression is a FUNCTION. * Test if this S-expression is a FUNCTION.
* *
* @return * @return <code>true</code>
* <code>true</code>
*/ */
public boolean functionp() { public boolean functionp() {
return true; return true;
@ -45,8 +36,7 @@ public class LambdaExpression extends SExpression {
/** /**
* Retrieve the lambda expression of this FUNCTION. * Retrieve the lambda expression of this FUNCTION.
* *
* @return * @return the lambda expression of this FUNCTION
* the lambda expression of this FUNCTION
*/ */
public Cons getLExpression() { public Cons getLExpression() {
return lexpr; return lexpr;
@ -55,8 +45,7 @@ public class LambdaExpression extends SExpression {
/** /**
* Retrieve the internal representation of this FUNCTION. * Retrieve the internal representation of this FUNCTION.
* *
* @return * @return the user-defined function of this FUNCTION
* the user-defined function of this FUNCTION
*/ */
public UserDefinedFunction getFunction() { public UserDefinedFunction getFunction() {
return function; return function;
@ -65,8 +54,7 @@ public class LambdaExpression extends SExpression {
/** /**
* Returns a string representation of this FUNCTION. * Returns a string representation of this FUNCTION.
* *
* @return * @return a string representation of this FUNCTION
* a string representation of this FUNCTION
*/ */
public String toString() { public String toString() {
return lexpr.toString(); return lexpr.toString();

View File

@ -1,18 +1,11 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*;
import sexpression.Cons; import sexpression.Cons;
import sexpression.SExpression; import sexpression.SExpression;
/** /**
* A <code>LispFunction</code> is an internal representation of a built-in * A <code>LispFunction</code> is an internal representation of a built-in function in the Lisp
* function in the Lisp programming language. * programming language.
*/ */
public abstract class LispFunction { public abstract class LispFunction {
@ -21,23 +14,19 @@ public abstract class LispFunction {
* *
* @param argList * @param argList
* the list of arguments to pass to this function (MUST BE A PROPER LIST) * the list of arguments to pass to this function (MUST BE A PROPER LIST)
* @return * @return the resulting S-expression of calling this function with the specified arguments
* the resulting S-expression of calling this function with the specified
* arguments
* @throws RuntimeException * @throws RuntimeException
* Indicates that an incorrect number of arguments has been passed to this * Indicates that an incorrect number of arguments has been passed to this function
* function or that one of the arguments is not of the expected type. * or that one of the arguments is not of the expected type.
*/ */
public abstract SExpression call(Cons argList); public abstract SExpression call(Cons argList);
/** /**
* Determine if the arguments passed to this Lisp function should be * Determine if the arguments passed to this Lisp function should be evaluated. A subclass
* evaluated. A subclass should override this method to return * should override this method to return <code>false</code> if it does not want its arguments to
* <code>false</code> if it does not want its arguments to be evaluated * be evaluated prior to being passed.
* prior to being passed.
* *
* @return * @return <code>true</code>
* <code>true</code>
*/ */
public boolean evaluateArguments() { public boolean evaluateArguments() {
return true; return true;

View File

@ -1,16 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.LispNumber;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>MINUS</code> represents the '-' function in Lisp. * <code>MINUS</code> represents the '-' function in Lisp.
@ -22,8 +12,7 @@ public class MINUS extends LispFunction {
if (argList.nullp()) { if (argList.nullp()) {
Cons originalSExpr = new Cons(new Symbol("-"), argList); Cons originalSExpr = new Cons(new Symbol("-"), argList);
throw new RuntimeException("too few arguments given to -: " + throw new RuntimeException("too few arguments given to -: " + originalSExpr);
originalSExpr);
} }
SExpression argFirst = argList.getCar(); SExpression argFirst = argList.getCar();
@ -36,7 +25,7 @@ public class MINUS extends LispFunction {
if (argRest.nullp()) { if (argRest.nullp()) {
// there is only one argument, so return the additive // there is only one argument, so return the additive
// inverse of the number // inverse of the number
return new LispNumber(- num1.getValue()); return new LispNumber(-num1.getValue());
} }
SExpression argSecond = argRest.getCar(); SExpression argSecond = argRest.getCar();
@ -44,8 +33,7 @@ public class MINUS extends LispFunction {
// make sure that the next argument is a number as well // make sure that the next argument is a number as well
if (argSecond.numberp()) { if (argSecond.numberp()) {
LispNumber num2 = (LispNumber) argSecond; LispNumber num2 = (LispNumber) argSecond;
LispNumber difference = new LispNumber(num1.getValue() - LispNumber difference = new LispNumber(num1.getValue() - num2.getValue());
num2.getValue());
SExpression argCddr = argRest.getCdr(); SExpression argCddr = argRest.getCdr();
if (argCddr.consp()) { if (argCddr.consp()) {

View File

@ -1,15 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.LispNumber;
import sexpression.SExpression;
/** /**
* <code>MULTIPLY</code> represents the '*' function in Lisp. * <code>MULTIPLY</code> represents the '*' function in Lisp.

View File

@ -1,16 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 2
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>NULL</code> represents the NULL function in Lisp. * <code>NULL</code> represents the NULL function in Lisp.
@ -27,9 +17,8 @@ public class NULL extends LispFunction {
// make sure we have received the proper number of arguments // make sure we have received the proper number of arguments
if (argListLength != NUM_ARGS) { if (argListLength != NUM_ARGS) {
Cons originalSExpr = new Cons(new Symbol("NULL"), argList); Cons originalSExpr = new Cons(new Symbol("NULL"), argList);
String errMsg = "too " + String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to NULL: "
((argListLength > NUM_ARGS) ? "many" : "few") + + originalSExpr;
" arguments given to NULL: " + originalSExpr;
throw new RuntimeException(errMsg); throw new RuntimeException(errMsg);
} }

View File

@ -1,15 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.LispNumber;
import sexpression.SExpression;
/** /**
* <code>PLUS</code> represents the '+' function in Lisp. * <code>PLUS</code> represents the '+' function in Lisp.

View File

@ -1,15 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 2
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>PRINT</code> represents the PRINT function in Lisp. * <code>PRINT</code> represents the PRINT function in Lisp.
@ -26,9 +17,8 @@ public class PRINT extends LispFunction {
// make sure we have received the proper number of arguments // make sure we have received the proper number of arguments
if (argListLength != NUM_ARGS) { if (argListLength != NUM_ARGS) {
Cons originalSExpr = new Cons(new Symbol("PRINT"), argList); Cons originalSExpr = new Cons(new Symbol("PRINT"), argList);
String errMsg = "too " + String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to PRINT: "
((argListLength > NUM_ARGS) ? "many" : "few") + + originalSExpr;
" arguments given to PRINT: " + originalSExpr;
throw new RuntimeException(errMsg); throw new RuntimeException(errMsg);
} }

View File

@ -1,15 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 1
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>QUOTE</code> represents the QUOTE form in Lisp. * <code>QUOTE</code> represents the QUOTE form in Lisp.

View File

@ -1,15 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 2
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>SETF</code> represents the SETF form in Lisp. * <code>SETF</code> represents the SETF form in Lisp.

View File

@ -1,15 +1,6 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 2
*/
package eval; package eval;
import parser.*; import sexpression.*;
import sexpression.Cons;
import sexpression.SExpression;
import sexpression.Symbol;
/** /**
* <code>SYMBOL_FUNCTION</code> represents the SYMBOL-FUNCTION function in * <code>SYMBOL_FUNCTION</code> represents the SYMBOL-FUNCTION function in

View File

@ -1,16 +1,9 @@
/*
* Name: Mike Cifelli
* Course: CIS 443 - Programming Languages
* Assignment: Lisp Interpreter 2
*/
package eval; package eval;
import parser.*;
import sexpression.SExpression;
import java.util.HashMap; import java.util.HashMap;
import sexpression.SExpression;
/** /**
* A <code>SymbolTable</code> maps symbol names to values. * A <code>SymbolTable</code> maps symbol names to values.
*/ */
@ -42,36 +35,31 @@ public class SymbolTable {
* *
* @param symbolName * @param symbolName
* the name of the symbol to look up * the name of the symbol to look up
* @return * @return <code>true</code> if the symbol is in this symbol table; <code>false</code> otherwise
* <code>true</code> if the symbol is in this symbol table;
* <code>false</code> otherwise
*/ */
public boolean contains(String symbolName) { public boolean contains(String symbolName) {
return table.containsKey(symbolName); return table.containsKey(symbolName);
} }
/** /**
* Returns the value to which the specified symbol name is mapped in this * Returns the value to which the specified symbol name is mapped in this symbol table.
* symbol table.
* *
* @param symbolName * @param symbolName
* the name of the symbol whose associated value is to be returned * the name of the symbol whose associated value is to be returned
* @return * @return the value to which this symbol table maps <code>symbolName</code>, or null if no
* the value to which this symbol table maps <code>symbolName</code>, or * mapping exists
* null if no mapping exists
*/ */
public SExpression get(String symbolName) { public SExpression get(String symbolName) {
return table.get(symbolName); return table.get(symbolName);
} }
/** /**
* Associates the specified symbol name with the specified value in this * Associates the specified symbol name with the specified value in this symbol table. If the
* symbol table. If the symbol table previously contained a mapping for * symbol table previously contained a mapping for this symbol name, the old value has been
* this symbol name, the old value has been replaced. * replaced.
* *
* @param symbolName * @param symbolName
* the name of the symbol with which the specified value is to be * the name of the symbol with which the specified value is to be associated
* associated
* @param value * @param value
* the value to be associated with the specified symbol name * the value to be associated with the specified symbol name
*/ */
@ -82,8 +70,7 @@ public class SymbolTable {
/** /**
* Returns the parent of this symbol table. * Returns the parent of this symbol table.
* *
* @return * @return the parent of this symbol table
* the parent of this symbol table
*/ */
public SymbolTable getParent() { public SymbolTable getParent() {
return parent; return parent;

View File

@ -0,0 +1,70 @@
package sexpression;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
public class SExpressionTester {
private void assertSExpressionMatchesString(String expected, SExpression sExpression) {
assertEquals(expected, sExpression.toString());
}
@Before
public void setUp() throws Exception {}
@Test
public void testNilToString() {
String input = "NIL";
assertSExpressionMatchesString(input, Nil.getUniqueInstance());
}
@Test
public void testNumberToString() {
String input = "12";
assertSExpressionMatchesString(input, new LispNumber(input));
}
@Test
public void testNumberValueToString() {
String expected = "12";
assertSExpressionMatchesString(expected, new LispNumber(12));
}
@Test
public void testStringToString() {
String input = "\"hi\"";
assertSExpressionMatchesString(input, new LispString(input));
}
@Test
public void testSymbolToString() {
String input = "symbol";
assertSExpressionMatchesString(input.toUpperCase(), new Symbol(input));
}
@Test
public void testSimpleConsToString() {
String expected = "(1)";
Cons cons = new Cons(new LispNumber(1), Nil.getUniqueInstance());
assertSExpressionMatchesString(expected, cons);
}
@Test
public void testComplexConsToString() {
String expected = "(1 A \"string\")";
Cons list = new Cons(new LispNumber(1),
new Cons(new Symbol("a"),
new Cons(new LispString("\"string\""), Nil.getUniqueInstance())));
assertSExpressionMatchesString(expected, list);
}
}