瀏覽代碼

Initial version

pull/1/head
Malte Schmitz 9 年之前
父節點
當前提交
812f144c69
共有 15 個文件被更改,包括 585 次插入0 次删除
  1. +3
    -0
      .gitignore
  2. +5
    -0
      src/Main.java
  3. +35
    -0
      src/expression/Addition.java
  4. +4
    -0
      src/expression/Expression.java
  5. +30
    -0
      src/expression/Identifier.java
  6. +30
    -0
      src/expression/Number.java
  7. +35
    -0
      src/expression/Subtraction.java
  8. +243
    -0
      src/parser/Parser.java
  9. +20
    -0
      src/parser/SyntaxException.java
  10. +38
    -0
      src/program/Assignment.java
  11. +35
    -0
      src/program/Composition.java
  12. +41
    -0
      src/program/Conditional.java
  13. +37
    -0
      src/program/Loop.java
  14. +4
    -0
      src/program/Program.java
  15. +25
    -0
      test/parser/ParserTest.java

+ 3
- 0
.gitignore 查看文件

@@ -0,0 +1,3 @@
.idea/
*.iml
/out

+ 5
- 0
src/Main.java 查看文件

@@ -0,0 +1,5 @@
public class Main {
public static void main(String[] args) {

}
}

+ 35
- 0
src/expression/Addition.java 查看文件

@@ -0,0 +1,35 @@
package expression;

public class Addition extends Expression {
public final Expression leftHandSide;
public final Expression rightHandSide;

public Addition(Expression leftHandSide, Expression rightHandSide) {
this.leftHandSide = leftHandSide;
this.rightHandSide = rightHandSide;
}

@Override
public String toString() {
return "(" + leftHandSide + " + " + rightHandSide + ")";
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Addition addition = (Addition) o;

if (!leftHandSide.equals(addition.leftHandSide)) return false;
return rightHandSide.equals(addition.rightHandSide);

}

@Override
public int hashCode() {
int result = leftHandSide.hashCode();
result = 31 * result + rightHandSide.hashCode();
return result;
}
}

+ 4
- 0
src/expression/Expression.java 查看文件

@@ -0,0 +1,4 @@
package expression;

abstract public class Expression {
}

+ 30
- 0
src/expression/Identifier.java 查看文件

@@ -0,0 +1,30 @@
package expression;

public class Identifier extends Expression {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Identifier that = (Identifier) o;

return name.equals(that.name);

}

@Override
public String toString() {
return name;
}

@Override
public int hashCode() {
return name.hashCode();
}

public final String name;

public Identifier(String name) {
this.name = name;
}
}

+ 30
- 0
src/expression/Number.java 查看文件

@@ -0,0 +1,30 @@
package expression;

public class Number extends Expression {
public final int value;

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

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Number number = (Number) o;

return value == number.value;

}

@Override
public String toString() {
return Integer.toString(value);
}

@Override
public int hashCode() {
return value;
}
}

+ 35
- 0
src/expression/Subtraction.java 查看文件

@@ -0,0 +1,35 @@
package expression;

public class Subtraction extends Expression {
public final Expression leftHandSide;
public final Expression rightHandSide;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Subtraction that = (Subtraction) o;

if (!leftHandSide.equals(that.leftHandSide)) return false;
return rightHandSide.equals(that.rightHandSide);

}

@Override
public String toString() {
return "(" + leftHandSide + " - " + rightHandSide + ")";
}

@Override
public int hashCode() {
int result = leftHandSide.hashCode();
result = 31 * result + rightHandSide.hashCode();
return result;
}

public Subtraction(Expression leftHandSide, Expression rightHandSide) {
this.leftHandSide = leftHandSide;
this.rightHandSide = rightHandSide;
}
}

+ 243
- 0
src/parser/Parser.java 查看文件

@@ -0,0 +1,243 @@
package parser;

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

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class Parser {

private int position = 0;
private String input;

public Parser(String input) {
this.input = input;
}

public Program parse() {
Optional<Program> programOpt = program();
Program program = programOpt.orElseThrow(() -> new SyntaxException("Program", position));
whitespace();
if (position < input.length()) {
throw new SyntaxException("End of input", position);
}
return program;
}

private Optional<Program> program() {
List<Program> statements = new ArrayList<>();
boolean run = true;
int start = position;
while (run) {
Optional<Program> statement = statement();
statement.ifPresent(stmt -> statements.add(stmt));
if (statement.isPresent()) {
start = position;
run = token(";");
} else {
position = start;
run = false;
}
}
Optional<Program> program = Optional.empty();
for (Program statement: statements) {
if (!program.isPresent()) {
program = Optional.of(statement);
} else {
program = program.map(pgm -> new Composition(pgm, statement));
}
}
return program;
}

private Optional<Program> statement() {
int start = position;
Optional<Program> result = assignment();
if (!result.isPresent()) {
position = start;
result = conditional();
if (!result.isPresent()) {
position = start;
result = loop();
}
}
return result;
}

private Optional<Program> loop() {
if (token("while") && token("(")) {
Optional<Expression> condition = expression();
return condition.flatMap(cond -> {
if (token(")") && token("{")) {
Optional<Program> program = program();
return program.filter(pgm -> token("}")).map(pgm -> new Loop(cond, pgm));
}
return Optional.empty();
});
}
return Optional.empty();
}

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

private Optional<Program> assignment() {
Optional<Identifier> identifier = identifier();
return identifier.flatMap(id -> {
if (token(":=")) {
Optional<Expression> expression = expression();
return expression.map(exp -> new Assignment(id, exp));
}
return Optional.empty();
});
}

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

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

private enum Operator {
PLUS, MINUS, NONE;

Expression toOperation(Expression leftHandSide, Expression rightHandSide) {
if (this == Operator.PLUS) {
return new Addition(leftHandSide, rightHandSide);
} else if (this == Operator.MINUS) {
return new Subtraction(leftHandSide, rightHandSide);
} else {
throw new RuntimeException("Operator invalid");
}
}
}

private Optional<Expression> expression() {
List<OperatorWithExpression> atoms = new ArrayList<>();
Operator operator = Operator.PLUS;
int start = position;
while (operator != Operator.NONE) {
Optional<Expression> atom = atom();
Operator op = operator;
atom.ifPresent(at -> atoms.add(new OperatorWithExpression(op, at)));
if (atom.isPresent()) {
start = position;
operator = operator();
} else {
operator = Operator.NONE;
position = start;
}
}
Optional<Expression> expression = Optional.empty();
for (OperatorWithExpression atom: atoms) {
if (!expression.isPresent()) {
expression = Optional.of(atom.expression);
} else {
expression = expression.map(expr -> atom.operator.toOperation(expr, atom.expression));
}
}
return expression;
}

private Operator operator() {
if (token("+")) {
return Operator.PLUS;
} else if (token("-")) {
return Operator.MINUS;
} else {
return Operator.NONE;
}
}

private Optional<Expression> atom() {
int start = position;
Optional<Expression> result;
if (token("(")) {
Optional<Expression> expression = expression();
result = expression.filter(exp -> token(")"));
} else {
position = start;
result = number();
if (!result.isPresent()) {
position = start;
result = identifier().map(id -> id);
}
}
return result;
}

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

private Optional<Expression> number() {
whitespace();
int start = position;
boolean minus = position < input.length() && input.charAt(position) == '-';
if (minus) {
position += 1;
}
boolean digitsFound = false;
while (position < input.length() && Character.isDigit(input.charAt(position))) {
position += 1;
digitsFound = true;
}
if (digitsFound) {
return Optional.of(new Number(Integer.parseInt(input.substring(start, position))));
} else {
return Optional.empty();
}
}

private Optional<Identifier> identifier() {
whitespace();
int start = position;
while (position < input.length() && isLowerLetter(input.charAt(position))) {
position += 1;
}
if (position > start) {
Identifier identifier = new Identifier(input.substring(start, position));
return Optional.of(identifier);
}
return Optional.empty();
}

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

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

+ 20
- 0
src/parser/SyntaxException.java 查看文件

@@ -0,0 +1,20 @@
package parser;

public class SyntaxException extends RuntimeException {
private String expected;
private int position;

public SyntaxException(String expected, int atPosition) {
super(expected + " expected at position " + atPosition);
this.expected = expected;
this.position = atPosition;
}

public String getExpected() {
return expected;
}

public int getPosition() {
return position;
}
}

+ 38
- 0
src/program/Assignment.java 查看文件

@@ -0,0 +1,38 @@
package program;

import expression.Expression;
import expression.Identifier;

public class Assignment extends Program {
public final Identifier identifier;
public final Expression expression;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Assignment that = (Assignment) o;

if (!identifier.equals(that.identifier)) return false;
return expression.equals(that.expression);

}

@Override
public String toString() {
return identifier + " := " + expression;
}

@Override
public int hashCode() {
int result = identifier.hashCode();
result = 31 * result + expression.hashCode();
return result;
}

public Assignment(Identifier identifier, Expression expression) {
this.identifier = identifier;
this.expression = expression;
}
}

