Started refactoring the sexpression package and cleaned up some unit test code
This commit is contained in:
parent
c4e3740dfb
commit
7b7556cc65
|
@ -1,3 +0,0 @@
|
|||
<body>
|
||||
Provides a class for managing errors in the Lisp Interpreter.
|
||||
</body>
|
|
@ -67,7 +67,7 @@ public class DEFUN extends LispFunction {
|
|||
|
||||
// place the function in the function table
|
||||
functionTable.put(name.toString(),
|
||||
new UDFunction(name.toString(), lambdaList, body));
|
||||
new UserDefinedFunction(name.toString(), lambdaList, body));
|
||||
|
||||
return name;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ public class LAMBDA extends LispFunction {
|
|||
* @throws RuntimeException
|
||||
* Indicates that <code>lexpr</code> is not a valid lambda expression.
|
||||
*/
|
||||
public static UDFunction createFunction(Cons lexpr) {
|
||||
public static UserDefinedFunction createFunction(Cons lexpr) {
|
||||
LAMBDA lambda = new LAMBDA();
|
||||
SExpression cdr = lexpr.getCdr();
|
||||
|
||||
|
@ -92,7 +92,7 @@ public class LAMBDA extends LispFunction {
|
|||
Cons lambdaList = (Cons) car;
|
||||
Cons body = (Cons) argList.getCdr();
|
||||
Cons lexpr = new Cons(new Symbol("LAMBDA"), argList);
|
||||
UDFunction function = new UDFunction(":LAMBDA", lambdaList, body);
|
||||
UserDefinedFunction function = new UserDefinedFunction(":LAMBDA", lambdaList, body);
|
||||
|
||||
return new LambdaExpression(lexpr, function);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import sexpression.SExpression;
|
|||
public class LambdaExpression extends SExpression {
|
||||
|
||||
private Cons lexpr;
|
||||
private UDFunction function;
|
||||
private UserDefinedFunction function;
|
||||
|
||||
/**
|
||||
* Create a new FUNCTION with the specified lambda expression and
|
||||
|
@ -27,7 +27,7 @@ public class LambdaExpression extends SExpression {
|
|||
* @param function
|
||||
* the internal representation of this FUNCTION
|
||||
*/
|
||||
public LambdaExpression(Cons lexpr, UDFunction function) {
|
||||
public LambdaExpression(Cons lexpr, UserDefinedFunction function) {
|
||||
this.lexpr = lexpr;
|
||||
this.function = function;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ public class LambdaExpression extends SExpression {
|
|||
* @return
|
||||
* the user-defined function of this FUNCTION
|
||||
*/
|
||||
public UDFunction getFunction() {
|
||||
public UserDefinedFunction getFunction() {
|
||||
return function;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,10 +44,10 @@ public class SYMBOL_FUNCTION extends LispFunction {
|
|||
|
||||
// make sure the function actually exists
|
||||
if (function != null) {
|
||||
if (function instanceof UDFunction) {
|
||||
if (function instanceof UserDefinedFunction) {
|
||||
// this is a user-defined function
|
||||
|
||||
UDFunction udFunction = (UDFunction) function;
|
||||
UserDefinedFunction udFunction = (UserDefinedFunction) function;
|
||||
|
||||
return udFunction.getLexpr();
|
||||
}
|
||||
|
|
|
@ -1,23 +1,10 @@
|
|||
/*
|
||||
* Name: Mike Cifelli
|
||||
* Course: CIS 443 - Programming Languages
|
||||
* Assignment: Lisp Interpreter 2
|
||||
*/
|
||||
|
||||
package eval;
|
||||
|
||||
import parser.*;
|
||||
import sexpression.Cons;
|
||||
import sexpression.SExpression;
|
||||
import sexpression.Symbol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A <code>UDFunction</code> is an internal representation of a user-defined
|
||||
* function in the Lisp programming language.
|
||||
*/
|
||||
public class UDFunction extends LispFunction {
|
||||
import sexpression.*;
|
||||
|
||||
public class UserDefinedFunction extends LispFunction {
|
||||
|
||||
// the number of arguments that this user-defined function takes.
|
||||
private final int NUM_ARGS;
|
||||
|
@ -40,7 +27,7 @@ public class UDFunction extends LispFunction {
|
|||
* @param body
|
||||
* the body of this user-defined function (MUST BE A PROPER LIST)
|
||||
*/
|
||||
public UDFunction(String name, Cons lambdaList, Cons body) {
|
||||
public UserDefinedFunction(String name, Cons lambdaList, Cons body) {
|
||||
this.name = name;
|
||||
this.body = body;
|
||||
this.lexpr = new Cons(new Symbol(name), new Cons(lambdaList, body));
|
|
@ -1,4 +0,0 @@
|
|||
<body>
|
||||
Provides functions and forms to be used during the evaluation of an
|
||||
S-expression.
|
||||
</body>
|
|
@ -1,7 +1,5 @@
|
|||
package file;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class FilePosition {
|
||||
|
||||
private String fileName;
|
||||
|
@ -11,29 +9,25 @@ public class FilePosition {
|
|||
public FilePosition(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
|
||||
public int getLineNumber() {
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
|
||||
public void setLineNumber(int lineNumber) {
|
||||
this.lineNumber = lineNumber;
|
||||
}
|
||||
|
||||
|
||||
public int getColumnNumber() {
|
||||
return columnNumber;
|
||||
}
|
||||
|
||||
|
||||
public void setColumnNumber(int columnNumber) {
|
||||
this.columnNumber = columnNumber;
|
||||
}
|
||||
|
||||
public boolean isEqual(FilePosition otherFilePosition) {
|
||||
return Objects.equals(this.fileName, otherFilePosition.fileName) && (this.lineNumber == otherFilePosition.lineNumber)
|
||||
&& (this.columnNumber == otherFilePosition.columnNumber);
|
||||
}
|
||||
}
|
|
@ -16,11 +16,10 @@ import java.io.*;
|
|||
import java.text.MessageFormat;
|
||||
|
||||
/**
|
||||
* <code>LispInterpreter</code> is an interpreter for the Lisp programming
|
||||
* language. It takes the name of a file as a command-line argument, evaluates
|
||||
* the S-expressions found in the file and then prints the results to the
|
||||
* console. If no file name is provided at the command-line, this program will
|
||||
* read from standard input.
|
||||
* This is an interpreter for the Lisp programming language. It takes the name of a file as a
|
||||
* command-line argument, evaluates the s-expressions found in the file and then prints the results
|
||||
* to the console. If no file name is provided at the command-line, this program will read from
|
||||
* standard input.
|
||||
*/
|
||||
public class LispInterpreter {
|
||||
|
||||
|
@ -31,15 +30,9 @@ public class LispInterpreter {
|
|||
public static final String ANSI_GREEN = "\u001B[32m";
|
||||
|
||||
/**
|
||||
* Evaluate the S-expressions found in the file given as a command-line
|
||||
* argument and print the results to the console. If no file name was given,
|
||||
* retrieve the S-expressions from standard input.
|
||||
*
|
||||
* @param args
|
||||
* the command-line arguments:
|
||||
* <ul>
|
||||
* <li><code>args[0]</code> - file name (optional)</li>
|
||||
* </ul>
|
||||
* Evaluate the s-expressions found in the file given as a command-line argument and print the
|
||||
* results to the console. If no file name was given, retrieve the s-expressions from standard
|
||||
* input.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
LispParser parser = null;
|
||||
|
@ -94,7 +87,7 @@ public class LispInterpreter {
|
|||
|
||||
@Override
|
||||
public int getSeverity() {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
<body>
|
||||
Provides test drivers for the various stages of the Lisp Interpreter.
|
||||
</body>
|
|
@ -9,8 +9,7 @@ import token.Eof;
|
|||
import token.Token;
|
||||
|
||||
/**
|
||||
* Converts a stream of bytes into internal representations of Lisp
|
||||
* S-expressions.
|
||||
* Converts a stream of bytes into internal representations of Lisp s-expressions.
|
||||
*/
|
||||
public class LispParser {
|
||||
|
||||
|
@ -50,7 +49,7 @@ public class LispParser {
|
|||
|
||||
isNextTokenStored = false;
|
||||
|
||||
return nextToken.sExpr(scanner::getNextToken);
|
||||
return nextToken.parseSExpression(scanner::getNextToken);
|
||||
}
|
||||
|
||||
private void throwDelayedExceptionIfNecessary() {
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
<body>
|
||||
Provides the classes necessary for creating an internal representation of
|
||||
the Lisp programming language.
|
||||
</body>
|
|
@ -1,3 +0,0 @@
|
|||
<body>
|
||||
Provides the classes necessary to perform a lexical analysis of the Lisp programming language.
|
||||
</body>
|
|
@ -1,44 +1,17 @@
|
|||
/*
|
||||
* Name: Mike Cifelli
|
||||
* Course: CIS 443 - Programming Languages
|
||||
* Assignment: Lisp Parser
|
||||
*/
|
||||
|
||||
package sexpression;
|
||||
|
||||
/**
|
||||
* This class represents an ATOM in the PL-Lisp implementation.
|
||||
*/
|
||||
public class Atom extends SExpression {
|
||||
public abstract class Atom extends SExpression {
|
||||
|
||||
private String text;
|
||||
|
||||
/**
|
||||
* Create a new ATOM with the specified text.
|
||||
*
|
||||
* @param text
|
||||
* the text representing this ATOM
|
||||
*/
|
||||
public Atom(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is an ATOM.
|
||||
*
|
||||
* @return
|
||||
* <code>true</code>
|
||||
*/
|
||||
public boolean atomp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this ATOM.
|
||||
*
|
||||
* @return
|
||||
* a string representation of this ATOM
|
||||
*/
|
||||
public String toString() {
|
||||
return text;
|
||||
}
|
||||
|
|
|
@ -1,88 +1,35 @@
|
|||
/*
|
||||
* Name: Mike Cifelli
|
||||
* Course: CIS 443 - Programming Languages
|
||||
* Assignment: Lisp Parser
|
||||
*/
|
||||
|
||||
package sexpression;
|
||||
|
||||
/**
|
||||
* This class represents a Lisp CONS cell in the PL-Lisp implementation.
|
||||
*/
|
||||
public class Cons extends SExpression {
|
||||
|
||||
private SExpression car;
|
||||
private SExpression cdr;
|
||||
|
||||
/**
|
||||
* Create a new CONS cell with the specified car and cdr.
|
||||
*
|
||||
* @param car
|
||||
* the car of this CONS cell
|
||||
* @param cdr
|
||||
* the cdr of this CONS cell
|
||||
*/
|
||||
public Cons(SExpression car, SExpression cdr) {
|
||||
this.car = car;
|
||||
this.cdr = cdr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the car of this CONS cell.
|
||||
*
|
||||
* @return
|
||||
* the car of this CONS cell
|
||||
*/
|
||||
public SExpression getCar() {
|
||||
return car;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the cdr of this CONS cell.
|
||||
*
|
||||
* @return
|
||||
* the cdr of this CONS cell
|
||||
*/
|
||||
public SExpression getCdr() {
|
||||
return cdr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the car of this CONS cell to the specified value.
|
||||
*
|
||||
* @param newCar
|
||||
* the value to assign to the car of this CONS cell
|
||||
*/
|
||||
public void setCar(SExpression newCar) {
|
||||
car = newCar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cdr of this CONS cell to the specified value.
|
||||
*
|
||||
* @param newCdr
|
||||
* the value to assign to the cdr of this CONS cell
|
||||
*/
|
||||
public void setCdr(SExpression newCdr) {
|
||||
cdr = newCdr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is a CONS cell.
|
||||
*
|
||||
* @return
|
||||
* <code>true</code>
|
||||
*/
|
||||
public boolean consp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this CONS cell.
|
||||
*
|
||||
* @return
|
||||
* a string representation of this CONS cell
|
||||
*/
|
||||
public String toString() {
|
||||
return ("(" + toStringAux());
|
||||
}
|
||||
|
@ -94,17 +41,12 @@ public class Cons extends SExpression {
|
|||
// this method. When used in conjunction with the 'toString' method of this
|
||||
// class, this method provides a means for creating the correct string
|
||||
// representation of a list.
|
||||
//
|
||||
// Returns: a string representation of the car of a CONS cell followed by
|
||||
// its cdr
|
||||
private String toStringAux() {
|
||||
if (cdr.nullp()) {
|
||||
if (cdr.nullp())
|
||||
return (car.toString() + ")");
|
||||
} else if (cdr.consp()) {
|
||||
else if (cdr.consp())
|
||||
return (car.toString() + " " + ((Cons) cdr).toStringAux());
|
||||
}
|
||||
|
||||
// the cdr of this CONS cell is not a list
|
||||
return (car.toString() + " . " + cdr.toString() + ")");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,65 +1,29 @@
|
|||
/*
|
||||
* Name: Mike Cifelli
|
||||
* Course: CIS 443 - Programming Languages
|
||||
* Assignment: Lisp Parser
|
||||
*/
|
||||
|
||||
package sexpression;
|
||||
|
||||
/**
|
||||
* This class represents a NUMBER in the PL-Lisp implementation.
|
||||
*/
|
||||
public class LispNumber extends Atom {
|
||||
|
||||
private int value;
|
||||
|
||||
/**
|
||||
* Create a new NUMBER with the specified text.
|
||||
*
|
||||
* @param text
|
||||
* the text representing this NUMBER
|
||||
* @throws IllegalArgumentException
|
||||
* Indicates that <code>text</code> does not represent a valid integer.
|
||||
*/
|
||||
public LispNumber(String text) {
|
||||
super(text.replaceFirst("^0+(?!$)", ""));
|
||||
|
||||
try {
|
||||
this.value = Integer.parseInt(text);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException(text +
|
||||
" is not a valid integer");
|
||||
throw new IllegalArgumentException(text + " is not a valid integer");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new NUMBER with the specified value.
|
||||
*
|
||||
* @param value
|
||||
* the integer value of this NUMBER
|
||||
*/
|
||||
public LispNumber(int value) {
|
||||
super(Integer.toString(value));
|
||||
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is a NUMBER.
|
||||
*
|
||||
* @return
|
||||
* <code>true</code>
|
||||
*/
|
||||
public boolean numberp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the integer value of this NUMBER.
|
||||
*
|
||||
* @return
|
||||
* the integer value of this NUMBER
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -1,32 +1,11 @@
|
|||
/*
|
||||
* Name: Mike Cifelli
|
||||
* Course: CIS 443 - Programming Languages
|
||||
* Assignment: Lisp Parser
|
||||
*/
|
||||
|
||||
package sexpression;
|
||||
|
||||
/**
|
||||
* This class represents a STRING in the PL-Lisp implementation.
|
||||
*/
|
||||
public class LispString extends Atom {
|
||||
|
||||
/**
|
||||
* Create a new STRING with the specified text.
|
||||
*
|
||||
* @param text
|
||||
* the text representing this STRING
|
||||
*/
|
||||
public LispString(String text) {
|
||||
super(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is a STRING.
|
||||
*
|
||||
* @return
|
||||
* <code>true</code>
|
||||
*/
|
||||
public boolean stringp() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,102 +1,48 @@
|
|||
/*
|
||||
* Name: Mike Cifelli
|
||||
* Course: CIS 443 - Programming Languages
|
||||
* Assignment: Lisp Parser
|
||||
*/
|
||||
|
||||
package sexpression;
|
||||
|
||||
/**
|
||||
* This class represents NIL in the PL-Lisp implementation.
|
||||
*/
|
||||
public class Nil extends Cons {
|
||||
|
||||
private static Nil uniqueInstance = new Nil();
|
||||
|
||||
/**
|
||||
* Retrieve the single unique instance of NIL.
|
||||
*
|
||||
* @return
|
||||
* the single unique instance of NIL
|
||||
*/
|
||||
public static Nil getUniqueInstance() {
|
||||
return uniqueInstance;
|
||||
}
|
||||
|
||||
// We are using the Singleton pattern, so the constructor for 'Nil' is
|
||||
// private.
|
||||
private Nil() {
|
||||
super(null, null);
|
||||
|
||||
// the car and cdr of NIL both refer to NIL
|
||||
super.setCar(this);
|
||||
super.setCdr(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is NULL.
|
||||
*
|
||||
* @return
|
||||
* <code>true</code>
|
||||
*/
|
||||
public boolean nullp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is an ATOM.
|
||||
*
|
||||
* @return
|
||||
* <code>true</code>
|
||||
*/
|
||||
public boolean atomp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is a CONS cell.
|
||||
*
|
||||
* @return
|
||||
* <code>false</code>
|
||||
*/
|
||||
public boolean consp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is a SYMBOL.
|
||||
*
|
||||
* @return
|
||||
* <code>true</code>
|
||||
*/
|
||||
public boolean symbolp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the car of this CONS cell to the specified value. This method does
|
||||
* nothing (the car of NIL can not be changed).
|
||||
*
|
||||
* @param newCar
|
||||
* the value to assign to the car of this CONS cell
|
||||
* Set the car of this CONS cell to the specified value. This method does nothing (the car of
|
||||
* NIL can not be changed).
|
||||
*/
|
||||
public void setCar(SExpression newCar) {}
|
||||
|
||||
/**
|
||||
* Set the cdr of this CONS cell to the specified value. This method does
|
||||
* nothing (the cdr of NIL can not be changed).
|
||||
*
|
||||
* @param newCdr
|
||||
* the value to assign to the cdr of this CONS cell
|
||||
* Set the cdr of this CONS cell to the specified value. This method does nothing (the cdr of
|
||||
* NIL can not be changed).
|
||||
*/
|
||||
public void setCdr(SExpression newCdr) {}
|
||||
|
||||
/**
|
||||
* Returns a string representation of NIL.
|
||||
*
|
||||
* @return
|
||||
* a string representation of NIL
|
||||
*/
|
||||
public String toString() {
|
||||
return "NIL";
|
||||
}
|
||||
|
|
|
@ -1,120 +1,49 @@
|
|||
/*
|
||||
* Name: Mike Cifelli
|
||||
* Course: CIS 443 - Programming Languages
|
||||
* Assignment: Lisp Parser
|
||||
*/
|
||||
|
||||
package sexpression;
|
||||
|
||||
/**
|
||||
* This is the base class for memory in the PL-Lisp implementation.
|
||||
*/
|
||||
public class SExpression {
|
||||
public abstract class SExpression {
|
||||
|
||||
// for mark and sweep garbage collection
|
||||
private boolean marked = false;
|
||||
|
||||
/**
|
||||
* Determine if this <code>SExpression</code> is marked.
|
||||
*
|
||||
* @return
|
||||
* <code>true</code> if this <code>SExpression</code> is marked;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public final boolean isMarked() {
|
||||
return marked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the marked status of this S-expression to the specified value.
|
||||
*
|
||||
* @param value
|
||||
* the value to assign to this S-expression's marked status
|
||||
*/
|
||||
public final void setMarked(final boolean value) {
|
||||
marked = value;
|
||||
}
|
||||
|
||||
// Lisp type predicates;
|
||||
// by default, all return false (an SExpression effectively has NO type);
|
||||
// Lisp type predicates...
|
||||
// overridden in subclasses to describe their Lisp type
|
||||
|
||||
/**
|
||||
* Test if this S-expression is NULL.
|
||||
*
|
||||
* @return
|
||||
* <code>false</code>
|
||||
*/
|
||||
public boolean nullp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is an ATOM.
|
||||
*
|
||||
* @return
|
||||
* <code>false</code>
|
||||
*/
|
||||
public boolean atomp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is a CONS cell.
|
||||
*
|
||||
* @return
|
||||
* <code>false</code>
|
||||
*/
|
||||
public boolean consp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is a LIST.
|
||||
*
|
||||
* @return
|
||||
* the value of <code>(consp() || nullp())</code>
|
||||
*/
|
||||
public boolean listp() {
|
||||
return (consp() || nullp());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is a NUMBER.
|
||||
*
|
||||
* @return
|
||||
* <code>false</code>
|
||||
*/
|
||||
public boolean numberp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is a SYMBOL.
|
||||
*
|
||||
* @return
|
||||
* <code>false</code>
|
||||
*/
|
||||
public boolean symbolp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is a FUNCTION.
|
||||
*
|
||||
* @return
|
||||
* <code>false</code>
|
||||
*/
|
||||
public boolean functionp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is a STRING.
|
||||
*
|
||||
* @return
|
||||
* <code>false</code>
|
||||
*/
|
||||
public boolean stringp() {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,35 +1,17 @@
|
|||
/*
|
||||
* Name: Mike Cifelli
|
||||
* Course: CIS 443 - Programming Languages
|
||||
* Assignment: Lisp Parser
|
||||
*/
|
||||
|
||||
package sexpression;
|
||||
|
||||
/**
|
||||
* This class represents a SYMBOL in the PL-Lisp implementation.
|
||||
*/
|
||||
public class Symbol extends Atom {
|
||||
|
||||
/** This SYMBOL represents TRUE in the PL-Lisp implementation. */
|
||||
public static final Symbol T = new Symbol("T");
|
||||
|
||||
public static Symbol createQuote() {
|
||||
return new Symbol("QUOTE");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new SYMBOL with the specified text.
|
||||
*
|
||||
* @param text
|
||||
* the text representing this SYMBOL
|
||||
*/
|
||||
public Symbol(String text) {
|
||||
super(text.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this S-expression is a SYMBOL.
|
||||
*
|
||||
* @return
|
||||
* <code>true</code>
|
||||
*/
|
||||
public boolean symbolp() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ public class Eof extends Token {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SExpression sExpr(Supplier<Token> getNextToken) {
|
||||
public SExpression parseSExpression(Supplier<Token> getNextToken) {
|
||||
throw new EofEncounteredException(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ public class Identifier extends Token {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SExpression sExpr(Supplier<Token> getNextToken) {
|
||||
public SExpression parseSExpression(Supplier<Token> getNextToken) {
|
||||
return new Symbol(getText());
|
||||
}
|
||||
|
||||
|
|
|
@ -12,10 +12,10 @@ public class LeftParenthesis extends Token {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SExpression sExpr(Supplier<Token> getNextToken) {
|
||||
public SExpression parseSExpression(Supplier<Token> getNextToken) {
|
||||
Token nextToken = getNextToken.get();
|
||||
|
||||
return nextToken.sExprTail(getNextToken);
|
||||
return nextToken.parseSExpressionTail(getNextToken);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ public class Number extends Token {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SExpression sExpr(Supplier<Token> getNextToken) {
|
||||
public SExpression parseSExpression(Supplier<Token> getNextToken) {
|
||||
return new LispNumber(getText());
|
||||
}
|
||||
|
||||
|
|
|
@ -12,11 +12,11 @@ public class QuoteMark extends Token {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SExpression sExpr(Supplier<Token> getNextToken) {
|
||||
public SExpression parseSExpression(Supplier<Token> getNextToken) {
|
||||
Token nextToken = getNextToken.get();
|
||||
SExpression argument = nextToken.sExpr(getNextToken);
|
||||
SExpression argument = nextToken.parseSExpression(getNextToken);
|
||||
|
||||
return new Cons(new Symbol("QUOTE"), new Cons(argument, Nil.getUniqueInstance()));
|
||||
return new Cons(Symbol.createQuote(), new Cons(argument, Nil.getUniqueInstance()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ public class QuotedString extends Token {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SExpression sExpr(Supplier<Token> getNextToken) {
|
||||
public SExpression parseSExpression(Supplier<Token> getNextToken) {
|
||||
return new LispString(getText());
|
||||
}
|
||||
|
||||
|
|
|
@ -14,12 +14,12 @@ public class RightParenthesis extends Token {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SExpression sExpr(Supplier<Token> getNextToken) {
|
||||
public SExpression parseSExpression(Supplier<Token> getNextToken) {
|
||||
throw new StartsWithRightParenthesisException(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SExpression sExprTail(Supplier<Token> getNextToken) {
|
||||
public SExpression parseSExpressionTail(Supplier<Token> getNextToken) {
|
||||
return Nil.getUniqueInstance();
|
||||
}
|
||||
|
||||
|
|
|
@ -35,16 +35,15 @@ public abstract class Token {
|
|||
return position.getColumnNumber();
|
||||
}
|
||||
|
||||
// sExpr ::= NUMBER | IDENTIFIER | STRING | QUOTE_MARK sExpr |
|
||||
// LEFT_PAREN sExprTail
|
||||
public abstract SExpression sExpr(Supplier<Token> getNextToken);
|
||||
// sExpr ::= NUMBER | IDENTIFIER | STRING | QUOTE_MARK sExpr | LEFT_PAREN sExprTail
|
||||
public abstract SExpression parseSExpression(Supplier<Token> getNextToken);
|
||||
|
||||
// sExprTail ::= RIGHT_PAREN | sExpr sExprTail
|
||||
public SExpression sExprTail(Supplier<Token> getNextToken) {
|
||||
SExpression car = sExpr(getNextToken);
|
||||
public SExpression parseSExpressionTail(Supplier<Token> getNextToken) {
|
||||
SExpression car = parseSExpression(getNextToken);
|
||||
|
||||
Token nextToken = getNextToken.get();
|
||||
SExpression cdr = nextToken.sExprTail(getNextToken);
|
||||
SExpression cdr = nextToken.parseSExpressionTail(getNextToken);
|
||||
|
||||
return new Cons(car, cdr);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package file;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -20,81 +21,46 @@ public class FilePositionTrackerTester {
|
|||
return position;
|
||||
}
|
||||
|
||||
private void assertTrackerPositionEquals(FilePosition expectedPosition) {
|
||||
assertTrue(arePositionsEqual(expectedPosition, trackerUnderTest.getCurrentPosition()));
|
||||
}
|
||||
|
||||
private boolean arePositionsEqual(FilePosition position1, FilePosition position2) {
|
||||
return Objects.equals(position1.getFileName(), position2.getFileName())
|
||||
&& Objects.equals(position1.getLineNumber(), position2.getLineNumber())
|
||||
&& Objects.equals(position1.getColumnNumber(), position2.getColumnNumber());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
trackerUnderTest = new FilePositionTracker(FILE_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filePositionEquality_CorrectlyReturnsTrue() {
|
||||
FilePosition positionOne = createFilePosition(5, 9);
|
||||
FilePosition positionTwo = createFilePosition(5, 9);
|
||||
|
||||
assertTrue(positionOne.isEqual(positionTwo));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filePositionEquality_CorrectlyReturnsFalseWithDifferentLine() {
|
||||
FilePosition positionOne = createFilePosition(5, 9);
|
||||
FilePosition positionTwo = createFilePosition(8, 9);
|
||||
|
||||
assertFalse(positionOne.isEqual(positionTwo));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filePositionEquality_CorrectlyReturnsFalseWithDifferentColumn() {
|
||||
FilePosition positionOne = createFilePosition(5, 9);
|
||||
FilePosition positionTwo = createFilePosition(5, 10);
|
||||
|
||||
assertFalse(positionOne.isEqual(positionTwo));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filePositionEquality_CorrectlyReturnsFalseWithDifferentFileName() {
|
||||
FilePosition positionOne = new FilePosition("FileOne");
|
||||
positionOne.setLineNumber(5);
|
||||
positionOne.setColumnNumber(9);
|
||||
|
||||
FilePosition positionTwo = new FilePosition("FileTwo");
|
||||
positionTwo.setLineNumber(5);
|
||||
positionTwo.setColumnNumber(9);
|
||||
|
||||
assertFalse(positionOne.isEqual(positionTwo));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noMovement_ReturnsInitialPosition() {
|
||||
FilePosition expectedPosition = createFilePosition(1, 0);
|
||||
|
||||
assertTrue(expectedPosition.isEqual(trackerUnderTest.getCurrentPosition()));
|
||||
assertTrackerPositionEquals(createFilePosition(1, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void advanceOneColumn_ReturnsCorrectPosition() {
|
||||
FilePosition expectedPosition = createFilePosition(1, 1);
|
||||
|
||||
trackerUnderTest.incrementColumn();
|
||||
|
||||
assertTrue(expectedPosition.isEqual(trackerUnderTest.getCurrentPosition()));
|
||||
assertTrackerPositionEquals(createFilePosition(1, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void advanceOneLine_ReturnsCorrectPosition() {
|
||||
FilePosition expectedPosition = createFilePosition(2, 0);
|
||||
|
||||
trackerUnderTest.incrementLine();
|
||||
|
||||
assertTrue(expectedPosition.isEqual(trackerUnderTest.getCurrentPosition()));
|
||||
assertTrackerPositionEquals(createFilePosition(2, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void advanceOneLine_ResetsColumn() {
|
||||
FilePosition expectedPosition = createFilePosition(2, 0);
|
||||
|
||||
trackerUnderTest.incrementColumn();
|
||||
trackerUnderTest.incrementLine();
|
||||
|
||||
assertTrue(expectedPosition.isEqual(trackerUnderTest.getCurrentPosition()));
|
||||
assertTrackerPositionEquals(createFilePosition(2, 0));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue