Resolves #7 - Allow prefixing of numbers
This commit is contained in:
parent
bf40feadec
commit
fb35884479
|
@ -2,13 +2,14 @@
|
|||
Test
|
||||
---
|
||||
| script | lisp interpreter fixture |
|
||||
| evaluate | (defun adderx (x) (lambda (y) (+ x y))) |
|
||||
| evaluate | (setf adder20 (adderx 20)) |
|
||||
| show | evaluate | (defun adderx (x) (lambda (y) (+ x y))) |
|
||||
| show | evaluate | (setf adder20 (adderx 20)) |
|
||||
| check | evaluate | (funcall adder20 2) | 22 |
|
||||
|
||||
|
||||
| script | lisp interpreter fixture |
|
||||
| evaluate |{{{!-
|
||||
| # | Let Over Lambda Over Let Over Lambda |
|
||||
| show | evaluate |!-
|
||||
|
||||
(let ((direction 'up))
|
||||
(defun toggle-counter-direction ()
|
||||
|
@ -23,16 +24,16 @@ Test
|
|||
(if (eq direction 'up)
|
||||
(setq counter (+ counter 1))
|
||||
(setq counter (- counter 1)))))))
|
||||
-!}}}|
|
||||
| evaluate | (setq my-counter (counter-class)) |
|
||||
-!|
|
||||
| show | evaluate | (setq my-counter (counter-class)) |
|
||||
| check | evaluate | (funcall my-counter) | 1 |
|
||||
| check | evaluate | (funcall my-counter) | 2 |
|
||||
| check | evaluate | (funcall my-counter) | 3 |
|
||||
| evaluate | (toggle-counter-direction) |
|
||||
| show | evaluate | (toggle-counter-direction) |
|
||||
| check | evaluate | (funcall my-counter) | 2 |
|
||||
| check | evaluate | (funcall my-counter) | 1 |
|
||||
| check | evaluate | (funcall my-counter) | 0 |
|
||||
| evaluate | (toggle-counter-direction) |
|
||||
| show | evaluate | (toggle-counter-direction) |
|
||||
| check | evaluate | (funcall my-counter) | 1 |
|
||||
| check | evaluate | (funcall my-counter) | 2 |
|
||||
| check | evaluate | (funcall my-counter) | 3 |
|
|
@ -1,4 +1,4 @@
|
|||
|LispInterpreter.LexicalClosures||11:52:29 Mon, Feb 27, 2017|
|
||||
|LispInterpreter.LexicalClosures||12:10:13 Mon, Feb 27, 2017|
|
||||
|LispInterpreter.TestClosure||11:24:27 Mon, Feb 27, 2017|
|
||||
|LispInterpreter.TestOne||09:26:08 Fri, Feb 24, 2017|
|
||||
|LispInterpreter.SuiteSetUp||14:27:52 Wed, Feb 22, 2017|
|
||||
|
|
|
@ -29,19 +29,19 @@
|
|||
)
|
||||
|
||||
(defun one-year-with-negative-interest-rate ()
|
||||
(assert= 95000 (compound-interest 100000 (- 5) 1))
|
||||
(assert= 95000 (compound-interest 100000 -5 1))
|
||||
)
|
||||
|
||||
(defun two-years-with-negative-interest-rate ()
|
||||
(assert= 90250 (compound-interest 100000 (- 5) 2))
|
||||
(assert= 90250 (compound-interest 100000 -5 2))
|
||||
)
|
||||
|
||||
(defun three-years-with-negative-interest-rate ()
|
||||
(assert= 85737 (compound-interest 100000 (- 5) 3))
|
||||
(assert= 85737 (compound-interest 100000 -5 3))
|
||||
)
|
||||
|
||||
(defun four-years-with-negative-interest-rate ()
|
||||
(assert= 81450 (compound-interest 100000 (- 5) 4))
|
||||
(assert= 81450 (compound-interest 100000 -5 4))
|
||||
)
|
||||
|
||||
)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package scanner;
|
||||
|
||||
import static java.lang.Character.*;
|
||||
import static util.Characters.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
@ -30,7 +31,7 @@ public class LispScanner {
|
|||
char currentCharacter = (char) c;
|
||||
positionTracker.incrementColumn();
|
||||
|
||||
if (!Character.isWhitespace(currentCharacter))
|
||||
if (!isWhitespace(currentCharacter))
|
||||
return createTokenFromCharacter(currentCharacter);
|
||||
else if (currentCharacter == NEWLINE)
|
||||
positionTracker.incrementLine();
|
||||
|
@ -51,9 +52,11 @@ public class LispScanner {
|
|||
|
||||
if (firstCharacter == DOUBLE_QUOTE)
|
||||
tokenText = retrieveStringTokenText(firstCharacter);
|
||||
else if (Character.isDigit(firstCharacter))
|
||||
else if (isNumberPrefix(firstCharacter))
|
||||
tokenText = retrieveNumberOrIdentifierTokenText(firstCharacter);
|
||||
else if (isDigit(firstCharacter))
|
||||
tokenText = retrieveNumberTokenText(firstCharacter);
|
||||
else if (Characters.isLegalIdentifierCharacter(firstCharacter))
|
||||
else if (isLegalIdentifierCharacter(firstCharacter))
|
||||
tokenText = retrieveIdentifierTokenText(firstCharacter);
|
||||
|
||||
return tokenText;
|
||||
|
@ -66,8 +69,18 @@ public class LispScanner {
|
|||
return retriever.retrieveToken();
|
||||
}
|
||||
|
||||
private String retrieveNumberTokenText(char firstDigit) {
|
||||
ComplexTokenTextRetriever retriever = new ComplexTokenTextRetriever(firstDigit, Character::isDigit);
|
||||
private String retrieveNumberOrIdentifierTokenText(char firstCharacter) {
|
||||
char nextCharacter = (char) inputStream.read();
|
||||
inputStream.unreadLastCharacter();
|
||||
|
||||
if (isDigit(nextCharacter))
|
||||
return retrieveNumberTokenText(firstCharacter);
|
||||
|
||||
return retrieveIdentifierTokenText(firstCharacter);
|
||||
}
|
||||
|
||||
private String retrieveNumberTokenText(char firstCharacter) {
|
||||
ComplexTokenTextRetriever retriever = new ComplexTokenTextRetriever(firstCharacter, Character::isDigit);
|
||||
|
||||
return retriever.retrieveToken();
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package token;
|
||||
|
||||
import static java.lang.Character.isDigit;
|
||||
import static util.Characters.*;
|
||||
|
||||
import file.FilePosition;
|
||||
import util.Characters;
|
||||
|
||||
public class TokenFactoryImpl implements TokenFactory {
|
||||
|
||||
|
@ -23,9 +23,9 @@ public class TokenFactoryImpl implements TokenFactory {
|
|||
case DOUBLE_QUOTE:
|
||||
return new QuotedString(text, position);
|
||||
default:
|
||||
if (Character.isDigit(firstCharacter)) {
|
||||
if (isNumeric(firstCharacter, text)) {
|
||||
return new Number(text, position);
|
||||
} else if (Characters.isLegalIdentifierCharacter(firstCharacter)) {
|
||||
} else if (isLegalIdentifierCharacter(firstCharacter)) {
|
||||
return new Identifier(text, position);
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,18 @@ public class TokenFactoryImpl implements TokenFactory {
|
|||
throw new BadCharacterException(text, position);
|
||||
}
|
||||
|
||||
private boolean isNumeric(char firstCharacter, String text) {
|
||||
return isDigit(firstCharacter) || isPrefixedNumeric(firstCharacter, text);
|
||||
}
|
||||
|
||||
private boolean isPrefixedNumeric(char firstCharacter, String text) {
|
||||
return isNumberPrefix(firstCharacter) && isNextCharacterDigit(text);
|
||||
}
|
||||
|
||||
private boolean isNextCharacterDigit(String text) {
|
||||
return (text.length() > 1) && isDigit(text.charAt(1));
|
||||
}
|
||||
|
||||
public Token createEOFToken(FilePosition position) {
|
||||
return new Eof("EOF", position);
|
||||
}
|
||||
|
|
|
@ -9,12 +9,14 @@ public final class Characters {
|
|||
public static final int EOF = -1;
|
||||
|
||||
public static final char BACKSLASH = '\\';
|
||||
public static final char DASH = '-';
|
||||
public static final char DOUBLE_QUOTE = '\"';
|
||||
public static final char HASH = '#';
|
||||
public static final char LEFT_PARENTHESIS = '(';
|
||||
public static final char LEFT_SQUARE_BRACKET = '[';
|
||||
public static final char NEWLINE = '\n';
|
||||
public static final char PERIOD = '.';
|
||||
public static final char PLUS = '+';
|
||||
public static final char RIGHT_PARENTHESIS = ')';
|
||||
public static final char RIGHT_SQUARE_BRACKET = ']';
|
||||
public static final char SEMICOLON = ';';
|
||||
|
@ -45,4 +47,8 @@ public final class Characters {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static boolean isNumberPrefix(char c) {
|
||||
return c == DASH || c == PLUS;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -161,6 +161,15 @@ public class LispScannerTypeTester {
|
|||
assertTokenTypesMatch(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenPrefixedIdentifiers_ReturnsCorrectTypes() {
|
||||
String input = "-a +b";
|
||||
expectedTypes.add(Identifier.class);
|
||||
expectedTypes.add(Identifier.class);
|
||||
|
||||
assertTokenTypesMatch(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSingleDigitNumber_ReturnsCorrectTypes() {
|
||||
String input = "1";
|
||||
|
@ -169,6 +178,58 @@ public class LispScannerTypeTester {
|
|||
assertTokenTypesMatch(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenPrefixedNegativeNumber_ReturnsCorrectTypes() {
|
||||
String input = "-1";
|
||||
expectedTypes.add(Number.class);
|
||||
|
||||
assertTokenTypesMatch(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenPrefixedNumber_ReturnsCorrectTypes() {
|
||||
String input = "+1";
|
||||
expectedTypes.add(Number.class);
|
||||
|
||||
assertTokenTypesMatch(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenPrefixedNegativeNumberAndIdentifier_ReturnsCorrectTypes() {
|
||||
String input = "-1apple";
|
||||
expectedTypes.add(Number.class);
|
||||
expectedTypes.add(Identifier.class);
|
||||
|
||||
assertTokenTypesMatch(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenPrefixedNumberAndIdentifier_ReturnsCorrectTypes() {
|
||||
String input = "+1apple";
|
||||
expectedTypes.add(Number.class);
|
||||
expectedTypes.add(Identifier.class);
|
||||
|
||||
assertTokenTypesMatch(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenPrefixedNegativeNumberAndString_ReturnsCorrectTypes() {
|
||||
String input = "-1\"apple\"";
|
||||
expectedTypes.add(Number.class);
|
||||
expectedTypes.add(QuotedString.class);
|
||||
|
||||
assertTokenTypesMatch(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenPrefixedNumberAndString_ReturnsCorrectTypes() {
|
||||
String input = "+1\"apple\"";
|
||||
expectedTypes.add(Number.class);
|
||||
expectedTypes.add(QuotedString.class);
|
||||
|
||||
assertTokenTypesMatch(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMultipleDigitNumber_ReturnsCorrectTypes() {
|
||||
String input = "1234567890";
|
||||
|
|
Loading…
Reference in New Issue