diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java index bd7df451f..0471a5c90 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java @@ -11,6 +11,7 @@ import com.dfsek.terra.api.structures.parser.lang.constants.StringConstant; import com.dfsek.terra.api.structures.parser.lang.functions.Function; import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.api.structures.parser.lang.keywords.IfKeyword; +import com.dfsek.terra.api.structures.parser.lang.keywords.WhileKeyword; import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation; import com.dfsek.terra.api.structures.parser.lang.operations.BooleanAndOperation; import com.dfsek.terra.api.structures.parser.lang.operations.BooleanNotOperation; @@ -47,7 +48,7 @@ import java.util.Set; public class Parser { private final String data; private final Map>> functions = new HashMap<>(); - private final Set keywords = Sets.newHashSet("if", "return", "var"); + private final Set keywords = Sets.newHashSet("if", "return", "while"); Set allowedArguments = Sets.newHashSet(Token.Type.STRING, Token.Type.NUMBER, Token.Type.IDENTIFIER); @@ -90,7 +91,7 @@ public class Parser { if(!keywords.contains(identifier.getContent())) throw new ParseException("No such keyword " + identifier.getContent() + ": " + identifier.getPosition()); Keyword k = null; - if(identifier.getContent().equals("if")) { + if(identifier.getContent().equals("if") || identifier.getContent().equals("while")) { ParserUtil.checkType(tokens.remove(0), Token.Type.GROUP_BEGIN); @@ -101,7 +102,10 @@ public class Parser { ParserUtil.checkType(tokens.remove(0), Token.Type.BLOCK_BEGIN); - k = new IfKeyword(parseBlock(tokens, variableMap), (Returnable) comparator, identifier.getPosition()); + if(identifier.getContent().equals("if")) + k = new IfKeyword(parseBlock(tokens, variableMap), (Returnable) comparator, identifier.getPosition()); // If statement + else + k = new WhileKeyword(parseBlock(tokens, variableMap), (Returnable) comparator, identifier.getPosition()); // While loop } return k; @@ -232,6 +236,7 @@ public class Parser { throw new UnsupportedOperationException("Unsupported variable type: " + type); } + @SuppressWarnings("unchecked") private Block parseBlock(List tokens, Map> superVars) throws ParseException { List> parsedItems = new GlueList<>(); @@ -251,7 +256,11 @@ public class Parser { ParserUtil.checkType(tokens.get(0), Token.Type.IDENTIFIER, Token.Type.KEYWORD, Token.Type.BLOCK_END); break; case IDENTIFIER: - parsedItems.add(parseFunction(tokens, true, parsedVariables)); + if(parsedVariables.containsKey(token.getContent())) { + Variable variable = parsedVariables.get(token.getContent()); + + parsedItems.add(parseAssignment(variable, tokens, parsedVariables)); + } else parsedItems.add(parseFunction(tokens, true, parsedVariables)); if(tokens.isEmpty()) break; ParserUtil.checkType(tokens.remove(0), Token.Type.STATEMENT_END, Token.Type.BLOCK_END); break; @@ -272,6 +281,9 @@ public class Parser { throw new ParseException(name.getContent() + " is already defined in this scope: " + name.getPosition()); parsedVariables.put(name.getContent(), temp); + + ParserUtil.checkType(tokens.remove(0), Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE); + parsedItems.add(parseAssignment(temp, tokens, parsedVariables)); ParserUtil.checkType(tokens.remove(0), Token.Type.STATEMENT_END); break; @@ -285,8 +297,6 @@ public class Parser { @SuppressWarnings("unchecked") private Assignment parseAssignment(Variable variable, List tokens, Map> variableMap) throws ParseException { - ParserUtil.checkType(tokens.remove(0), Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE); - Token name = tokens.get(0); ParserUtil.checkType(tokens.remove(0), Token.Type.IDENTIFIER); diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/WhileKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/WhileKeyword.java new file mode 100644 index 000000000..7706d1b4e --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/WhileKeyword.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.api.structures.parser.lang.keywords; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.structures.parser.lang.Block; +import com.dfsek.terra.api.structures.parser.lang.Keyword; +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class WhileKeyword implements Keyword { + private final Block conditional; + private final Returnable statement; + private final Position position; + + public WhileKeyword(Block conditional, Returnable statement, Position position) { + this.conditional = conditional; + this.statement = statement; + this.position = position; + } + + @Override + public Void apply(Location location) { + while(statement.apply(location)) conditional.apply(location); + return null; + } + + @Override + public Void apply(Location location, Chunk chunk) { + while(statement.apply(location, chunk)) conditional.apply(location, chunk); + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java index bf0d96b56..b8bfc7297 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java @@ -12,7 +12,7 @@ public class Tokenizer { private final Lookahead reader; private final Set syntaxSignificant = Sets.newHashSet(';', '(', ')', '"', ',', '\\', '=', '{', '}', '+', '-', '*', '/', '>', '<', '!'); // Reserved chars - private final Set keywords = Sets.newHashSet("if", "return", "num", "bool", "str"); + private final Set keywords = Sets.newHashSet("if", "while", "num", "bool", "str"); public Tokenizer(String data) { diff --git a/common/src/test/resources/test.tesf b/common/src/test/resources/test.tesf index 72c01ec70..122c25a8e 100644 --- a/common/src/test/resources/test.tesf +++ b/common/src/test/resources/test.tesf @@ -1,9 +1,18 @@ test("hello" + 3 + "gdfg", (2 * (3+1) * (2 * (1+1)))); // + num testVar = 3.4; bool boolean = true; str stringVar = "hello!"; +num iterator = 0; + +while(iterator < 5) { + test("fdsgdf" + 2 + stringVar, iterator); + iterator = iterator + 1; +} + + if(true && boolean) { num scopedVar = 2; test("fdsgdf" + 2 + stringVar, 1 + testVar + scopedVar);