Reformat all code

Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
This commit is contained in:
solonovamax
2021-08-30 17:34:44 -04:00
parent 1655381413
commit c445a0434d
753 changed files with 10461 additions and 8783 deletions

View File

@@ -1,6 +1,10 @@
package com.dfsek.terra.addons.terrascript;
import com.dfsek.tectonic.exception.LoadException;
import java.io.InputStream;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.script.StructureScript;
import com.dfsek.terra.api.TerraPlugin;
@@ -15,8 +19,6 @@ import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.structure.LootTable;
import com.dfsek.terra.api.structure.Structure;
import java.io.InputStream;
import java.util.Map;
@Addon("structure-terrascript-loader")
@Author("Terra")
@@ -24,26 +26,27 @@ import java.util.Map;
public class TerraScriptAddon extends TerraAddon {
@Inject
private TerraPlugin main;
@Override
public void initialize() {
main.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigPackPreLoadEvent.class)
.then(event -> {
CheckedRegistry<Structure> structureRegistry = event.getPack().getOrCreateRegistry(Structure.class);
CheckedRegistry<LootTable> lootRegistry = event.getPack().getOrCreateRegistry(LootTable.class);
event.getPack().getLoader().open("", ".tesf").thenEntries(entries -> {
for(Map.Entry<String, InputStream> entry : entries) {
try {
StructureScript structureScript = new StructureScript(entry.getValue(), main, structureRegistry, lootRegistry, event.getPack().getRegistryFactory().create());
structureRegistry.register(structureScript.getID(), structureScript);
} catch(ParseException e) {
throw new LoadException("Failed to load script: ", e);
}
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigPackPreLoadEvent.class)
.then(event -> {
CheckedRegistry<Structure> structureRegistry = event.getPack().getOrCreateRegistry(Structure.class);
CheckedRegistry<LootTable> lootRegistry = event.getPack().getOrCreateRegistry(LootTable.class);
event.getPack().getLoader().open("", ".tesf").thenEntries(entries -> {
for(Map.Entry<String, InputStream> entry : entries) {
try {
StructureScript structureScript = new StructureScript(entry.getValue(), main, structureRegistry, lootRegistry,
event.getPack().getRegistryFactory().create());
structureRegistry.register(structureScript.getID(), structureScript);
} catch(ParseException e) {
throw new LoadException("Failed to load script: ", e);
}
}).close();
})
.failThrough();
}
}).close();
})
.failThrough();
}
}

View File

