Implement boolean binary operations AND and OR

This commit is contained in:
dfsek
2020-12-21 21:08:43 -07:00
parent be8ed913e5
commit 13fbb9bf54
8 changed files with 80 additions and 7 deletions

View File

@@ -12,7 +12,9 @@ import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.parser.lang.keywords.IfKeyword;
import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation;
import com.dfsek.terra.api.structures.parser.lang.operations.BooleanAndOperation;
import com.dfsek.terra.api.structures.parser.lang.operations.BooleanNotOperation;
import com.dfsek.terra.api.structures.parser.lang.operations.BooleanOrOperation;
import com.dfsek.terra.api.structures.parser.lang.operations.ConcatenationOperation;
import com.dfsek.terra.api.structures.parser.lang.operations.DivisionOperation;
import com.dfsek.terra.api.structures.parser.lang.operations.MultiplicationOperation;
@@ -156,7 +158,8 @@ public class Parser {
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.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);
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,
Token.Type.BOOLEAN_AND, Token.Type.BOOLEAN_OR);
Returnable<?> right = parseExpression(tokens, false);
@@ -172,6 +175,7 @@ public class Parser {
@SuppressWarnings("unchecked")
private BinaryOperation<?, ?> assemble(Returnable<?> left, Returnable<?> right, Token binaryOperator) throws ParseException {
if(binaryOperator.isStrictNumericOperator()) checkArithmeticOperation(left, right, binaryOperator.getType());
if(binaryOperator.isStrictBooleanOperator()) checkBooleanOperation(left, right, binaryOperator.getType());
switch(binaryOperator.getType()) {
case ADDITION_OPERATOR:
if(left.returnType().equals(Returnable.ReturnType.NUMBER) && right.returnType().equals(Returnable.ReturnType.NUMBER)) {
@@ -196,6 +200,10 @@ public class Parser {
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());
case BOOLEAN_AND:
return new BooleanAndOperation((Returnable<Boolean>) left, (Returnable<Boolean>) right, binaryOperator.getPosition());
case BOOLEAN_OR:
return new BooleanOrOperation((Returnable<Boolean>) left, (Returnable<Boolean>) right, binaryOperator.getPosition());
default:
throw new UnsupportedOperationException("Unsupported binary operator: " + binaryOperator.getType());
}
@@ -278,4 +286,10 @@ public class Parser {
throw new ParseException("Operation " + operation + " not supported between " + left.returnType() + " and " + right.returnType());
}
}
private void checkBooleanOperation(Returnable<?> left, Returnable<?> right, Token.Type operation) throws ParseException {
if(!left.returnType().equals(Returnable.ReturnType.BOOLEAN) || !right.returnType().equals(Returnable.ReturnType.BOOLEAN)) {
throw new ParseException("Operation " + operation + " not supported between " + left.returnType() + " and " + right.returnType());
}
}
}

View File

@@ -10,7 +10,7 @@ public abstract class BinaryOperation<I, O> implements Returnable<O> {
private final Returnable<I> right;
private final Position start;
protected BinaryOperation(Returnable<I> left, Returnable<I> right, Position start) {
public BinaryOperation(Returnable<I> left, Returnable<I> right, Position start) {
this.left = left;
this.right = right;
this.start = start;

View File

@@ -0,0 +1,20 @@
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 BooleanAndOperation extends BinaryOperation<Boolean, Boolean> {
public BooleanAndOperation(Returnable<Boolean> left, Returnable<Boolean> right, Position start) {
super(left, right, start);
}
@Override
public Boolean apply(Boolean left, Boolean right) {
return left && right;
}
@Override
public ReturnType returnType() {
return ReturnType.BOOLEAN;
}
}

View File

@@ -0,0 +1,20 @@
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 BooleanOrOperation extends BinaryOperation<Boolean, Boolean> {
public BooleanOrOperation(Returnable<Boolean> left, Returnable<Boolean> right, Position start) {
super(left, right, start);
}
@Override
public Boolean apply(Boolean left, Boolean right) {
return left || right;
}
@Override
public ReturnType returnType() {
return ReturnType.BOOLEAN;
}
}

View File

@@ -9,7 +9,7 @@ public abstract class UnaryOperation<T> implements Returnable<T> {
private final Returnable<T> input;
private final Position position;
protected UnaryOperation(Returnable<T> input, Position position) {
public UnaryOperation(Returnable<T> input, Position position) {
this.input = input;
this.position = position;
}

View File

@@ -42,7 +42,9 @@ public class Token {
|| 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);
|| type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR)
|| type.equals(Type.BOOLEAN_OR)
|| type.equals(Type.BOOLEAN_AND);
}
public boolean isStrictNumericOperator() {
@@ -55,6 +57,11 @@ public class Token {
|| type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR);
}
public boolean isStrictBooleanOperator() {
return type.equals(Type.BOOLEAN_AND)
|| type.equals(Type.BOOLEAN_OR);
}
public enum Type {
/**
* Function identifier or language keyword
@@ -148,6 +155,14 @@ public class Token {
/**
* Boolean not operator
*/
BOOLEAN_NOT
BOOLEAN_NOT,
/**
* Boolean or
*/
BOOLEAN_OR,
/**
* Boolean and
*/
BOOLEAN_AND
}
}

View File

@@ -50,6 +50,10 @@ public class Tokenizer {
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.LESS_THAN_OR_EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
if(reader.matches("||", true))
return new Token("||", Token.Type.BOOLEAN_OR, new Position(reader.getLine(), reader.getIndex()));
if(reader.matches("&&", true))
return new Token("&&", Token.Type.BOOLEAN_AND, new Position(reader.getLine(), reader.getIndex()));
if(isNumberStart()) {

View File

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