Added unit tests, refactored some code, and removed IOException references

This commit is contained in:
Mike Cifelli 2016-12-11 15:09:48 -05:00
parent f50b07842c
commit c02ef37f64
8 changed files with 127 additions and 25 deletions

View File

@ -72,10 +72,6 @@ public class LOAD extends LispFunction {
} catch (RuntimeException e) { } catch (RuntimeException e) {
System.out.println("LOAD: " + e.getMessage()); System.out.println("LOAD: " + e.getMessage());
return Nil.getUniqueInstance();
} catch (IOException e) {
System.out.println("LOAD: " + e.getMessage());
return Nil.getUniqueInstance(); return Nil.getUniqueInstance();
} }
} }

View File

@ -9,6 +9,8 @@ package main;
import parser.*; import parser.*;
import eval.*; import eval.*;
import error.ErrorManager; import error.ErrorManager;
import error.LispException;
import java.io.*; import java.io.*;
import java.text.MessageFormat; import java.text.MessageFormat;
@ -67,11 +69,12 @@ public class LispInterpreter {
LispInterpreter.erasePrompt(interactive); LispInterpreter.erasePrompt(interactive);
System.out.println(result); System.out.println(result);
} catch (LispException e) {
LispInterpreter.erasePrompt(interactive);
ErrorManager.generateError(e);
} catch (RuntimeException e) { } catch (RuntimeException e) {
LispInterpreter.erasePrompt(interactive); LispInterpreter.erasePrompt(interactive);
ErrorManager.generateError(e.getMessage(), 2); ErrorManager.generateError(e.getMessage(), 0);
} catch (IOException e) {
ErrorManager.generateError(e.getMessage(), ErrorManager.CRITICAL_LEVEL);
} }
if (interactive) { if (interactive) {

View File

@ -6,10 +6,10 @@
package parser; package parser;
import scanner.*; import java.io.InputStream;
import java.io.*;
import constructs.Token; import constructs.Token;
import scanner.LispScanner;
/** /**
* A <code>LispParser</code> converts a stream of bytes into internal * A <code>LispParser</code> converts a stream of bytes into internal
@ -91,19 +91,12 @@ public class LispParser {
* @throws IOException * @throws IOException
* Indicates that an I/O error has occurred. * Indicates that an I/O error has occurred.
*/ */
public SExpression getSExpr() throws IOException { public SExpression getSExpr() {
if (delayedException != null) { if (delayedException != null) {
// the 'eof' method has stored an exception for us to throw // the 'eof' method has stored an exception for us to throw
// determine the type of the stored exception and throw it! // determine the type of the stored exception and throw it!
if (delayedException instanceof IOException) { if (delayedException instanceof RuntimeException) {
IOException e = (IOException) delayedException;
// remove the exception from 'delayedException'
delayedException = null;
throw e;
} else if (delayedException instanceof RuntimeException) {
RuntimeException e = (RuntimeException) delayedException; RuntimeException e = (RuntimeException) delayedException;
// remove the exception from 'delayedException' // remove the exception from 'delayedException'
@ -136,7 +129,7 @@ public class LispParser {
// encountered in the underlying input stream. // encountered in the underlying input stream.
// Throws: IOException - Indicates that an I/O error has occurred. // Throws: IOException - Indicates that an I/O error has occurred.
// Precondition: 'nextToken' is not null. // Precondition: 'nextToken' is not null.
private SExpression sExpr() throws IOException { private SExpression sExpr() {
// determine the type of 'nextToken' and create the appropriate // determine the type of 'nextToken' and create the appropriate
// S-expression // S-expression
switch (nextToken.getType()) { switch (nextToken.getType()) {
@ -174,7 +167,7 @@ public class LispParser {
// Returns: an S-expression that matches the rules given above // Returns: an S-expression that matches the rules given above
// Throws: IOException - Indicates that an I/O error has occurred. // Throws: IOException - Indicates that an I/O error has occurred.
// Precondition: 'scanner' is not null. // Precondition: 'scanner' is not null.
private SExpression sExprTail() throws IOException { private SExpression sExprTail() {
nextToken = scanner.getNextToken(); nextToken = scanner.getNextToken();
// determine the type of 'nextToken' and create the appropriate // determine the type of 'nextToken' and create the appropriate

View File

@ -83,7 +83,7 @@ public class LispScanner {
return retriever.retrieveToken(); return retriever.retrieveToken();
} }
public class ComplexTokenTextRetriever { private class ComplexTokenTextRetriever {
Function<Character, Boolean> isPartOfToken; Function<Character, Boolean> isPartOfToken;
StringBuilder text; StringBuilder text;
@ -115,7 +115,7 @@ public class LispScanner {
addCharacterToToken(); addCharacterToToken();
if (isStringToken() && isTerminatingDoubleQuote()) if (isTerminatingCharacter())
return text.toString(); return text.toString();
previousCharacter = currentCharacter; previousCharacter = currentCharacter;
@ -132,6 +132,10 @@ public class LispScanner {
positionTracker.incrementLine(); positionTracker.incrementLine();
} }
private boolean isTerminatingCharacter() {
return isStringToken() && isTerminatingDoubleQuote();
}
private boolean isStringToken() { private boolean isStringToken() {
return firstCharacter == DOUBLE_QUOTE; return firstCharacter == DOUBLE_QUOTE;
} }

View File

@ -0,0 +1,70 @@
package constructs;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import file.FilePosition;
public class TokenFactoryTester {
private TokenFactory tokenFactory;
private FilePosition testPosition;
@Before
public void setUp() throws Exception {
tokenFactory = new TokenFactoryImpl();
testPosition = new FilePosition("testFile");
testPosition.setLineNumber(0);
testPosition.setColumnNumber(0);
}
@Test
public void testEOFTokenCreation() {
assertEquals(Token.Type.EOF, tokenFactory.createEOFToken(testPosition).getType());
}
@Test
public void testLeftParenthesisCreation() {
String text = "(";
assertEquals(Token.Type.LEFT_PAREN, tokenFactory.createToken(text, testPosition).getType());
}
@Test
public void testRightParenthesisCreation() {
String text = ")";
assertEquals(Token.Type.RIGHT_PAREN, tokenFactory.createToken(text, testPosition).getType());
}
@Test
public void testQuoteMarkCreation() {
String text = "'";
assertEquals(Token.Type.QUOTE_MARK, tokenFactory.createToken(text, testPosition).getType());
}
@Test
public void testNumberCreation() {
String text = "987";
assertEquals(Token.Type.NUMBER, tokenFactory.createToken(text, testPosition).getType());
}
@Test
public void testIdentifierCreation() {
String text = "identifier";
assertEquals(Token.Type.IDENTIFIER, tokenFactory.createToken(text, testPosition).getType());
}
@Test
public void testStringCreation() {
String text = "\"string\"";
assertEquals(Token.Type.STRING, tokenFactory.createToken(text, testPosition).getType());
}
@Test(expected = TokenFactory.BadCharacterException.class)
public void testBadCharacter() {
String text = "[abc]";
tokenFactory.createToken(text, testPosition);
}
}

View File

@ -103,6 +103,14 @@ public class LispScannerLineColumnTester {
assertTokenLineAndColumnsMatch(input, expectedLinesAndColumns); assertTokenLineAndColumnsMatch(input, expectedLinesAndColumns);
} }
@Test
public void givenCommentImmediatelyFollowingNumber_RecordsCorrectLocations() {
String input = "12;comment\n34";
LineColumn[] expectedLinesAndColumns = { LineColumn.create(1, 1), LineColumn.create(2, 1) };
assertTokenLineAndColumnsMatch(input, expectedLinesAndColumns);
}
private void assertTokenLineAndColumnsMatch(String input, LineColumn[] expectedLineColumnList) { private void assertTokenLineAndColumnsMatch(String input, LineColumn[] expectedLineColumnList) {
InputStream stringInputStream = TestUtilities.createInputStreamFromString(input); InputStream stringInputStream = TestUtilities.createInputStreamFromString(input);
LispScanner lispScanner = new LispScanner(stringInputStream, "stringInputStream"); LispScanner lispScanner = new LispScanner(stringInputStream, "stringInputStream");

View File

@ -32,11 +32,27 @@ public class LispScannerTextTester {
} }
@Test @Test
public void givenEmptyStream_RecordsCorrectInputStreamName() { public void givenEmptyStream_RecordsCorrectFileName() {
String input = ""; String input = "";
String expectedInputStreamName = "testInputStream"; String expectedFileName = "testFileName";
assertInputFileNameMatches(input, expectedInputStreamName); assertInputFileNameMatches(input, expectedFileName);
}
@Test
public void givenNumberFollowedByComment_RecordsCorrectText() {
String input = "192837456;comment";
String expected = "192837456";
assertTokenTextMatches(input, expected);
}
@Test
public void givenIdentifiersWithCommentBetween_RecordsCorrectText() {
String input = "abc123;comment\nabc222";
String expected = "abc123";
assertTokenTextMatches(input, expected);
} }
private void assertTokenTextMatches(String input, String expectedText) { private void assertTokenTextMatches(String input, String expectedText) {

View File

@ -30,6 +30,18 @@ public class LispScannerTypeTester {
assertTokenTypesMatch(input, expectedTypes); assertTokenTypesMatch(input, expectedTypes);
} }
@Test
public void givenBadCharacter_ExceptionContainsCorrectSeverity() {
String input = "abc\ndef[";
Token.Type[] expectedTypes = { Type.IDENTIFIER, Type.IDENTIFIER };
try {
assertTokenTypesMatch(input, expectedTypes);
} catch (TokenFactory.BadCharacterException e) {
assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL);
}
}
@Test @Test
public void givenNil_ReturnsCorrectTypes() { public void givenNil_ReturnsCorrectTypes() {
String input = "()"; String input = "()";