implement comparison operators

This commit is contained in:
dfsek
2020-12-21 20:31:57 -07:00
parent 7a75f20a2c
commit 7d72a91bb7
20 changed files with 195 additions and 175 deletions

View File

@@ -18,6 +18,12 @@ import com.dfsek.terra.api.structures.parser.lang.operations.DivisionOperation;
import com.dfsek.terra.api.structures.parser.lang.operations.MultiplicationOperation;
import com.dfsek.terra.api.structures.parser.lang.operations.NumberAdditionOperation;
import com.dfsek.terra.api.structures.parser.lang.operations.SubtractionOperation;
import com.dfsek.terra.api.structures.parser.lang.operations.statements.EqualsStatement;
import com.dfsek.terra.api.structures.parser.lang.operations.statements.GreaterOrEqualsThanStatement;
import com.dfsek.terra.api.structures.parser.lang.operations.statements.GreaterThanStatement;
import com.dfsek.terra.api.structures.parser.lang.operations.statements.LessThanOrEqualsStatement;
import com.dfsek.terra.api.structures.parser.lang.operations.statements.LessThanStatement;
import com.dfsek.terra.api.structures.parser.lang.operations.statements.NotEqualsStatement;
import com.dfsek.terra.api.structures.tokenizer.Position;
import com.dfsek.terra.api.structures.tokenizer.Token;
import com.dfsek.terra.api.structures.tokenizer.Tokenizer;
@@ -138,12 +144,12 @@ public class Parser {
}
private BinaryOperation<?> parseBinaryOperation(Returnable<?> left, List<Token> tokens) throws ParseException {
private BinaryOperation<?, ?> parseBinaryOperation(Returnable<?> left, List<Token> tokens) throws ParseException {
Token binaryOperator = tokens.remove(0);
checkType(binaryOperator, Token.Type.ADDITION_OPERATOR, Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR, Token.Type.SUBTRACTION_OPERATOR, Token.Type.BOOLEAN_OPERATOR);
checkType(binaryOperator, Token.Type.ADDITION_OPERATOR, Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR, Token.Type.SUBTRACTION_OPERATOR,
Token.Type.GREATER_THAN_OPERATOR, Token.Type.LESS_THAN_OPERATOR, Token.Type.LESS_THAN_OR_EQUALS_OPERATOR, Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR, Token.Type.EQUALS_OPERATOR, Token.Type.NOT_EQUALS_OPERATOR);
Returnable<?> right = parseExpression(tokens, false);
if(binaryOperator.isStrictArithmeticOperator()) checkArithmeticOperation(left, right, binaryOperator.getType());
Token other = tokens.get(0);
System.out.println("other: " + other);
@@ -158,7 +164,8 @@ public class Parser {
}
@SuppressWarnings("unchecked")
private BinaryOperation<?> assemble(Returnable<?> left, Returnable<?> right, Token binaryOperator) {
private BinaryOperation<?, ?> assemble(Returnable<?> left, Returnable<?> right, Token binaryOperator) throws ParseException {
if(binaryOperator.isStrictNumericOperator()) checkArithmeticOperation(left, right, binaryOperator.getType());
switch(binaryOperator.getType()) {
case ADDITION_OPERATOR:
if(left.returnType().equals(Returnable.ReturnType.NUMBER) && right.returnType().equals(Returnable.ReturnType.NUMBER)) {
@@ -171,7 +178,18 @@ public class Parser {
return new MultiplicationOperation((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
case DIVISION_OPERATOR:
return new DivisionOperation((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
case BOOLEAN_OPERATOR:
case EQUALS_OPERATOR:
return new EqualsStatement((Returnable<Object>) left, (Returnable<Object>) right, binaryOperator.getPosition());
case NOT_EQUALS_OPERATOR:
return new NotEqualsStatement((Returnable<Object>) left, (Returnable<Object>) right, binaryOperator.getPosition());
case GREATER_THAN_OPERATOR:
return new GreaterThanStatement((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
case LESS_THAN_OPERATOR:
return new LessThanStatement((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
case GREATER_THAN_OR_EQUALS_OPERATOR:
return new GreaterOrEqualsThanStatement((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
case LESS_THAN_OR_EQUALS_OPERATOR:
return new LessThanOrEqualsStatement((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
default:
@@ -252,7 +270,7 @@ public class Parser {
}
private void checkArithmeticOperation(Returnable<?> left, Returnable<?> right, Token.Type operation) throws ParseException {
if(!left.returnType().equals(Returnable.ReturnType.NUMBER) && !right.returnType().equals(Returnable.ReturnType.NUMBER)) {
if(!left.returnType().equals(Returnable.ReturnType.NUMBER) || !right.returnType().equals(Returnable.ReturnType.NUMBER)) {
throw new ParseException("Operation " + operation + " not supported between " + left.returnType() + " and " + right.returnType());
}
}

View File

@@ -1,42 +0,0 @@
package com.dfsek.terra.api.structures.parser.lang;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class Expression<T> implements Returnable<T> {
private final ReturnType type;
private final Returnable<T> left;
private final Returnable<T> right;
private final BinaryOperation<T> operation;
private final Position position;
public Expression(ReturnType type, Returnable<T> left, Returnable<T> right, BinaryOperation<T> operation, Position position) {
this.type = type;
this.left = left;
this.right = right;
this.operation = operation;
this.position = position;
}
@Override
public ReturnType returnType() {
return type;
}
@Override
public T apply(Location location) {
return operation.apply(left.apply(location), right.apply(location));
}
@Override
public T apply(Location location, Chunk chunk) {
return operation.apply(left.apply(location, chunk), right.apply(location, chunk));
}
@Override
public Position getPosition() {
return position;
}
}

View File

@@ -5,18 +5,18 @@ import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.tokenizer.Position;
public abstract class BinaryOperation<T> implements Returnable<T> {
private final Returnable<T> left;
private final Returnable<T> right;
public abstract class BinaryOperation<I, O> implements Returnable<O> {
private final Returnable<I> left;
private final Returnable<I> right;
private final Position start;
protected BinaryOperation(Returnable<T> left, Returnable<T> right, Position start) {
protected BinaryOperation(Returnable<I> left, Returnable<I> right, Position start) {
this.left = left;
this.right = right;
this.start = start;
}
public abstract T apply(T left, T right);
public abstract O apply(I left, I right);
@Override
public Position getPosition() {
@@ -24,12 +24,12 @@ public abstract class BinaryOperation<T> implements Returnable<T> {
}
@Override
public T apply(Location location) {
public O apply(Location location) {
return apply(left.apply(location), right.apply(location));
}
@Override
public T apply(Location location, Chunk chunk) {
public O apply(Location location, Chunk chunk) {
return apply(left.apply(location, chunk), right.apply(location, chunk));
}
}

View File

@@ -3,7 +3,7 @@ package com.dfsek.terra.api.structures.parser.lang.operations;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class ConcatenationOperation extends BinaryOperation<Object> {
public class ConcatenationOperation extends BinaryOperation<Object, Object> {
public ConcatenationOperation(Returnable<Object> left, Returnable<Object> right, Position position) {
super(left, right, position);
}

View File

@@ -3,7 +3,7 @@ package com.dfsek.terra.api.structures.parser.lang.operations;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class DivisionOperation extends BinaryOperation<Number> {
public class DivisionOperation extends BinaryOperation<Number, Number> {
public DivisionOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
super(left, right, position);
}

View File

@@ -3,7 +3,7 @@ package com.dfsek.terra.api.structures.parser.lang.operations;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class MultiplicationOperation extends BinaryOperation<Number> {
public class MultiplicationOperation extends BinaryOperation<Number, Number> {
public MultiplicationOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
super(left, right, position);
}

View File

@@ -3,7 +3,7 @@ package com.dfsek.terra.api.structures.parser.lang.operations;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class NumberAdditionOperation extends BinaryOperation<Number> {
public class NumberAdditionOperation extends BinaryOperation<Number, Number> {
public NumberAdditionOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
super(left, right, position);
}

View File

@@ -3,7 +3,7 @@ package com.dfsek.terra.api.structures.parser.lang.operations;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class SubtractionOperation extends BinaryOperation<Number> {
public class SubtractionOperation extends BinaryOperation<Number, Number> {
public SubtractionOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
super(left, right, position);
}

View File

@@ -0,0 +1,22 @@
package com.dfsek.terra.api.structures.parser.lang.operations.statements;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class EqualsStatement extends BinaryOperation<Object, Boolean> {
public EqualsStatement(Returnable<Object> left, Returnable<Object> right, Position position) {
super(left, right, position);
}
@Override
public Boolean apply(Object left, Object right) {
return left.equals(right);
}
@Override
public ReturnType returnType() {
return ReturnType.BOOLEAN;
}
}

View File

@@ -0,0 +1,22 @@
package com.dfsek.terra.api.structures.parser.lang.operations.statements;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class GreaterOrEqualsThanStatement extends BinaryOperation<Number, Boolean> {
public GreaterOrEqualsThanStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
super(left, right, position);
}
@Override
public Boolean apply(Number left, Number right) {
return left.doubleValue() >= right.doubleValue();
}
@Override
public ReturnType returnType() {
return ReturnType.BOOLEAN;
}
}

View File

@@ -0,0 +1,22 @@
package com.dfsek.terra.api.structures.parser.lang.operations.statements;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class GreaterThanStatement extends BinaryOperation<Number, Boolean> {
public GreaterThanStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
super(left, right, position);
}
@Override
public Boolean apply(Number left, Number right) {
return left.doubleValue() > right.doubleValue();
}
@Override
public ReturnType returnType() {
return ReturnType.BOOLEAN;
}
}

View File

@@ -0,0 +1,22 @@
package com.dfsek.terra.api.structures.parser.lang.operations.statements;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class LessThanOrEqualsStatement extends BinaryOperation<Number, Boolean> {
public LessThanOrEqualsStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
super(left, right, position);
}
@Override
public Boolean apply(Number left, Number right) {
return left.doubleValue() <= right.doubleValue();
}
@Override
public ReturnType returnType() {
return ReturnType.BOOLEAN;
}
}

View File

@@ -0,0 +1,22 @@
package com.dfsek.terra.api.structures.parser.lang.operations.statements;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class LessThanStatement extends BinaryOperation<Number, Boolean> {
public LessThanStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
super(left, right, position);
}
@Override
public Boolean apply(Number left, Number right) {
return left.doubleValue() < right.doubleValue();
}
@Override
public ReturnType returnType() {
return ReturnType.BOOLEAN;
}
}

View File

@@ -0,0 +1,22 @@
package com.dfsek.terra.api.structures.parser.lang.operations.statements;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class NotEqualsStatement extends BinaryOperation<Object, Boolean> {
public NotEqualsStatement(Returnable<Object> left, Returnable<Object> right, Position position) {
super(left, right, position);
}
@Override
public Boolean apply(Object left, Object right) {
return !left.equals(right);
}
@Override
public ReturnType returnType() {
return ReturnType.BOOLEAN;
}
}

View File

@@ -1,34 +0,0 @@
package com.dfsek.terra.api.structures.parser.lang.statements;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.structures.parser.lang.Item;
import com.dfsek.terra.api.structures.parser.lang.Statement;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class EqualsStatement implements Statement {
private final Item<?> left;
private final Item<?> right;
private final Position position;
public EqualsStatement(Item<?> left, Item<?> right, Position position) {
this.left = left;
this.right = right;
this.position = position;
}
@Override
public Boolean apply(Location location) {
return left.apply(location).equals(right.apply(location));
}
@Override
public Boolean apply(Location location, Chunk chunk) {
return left.apply(location, chunk).equals(right.apply(location, chunk));
}
@Override
public Position getPosition() {
return position;
}
}

View File

@@ -1,34 +0,0 @@
package com.dfsek.terra.api.structures.parser.lang.statements;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.structures.parser.lang.Item;
import com.dfsek.terra.api.structures.parser.lang.Statement;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class GreaterThanStatement<T extends Comparable<T>> implements Statement {
private final Item<T> left;
private final Item<T> right;
private final Position position;
public GreaterThanStatement(Item<T> left, Item<T> right, Position position) {
this.left = left;
this.right = right;
this.position = position;
}
@Override
public Boolean apply(Location location) {
return left.apply(location).compareTo(right.apply(location)) > 0;
}
@Override
public Boolean apply(Location location, Chunk chunk) {
return left.apply(location).compareTo(right.apply(location)) > 0;
}
@Override
public Position getPosition() {
return position;
}
}

View File

@@ -1,34 +0,0 @@
package com.dfsek.terra.api.structures.parser.lang.statements;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.structures.parser.lang.Item;
import com.dfsek.terra.api.structures.parser.lang.Statement;
import com.dfsek.terra.api.structures.tokenizer.Position;
public class NotEqualsStatement implements Statement {
private final Item<?> left;
private final Item<?> right;
private final Position position;
public NotEqualsStatement(Item<?> left, Item<?> right, Position position) {
this.left = left;
this.right = right;
this.position = position;
}
@Override
public Boolean apply(Location location) {
return !left.apply(location).equals(right.apply(location));
}
@Override
public Boolean apply(Location location, Chunk chunk) {
return !left.apply(location, chunk).equals(right.apply(location, chunk));
}
@Override
public Position getPosition() {
return position;
}
}

View File

@@ -37,13 +37,22 @@ public class Token {
|| type.equals(Type.SUBTRACTION_OPERATOR)
|| type.equals(Type.MULTIPLICATION_OPERATOR)
|| type.equals(Type.DIVISION_OPERATOR)
|| type.equals(Type.BOOLEAN_OPERATOR);
|| type.equals(Type.EQUALS_OPERATOR)
|| type.equals(Type.NOT_EQUALS_OPERATOR)
|| type.equals(Type.LESS_THAN_OPERATOR)
|| type.equals(Type.GREATER_THAN_OPERATOR)
|| type.equals(Type.LESS_THAN_OR_EQUALS_OPERATOR)
|| type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR);
}
public boolean isStrictArithmeticOperator() {
public boolean isStrictNumericOperator() {
return type.equals(Type.SUBTRACTION_OPERATOR)
|| type.equals(Type.MULTIPLICATION_OPERATOR)
|| type.equals(Type.DIVISION_OPERATOR);
|| type.equals(Type.DIVISION_OPERATOR)
|| type.equals(Type.GREATER_THAN_OPERATOR)
|| type.equals(Type.LESS_THAN_OPERATOR)
|| type.equals(Type.LESS_THAN_OR_EQUALS_OPERATOR)
|| type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR);
}
public enum Type {
@@ -97,9 +106,14 @@ public class Token {
*/
ASSIGNMENT,
/**
* Boolean operator
* Boolean equals operator
*/
BOOLEAN_OPERATOR,
EQUALS_OPERATOR,
NOT_EQUALS_OPERATOR,
GREATER_THAN_OPERATOR,
LESS_THAN_OPERATOR,
GREATER_THAN_OR_EQUALS_OPERATOR,
LESS_THAN_OR_EQUALS_OPERATOR,
/**
* Addition/concatenation operator
*/

View File

@@ -39,17 +39,17 @@ public class Tokenizer {
if(reader.matches("==", true))
return new Token("==", Token.Type.BOOLEAN_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
return new Token("==", Token.Type.EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
if(reader.matches("!=", true))
return new Token("!=", Token.Type.BOOLEAN_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
return new Token("!=", Token.Type.NOT_EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
if(reader.matches(">", true))
return new Token(">", Token.Type.BOOLEAN_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
return new Token(">", Token.Type.GREATER_THAN_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
if(reader.matches("<", true))
return new Token("<", Token.Type.BOOLEAN_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
return new Token("<", Token.Type.LESS_THAN_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
if(reader.matches(">=", true))
return new Token(">=", Token.Type.BOOLEAN_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
return new Token(">=", Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
if(reader.matches("<=", true))
return new Token("<=", Token.Type.BOOLEAN_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
return new Token("<=", Token.Type.LESS_THAN_OR_EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
if(isNumberStart()) {

View File

@@ -1,5 +1,5 @@
test("hello" + 3 + "gdfg", 3 + 8*2 - 1);
test("hello" + 3 + "gdfg", 2);
if(true) {
if(true == test("hello" + 3 + "gdfg", 3 + 8*2 - 1)) {
test("fdsgdf" + 2, 3.4);
}