Continued refactoring the LispParser and writing unit tests
This commit is contained in:
		
							parent
							
								
									930c8137df
								
							
						
					
					
						commit
						ad2375e2bd
					
				@ -1,5 +1,4 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
					<?xml version="1.0" encoding="UTF-8"?><launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
 | 
				
			||||||
<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
 | 
					 | 
				
			||||||
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AFTER_CLEAN_TARGETS" value="jar,"/>
 | 
					<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AFTER_CLEAN_TARGETS" value="jar,"/>
 | 
				
			||||||
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AUTO_TARGETS" value="jar,"/>
 | 
					<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AUTO_TARGETS" value="jar,"/>
 | 
				
			||||||
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_CLEAN_TARGETS" value="clean,"/>
 | 
					<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_CLEAN_TARGETS" value="clean,"/>
 | 
				
			||||||
 | 
				
			|||||||
@ -3,9 +3,8 @@ package parser;
 | 
				
			|||||||
import java.io.InputStream;
 | 
					import java.io.InputStream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import error.LispException;
 | 
					import error.LispException;
 | 
				
			||||||
import parser.MalformedSExpressionException.*;
 | 
					 | 
				
			||||||
import scanner.LispScanner;
 | 
					import scanner.LispScanner;
 | 
				
			||||||
import sexpression.*;
 | 
					import sexpression.SExpression;
 | 
				
			||||||
import token.Eof;
 | 
					import token.Eof;
 | 
				
			||||||