@@ -1,29 +1,30 @@
package com.dfsek.terra.addons.terrascript.buffer;
import java.util.ArrayList;
import java.util.List;
import com.dfsek.terra.api.structure.buffer.BufferedItem;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.World;
import java.util.ArrayList;
import java.util.List;
public class Cell implements BufferedItem {
private final List<BufferedItem> items = new ArrayList<>();
private String mark = null;
private String mark;
@Override
public void paste(Vector3 origin, World world) {
items.forEach(item -> item.paste(origin.clone(), world));
}
public void add(BufferedItem item) {
items.add(item);
}
public String getMark() {
return mark;
}
public void setMark(String mark) {
this.mark = mark;
}

View File

@@ -1,13 +1,14 @@
package com.dfsek.terra.addons.terrascript.buffer;
import java.util.LinkedHashMap;
import java.util.Map;
import com.dfsek.terra.api.structure.buffer.Buffer;
import com.dfsek.terra.api.structure.buffer.BufferedItem;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.Chunk;
import com.dfsek.terra.api.world.World;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Buffer implementation that directly pastes to the world.
@@ -16,41 +17,41 @@ public class DirectBuffer implements Buffer {
private final Vector3 origin;
private final World target;
private final Map<Vector3, String> marks = new LinkedHashMap<>();
public DirectBuffer(Vector3 origin, World target) {
this.origin = origin;
this.target = target;
}
@Override
public void paste(Vector3 origin, Chunk chunk) {
// no-op
}
@Override
public void paste(Vector3 origin, World world) {
// no-op
}
@Override
public Buffer addItem(BufferedItem item, Vector3 location) {
item.paste(origin.clone().add(location), target);
return this;
}
@Override
public Vector3 getOrigin() {
return origin;
}
@Override
public String getMark(Vector3 location) {
return marks.get(location);
}
@Override
public Buffer setMark(String mark, Vector3 location) {
marks.put(location, mark);
return this;
}
@Override
public Vector3 getOrigin() {
return origin;
}
@Override
public String getMark(Vector3 location) {
return marks.get(location);
}
}

View File

@@ -6,43 +6,44 @@ import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.Chunk;
import com.dfsek.terra.api.world.World;
public class IntermediateBuffer implements Buffer {
private final Buffer original;
private final Vector3 offset;
public IntermediateBuffer(Buffer original, Vector3 offset) {
this.original = original;
this.offset = offset.clone();
}
@Override
public void paste(Vector3 origin, Chunk chunk) {
// no-op
}
@Override
public void paste(Vector3 origin, World world) {
// no-op
}
@Override
public Buffer addItem(BufferedItem item, Vector3 location) {
return original.addItem(item, location.clone().add(offset));
}
@Override
public Vector3 getOrigin() {
return original.getOrigin().clone().add(offset);
}
@Override
public String getMark(Vector3 location) {
return original.getMark(location.clone().add(offset));
}
@Override
public Buffer setMark(String mark, Vector3 location) {
original.setMark(mark, location.clone().add(offset));
return this;
}
@Override
public Vector3 getOrigin() {
return original.getOrigin().clone().add(offset);
}
@Override
public String getMark(Vector3 location) {
return original.getMark(location.clone().add(offset));
}
}

View File

@@ -1,28 +1,26 @@
package com.dfsek.terra.addons.terrascript.buffer;
import net.jafama.FastMath;
import java.util.LinkedHashMap;
import java.util.Map;
import com.dfsek.terra.api.structure.buffer.Buffer;
import com.dfsek.terra.api.structure.buffer.BufferedItem;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.Chunk;
import com.dfsek.terra.api.world.World;
import net.jafama.FastMath;
import java.util.LinkedHashMap;
import java.util.Map;
public class StructureBuffer implements Buffer {
private final Map<Vector3, Cell> bufferedItemMap = new LinkedHashMap<>();
private final Vector3 origin;
private boolean succeeded;
public StructureBuffer(Vector3 origin) {
this.origin = origin;
}
public void paste(Vector3 origin, World world) {
bufferedItemMap.forEach(((vector3, item) -> item.paste(origin.clone().add(vector3), world)));
}
public void paste(Vector3 origin, Chunk chunk) {
bufferedItemMap.forEach(((location, item) -> {
Vector3 current = origin.clone().add(location);
@@ -31,13 +29,28 @@ public class StructureBuffer implements Buffer {
item.paste(current, chunk.getWorld());
}));
}
public void paste(Vector3 origin, World world) {
bufferedItemMap.forEach(((vector3, item) -> item.paste(origin.clone().add(vector3), world)));
}
@Override
public Buffer addItem(BufferedItem item, Vector3 location) {
bufferedItemMap.computeIfAbsent(location.clone(), l -> new Cell()).add(item);
return this;
}
@Override
public Buffer setMark(String mark, Vector3 location) {
bufferedItemMap.computeIfAbsent(location.clone(), l -> new Cell()).setMark(mark);
return this;
}
@Override
public Vector3 getOrigin() {
return origin.clone();
}
@Override
public String getMark(Vector3 location) {
Cell cell = bufferedItemMap.get(location);
@@ -46,23 +59,12 @@ public class StructureBuffer implements Buffer {
}
return null;
}
@Override
public Buffer setMark(String mark, Vector3 location) {
bufferedItemMap.computeIfAbsent(location.clone(), l -> new Cell()).setMark(mark);
return this;
}
public void setSucceeded(boolean succeeded) {
this.succeeded = succeeded;
}
public boolean succeeded() {
return succeeded;
}
@Override
public Vector3 getOrigin() {
return origin.clone();
public void setSucceeded(boolean succeeded) {
this.succeeded = succeeded;
}
}

View File

@@ -7,19 +7,20 @@ import com.dfsek.terra.api.structure.buffer.BufferedItem;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.World;
public class BufferedBlock implements BufferedItem {
private final BlockState data;
private final boolean overwrite;
private final TerraPlugin main;
private final boolean waterlog;
public BufferedBlock(BlockState data, boolean overwrite, TerraPlugin main, boolean waterlog) {
this.data = data;
this.overwrite = overwrite;
this.main = main;
this.waterlog = waterlog;
}
@Override
public void paste(Vector3 origin, World world) {
try {

View File

@@ -8,16 +8,17 @@ import com.dfsek.terra.api.structure.buffer.BufferedItem;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.World;
public class BufferedEntity implements BufferedItem {
public class BufferedEntity implements BufferedItem {
private final EntityType type;
private final TerraPlugin main;
public BufferedEntity(EntityType type, TerraPlugin main) {
this.type = type;
this.main = main;
}
@Override
public void paste(Vector3 origin, World world) {
Entity entity = world.spawnEntity(origin.clone().add(0.5, 0, 0.5), type);

View File

@@ -1,5 +1,7 @@
package com.dfsek.terra.addons.terrascript.buffer.items;
import java.util.Random;
import com.dfsek.terra.addons.terrascript.script.StructureScript;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.block.entity.BlockEntity;
@@ -10,19 +12,18 @@ import com.dfsek.terra.api.structure.buffer.BufferedItem;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.World;
import java.util.Random;
public class BufferedLootApplication implements BufferedItem {
private final LootTable table;
private final TerraPlugin main;
private final StructureScript structure;
public BufferedLootApplication(LootTable table, TerraPlugin main, StructureScript structure) {
this.table = table;
this.main = main;
this.structure = structure;
}
@Override
public void paste(Vector3 origin, World world) {
try {
@@ -32,11 +33,11 @@ public class BufferedLootApplication implements BufferedItem {
return;
}
Container container = (Container) data;
LootPopulateEvent event = new LootPopulateEvent(container, table, world.getConfig().getPack(), structure);
main.getEventManager().callEvent(event);
if(event.isCancelled()) return;
event.getTable().fillInventory(container.getInventory(), new Random(origin.hashCode()));
data.update(false);
} catch(Exception e) {

View File

@@ -5,13 +5,14 @@ import com.dfsek.terra.api.structure.buffer.BufferedItem;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.World;
public class BufferedPulledBlock implements BufferedItem {
private final BlockState data;
public BufferedPulledBlock(BlockState data) {
this.data = data;
}
@Override
public void paste(Vector3 origin, World world) {
Vector3 mutable = origin.clone();

View File

@@ -6,15 +6,16 @@ import com.dfsek.terra.api.structure.buffer.BufferedItem;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.World;
public class BufferedStateManipulator implements BufferedItem {
private final TerraPlugin main;
private final String data;
public BufferedStateManipulator(TerraPlugin main, String state) {
this.main = main;
this.data = state;
}
@Override
public void paste(Vector3 origin, World world) {
try {

View File

@@ -1,5 +1,11 @@
package com.dfsek.terra.addons.terrascript.parser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.Block;
import com.dfsek.terra.addons.terrascript.parser.lang.Item;
@@ -42,66 +48,57 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import com.dfsek.terra.addons.terrascript.tokenizer.Token;
import com.dfsek.terra.addons.terrascript.tokenizer.Tokenizer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SuppressWarnings("unchecked")
public class Parser {
private final String data;
private final Map<String, FunctionBuilder<? extends Function<?>>> functions = new HashMap<>();
private final List<String> ignoredFunctions = new ArrayList<>();
private String id;
public Parser(String data) {
this.data = data;
}
public Parser registerFunction(String name, FunctionBuilder<? extends Function<?>> functionBuilder) {
functions.put(name, functionBuilder);
return this;
}
public Parser ignoreFunction(String name) {
ignoredFunctions.add(name);
return this;
}
public String getID() {
return id;
}
/**
* Parse input
*
* @return executable {@link Block}
*
* @throws ParseException If parsing fails.
*/
public Block parse() throws ParseException {
Tokenizer tokens = new Tokenizer(data);
// Parse ID
ParserUtil.checkType(tokens.consume(), Token.Type.ID); // First token must be ID
Token idToken = tokens.get();
ParserUtil.checkType(tokens.consume(), Token.Type.STRING); // Second token must be string literal containing ID
ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
this.id = idToken.getContent();
return parseBlock(tokens, new HashMap<>(), false);
}
private Keyword<?> parseLoopLike(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, boolean loop) throws ParseException {
Token identifier = tokens.consume();
ParserUtil.checkType(identifier, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP);
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN);
switch(identifier.getType()) {
case FOR_LOOP:
return parseForLoop(tokens, variableMap, identifier.getPosition());
@@ -113,27 +110,29 @@ public class Parser {
throw new UnsupportedOperationException("Unknown keyword " + identifier.getContent() + ": " + identifier.getPosition());
}
}
private WhileKeyword parseWhileLoop(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, Position start) throws ParseException {
private WhileKeyword parseWhileLoop(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, Position start)
throws ParseException {
Returnable<?> first = parseExpression(tokens, true, variableMap);
ParserUtil.checkReturnType(first, Returnable.ReturnType.BOOLEAN);
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
return new WhileKeyword(parseStatementBlock(tokens, variableMap, true), (Returnable<Boolean>) first, start); // While loop
}
private IfKeyword parseIfStatement(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, Position start, boolean loop) throws ParseException {
private IfKeyword parseIfStatement(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, Position start, boolean loop)
throws ParseException {
Returnable<?> condition = parseExpression(tokens, true, variableMap);
ParserUtil.checkReturnType(condition, Returnable.ReturnType.BOOLEAN);
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
Block elseBlock = null;
Block statement = parseStatementBlock(tokens, variableMap, loop);
List<IfKeyword.Pair<Returnable<Boolean>, Block>> elseIf = new ArrayList<>();
while(tokens.hasNext() && tokens.get().getType().equals(Token.Type.ELSE)) {
tokens.consume(); // Consume else.
if(tokens.get().getType().equals(Token.Type.IF_STATEMENT)) {
@@ -146,12 +145,13 @@ public class Parser {
break; // Else must be last.
}
}
return new IfKeyword(statement, (Returnable<Boolean>) condition, elseIf, elseBlock, start); // If statement
}
private Block parseStatementBlock(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, boolean loop) throws ParseException {
private Block parseStatementBlock(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, boolean loop)
throws ParseException {
if(tokens.get().getType().equals(Token.Type.BLOCK_BEGIN)) {
ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_BEGIN);
Block block = parseBlock(tokens, variableMap, loop);
@@ -164,7 +164,7 @@ public class Parser {
return block;
}
}
private ForKeyword parseForLoop(Tokenizer tokens, Map<String, Returnable.ReturnType> old, Position start) throws ParseException {
Map<String, Returnable.ReturnType> variableMap = new HashMap<>(old); // New scope
Token f = tokens.get();
@@ -181,19 +181,21 @@ public class Parser {
Returnable<?> conditional = parseExpression(tokens, true, variableMap);
ParserUtil.checkReturnType(conditional, Returnable.ReturnType.BOOLEAN);
ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
Item<?> incrementer;
Token token = tokens.get();
if(variableMap.containsKey(token.getContent())) { // Assume variable assignment
incrementer = parseAssignment(tokens, variableMap);
} else incrementer = parseFunction(tokens, true, variableMap);
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
return new ForKeyword(parseStatementBlock(tokens, variableMap, true), initializer, (Returnable<Boolean>) conditional, incrementer, start);
return new ForKeyword(parseStatementBlock(tokens, variableMap, true), initializer, (Returnable<Boolean>) conditional, incrementer,
start);
}
private Returnable<?> parseExpression(Tokenizer tokens, boolean full, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
private Returnable<?> parseExpression(Tokenizer tokens, boolean full, Map<String, Returnable.ReturnType> variableMap)
throws ParseException {
boolean booleanInverted = false; // Check for boolean not operator
boolean negate = false;
if(tokens.get().getType().equals(Token.Type.BOOLEAN_NOT)) {
@@ -203,11 +205,11 @@ public class Parser {
negate = true;
tokens.consume();
}
Token id = tokens.get();
ParserUtil.checkType(id, Token.Type.IDENTIFIER, Token.Type.BOOLEAN, Token.Type.STRING, Token.Type.NUMBER, Token.Type.GROUP_BEGIN);
Returnable<?> expression;
if(id.isConstant()) {
expression = parseConstantExpression(tokens);
@@ -221,7 +223,7 @@ public class Parser {
expression = new Getter(id.getContent(), id.getPosition(), variableMap.get(id.getContent()));
} else throw new ParseException("Unexpected token \" " + id.getContent() + "\"", id.getPosition());
}
if(booleanInverted) { // Invert operation if boolean not detected
ParserUtil.checkReturnType(expression, Returnable.ReturnType.BOOLEAN);
expression = new BooleanNotOperation((Returnable<Boolean>) expression, expression.getPosition());
@@ -229,13 +231,13 @@ public class Parser {
ParserUtil.checkReturnType(expression, Returnable.ReturnType.NUMBER);
expression = new NegationOperation((Returnable<Number>) expression, expression.getPosition());
}
if(full && tokens.get().isBinaryOperator()) { // Parse binary operations
return parseBinaryOperation(expression, tokens, variableMap);
}
return expression;
}
private ConstantExpression<?> parseConstantExpression(Tokenizer tokens) throws ParseException {
Token constantToken = tokens.consume();
Position position = constantToken.getPosition();
@@ -248,24 +250,25 @@ public class Parser {
case BOOLEAN:
return new BooleanConstant(Boolean.parseBoolean(constantToken.getContent()), position);
default:
throw new UnsupportedOperationException("Unsupported constant token: " + constantToken.getType() + " at position: " + position);
throw new UnsupportedOperationException(
"Unsupported constant token: " + constantToken.getType() + " at position: " + position);
}
}
private Returnable<?> parseGroup(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN);
Returnable<?> expression = parseExpression(tokens, true, variableMap); // Parse inside of group as a separate expression
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
return expression;
}
private BinaryOperation<?, ?> parseBinaryOperation(Returnable<?> left, Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
private BinaryOperation<?, ?> parseBinaryOperation(Returnable<?> left, Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap)
throws ParseException {
Token binaryOperator = tokens.consume();
ParserUtil.checkBinaryOperator(binaryOperator);
Returnable<?> right = parseExpression(tokens, false, variableMap);
Token other = tokens.get();
if(ParserUtil.hasPrecedence(binaryOperator.getType(), other.getType())) {
return assemble(left, parseBinaryOperation(right, tokens, variableMap), binaryOperator);
@@ -274,7 +277,7 @@ public class Parser {
}
return assemble(left, right, binaryOperator);
}
private BinaryOperation<?, ?> assemble(Returnable<?> left, Returnable<?> right, Token binaryOperator) throws ParseException {
if(binaryOperator.isStrictNumericOperator())
ParserUtil.checkArithmeticOperation(left, right, binaryOperator); // Numeric type checking
@@ -300,7 +303,8 @@ public class Parser {
case LESS_THAN_OPERATOR:
return new LessThanStatement((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
case GREATER_THAN_OR_EQUALS_OPERATOR:
return new GreaterOrEqualsThanStatement((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
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:
@@ -313,35 +317,37 @@ public class Parser {
throw new UnsupportedOperationException("Unsupported binary operator: " + binaryOperator.getType());
}
}
private Declaration<?> parseVariableDeclaration(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
private Declaration<?> parseVariableDeclaration(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap)
throws ParseException {
Token type = tokens.consume();
ParserUtil.checkType(type, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE);
Returnable.ReturnType returnType = ParserUtil.getVariableReturnType(type);
ParserUtil.checkVarType(type, returnType); // Check for type mismatch
Token identifier = tokens.consume();
ParserUtil.checkType(identifier, Token.Type.IDENTIFIER);
if(functions.containsKey(identifier.getContent()) || variableMap.containsKey(identifier.getContent()))
throw new ParseException(identifier.getContent() + " is already defined in this scope", identifier.getPosition());
ParserUtil.checkType(tokens.consume(), Token.Type.ASSIGNMENT);
Returnable<?> value = parseExpression(tokens, true, variableMap);
ParserUtil.checkReturnType(value, returnType);
variableMap.put(identifier.getContent(), returnType);
return new Declaration<>(tokens.get().getPosition(), identifier.getContent(), value, returnType);
}
private Block parseBlock(Tokenizer tokens, Map<String, Returnable.ReturnType> superVars, boolean loop) throws ParseException {
List<Item<?>> parsedItems = new ArrayList<>();
Map<String, Returnable.ReturnType> parsedVariables = new HashMap<>(superVars); // New hashmap as to not mutate parent scope's declarations.
Map<String, Returnable.ReturnType> parsedVariables = new HashMap<>(
superVars); // New hashmap as to not mutate parent scope's declarations.
Token first = tokens.get();
while(tokens.hasNext()) {
Token token = tokens.get();
if(token.getType().equals(Token.Type.BLOCK_END)) break; // Stop parsing at block end.
@@ -353,14 +359,16 @@ public class Parser {
}
return new Block(parsedItems, first.getPosition());
}
private Item<?> parseItem(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, boolean loop) throws ParseException {
Token token = tokens.get();
if(loop) ParserUtil.checkType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP,
Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.RETURN, Token.Type.BREAK, Token.Type.CONTINUE, Token.Type.FAIL);
Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE,
Token.Type.RETURN, Token.Type.BREAK, Token.Type.CONTINUE, Token.Type.FAIL);
else ParserUtil.checkType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP,
Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.RETURN, Token.Type.FAIL);
Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.RETURN,
Token.Type.FAIL);
if(token.isLoopLike()) { // Parse loop-like tokens (if, while, etc)
return parseLoopLike(tokens, variableMap, loop);
} else if(token.isIdentifier()) { // Parse identifiers
@@ -368,71 +376,76 @@ public class Parser {
return parseAssignment(tokens, variableMap);
} else return parseFunction(tokens, true, variableMap);
} else if(token.isVariableDeclaration()) {
return parseVariableDeclaration(tokens, variableMap);
} else if(token.getType().equals(Token.Type.RETURN)) return new ReturnKeyword(tokens.consume().getPosition());
else if(token.getType().equals(Token.Type.BREAK)) return new BreakKeyword(tokens.consume().getPosition());
else if(token.getType().equals(Token.Type.CONTINUE)) return new ContinueKeyword(tokens.consume().getPosition());
else if(token.getType().equals(Token.Type.FAIL)) return new FailKeyword(tokens.consume().getPosition());
else throw new UnsupportedOperationException("Unexpected token " + token.getType() + ": " + token.getPosition());
}
private Assignment<?> parseAssignment(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
Token identifier = tokens.consume();
ParserUtil.checkType(identifier, Token.Type.IDENTIFIER);
ParserUtil.checkType(tokens.consume(), Token.Type.ASSIGNMENT);
Returnable<?> value = parseExpression(tokens, true, variableMap);
ParserUtil.checkReturnType(value, variableMap.get(identifier.getContent()));
return new Assignment<>(value, identifier.getContent(), identifier.getPosition());
}
private Function<?> parseFunction(Tokenizer tokens, boolean fullStatement, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
private Function<?> parseFunction(Tokenizer tokens, boolean fullStatement, Map<String, Returnable.ReturnType> variableMap)
throws ParseException {
Token identifier = tokens.consume();
ParserUtil.checkType(identifier, Token.Type.IDENTIFIER); // First token must be identifier
if(!functions.containsKey(identifier.getContent()))
throw new ParseException("No such function \"" + identifier.getContent() + "\"", identifier.getPosition());
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN); // Second is body begin
List<Returnable<?>> args = getArgs(tokens, variableMap); // Extract arguments, consume the rest.
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); // Remove body end
if(fullStatement) ParserUtil.checkType(tokens.get(), Token.Type.STATEMENT_END);
if(ignoredFunctions.contains(identifier.getContent())) {
return Function.NULL;
}
if(functions.containsKey(identifier.getContent())) {
FunctionBuilder<?> builder = functions.get(identifier.getContent());
if(builder.argNumber() != -1 && args.size() != builder.argNumber())
throw new ParseException("Expected " + builder.argNumber() + " arguments, found " + args.size(), identifier.getPosition());
for(int i = 0; i < args.size(); i++) {
Returnable<?> argument = args.get(i);
if(builder.getArgument(i) == null)
throw new ParseException("Unexpected argument at position " + i + " in function " + identifier.getContent(), identifier.getPosition());
throw new ParseException("Unexpected argument at position " + i + " in function " + identifier.getContent(),
identifier.getPosition());
ParserUtil.checkReturnType(argument, builder.getArgument(i));
}
return builder.build(args, identifier.getPosition());
}
throw new UnsupportedOperationException("Unsupported function: " + identifier.getContent());
}
public String getID() {
return id;
}
private List<Returnable<?>> getArgs(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
List<Returnable<?>> args = new ArrayList<>();
while(!tokens.get().getType().equals(Token.Type.GROUP_END)) {
args.add(parseExpression(tokens, true, variableMap));
ParserUtil.checkType(tokens.get(), Token.Type.SEPARATOR, Token.Type.GROUP_END);

View File

@@ -1,83 +1,94 @@
package com.dfsek.terra.addons.terrascript.parser;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Token;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Token;
public class ParserUtil {
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> 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> 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);
static { // Setup precedence
Map<Token.Type, Boolean> add = new HashMap<>(); // Addition/subtraction before Multiplication/division.
add.put(Token.Type.MULTIPLICATION_OPERATOR, true);
add.put(Token.Type.DIVISION_OPERATOR, true);
PRECEDENCE.put(Token.Type.ADDITION_OPERATOR, add);
PRECEDENCE.put(Token.Type.SUBTRACTION_OPERATOR, add);
Map<Token.Type, Boolean> numericBoolean = new HashMap<>();
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 {
for(Token.Type type : expected) if(token.getType().equals(type)) return;
throw new ParseException("Expected " + Arrays.toString(expected) + " but found " + token.getType(), token.getPosition());
}
public static void checkReturnType(Returnable<?> returnable, Returnable.ReturnType... types) throws ParseException {
for(Returnable.ReturnType type : types) if(returnable.returnType().equals(type)) return;
throw new ParseException("Expected " + Arrays.toString(types) + " but found " + returnable.returnType(), returnable.getPosition());
}
public static void checkArithmeticOperation(Returnable<?> left, Returnable<?> right, Token operation) throws ParseException {
if(!left.returnType().equals(Returnable.ReturnType.NUMBER) || !right.returnType().equals(Returnable.ReturnType.NUMBER)) {
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());
}
}
public static void checkBooleanOperation(Returnable<?> left, Returnable<?> right, Token operation) throws ParseException {
if(!left.returnType().equals(Returnable.ReturnType.BOOLEAN) || !right.returnType().equals(Returnable.ReturnType.BOOLEAN)) {
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());
}
}
public static 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());
}
/**
* Checks if token is a binary operator
*
* @param token Token to check
*
* @throws ParseException If token isn't a binary operator
*/
public static void checkBinaryOperator(Token token) throws ParseException {
if(!token.isBinaryOperator())
throw new ParseException("Expected binary operator, found " + token.getType(), token.getPosition());
}
public static Returnable.ReturnType getVariableReturnType(Token varToken) throws ParseException {
switch(varToken.getType()) {
case NUMBER_VARIABLE:
@@ -87,10 +98,11 @@ public class ParserUtil {
case BOOLEAN_VARIABLE:
return Returnable.ReturnType.BOOLEAN;
default:
throw new ParseException("Unexpected token " + varToken.getType() + "; expected variable declaration", varToken.getPosition());
throw new ParseException("Unexpected token " + varToken.getType() + "; expected variable declaration",
varToken.getPosition());
}
}
public static boolean hasPrecedence(Token.Type first, Token.Type second) {
if(!PRECEDENCE.containsKey(first)) return false;
Map<Token.Type, Boolean> pre = PRECEDENCE.get(first);

View File

@@ -2,25 +2,26 @@ package com.dfsek.terra.addons.terrascript.parser.exceptions;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class ParseException extends Exception {
private static final long serialVersionUID = 6744390543046766386L;
private final Position position;
public ParseException(String message, Position position) {
super(message);
this.position = position;
}
public ParseException(String message, Position position, Throwable cause) {
super(message, cause);
this.position = position;
}
@Override
public String getMessage() {
return super.getMessage() + ": " + position;
}
public Position getPosition() {
return position;
}

View File

@@ -1,29 +1,26 @@
package com.dfsek.terra.addons.terrascript.parser.lang;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class Block implements Item<Block.ReturnInfo<?>> {
private final List<Item<?>> items;
private final Position position;
public Block(List<Item<?>> items, Position position) {
this.items = items;
this.position = position;
}
public List<Item<?>> getItems() {
return items;
}
public ReturnInfo<?> apply(ImplementationArguments implementationArguments) {
return apply(implementationArguments, new HashMap<>());
}
@Override
public ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
Map<String, Variable<?>> scope = new HashMap<>(variableMap);
@@ -36,39 +33,48 @@ public class Block implements Item<Block.ReturnInfo<?>> {
}
return new ReturnInfo<>(ReturnLevel.NONE, null);
}
@Override
public Position getPosition() {
return position;
}
public List<Item<?>> getItems() {
return items;
}
public enum ReturnLevel {
NONE(false), BREAK(false), CONTINUE(false), RETURN(true), FAIL(true);
NONE(false),
BREAK(false),
CONTINUE(false),
RETURN(true),
FAIL(true);
private final boolean returnFast;
ReturnLevel(boolean returnFast) {
this.returnFast = returnFast;
}
public boolean isReturnFast() {
return returnFast;
}
}
public static class ReturnInfo<T> {
private final ReturnLevel level;
private final T data;
public ReturnInfo(ReturnLevel level, T data) {
this.level = level;
this.data = data;
}
public ReturnLevel getLevel() {
return level;
}
public T getData() {
return data;
}

View File

@@ -1,12 +1,13 @@
package com.dfsek.terra.addons.terrascript.parser.lang;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public interface Item<T> {
T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap);
Position getPosition();
}

View File

@@ -2,16 +2,20 @@ package com.dfsek.terra.addons.terrascript.parser.lang;
public interface Returnable<T> extends Item<T> {
ReturnType returnType();
enum ReturnType {
NUMBER(true), STRING(true), BOOLEAN(false), VOID(false), OBJECT(false);
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;
}

View File

@@ -2,11 +2,12 @@ package com.dfsek.terra.addons.terrascript.parser.lang.constants;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class BooleanConstant extends ConstantExpression<Boolean> {
public BooleanConstant(Boolean constant, Position position) {
super(constant, position);
}
@Override
public ReturnType returnType() {
return ReturnType.BOOLEAN;

View File

@@ -1,31 +1,32 @@
package com.dfsek.terra.addons.terrascript.parser.lang.constants;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public abstract class ConstantExpression<T> implements Returnable<T> {
private final T constant;
private final Position position;
public ConstantExpression(T constant, Position position) {
this.constant = constant;
this.position = position;
}
@Override
public T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return constant;
}
@Override
public Position getPosition() {
return position;
}
public T getConstant() {
return constant;
}

View File

@@ -3,11 +3,12 @@ package com.dfsek.terra.addons.terrascript.parser.lang.constants;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class NumericConstant extends ConstantExpression<Number> {
public NumericConstant(Number constant, Position position) {
super(constant, position);
}
@Override
public Returnable.ReturnType returnType() {
return Returnable.ReturnType.NUMBER;

View File

@@ -3,11 +3,12 @@ package com.dfsek.terra.addons.terrascript.parser.lang.constants;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class StringConstant extends ConstantExpression<String> {
public StringConstant(String constant, Position position) {
super(constant, position);
}
@Override
public Returnable.ReturnType returnType() {
return Returnable.ReturnType.STRING;

View File

@@ -1,11 +1,12 @@
package com.dfsek.terra.addons.terrascript.parser.lang.functions;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public interface Function<T> extends Returnable<T> {
Function<?> NULL = new Function<Object>() {
@@ -13,12 +14,12 @@ public interface Function<T> extends Returnable<T> {
public ReturnType returnType() {
return null;
}
@Override
public Object apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return null;
}
@Override
public Position getPosition() {
return null;

View File

@@ -1,15 +1,16 @@
package com.dfsek.terra.addons.terrascript.parser.lang.functions;
import java.util.List;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.List;
public interface FunctionBuilder<T extends Function<?>> {
T build(List<Returnable<?>> argumentList, Position position) throws ParseException;
int argNumber();
Returnable.ReturnType getArgument(int position);
}

View File

@@ -1,30 +1,27 @@
package com.dfsek.terra.addons.terrascript.parser.lang.functions.def;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.Block;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Item;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FunctionBlock<T> implements Item<T> {
private final List<Item<?>> items;
private final Position position;
private final T defaultVal;
public FunctionBlock(List<Item<?>> items, T defaultVal, Position position) {
this.items = items;
this.position = position;
this.defaultVal = defaultVal;
}
public List<Item<?>> getItems() {
return items;
}
@SuppressWarnings("unchecked")
@Override
public synchronized T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
@@ -38,9 +35,13 @@ public class FunctionBlock<T> implements Item<T> {
}
return defaultVal;
}
@Override
public Position getPosition() {
return position;
}
public List<Item<?>> getItems() {
return items;
}
}

View File

@@ -1,30 +1,31 @@
package com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.Block;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Keyword;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public class BreakKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Position position;
public BreakKeyword(Position position) {
this.position = position;
}
@Override
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return new Block.ReturnInfo<>(Block.ReturnLevel.BREAK, null);
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;

View File

@@ -1,30 +1,31 @@
package com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.Block;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Keyword;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public class ContinueKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Position position;
public ContinueKeyword(Position position) {
this.position = position;
}
@Override
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return new Block.ReturnInfo<>(Block.ReturnLevel.CONTINUE, null);
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;

View File

@@ -1,30 +1,31 @@
package com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.Block;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Keyword;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public class FailKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Position position;
public FailKeyword(Position position) {
this.position = position;
}
@Override
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return new Block.ReturnInfo<>(Block.ReturnLevel.FAIL, null);
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;

View File

@@ -1,30 +1,31 @@
package com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.Block;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Keyword;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public class ReturnKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Position position;
public ReturnKeyword(Position position) {
this.position = position;
}
@Override
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return new Block.ReturnInfo<>(Block.ReturnLevel.RETURN, null);
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;

View File

@@ -1,5 +1,7 @@
package com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.Block;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Item;
@@ -8,7 +10,6 @@ import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public class ForKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Block conditional;
@@ -16,7 +17,7 @@ public class ForKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Returnable<Boolean> statement;
private final Item<?> incrementer;
private final Position position;
public ForKeyword(Block conditional, Item<?> initializer, Returnable<Boolean> statement, Item<?> incrementer, Position position) {
this.conditional = conditional;
this.initializer = initializer;
@@ -24,22 +25,24 @@ public class ForKeyword implements Keyword<Block.ReturnInfo<?>> {
this.incrementer = incrementer;
this.position = position;
}
@Override
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
for(initializer.apply(implementationArguments, variableMap); statement.apply(implementationArguments, variableMap); incrementer.apply(implementationArguments, variableMap)) {
for(initializer.apply(implementationArguments, variableMap);
statement.apply(implementationArguments, variableMap);
incrementer.apply(implementationArguments, variableMap)) {
Block.ReturnInfo<?> level = conditional.apply(implementationArguments, variableMap);
if(level.getLevel().equals(Block.ReturnLevel.BREAK)) break;
if(level.getLevel().isReturnFast()) return level;
}
return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null);
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;

View File

@@ -1,15 +1,17 @@
package com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.Block;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Keyword;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
public class IfKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Block conditional;
@@ -17,15 +19,16 @@ public class IfKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Position position;
private final List<Pair<Returnable<Boolean>, Block>> elseIf;
private final Block elseBlock;
public IfKeyword(Block conditional, Returnable<Boolean> statement, List<Pair<Returnable<Boolean>, Block>> elseIf, @Nullable Block elseBlock, Position position) {
public IfKeyword(Block conditional, Returnable<Boolean> statement, List<Pair<Returnable<Boolean>, Block>> elseIf,
@Nullable Block elseBlock, Position position) {
this.conditional = conditional;
this.statement = statement;
this.position = position;
this.elseIf = elseIf;
this.elseBlock = elseBlock;
}
@Override
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
if(statement.apply(implementationArguments, variableMap)) return conditional.apply(implementationArguments, variableMap);
@@ -39,31 +42,31 @@ public class IfKeyword implements Keyword<Block.ReturnInfo<?>> {
}
return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null);
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;
}
public static class Pair<L, R> {
private final L left;
private final R right;
public Pair(L left, R right) {
this.left = left;
this.right = right;
}
public L getLeft() {
return left;
}
public R getRight() {
return right;
}

View File

@@ -1,5 +1,7 @@
package com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.Block;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Keyword;
@@ -7,19 +9,18 @@ import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public class WhileKeyword implements Keyword<Block.ReturnInfo<?>> {
private final Block conditional;
private final Returnable<Boolean> statement;
private final Position position;
public WhileKeyword(Block conditional, Returnable<Boolean> statement, Position position) {
this.conditional = conditional;
this.statement = statement;
this.position = position;
}
@Override
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
while(statement.apply(implementationArguments, variableMap)) {
@@ -29,12 +30,12 @@ public class WhileKeyword implements Keyword<Block.ReturnInfo<?>> {
}
return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null);
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;

View File

@@ -1,32 +1,33 @@
package com.dfsek.terra.addons.terrascript.parser.lang.operations;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public abstract class BinaryOperation<I, O> implements Returnable<O> {
private final Returnable<I> left;
private final Returnable<I> right;
private final Position start;
public BinaryOperation(Returnable<I> left, Returnable<I> right, Position start) {
this.left = left;
this.right = right;
this.start = start;
}
public abstract O apply(I left, I right);
@Override
public Position getPosition() {
return start;
}
@Override
public O apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return apply(left.apply(implementationArguments, variableMap), right.apply(implementationArguments, variableMap));
}
@Override
public Position getPosition() {
return start;
}
}

View File

@@ -3,16 +3,17 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.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

@@ -3,16 +3,17 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class BooleanNotOperation extends UnaryOperation<Boolean> {
public BooleanNotOperation(Returnable<Boolean> input, Position position) {
super(input, position);
}
@Override
public Boolean apply(Boolean input) {
return !input;
}
@Override
public ReturnType returnType() {
return ReturnType.BOOLEAN;

View File

@@ -3,16 +3,17 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.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

@@ -3,16 +3,17 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class ConcatenationOperation extends BinaryOperation<Object, Object> {
public ConcatenationOperation(Returnable<Object> left, Returnable<Object> right, Position position) {
super(left, right, position);
}
@Override
public String apply(Object left, Object right) {
return left.toString() + right.toString();
}
@Override
public Returnable.ReturnType returnType() {
return Returnable.ReturnType.STRING;

View File

@@ -3,16 +3,17 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class DivisionOperation extends BinaryOperation<Number, 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 Returnable.ReturnType returnType() {
return Returnable.ReturnType.NUMBER;

View File

@@ -3,16 +3,17 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class ModuloOperation extends BinaryOperation<Number, Number> {
public ModuloOperation(Returnable<Number> left, Returnable<Number> right, Position start) {
super(left, right, start);
}
@Override
public Number apply(Number left, Number right) {
return left.doubleValue() % right.doubleValue();
}
@Override
public ReturnType returnType() {
return ReturnType.NUMBER;

View File

@@ -3,16 +3,17 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class MultiplicationOperation extends BinaryOperation<Number, Number> {
public MultiplicationOperation(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;

View File

@@ -3,16 +3,17 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.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;

View File

@@ -3,16 +3,17 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class NumberAdditionOperation extends BinaryOperation<Number, Number> {
public NumberAdditionOperation(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;

View File

@@ -3,16 +3,17 @@ package com.dfsek.terra.addons.terrascript.parser.lang.operations;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class SubtractionOperation extends BinaryOperation<Number, 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;

View File

@@ -1,28 +1,29 @@
package com.dfsek.terra.addons.terrascript.parser.lang.operations;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public abstract class UnaryOperation<T> implements Returnable<T> {
private final Returnable<T> input;
private final Position position;
public UnaryOperation(Returnable<T> input, Position position) {
this.input = input;
this.position = position;
}
public abstract T apply(T input);
@Override
public T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return apply(input.apply(implementationArguments, variableMap));
}
@Override
public Position getPosition() {
return position;

View File

@@ -1,27 +1,29 @@
package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements;
import net.jafama.FastMath;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import net.jafama.FastMath;
public class EqualsStatement extends BinaryOperation<Object, Boolean> {
private static final double EPSILON = 0.000000001D;
public EqualsStatement(Returnable<Object> left, Returnable<Object> right, Position position) {
super(left, right, position);
}
@Override
public Boolean apply(Object left, Object right) {
if(left instanceof Number && right instanceof Number) {
return FastMath.abs(((Number) left).doubleValue() - ((Number) right).doubleValue()) <= EPSILON;
}
return left.equals(right);
}
@Override
public Returnable.ReturnType returnType() {
return Returnable.ReturnType.BOOLEAN;

View File

@@ -4,17 +4,18 @@ import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class GreaterOrEqualsThanStatement extends BinaryOperation<Number, Boolean> {
public GreaterOrEqualsThanStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
super(left, right, position);
}
@Override
public Boolean apply(Number left, Number right) {
return left.doubleValue() >= right.doubleValue();
}
@Override
public Returnable.ReturnType returnType() {
return Returnable.ReturnType.BOOLEAN;

View File

@@ -4,17 +4,18 @@ import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class GreaterThanStatement extends BinaryOperation<Number, Boolean> {
public GreaterThanStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
super(left, right, position);
}
@Override
public Boolean apply(Number left, Number right) {
return left.doubleValue() > right.doubleValue();
}
@Override
public Returnable.ReturnType returnType() {
return Returnable.ReturnType.BOOLEAN;

View File

@@ -4,17 +4,18 @@ import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class LessThanOrEqualsStatement extends BinaryOperation<Number, Boolean> {
public LessThanOrEqualsStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
super(left, right, position);
}
@Override
public Boolean apply(Number left, Number right) {
return left.doubleValue() <= right.doubleValue();
}
@Override
public Returnable.ReturnType returnType() {
return Returnable.ReturnType.BOOLEAN;

View File

@@ -4,17 +4,18 @@ import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class LessThanStatement extends BinaryOperation<Number, Boolean> {
public LessThanStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
super(left, right, position);
}
@Override
public Boolean apply(Number left, Number right) {
return left.doubleValue() < right.doubleValue();
}
@Override
public Returnable.ReturnType returnType() {
return Returnable.ReturnType.BOOLEAN;

View File

@@ -4,17 +4,18 @@ import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class NotEqualsStatement extends BinaryOperation<Object, Boolean> {
public NotEqualsStatement(Returnable<Object> left, Returnable<Object> right, Position position) {
super(left, right, position);
}
@Override
public Boolean apply(Object left, Object right) {
return !left.equals(right);
}
@Override
public Returnable.ReturnType returnType() {
return Returnable.ReturnType.BOOLEAN;

View File

@@ -1,23 +1,24 @@
package com.dfsek.terra.addons.terrascript.parser.lang.variables;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Item;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public class Assignment<T> implements Item<T> {
private final Returnable<T> value;
private final Position position;
private final String identifier;
public Assignment(Returnable<T> value, String identifier, Position position) {
this.value = value;
this.identifier = identifier;
this.position = position;
}
@SuppressWarnings("unchecked")
@Override
public synchronized T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
@@ -25,7 +26,7 @@ public class Assignment<T> implements Item<T> {
((Variable<T>) variableMap.get(identifier)).setValue(val);
return val;
}
@Override
public Position getPosition() {
return position;

View File

@@ -3,30 +3,31 @@ package com.dfsek.terra.addons.terrascript.parser.lang.variables;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.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;

View File

@@ -1,18 +1,19 @@
package com.dfsek.terra.addons.terrascript.parser.lang.variables;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Item;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public class Declaration<T> implements Item<T> {
private final Position position;
private final String identifier;
private final Returnable<T> value;
private final Returnable.ReturnType type;
public Declaration(Position position, String identifier, Returnable<T> value, Returnable.ReturnType type) {
switch(type) {
case STRING:
@@ -27,7 +28,7 @@ public class Declaration<T> implements Item<T> {
this.value = value;
this.type = type;
}
@Override
public T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
T result = value.apply(implementationArguments, variableMap);
@@ -44,16 +45,16 @@ public class Declaration<T> implements Item<T> {
}
return result;
}
@Override
public Position getPosition() {
return position;
}
public Returnable.ReturnType getType() {
return type;
}
public String getIdentifier() {
return identifier;
}

View File

@@ -1,32 +1,33 @@
package com.dfsek.terra.addons.terrascript.parser.lang.variables;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public class Getter implements Returnable<Object> {
private final String identifier;
private final Position position;
private final ReturnType type;
public Getter(String identifier, Position position, ReturnType type) {
this.identifier = identifier;
this.position = position;
this.type = type;
}
@Override
public ReturnType returnType() {
return type;
}
@Override
public synchronized Object apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return variableMap.get(identifier).getValue();
}
@Override
public Position getPosition() {
return position;

View File

@@ -3,30 +3,31 @@ package com.dfsek.terra.addons.terrascript.parser.lang.variables;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.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;

View File

@@ -3,30 +3,31 @@ package com.dfsek.terra.addons.terrascript.parser.lang.variables;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.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;

View File

@@ -3,12 +3,13 @@ package com.dfsek.terra.addons.terrascript.parser.lang.variables;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public interface Variable<T> {
T getValue();
void setValue(T value);
Returnable.ReturnType getType();
Position getPosition();
}

View File

@@ -1,5 +1,16 @@
package com.dfsek.terra.addons.terrascript.script;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import net.jafama.FastMath;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import com.dfsek.terra.addons.terrascript.buffer.DirectBuffer;
import com.dfsek.terra.addons.terrascript.buffer.StructureBuffer;
import com.dfsek.terra.addons.terrascript.parser.Parser;
@@ -35,16 +46,7 @@ import com.dfsek.terra.api.structure.rotation.Rotation;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.Chunk;
import com.dfsek.terra.api.world.World;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import net.jafama.FastMath;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Random;
import java.util.concurrent.ExecutionException;
public class StructureScript implements Structure {
private final Block block;
@@ -52,17 +54,18 @@ public class StructureScript implements Structure {
private final Cache<Vector3, StructureBuffer> cache;
private final TerraPlugin main;
private String tempID;
public StructureScript(InputStream inputStream, TerraPlugin main, Registry<Structure> registry, Registry<LootTable> lootRegistry, Registry<FunctionBuilder<?>> functionRegistry) throws ParseException {
public StructureScript(InputStream inputStream, TerraPlugin main, Registry<Structure> registry, Registry<LootTable> lootRegistry,
Registry<FunctionBuilder<?>> functionRegistry) throws ParseException {
Parser parser;
try {
parser = new Parser(IOUtils.toString(inputStream, Charset.defaultCharset()));
} catch(IOException e) {
throw new RuntimeException(e);
}
functionRegistry.forEach(parser::registerFunction); // Register registry functions.
parser
.registerFunction("block", new BlockFunctionBuilder(main))
.registerFunction("debugBlock", new BlockFunctionBuilder(main))
@@ -79,14 +82,21 @@ public class StructureScript implements Structure {
.registerFunction("getBlock", new CheckBlockFunctionBuilder())
.registerFunction("state", new StateFunctionBuilder(main))
.registerFunction("setWaterlog", new UnaryBooleanFunctionBuilder((waterlog, args) -> args.setWaterlog(waterlog)))
.registerFunction("originX", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getX(), Returnable.ReturnType.NUMBER))
.registerFunction("originY", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getY(), Returnable.ReturnType.NUMBER))
.registerFunction("originZ", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getZ(), Returnable.ReturnType.NUMBER))
.registerFunction("rotation", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().toString(), Returnable.ReturnType.STRING))
.registerFunction("rotationDegrees", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().getDegrees(), Returnable.ReturnType.NUMBER))
.registerFunction("print", new UnaryStringFunctionBuilder(string -> main.getDebugLogger().info("[" + tempID + "] " + string)))
.registerFunction("originX", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getX(),
Returnable.ReturnType.NUMBER))
.registerFunction("originY", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getY(),
Returnable.ReturnType.NUMBER))
.registerFunction("originZ", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getZ(),
Returnable.ReturnType.NUMBER))
.registerFunction("rotation", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().toString(),
Returnable.ReturnType.STRING))
.registerFunction("rotationDegrees", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().getDegrees(),
Returnable.ReturnType.NUMBER))
.registerFunction("print",
new UnaryStringFunctionBuilder(string -> main.getDebugLogger().info("[" + tempID + "] " + string)))
.registerFunction("abs", new UnaryNumberFunctionBuilder(number -> FastMath.abs(number.doubleValue())))
.registerFunction("pow", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.pow(number.doubleValue(), number2.doubleValue())))
.registerFunction("pow", new BinaryNumberFunctionBuilder(
(number, number2) -> FastMath.pow(number.doubleValue(), number2.doubleValue())))
.registerFunction("sqrt", new UnaryNumberFunctionBuilder(number -> FastMath.sqrt(number.doubleValue())))
.registerFunction("floor", new UnaryNumberFunctionBuilder(number -> FastMath.floor(number.doubleValue())))
.registerFunction("ceil", new UnaryNumberFunctionBuilder(number -> FastMath.ceil(number.doubleValue())))
@@ -98,20 +108,22 @@ public class StructureScript implements Structure {
.registerFunction("asin", new UnaryNumberFunctionBuilder(number -> FastMath.asin(number.doubleValue())))
.registerFunction("acos", new UnaryNumberFunctionBuilder(number -> FastMath.acos(number.doubleValue())))
.registerFunction("atan", new UnaryNumberFunctionBuilder(number -> FastMath.atan(number.doubleValue())))
.registerFunction("max", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.max(number.doubleValue(), number2.doubleValue())))
.registerFunction("min", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.min(number.doubleValue(), number2.doubleValue())));
.registerFunction("max", new BinaryNumberFunctionBuilder(
(number, number2) -> FastMath.max(number.doubleValue(), number2.doubleValue())))
.registerFunction("min", new BinaryNumberFunctionBuilder(
(number, number2) -> FastMath.min(number.doubleValue(), number2.doubleValue())));
if(!main.getTerraConfig().isDebugScript()) {
parser.ignoreFunction("debugBlock");
}
block = parser.parse();
this.id = parser.getID();
tempID = id;
this.main = main;
this.cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getStructureCache()).build();
}
@Override
@SuppressWarnings("try")
public boolean generate(Vector3 location, World world, Chunk chunk, Random random, Rotation rotation) {
@@ -121,7 +133,24 @@ public class StructureScript implements Structure {
return buffer.succeeded();
}
}
@Override
@SuppressWarnings("try")
public boolean generate(Buffer buffer, World world, Random random, Rotation rotation, int recursions) {
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_recursive:" + id)) {
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, world, recursions));
}
}
@Override
@SuppressWarnings("try")
public boolean generate(Vector3 location, World world, Random random, Rotation rotation) {
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_direct:" + id)) {
DirectBuffer buffer = new DirectBuffer(location, world);
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, world, 0));
}
}
@SuppressWarnings("try")
public boolean test(Vector3 location, World world, Random random, Rotation rotation) {
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_test:" + id)) {
@@ -129,7 +158,7 @@ public class StructureScript implements Structure {
return buffer.succeeded();
}
}
private StructureBuffer computeBuffer(Vector3 location, World world, Random random, Rotation rotation) {
try {
return cache.get(location, () -> {
@@ -141,29 +170,7 @@ public class StructureScript implements Structure {
throw new RuntimeException(e);
}
}
@Override
@SuppressWarnings("try")
public boolean generate(Buffer buffer, World world, Random random, Rotation rotation, int recursions) {
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_recursive:" + id)) {
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, world, recursions));
}
}
@Override
@SuppressWarnings("try")
public boolean generate(Vector3 location, World world, Random random, Rotation rotation) {
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_direct:" + id)) {
DirectBuffer buffer = new DirectBuffer(location, world);
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, world, 0));
}
}
@Override
public String getID() {
return id;
}
private boolean applyBlock(TerraImplementationArguments arguments) {
try {
return block.apply(arguments).getLevel() != Block.ReturnLevel.FAIL;
@@ -173,4 +180,9 @@ public class StructureScript implements Structure {
return false;
}
}
@Override
public String getID() {
return id;
}
}

View File

@@ -1,11 +1,12 @@
package com.dfsek.terra.addons.terrascript.script;
import java.util.Random;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structure.buffer.Buffer;
import com.dfsek.terra.api.structure.rotation.Rotation;
import com.dfsek.terra.api.world.World;
import java.util.Random;
public class TerraImplementationArguments implements ImplementationArguments {
private final Buffer buffer;
@@ -14,7 +15,7 @@ public class TerraImplementationArguments implements ImplementationArguments {
private final World world;
private final int recursions;
private boolean waterlog = false;
public TerraImplementationArguments(Buffer buffer, Rotation rotation, Random random, World world, int recursions) {
this.buffer = buffer;
this.rotation = rotation;
@@ -22,31 +23,31 @@ public class TerraImplementationArguments implements ImplementationArguments {
this.world = world;
this.recursions = recursions;
}
public Buffer getBuffer() {
return buffer;
}
public int getRecursions() {
return recursions;
}
public Random getRandom() {
return random;
}
public Rotation getRotation() {
return rotation;
}
public boolean isWaterlog() {
return waterlog;
}
public void setWaterlog(boolean waterlog) {
this.waterlog = waterlog;
}
public World getWorld() {
return world;
}

View File

@@ -1,5 +1,9 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
@@ -7,18 +11,15 @@ import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
public class BinaryNumberFunctionBuilder implements FunctionBuilder<Function<Number>> {
private final BiFunction<Number, Number, Number> function;
public BinaryNumberFunctionBuilder(BiFunction<Number, Number, Number> function) {
this.function = function;
}
@Override
public Function<Number> build(List<Returnable<?>> argumentList, Position position) {
return new Function<Number>() {
@@ -26,25 +27,26 @@ public class BinaryNumberFunctionBuilder implements FunctionBuilder<Function<Num
public ReturnType returnType() {
return ReturnType.NUMBER;
}
@SuppressWarnings("unchecked")
@Override
public Number apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return function.apply(((Returnable<Number>) argumentList.get(0)).apply(implementationArguments, variableMap), ((Returnable<Number>) argumentList.get(1)).apply(implementationArguments, variableMap));
return function.apply(((Returnable<Number>) argumentList.get(0)).apply(implementationArguments, variableMap),
((Returnable<Number>) argumentList.get(1)).apply(implementationArguments, variableMap));
}
@Override
public Position getPosition() {
return position;
}
};
}
@Override
public int argNumber() {
return 2;
}
@Override
public Returnable.ReturnType getArgument(int position) {
if(position == 0 || position == 1) return Returnable.ReturnType.NUMBER;

View File

@@ -1,31 +1,33 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.functions.BiomeFunction;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import com.dfsek.terra.api.TerraPlugin;
import java.util.List;
public class BiomeFunctionBuilder implements FunctionBuilder<BiomeFunction> {
private final TerraPlugin main;
public BiomeFunctionBuilder(TerraPlugin main) {
this.main = main;
}
@SuppressWarnings("unchecked")
@Override
public BiomeFunction build(List<Returnable<?>> argumentList, Position position) {
return new BiomeFunction(main, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), position);
return new BiomeFunction(main, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
(Returnable<Number>) argumentList.get(2), position);
}
@Override
public int argNumber() {
return 3;
}
@Override
public Returnable.ReturnType getArgument(int position) {
switch(position) {

View File

@@ -1,5 +1,7 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.constants.BooleanConstant;
@@ -9,15 +11,14 @@ import com.dfsek.terra.addons.terrascript.script.functions.BlockFunction;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import com.dfsek.terra.api.TerraPlugin;
import java.util.List;
public class BlockFunctionBuilder implements FunctionBuilder<BlockFunction> {
private final TerraPlugin main;
public BlockFunctionBuilder(TerraPlugin main) {
this.main = main;
}
@SuppressWarnings("unchecked")
@Override
public BlockFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
@@ -25,16 +26,20 @@ public class BlockFunctionBuilder implements FunctionBuilder<BlockFunction> {
Returnable<Boolean> booleanReturnable = new BooleanConstant(true, position);
if(argumentList.size() == 5) booleanReturnable = (Returnable<Boolean>) argumentList.get(4);
if(argumentList.get(3) instanceof StringConstant) {
return new BlockFunction.Constant((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (StringConstant) argumentList.get(3), booleanReturnable, main, position);
return new BlockFunction.Constant((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
(Returnable<Number>) argumentList.get(2), (StringConstant) argumentList.get(3),
booleanReturnable, main, position);
}
return new BlockFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), booleanReturnable, main, position);
return new BlockFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), booleanReturnable,
main, position);
}
@Override
public int argNumber() {
return -1;
}
@Override
public Returnable.ReturnType getArgument(int position) {
switch(position) {

View File

@@ -1,24 +1,26 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.functions.CheckBlockFunction;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.List;
public class CheckBlockFunctionBuilder implements FunctionBuilder<CheckBlockFunction> {
@SuppressWarnings("unchecked")
@Override
public CheckBlockFunction build(List<Returnable<?>> argumentList, Position position) {
return new CheckBlockFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), position);
return new CheckBlockFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
(Returnable<Number>) argumentList.get(2), position);
}
@Override
public int argNumber() {
return 3;
}
@Override
public Returnable.ReturnType getArgument(int position) {
switch(position) {

View File

@@ -1,5 +1,7 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
@@ -7,26 +9,26 @@ import com.dfsek.terra.addons.terrascript.script.functions.CheckFunction;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import com.dfsek.terra.api.TerraPlugin;
import java.util.List;
public class CheckFunctionBuilder implements FunctionBuilder<CheckFunction> {
private final TerraPlugin main;
public CheckFunctionBuilder(TerraPlugin main) {
this.main = main;
}
@SuppressWarnings("unchecked")
@Override
public CheckFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
return new CheckFunction(main, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), position);
return new CheckFunction(main, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
(Returnable<Number>) argumentList.get(2), position);
}
@Override
public int argNumber() {
return 3;
}
@Override
public Returnable.ReturnType getArgument(int position) {
switch(position) {

View File

@@ -1,5 +1,7 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
@@ -7,26 +9,26 @@ import com.dfsek.terra.addons.terrascript.script.functions.EntityFunction;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import com.dfsek.terra.api.TerraPlugin;
import java.util.List;
public class EntityFunctionBuilder implements FunctionBuilder<EntityFunction> {
private final TerraPlugin main;
public EntityFunctionBuilder(TerraPlugin main) {
this.main = main;
}
@SuppressWarnings("unchecked")
@Override
public EntityFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
return new EntityFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position);
return new EntityFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position);
}
@Override
public int argNumber() {
return 4;
}
@Override
public Returnable.ReturnType getArgument(int position) {
switch(position) {

View File

@@ -1,28 +1,30 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.functions.GetMarkFunction;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.List;
public class GetMarkFunctionBuilder implements FunctionBuilder<GetMarkFunction> {
public GetMarkFunctionBuilder() {
}
@SuppressWarnings("unchecked")
@Override
public GetMarkFunction build(List<Returnable<?>> argumentList, Position position) {
return new GetMarkFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), position);
return new GetMarkFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
(Returnable<Number>) argumentList.get(2), position);
}
@Override
public int argNumber() {
return 3;
}
@Override
public Returnable.ReturnType getArgument(int position) {
switch(position) {

View File

@@ -1,5 +1,7 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.StructureScript;
@@ -9,30 +11,30 @@ import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.structure.LootTable;
import java.util.List;
public class LootFunctionBuilder implements FunctionBuilder<LootFunction> {
private final TerraPlugin main;
private final Registry<LootTable> registry;
private final StructureScript script;
public LootFunctionBuilder(TerraPlugin main, Registry<LootTable> registry, StructureScript script) {
this.main = main;
this.registry = registry;
this.script = script;
}
@SuppressWarnings("unchecked")
@Override
public LootFunction build(List<Returnable<?>> argumentList, Position position) {
return new LootFunction(registry, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position, script);
return new LootFunction(registry, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position, script);
}
@Override
public int argNumber() {
return 4;
}
@Override
public Returnable.ReturnType getArgument(int position) {
switch(position) {

View File

@@ -1,5 +1,7 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
@@ -7,26 +9,26 @@ import com.dfsek.terra.addons.terrascript.script.functions.PullFunction;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import com.dfsek.terra.api.TerraPlugin;
import java.util.List;
public class PullFunctionBuilder implements FunctionBuilder<PullFunction> {
private final TerraPlugin main;
public PullFunctionBuilder(TerraPlugin main) {
this.main = main;
}
@SuppressWarnings("unchecked")
@Override
public PullFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
return new PullFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position);
return new PullFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position);
}
@Override
public int argNumber() {
return 4;
}
@Override
public Returnable.ReturnType getArgument(int position) {
switch(position) {

View File

@@ -1,12 +1,13 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.functions.RandomFunction;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.List;
public class RandomFunctionBuilder implements FunctionBuilder<RandomFunction> {
@SuppressWarnings("unchecked")
@@ -14,12 +15,12 @@ public class RandomFunctionBuilder implements FunctionBuilder<RandomFunction> {
public RandomFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
return new RandomFunction((Returnable<Number>) argumentList.get(0), position);
}
@Override
public int argNumber() {
return 1;
}
@Override
public Returnable.ReturnType getArgument(int position) {
if(position == 0) return Returnable.ReturnType.NUMBER;

View File

@@ -1,24 +1,25 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.functions.RecursionsFunction;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.List;
public class RecursionsFunctionBuilder implements FunctionBuilder<RecursionsFunction> {
@Override
public RecursionsFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
return new RecursionsFunction(position);
}
@Override
public int argNumber() {
return 0;
}
@Override
public Returnable.ReturnType getArgument(int position) {
return null;

View File

@@ -1,29 +1,31 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.functions.SetMarkFunction;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.List;
public class SetMarkFunctionBuilder implements FunctionBuilder<SetMarkFunction> {
public SetMarkFunctionBuilder() {
}
@SuppressWarnings("unchecked")
@Override
public SetMarkFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
return new SetMarkFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), position);
return new SetMarkFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), position);
}
@Override
public int argNumber() {
return 4;
}
@Override
public Returnable.ReturnType getArgument(int position) {
switch(position) {

View File

@@ -1,5 +1,7 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
@@ -7,27 +9,27 @@ import com.dfsek.terra.addons.terrascript.script.functions.StateFunction;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import com.dfsek.terra.api.TerraPlugin;
import java.util.List;
public class StateFunctionBuilder implements FunctionBuilder<StateFunction> {
private final TerraPlugin main;
public StateFunctionBuilder(TerraPlugin main) {
this.main = main;
}
@SuppressWarnings("unchecked")
@Override
public StateFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
if(argumentList.size() < 4) throw new ParseException("Expected data", position);
return new StateFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position);
return new StateFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position);
}
@Override
public int argNumber() {
return 4;
}
@Override
public Returnable.ReturnType getArgument(int position) {
switch(position) {

View File

@@ -1,5 +1,8 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import java.util.stream.Collectors;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
@@ -9,32 +12,32 @@ import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.structure.Structure;
import java.util.List;
import java.util.stream.Collectors;
public class StructureFunctionBuilder implements FunctionBuilder<StructureFunction> {
private final Registry<Structure> registry;
private final TerraPlugin main;
public StructureFunctionBuilder(Registry<Structure> registry, TerraPlugin main) {
this.registry = registry;
this.main = main;
}
@SuppressWarnings("unchecked")
@Override
public StructureFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
if(argumentList.size() < 5) throw new ParseException("Expected rotations", position);
return new StructureFunction((Returnable<Number>) argumentList.remove(0), (Returnable<Number>) argumentList.remove(0), (Returnable<Number>) argumentList.remove(0), (Returnable<String>) argumentList.remove(0),
argumentList.stream().map(item -> ((Returnable<String>) item)).collect(Collectors.toList()), registry, position, main);
return new StructureFunction((Returnable<Number>) argumentList.remove(0), (Returnable<Number>) argumentList.remove(0),
(Returnable<Number>) argumentList.remove(0), (Returnable<String>) argumentList.remove(0),
argumentList.stream().map(item -> ((Returnable<String>) item)).collect(Collectors.toList()), registry,
position, main);
}
@Override
public int argNumber() {
return -1;
}
@Override
public Returnable.ReturnType getArgument(int position) {
switch(position) {

View File

@@ -1,5 +1,9 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
@@ -8,18 +12,15 @@ import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
public class UnaryBooleanFunctionBuilder implements FunctionBuilder<Function<Void>> {
private final BiConsumer<Boolean, TerraImplementationArguments> function;
public UnaryBooleanFunctionBuilder(BiConsumer<Boolean, TerraImplementationArguments> function) {
this.function = function;
}
@Override
public Function<Void> build(List<Returnable<?>> argumentList, Position position) {
return new Function<Void>() {
@@ -27,26 +28,27 @@ public class UnaryBooleanFunctionBuilder implements FunctionBuilder<Function<Voi
public ReturnType returnType() {
return ReturnType.VOID;
}
@SuppressWarnings("unchecked")
@Override
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
function.accept(((Returnable<Boolean>) argumentList.get(0)).apply(implementationArguments, variableMap), (TerraImplementationArguments) implementationArguments);
function.accept(((Returnable<Boolean>) argumentList.get(0)).apply(implementationArguments, variableMap),
(TerraImplementationArguments) implementationArguments);
return null;
}
@Override
public Position getPosition() {
return position;
}
};
}
@Override
public int argNumber() {
return 1;
}
@Override
public Returnable.ReturnType getArgument(int position) {
if(position == 0) return Returnable.ReturnType.BOOLEAN;

View File

@@ -1,5 +1,8 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
@@ -7,17 +10,15 @@ import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.List;
import java.util.Map;
public class UnaryNumberFunctionBuilder implements FunctionBuilder<Function<Number>> {
private final java.util.function.Function<Number, Number> function;
public UnaryNumberFunctionBuilder(java.util.function.Function<Number, Number> function) {
this.function = function;
}
@Override
public Function<Number> build(List<Returnable<?>> argumentList, Position position) {
return new Function<Number>() {
@@ -25,25 +26,25 @@ public class UnaryNumberFunctionBuilder implements FunctionBuilder<Function<Numb
public ReturnType returnType() {
return ReturnType.NUMBER;
}
@SuppressWarnings("unchecked")
@Override
public Number apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return function.apply(((Returnable<Number>) argumentList.get(0)).apply(implementationArguments, variableMap));
}
@Override
public Position getPosition() {
return position;
}
};
}
@Override
public int argNumber() {
return 1;
}
@Override
public Returnable.ReturnType getArgument(int position) {
if(position == 0) return Returnable.ReturnType.NUMBER;

View File

@@ -1,5 +1,8 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
@@ -7,17 +10,15 @@ import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.List;
import java.util.Map;
public class UnaryStringFunctionBuilder implements FunctionBuilder<Function<Void>> {
private final java.util.function.Consumer<String> function;
public UnaryStringFunctionBuilder(java.util.function.Consumer<String> function) {
this.function = function;
}
@Override
public Function<Void> build(List<Returnable<?>> argumentList, Position position) {
return new Function<Void>() {
@@ -25,26 +26,26 @@ public class UnaryStringFunctionBuilder implements FunctionBuilder<Function<Void
public ReturnType returnType() {
return ReturnType.VOID;
}
@SuppressWarnings("unchecked")
@Override
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
function.accept(((Returnable<String>) argumentList.get(0)).apply(implementationArguments, variableMap));
return null;
}
@Override
public Position getPosition() {
return position;
}
};
}
@Override
public int argNumber() {
return 1;
}
@Override
public Returnable.ReturnType getArgument(int position) {
if(position == 0) return Returnable.ReturnType.STRING;

View File

@@ -1,5 +1,8 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
@@ -8,18 +11,16 @@ import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.List;
import java.util.Map;
public class ZeroArgFunctionBuilder<T> implements FunctionBuilder<Function<T>> {
private final java.util.function.Function<TerraImplementationArguments, T> function;
private final Returnable.ReturnType type;
public ZeroArgFunctionBuilder(java.util.function.Function<TerraImplementationArguments, T> function, Returnable.ReturnType type) {
this.function = function;
this.type = type;
}
@Override
public Function<T> build(List<Returnable<?>> argumentList, Position position) {
return new Function<T>() {
@@ -27,24 +28,24 @@ public class ZeroArgFunctionBuilder<T> implements FunctionBuilder<Function<T>> {
public ReturnType returnType() {
return type;
}
@Override
public T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return function.apply((TerraImplementationArguments) implementationArguments);
}
@Override
public Position getPosition() {
return position;
}
};
}
@Override
public int argNumber() {
return 0;
}
@Override
public Returnable.ReturnType getArgument(int position) {
if(position == 0) return type;

View File

@@ -1,5 +1,9 @@
package com.dfsek.terra.addons.terrascript.script.functions;
import net.jafama.FastMath;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
@@ -11,16 +15,14 @@ import com.dfsek.terra.api.util.RotationUtil;
import com.dfsek.terra.api.vector.Vector2;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import net.jafama.FastMath;
import java.util.Map;
public class BiomeFunction implements Function<String> {
private final TerraPlugin main;
private final Returnable<Number> x, y, z;
private final Position position;
public BiomeFunction(TerraPlugin main, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Position position) {
this.main = main;
this.x = x;
@@ -28,27 +30,32 @@ public class BiomeFunction implements Function<String> {
this.z = z;
this.position = position;
}
@Override
public String apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(),
z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
BiomeProvider grid = arguments.getWorld().getBiomeProvider();
return grid.getBiome(arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ()))), arguments.getWorld().getSeed()).getID();
return grid.getBiome(arguments.getBuffer()
.getOrigin()
.clone()
.add(new Vector3(FastMath.roundToInt(xz.getX()),
y.apply(implementationArguments, variableMap).intValue(),
FastMath.roundToInt(xz.getZ()))), arguments.getWorld().getSeed()).getID();
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.STRING;

View File

@@ -1,5 +1,10 @@
package com.dfsek.terra.addons.terrascript.script.functions;
import net.jafama.FastMath;
import java.util.HashMap;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.buffer.items.BufferedBlock;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
@@ -13,21 +18,18 @@ import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.util.RotationUtil;
import com.dfsek.terra.api.vector.Vector2;
import com.dfsek.terra.api.vector.Vector3;
import net.jafama.FastMath;
import java.util.HashMap;
import java.util.Map;
public class BlockFunction implements Function<Void> {
protected final Returnable<Number> x, y, z;
private final Map<String, BlockState> data = new HashMap<>();
protected final Returnable<String> blockData;
protected final TerraPlugin main;
private final Map<String, BlockState> data = new HashMap<>();
private final Returnable<Boolean> overwrite;
private final Position position;
public BlockFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> blockData, Returnable<Boolean> overwrite, TerraPlugin main, Position position) {
public BlockFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> blockData,
Returnable<Boolean> overwrite, TerraPlugin main, Position position) {
this.x = x;
this.y = y;
this.z = z;
@@ -36,16 +38,7 @@ public class BlockFunction implements Function<Void> {
this.main = main;
this.position = position;
}
void setBlock(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap, TerraImplementationArguments arguments, BlockState rot) {
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
RotationUtil.rotateBlockData(rot, arguments.getRotation().inverse());
arguments.getBuffer().addItem(new BufferedBlock(rot, overwrite.apply(implementationArguments, variableMap), main, arguments.isWaterlog()), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ())));
}
@Override
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
@@ -53,28 +46,45 @@ public class BlockFunction implements Function<Void> {
setBlock(implementationArguments, variableMap, arguments, rot);
return null;
}
protected BlockState getBlockState(ImplementationArguments arguments, Map<String, Variable<?>> variableMap) {
return data.computeIfAbsent(blockData.apply(arguments, variableMap), main.getWorldHandle()::createBlockData);
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;
}
void setBlock(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap,
TerraImplementationArguments arguments, BlockState rot) {
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(),
z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
RotationUtil.rotateBlockData(rot, arguments.getRotation().inverse());
arguments.getBuffer().addItem(
new BufferedBlock(rot, overwrite.apply(implementationArguments, variableMap), main, arguments.isWaterlog()),
new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(),
FastMath.roundToInt(xz.getZ())));
}
protected BlockState getBlockState(ImplementationArguments arguments, Map<String, Variable<?>> variableMap) {
return data.computeIfAbsent(blockData.apply(arguments, variableMap), main.getWorldHandle()::createBlockData);
}
public static class Constant extends BlockFunction {
private final BlockState state;
public Constant(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, StringConstant blockData, Returnable<Boolean> overwrite, TerraPlugin main, Position position) {
public Constant(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, StringConstant blockData,
Returnable<Boolean> overwrite, TerraPlugin main, Position position) {
super(x, y, z, blockData, overwrite, main, position);
this.state = main.getWorldHandle().createBlockData(blockData.getConstant());
}
@Override
protected BlockState getBlockState(ImplementationArguments arguments, Map<String, Variable<?>> variableMap) {
return state;

View File

@@ -1,5 +1,9 @@
package com.dfsek.terra.addons.terrascript.script.functions;
import net.jafama.FastMath;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
@@ -9,41 +13,46 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import com.dfsek.terra.api.util.RotationUtil;
import com.dfsek.terra.api.vector.Vector2;
import com.dfsek.terra.api.vector.Vector3;
import net.jafama.FastMath;
import java.util.Map;
public class CheckBlockFunction implements Function<String> {
private final Returnable<Number> x, y, z;
private final Position position;
public CheckBlockFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Position position) {
this.x = x;
this.y = y;
this.z = z;
this.position = position;
}
@Override
public String apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(),
z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
String data = arguments.getWorld().getBlockData(arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ())))).getAsString();
String data = arguments.getWorld()
.getBlockData(arguments.getBuffer()
.getOrigin()
.clone()
.add(new Vector3(FastMath.roundToInt(xz.getX()),
y.apply(implementationArguments, variableMap)
.doubleValue(), FastMath.roundToInt(xz.getZ()))))
.getAsString();
if(data.contains("[")) return data.substring(0, data.indexOf('[')); // Strip properties
else return data;
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.STRING;

View File

@@ -1,5 +1,9 @@
package com.dfsek.terra.addons.terrascript.script.functions;
import net.jafama.FastMath;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
@@ -12,15 +16,13 @@ import com.dfsek.terra.api.vector.Vector2;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.generator.SamplerCache;
import net.jafama.FastMath;
import java.util.Map;
public class CheckFunction implements Function<String> {
private final TerraPlugin main;
private final Returnable<Number> x, y, z;
private final Position position;
public CheckFunction(TerraPlugin main, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Position position) {
this.main = main;
this.x = x;
@@ -28,52 +30,56 @@ public class CheckFunction implements Function<String> {
this.z = z;
this.position = position;
}
@Override
public String apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(),
z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
Vector3 location = arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ())));
Vector3 location = arguments.getBuffer().getOrigin().clone().add(
new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(),
FastMath.roundToInt(xz.getZ())));
return apply(location, arguments.getWorld());
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.STRING;
}
private String apply(Vector3 vector, World world) {
int y = vector.getBlockY();
if(y >= world.getMaxHeight() || y < 0) return "AIR";
SamplerCache cache = world.getConfig().getSamplerCache();
double comp = sample(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), cache);
if(comp > 0) return "LAND"; // If noise val is greater than zero, location will always be land.
//BiomeProvider provider = tw.getBiomeProvider();
//TerraBiome b = provider.getBiome(vector.getBlockX(), vector.getBlockZ());
/*if(vector.getY() > c.getSeaLevel())*/ return "AIR"; // Above sea level
/*if(vector.getY() > c.getSeaLevel())*/
return "AIR"; // Above sea level
//return "OCEAN"; // Below sea level
}
private double sample(int x, int y, int z, SamplerCache cache) {
int cx = FastMath.floorDiv(x, 16);
int cz = FastMath.floorDiv(z, 16);
return cache.get(x, z).sample(x - (cx << 4), y, z - (cz << 4));
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.STRING;
}
}

View File

@@ -1,5 +1,7 @@
package com.dfsek.terra.addons.terrascript.script.functions;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.buffer.items.BufferedEntity;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
@@ -15,41 +17,43 @@ import com.dfsek.terra.api.util.RotationUtil;
import com.dfsek.terra.api.vector.Vector2;
import com.dfsek.terra.api.vector.Vector3;
import java.util.Map;
public class EntityFunction implements Function<Void> {
private final EntityType data;
private final Returnable<Number> x, y, z;
private final Position position;
private final TerraPlugin main;
public EntityFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position) throws ParseException {
public EntityFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main,
Position position) throws ParseException {
this.position = position;
this.main = main;
if(!(data instanceof ConstantExpression)) throw new ParseException("Entity data must be constant", data.getPosition());
this.data = main.getWorldHandle().getEntity(((ConstantExpression<String>) data).getConstant());
this.x = x;
this.y = y;
this.z = z;
}
@Override
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(),
z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
arguments.getBuffer().addItem(new BufferedEntity(data, main), new Vector3(xz.getX(), y.apply(implementationArguments, variableMap).doubleValue(), xz.getZ()));
arguments.getBuffer().addItem(new BufferedEntity(data, main),
new Vector3(xz.getX(), y.apply(implementationArguments, variableMap).doubleValue(), xz.getZ()));
return null;
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;

View File

@@ -1,5 +1,9 @@
package com.dfsek.terra.addons.terrascript.script.functions;
import net.jafama.FastMath;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
@@ -9,36 +13,36 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import com.dfsek.terra.api.util.RotationUtil;
import com.dfsek.terra.api.vector.Vector2;
import com.dfsek.terra.api.vector.Vector3;
import net.jafama.FastMath;
import java.util.Map;
public class GetMarkFunction implements Function<String> {
private final Returnable<Number> x, y, z;
private final Position position;
public GetMarkFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Position position) {
this.position = position;
this.x = x;
this.y = y;
this.z = z;
}
@Override
public String apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(),
z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
String mark = arguments.getBuffer().getMark(new Vector3(FastMath.floorToInt(xz.getX()), FastMath.floorToInt(y.apply(implementationArguments, variableMap).doubleValue()), FastMath.floorToInt(xz.getZ())));
String mark = arguments.getBuffer().getMark(new Vector3(FastMath.floorToInt(xz.getX()), FastMath.floorToInt(
y.apply(implementationArguments, variableMap).doubleValue()), FastMath.floorToInt(xz.getZ())));
return mark == null ? "" : mark;
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.STRING;

View File

@@ -1,5 +1,9 @@
package com.dfsek.terra.addons.terrascript.script.functions;
import net.jafama.FastMath;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.buffer.items.BufferedLootApplication;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
@@ -14,9 +18,7 @@ import com.dfsek.terra.api.structure.LootTable;
import com.dfsek.terra.api.util.RotationUtil;
import com.dfsek.terra.api.vector.Vector2;
import com.dfsek.terra.api.vector.Vector3;
import net.jafama.FastMath;
import java.util.Map;
public class LootFunction implements Function<Void> {
private final Registry<LootTable> registry;
@@ -25,8 +27,9 @@ public class LootFunction implements Function<Void> {
private final Position position;
private final TerraPlugin main;
private final StructureScript script;
public LootFunction(Registry<LootTable> registry, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position, StructureScript script) {
public LootFunction(Registry<LootTable> registry, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z,
Returnable<String> data, TerraPlugin main, Position position, StructureScript script) {
this.registry = registry;
this.position = position;
this.data = data;
@@ -36,31 +39,34 @@ public class LootFunction implements Function<Void> {
this.main = main;
this.script = script;
}
@Override
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(),
z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
String id = data.apply(implementationArguments, variableMap);
LootTable table = registry.get(id);
if(table == null) {
main.logger().severe("No such loot table " + id);
return null;
}
arguments.getBuffer().addItem(new BufferedLootApplication(table, main, script), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())));
arguments.getBuffer().addItem(new BufferedLootApplication(table, main, script),
new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(),
FastMath.roundToInt(xz.getZ())));
return null;
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;

View File

@@ -1,5 +1,9 @@
package com.dfsek.terra.addons.terrascript.script.functions;
import net.jafama.FastMath;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.buffer.items.BufferedPulledBlock;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
@@ -14,42 +18,44 @@ import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.util.RotationUtil;
import com.dfsek.terra.api.vector.Vector2;
import com.dfsek.terra.api.vector.Vector3;
import net.jafama.FastMath;
import java.util.Map;
public class PullFunction implements Function<Void> {
private final BlockState data;
private final Returnable<Number> x, y, z;
private final Position position;
public PullFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position) throws ParseException {
public PullFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main,
Position position) throws ParseException {
this.position = position;
if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition());
this.data = main.getWorldHandle().createBlockData(((ConstantExpression<String>) data).getConstant());
this.x = x;
this.y = y;
this.z = z;
}
@Override
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(),
z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
BlockState rot = data.clone();
RotationUtil.rotateBlockData(rot, arguments.getRotation().inverse());
arguments.getBuffer().addItem(new BufferedPulledBlock(rot), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())));
arguments.getBuffer().addItem(new BufferedPulledBlock(rot),
new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(),
FastMath.roundToInt(xz.getZ())));
return null;
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;

View File

@@ -1,5 +1,7 @@
package com.dfsek.terra.addons.terrascript.script.functions;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
@@ -7,28 +9,28 @@ import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public class RandomFunction implements Function<Integer> {
private final Returnable<Number> numberReturnable;
private final Position position;
public RandomFunction(Returnable<Number> numberReturnable, Position position) {
this.numberReturnable = numberReturnable;
this.position = position;
}
@Override
public ReturnType returnType() {
return ReturnType.NUMBER;
}
@Override
public Integer apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return ((TerraImplementationArguments) implementationArguments).getRandom().nextInt(numberReturnable.apply(implementationArguments, variableMap).intValue());
return ((TerraImplementationArguments) implementationArguments).getRandom().nextInt(
numberReturnable.apply(implementationArguments, variableMap).intValue());
}
@Override
public Position getPosition() {
return position;

View File

@@ -1,30 +1,31 @@
package com.dfsek.terra.addons.terrascript.script.functions;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.Map;
public class RecursionsFunction implements Function<Number> {
private final Position position;
public RecursionsFunction(Position position) {
this.position = position;
}
@Override
public ReturnType returnType() {
return ReturnType.NUMBER;
}
@Override
public Number apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
return ((TerraImplementationArguments) implementationArguments).getRecursions();
}
@Override
public Position getPosition() {
return position;

View File

@@ -1,5 +1,9 @@
package com.dfsek.terra.addons.terrascript.script.functions;
import net.jafama.FastMath;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
@@ -9,15 +13,13 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import com.dfsek.terra.api.util.RotationUtil;
import com.dfsek.terra.api.vector.Vector2;
import com.dfsek.terra.api.vector.Vector3;
import net.jafama.FastMath;
import java.util.Map;
public class SetMarkFunction implements Function<Void> {
private final Returnable<Number> x, y, z;
private final Position position;
private final Returnable<String> mark;
public SetMarkFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> mark, Position position) {
this.position = position;
this.mark = mark;
@@ -25,23 +27,29 @@ public class SetMarkFunction implements Function<Void> {
this.y = y;
this.z = z;
}
@Override
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(),
z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
arguments.getBuffer().setMark(mark.apply(implementationArguments, variableMap), new Vector3(FastMath.floorToInt(xz.getX()), FastMath.floorToInt(y.apply(implementationArguments, variableMap).doubleValue()), FastMath.floorToInt(xz.getZ())));
arguments.getBuffer().setMark(mark.apply(implementationArguments, variableMap), new Vector3(FastMath.floorToInt(xz.getX()),
FastMath.floorToInt(
y.apply(implementationArguments,
variableMap)
.doubleValue()),
FastMath.floorToInt(xz.getZ())));
return null;
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;

View File

@@ -1,5 +1,9 @@
package com.dfsek.terra.addons.terrascript.script.functions;
import net.jafama.FastMath;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.buffer.items.BufferedStateManipulator;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
@@ -11,17 +15,16 @@ import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.util.RotationUtil;
import com.dfsek.terra.api.vector.Vector2;
import com.dfsek.terra.api.vector.Vector3;
import net.jafama.FastMath;
import java.util.Map;
public class StateFunction implements Function<Void> {
private final Returnable<String> data;
private final Returnable<Number> x, y, z;
private final Position position;
private final TerraPlugin main;
public StateFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position) {
public StateFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main,
Position position) {
this.position = position;
this.main = main;
this.data = data;
@@ -29,22 +32,25 @@ public class StateFunction implements Function<Void> {
this.y = y;
this.z = z;
}
@Override
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(),
z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
arguments.getBuffer().addItem(new BufferedStateManipulator(main, data.apply(implementationArguments, variableMap)), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())));
arguments.getBuffer().addItem(new BufferedStateManipulator(main, data.apply(implementationArguments, variableMap)),
new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(),
FastMath.roundToInt(xz.getZ())));
return null;
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;

View File

@@ -1,5 +1,10 @@
package com.dfsek.terra.addons.terrascript.script.functions;
import net.jafama.FastMath;
import java.util.List;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.buffer.IntermediateBuffer;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
@@ -14,10 +19,7 @@ import com.dfsek.terra.api.structure.rotation.Rotation;
import com.dfsek.terra.api.util.RotationUtil;
import com.dfsek.terra.api.vector.Vector2;
import com.dfsek.terra.api.vector.Vector3;
import net.jafama.FastMath;
import java.util.List;
import java.util.Map;
public class StructureFunction implements Function<Boolean> {
private final Registry<Structure> registry;
@@ -26,8 +28,9 @@ public class StructureFunction implements Function<Boolean> {
private final Position position;
private final TerraPlugin main;
private final List<Returnable<String>> rotations;
public StructureFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> id, List<Returnable<String>> rotations, Registry<Structure> registry, Position position, TerraPlugin main) {
public StructureFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> id,
List<Returnable<String>> rotations, Registry<Structure> registry, Position position, TerraPlugin main) {
this.registry = registry;
this.id = id;
this.position = position;
@@ -37,30 +40,31 @@ public class StructureFunction implements Function<Boolean> {
this.main = main;
this.rotations = rotations;
}
@Override
public ReturnType returnType() {
return ReturnType.BOOLEAN;
}
@Override
public Boolean apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
if(arguments.getRecursions() > main.getTerraConfig().getMaxRecursion())
throw new RuntimeException("Structure recursion too deep: " + arguments.getRecursions());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(),
z.apply(implementationArguments, variableMap).doubleValue());
RotationUtil.rotateVector(xz, arguments.getRotation());
String app = id.apply(implementationArguments, variableMap);
Structure script = registry.get(app);
if(script == null) {
main.logger().severe("No such structure " + app);
return null;
}
Rotation rotation1;
String rotString = rotations.get(arguments.getRandom().nextInt(rotations.size())).apply(implementationArguments, variableMap);
try {
@@ -69,12 +73,14 @@ public class StructureFunction implements Function<Boolean> {
main.logger().severe("Invalid rotation " + rotString);
return null;
}
Vector3 offset = new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ()));
return script.generate(new IntermediateBuffer(arguments.getBuffer(), offset), arguments.getWorld(), arguments.getRandom(), arguments.getRotation().rotate(rotation1), arguments.getRecursions() + 1);
Vector3 offset = new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(),
FastMath.roundToInt(xz.getZ()));
return script.generate(new IntermediateBuffer(arguments.getBuffer(), offset), arguments.getWorld(), arguments.getRandom(),
arguments.getRotation().rotate(rotation1), arguments.getRecursions() + 1);
}
@Override
public Position getPosition() {
return position;

View File

@@ -4,38 +4,14 @@ public class Char {
private final char character;
private final int index;
private final int line;
public Char(char character, int index, int line) {
this.character = character;
this.index = index;
this.line = line;
}
public char getCharacter() {
return character;
}
public int getIndex() {
return index;
}
public int getLine() {
return line;
}
public boolean isWhitespace() {
return Character.isWhitespace(character);
}
public boolean isNewLine() {
return character == '\n';
}
public boolean isDigit() {
return Character.isDigit(character);
}
public boolean is(char... tests) {
for(char test : tests) {
if(test == character && test != '\0') {
@@ -44,13 +20,37 @@ public class Char {
}
return false;
}
public boolean isEOF() {
return character == '\0';
}
@Override
public String toString() {
return Character.toString(character);
}
public char getCharacter() {
return character;
}
public int getIndex() {
return index;
}
public int getLine() {
return line;
}
public boolean isWhitespace() {
return Character.isWhitespace(character);
}
public boolean isNewLine() {
return character == '\n';
}
public boolean isDigit() {
return Character.isDigit(character);
}
public boolean isEOF() {
return character == '\0';
}
}

View File

@@ -6,6 +6,7 @@ import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
/**
* Stream-like data structure that allows viewing future elements without consuming current.
*/
@@ -15,11 +16,11 @@ public class Lookahead {
private int index = 0;
private int line = 0;
private boolean end = false;
public Lookahead(Reader r) {
this.input = r;
}
/**
* Get the current character without consuming it.
*
@@ -28,8 +29,8 @@ public class Lookahead {
public Char current() {
return next(0);
}
/**
* Consume and return one character.
*
@@ -40,7 +41,57 @@ public class Lookahead {
consume(1);
return consumed;
}
/**
* Fetch a future character without consuming it.
*
* @param ahead Distance ahead to peek
*
* @return Character
*/
public Char next(int ahead) {
if(ahead < 0) throw new IllegalArgumentException();
while(buffer.size() <= ahead && !end) {
Char item = fetch();
if(item != null) {
buffer.add(item);
} else end = true;
}
if(ahead >= buffer.size()) {
return null;
} else return buffer.get(ahead);
}
/**
* Consume an amount of characters
*
* @param amount Number of characters to consume
*/
public void consume(int amount) {
if(amount < 0) throw new IllegalArgumentException();
while(amount-- > 0) {
if(!buffer.isEmpty()) buffer.remove(0); // Remove top item from buffer.
else {
if(end) return;
Char item = fetch();
if(item == null) end = true;
}
}
}
public boolean matches(String check, boolean consume) {
if(check == null) return false;
for(int i = 0; i < check.length(); i++) {
if(!next(i).is(check.charAt(i))) return false;
}
if(consume) consume(check.length()); // Consume string
return true;
}
/**
* Fetch the next character.
*
@@ -61,61 +112,12 @@ public class Lookahead {
return null;
}
}
/**
* Fetch a future character without consuming it.
*
* @param ahead Distance ahead to peek
* @return Character
*/
public Char next(int ahead) {
if(ahead < 0) throw new IllegalArgumentException();
while(buffer.size() <= ahead && !end) {
Char item = fetch();
if(item != null) {
buffer.add(item);
} else end = true;
}
if(ahead >= buffer.size()) {
return null;
} else return buffer.get(ahead);
}
public int getLine() {
return line;
}
public int getIndex() {
return index;
}
/**
* Consume an amount of characters
*
* @param amount Number of characters to consume
*/
public void consume(int amount) {
if(amount < 0) throw new IllegalArgumentException();
while(amount-- > 0) {
if(!buffer.isEmpty()) buffer.remove(0); // Remove top item from buffer.
else {
if(end) return;
Char item = fetch();
if(item == null) end = true;
}
}
}
public boolean matches(String check, boolean consume) {
if(check == null) return false;
for(int i = 0; i < check.length(); i++) {
if(!next(i).is(check.charAt(i))) return false;
}
if(consume) consume(check.length()); // Consume string
return true;
}
}

View File

@@ -3,12 +3,12 @@ package com.dfsek.terra.addons.terrascript.tokenizer;
public class Position {
private final int line;
private final int index;
public Position(int line, int index) {
this.line = line;
this.index = index;
}
@Override
public String toString() {
return (line + 1) + ":" + index;

View File

@@ -4,88 +4,88 @@ public class Token {
private final String content;
private final Type type;
private final Position start;
public Token(String content, Type type, Position start) {
this.content = content;
this.type = type;
this.start = start;
}
public Type getType() {
return type;
}
public String getContent() {
return content;
}
public Position getPosition() {
return start;
}
@Override
public String toString() {
return type + ": '" + content + "'";
}
public Type getType() {
return type;
}
public String getContent() {
return content;
}
public Position getPosition() {
return start;
}
public boolean isConstant() {
return this.type.equals(Type.NUMBER) || this.type.equals(Type.STRING) || this.type.equals(Type.BOOLEAN);
}
public boolean isBinaryOperator() {
return type.equals(Type.ADDITION_OPERATOR)
|| type.equals(Type.SUBTRACTION_OPERATOR)
|| type.equals(Type.MULTIPLICATION_OPERATOR)
|| type.equals(Type.DIVISION_OPERATOR)
|| type.equals(Type.EQUALS_OPERATOR)
|| type.equals(Type.NOT_EQUALS_OPERATOR)
|| 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.BOOLEAN_OR)
|| type.equals(Type.BOOLEAN_AND)
|| type.equals(Type.MODULO_OPERATOR);
|| type.equals(Type.SUBTRACTION_OPERATOR)
|| type.equals(Type.MULTIPLICATION_OPERATOR)
|| type.equals(Type.DIVISION_OPERATOR)
|| type.equals(Type.EQUALS_OPERATOR)
|| type.equals(Type.NOT_EQUALS_OPERATOR)
|| 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.BOOLEAN_OR)
|| type.equals(Type.BOOLEAN_AND)
|| type.equals(Type.MODULO_OPERATOR);
}
public boolean isStrictNumericOperator() {
return type.equals(Type.SUBTRACTION_OPERATOR)
|| type.equals(Type.MULTIPLICATION_OPERATOR)
|| type.equals(Type.DIVISION_OPERATOR)
|| type.equals(Type.GREATER_THAN_OPERATOR)
|| type.equals(Type.LESS_THAN_OPERATOR)
|| type.equals(Type.LESS_THAN_OR_EQUALS_OPERATOR)
|| type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR)
|| type.equals(Type.MODULO_OPERATOR);
|| type.equals(Type.MULTIPLICATION_OPERATOR)
|| type.equals(Type.DIVISION_OPERATOR)
|| type.equals(Type.GREATER_THAN_OPERATOR)
|| type.equals(Type.LESS_THAN_OPERATOR)
|| type.equals(Type.LESS_THAN_OR_EQUALS_OPERATOR)
|| type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR)
|| type.equals(Type.MODULO_OPERATOR);
}
public boolean isStrictBooleanOperator() {
return type.equals(Type.BOOLEAN_AND)
|| type.equals(Type.BOOLEAN_OR);
|| type.equals(Type.BOOLEAN_OR);
}
public boolean isVariableDeclaration() {
return type.equals(Type.STRING_VARIABLE)
|| type.equals(Type.BOOLEAN_VARIABLE)
|| type.equals(Type.NUMBER_VARIABLE);
|| type.equals(Type.BOOLEAN_VARIABLE)
|| type.equals(Type.NUMBER_VARIABLE);
}
public boolean isLoopLike() {
return type.equals(Type.IF_STATEMENT)
|| type.equals(Type.WHILE_LOOP)
|| type.equals(Type.FOR_LOOP);
|| type.equals(Type.WHILE_LOOP)
|| type.equals(Type.FOR_LOOP);
}
public boolean isIdentifier() {
return type.equals(Type.IDENTIFIER);
}
public enum Type {
/**
* Function identifier or language keyword
*/
IDENTIFIER,
/**
* Numeric literal
*/

View File

@@ -1,42 +1,47 @@
package com.dfsek.terra.addons.terrascript.tokenizer;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.tokenizer.exceptions.EOFException;
import com.dfsek.terra.addons.terrascript.tokenizer.exceptions.FormatException;
import com.dfsek.terra.addons.terrascript.tokenizer.exceptions.TokenizerException;
import com.google.common.collect.Sets;
import java.io.StringReader;
import java.util.Set;
import java.util.Stack;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.tokenizer.exceptions.EOFException;
import com.dfsek.terra.addons.terrascript.tokenizer.exceptions.FormatException;
import com.dfsek.terra.addons.terrascript.tokenizer.exceptions.TokenizerException;
public class Tokenizer {
public static final Set<Character> syntaxSignificant = Sets.newHashSet(';', '(', ')', '"', ',', '\\', '=', '{', '}', '+', '-', '*', '/', '>', '<', '!'); // Reserved chars
public static final Set<Character> syntaxSignificant = Sets.newHashSet(';', '(', ')', '"', ',', '\\', '=', '{', '}', '+', '-', '*', '/',
'>', '<', '!'); // Reserved chars
private final Lookahead reader;
private final Stack<Token> brackets = new Stack<>();
private Token current;
private Token last;
public Tokenizer(String data) throws ParseException {
reader = new Lookahead(new StringReader(data + '\0'));
current = fetchCheck();
}
/**
* Get the first token.
*
* @return First token
*
* @throws ParseException If token does not exist
*/
public Token get() throws ParseException {
if(!hasNext()) throw new ParseException("Unexpected end of input", last.getPosition());
return current;
}
/**
* Consume (get and remove) the first token.
*
* @return First token
*
* @throws ParseException If token does not exist
*/
public Token consume() throws ParseException {
@@ -45,16 +50,7 @@ public class Tokenizer {
current = fetchCheck();
return temp;
}
/**
* Whether this {@code Tokenizer} contains additional tokens.
*
* @return {@code true} if more tokens are present, otherwise {@code false}
*/
public boolean hasNext() {
return !(current == null);
}
private Token fetchCheck() throws ParseException {
Token fetch = fetch();
if(fetch != null) {
@@ -69,16 +65,16 @@ public class Tokenizer {
}
return fetch;
}
private Token fetch() throws TokenizerException {
while(!reader.current().isEOF() && reader.current().isWhitespace()) reader.consume();
while(reader.matches("//", true)) skipLine(); // Skip line if comment
if(reader.matches("/*", true)) skipTo("*/"); // Skip multi line comment
if(reader.current().isEOF()) return null; // EOF
if(reader.matches("==", true))
return new Token("==", Token.Type.EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
if(reader.matches("!=", true))
@@ -91,14 +87,14 @@ public class Tokenizer {
return new Token(">", Token.Type.GREATER_THAN_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
if(reader.matches("<", true))
return new Token("<", Token.Type.LESS_THAN_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()) {
StringBuilder num = new StringBuilder();
while(!reader.current().isEOF() && isNumberLike()) {
@@ -106,7 +102,7 @@ public class Tokenizer {
}
return new Token(num.toString(), Token.Type.NUMBER, new Position(reader.getLine(), reader.getIndex()));
}
if(reader.current().is('"')) {
reader.consume(); // Consume first quote
StringBuilder string = new StringBuilder();
@@ -122,10 +118,10 @@ public class Tokenizer {
string.append(reader.consume());
}
reader.consume(); // Consume last quote
return new Token(string.toString(), Token.Type.STRING, new Position(reader.getLine(), reader.getIndex()));
}
if(reader.current().is('('))
return new Token(reader.consume().toString(), Token.Type.GROUP_BEGIN, new Position(reader.getLine(), reader.getIndex()));
if(reader.current().is(')'))
@@ -143,37 +139,39 @@ public class Tokenizer {
if(reader.current().is('+'))
return new Token(reader.consume().toString(), Token.Type.ADDITION_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
if(reader.current().is('-'))
return new Token(reader.consume().toString(), Token.Type.SUBTRACTION_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
return new Token(reader.consume().toString(), Token.Type.SUBTRACTION_OPERATOR,
new Position(reader.getLine(), reader.getIndex()));
if(reader.current().is('*'))
return new Token(reader.consume().toString(), Token.Type.MULTIPLICATION_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
return new Token(reader.consume().toString(), Token.Type.MULTIPLICATION_OPERATOR,
new Position(reader.getLine(), reader.getIndex()));
if(reader.current().is('/'))
return new Token(reader.consume().toString(), Token.Type.DIVISION_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
if(reader.current().is('%'))
return new Token(reader.consume().toString(), Token.Type.MODULO_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
if(reader.current().is('!'))
return new Token(reader.consume().toString(), Token.Type.BOOLEAN_NOT, new Position(reader.getLine(), reader.getIndex()));
StringBuilder token = new StringBuilder();
while(!reader.current().isEOF() && !isSyntaxSignificant(reader.current().getCharacter())) {
Char c = reader.consume();
if(c.isWhitespace()) break;
token.append(c);
}
String tokenString = token.toString();
if(tokenString.equals("true"))
return new Token(tokenString, Token.Type.BOOLEAN, new Position(reader.getLine(), reader.getIndex()));
if(tokenString.equals("false"))
return new Token(tokenString, Token.Type.BOOLEAN, new Position(reader.getLine(), reader.getIndex()));
if(tokenString.equals("num"))
return new Token(tokenString, Token.Type.NUMBER_VARIABLE, new Position(reader.getLine(), reader.getIndex()));
if(tokenString.equals("str"))
return new Token(tokenString, Token.Type.STRING_VARIABLE, new Position(reader.getLine(), reader.getIndex()));
if(tokenString.equals("bool"))
return new Token(tokenString, Token.Type.BOOLEAN_VARIABLE, new Position(reader.getLine(), reader.getIndex()));
if(tokenString.equals("if"))
return new Token(tokenString, Token.Type.IF_STATEMENT, new Position(reader.getLine(), reader.getIndex()));
if(tokenString.equals("else"))
@@ -182,7 +180,7 @@ public class Tokenizer {
return new Token(tokenString, Token.Type.WHILE_LOOP, new Position(reader.getLine(), reader.getIndex()));
if(tokenString.equals("for"))
return new Token(tokenString, Token.Type.FOR_LOOP, new Position(reader.getLine(), reader.getIndex()));
if(tokenString.equals("return"))
return new Token(tokenString, Token.Type.RETURN, new Position(reader.getLine(), reader.getIndex()));
if(tokenString.equals("continue"))
@@ -191,32 +189,22 @@ public class Tokenizer {
return new Token(tokenString, Token.Type.BREAK, new Position(reader.getLine(), reader.getIndex()));
if(tokenString.equals("fail"))
return new Token(tokenString, Token.Type.FAIL, new Position(reader.getLine(), reader.getIndex()));
if(tokenString.equals("id"))
return new Token(tokenString, Token.Type.ID, new Position(reader.getLine(), reader.getIndex()));
return new Token(tokenString, Token.Type.IDENTIFIER, new Position(reader.getLine(), reader.getIndex()));
}
private boolean isNumberLike() {
return reader.current().isDigit()
|| reader.current().is('_', '.', 'E');
}
private boolean isNumberStart() {
return reader.current().isDigit()
|| reader.current().is('.') && reader.next(1).isDigit();
}
private void skipLine() {
while(!reader.current().isEOF() && !reader.current().isNewLine()) reader.consume();
consumeWhitespace();
}
private void consumeWhitespace() {
while(!reader.current().isEOF() && reader.current().isWhitespace()) reader.consume(); // Consume whitespace.
}
private void skipTo(String s) throws EOFException {
Position begin = new Position(reader.getLine(), reader.getIndex());
while(!reader.current().isEOF()) {
@@ -228,9 +216,28 @@ public class Tokenizer {
}
throw new EOFException("No end of expression found.", begin);
}
/**
* Whether this {@code Tokenizer} contains additional tokens.
*
* @return {@code true} if more tokens are present, otherwise {@code false}
*/
public boolean hasNext() {
return !(current == null);
}
private boolean isNumberLike() {
return reader.current().isDigit()
|| reader.current().is('_', '.', 'E');
}
private boolean isNumberStart() {
return reader.current().isDigit()
|| reader.current().is('.') && reader.next(1).isDigit();
}
public boolean isSyntaxSignificant(char c) {
return syntaxSignificant.contains(c);
}
}

View File

@@ -2,14 +2,15 @@ package com.dfsek.terra.addons.terrascript.tokenizer.exceptions;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class EOFException extends TokenizerException {
private static final long serialVersionUID = 3980047409902809440L;
public EOFException(String message, Position position) {
super(message, position);
}
public EOFException(String message, Position position, Throwable cause) {
super(message, position, cause);
}

View File

@@ -2,14 +2,15 @@ package com.dfsek.terra.addons.terrascript.tokenizer.exceptions;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class FormatException extends TokenizerException {
private static final long serialVersionUID = -791308012940744455L;
public FormatException(String message, Position position) {
super(message, position);
}
public FormatException(String message, Position position, Throwable cause) {
super(message, position, cause);
}

View File

@@ -3,14 +3,15 @@ package com.dfsek.terra.addons.terrascript.tokenizer.exceptions;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public abstract class TokenizerException extends ParseException {
private static final long serialVersionUID = 2792384010083575420L;
public TokenizerException(String message, Position position) {
super(message, position);
}
public TokenizerException(String message, Position position, Throwable cause) {
super(message, position, cause);
}

View File

@@ -1,15 +1,17 @@
package structure;
import com.dfsek.terra.addons.terrascript.tokenizer.Lookahead;
import org.junit.jupiter.api.Test;
import java.io.StringReader;
import com.dfsek.terra.addons.terrascript.tokenizer.Lookahead;
public class LookaheadTest {
@Test
public void lookahead() {
Lookahead lookahead = new Lookahead(new StringReader("Test string..."));
for(int i = 0; lookahead.next(i) != null; i++) {
System.out.print(lookahead.next(i).getCharacter());
}

View File

@@ -1,6 +1,15 @@
package structure;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.dfsek.terra.addons.terrascript.parser.Parser;
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
import com.dfsek.terra.addons.terrascript.parser.lang.Block;
@@ -10,31 +19,24 @@ import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ParserTest {
@Test
public void parse() throws IOException, ParseException {
Parser parser = new Parser(IOUtils.toString(getClass().getResourceAsStream("/test.tesf"), Charset.defaultCharset()));
parser.registerFunction("test", new FunctionBuilder<Test1>() {
@Override
public Test1 build(List<Returnable<?>> argumentList, Position position) {
return new Test1(argumentList.get(0), argumentList.get(1), position);
}
@Override
public int argNumber() {
return 2;
}
@Override
public Returnable.ReturnType getArgument(int position) {
switch(position) {
@@ -46,41 +48,42 @@ public class ParserTest {
return null;
}
}
});
long l = System.nanoTime();
Block block = parser.parse();
long t = System.nanoTime() - l;
System.out.println("Took " + (double) t / 1000000);
block.apply(null, new HashMap<>());
block.apply(null, new HashMap<>());
}
private static class Test1 implements Function<Void> {
private final Returnable<?> a;
private final Returnable<?> b;
private final Position position;
public Test1(Returnable<?> a, Returnable<?> b, Position position) {
this.a = a;
this.b = b;
this.position = position;
}
@Override
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
System.out.println("string: " + a.apply(implementationArguments, variableMap) + ", double: " + b.apply(implementationArguments, variableMap));
System.out.println("string: " + a.apply(implementationArguments, variableMap) + ", double: " +
b.apply(implementationArguments, variableMap));
return null;
}
@Override
public Position getPosition() {
return position;
}
@Override
public ReturnType returnType() {
return ReturnType.VOID;