Added special functions (forms) and refactored internal s-expression predicates

This commit is contained in:
Mike Cifelli 2017-02-25 17:29:37 -05:00
parent b9466d2c5d
commit 4f4bc8f71a
36 changed files with 142 additions and 152 deletions

View File

@ -65,10 +65,10 @@ public class ArgumentValidator {
private void validateListNotDotted(Cons argumentList) { private void validateListNotDotted(Cons argumentList) {
SExpression next = argumentList.getRest(); SExpression next = argumentList.getRest();
for (Cons current = argumentList; next.consp(); next = current.getRest()) for (Cons current = argumentList; next.isCons(); next = current.getRest())
current = (Cons) next; current = (Cons) next;
if (!next.nullp()) if (!next.isNull())
throw new DottedArgumentListException(functionName, argumentList); throw new DottedArgumentListException(functionName, argumentList);
} }
@ -114,7 +114,7 @@ public class ArgumentValidator {
} }
private boolean isFirstArgumentValid(Cons argumentList) { private boolean isFirstArgumentValid(Cons argumentList) {
return argumentList.nullp() || isExpectedFirstArgumentType(argumentList.getFirst()); return argumentList.isNull() || isExpectedFirstArgumentType(argumentList.getFirst());
} }
private boolean isExpectedFirstArgumentType(SExpression firstArgument) { private boolean isExpectedFirstArgumentType(SExpression firstArgument) {
@ -122,11 +122,11 @@ public class ArgumentValidator {
} }
private boolean isDisallowedNil(SExpression argument) { private boolean isDisallowedNil(SExpression argument) {
return !isNilAcceptable && argument.nullp(); return !isNilAcceptable && argument.isNull();
} }
private void validateTrailingArguments(Cons argumentList) { private void validateTrailingArguments(Cons argumentList) {
for (Cons cons = (Cons) argumentList.getRest(); !cons.nullp(); cons = (Cons) cons.getRest()) for (Cons cons = (Cons) argumentList.getRest(); !cons.isNull(); cons = (Cons) cons.getRest())
if (!isExpectedTrailingArgumentType(cons.getFirst())) if (!isExpectedTrailingArgumentType(cons.getFirst()))
throw new BadArgumentTypeException(functionName, cons.getFirst(), trailingArgumentType); throw new BadArgumentTypeException(functionName, cons.getFirst(), trailingArgumentType);
} }

View File

@ -6,11 +6,6 @@ public abstract class LispFunction {
public abstract SExpression call(Cons argList); public abstract SExpression call(Cons argList);
/**
* Determine if the arguments passed to this Lisp function should be evaluated. A subclass
* should override this method to return false if it does not want its arguments to be evaluated
* prior to being passed.
*/
public boolean evaluateArguments() { public boolean evaluateArguments() {
return true; return true;
} }

View File

@ -0,0 +1,10 @@
package function;
public abstract class LispSpecialFunction extends LispFunction {
@Override
public boolean evaluateArguments() {
return false;
}
}

View File

@ -24,7 +24,7 @@ public class UserDefinedFunction extends LispFunction {
this.executionContext = ExecutionContext.getInstance(); this.executionContext = ExecutionContext.getInstance();
this.functionScope = executionContext.getScope(); this.functionScope = executionContext.getScope();
for (this.formalParameters = new ArrayList<>(); lambdaList.consp(); lambdaList = (Cons) lambdaList.getRest()) for (this.formalParameters = new ArrayList<>(); lambdaList.isCons(); lambdaList = (Cons) lambdaList.getRest())
this.formalParameters.add(lambdaList.getFirst().toString()); this.formalParameters.add(lambdaList.getFirst().toString());
this.argumentValidator = new ArgumentValidator(this.name); this.argumentValidator = new ArgumentValidator(this.name);
@ -38,10 +38,7 @@ public class UserDefinedFunction extends LispFunction {
SymbolTable callingScope = executionContext.getScope(); SymbolTable callingScope = executionContext.getScope();
executionContext.setScope(functionScope); executionContext.setScope(functionScope);
SExpression lastEvaluation = Nil.getInstance(); SExpression lastEvaluation = evaluateBody();
for (Cons expression = body; expression.consp(); expression = (Cons) expression.getRest())
lastEvaluation = eval(expression.getFirst());
executionContext.setScope(callingScope); executionContext.setScope(callingScope);
releaseParameterValues(); releaseParameterValues();
@ -59,6 +56,15 @@ public class UserDefinedFunction extends LispFunction {
} }
} }
private SExpression evaluateBody() {
SExpression lastEvaluation = Nil.getInstance();
for (Cons expression = body; expression.isCons(); expression = (Cons) expression.getRest())
lastEvaluation = eval(expression.getFirst());
return lastEvaluation;
}
private void releaseParameterValues() { private void releaseParameterValues() {
functionScope = new SymbolTable(functionScope.getParent()); functionScope = new SymbolTable(functionScope.getParent());
} }

View File

@ -0,0 +1,16 @@
package function;
import sexpression.Cons;
public class UserDefinedSpecialFunction extends UserDefinedFunction {
public UserDefinedSpecialFunction(String name, Cons lambdaList, Cons body) {
super(name, lambdaList, body);
}
@Override
public boolean evaluateArguments() {
return false;
}
}

View File

@ -21,7 +21,7 @@ public class EVAL extends LispFunction {
} }
private static LispFunction createLambdaFunction(SExpression lambdaExpression) { private static LispFunction createLambdaFunction(SExpression lambdaExpression) {
if (lambdaExpression.functionp()) if (lambdaExpression.isFunction())
return ((LambdaExpression) lambdaExpression).getFunction(); return ((LambdaExpression) lambdaExpression).getFunction();
else if (LAMBDA.isLambdaExpression(lambdaExpression)) else if (LAMBDA.isLambdaExpression(lambdaExpression))
return LAMBDA.createFunction((Cons) lambdaExpression); return LAMBDA.createFunction((Cons) lambdaExpression);
@ -59,14 +59,14 @@ public class EVAL extends LispFunction {
SExpression argument = argumentList.getFirst(); SExpression argument = argumentList.getFirst();
if (argument.listp()) { if (argument.isList()) {
if (argument.consp()) if (argument.isCons())
return evaluateList((Cons) argument); return evaluateList((Cons) argument);
return argument; // NIL return argument; // NIL
} }
if (argument.symbolp()) { if (argument.isSymbol()) {
SExpression symbolValue = lookupSymbol(argument.toString()); SExpression symbolValue = lookupSymbol(argument.toString());
if (symbolValue != null) if (symbolValue != null)
@ -95,7 +95,7 @@ public class EVAL extends LispFunction {
} }
private Cons evaluateArgList(Cons arguments) { private Cons evaluateArgList(Cons arguments) {
if (arguments.nullp()) if (arguments.isNull())
return Nil.getInstance(); return Nil.getInstance();
SExpression first = eval(arguments.getFirst()); SExpression first = eval(arguments.getFirst());

View File

@ -36,7 +36,7 @@ public class LENGTH extends LispFunction {
Cons list = (Cons) argumentList.getFirst(); Cons list = (Cons) argumentList.getFirst();
Cons restOfList = LIST.makeList(list.getRest()); Cons restOfList = LIST.makeList(list.getRest());
if (list.nullp()) if (list.isNull())
return new LispNumber(accumulatedLength); return new LispNumber(accumulatedLength);
return callTailRecursive(increment(accumulatedLength), restOfList); return callTailRecursive(increment(accumulatedLength), restOfList);

View File

@ -22,7 +22,7 @@ public class LIST extends LispFunction {
} }
private Cons callRecursive(Cons argumentList) { private Cons callRecursive(Cons argumentList) {
if (argumentList.nullp()) if (argumentList.isNull())
return Nil.getInstance(); return Nil.getInstance();
SExpression firstArgument = argumentList.getFirst(); SExpression firstArgument = argumentList.getFirst();

View File

@ -20,7 +20,7 @@ class MathFunction {
SExpression firstArgument = argumentList.getFirst(); SExpression firstArgument = argumentList.getFirst();
LispNumber number1 = (LispNumber) firstArgument; LispNumber number1 = (LispNumber) firstArgument;
if (remainingArguments.nullp()) if (remainingArguments.isNull())
return singleValueOperation.apply(number1); return singleValueOperation.apply(number1);
SExpression secondArgument = remainingArguments.getFirst(); SExpression secondArgument = remainingArguments.getFirst();
@ -28,7 +28,7 @@ class MathFunction {
LispNumber operationResult = multipleValueOperation.apply(number1, number2); LispNumber operationResult = multipleValueOperation.apply(number1, number2);
SExpression remainingNumbers = remainingArguments.getRest(); SExpression remainingNumbers = remainingArguments.getRest();
if (remainingNumbers.nullp()) if (remainingNumbers.isNull())
return operationResult; return operationResult;
return callTailRecursive(new Cons(operationResult, remainingNumbers)); return callTailRecursive(new Cons(operationResult, remainingNumbers));

View File

@ -16,7 +16,7 @@ public class ATOM extends LispFunction {
argumentValidator.validate(argumentList); argumentValidator.validate(argumentList);
SExpression argument = argumentList.getFirst(); SExpression argument = argumentList.getFirst();
return argument.atomp() ? Symbol.T : Nil.getInstance(); return argument.isAtom() ? Symbol.T : Nil.getInstance();
} }
} }

View File

@ -30,7 +30,7 @@ public class EQ extends LispFunction {
} }
private boolean isAtomPair(SExpression firstArgument, SExpression secondArgument) { private boolean isAtomPair(SExpression firstArgument, SExpression secondArgument) {
return firstArgument.atomp() && secondArgument.atomp(); return firstArgument.isAtom() && secondArgument.isAtom();
} }
private SExpression atomEq(SExpression firstArgument, SExpression secondArgument) { private SExpression atomEq(SExpression firstArgument, SExpression secondArgument) {

View File

@ -41,7 +41,7 @@ public class EQUAL extends LispFunction {
} }
private boolean isListPair(SExpression firstArgument, SExpression secondArgument) { private boolean isListPair(SExpression firstArgument, SExpression secondArgument) {
return firstArgument.consp() && secondArgument.consp(); return firstArgument.isCons() && secondArgument.isCons();
} }
private SExpression equal(SExpression firstArgument, SExpression secondArgument) { private SExpression equal(SExpression firstArgument, SExpression secondArgument) {

View File

@ -22,7 +22,7 @@ public class EQUALSP extends LispFunction {
private SExpression callTailRecursive(Cons argumentList) { private SExpression callTailRecursive(Cons argumentList) {
Cons remainingArguments = (Cons) argumentList.getRest(); Cons remainingArguments = (Cons) argumentList.getRest();
if (remainingArguments.nullp()) if (remainingArguments.isNull())
return Symbol.T; return Symbol.T;
SExpression firstArgument = argumentList.getFirst(); SExpression firstArgument = argumentList.getFirst();

View File

@ -22,7 +22,7 @@ public class GREATERP extends LispFunction {
private SExpression callTailRecursive(Cons argumentList) { private SExpression callTailRecursive(Cons argumentList) {
Cons remainingArguments = (Cons) argumentList.getRest(); Cons remainingArguments = (Cons) argumentList.getRest();
if (remainingArguments.nullp()) if (remainingArguments.isNull())
return Symbol.T; return Symbol.T;
SExpression firstArgument = argumentList.getFirst(); SExpression firstArgument = argumentList.getFirst();

View File

@ -22,7 +22,7 @@ public class LESSP extends LispFunction {
private SExpression callTailRecursive(Cons argumentList) { private SExpression callTailRecursive(Cons argumentList) {
Cons remainingArguments = (Cons) argumentList.getRest(); Cons remainingArguments = (Cons) argumentList.getRest();
if (remainingArguments.nullp()) if (remainingArguments.isNull())
return Symbol.T; return Symbol.T;
SExpression firstArgument = argumentList.getFirst(); SExpression firstArgument = argumentList.getFirst();

View File

@ -15,7 +15,7 @@ public class LISTP extends LispFunction {
public SExpression call(Cons argumentList) { public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList); argumentValidator.validate(argumentList);
return argumentList.getFirst().listp() ? Symbol.T : Nil.getInstance(); return argumentList.getFirst().isList() ? Symbol.T : Nil.getInstance();
} }
} }

View File

@ -15,7 +15,7 @@ public class NULL extends LispFunction {
public SExpression call(Cons argumentList) { public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList); argumentValidator.validate(argumentList);
return argumentList.getFirst().nullp() ? Symbol.T : Nil.getInstance(); return argumentList.getFirst().isNull() ? Symbol.T : Nil.getInstance();
} }
} }

View File

@ -5,7 +5,7 @@ import static function.builtin.EVAL.eval;
import function.*; import function.*;
import sexpression.*; import sexpression.*;
public class AND extends LispFunction { public class AND extends LispSpecialFunction {
private ArgumentValidator argumentValidator; private ArgumentValidator argumentValidator;
@ -23,17 +23,13 @@ public class AND extends LispFunction {
SExpression currentValue = eval(argumentList.getFirst()); SExpression currentValue = eval(argumentList.getFirst());
Cons remainingValues = (Cons) argumentList.getRest(); Cons remainingValues = (Cons) argumentList.getRest();
if (argumentList.nullp()) if (argumentList.isNull())
return lastValue; return lastValue;
if (currentValue.nullp()) if (currentValue.isNull())
return currentValue; return currentValue;
return callTailRecursive(remainingValues, currentValue); return callTailRecursive(remainingValues, currentValue);
} }
public boolean evaluateArguments() {
return false;
}
} }

View File

@ -5,7 +5,7 @@ import static function.builtin.EVAL.eval;
import function.*; import function.*;
import sexpression.*; import sexpression.*;
public class COND extends LispFunction { public class COND extends LispSpecialFunction {
private ArgumentValidator argumentValidator; private ArgumentValidator argumentValidator;
@ -22,7 +22,7 @@ public class COND extends LispFunction {
} }
private SExpression callTailRecursive(Cons argumentList) { private SExpression callTailRecursive(Cons argumentList) {
if (argumentList.nullp()) if (argumentList.isNull())
return Nil.getInstance(); return Nil.getInstance();
Cons clause = (Cons) argumentList.getFirst(); Cons clause = (Cons) argumentList.getFirst();
@ -42,7 +42,7 @@ public class COND extends LispFunction {
private SExpression evaluateResult(Cons clause, SExpression test) { private SExpression evaluateResult(Cons clause, SExpression test) {
SExpression lastResultValue = test; SExpression lastResultValue = test;
for (SExpression result = clause.getRest(); result.consp(); result = advanceCons(result)) for (SExpression result = clause.getRest(); result.isCons(); result = advanceCons(result))
lastResultValue = eval(getFirst(result)); lastResultValue = eval(getFirst(result));
return lastResultValue; return lastResultValue;
@ -56,8 +56,4 @@ public class COND extends LispFunction {
return ((Cons) knownCons).getFirst(); return ((Cons) knownCons).getFirst();
} }
public boolean evaluateArguments() {
return false;
}
} }

View File

@ -9,7 +9,7 @@ import function.builtin.cons.LIST;
import sexpression.*; import sexpression.*;
import table.FunctionTable; import table.FunctionTable;
public class DEFUN extends LispFunction { public class DEFUN extends LispSpecialFunction {
private ArgumentValidator argumentValidator; private ArgumentValidator argumentValidator;
private ArgumentValidator lambdaListIsListValidator; private ArgumentValidator lambdaListIsListValidator;
@ -52,10 +52,6 @@ public class DEFUN extends LispFunction {
return functionName; return functionName;
} }
public boolean evaluateArguments() {
return false;
}
public class RedefiningFunctionWarning extends LispWarning { public class RedefiningFunctionWarning extends LispWarning {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -5,7 +5,7 @@ import static function.builtin.EVAL.eval;
import function.*; import function.*;
import sexpression.*; import sexpression.*;
public class IF extends LispFunction { public class IF extends LispSpecialFunction {
private ArgumentValidator argumentValidator; private ArgumentValidator argumentValidator;
@ -26,7 +26,7 @@ public class IF extends LispFunction {
} }
private boolean isNil(SExpression test) { private boolean isNil(SExpression test) {
return test.nullp(); return test.isNull();
} }
private SExpression getThenForm(Cons argumentList) { private SExpression getThenForm(Cons argumentList) {
@ -45,8 +45,4 @@ public class IF extends LispFunction {
return getRestOfList(expressions).getFirst(); return getRestOfList(expressions).getFirst();
} }
public boolean evaluateArguments() {
return false;
}
} }

View File

@ -5,10 +5,10 @@ import static function.builtin.cons.LIST.makeList;
import function.*; import function.*;
import sexpression.*; import sexpression.*;
public class LAMBDA extends LispFunction { public class LAMBDA extends LispSpecialFunction {
public static boolean isLambdaExpression(SExpression sexpr) { public static boolean isLambdaExpression(SExpression sexpr) {
if (sexpr.consp()) { if (sexpr.isCons()) {
SExpression first = ((Cons) sexpr).getFirst(); SExpression first = ((Cons) sexpr).getFirst();
return "LAMBDA".equals(first.toString()); return "LAMBDA".equals(first.toString());
@ -59,8 +59,4 @@ public class LAMBDA extends LispFunction {
return new Cons(new Symbol("LAMBDA"), argumentList); return new Cons(new Symbol("LAMBDA"), argumentList);
} }
public boolean evaluateArguments() {
return false;
}
} }

View File

@ -6,7 +6,7 @@ import function.*;
import sexpression.*; import sexpression.*;
import table.*; import table.*;
public class LET extends LispFunction { public class LET extends LispSpecialFunction {
private ArgumentValidator argumentValidator; private ArgumentValidator argumentValidator;
private ArgumentValidator variableDefinitionListValidator; private ArgumentValidator variableDefinitionListValidator;
@ -55,7 +55,7 @@ public class LET extends LispFunction {
private void addVariablesToScope(SymbolTable scope, Cons variableDefinitions) { private void addVariablesToScope(SymbolTable scope, Cons variableDefinitions) {
variableDefinitionListValidator.validate(variableDefinitions); variableDefinitionListValidator.validate(variableDefinitions);
for (; variableDefinitions.consp(); variableDefinitions = (Cons) variableDefinitions.getRest()) for (; variableDefinitions.isCons(); variableDefinitions = (Cons) variableDefinitions.getRest())
addPairToScope((Cons) variableDefinitions.getFirst(), scope); addPairToScope((Cons) variableDefinitions.getFirst(), scope);
} }
@ -72,7 +72,7 @@ public class LET extends LispFunction {
private SExpression evaluateBody(Cons body) { private SExpression evaluateBody(Cons body) {
SExpression lastEvaluation = Nil.getInstance(); SExpression lastEvaluation = Nil.getInstance();
for (; body.consp(); body = (Cons) body.getRest()) for (; body.isCons(); body = (Cons) body.getRest())
lastEvaluation = eval(body.getFirst()); lastEvaluation = eval(body.getFirst());
return lastEvaluation; return lastEvaluation;
@ -82,8 +82,4 @@ public class LET extends LispFunction {
executionContext.setScope(localScope.getParent()); executionContext.setScope(localScope.getParent());
} }
public boolean evaluateArguments() {
return false;
}
} }

View File

@ -5,7 +5,7 @@ import static function.builtin.EVAL.eval;
import function.*; import function.*;
import sexpression.*; import sexpression.*;
public class OR extends LispFunction { public class OR extends LispSpecialFunction {
private ArgumentValidator argumentValidator; private ArgumentValidator argumentValidator;
@ -23,14 +23,10 @@ public class OR extends LispFunction {
SExpression currentValue = eval(argumentList.getFirst()); SExpression currentValue = eval(argumentList.getFirst());
Cons remainingValues = (Cons) argumentList.getRest(); Cons remainingValues = (Cons) argumentList.getRest();
if (remainingValues.nullp() || !currentValue.nullp()) if (remainingValues.isNull() || !currentValue.isNull())
return currentValue; return currentValue;
return callTailRecursive(remainingValues); return callTailRecursive(remainingValues);
} }
public boolean evaluateArguments() {
return false;
}
} }

View File

@ -3,7 +3,7 @@ package function.builtin.special;
import function.*; import function.*;
import sexpression.*; import sexpression.*;
public class QUOTE extends LispFunction { public class QUOTE extends LispSpecialFunction {
private ArgumentValidator argumentValidator; private ArgumentValidator argumentValidator;
@ -18,8 +18,4 @@ public class QUOTE extends LispFunction {
return argumentList.getFirst(); return argumentList.getFirst();
} }
public boolean evaluateArguments() {
return false;
}
} }

View File

@ -6,7 +6,7 @@ import function.*;
import sexpression.*; import sexpression.*;
import table.*; import table.*;
public class SETF extends LispFunction { public class SETF extends LispSpecialFunction {
private ArgumentValidator argumentValidator; private ArgumentValidator argumentValidator;
private ExecutionContext executionContext; private ExecutionContext executionContext;
@ -48,8 +48,4 @@ public class SETF extends LispFunction {
return table.getParent() == null; return table.getParent() == null;
} }
public boolean evaluateArguments() {
return false;
}
} }

View File

@ -9,7 +9,7 @@ public abstract class Atom extends SExpression {
this.text = text; this.text = text;
} }
public boolean atomp() { public boolean isAtom() {
return true; return true;
} }

View File

@ -27,7 +27,7 @@ public class Cons extends SExpression {
this.rest = rest; this.rest = rest;
} }
public boolean consp() { public boolean isCons() {
return true; return true;
} }
@ -36,9 +36,9 @@ public class Cons extends SExpression {
} }
private String toStringAux() { private String toStringAux() {
if (rest.nullp()) if (rest.isNull())
return (first.toString() + ")"); return (first.toString() + ")");
else if (rest.consp()) else if (rest.isCons())
return (first.toString() + " " + ((Cons) rest).toStringAux()); return (first.toString() + " " + ((Cons) rest).toStringAux());
return (first.toString() + " . " + rest.toString() + ")"); return (first.toString() + " . " + rest.toString() + ")");

View File

@ -13,7 +13,7 @@ public class LambdaExpression extends SExpression {
this.function = function; this.function = function;
} }
public boolean functionp() { public boolean isFunction() {
return true; return true;
} }

View File

@ -29,7 +29,7 @@ public class LispNumber extends Atom {
this.value = value; this.value = value;
} }
public boolean numberp() { public boolean isNumber() {
return true; return true;
} }

View File

@ -7,7 +7,7 @@ public class LispString extends Atom {
super(text); super(text);
} }
public boolean stringp() { public boolean isString() {
return true; return true;
} }

View File

@ -16,19 +16,19 @@ public class Nil extends Cons {
super.setRest(this); super.setRest(this);
} }
public boolean nullp() { public boolean isNull() {
return true; return true;
} }
public boolean atomp() { public boolean isAtom() {
return true; return true;
} }
public boolean consp() { public boolean isCons() {
return false; return false;
} }
public boolean symbolp() { public boolean isSymbol() {
return true; return true;
} }

View File

@ -3,35 +3,35 @@ package sexpression;
@DisplayName("s-expression") @DisplayName("s-expression")
public abstract class SExpression { public abstract class SExpression {
public boolean nullp() { public boolean isNull() {
return false; return false;
} }
public boolean atomp() { public boolean isAtom() {
return false; return false;
} }
public boolean consp() { public boolean isCons() {
return false; return false;
} }
public boolean listp() { public boolean isList() {
return (consp() || nullp()); return (isCons() || isNull());
} }
public boolean numberp() { public boolean isNumber() {
return false; return false;
} }
public boolean symbolp() { public boolean isSymbol() {
return false; return false;
} }
public boolean functionp() { public boolean isFunction() {
return false; return false;
} }
public boolean stringp() { public boolean isString() {
return false; return false;
} }

View File

@ -13,7 +13,7 @@ public class Symbol extends Atom {
super(text.toUpperCase()); super(text.toUpperCase());
} }
public boolean symbolp() { public boolean isSymbol() {
return true; return true;
} }

View File

@ -5,9 +5,6 @@ import java.util.function.Supplier;
import file.FilePosition; import file.FilePosition;
import sexpression.*; import sexpression.*;
/**
* A token in Lisp.
*/
public abstract class Token { public abstract class Token {
private String text; private String text;
@ -26,10 +23,12 @@ public abstract class Token {
return position; return position;
} }
// sExpr ::= NUMBER | IDENTIFIER | STRING | QUOTE_MARK sExpr | LEFT_PAREN sExprTail // s-expression ::= NUMBER | IDENTIFIER | STRING | QUOTE_MARK s-expression | LEFT_PAREN
// s-expression-tail
// s-expression-tail ::= RIGHT_PAREN | s-expression s-expression-tail
public abstract SExpression parseSExpression(Supplier<Token> getNextToken); public abstract SExpression parseSExpression(Supplier<Token> getNextToken);
// sExprTail ::= RIGHT_PAREN | sExpr sExprTail
public SExpression parseSExpressionTail(Supplier<Token> getNextToken) { public SExpression parseSExpressionTail(Supplier<Token> getNextToken) {
SExpression first = parseSExpression(getNextToken); SExpression first = parseSExpression(getNextToken);

View File

@ -7,61 +7,61 @@ import sexpression.*;
public final class TypeAssertions { public final class TypeAssertions {
public static void assertList(SExpression sExpression) { public static void assertList(SExpression sExpression) {
assertFalse(sExpression.atomp()); assertFalse(sExpression.isAtom());
assertTrue(sExpression.consp()); assertTrue(sExpression.isCons());
assertFalse(sExpression.functionp()); assertFalse(sExpression.isFunction());
assertTrue(sExpression.listp()); assertTrue(sExpression.isList());
assertFalse(sExpression.nullp()); assertFalse(sExpression.isNull());
assertFalse(sExpression.numberp()); assertFalse(sExpression.isNumber());
assertFalse(sExpression.stringp()); assertFalse(sExpression.isString());
assertFalse(sExpression.symbolp()); assertFalse(sExpression.isSymbol());
} }
public static void assertNil(SExpression sExpression) { public static void assertNil(SExpression sExpression) {
assertEquals(Nil.getInstance(), sExpression); assertEquals(Nil.getInstance(), sExpression);
assertTrue(sExpression.atomp()); assertTrue(sExpression.isAtom());
assertFalse(sExpression.consp()); assertFalse(sExpression.isCons());
assertFalse(sExpression.functionp()); assertFalse(sExpression.isFunction());
assertTrue(sExpression.listp()); assertTrue(sExpression.isList());
assertTrue(sExpression.nullp()); assertTrue(sExpression.isNull());
assertFalse(sExpression.numberp()); assertFalse(sExpression.isNumber());
assertFalse(sExpression.stringp()); assertFalse(sExpression.isString());
assertTrue(sExpression.symbolp()); assertTrue(sExpression.isSymbol());
} }
public static void assertNumber(SExpression sExpression) { public static void assertNumber(SExpression sExpression) {
assertTrue(sExpression.atomp()); assertTrue(sExpression.isAtom());
assertFalse(sExpression.consp()); assertFalse(sExpression.isCons());
assertFalse(sExpression.functionp()); assertFalse(sExpression.isFunction());
assertFalse(sExpression.listp()); assertFalse(sExpression.isList());
assertFalse(sExpression.nullp()); assertFalse(sExpression.isNull());
assertTrue(sExpression.numberp()); assertTrue(sExpression.isNumber());
assertFalse(sExpression.stringp()); assertFalse(sExpression.isString());
assertFalse(sExpression.symbolp()); assertFalse(sExpression.isSymbol());
} }
public static void assertString(SExpression sExpression) { public static void assertString(SExpression sExpression) {
assertTrue(sExpression.atomp()); assertTrue(sExpression.isAtom());
assertFalse(sExpression.consp()); assertFalse(sExpression.isCons());
assertFalse(sExpression.functionp()); assertFalse(sExpression.isFunction());
assertFalse(sExpression.listp()); assertFalse(sExpression.isList());
assertFalse(sExpression.nullp()); assertFalse(sExpression.isNull());
assertFalse(sExpression.numberp()); assertFalse(sExpression.isNumber());
assertTrue(sExpression.stringp()); assertTrue(sExpression.isString());
assertFalse(sExpression.symbolp()); assertFalse(sExpression.isSymbol());
} }
public static void assertSymbol(SExpression sExpression) { public static void assertSymbol(SExpression sExpression) {
assertTrue(sExpression.atomp()); assertTrue(sExpression.isAtom());
assertFalse(sExpression.consp()); assertFalse(sExpression.isCons());
assertFalse(sExpression.functionp()); assertFalse(sExpression.isFunction());
assertFalse(sExpression.listp()); assertFalse(sExpression.isList());
assertFalse(sExpression.nullp()); assertFalse(sExpression.isNull());
assertFalse(sExpression.numberp()); assertFalse(sExpression.isNumber());
assertFalse(sExpression.stringp()); assertFalse(sExpression.isString());
assertTrue(sExpression.symbolp()); assertTrue(sExpression.isSymbol());
} }
public static void assertT(SExpression sExpression) { public static void assertT(SExpression sExpression) {