import token.Token;
 | 
					import token.Token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -17,11 +16,13 @@ public class LispParser {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private LispScanner scanner;
 | 
					    private LispScanner scanner;
 | 
				
			||||||
    private Token nextToken;
 | 
					    private Token nextToken;
 | 
				
			||||||
 | 
					    private LispException delayedException;
 | 
				
			||||||
    private boolean isNextTokenStored;
 | 
					    private boolean isNextTokenStored;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public LispParser(InputStream inputStream, String fileName) {
 | 
					    public LispParser(InputStream inputStream, String fileName) {
 | 
				
			||||||
        scanner = new LispScanner(inputStream, fileName);
 | 
					        scanner = new LispScanner(inputStream, fileName);
 | 
				
			||||||
        nextToken = null;
 | 
					        nextToken = null;
 | 
				
			||||||
 | 
					        delayedException = null;
 | 
				
			||||||
        isNextTokenStored = false;
 | 
					        isNextTokenStored = false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -37,59 +38,27 @@ public class LispParser {
 | 
				
			|||||||
            nextToken = scanner.getNextToken();
 | 
					            nextToken = scanner.getNextToken();
 | 
				
			||||||
            isNextTokenStored = true;
 | 
					            isNextTokenStored = true;
 | 
				
			||||||
        } catch (LispException e) {
 | 
					        } catch (LispException e) {
 | 
				
			||||||
            // This method should give the illusion of not actually reading
 | 
					            delayedException = e;
 | 
				
			||||||
            // a token, so we ignore any exception. It will be thrown when we
 | 
					 | 
				
			||||||
            // return the next sExpression.
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public SExpression getNextSExpression() {
 | 
					    public SExpression getNextSExpression() {
 | 
				
			||||||
 | 
					        throwDelayedExceptionIfNecessary();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!isNextTokenStored)
 | 
					        if (!isNextTokenStored)
 | 
				
			||||||
            nextToken = scanner.getNextToken();
 | 
					            nextToken = scanner.getNextToken();
 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            isNextTokenStored = false;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return sExpr();
 | 
					        isNextTokenStored = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return nextToken.sExpr(scanner::getNextToken);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // sExpr ::= NUMBER | IDENTIFIER | STRING | QUOTE_MARK sExpr |
 | 
					    private void throwDelayedExceptionIfNecessary() {
 | 
				
			||||||
    // LEFT_PAREN sExprTail
 | 
					        if (delayedException != null) {
 | 
				
			||||||
    private SExpression sExpr() {
 | 
					            LispException exceptionToThrow = delayedException;
 | 
				
			||||||
        switch (nextToken.getType()) {
 | 
					            delayedException = null;
 | 
				
			||||||
        case NUMBER:
 | 
					 | 
				
			||||||
            return new LispNumber(nextToken.getText());
 | 
					 | 
				
			||||||
        case IDENTIFIER:
 | 
					 | 
				
			||||||
            return new Symbol(nextToken.getText());
 | 
					 | 
				
			||||||
        case STRING:
 | 
					 | 
				
			||||||
            return new LispString(nextToken.getText());
 | 
					 | 
				
			||||||
        case QUOTE_MARK:
 | 
					 | 
				
			||||||
            nextToken = scanner.getNextToken();
 | 
					 | 
				
			||||||
            SExpression arg = sExpr();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return new Cons(new Symbol("QUOTE"), new Cons(arg, Nil.getUniqueInstance()));
 | 
					            throw exceptionToThrow;
 | 
				
			||||||
        case LEFT_PAREN:
 | 
					 | 
				
			||||||
            return sExprTail();
 | 
					 | 
				
			||||||
        case RIGHT_PAREN:
 | 
					 | 
				
			||||||
            throw new StartsWithRightParenthesisException(nextToken);
 | 
					 | 
				
			||||||
        case EOF:
 | 
					 | 
				
			||||||
            throw new EofEncounteredException(nextToken);
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
            throw new UnrecognizedTokenException(nextToken);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // sExprTail ::= RIGHT_PAREN | sExpr sExprTail
 | 
					 | 
				
			||||||
    private SExpression sExprTail() {
 | 
					 | 
				
			||||||
        nextToken = scanner.getNextToken();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        switch (nextToken.getType()) {
 | 
					 | 
				
			||||||
        case RIGHT_PAREN:
 | 
					 | 
				
			||||||
            return Nil.getUniqueInstance();
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
            SExpression car = sExpr();
 | 
					 | 
				
			||||||
            SExpression cdr = sExprTail();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return new Cons(car, cdr);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
package parser;
 | 
					package sexpression;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.text.MessageFormat;
 | 
					import java.text.MessageFormat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1,7 +1,10 @@
 | 
				
			|||||||
package token;
 | 
					package token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import file.FilePosition;
 | 
					import java.util.function.Supplier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import file.FilePosition;
 | 
				
			||||||
 | 
					import sexpression.MalformedSExpressionException.EofEncounteredException;
 | 
				
			||||||
 | 
					import sexpression.SExpression;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class Eof extends Token {
 | 
					public class Eof extends Token {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -10,8 +13,8 @@ public class Eof extends Token {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Type getType() {
 | 
					    public SExpression sExpr(Supplier<Token> getNextToken) {
 | 
				
			||||||
        return Type.EOF;
 | 
					        throw new EofEncounteredException(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,10 @@
 | 
				
			|||||||
package token;
 | 
					package token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import file.FilePosition;
 | 
					import java.util.function.Supplier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import file.FilePosition;
 | 
				
			||||||
 | 
					import sexpression.SExpression;
 | 
				
			||||||
 | 
					import sexpression.Symbol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class Identifier extends Token {
 | 
					public class Identifier extends Token {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -10,8 +13,8 @@ public class Identifier extends Token {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Type getType() {
 | 
					    public SExpression sExpr(Supplier<Token> getNextToken) {
 | 
				
			||||||
        return Type.IDENTIFIER;
 | 
					        return new Symbol(getText());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,9 @@
 | 
				
			|||||||
package token;
 | 
					package token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.function.Supplier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import file.FilePosition;
 | 
					import file.FilePosition;
 | 
				
			||||||
 | 
					import sexpression.SExpression;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class LeftParenthesis extends Token {
 | 
					public class LeftParenthesis extends Token {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -9,8 +12,10 @@ public class LeftParenthesis extends Token {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Type getType() {
 | 
					    public SExpression sExpr(Supplier<Token> getNextToken) {
 | 
				
			||||||
        return Type.LEFT_PAREN;
 | 
					        Token nextToken = getNextToken.get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return nextToken.sExprTail(getNextToken);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,10 @@
 | 
				
			|||||||
package token;
 | 
					package token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import file.FilePosition;
 | 
					import java.util.function.Supplier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import file.FilePosition;
 | 
				
			||||||
 | 
					import sexpression.LispNumber;
 | 
				
			||||||
 | 
					import sexpression.SExpression;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class Number extends Token {
 | 
					public class Number extends Token {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -10,8 +13,8 @@ public class Number extends Token {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Type getType() {
 | 
					    public SExpression sExpr(Supplier<Token> getNextToken) {
 | 
				
			||||||
        return Type.NUMBER;
 | 
					        return new LispNumber(getText());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,9 @@
 | 
				
			|||||||
package token;
 | 
					package token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import file.FilePosition;
 | 
					import java.util.function.Supplier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import file.FilePosition;
 | 
				
			||||||
 | 
					import sexpression.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class QuoteMark extends Token {
 | 
					public class QuoteMark extends Token {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -10,8 +12,11 @@ public class QuoteMark extends Token {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Type getType() {
 | 
					    public SExpression sExpr(Supplier<Token> getNextToken) {
 | 
				
			||||||
        return Type.QUOTE_MARK;
 | 
					        Token nextToken = getNextToken.get();
 | 
				
			||||||
 | 
					        SExpression argument = nextToken.sExpr(getNextToken);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Cons(new Symbol("QUOTE"), new Cons(argument, Nil.getUniqueInstance()));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,10 @@
 | 
				
			|||||||
package token;
 | 
					package token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import file.FilePosition;
 | 
					import java.util.function.Supplier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import file.FilePosition;
 | 
				
			||||||
 | 
					import sexpression.LispString;
 | 
				
			||||||
 | 
					import sexpression.SExpression;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class QuotedString extends Token {
 | 
					public class QuotedString extends Token {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -10,8 +13,8 @@ public class QuotedString extends Token {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Type getType() {
 | 
					    public SExpression sExpr(Supplier<Token> getNextToken) {
 | 
				
			||||||
        return Type.STRING;
 | 
					        return new LispString(getText());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,11 @@
 | 
				
			|||||||
package token;
 | 
					package token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import file.FilePosition;
 | 
					import java.util.function.Supplier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import file.FilePosition;
 | 
				
			||||||
 | 
					import sexpression.MalformedSExpressionException.StartsWithRightParenthesisException;
 | 
				
			||||||
 | 
					import sexpression.Nil;
 | 
				
			||||||
 | 
					import sexpression.SExpression;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class RightParenthesis extends Token {
 | 
					public class RightParenthesis extends Token {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -10,8 +14,13 @@ public class RightParenthesis extends Token {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Type getType() {
 | 
					    public SExpression sExpr(Supplier<Token> getNextToken) {
 | 
				
			||||||
        return Type.RIGHT_PAREN;
 | 
					        throw new StartsWithRightParenthesisException(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public SExpression sExprTail(Supplier<Token> getNextToken) {
 | 
				
			||||||
 | 
					        return Nil.getUniqueInstance();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,44 +1,52 @@
 | 
				
			|||||||
package token;
 | 
					package token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.function.Supplier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import file.FilePosition;
 | 
					import file.FilePosition;
 | 
				
			||||||
 | 
					import sexpression.Cons;
 | 
				
			||||||
 | 
					import sexpression.SExpression;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A token in Lisp.
 | 
					 * A token in Lisp.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public abstract class Token {
 | 
					public abstract class Token {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public enum Type {
 | 
					 | 
				
			||||||
        LEFT_PAREN, RIGHT_PAREN, STRING, QUOTE_MARK, NUMBER, IDENTIFIER, EOF
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private String text;
 | 
					    private String text;
 | 
				
			||||||
    private String fileName;
 | 
					    private FilePosition position;
 | 
				
			||||||
    private int line;
 | 
					 | 
				
			||||||
    private int column;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Token(String text, FilePosition position) {
 | 
					    public Token(String text, FilePosition position) {
 | 
				
			||||||
        this.text = text;
 | 
					        this.text = text;
 | 
				
			||||||
        this.fileName = position.getFileName();
 | 
					        this.position = position;
 | 
				
			||||||
        this.line = position.getLineNumber();
 | 
					 | 
				
			||||||
        this.column = position.getColumnNumber();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract Type getType();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public String getText() {
 | 
					    public String getText() {
 | 
				
			||||||
        return text;
 | 
					        return text;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public String getFileName() {
 | 
					    public String getFileName() {
 | 
				
			||||||
        return fileName;
 | 
					        return position.getFileName();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public int getLine() {
 | 
					    public int getLine() {
 | 
				
			||||||
        return line;
 | 
					        return position.getLineNumber();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public int getColumn() {
 | 
					    public int getColumn() {
 | 
				
			||||||
        return column;
 | 
					        return position.getColumnNumber();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // sExpr ::= NUMBER | IDENTIFIER | STRING | QUOTE_MARK sExpr |
 | 
				
			||||||
 | 
					    // LEFT_PAREN sExprTail
 | 
				
			||||||
 | 
					    public abstract SExpression sExpr(Supplier<Token> getNextToken);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // sExprTail ::= RIGHT_PAREN | sExpr sExprTail
 | 
				
			||||||
 | 
					    public SExpression sExprTail(Supplier<Token> getNextToken) {
 | 
				
			||||||
 | 
					        SExpression car = sExpr(getNextToken);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Token nextToken = getNextToken.get();
 | 
				
			||||||
 | 
					        SExpression cdr = nextToken.sExprTail(getNextToken);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Cons(car, cdr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,9 @@ package util;
 | 
				
			|||||||
import java.util.HashSet;
 | 
					import java.util.HashSet;
 | 
				
			||||||
import java.util.Set;
 | 
					import java.util.Set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class Characters {
 | 
					public final class Characters {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Characters() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static final int EOF = -1;
 | 
					    public static final int EOF = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,20 +1,31 @@
 | 
				
			|||||||
package parser;
 | 
					package parser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static org.junit.Assert.*;
 | 
					import static org.junit.Assert.*;
 | 
				
			||||||
 | 
					import static testutil.TestUtilities.createIOExceptionThrowingInputStream;
 | 
				
			||||||
 | 
					import static testutil.TestUtilities.createInputStreamFromString;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.InputStream;
 | 
					import java.io.InputStream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import error.LispException;
 | 
					import error.LispException;
 | 
				
			||||||
 | 
					import scanner.LispInputStream.UncheckedIOException;
 | 
				
			||||||
 | 
					import scanner.LispScanner.UnterminatedStringException;
 | 
				
			||||||
 | 
					import sexpression.MalformedSExpressionException.EofEncounteredException;
 | 
				
			||||||
 | 
					import sexpression.MalformedSExpressionException.StartsWithRightParenthesisException;
 | 
				
			||||||
import sexpression.Nil;
 | 
					import sexpression.Nil;
 | 
				
			||||||
import sexpression.SExpression;
 | 
					import sexpression.SExpression;
 | 
				
			||||||
import testutils.TestUtilities;
 | 
					import token.TokenFactory.BadCharacterException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class LispParserTester {
 | 
					public class LispParserTester {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private LispParser createLispParser(String input) {
 | 
					    private LispParser createLispParser(String input) {
 | 
				
			||||||
        InputStream stringInputStream = TestUtilities.createInputStreamFromString(input);
 | 
					        InputStream stringInputStream = createInputStreamFromString(input);
 | 
				
			||||||
 | 
					        return new LispParser(stringInputStream, "testFile");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private LispParser createIOExceptionThrowingLispParser() {
 | 
				
			||||||
 | 
					        InputStream stringInputStream = createIOExceptionThrowingInputStream();
 | 
				
			||||||
        return new LispParser(stringInputStream, "testFile");
 | 
					        return new LispParser(stringInputStream, "testFile");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -183,6 +194,17 @@ public class LispParserTester {
 | 
				
			|||||||
        assertTrue(parser.isEof());
 | 
					        assertTrue(parser.isEof());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void givenMultipleComplexLists_CreatesCorrectSExpressions() {
 | 
				
			||||||
 | 
					        String input = "(defun f (x) \n (print \n (list \"x is \" x) \n ) \n )"
 | 
				
			||||||
 | 
					                       + "(defun f (x) \n (print \n (list \"x is \" x) \n ) \n )";
 | 
				
			||||||
 | 
					        LispParser parser = createLispParser(input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertList(parser.getNextSExpression());
 | 
				
			||||||
 | 
					        assertList(parser.getNextSExpression());
 | 
				
			||||||
 | 
					        assertTrue(parser.isEof());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Test
 | 
					    @Test
 | 
				
			||||||
    public void givenMultipleExpressions_CreatesCorrectSExpressions() {
 | 
					    public void givenMultipleExpressions_CreatesCorrectSExpressions() {
 | 
				
			||||||
        String input = "(setf x 2) x \"hi\" () 29";
 | 
					        String input = "(setf x 2) x \"hi\" () 29";
 | 
				
			||||||
@ -208,7 +230,7 @@ public class LispParserTester {
 | 
				
			|||||||
        assertTrue(parser.isEof());
 | 
					        assertTrue(parser.isEof());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Test(expected = LispException.class)
 | 
					    @Test(expected = BadCharacterException.class)
 | 
				
			||||||
    public void givenBadToken_ThrowsException() {
 | 
					    public void givenBadToken_ThrowsException() {
 | 
				
			||||||
        String input = "[";
 | 
					        String input = "[";
 | 
				
			||||||
        LispParser parser = createLispParser(input);
 | 
					        LispParser parser = createLispParser(input);
 | 
				
			||||||
@ -216,7 +238,7 @@ public class LispParserTester {
 | 
				
			|||||||
        parser.getNextSExpression();
 | 
					        parser.getNextSExpression();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Test(expected = LispException.class)
 | 
					    @Test(expected = UnterminatedStringException.class)
 | 
				
			||||||
    public void givenUnterminatedString_ThrowsException() {
 | 
					    public void givenUnterminatedString_ThrowsException() {
 | 
				
			||||||
        String input = "\"string";
 | 
					        String input = "\"string";
 | 
				
			||||||
        LispParser parser = createLispParser(input);
 | 
					        LispParser parser = createLispParser(input);
 | 
				
			||||||
@ -224,7 +246,7 @@ public class LispParserTester {
 | 
				
			|||||||
        parser.getNextSExpression();
 | 
					        parser.getNextSExpression();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Test(expected = LispException.class)
 | 
					    @Test(expected = EofEncounteredException.class)
 | 
				
			||||||
    public void givenUnterminatedList_ThrowsException() {
 | 
					    public void givenUnterminatedList_ThrowsException() {
 | 
				
			||||||
        String input = "(bad list";
 | 
					        String input = "(bad list";
 | 
				
			||||||
        LispParser parser = createLispParser(input);
 | 
					        LispParser parser = createLispParser(input);
 | 
				
			||||||
@ -232,7 +254,7 @@ public class LispParserTester {
 | 
				
			|||||||
        parser.getNextSExpression();
 | 
					        parser.getNextSExpression();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Test(expected = LispException.class)
 | 
					    @Test(expected = StartsWithRightParenthesisException.class)
 | 
				
			||||||
    public void givenUnmatchedRightParenthesis_ThrowsException() {
 | 
					    public void givenUnmatchedRightParenthesis_ThrowsException() {
 | 
				
			||||||
        String input = ")";
 | 
					        String input = ")";
 | 
				
			||||||
        LispParser parser = createLispParser(input);
 | 
					        LispParser parser = createLispParser(input);
 | 
				
			||||||
@ -240,7 +262,7 @@ public class LispParserTester {
 | 
				
			|||||||
        parser.getNextSExpression();
 | 
					        parser.getNextSExpression();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Test(expected = LispException.class)
 | 
					    @Test(expected = BadCharacterException.class)
 | 
				
			||||||
    public void givenBadCharacter_ThrowsExceptionAfterEofCalled() {
 | 
					    public void givenBadCharacter_ThrowsExceptionAfterEofCalled() {
 | 
				
			||||||
        String input = "[";
 | 
					        String input = "[";
 | 
				
			||||||
        LispParser parser = createLispParser(input);
 | 
					        LispParser parser = createLispParser(input);
 | 
				
			||||||
@ -254,7 +276,7 @@ public class LispParserTester {
 | 
				
			|||||||
        parser.getNextSExpression();
 | 
					        parser.getNextSExpression();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Test(expected = LispException.class)
 | 
					    @Test(expected = BadCharacterException.class)
 | 
				
			||||||
    public void givenBadCharacterAfterValidToken_ThrowsExceptionAtTheCorrectTime() {
 | 
					    public void givenBadCharacterAfterValidToken_ThrowsExceptionAtTheCorrectTime() {
 | 
				
			||||||
        String input = "id[";
 | 
					        String input = "id[";
 | 
				
			||||||
        LispParser parser = createLispParser(input);
 | 
					        LispParser parser = createLispParser(input);
 | 
				
			||||||
@ -279,9 +301,22 @@ public class LispParserTester {
 | 
				
			|||||||
        try {
 | 
					        try {
 | 
				
			||||||
            parser.getNextSExpression();
 | 
					            parser.getNextSExpression();
 | 
				
			||||||
            fail("Expected LispException");
 | 
					            fail("Expected LispException");
 | 
				
			||||||
        } catch (LispException e) {
 | 
					        } catch (LispException e) {}
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assertTrue(parser.isEof());
 | 
					        assertTrue(parser.isEof());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test(expected = UncheckedIOException.class)
 | 
				
			||||||
 | 
					    public void handlesIOExceptionCorrectly() {
 | 
				
			||||||
 | 
					        LispParser parser = createIOExceptionThrowingLispParser();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            parser.isEof();
 | 
				
			||||||
 | 
					        } catch (LispException e) {
 | 
				
			||||||
 | 
					            fail("Exception thrown too early");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        parser.getNextSExpression();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,9 @@
 | 
				
			|||||||
package scanner;
 | 
					package scanner;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static org.junit.Assert.*;
 | 
					import static org.junit.Assert.*;
 | 
				
			||||||
 | 
					import static testutil.TestUtilities.createIOExceptionThrowingInputStream;
 | 
				
			||||||
 | 
					import static testutil.TestUtilities.createInputStreamFromString;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.IOException;
 | 
					 | 
				
			||||||
import java.io.InputStream;
 | 
					import java.io.InputStream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
@ -10,7 +11,6 @@ import org.junit.Test;
 | 
				
			|||||||
import error.ErrorManager;
 | 
					import error.ErrorManager;
 | 
				
			||||||
import scanner.LispInputStream.MaximumUnreadsExceededException;
 | 
					import scanner.LispInputStream.MaximumUnreadsExceededException;
 | 
				
			||||||
import scanner.LispInputStream.UncheckedIOException;
 | 
					import scanner.LispInputStream.UncheckedIOException;
 | 
				
			||||||
import testutils.TestUtilities;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class LispCommentRemovingInputStreamTester {
 | 
					public class LispCommentRemovingInputStreamTester {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -19,7 +19,7 @@ public class LispCommentRemovingInputStreamTester {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private LispInputStream createLispInputStream(String inputString) {
 | 
					    private LispInputStream createLispInputStream(String inputString) {
 | 
				
			||||||
        InputStream stringInputStream = TestUtilities.createInputStreamFromString(inputString);
 | 
					        InputStream stringInputStream = createInputStreamFromString(inputString);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return new LispCommentRemovingInputStream(stringInputStream);
 | 
					        return new LispCommentRemovingInputStream(stringInputStream);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -32,15 +32,6 @@ public class LispCommentRemovingInputStreamTester {
 | 
				
			|||||||
        return charactersRead.toString();
 | 
					        return charactersRead.toString();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private InputStream createIOExceptionThrowingInputStream() {
 | 
					 | 
				
			||||||
        return new InputStream() {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            public int read() throws IOException {
 | 
					 | 
				
			||||||
                throw new IOException("test IOException");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Test
 | 
					    @Test
 | 
				
			||||||
    public void noBytesIn_noBytesOut() {
 | 
					    public void noBytesIn_noBytesOut() {
 | 
				
			||||||
        String input = "";
 | 
					        String input = "";
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,12 @@
 | 
				
			|||||||
package scanner;
 | 
					package scanner;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static org.junit.Assert.assertTrue;
 | 
					import static org.junit.Assert.assertTrue;
 | 
				
			||||||
 | 
					import static testutil.TestUtilities.createInputStreamFromString;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.InputStream;
 | 
					import java.io.InputStream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import testutils.TestUtilities;
 | 
					 | 
				
			||||||
import token.Token;
 | 
					import token.Token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class LispScannerLineColumnTester {
 | 
					public class LispScannerLineColumnTester {
 | 
				
			||||||
@ -30,7 +30,7 @@ public class LispScannerLineColumnTester {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void assertTokenLineAndColumnsMatch(String input, LineColumn[] expectedLineColumnList) {
 | 
					    private void assertTokenLineAndColumnsMatch(String input, LineColumn[] expectedLineColumnList) {
 | 
				
			||||||
        InputStream stringInputStream = TestUtilities.createInputStreamFromString(input);
 | 
					        InputStream stringInputStream = createInputStreamFromString(input);
 | 
				
			||||||
        LispScanner lispScanner = new LispScanner(stringInputStream, "testFile");
 | 
					        LispScanner lispScanner = new LispScanner(stringInputStream, "testFile");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (LineColumn lineColumn : expectedLineColumnList) {
 | 
					        for (LineColumn lineColumn : expectedLineColumnList) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,13 +1,12 @@
 | 
				
			|||||||
package scanner;
 | 
					package scanner;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static org.junit.Assert.assertEquals;
 | 
					import static org.junit.Assert.assertEquals;
 | 
				
			||||||
 | 
					import static testutil.TestUtilities.createInputStreamFromString;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.InputStream;
 | 
					import java.io.InputStream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import testutils.TestUtilities;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class LispScannerTextTester {
 | 
					public class LispScannerTextTester {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void assertTokenTextMatches(String input, String[] expectedTextList) {
 | 
					    private void assertTokenTextMatches(String input, String[] expectedTextList) {
 | 
				
			||||||
@ -24,13 +23,13 @@ public class LispScannerTextTester {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private LispScanner createLispScanner(String input) {
 | 
					    private LispScanner createLispScanner(String input) {
 | 
				
			||||||
        InputStream stringInputStream = TestUtilities.createInputStreamFromString(input);
 | 
					        InputStream stringInputStream = createInputStreamFromString(input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return new LispScanner(stringInputStream, "testFile");
 | 
					        return new LispScanner(stringInputStream, "testFile");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void assertInputFileNameMatches(String input, String expectedInputFileName) {
 | 
					    private void assertInputFileNameMatches(String input, String expectedInputFileName) {
 | 
				
			||||||
        InputStream stringInputStream = TestUtilities.createInputStreamFromString(input);
 | 
					        InputStream stringInputStream = createInputStreamFromString(input);
 | 
				
			||||||
        LispScanner lispScanner = new LispScanner(stringInputStream, expectedInputFileName);
 | 
					        LispScanner lispScanner = new LispScanner(stringInputStream, expectedInputFileName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assertEquals(expectedInputFileName, lispScanner.getNextToken().getFileName());
 | 
					        assertEquals(expectedInputFileName, lispScanner.getNextToken().getFileName());
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@ package scanner;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import static org.junit.Assert.assertNotNull;
 | 
					import static org.junit.Assert.assertNotNull;
 | 
				
			||||||
import static org.junit.Assert.assertTrue;
 | 
					import static org.junit.Assert.assertTrue;
 | 
				
			||||||
 | 
					import static testutil.TestUtilities.createInputStreamFromString;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.InputStream;
 | 
					import java.io.InputStream;
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
@ -12,15 +13,8 @@ import org.junit.Test;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import error.ErrorManager;
 | 
					import error.ErrorManager;
 | 
				
			||||||
import scanner.LispScanner.UnterminatedStringException;
 | 
					import scanner.LispScanner.UnterminatedStringException;
 | 
				
			||||||
import testutils.TestUtilities;
 | 
					import token.*;
 | 
				
			||||||
import token.Eof;
 | 
					 | 
				
			||||||
import token.Identifier;
 | 
					 | 
				
			||||||
import token.LeftParenthesis;
 | 
					 | 
				
			||||||
import token.Number;
 | 
					import token.Number;
 | 
				
			||||||
import token.QuoteMark;
 | 
					 | 
				
			||||||
import token.QuotedString;
 | 
					 | 
				
			||||||
import token.RightParenthesis;
 | 
					 | 
				
			||||||
import token.Token;
 | 
					 | 
				
			||||||
import token.TokenFactory.BadCharacterException;
 | 
					import token.TokenFactory.BadCharacterException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class LispScannerTypeTester {
 | 
					public class LispScannerTypeTester {
 | 
				
			||||||
@ -28,7 +22,7 @@ public class LispScannerTypeTester {
 | 
				
			|||||||
    private List<Class<? extends Token>> expectedTypes;
 | 
					    private List<Class<? extends Token>> expectedTypes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void assertTokenTypesMatch(String input) {
 | 
					    private void assertTokenTypesMatch(String input) {
 | 
				
			||||||
        InputStream stringInputStream = TestUtilities.createInputStreamFromString(input);
 | 
					        InputStream stringInputStream = createInputStreamFromString(input);
 | 
				
			||||||
        LispScanner lispScanner = new LispScanner(stringInputStream, "testFile");
 | 
					        LispScanner lispScanner = new LispScanner(stringInputStream, "testFile");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (Class<? extends Token> type : expectedTypes)
 | 
					        for (Class<? extends Token> type : expectedTypes)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										20
									
								
								test/testutil/TestUtilities.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								test/testutil/TestUtilities.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					package testutil;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class TestUtilities {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static InputStream createInputStreamFromString(String string) {
 | 
				
			||||||
 | 
					        return new ByteArrayInputStream(string.getBytes());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public static InputStream createIOExceptionThrowingInputStream() {
 | 
				
			||||||
 | 
					        return new InputStream() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public int read() throws IOException {
 | 
				
			||||||
 | 
					                throw new IOException("test IOException");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,12 +0,0 @@
 | 
				
			|||||||
package testutils;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.io.ByteArrayInputStream;
 | 
					 | 
				
			||||||
import java.io.InputStream;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class TestUtilities {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static InputStream createInputStreamFromString(String string) {
 | 
					 | 
				
			||||||
        return new ByteArrayInputStream(string.getBytes());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user