Refactored some code and added unit tests
This commit is contained in:
parent
62a509eb4b
commit
60a7eb562c
|
@ -1,5 +1,9 @@
|
|||
package sexpression;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import error.LispException;
|
||||
|
||||
public class LispNumber extends Atom {
|
||||
|
||||
private int value;
|
||||
|
@ -10,7 +14,7 @@ public class LispNumber extends Atom {
|
|||
try {
|
||||
this.value = Integer.parseInt(text);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException(text + " is not a valid integer");
|
||||
throw new InvalidNumberException(text);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,4 +32,25 @@ public class LispNumber extends Atom {
|
|||
return value;
|
||||
}
|
||||
|
||||
public class InvalidNumberException extends LispException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String text;
|
||||
|
||||
public InvalidNumberException(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSeverity() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return MessageFormat.format("{0} is not a valid integer", text);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,20 +2,6 @@ package sexpression;
|
|||
|
||||
public abstract class SExpression {
|
||||
|
||||
// for mark and sweep garbage collection
|
||||
private boolean marked = false;
|
||||
|
||||
public final boolean isMarked() {
|
||||
return marked;
|
||||
}
|
||||
|
||||
public final void setMarked(final boolean value) {
|
||||
marked = value;
|
||||
}
|
||||
|
||||
// Lisp type predicates...
|
||||
// overridden in subclasses to describe their Lisp type
|
||||
|
||||
public boolean nullp() {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ package token;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
import file.FilePosition;
|
||||
import sexpression.MalformedSExpressionException.EofEncounteredException;
|
||||
import sexpression.SExpression;
|
||||
import token.ParseException.EofEncounteredException;
|
||||
|
||||
public class Eof extends Token {
|
||||
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
package sexpression;
|
||||
package token;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import error.LispException;
|
||||
import token.Token;
|
||||
|
||||
public abstract class MalformedSExpressionException extends LispException {
|
||||
public abstract class ParseException extends LispException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Token token;
|
||||
|
||||
public MalformedSExpressionException(Token token) {
|
||||
public ParseException(Token token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
|
@ -27,7 +26,7 @@ public abstract class MalformedSExpressionException extends LispException {
|
|||
|
||||
public abstract String getMessagePrefix();
|
||||
|
||||
public static class EofEncounteredException extends MalformedSExpressionException {
|
||||
public static class EofEncounteredException extends ParseException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
@ -40,7 +39,7 @@ public abstract class MalformedSExpressionException extends LispException {
|
|||
}
|
||||
}
|
||||
|
||||
public static class StartsWithRightParenthesisException extends MalformedSExpressionException {
|
||||
public static class StartsWithRightParenthesisException extends ParseException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
@ -53,17 +52,4 @@ public abstract class MalformedSExpressionException extends LispException {
|
|||
}
|
||||
}
|
||||
|
||||
public static class UnrecognizedTokenException extends MalformedSExpressionException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public UnrecognizedTokenException(Token token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public String getMessagePrefix() {
|
||||
return "Unrecognized token";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -3,9 +3,9 @@ package token;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
import file.FilePosition;
|
||||
import sexpression.MalformedSExpressionException.StartsWithRightParenthesisException;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
import token.ParseException.StartsWithRightParenthesisException;
|
||||
|
||||
public class RightParenthesis extends Token {
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package parser;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static parser.SExpressionTypeAssertions.*;
|
||||
import static testutil.TestUtilities.createIOExceptionThrowingInputStream;
|
||||
import static testutil.TestUtilities.createInputStreamFromString;
|
||||
|
||||
|
@ -8,13 +9,12 @@ import java.io.InputStream;
|
|||
|
||||
import org.junit.Test;
|
||||
|
||||
import error.ErrorManager;
|
||||
import error.LispException;
|
||||
import scanner.LispInputStream.UncheckedIOException;
|
||||
import scanner.LispScanner.UnterminatedStringException;
|
||||
import sexpression.MalformedSExpressionException.EofEncounteredException;
|
||||
import sexpression.MalformedSExpressionException.StartsWithRightParenthesisException;
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
import token.ParseException.EofEncounteredException;
|
||||
import token.ParseException.StartsWithRightParenthesisException;
|
||||
import token.TokenFactory.BadCharacterException;
|
||||
|
||||
public class LispParserTester {
|
||||
|
@ -29,64 +29,6 @@ public class LispParserTester {
|
|||
return new LispParser(stringInputStream, "testFile");
|
||||
}
|
||||
|
||||
private void assertList(SExpression sExpression) {
|
||||
assertFalse(sExpression.atomp());
|
||||
assertTrue(sExpression.consp());
|
||||
assertFalse(sExpression.functionp());
|
||||
assertTrue(sExpression.listp());
|
||||
assertFalse(sExpression.nullp());
|
||||
assertFalse(sExpression.numberp());
|
||||
assertFalse(sExpression.stringp());
|
||||
assertFalse(sExpression.symbolp());
|
||||
}
|
||||
|
||||
private void assertNil(SExpression sExpression) {
|
||||
assertEquals(sExpression, Nil.getUniqueInstance());
|
||||
|
||||
assertTrue(sExpression.atomp());
|
||||
assertFalse(sExpression.consp());
|
||||
assertFalse(sExpression.functionp());
|
||||
assertTrue(sExpression.listp());
|
||||
assertTrue(sExpression.nullp());
|
||||
assertFalse(sExpression.numberp());
|
||||
assertFalse(sExpression.stringp());
|
||||
assertTrue(sExpression.symbolp());
|
||||
|
||||
}
|
||||
|
||||
private void assertNumber(SExpression sExpression) {
|
||||
assertTrue(sExpression.atomp());
|
||||
assertFalse(sExpression.consp());
|
||||
assertFalse(sExpression.functionp());
|
||||
assertFalse(sExpression.listp());
|
||||
assertFalse(sExpression.nullp());
|
||||
assertTrue(sExpression.numberp());
|
||||
assertFalse(sExpression.stringp());
|
||||
assertFalse(sExpression.symbolp());
|
||||
}
|
||||
|
||||
private void assertString(SExpression sExpression) {
|
||||
assertTrue(sExpression.atomp());
|
||||
assertFalse(sExpression.consp());
|
||||
assertFalse(sExpression.functionp());
|
||||
assertFalse(sExpression.listp());
|
||||
assertFalse(sExpression.nullp());
|
||||
assertFalse(sExpression.numberp());
|
||||
assertTrue(sExpression.stringp());
|
||||
assertFalse(sExpression.symbolp());
|
||||
}
|
||||
|
||||
private void assertSymbol(SExpression sExpression) {
|
||||
assertTrue(sExpression.atomp());
|
||||
assertFalse(sExpression.consp());
|
||||
assertFalse(sExpression.functionp());
|
||||
assertFalse(sExpression.listp());
|
||||
assertFalse(sExpression.nullp());
|
||||
assertFalse(sExpression.numberp());
|
||||
assertFalse(sExpression.stringp());
|
||||
assertTrue(sExpression.symbolp());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEofMethod_ReturnsTrueWithNoInput() {
|
||||
String input = "";
|
||||
|
@ -107,8 +49,8 @@ public class LispParserTester {
|
|||
public void testEofMethod_ReturnsTrueAfterSomeInput() {
|
||||
String input = "(yyz 9 9 9)";
|
||||
LispParser parser = createLispParser(input);
|
||||
parser.getNextSExpression();
|
||||
|
||||
parser.getNextSExpression();
|
||||
assertTrue(parser.isEof());
|
||||
}
|
||||
|
||||
|
@ -116,6 +58,7 @@ public class LispParserTester {
|
|||
public void testEofMethod_ReturnsFalseAfterMultipleExpressions() {
|
||||
String input = "()()()";
|
||||
LispParser parser = createLispParser(input);
|
||||
|
||||
assertFalse(parser.isEof());
|
||||
parser.getNextSExpression();
|
||||
assertFalse(parser.isEof());
|
||||
|
@ -127,6 +70,7 @@ public class LispParserTester {
|
|||
public void testEofMethod_ReturnsTrueAfterMultipleExpressions() {
|
||||
String input = "()()()";
|
||||
LispParser parser = createLispParser(input);
|
||||
|
||||
assertFalse(parser.isEof());
|
||||
parser.getNextSExpression();
|
||||
assertFalse(parser.isEof());
|
||||
|
@ -238,6 +182,33 @@ public class LispParserTester {
|
|||
parser.getNextSExpression();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBadToken_ExceptionHasCorrectSeverity() {
|
||||
String input = "[";
|
||||
LispParser parser = createLispParser(input);
|
||||
|
||||
try {
|
||||
parser.getNextSExpression();
|
||||
} catch (BadCharacterException e) {
|
||||
assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBadToken_ExceptionHasMessageText() {
|
||||
String input = "[";
|
||||
LispParser parser = createLispParser(input);
|
||||
|
||||
try {
|
||||
parser.getNextSExpression();
|
||||
} catch (BadCharacterException e) {
|
||||
String message = e.getMessage();
|
||||
|
||||
assertNotNull(message);
|
||||
assertTrue(message.length() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = UnterminatedStringException.class)
|
||||
public void givenUnterminatedString_ThrowsException() {
|
||||
String input = "\"string";
|
||||
|
@ -254,6 +225,33 @@ public class LispParserTester {
|
|||
parser.getNextSExpression();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnterminatedList_ExceptionHasCorrectSeverity() {
|
||||
String input = "(bad list";
|
||||
LispParser parser = createLispParser(input);
|
||||
|
||||
try {
|
||||
parser.getNextSExpression();
|
||||
} catch (EofEncounteredException e) {
|
||||
assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnterminatedList_ExceptionHasMessage() {
|
||||
String input = "(bad list";
|
||||
LispParser parser = createLispParser(input);
|
||||
|
||||
try {
|
||||
parser.getNextSExpression();
|
||||
} catch (EofEncounteredException e) {
|
||||
String message = e.getMessage();
|
||||
|
||||
assertNotNull(message);
|
||||
assertTrue(message.length() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = StartsWithRightParenthesisException.class)
|
||||
public void givenUnmatchedRightParenthesis_ThrowsException() {
|
||||
String input = ")";
|
||||
|
@ -262,6 +260,33 @@ public class LispParserTester {
|
|||
parser.getNextSExpression();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnmatchedRightParenthesis_ExceptionHasCorrectSeverity() {
|
||||
String input = ")";
|
||||
LispParser parser = createLispParser(input);
|
||||
|
||||
try {
|
||||
parser.getNextSExpression();
|
||||
} catch (StartsWithRightParenthesisException e) {
|
||||
assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnmatchedRightParenthesis_ExceptionHasMessage() {
|
||||
String input = ")";
|
||||
LispParser parser = createLispParser(input);
|
||||
|
||||
try {
|
||||
parser.getNextSExpression();
|
||||
} catch (StartsWithRightParenthesisException e) {
|
||||
String message = e.getMessage();
|
||||
|
||||
assertNotNull(message);
|
||||
assertTrue(message.length() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = BadCharacterException.class)
|
||||
public void givenBadCharacter_ThrowsExceptionAfterEofCalled() {
|
||||
String input = "[";
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package parser;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import sexpression.Nil;
|
||||
import sexpression.SExpression;
|
||||
|
||||
public final class SExpressionTypeAssertions {
|
||||
|
||||
public static void assertList(SExpression sExpression) {
|
||||
assertFalse(sExpression.atomp());
|
||||
assertTrue(sExpression.consp());
|
||||
assertFalse(sExpression.functionp());
|
||||
assertTrue(sExpression.listp());
|
||||
assertFalse(sExpression.nullp());
|
||||
assertFalse(sExpression.numberp());
|
||||
assertFalse(sExpression.stringp());
|
||||
assertFalse(sExpression.symbolp());
|
||||
}
|
||||
|
||||
public static void assertNil(SExpression sExpression) {
|
||||
assertEquals(sExpression, Nil.getUniqueInstance());
|
||||
|
||||
assertTrue(sExpression.atomp());
|
||||
assertFalse(sExpression.consp());
|
||||
assertFalse(sExpression.functionp());
|
||||
assertTrue(sExpression.listp());
|
||||
assertTrue(sExpression.nullp());
|
||||
assertFalse(sExpression.numberp());
|
||||
assertFalse(sExpression.stringp());
|
||||
assertTrue(sExpression.symbolp());
|
||||
|
||||
}
|
||||
|
||||
public static void assertNumber(SExpression sExpression) {
|
||||
assertTrue(sExpression.atomp());
|
||||
assertFalse(sExpression.consp());
|
||||
assertFalse(sExpression.functionp());
|
||||
assertFalse(sExpression.listp());
|
||||
assertFalse(sExpression.nullp());
|
||||
assertTrue(sExpression.numberp());
|
||||
assertFalse(sExpression.stringp());
|
||||
assertFalse(sExpression.symbolp());
|
||||
}
|
||||
|
||||
public static void assertString(SExpression sExpression) {
|
||||
assertTrue(sExpression.atomp());
|
||||
assertFalse(sExpression.consp());
|
||||
assertFalse(sExpression.functionp());
|
||||
assertFalse(sExpression.listp());
|
||||
assertFalse(sExpression.nullp());
|
||||
assertFalse(sExpression.numberp());
|
||||
assertTrue(sExpression.stringp());
|
||||
assertFalse(sExpression.symbolp());
|
||||
}
|
||||
|
||||
public static void assertSymbol(SExpression sExpression) {
|
||||
assertTrue(sExpression.atomp());
|
||||
assertFalse(sExpression.consp());
|
||||
assertFalse(sExpression.functionp());
|
||||
assertFalse(sExpression.listp());
|
||||
assertFalse(sExpression.nullp());
|
||||
assertFalse(sExpression.numberp());
|
||||
assertFalse(sExpression.stringp());
|
||||
assertTrue(sExpression.symbolp());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +1,13 @@
|
|||
package sexpression;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import error.ErrorManager;
|
||||
import sexpression.LispNumber.InvalidNumberException;
|
||||
|
||||
public class SExpressionTester {
|
||||
|
||||
private void assertSExpressionMatchesString(String expected, SExpression sExpression) {
|
||||
|
@ -67,4 +70,72 @@ public class SExpressionTester {
|
|||
assertSExpressionMatchesString(expected, list);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConsWithNonListCdrToString() {
|
||||
String expected = "(A . B)";
|
||||
Cons list = new Cons(new Symbol("A"), new Symbol("B"));
|
||||
|
||||
assertSExpressionMatchesString(expected, list);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCarOfNilIsNil() {
|
||||
assertEquals(Nil.getUniqueInstance().getCar(), Nil.getUniqueInstance());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCdrOfNilIsNil() {
|
||||
assertEquals(Nil.getUniqueInstance().getCdr(), Nil.getUniqueInstance());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterSettingCarOfNil_ShouldStillBeNil() {
|
||||
Cons nil = Nil.getUniqueInstance();
|
||||
nil.setCar(new LispNumber(2));
|
||||
|
||||
assertEquals(nil.getCar(), Nil.getUniqueInstance());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterSettingCdrOfNil_ShouldStillBeNil() {
|
||||
Cons nil = Nil.getUniqueInstance();
|
||||
nil.setCdr(new LispNumber(2));
|
||||
|
||||
assertEquals(nil.getCdr(), Nil.getUniqueInstance());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNumberValue() {
|
||||
int value = 12;
|
||||
LispNumber number = new LispNumber(String.valueOf(value));
|
||||
|
||||
assertEquals(number.getValue(), value);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidNumberException.class)
|
||||
public void testInvalidNumberText_ThrowsException() {
|
||||
new LispNumber("a");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidNumberException_HasCorrectSeverity() {
|
||||
try {
|
||||
new LispNumber("a");
|
||||
} catch (InvalidNumberException e) {
|
||||
assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidNumberException_HasMessageText() {
|
||||
try {
|
||||
new LispNumber("a");
|
||||
} catch (InvalidNumberException e) {
|
||||
String message = e.getMessage();
|
||||
|
||||
assertNotNull(message);
|
||||
assertTrue(message.length() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package testutil;
|
|||
|
||||
import java.io.*;
|
||||
|
||||
public class TestUtilities {
|
||||
public final class TestUtilities {
|
||||
|
||||
public static InputStream createInputStreamFromString(String string) {
|
||||
return new ByteArrayInputStream(string.getBytes());
|
||||
|
|
Loading…
Reference in New Issue