Browse Source

Add tests and fixes

pull/1/head
Malte Schmitz 9 years ago
parent
commit
bd6bfb17bd
3 changed files with 158 additions and 43 deletions
  1. +4
    -4
      src/expression/Int.java
  2. +23
    -23
      src/parser/Parser.java
  3. +131
    -16
      test/parser/ParserTest.java

src/expression/Number.java → src/expression/Int.java View File

@@ -1,9 +1,9 @@
package expression;

public class Number extends Expression {
public class Int extends Expression {
public final int value;

public Number(int value) {
public Int(int value) {
this.value = value;
}

@@ -12,9 +12,9 @@ public class Number extends Expression {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Number number = (Number) o;
Int integer = (Int) o;

return value == number.value;
return value == integer.value;

}


+ 23
- 23
src/parser/Parser.java View File

@@ -1,7 +1,7 @@
package parser;

import expression.*;
import expression.Number;
import expression.Int;
import program.*;

import java.util.ArrayList;
@@ -10,8 +10,8 @@ import java.util.Optional;

public class Parser {

private int position = 0;
private String input;
int position = 0;
String input;

public Parser(String input) {
this.input = input;
@@ -27,7 +27,7 @@ public class Parser {
return program;
}

private Optional<Program> program() {
Optional<Program> program() {
List<Program> statements = new ArrayList<>();
boolean run = true;
int start = position;
@@ -53,7 +53,7 @@ public class Parser {
return program;
}

private Optional<Program> statement() {
Optional<Program> statement() {
int start = position;
Optional<Program> result = assignment();
if (!result.isPresent()) {
@@ -67,7 +67,7 @@ public class Parser {
return result;
}

private Optional<Program> loop() {
Optional<Program> loop() {
if (token("while") && token("(")) {
Optional<Expression> condition = expression();
return condition.flatMap(cond -> {
@@ -81,13 +81,13 @@ public class Parser {
return Optional.empty();
}

private Optional<Program> conditional() {
Optional<Program> conditional() {
if (token("if") && token("(")) {
Optional<Expression> condition = expression();
condition.flatMap(cond -> {
return condition.flatMap(cond -> {
if (token(")") && token("then") && token("{")) {
Optional<Program> thenCase = program();
thenCase.flatMap(thenC -> {
return thenCase.flatMap(thenC -> {
if (token("}") && token("else") && token("{")) {
Optional<Program> elseCase = program();
return elseCase.filter(elseC -> token("}")).map(elseC -> new Conditional(cond, thenC, elseC));
@@ -101,7 +101,7 @@ public class Parser {
return Optional.empty();
}

private Optional<Program> assignment() {
Optional<Program> assignment() {
Optional<Identifier> identifier = identifier();
return identifier.flatMap(id -> {
if (token(":=")) {
@@ -112,17 +112,17 @@ public class Parser {
});
}

private static class OperatorWithExpression {
static class OperatorWithExpression {
private final Operator operator;
private final Expression expression;

private OperatorWithExpression(Operator operator, Expression expression) {
OperatorWithExpression(Operator operator, Expression expression) {
this.operator = operator;
this.expression = expression;
}
}

private enum Operator {
enum Operator {
PLUS, MINUS, NONE;

Expression toOperation(Expression leftHandSide, Expression rightHandSide) {
@@ -136,7 +136,7 @@ public class Parser {
}
}

private Optional<Expression> expression() {
Optional<Expression> expression() {
List<OperatorWithExpression> atoms = new ArrayList<>();
Operator operator = Operator.PLUS;
int start = position;
@@ -163,7 +163,7 @@ public class Parser {
return expression;
}

private Operator operator() {
Operator operator() {
if (token("+")) {
return Operator.PLUS;
} else if (token("-")) {
@@ -173,7 +173,7 @@ public class Parser {
}
}

private Optional<Expression> atom() {
Optional<Expression> atom() {
int start = position;
Optional<Expression> result;
if (token("(")) {
@@ -181,7 +181,7 @@ public class Parser {
result = expression.filter(exp -> token(")"));
} else {
position = start;
result = number();
result = integer();
if (!result.isPresent()) {
position = start;
result = identifier().map(id -> id);
@@ -190,11 +190,11 @@ public class Parser {
return result;
}

private boolean isLowerLetter(char ch) {
boolean isLowerLetter(char ch) {
return ch >= 'a' && ch <= 'z';
}

private Optional<Expression> number() {
Optional<Expression> integer() {
whitespace();
int start = position;
boolean minus = position < input.length() && input.charAt(position) == '-';
@@ -207,13 +207,13 @@ public class Parser {
digitsFound = true;
}
if (digitsFound) {
return Optional.of(new Number(Integer.parseInt(input.substring(start, position))));
return Optional.of(new Int(Integer.parseInt(input.substring(start, position))));
} else {
return Optional.empty();
}
}

private Optional<Identifier> identifier() {
Optional<Identifier> identifier() {
whitespace();
int start = position;
while (position < input.length() && isLowerLetter(input.charAt(position))) {
@@ -226,13 +226,13 @@ public class Parser {
return Optional.empty();
}

private void whitespace() {
void whitespace() {
while(position < input.length() && Character.isWhitespace(input.charAt(position))) {
position += 1;
}
}

private boolean token(String token) {
boolean token(String token) {
whitespace();
boolean success = position + token.length() <= input.length() && input.substring(position, position + token.length()).equals(token);
if (success) {


+ 131
- 16
test/parser/ParserTest.java View File

@@ -1,25 +1,140 @@
package parser;

import expression.Addition;
import expression.Identifier;
import expression.Number;
import expression.Subtraction;
import org.junit.Assert;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Test;
import program.Assignment;
import program.Composition;
import program.Loop;
import program.Program;
import expression.*;
import parser.Parser.Operator;
import program.*;

import java.util.Optional;

public class ParserTest {
final String loopCode = "while (a) { r := r + b ; a := a - 1 }";
final Loop loop = new Loop(new Identifier("a"), new Composition(new Assignment(new Identifier("r"), new Addition(new Identifier("r"), new Identifier("b"))), new Assignment(new Identifier("a"), new Subtraction(new Identifier("a"), new Int(1)))));

final String assignmentCode = "a := 2";
final Assignment assignment = new Assignment(new Identifier("a"), new Int(2));

final String compositionCode = assignmentCode + " ; b := bar";
final Composition composition = new Composition(assignment, new Assignment(new Identifier("b"), new Identifier("bar")));

final String conditionalCode = "if (foo - bar) then { x := 5 } else { x := x }";
final Conditional conditional = new Conditional(new Subtraction(new Identifier("foo"), new Identifier("bar")), new Assignment(new Identifier("x"), new Int(5)), new Assignment(new Identifier("x"), new Identifier("x")));

final String programCode = compositionCode + " ; " + loopCode + " ; " + conditionalCode;
final Program program = new Composition(new Composition(composition, loop), conditional);

@Test
public void testParse() {
String program = "a := 2 ; b := 4 ; r := 0 ; while (a) { r := r + b ; a := a - 1 }";
Parser parser = new Parser(program);
Program initialization = new Composition(new Composition(new Assignment(new Identifier("a"), new Number(2)), new Assignment(new Identifier("b"), new Number(4))), new Assignment(new Identifier("r"), new Number(0)));
Program loop = new Loop(new Identifier("a"), new Composition(new Assignment(new Identifier("r"), new Addition(new Identifier("r"), new Identifier("b"))), new Assignment(new Identifier("a"), new Subtraction(new Identifier("a"), new Number(1)))));
Program expected = new Composition(initialization, loop);
Program actual = parser.parse();
Assert.assertEquals(expected, actual);
Parser parser = new Parser(programCode);
assertEquals(program, parser.parse());
}

@Test
public void testProgram() {
Parser parser = new Parser(programCode);
assertEquals(Optional.of(program), parser.program());
}

@Test
public void testStatementAssignment() {
Parser parser = new Parser(assignmentCode);
assertEquals(Optional.of(assignment), parser.statement());
}

@Test
public void testStatementConditional() {
Parser parser = new Parser(conditionalCode);
assertEquals(Optional.of(conditional), parser.statement());
}

@Test
public void testStatementLoop() {
Parser parser = new Parser(loopCode);
assertEquals(Optional.of(loop), parser.statement());
}

@Test
public void testAssignment() {
Parser parser = new Parser(assignmentCode);
assertEquals(Optional.of(assignment), parser.assignment());
}

@Test
public void testConditional() {
Parser parser = new Parser(conditionalCode);
assertEquals(Optional.of(conditional), parser.conditional());
}

@Test
public void testLoop() {
Parser parser = new Parser(loopCode);
assertEquals(Optional.of(loop), parser.loop());
}

final String expressionCode = "a+b - (c - 56) + -47";
final Expression expression = new Addition(new Subtraction(new Addition(new Identifier("a"), new Identifier("b")), new Subtraction(new Identifier("c"), new Int(56))), new Int(-47));

@Test
public void testExpression() {
Parser parser = new Parser(expressionCode);
assertEquals(Optional.of(expression), parser.expression());
}

@Test
public void testOperatorMinus() {
Parser parser = new Parser("-");
assertEquals(Operator.MINUS, parser.operator());
}

@Test
public void testOperatorPlus() {
Parser parser = new Parser("+");
assertEquals(Operator.PLUS, parser.operator());
}

@Test
public void testAtomExpression() {
Parser parser = new Parser("(" + expressionCode + ")");
assertEquals(Optional.of(expression), parser.atom());
}

@Test
public void testAtomNumber() {
Parser parser = new Parser("37658");
assertEquals(Optional.of(new Int(37658)), parser.atom());
}

@Test
public void testAtomIdentifier() {
Parser parser = new Parser("egjfd");
assertEquals(Optional.of(new Identifier("egjfd")), parser.atom());
}

@Test
public void testNumber() {
Parser parser = new Parser("37658");
assertEquals(Optional.of(new Int(37658)), parser.integer());
}

@Test
public void testIdentifier() {
Parser parser = new Parser("egjfd");
assertEquals(Optional.of(new Identifier("egjfd")), parser.identifier());
}

@Test
public void testWhitespace() {
Parser parser = new Parser(" \n\t x");
parser.whitespace();
assertEquals('x', parser.input.charAt(parser.position));
}

@Test
public void testToken() {
Parser parser = new Parser("gehjfwdk");
assertTrue(parser.token("gehjfwdk"));
}
}

Loading…
Cancel
Save