set up framework for binary operations

This commit is contained in:
dfsek
2020-12-20 16:46:44 -07:00
parent 7cbf8dffbe
commit 6d710ca442
17 changed files with 149 additions and 18 deletions

View File

@@ -98,7 +98,7 @@ public class Parser {
private Executable<?> parseExpression(List<Token> tokens) throws ParseException {
if(tokens.get(0).isConstant()) {
return new ConstantExpression(tokens.remove(0).getContent());
return new ConstantExpression<>(tokens.remove(0).getContent());
} else return parseFunction(tokens, false);
}
@@ -128,21 +128,21 @@ public class Parser {
return new Block(parsedItems);
}
private Function<?> parseFunction(List<Token> functionAndArguments, boolean fullStatement) throws ParseException {
Token identifier = functionAndArguments.remove(0);
private Function<?> parseFunction(List<Token> tokens, boolean fullStatement) throws ParseException {
Token identifier = tokens.remove(0);
checkType(identifier, Token.Type.IDENTIFIER); // First token must be identifier
if(!functions.containsKey(identifier.getContent()))
throw new ParseException("No such function " + identifier.getContent() + ": " + identifier.getStart());
checkType(functionAndArguments.remove(0), Token.Type.BODY_BEGIN); // Second is body begin
checkType(tokens.remove(0), Token.Type.BODY_BEGIN); // Second is body begin
List<Token> args = getArgs(functionAndArguments); // Extract arguments, consume the rest.
List<Token> args = getArgs(tokens); // Extract arguments, consume the rest.
functionAndArguments.remove(0); // Remove body end
tokens.remove(0); // Remove body end
if(fullStatement) checkType(functionAndArguments.get(0), Token.Type.STATEMENT_END);
if(fullStatement) checkType(tokens.get(0), Token.Type.STATEMENT_END);
List<String> arg = args.stream().map(Token::getContent).collect(Collectors.toList());

View File

@@ -3,21 +3,29 @@ package com.dfsek.terra.api.structures.parser.lang;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.world.Chunk;
public class ConstantExpression implements Executable<Object> {
private final Object constant;
public class ConstantExpression<T> implements Executable<T> {
private final T constant;
public ConstantExpression(Object constant) {
public ConstantExpression(T constant) {
this.constant = constant;
}
@Override
public Object apply(Location location) {
public T apply(Location location) {
return constant;
}
@Override
public Object apply(Location location, Chunk chunk) {
public T apply(Location location, Chunk chunk) {
return constant;
}
@Override
public ReturnType returnType() {
if(constant instanceof String) return ReturnType.STRING;
if(constant instanceof Number) return ReturnType.NUMBER;
if(constant instanceof Boolean) return ReturnType.BOOLEAN;
return ReturnType.OBJECT;
}
}

View File

@@ -1,4 +1,19 @@
package com.dfsek.terra.api.structures.parser.lang;
public interface Executable<T> extends Item<T> {
ReturnType returnType();
enum ReturnType {
NUMBER(true), STRING(true), BOOLEAN(false), VOID(false), OBJECT(false);
private final boolean comparable;
ReturnType(boolean comparable) {
this.comparable = comparable;
}
public boolean isComparable() {
return comparable;
}
}
}

View File

@@ -0,0 +1,34 @@
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;
public class Expression<T> implements Executable<T> {
private final ReturnType type;
private final Executable<T> left;
private final Executable<T> right;
private final BinaryOperation<T> operation;
public Expression(ReturnType type, Executable<T> left, Executable<T> right, BinaryOperation<T> operation) {
this.type = type;
this.left = left;
this.right = right;
this.operation = operation;
}
@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));
}
}

View File

@@ -26,4 +26,9 @@ public class IfKeyword implements Keyword<Void> {
if(statement.apply(location, chunk)) conditional.apply(location, chunk);
return null;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;
}
}

View File

@@ -14,4 +14,9 @@ public class ReturnKeyword implements Keyword<Void> {
public Void apply(Location location, Chunk chunk) {
return null;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;
}
}

View File

@@ -0,0 +1,5 @@
package com.dfsek.terra.api.structures.parser.lang.operations;
public interface BinaryOperation<T> {
T apply(T left, T right);
}

View File

@@ -0,0 +1,8 @@
package com.dfsek.terra.api.structures.parser.lang.operations;
public class ConcatenationOperation implements BinaryOperation<Object> {
@Override
public String apply(Object left, Object right) {
return left.toString() + right.toString();
}
}

View File

@@ -0,0 +1,8 @@
package com.dfsek.terra.api.structures.parser.lang.operations;
public class NumberAdditionOperation implements BinaryOperation<Number> {
@Override
public Number apply(Number left, Number right) {
return left.doubleValue() + right.doubleValue();
}
}

View File

@@ -16,8 +16,6 @@ public class EqualsStatement implements Statement {
@Override
public Boolean apply(Location location) {
System.out.println(left.apply(location));
System.out.println(right.apply(location));
return left.apply(location).equals(right.apply(location));
}

View File

@@ -0,0 +1,26 @@
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;
public class GreaterThanStatement<T extends Comparable<T>> implements Statement {
private final Item<T> left;
private final Item<T> right;
public GreaterThanStatement(Item<T> left, Item<T> right) {
this.left = left;
this.right = right;
}
@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;
}
}

View File

@@ -16,13 +16,11 @@ public class NotEqualsStatement implements Statement {
@Override
public Boolean apply(Location location) {
System.out.println(left.apply(location));
System.out.println(right.apply(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));
return !left.apply(location, chunk).equals(right.apply(location, chunk));
}
}

View File

@@ -32,4 +32,9 @@ public class BlockFunction implements Function<Void> {
//TODO: do
return null;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;
}
}

View File

@@ -40,4 +40,9 @@ public class CheckFunction implements Function<String> {
return "OCEAN";
return "AIR";
}
@Override
public ReturnType returnType() {
return ReturnType.STRING;
}
}

View File

@@ -85,6 +85,10 @@ public class Token {
/**
* Boolean operator
*/
BOOLEAN_OPERATOR
BOOLEAN_OPERATOR,
/**
* Addition/concatenation operator
*/
ADDITION_OPERATOR
}
}

View File

@@ -82,6 +82,8 @@ public class Tokenizer {
return new Token(reader.consume().toString(), Token.Type.BLOCK_END, new Position(reader.getLine(), reader.getIndex()));
if(reader.current().is('='))
return new Token(reader.consume().toString(), Token.Type.ASSIGNMENT, new Position(reader.getLine(), reader.getIndex()));
if(reader.current().is('+'))
return new Token(reader.consume().toString(), Token.Type.ADDITION_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
StringBuilder token = new StringBuilder();
while(!reader.current().isEOF() && !isSyntaxSignificant(reader.current().getCharacter())) {

View File

@@ -74,5 +74,10 @@ public class ParserTest {
public String toString() {
return "string: " + a + ", double: " + b;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;
}
}
}