mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-08-29 05:10:58 +00:00
Implement variables
This commit is contained in:
@@ -26,6 +26,12 @@ import com.dfsek.terra.api.structures.parser.lang.operations.statements.GreaterT
|
|||||||
import com.dfsek.terra.api.structures.parser.lang.operations.statements.LessThanOrEqualsStatement;
|
import com.dfsek.terra.api.structures.parser.lang.operations.statements.LessThanOrEqualsStatement;
|
||||||
import com.dfsek.terra.api.structures.parser.lang.operations.statements.LessThanStatement;
|
import com.dfsek.terra.api.structures.parser.lang.operations.statements.LessThanStatement;
|
||||||
import com.dfsek.terra.api.structures.parser.lang.operations.statements.NotEqualsStatement;
|
import com.dfsek.terra.api.structures.parser.lang.operations.statements.NotEqualsStatement;
|
||||||
|
import com.dfsek.terra.api.structures.parser.lang.variables.Assignment;
|
||||||
|
import com.dfsek.terra.api.structures.parser.lang.variables.BooleanVariable;
|
||||||
|
import com.dfsek.terra.api.structures.parser.lang.variables.Getter;
|
||||||
|
import com.dfsek.terra.api.structures.parser.lang.variables.NumberVariable;
|
||||||
|
import com.dfsek.terra.api.structures.parser.lang.variables.StringVariable;
|
||||||
|
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||||
import com.dfsek.terra.api.structures.tokenizer.Token;
|
import com.dfsek.terra.api.structures.tokenizer.Token;
|
||||||
import com.dfsek.terra.api.structures.tokenizer.Tokenizer;
|
import com.dfsek.terra.api.structures.tokenizer.Tokenizer;
|
||||||
@@ -42,7 +48,7 @@ import java.util.Set;
|
|||||||
public class Parser {
|
public class Parser {
|
||||||
private final String data;
|
private final String data;
|
||||||
private final Map<String, FunctionBuilder<? extends Function<?>>> functions = new HashMap<>();
|
private final Map<String, FunctionBuilder<? extends Function<?>>> functions = new HashMap<>();
|
||||||
private final Set<String> keywords = Sets.newHashSet("if");
|
private final Set<String> keywords = Sets.newHashSet("if", "return", "var");
|
||||||
|
|
||||||
Set<Token.Type> allowedArguments = Sets.newHashSet(Token.Type.STRING, Token.Type.NUMBER, Token.Type.IDENTIFIER);
|
Set<Token.Type> allowedArguments = Sets.newHashSet(Token.Type.STRING, Token.Type.NUMBER, Token.Type.IDENTIFIER);
|
||||||
|
|
||||||
@@ -73,12 +79,12 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
if(blockLevel != 0) throw new ParseException("Dangling opening brace");
|
if(blockLevel != 0) throw new ParseException("Dangling opening brace");
|
||||||
|
|
||||||
return parseBlock(tokens);
|
return parseBlock(tokens, new HashMap<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Keyword<?> parseKeyword(List<Token> tokens) throws ParseException {
|
private Keyword<?> parseKeyword(List<Token> tokens, Map<String, Variable<?>> variableMap) throws ParseException {
|
||||||
|
|
||||||
Token identifier = tokens.remove(0);
|
Token identifier = tokens.remove(0);
|
||||||
checkType(identifier, Token.Type.KEYWORD);
|
checkType(identifier, Token.Type.KEYWORD);
|
||||||
@@ -89,24 +95,24 @@ public class Parser {
|
|||||||
|
|
||||||
checkType(tokens.remove(0), Token.Type.GROUP_BEGIN);
|
checkType(tokens.remove(0), Token.Type.GROUP_BEGIN);
|
||||||
|
|
||||||
Returnable<?> comparator = parseExpression(tokens, true);
|
Returnable<?> comparator = parseExpression(tokens, true, variableMap);
|
||||||
checkReturnType(comparator, Returnable.ReturnType.BOOLEAN);
|
checkReturnType(comparator, Returnable.ReturnType.BOOLEAN);
|
||||||
|
|
||||||
checkType(tokens.remove(0), Token.Type.GROUP_END);
|
checkType(tokens.remove(0), Token.Type.GROUP_END);
|
||||||
|
|
||||||
checkType(tokens.remove(0), Token.Type.BLOCK_BEGIN);
|
checkType(tokens.remove(0), Token.Type.BLOCK_BEGIN);
|
||||||
|
|
||||||
k = new IfKeyword(parseBlock(tokens), (Returnable<Boolean>) comparator, identifier.getPosition());
|
k = new IfKeyword(parseBlock(tokens, variableMap), (Returnable<Boolean>) comparator, identifier.getPosition());
|
||||||
|
|
||||||
}
|
}
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Returnable<?> parseExpression(List<Token> tokens, boolean full) throws ParseException {
|
private Returnable<?> parseExpression(List<Token> tokens, boolean full, Map<String, Variable<?>> variableMap) throws ParseException {
|
||||||
Token first = tokens.get(0);
|
Token first = tokens.get(0);
|
||||||
|
|
||||||
if(first.getType().equals(Token.Type.GROUP_BEGIN)) return parseGroup(tokens);
|
if(first.getType().equals(Token.Type.GROUP_BEGIN)) return parseGroup(tokens, variableMap);
|
||||||
|
|
||||||
checkType(first, Token.Type.IDENTIFIER, Token.Type.BOOLEAN, Token.Type.STRING, Token.Type.NUMBER, Token.Type.BOOLEAN_NOT, Token.Type.GROUP_BEGIN);
|
checkType(first, Token.Type.IDENTIFIER, Token.Type.BOOLEAN, Token.Type.STRING, Token.Type.NUMBER, Token.Type.BOOLEAN_NOT, Token.Type.GROUP_BEGIN);
|
||||||
|
|
||||||
@@ -116,8 +122,9 @@ public class Parser {
|
|||||||
tokens.remove(0);
|
tokens.remove(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token id = tokens.get(0);
|
||||||
Returnable<?> expression;
|
Returnable<?> expression;
|
||||||
if(tokens.get(0).isConstant()) {
|
if(id.isConstant()) {
|
||||||
Token constantToken = tokens.remove(0);
|
Token constantToken = tokens.remove(0);
|
||||||
Position position = constantToken.getPosition();
|
Position position = constantToken.getPosition();
|
||||||
switch(constantToken.getType()) {
|
switch(constantToken.getType()) {
|
||||||
@@ -134,7 +141,13 @@ public class Parser {
|
|||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("Unsupported constant token: " + constantToken.getType() + " at position: " + position);
|
throw new UnsupportedOperationException("Unsupported constant token: " + constantToken.getType() + " at position: " + position);
|
||||||
}
|
}
|
||||||
} else expression = parseFunction(tokens, false);
|
} else {
|
||||||
|
if(functions.containsKey(id.getContent())) expression = parseFunction(tokens, false, variableMap);
|
||||||
|
else if(variableMap.containsKey(id.getContent())) {
|
||||||
|
checkType(tokens.remove(0), Token.Type.IDENTIFIER);
|
||||||
|
expression = new Getter(variableMap.get(id.getContent()));
|
||||||
|
} else throw new ParseException("Unexpected token: " + id.getContent() + " at " + id.getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if(not) {
|
if(not) {
|
||||||
@@ -142,32 +155,32 @@ public class Parser {
|
|||||||
expression = new BooleanNotOperation((Returnable<Boolean>) expression, expression.getPosition());
|
expression = new BooleanNotOperation((Returnable<Boolean>) expression, expression.getPosition());
|
||||||
}
|
}
|
||||||
if(full && tokens.get(0).isBinaryOperator()) {
|
if(full && tokens.get(0).isBinaryOperator()) {
|
||||||
return parseBinaryOperation(expression, tokens);
|
return parseBinaryOperation(expression, tokens, variableMap);
|
||||||
}
|
}
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Returnable<?> parseGroup(List<Token> tokens) throws ParseException {
|
private Returnable<?> parseGroup(List<Token> tokens, Map<String, Variable<?>> variableMap) throws ParseException {
|
||||||
checkType(tokens.remove(0), Token.Type.GROUP_BEGIN);
|
checkType(tokens.remove(0), Token.Type.GROUP_BEGIN);
|
||||||
Returnable<?> expression = parseExpression(tokens, true);
|
Returnable<?> expression = parseExpression(tokens, true, variableMap);
|
||||||
checkType(tokens.remove(0), Token.Type.GROUP_END);
|
checkType(tokens.remove(0), Token.Type.GROUP_END);
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private BinaryOperation<?, ?> parseBinaryOperation(Returnable<?> left, List<Token> tokens) throws ParseException {
|
private BinaryOperation<?, ?> parseBinaryOperation(Returnable<?> left, List<Token> tokens, Map<String, Variable<?>> variableMap) throws ParseException {
|
||||||
Token binaryOperator = tokens.remove(0);
|
Token binaryOperator = tokens.remove(0);
|
||||||
checkType(binaryOperator, Token.Type.ADDITION_OPERATOR, Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR, Token.Type.SUBTRACTION_OPERATOR,
|
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);
|
Token.Type.BOOLEAN_AND, Token.Type.BOOLEAN_OR);
|
||||||
|
|
||||||
Returnable<?> right = parseExpression(tokens, false);
|
Returnable<?> right = parseExpression(tokens, false, variableMap);
|
||||||
|
|
||||||
Token other = tokens.get(0);
|
Token other = tokens.get(0);
|
||||||
if(other.isBinaryOperator() && (other.getType().equals(Token.Type.MULTIPLICATION_OPERATOR) || other.getType().equals(Token.Type.DIVISION_OPERATOR))) {
|
if(other.isBinaryOperator() && (other.getType().equals(Token.Type.MULTIPLICATION_OPERATOR) || other.getType().equals(Token.Type.DIVISION_OPERATOR))) {
|
||||||
return assemble(left, parseBinaryOperation(right, tokens), binaryOperator);
|
return assemble(left, parseBinaryOperation(right, tokens, variableMap), binaryOperator);
|
||||||
} else if(other.isBinaryOperator()) {
|
} else if(other.isBinaryOperator()) {
|
||||||
return parseBinaryOperation(assemble(left, right, binaryOperator), tokens);
|
return parseBinaryOperation(assemble(left, right, binaryOperator), tokens, variableMap);
|
||||||
}
|
}
|
||||||
return assemble(left, right, binaryOperator);
|
return assemble(left, right, binaryOperator);
|
||||||
}
|
}
|
||||||
@@ -209,35 +222,84 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Block parseBlock(List<Token> tokens) throws ParseException {
|
private Variable<?> parseVariableDeclaration(List<Token> tokens, Returnable.ReturnType type) throws ParseException {
|
||||||
|
checkVarType(tokens.get(0), type); // Check for type mismatch
|
||||||
|
switch(type) {
|
||||||
|
case NUMBER:
|
||||||
|
return new NumberVariable(0d, tokens.get(0).getPosition());
|
||||||
|
case STRING:
|
||||||
|
return new StringVariable("", tokens.get(0).getPosition());
|
||||||
|
case BOOLEAN:
|
||||||
|
return new BooleanVariable(false, tokens.get(0).getPosition());
|
||||||
|
}
|
||||||
|
throw new UnsupportedOperationException("Unsupported variable type: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Block parseBlock(List<Token> tokens, Map<String, Variable<?>> superVars) throws ParseException {
|
||||||
List<Item<?>> parsedItems = new GlueList<>();
|
List<Item<?>> parsedItems = new GlueList<>();
|
||||||
|
|
||||||
|
Map<String, Variable<?>> parsedVariables = new HashMap<>(superVars); // New hashmap as to not mutate parent scope's declarations.
|
||||||
|
|
||||||
Token first = tokens.get(0);
|
Token first = tokens.get(0);
|
||||||
|
|
||||||
checkType(tokens.get(0), Token.Type.IDENTIFIER, Token.Type.KEYWORD);
|
checkType(tokens.get(0), Token.Type.IDENTIFIER, Token.Type.KEYWORD, Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE);
|
||||||
main:
|
main:
|
||||||
while(tokens.size() > 0) {
|
while(tokens.size() > 0) {
|
||||||
Token token = tokens.get(0);
|
Token token = tokens.get(0);
|
||||||
checkType(token, Token.Type.IDENTIFIER, Token.Type.KEYWORD, Token.Type.BLOCK_END);
|
checkType(token, Token.Type.IDENTIFIER, Token.Type.KEYWORD, Token.Type.BLOCK_END, Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE);
|
||||||
switch(token.getType()) {
|
switch(token.getType()) {
|
||||||
case KEYWORD:
|
case KEYWORD:
|
||||||
parsedItems.add(parseKeyword(tokens));
|
parsedItems.add(parseKeyword(tokens, parsedVariables));
|
||||||
if(tokens.isEmpty()) break;
|
if(tokens.isEmpty()) break;
|
||||||
checkType(tokens.get(0), Token.Type.IDENTIFIER, Token.Type.KEYWORD, Token.Type.BLOCK_END);
|
checkType(tokens.get(0), Token.Type.IDENTIFIER, Token.Type.KEYWORD, Token.Type.BLOCK_END);
|
||||||
break;
|
break;
|
||||||
case IDENTIFIER:
|
case IDENTIFIER:
|
||||||
parsedItems.add(parseFunction(tokens, true));
|
parsedItems.add(parseFunction(tokens, true, parsedVariables));
|
||||||
if(tokens.isEmpty()) break;
|
if(tokens.isEmpty()) break;
|
||||||
checkType(tokens.remove(0), Token.Type.STATEMENT_END, Token.Type.BLOCK_END);
|
checkType(tokens.remove(0), Token.Type.STATEMENT_END, Token.Type.BLOCK_END);
|
||||||
break;
|
break;
|
||||||
case BLOCK_END:
|
case BLOCK_END:
|
||||||
tokens.remove(0);
|
tokens.remove(0); // Remove block end.
|
||||||
break main;
|
break main;
|
||||||
|
case NUMBER_VARIABLE:
|
||||||
|
case BOOLEAN_VARIABLE:
|
||||||
|
case STRING_VARIABLE:
|
||||||
|
Variable<?> temp;
|
||||||
|
if(token.getType().equals(Token.Type.NUMBER_VARIABLE))
|
||||||
|
temp = parseVariableDeclaration(tokens, Returnable.ReturnType.NUMBER);
|
||||||
|
else if(token.getType().equals(Token.Type.STRING_VARIABLE))
|
||||||
|
temp = parseVariableDeclaration(tokens, Returnable.ReturnType.STRING);
|
||||||
|
else temp = parseVariableDeclaration(tokens, Returnable.ReturnType.BOOLEAN);
|
||||||
|
Token name = tokens.get(1);
|
||||||
|
|
||||||
|
checkType(name, Token.Type.IDENTIFIER);
|
||||||
|
|
||||||
|
parsedVariables.put(name.getContent(), temp);
|
||||||
|
parsedItems.add(parseAssignment(temp, tokens, parsedVariables));
|
||||||
|
checkType(tokens.remove(0), Token.Type.STATEMENT_END);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new Block(parsedItems, first.getPosition());
|
return new Block(parsedItems, first.getPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Function<?> parseFunction(List<Token> tokens, boolean fullStatement) throws ParseException {
|
@SuppressWarnings("unchecked")
|
||||||
|
private Assignment<?> parseAssignment(Variable<?> variable, List<Token> tokens, Map<String, Variable<?>> variableMap) throws ParseException {
|
||||||
|
checkType(tokens.remove(0), Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE);
|
||||||
|
|
||||||
|
Token name = tokens.get(0);
|
||||||
|
|
||||||
|
checkType(tokens.remove(0), Token.Type.IDENTIFIER);
|
||||||
|
|
||||||
|
checkType(tokens.remove(0), Token.Type.ASSIGNMENT);
|
||||||
|
|
||||||
|
Returnable<?> expression = parseExpression(tokens, true, variableMap);
|
||||||
|
|
||||||
|
checkReturnType(expression, variable.getType());
|
||||||
|
|
||||||
|
return new Assignment<>((Variable<Object>) variable, (Returnable<Object>) expression, name.getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Function<?> parseFunction(List<Token> tokens, boolean fullStatement, Map<String, Variable<?>> variableMap) throws ParseException {
|
||||||
Token identifier = tokens.remove(0);
|
Token identifier = tokens.remove(0);
|
||||||
checkType(identifier, Token.Type.IDENTIFIER); // First token must be identifier
|
checkType(identifier, Token.Type.IDENTIFIER); // First token must be identifier
|
||||||
|
|
||||||
@@ -247,7 +309,7 @@ public class Parser {
|
|||||||
checkType(tokens.remove(0), Token.Type.GROUP_BEGIN); // Second is body begin
|
checkType(tokens.remove(0), Token.Type.GROUP_BEGIN); // Second is body begin
|
||||||
|
|
||||||
|
|
||||||
List<Returnable<?>> args = getArgs(tokens); // Extract arguments, consume the rest.
|
List<Returnable<?>> args = getArgs(tokens, variableMap); // Extract arguments, consume the rest.
|
||||||
|
|
||||||
tokens.remove(0); // Remove body end
|
tokens.remove(0); // Remove body end
|
||||||
|
|
||||||
@@ -268,11 +330,11 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<Returnable<?>> getArgs(List<Token> tokens) throws ParseException {
|
private List<Returnable<?>> getArgs(List<Token> tokens, Map<String, Variable<?>> variableMap) throws ParseException {
|
||||||
List<Returnable<?>> args = new GlueList<>();
|
List<Returnable<?>> args = new GlueList<>();
|
||||||
|
|
||||||
while(!tokens.get(0).getType().equals(Token.Type.GROUP_END)) {
|
while(!tokens.get(0).getType().equals(Token.Type.GROUP_END)) {
|
||||||
args.add(parseExpression(tokens, true));
|
args.add(parseExpression(tokens, true, variableMap));
|
||||||
checkType(tokens.get(0), Token.Type.SEPARATOR, Token.Type.GROUP_END);
|
checkType(tokens.get(0), Token.Type.SEPARATOR, Token.Type.GROUP_END);
|
||||||
if(tokens.get(0).getType().equals(Token.Type.SEPARATOR)) tokens.remove(0);
|
if(tokens.get(0).getType().equals(Token.Type.SEPARATOR)) tokens.remove(0);
|
||||||
}
|
}
|
||||||
@@ -300,4 +362,11 @@ public class Parser {
|
|||||||
throw new ParseException("Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType() + ": " + operation.getPosition());
|
throw new ParseException("Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType() + ": " + operation.getPosition());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkVarType(Token token, Returnable.ReturnType returnType) throws ParseException {
|
||||||
|
if(returnType.equals(Returnable.ReturnType.STRING) && token.getType().equals(Token.Type.STRING_VARIABLE)) return;
|
||||||
|
if(returnType.equals(Returnable.ReturnType.NUMBER) && token.getType().equals(Token.Type.NUMBER_VARIABLE)) return;
|
||||||
|
if(returnType.equals(Returnable.ReturnType.BOOLEAN) && token.getType().equals(Token.Type.BOOLEAN_VARIABLE)) return;
|
||||||
|
throw new ParseException("Type mismatch, cannot convert from " + returnType + " to " + token.getType() + ": " + token.getPosition());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
package com.dfsek.terra.api.structures.parser.lang.variables;
|
||||||
|
|
||||||
|
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.Returnable;
|
||||||
|
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||||
|
|
||||||
|
public class Assignment<T> implements Item<T> {
|
||||||
|
private final Variable<T> delegate;
|
||||||
|
private final Returnable<T> value;
|
||||||
|
private final Position position;
|
||||||
|
|
||||||
|
public Assignment(Variable<T> delegate, Returnable<T> value, Position position) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
this.value = value;
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T apply(Location location) {
|
||||||
|
T val = value.apply(location);
|
||||||
|
delegate.setValue(val);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T apply(Location location, Chunk chunk) {
|
||||||
|
T val = value.apply(location, chunk);
|
||||||
|
delegate.setValue(val);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Position getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
package com.dfsek.terra.api.structures.parser.lang.variables;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||||
|
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||||
|
|
||||||
|
public class BooleanVariable implements Variable<Boolean> {
|
||||||
|
private final Position position;
|
||||||
|
private Boolean value;
|
||||||
|
|
||||||
|
public BooleanVariable(Boolean value, Position position) {
|
||||||
|
this.value = value;
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setValue(Boolean value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Returnable.ReturnType getType() {
|
||||||
|
return Returnable.ReturnType.BOOLEAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Position getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.dfsek.terra.api.structures.parser.lang.variables;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.math.vector.Location;
|
||||||
|
import com.dfsek.terra.api.platform.world.Chunk;
|
||||||
|
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||||
|
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||||
|
|
||||||
|
public class Getter implements Returnable<Object> {
|
||||||
|
private final Variable<?> delegate;
|
||||||
|
|
||||||
|
public Getter(Variable<?> delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReturnType returnType() {
|
||||||
|
return delegate.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object apply(Location location) {
|
||||||
|
return delegate.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object apply(Location location, Chunk chunk) {
|
||||||
|
return delegate.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Position getPosition() {
|
||||||
|
return delegate.getPosition();
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
package com.dfsek.terra.api.structures.parser.lang.variables;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||||
|
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||||
|
|
||||||
|
public class NumberVariable implements Variable<Number> {
|
||||||
|
private final Position position;
|
||||||
|
private Number value;
|
||||||
|
|
||||||
|
public NumberVariable(Number value, Position position) {
|
||||||
|
this.value = value;
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Number getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setValue(Number value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Returnable.ReturnType getType() {
|
||||||
|
return Returnable.ReturnType.NUMBER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Position getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
package com.dfsek.terra.api.structures.parser.lang.variables;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||||
|
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||||
|
|
||||||
|
public class StringVariable implements Variable<String> {
|
||||||
|
private final Position position;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public StringVariable(String value, Position position) {
|
||||||
|
this.value = value;
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Returnable.ReturnType getType() {
|
||||||
|
return Returnable.ReturnType.STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Position getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
package com.dfsek.terra.api.structures.parser.lang.variables;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||||
|
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||||
|
|
||||||
|
public interface Variable<T> {
|
||||||
|
T getValue();
|
||||||
|
|
||||||
|
void setValue(T value);
|
||||||
|
|
||||||
|
Returnable.ReturnType getType();
|
||||||
|
|
||||||
|
Position getPosition();
|
||||||
|
}
|
||||||
@@ -163,6 +163,12 @@ public class Token {
|
|||||||
/**
|
/**
|
||||||
* Boolean and
|
* Boolean and
|
||||||
*/
|
*/
|
||||||
BOOLEAN_AND
|
BOOLEAN_AND,
|
||||||
|
/**
|
||||||
|
* Variable declaration
|
||||||
|
*/
|
||||||
|
NUMBER_VARIABLE,
|
||||||
|
STRING_VARIABLE,
|
||||||
|
BOOLEAN_VARIABLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ public class Tokenizer {
|
|||||||
private final Lookahead reader;
|
private final Lookahead reader;
|
||||||
|
|
||||||
private final Set<Character> syntaxSignificant = Sets.newHashSet(';', '(', ')', '"', ',', '\\', '=', '{', '}', '+', '-', '*', '/', '>', '<', '!'); // Reserved chars
|
private final Set<Character> syntaxSignificant = Sets.newHashSet(';', '(', ')', '"', ',', '\\', '=', '{', '}', '+', '-', '*', '/', '>', '<', '!'); // Reserved chars
|
||||||
private final Set<String> keywords = Sets.newHashSet("if", "return");
|
private final Set<String> keywords = Sets.newHashSet("if", "return", "num", "bool", "str");
|
||||||
|
|
||||||
|
|
||||||
public Tokenizer(String data) {
|
public Tokenizer(String data) {
|
||||||
@@ -20,7 +20,7 @@ public class Tokenizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
while(!reader.current().isEOF() && reader.current().isWhitespace()) reader.consume(); // Consume whitespace.
|
//while(!reader.current().isEOF() && reader.current().isWhitespace()) reader.consume(); // Consume whitespace.
|
||||||
return !reader.current().isEOF();
|
return !reader.current().isEOF();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,11 +50,19 @@ public class Tokenizer {
|
|||||||
return new Token(">=", Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
|
return new Token(">=", Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
|
||||||
if(reader.matches("<=", true))
|
if(reader.matches("<=", true))
|
||||||
return new Token("<=", Token.Type.LESS_THAN_OR_EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
|
return new Token("<=", Token.Type.LESS_THAN_OR_EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
|
||||||
|
|
||||||
if(reader.matches("||", true))
|
if(reader.matches("||", true))
|
||||||
return new Token("||", Token.Type.BOOLEAN_OR, new Position(reader.getLine(), reader.getIndex()));
|
return new Token("||", Token.Type.BOOLEAN_OR, new Position(reader.getLine(), reader.getIndex()));
|
||||||
if(reader.matches("&&", true))
|
if(reader.matches("&&", true))
|
||||||
return new Token("&&", Token.Type.BOOLEAN_AND, new Position(reader.getLine(), reader.getIndex()));
|
return new Token("&&", Token.Type.BOOLEAN_AND, new Position(reader.getLine(), reader.getIndex()));
|
||||||
|
|
||||||
|
if(reader.matches("num ", true))
|
||||||
|
return new Token("num ", Token.Type.NUMBER_VARIABLE, new Position(reader.getLine(), reader.getIndex()));
|
||||||
|
if(reader.matches("str ", true))
|
||||||
|
return new Token("str ", Token.Type.STRING_VARIABLE, new Position(reader.getLine(), reader.getIndex()));
|
||||||
|
if(reader.matches("bool ", true))
|
||||||
|
return new Token("bool ", Token.Type.BOOLEAN_VARIABLE, new Position(reader.getLine(), reader.getIndex()));
|
||||||
|
|
||||||
|
|
||||||
if(isNumberStart()) {
|
if(isNumberStart()) {
|
||||||
StringBuilder num = new StringBuilder();
|
StringBuilder num = new StringBuilder();
|
||||||
@@ -111,7 +119,8 @@ public class Tokenizer {
|
|||||||
StringBuilder token = new StringBuilder();
|
StringBuilder token = new StringBuilder();
|
||||||
while(!reader.current().isEOF() && !isSyntaxSignificant(reader.current().getCharacter())) {
|
while(!reader.current().isEOF() && !isSyntaxSignificant(reader.current().getCharacter())) {
|
||||||
Char c = reader.consume();
|
Char c = reader.consume();
|
||||||
if(!c.isWhitespace()) token.append(c);
|
if(c.isWhitespace()) break;
|
||||||
|
token.append(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
String tokenString = token.toString();
|
String tokenString = token.toString();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import com.dfsek.terra.api.math.vector.Location;
|
|||||||
import com.dfsek.terra.api.platform.world.Chunk;
|
import com.dfsek.terra.api.platform.world.Chunk;
|
||||||
import com.dfsek.terra.api.structures.parser.Parser;
|
import com.dfsek.terra.api.structures.parser.Parser;
|
||||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||||
import com.dfsek.terra.api.structures.parser.lang.Item;
|
import com.dfsek.terra.api.structures.parser.lang.Block;
|
||||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
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.functions.FunctionBuilder;
|
||||||
@@ -23,7 +23,7 @@ public class ParserTest {
|
|||||||
parser.addFunction("test", new FunctionBuilder<Test1>() {
|
parser.addFunction("test", new FunctionBuilder<Test1>() {
|
||||||
@Override
|
@Override
|
||||||
public Test1 build(List<Returnable<?>> argumentList, Position position) throws ParseException {
|
public Test1 build(List<Returnable<?>> argumentList, Position position) throws ParseException {
|
||||||
return new Test1(argumentList.get(0).apply(new Location(null, 0, 0, 0)).toString(), Double.parseDouble(argumentList.get(1).apply(new Location(null, 0, 0, 0)).toString()), position);
|
return new Test1(argumentList.get(0), argumentList.get(1), position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -46,34 +46,27 @@ public class ParserTest {
|
|||||||
});
|
});
|
||||||
|
|
||||||
long l = System.nanoTime();
|
long l = System.nanoTime();
|
||||||
List<Item<?>> functions = parser.parse().getItems();
|
Block block = parser.parse();
|
||||||
long t = System.nanoTime() - l;
|
long t = System.nanoTime() - l;
|
||||||
System.out.println("Took " + (double) t / 1000000);
|
System.out.println("Took " + (double) t / 1000000);
|
||||||
|
|
||||||
for(Item<?> f : functions) System.out.println(f);
|
block.apply(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Test1 implements Function<Void> {
|
private static class Test1 implements Function<Void> {
|
||||||
private final String a;
|
private final Returnable<?> a;
|
||||||
private final double b;
|
private final Returnable<?> b;
|
||||||
private final Position position;
|
private final Position position;
|
||||||
|
|
||||||
public Test1(String a, double b, Position position) {
|
public Test1(Returnable<?> a, Returnable<?> b, Position position) {
|
||||||
this.a = a;
|
this.a = a;
|
||||||
this.b = b;
|
this.b = b;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getA() {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getB() {
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void apply(Location location) {
|
public Void apply(Location location) {
|
||||||
|
System.out.println("string: " + a.apply(location) + ", double: " + b.apply(location));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,11 +85,6 @@ public class ParserTest {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "string: " + a + ", double: " + b;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ReturnType returnType() {
|
public ReturnType returnType() {
|
||||||
return ReturnType.VOID;
|
return ReturnType.VOID;
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
test("hello" + 3 + "gdfg", (2 * (3+1) * (2 * (1+1))));
|
test("hello" + 3 + "gdfg", (2 * (3+1) * (2 * (1+1))));
|
||||||
|
|
||||||
if(true || false) {
|
num testVar = 3.4;
|
||||||
test("fdsgdf" + 2, 1);
|
bool boolean = true;
|
||||||
}
|
str stringVar = "hello!";
|
||||||
|
|
||||||
|
if(true && boolean) {
|
||||||
|
num scopedVar = 2;
|
||||||
|
test("fdsgdf" + 2 + stringVar, 1 + testVar + scopedVar);
|
||||||
|
}
|
||||||
|
|
||||||
|
test("fdsgdf" + 2, 1 + testVar);
|
||||||
Reference in New Issue
Block a user