From 6d710ca4424d5cc7c80bdb2ac841e62d4c67c4dd Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 20 Dec 2020 16:46:44 -0700 Subject: [PATCH] set up framework for binary operations --- .../terra/api/structures/parser/Parser.java | 14 ++++---- .../parser/lang/ConstantExpression.java | 18 +++++++--- .../structures/parser/lang/Executable.java | 15 ++++++++ .../structures/parser/lang/Expression.java | 34 +++++++++++++++++++ .../parser/lang/keywords/IfKeyword.java | 5 +++ .../parser/lang/keywords/ReturnKeyword.java | 5 +++ .../lang/operations/BinaryOperation.java | 5 +++ .../operations/ConcatenationOperation.java | 8 +++++ .../operations/NumberAdditionOperation.java | 8 +++++ .../lang/statements/EqualsStatement.java | 2 -- .../lang/statements/GreaterThanStatement.java | 26 ++++++++++++++ .../lang/statements/NotEqualsStatement.java | 4 +-- .../script/functions/BlockFunction.java | 5 +++ .../script/functions/CheckFunction.java | 5 +++ .../terra/api/structures/tokenizer/Token.java | 6 +++- .../api/structures/tokenizer/Tokenizer.java | 2 ++ .../src/test/java/structure/ParserTest.java | 5 +++ 17 files changed, 149 insertions(+), 18 deletions(-) create mode 100644 common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Expression.java create mode 100644 common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BinaryOperation.java create mode 100644 common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ConcatenationOperation.java create mode 100644 common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NumberAdditionOperation.java create mode 100644 common/src/main/java/com/dfsek/terra/api/structures/parser/lang/statements/GreaterThanStatement.java diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java index 5751b1533..63c1706ec 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java @@ -98,7 +98,7 @@ public class Parser { private Executable parseExpression(List 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 functionAndArguments, boolean fullStatement) throws ParseException { - Token identifier = functionAndArguments.remove(0); + private Function parseFunction(List 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 args = getArgs(functionAndArguments); // Extract arguments, consume the rest. + List 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 arg = args.stream().map(Token::getContent).collect(Collectors.toList()); diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/ConstantExpression.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/ConstantExpression.java index 59e25c759..ce0e8304e 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/ConstantExpression.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/ConstantExpression.java @@ -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 { - private final Object constant; +public class ConstantExpression implements Executable { + 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; + } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Executable.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Executable.java index df9ca9665..bb6be7ca6 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Executable.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Executable.java @@ -1,4 +1,19 @@ package com.dfsek.terra.api.structures.parser.lang; public interface Executable extends Item { + 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; + } + } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Expression.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Expression.java new file mode 100644 index 000000000..29b26d203 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Expression.java @@ -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 implements Executable { + private final ReturnType type; + private final Executable left; + private final Executable right; + private final BinaryOperation operation; + + public Expression(ReturnType type, Executable left, Executable right, BinaryOperation 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)); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/IfKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/IfKeyword.java index 22a060f65..e990b6fbe 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/IfKeyword.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/IfKeyword.java @@ -26,4 +26,9 @@ public class IfKeyword implements Keyword { if(statement.apply(location, chunk)) conditional.apply(location, chunk); return null; } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/ReturnKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/ReturnKeyword.java index 402ebeccc..8645888bc 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/ReturnKeyword.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/ReturnKeyword.java @@ -14,4 +14,9 @@ public class ReturnKeyword implements Keyword { public Void apply(Location location, Chunk chunk) { return null; } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BinaryOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BinaryOperation.java new file mode 100644 index 000000000..c4530127a --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BinaryOperation.java @@ -0,0 +1,5 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +public interface BinaryOperation { + T apply(T left, T right); +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ConcatenationOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ConcatenationOperation.java new file mode 100644 index 000000000..cbd1adcd4 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ConcatenationOperation.java @@ -0,0 +1,8 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +public class ConcatenationOperation implements BinaryOperation { + @Override + public String apply(Object left, Object right) { + return left.toString() + right.toString(); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NumberAdditionOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NumberAdditionOperation.java new file mode 100644 index 000000000..4dd70f593 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NumberAdditionOperation.java @@ -0,0 +1,8 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +public class NumberAdditionOperation implements BinaryOperation { + @Override + public Number apply(Number left, Number right) { + return left.doubleValue() + right.doubleValue(); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/statements/EqualsStatement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/statements/EqualsStatement.java index a329a360f..b55178685 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/statements/EqualsStatement.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/statements/EqualsStatement.java @@ -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)); } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/statements/GreaterThanStatement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/statements/GreaterThanStatement.java new file mode 100644 index 000000000..b804756d0 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/statements/GreaterThanStatement.java @@ -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> implements Statement { + private final Item left; + private final Item right; + + public GreaterThanStatement(Item left, Item 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; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/statements/NotEqualsStatement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/statements/NotEqualsStatement.java index bcb5e8090..5d4a2b736 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/statements/NotEqualsStatement.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/statements/NotEqualsStatement.java @@ -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)); } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java index 08c0411b2..50e414dbf 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java @@ -32,4 +32,9 @@ public class BlockFunction implements Function { //TODO: do return null; } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckFunction.java index c6e92f269..6c5379fc5 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckFunction.java @@ -40,4 +40,9 @@ public class CheckFunction implements Function { return "OCEAN"; return "AIR"; } + + @Override + public ReturnType returnType() { + return ReturnType.STRING; + } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Token.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Token.java index 4dfb55eb7..66fa93960 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Token.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Token.java @@ -85,6 +85,10 @@ public class Token { /** * Boolean operator */ - BOOLEAN_OPERATOR + BOOLEAN_OPERATOR, + /** + * Addition/concatenation operator + */ + ADDITION_OPERATOR } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java index 39fb54914..729e6969c 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java @@ -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())) { diff --git a/common/src/test/java/structure/ParserTest.java b/common/src/test/java/structure/ParserTest.java index 29659085f..a71009926 100644 --- a/common/src/test/java/structure/ParserTest.java +++ b/common/src/test/java/structure/ParserTest.java @@ -74,5 +74,10 @@ public class ParserTest { public String toString() { return "string: " + a + ", double: " + b; } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } } }