mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-08-29 13:20:32 +00:00
implement precedence matrix and NegationOperation
This commit is contained in:
@@ -26,6 +26,7 @@ import com.dfsek.terra.api.structures.parser.lang.operations.ConcatenationOperat
|
|||||||
import com.dfsek.terra.api.structures.parser.lang.operations.DivisionOperation;
|
import com.dfsek.terra.api.structures.parser.lang.operations.DivisionOperation;
|
||||||
import com.dfsek.terra.api.structures.parser.lang.operations.ModuloOperation;
|
import com.dfsek.terra.api.structures.parser.lang.operations.ModuloOperation;
|
||||||
import com.dfsek.terra.api.structures.parser.lang.operations.MultiplicationOperation;
|
import com.dfsek.terra.api.structures.parser.lang.operations.MultiplicationOperation;
|
||||||
|
import com.dfsek.terra.api.structures.parser.lang.operations.NegationOperation;
|
||||||
import com.dfsek.terra.api.structures.parser.lang.operations.NumberAdditionOperation;
|
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.SubtractionOperation;
|
||||||
import com.dfsek.terra.api.structures.parser.lang.operations.statements.EqualsStatement;
|
import com.dfsek.terra.api.structures.parser.lang.operations.statements.EqualsStatement;
|
||||||
@@ -217,9 +218,13 @@ public class Parser {
|
|||||||
|
|
||||||
private Returnable<?> parseExpression(TokenHolder tokens, boolean full, Map<String, Variable<?>> variableMap) throws ParseException {
|
private Returnable<?> parseExpression(TokenHolder tokens, boolean full, Map<String, Variable<?>> variableMap) throws ParseException {
|
||||||
boolean booleanInverted = false; // Check for boolean not operator
|
boolean booleanInverted = false; // Check for boolean not operator
|
||||||
|
boolean negate = false;
|
||||||
if(tokens.get().getType().equals(Token.Type.BOOLEAN_NOT)) {
|
if(tokens.get().getType().equals(Token.Type.BOOLEAN_NOT)) {
|
||||||
booleanInverted = true;
|
booleanInverted = true;
|
||||||
tokens.consume();
|
tokens.consume();
|
||||||
|
} else if(tokens.get().getType().equals(Token.Type.SUBTRACTION_OPERATOR)) {
|
||||||
|
negate = true;
|
||||||
|
tokens.consume();
|
||||||
}
|
}
|
||||||
|
|
||||||
Token id = tokens.get();
|
Token id = tokens.get();
|
||||||
@@ -243,6 +248,9 @@ public class Parser {
|
|||||||
if(booleanInverted) { // Invert operation if boolean not detected
|
if(booleanInverted) { // Invert operation if boolean not detected
|
||||||
ParserUtil.checkReturnType(expression, Returnable.ReturnType.BOOLEAN);
|
ParserUtil.checkReturnType(expression, Returnable.ReturnType.BOOLEAN);
|
||||||
expression = new BooleanNotOperation((Returnable<Boolean>) expression, expression.getPosition());
|
expression = new BooleanNotOperation((Returnable<Boolean>) expression, expression.getPosition());
|
||||||
|
} else if(negate) {
|
||||||
|
ParserUtil.checkReturnType(expression, Returnable.ReturnType.NUMBER);
|
||||||
|
expression = new NegationOperation((Returnable<Number>) expression, expression.getPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(full && tokens.get().isBinaryOperator()) { // Parse binary operations
|
if(full && tokens.get().isBinaryOperator()) { // Parse binary operations
|
||||||
|
|||||||
@@ -11,21 +11,31 @@ import java.util.Map;
|
|||||||
|
|
||||||
public class ParserUtil {
|
public class ParserUtil {
|
||||||
|
|
||||||
private static final Map<Token.Type, List<Token.Type>> PRECEDENCE = new HashMap<>();
|
private static final Map<Token.Type, Map<Token.Type, Boolean>> PRECEDENCE = new HashMap<>(); // If second has precedence, true.
|
||||||
private static final List<Token.Type> ARITHMETIC = Arrays.asList(Token.Type.ADDITION_OPERATOR, Token.Type.SUBTRACTION_OPERATOR, Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR, Token.Type.MODULO_OPERATOR);
|
private static final List<Token.Type> ARITHMETIC = Arrays.asList(Token.Type.ADDITION_OPERATOR, Token.Type.SUBTRACTION_OPERATOR, Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR, Token.Type.MODULO_OPERATOR);
|
||||||
private static final List<Token.Type> COMPARISON = Arrays.asList(Token.Type.EQUALS_OPERATOR, Token.Type.NOT_EQUALS_OPERATOR, Token.Type.LESS_THAN_OPERATOR, Token.Type.LESS_THAN_OR_EQUALS_OPERATOR, Token.Type.GREATER_THAN_OPERATOR, Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR);
|
private static final List<Token.Type> COMPARISON = Arrays.asList(Token.Type.EQUALS_OPERATOR, Token.Type.NOT_EQUALS_OPERATOR, Token.Type.LESS_THAN_OPERATOR, Token.Type.LESS_THAN_OR_EQUALS_OPERATOR, Token.Type.GREATER_THAN_OPERATOR, Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR);
|
||||||
|
|
||||||
static { // Setup precedence
|
static { // Setup precedence
|
||||||
PRECEDENCE.put(Token.Type.ADDITION_OPERATOR, Arrays.asList(Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR));
|
Map<Token.Type, Boolean> add = new HashMap<>(); // Addition/subtraction before Multiplication/division.
|
||||||
PRECEDENCE.put(Token.Type.SUBTRACTION_OPERATOR, Arrays.asList(Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR));
|
add.put(Token.Type.MULTIPLICATION_OPERATOR, true);
|
||||||
PRECEDENCE.put(Token.Type.EQUALS_OPERATOR, ARITHMETIC);
|
add.put(Token.Type.DIVISION_OPERATOR, true);
|
||||||
PRECEDENCE.put(Token.Type.NOT_EQUALS_OPERATOR, ARITHMETIC);
|
|
||||||
PRECEDENCE.put(Token.Type.GREATER_THAN_OPERATOR, ARITHMETIC);
|
PRECEDENCE.put(Token.Type.ADDITION_OPERATOR, add);
|
||||||
PRECEDENCE.put(Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR, ARITHMETIC);
|
PRECEDENCE.put(Token.Type.SUBTRACTION_OPERATOR, add);
|
||||||
PRECEDENCE.put(Token.Type.LESS_THAN_OPERATOR, ARITHMETIC);
|
|
||||||
PRECEDENCE.put(Token.Type.LESS_THAN_OR_EQUALS_OPERATOR, ARITHMETIC);
|
Map<Token.Type, Boolean> numericBoolean = new HashMap<>();
|
||||||
PRECEDENCE.put(Token.Type.BOOLEAN_AND, COMPARISON);
|
|
||||||
PRECEDENCE.put(Token.Type.BOOLEAN_OR, COMPARISON);
|
ARITHMETIC.forEach(op -> numericBoolean.put(op, true)); // Numbers before comparison
|
||||||
|
COMPARISON.forEach(op -> PRECEDENCE.put(op, numericBoolean));
|
||||||
|
|
||||||
|
|
||||||
|
Map<Token.Type, Boolean> booleanOps = new HashMap<>();
|
||||||
|
ARITHMETIC.forEach(op -> booleanOps.put(op, true)); // Everything before boolean
|
||||||
|
COMPARISON.forEach(op -> booleanOps.put(op, true));
|
||||||
|
|
||||||
|
|
||||||
|
PRECEDENCE.put(Token.Type.BOOLEAN_AND, booleanOps);
|
||||||
|
PRECEDENCE.put(Token.Type.BOOLEAN_OR, booleanOps);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void checkType(Token token, Token.Type... expected) throws ParseException {
|
public static void checkType(Token token, Token.Type... expected) throws ParseException {
|
||||||
@@ -83,6 +93,8 @@ public class ParserUtil {
|
|||||||
|
|
||||||
public static boolean hasPrecedence(Token.Type first, Token.Type second) {
|
public static boolean hasPrecedence(Token.Type first, Token.Type second) {
|
||||||
if(!PRECEDENCE.containsKey(first)) return false;
|
if(!PRECEDENCE.containsKey(first)) return false;
|
||||||
return PRECEDENCE.get(first).contains(second);
|
Map<Token.Type, Boolean> pre = PRECEDENCE.get(first);
|
||||||
|
if(!pre.containsKey(second)) return false;
|
||||||
|
return pre.get(second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+20
@@ -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 NegationOperation extends UnaryOperation<Number> {
|
||||||
|
public NegationOperation(Returnable<Number> input, Position position) {
|
||||||
|
super(input, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Number apply(Number input) {
|
||||||
|
return -input.doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReturnType returnType() {
|
||||||
|
return ReturnType.NUMBER;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -148,13 +148,11 @@ public class Tokenizer {
|
|||||||
|
|
||||||
private boolean isNumberLike() {
|
private boolean isNumberLike() {
|
||||||
return reader.current().isDigit()
|
return reader.current().isDigit()
|
||||||
|| reader.current().is('_', '.', '-', 'E');
|
|| reader.current().is('_', '.', 'E');
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isNumberStart() {
|
private boolean isNumberStart() {
|
||||||
return reader.current().isDigit()
|
return reader.current().isDigit()
|
||||||
|| reader.current().is('-') && reader.next(1).isDigit()
|
|
||||||
|| reader.current().is('-') && reader.next(1).is('.') && reader.next(2).isDigit()
|
|
||||||
|| reader.current().is('.') && reader.next(1).isDigit();
|
|| reader.current().is('.') && reader.next(1).isDigit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
id "testScript";
|
id "testScript";
|
||||||
|
|
||||||
|
bool thing1 = 2 > (2+2) || false;
|
||||||
|
|
||||||
|
if(2 > 2 || 3 + 4 <= 2 && 4 + 5 > 2 / 3) {
|
||||||
|
test("ok", 2);
|
||||||
|
}
|
||||||
|
|
||||||
test("minecraft:green_w" + "ool", (2 * (3+1) * (2 * (1+1))));
|
test("minecraft:green_w" + "ool", (2 * (3+1) * (2 * (1+1))));
|
||||||
//
|
//
|
||||||
|
|
||||||
@@ -7,7 +13,7 @@ num testVar = 3.4;
|
|||||||
bool boolean = true;
|
bool boolean = true;
|
||||||
str stringVar = "hello!";
|
str stringVar = "hello!";
|
||||||
|
|
||||||
num precedence = (3 + 2) * 2 + 3;
|
num precedence = 3 + 2 * 2 + 3;
|
||||||
test("precedence: " + precedence, 2);
|
test("precedence: " + precedence, 2);
|
||||||
num precedence2 = 3 * 2 + 2 * 3;
|
num precedence2 = 3 * 2 + 2 * 3;
|
||||||
test("precedence 2: " + precedence2, 2);
|
test("precedence 2: " + precedence2, 2);
|
||||||
@@ -17,6 +23,13 @@ bool iftest = false;
|
|||||||
bool truetest = false;
|
bool truetest = false;
|
||||||
|
|
||||||
num iterator = 0;
|
num iterator = 0;
|
||||||
|
num thing = 4 - 2-2+2-2+2;
|
||||||
|
test("4 - 2 = " + thing, 2);
|
||||||
|
|
||||||
|
thing = -2;
|
||||||
|
test("-2 = " + thing, 2);
|
||||||
|
thing = -thing;
|
||||||
|
test("--2 = " + thing, 2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user