mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-06-13 20:33:01 +00:00
implement operator precedence
This commit is contained in:
@@ -14,7 +14,10 @@ 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.BooleanNotOperation;
|
||||
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;
|
||||
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.tokenizer.Position;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Token;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Tokenizer;
|
||||
@@ -78,7 +81,7 @@ public class Parser {
|
||||
|
||||
checkType(tokens.remove(0), Token.Type.BODY_BEGIN);
|
||||
|
||||
Returnable<?> comparator = parseExpression(tokens);
|
||||
Returnable<?> comparator = parseExpression(tokens, true);
|
||||
checkReturnType(comparator, Returnable.ReturnType.BOOLEAN);
|
||||
|
||||
checkType(tokens.remove(0), Token.Type.BODY_END);
|
||||
@@ -92,10 +95,10 @@ public class Parser {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Returnable<?> parseExpression(List<Token> tokens) throws ParseException {
|
||||
private Returnable<?> parseExpression(List<Token> tokens, boolean full) throws ParseException {
|
||||
System.out.println(tokens.get(0));
|
||||
Token first = tokens.get(0);
|
||||
checkType(first, Token.Type.IDENTIFIER, Token.Type.BOOLEAN, Token.Type.STRING, Token.Type.NUMBER, Token.Type.BOOLEAN_NOT);
|
||||
checkType(first, Token.Type.IDENTIFIER, Token.Type.BOOLEAN, Token.Type.STRING, Token.Type.NUMBER, Token.Type.BOOLEAN_NOT, Token.Type.BODY_BEGIN);
|
||||
|
||||
boolean not = false;
|
||||
if(first.getType().equals(Token.Type.BOOLEAN_NOT)) {
|
||||
@@ -128,30 +131,52 @@ public class Parser {
|
||||
checkReturnType(expression, Returnable.ReturnType.BOOLEAN);
|
||||
expression = new BooleanNotOperation((Returnable<Boolean>) expression, expression.getPosition());
|
||||
}
|
||||
if(tokens.get(0).isBinaryOperator()) return parseBinaryOperation(expression, tokens);
|
||||
if(full && tokens.get(0).isBinaryOperator()) {
|
||||
return parseBinaryOperation(expression, tokens);
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
private BinaryOperation<?> parseBinaryOperation(Returnable<?> left, List<Token> tokens) throws ParseException {
|
||||
Token binaryOperator = tokens.remove(0);
|
||||
Returnable<?> right = parseExpression(tokens);
|
||||
checkType(binaryOperator, Token.Type.ADDITION_OPERATOR, Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR, Token.Type.SUBTRACTION_OPERATOR, Token.Type.BOOLEAN_OPERATOR);
|
||||
|
||||
Returnable<?> right = parseExpression(tokens, false);
|
||||
if(binaryOperator.isStrictArithmeticOperator()) checkArithmeticOperation(left, right, binaryOperator.getType());
|
||||
|
||||
Token other = tokens.get(0);
|
||||
System.out.println("other: " + other);
|
||||
if(other.isBinaryOperator() && (other.getType().equals(Token.Type.MULTIPLICATION_OPERATOR) || other.getType().equals(Token.Type.DIVISION_OPERATOR))) {
|
||||
System.out.println("using left");
|
||||
return assemble(left, parseBinaryOperation(right, tokens), binaryOperator);
|
||||
} else if(other.isBinaryOperator()) {
|
||||
System.out.println("using right");
|
||||
return parseBinaryOperation(assemble(left, right, binaryOperator), tokens);
|
||||
}
|
||||
return assemble(left, right, binaryOperator);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private BinaryOperation<?> assemble(Returnable<?> left, Returnable<?> right, Token binaryOperator) {
|
||||
switch(binaryOperator.getType()) {
|
||||
case ADDITION_OPERATOR:
|
||||
System.out.println(left.returnType());
|
||||
System.out.println(right.returnType());
|
||||
if(left.returnType().equals(Returnable.ReturnType.NUMBER) && right.returnType().equals(Returnable.ReturnType.NUMBER)) {
|
||||
System.out.println("number " + binaryOperator.getPosition());
|
||||
return new NumberAdditionOperation((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
|
||||
}
|
||||
return new ConcatenationOperation((Returnable<Object>) left, (Returnable<Object>) right, binaryOperator.getPosition());
|
||||
case SUBTRACTION_OPERATOR:
|
||||
return new SubtractionOperation((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
|
||||
case MULTIPLICATION_OPERATOR:
|
||||
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:
|
||||
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unsupported binary operator: " + binaryOperator.getType());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Block parseBlock(List<Token> tokens) throws ParseException {
|
||||
@@ -162,7 +187,6 @@ public class Parser {
|
||||
main:
|
||||
while(tokens.size() > 0) {
|
||||
Token token = tokens.get(0);
|
||||
System.out.println(token);
|
||||
checkType(token, Token.Type.IDENTIFIER, Token.Type.KEYWORD, Token.Type.BLOCK_END);
|
||||
switch(token.getType()) {
|
||||
case KEYWORD:
|
||||
@@ -210,7 +234,7 @@ public class Parser {
|
||||
List<Returnable<?>> args = new GlueList<>();
|
||||
|
||||
while(!tokens.get(0).getType().equals(Token.Type.BODY_END)) {
|
||||
args.add(parseExpression(tokens));
|
||||
args.add(parseExpression(tokens, true));
|
||||
checkType(tokens.get(0), Token.Type.SEPARATOR, Token.Type.BODY_END);
|
||||
if(tokens.get(0).getType().equals(Token.Type.SEPARATOR)) tokens.remove(0);
|
||||
}
|
||||
@@ -226,4 +250,10 @@ public class Parser {
|
||||
for(Returnable.ReturnType type : types) if(returnable.returnType().equals(type)) return;
|
||||
throw new ParseException("Expected " + Arrays.toString(types) + " but found " + returnable.returnType() + ": " + returnable.getPosition());
|
||||
}
|
||||
|
||||
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)) {
|
||||
throw new ParseException("Operation " + operation + " not supported between " + left.returnType() + " and " + right.returnType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+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 DivisionOperation extends BinaryOperation<Number> {
|
||||
public DivisionOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number apply(Number left, Number right) {
|
||||
return left.doubleValue() / right.doubleValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@ import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class MultiplicationOperation extends BinaryOperation<Number> {
|
||||
protected MultiplicationOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
public MultiplicationOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
|
||||
+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 SubtractionOperation extends BinaryOperation<Number> {
|
||||
public SubtractionOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number apply(Number left, Number right) {
|
||||
return left.doubleValue() - right.doubleValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,12 @@ public class Token {
|
||||
|| type.equals(Type.BOOLEAN_OPERATOR);
|
||||
}
|
||||
|
||||
public boolean isStrictArithmeticOperator() {
|
||||
return type.equals(Type.SUBTRACTION_OPERATOR)
|
||||
|| type.equals(Type.MULTIPLICATION_OPERATOR)
|
||||
|| type.equals(Type.DIVISION_OPERATOR);
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
/**
|
||||
* Function identifier or language keyword
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
test("hello" + 3 + "gdfg", 2 + 1.2);
|
||||
test("hello" + 3 + "gdfg", 3 + 8*2 - 1);
|
||||
|
||||
if(true) {
|
||||
test("fdsgdf" + 2, 3.4);
|
||||
|
||||
Reference in New Issue
Block a user