+ 35
- 0
src/program/Composition.java 查看文件

@@ -0,0 +1,35 @@
package program;

public class Composition extends Program {
public final Program first;
public final Program second;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Composition that = (Composition) o;

if (!first.equals(that.first)) return false;
return second.equals(that.second);

}

@Override
public String toString() {
return first + " ; " + second;
}

@Override
public int hashCode() {
int result = first.hashCode();
result = 31 * result + second.hashCode();
return result;
}

public Composition(Program first, Program second) {
this.first = first;
this.second = second;
}
}

+ 41
- 0
src/program/Conditional.java 查看文件

@@ -0,0 +1,41 @@
package program;

import expression.Expression;

public class Conditional extends Program {
public final Expression condition;
public final Program thenCase;
public final Program elseCase;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Conditional that = (Conditional) o;

if (!condition.equals(that.condition)) return false;
if (!thenCase.equals(that.thenCase)) return false;
return elseCase.equals(that.elseCase);

}

@Override
public String toString() {
return "if (" + condition + ") then { " + thenCase + " } else { " + elseCase + " }";
}

@Override
public int hashCode() {
int result = condition.hashCode();
result = 31 * result + thenCase.hashCode();
result = 31 * result + elseCase.hashCode();
return result;
}

public Conditional(Expression condition, Program thenCase, Program elseCase) {
this.condition = condition;
this.thenCase = thenCase;
this.elseCase = elseCase;
}
}

+ 37
- 0
src/program/Loop.java 查看文件

@@ -0,0 +1,37 @@
package program;

import expression.Expression;

public class Loop extends Program {
public final Expression condition;
public final Program program;

public Loop(Expression condition, Program program) {
this.condition = condition;
this.program = program;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Loop loop = (Loop) o;

if (!condition.equals(loop.condition)) return false;
return program.equals(loop.program);

}

@Override
public String toString() {
return "while (" + condition + ") { " + program + " }";
}

@Override
public int hashCode() {
int result = condition.hashCode();
result = 31 * result + program.hashCode();
return result;
}
}

+ 4
- 0
src/program/Program.java 查看文件

@@ -0,0 +1,4 @@
package program;

abstract public class Program {
}

+ 25
- 0
test/parser/ParserTest.java 查看文件

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

import expression.Addition;
import expression.Identifier;
import expression.Number;
import expression.Subtraction;
import org.junit.Assert;
import org.junit.Test;
import program.Assignment;
import program.Composition;
import program.Loop;
import program.Program;

public class ParserTest {
@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);
}
}

Loading…
取消
儲存