mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-20 23:30:29 +00:00
only allow loop flow control in loop
This commit is contained in:
@@ -113,11 +113,11 @@ public class Parser {
|
|||||||
if(blockLevel != 0)
|
if(blockLevel != 0)
|
||||||
throw new ParseException("Dangling opening brace", tokens.getTokens().get(tokens.getTokens().size() - 1).getPosition());
|
throw new ParseException("Dangling opening brace", tokens.getTokens().get(tokens.getTokens().size() - 1).getPosition());
|
||||||
|
|
||||||
return parseBlock(tokens, new HashMap<>());
|
return parseBlock(tokens, new HashMap<>(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Keyword<?> parseLoopLike(TokenHolder tokens, Map<String, Variable<?>> variableMap) throws ParseException {
|
private Keyword<?> parseLoopLike(TokenHolder tokens, Map<String, Variable<?>> variableMap, boolean loop) throws ParseException {
|
||||||
|
|
||||||
Token identifier = tokens.consume();
|
Token identifier = tokens.consume();
|
||||||
ParserUtil.checkType(identifier, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP);
|
ParserUtil.checkType(identifier, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP);
|
||||||
@@ -128,7 +128,7 @@ public class Parser {
|
|||||||
case FOR_LOOP:
|
case FOR_LOOP:
|
||||||
return parseForLoop(tokens, variableMap, identifier.getPosition());
|
return parseForLoop(tokens, variableMap, identifier.getPosition());
|
||||||
case IF_STATEMENT:
|
case IF_STATEMENT:
|
||||||
return parseIfStatement(tokens, variableMap, identifier.getPosition());
|
return parseIfStatement(tokens, variableMap, identifier.getPosition(), loop);
|
||||||
case WHILE_LOOP:
|
case WHILE_LOOP:
|
||||||
return parseWhileLoop(tokens, variableMap, identifier.getPosition());
|
return parseWhileLoop(tokens, variableMap, identifier.getPosition());
|
||||||
default:
|
default:
|
||||||
@@ -142,17 +142,17 @@ public class Parser {
|
|||||||
|
|
||||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
||||||
|
|
||||||
return new WhileKeyword(parseStatementBlock(tokens, variableMap), (Returnable<Boolean>) first, start); // While loop
|
return new WhileKeyword(parseStatementBlock(tokens, variableMap, true), (Returnable<Boolean>) first, start); // While loop
|
||||||
}
|
}
|
||||||
|
|
||||||
private IfKeyword parseIfStatement(TokenHolder tokens, Map<String, Variable<?>> variableMap, Position start) throws ParseException {
|
private IfKeyword parseIfStatement(TokenHolder tokens, Map<String, Variable<?>> variableMap, Position start, boolean loop) throws ParseException {
|
||||||
Returnable<?> condition = parseExpression(tokens, true, variableMap);
|
Returnable<?> condition = parseExpression(tokens, true, variableMap);
|
||||||
ParserUtil.checkReturnType(condition, Returnable.ReturnType.BOOLEAN);
|
ParserUtil.checkReturnType(condition, Returnable.ReturnType.BOOLEAN);
|
||||||
|
|
||||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
||||||
|
|
||||||
Block elseBlock = null;
|
Block elseBlock = null;
|
||||||
Block statement = parseStatementBlock(tokens, variableMap);
|
Block statement = parseStatementBlock(tokens, variableMap, loop);
|
||||||
|
|
||||||
List<IfKeyword.Pair<Returnable<Boolean>, Block>> elseIf = new GlueList<>();
|
List<IfKeyword.Pair<Returnable<Boolean>, Block>> elseIf = new GlueList<>();
|
||||||
|
|
||||||
@@ -162,9 +162,9 @@ public class Parser {
|
|||||||
tokens.consume(); // Consume if.
|
tokens.consume(); // Consume if.
|
||||||
Returnable<?> elseCondition = parseExpression(tokens, true, variableMap);
|
Returnable<?> elseCondition = parseExpression(tokens, true, variableMap);
|
||||||
ParserUtil.checkReturnType(elseCondition, Returnable.ReturnType.BOOLEAN);
|
ParserUtil.checkReturnType(elseCondition, Returnable.ReturnType.BOOLEAN);
|
||||||
elseIf.add(new IfKeyword.Pair<>((Returnable<Boolean>) elseCondition, parseStatementBlock(tokens, variableMap)));
|
elseIf.add(new IfKeyword.Pair<>((Returnable<Boolean>) elseCondition, parseStatementBlock(tokens, variableMap, loop)));
|
||||||
} else {
|
} else {
|
||||||
elseBlock = parseStatementBlock(tokens, variableMap);
|
elseBlock = parseStatementBlock(tokens, variableMap, loop);
|
||||||
break; // Else must be last.
|
break; // Else must be last.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,16 +172,16 @@ public class Parser {
|
|||||||
return new IfKeyword(statement, (Returnable<Boolean>) condition, elseIf, elseBlock, start); // If statement
|
return new IfKeyword(statement, (Returnable<Boolean>) condition, elseIf, elseBlock, start); // If statement
|
||||||
}
|
}
|
||||||
|
|
||||||
private Block parseStatementBlock(TokenHolder tokens, Map<String, Variable<?>> variableMap) throws ParseException {
|
private Block parseStatementBlock(TokenHolder tokens, Map<String, Variable<?>> variableMap, boolean loop) throws ParseException {
|
||||||
|
|
||||||
if(tokens.get().getType().equals(Token.Type.BLOCK_BEGIN)) {
|
if(tokens.get().getType().equals(Token.Type.BLOCK_BEGIN)) {
|
||||||
ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_BEGIN);
|
ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_BEGIN);
|
||||||
Block block = parseBlock(tokens, variableMap);
|
Block block = parseBlock(tokens, variableMap, loop);
|
||||||
ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_END);
|
ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_END);
|
||||||
return block;
|
return block;
|
||||||
} else {
|
} else {
|
||||||
Position position = tokens.get().getPosition();
|
Position position = tokens.get().getPosition();
|
||||||
Block block = new Block(Collections.singletonList(parseItem(tokens, variableMap)), position);
|
Block block = new Block(Collections.singletonList(parseItem(tokens, variableMap, loop)), position);
|
||||||
ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
|
ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
@@ -217,7 +217,7 @@ public class Parser {
|
|||||||
|
|
||||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
||||||
|
|
||||||
return new ForKeyword(parseStatementBlock(tokens, variableMap), initializer, (Returnable<Boolean>) conditional, incrementer, start);
|
return new ForKeyword(parseStatementBlock(tokens, variableMap, true), initializer, (Returnable<Boolean>) conditional, incrementer, start);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Returnable<?> parseExpression(TokenHolder tokens, boolean full, Map<String, Variable<?>> variableMap) throws ParseException {
|
private Returnable<?> parseExpression(TokenHolder tokens, boolean full, Map<String, Variable<?>> variableMap) throws ParseException {
|
||||||
@@ -345,7 +345,7 @@ public class Parser {
|
|||||||
throw new UnsupportedOperationException("Unsupported variable type: " + type);
|
throw new UnsupportedOperationException("Unsupported variable type: " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Block parseBlock(TokenHolder tokens, Map<String, Variable<?>> superVars) throws ParseException {
|
private Block parseBlock(TokenHolder tokens, Map<String, Variable<?>> superVars, boolean loop) throws ParseException {
|
||||||
List<Item<?>> parsedItems = new GlueList<>();
|
List<Item<?>> parsedItems = new GlueList<>();
|
||||||
|
|
||||||
Map<String, Variable<?>> parsedVariables = new HashMap<>(superVars); // New hashmap as to not mutate parent scope's declarations.
|
Map<String, Variable<?>> parsedVariables = new HashMap<>(superVars); // New hashmap as to not mutate parent scope's declarations.
|
||||||
@@ -355,19 +355,21 @@ public class Parser {
|
|||||||
while(tokens.hasNext()) {
|
while(tokens.hasNext()) {
|
||||||
Token token = tokens.get();
|
Token token = tokens.get();
|
||||||
if(token.getType().equals(Token.Type.BLOCK_END)) break; // Stop parsing at block end.
|
if(token.getType().equals(Token.Type.BLOCK_END)) break; // Stop parsing at block end.
|
||||||
parsedItems.add(parseItem(tokens, parsedVariables));
|
parsedItems.add(parseItem(tokens, parsedVariables, loop));
|
||||||
if(tokens.hasNext() && !token.isLoopLike()) ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
|
if(tokens.hasNext() && !token.isLoopLike()) ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
|
||||||
}
|
}
|
||||||
return new Block(parsedItems, first.getPosition());
|
return new Block(parsedItems, first.getPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Item<?> parseItem(TokenHolder tokens, Map<String, Variable<?>> variableMap) throws ParseException {
|
private Item<?> parseItem(TokenHolder tokens, Map<String, Variable<?>> variableMap, boolean loop) throws ParseException {
|
||||||
Token token = tokens.get();
|
Token token = tokens.get();
|
||||||
ParserUtil.checkType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP,
|
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);
|
||||||
|
|
||||||
if(token.isLoopLike()) { // Parse loop-like tokens (if, while, etc)
|
if(token.isLoopLike()) { // Parse loop-like tokens (if, while, etc)
|
||||||
return parseLoopLike(tokens, variableMap);
|
return parseLoopLike(tokens, variableMap, loop);
|
||||||
} else if(token.isIdentifier()) { // Parse identifiers
|
} else if(token.isIdentifier()) { // Parse identifiers
|
||||||
if(variableMap.containsKey(token.getContent())) { // Assume variable assignment
|
if(variableMap.containsKey(token.getContent())) { // Assume variable assignment
|
||||||
Variable<?> variable = variableMap.get(token.getContent());
|
Variable<?> variable = variableMap.get(token.getContent());
|
||||||
|
|||||||
@@ -18,10 +18,13 @@ bool truetest = false;
|
|||||||
|
|
||||||
num iterator = 0;
|
num iterator = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for(num i = 0; i < 5; i = i + 1) {
|
for(num i = 0; i < 5; i = i + 1) {
|
||||||
test("i = " + i, iterator);
|
test("i = " + i, iterator);
|
||||||
if(i > 1 + 1) {
|
if(i > 1 + 1) {
|
||||||
test("more than 2", iterator);
|
test("more than 2", iterator);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user