mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-08-29 13:20:32 +00:00
more cleanup
This commit is contained in:
@@ -57,6 +57,12 @@ public class Parser {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse input
|
||||||
|
*
|
||||||
|
* @return executable {@link Block}
|
||||||
|
* @throws ParseException If parsing fails.
|
||||||
|
*/
|
||||||
public Block parse() throws ParseException {
|
public Block parse() throws ParseException {
|
||||||
Tokenizer tokenizer = new Tokenizer(data);
|
Tokenizer tokenizer = new Tokenizer(data);
|
||||||
|
|
||||||
@@ -80,7 +86,7 @@ public class Parser {
|
|||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Keyword<?> parseKeyword(List<Token> tokens, Map<String, Variable<?>> variableMap) throws ParseException {
|
private Keyword<?> parseLoopLike(List<Token> tokens, Map<String, Variable<?>> variableMap) throws ParseException {
|
||||||
|
|
||||||
Token identifier = tokens.remove(0);
|
Token identifier = tokens.remove(0);
|
||||||
ParserUtil.checkType(identifier, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP);
|
ParserUtil.checkType(identifier, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP);
|
||||||
@@ -178,8 +184,9 @@ public class Parser {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private BinaryOperation<?, ?> assemble(Returnable<?> left, Returnable<?> right, Token binaryOperator) throws ParseException {
|
private BinaryOperation<?, ?> assemble(Returnable<?> left, Returnable<?> right, Token binaryOperator) throws ParseException {
|
||||||
if(binaryOperator.isStrictNumericOperator()) ParserUtil.checkArithmeticOperation(left, right, binaryOperator);
|
if(binaryOperator.isStrictNumericOperator())
|
||||||
if(binaryOperator.isStrictBooleanOperator()) ParserUtil.checkBooleanOperation(left, right, binaryOperator);
|
ParserUtil.checkArithmeticOperation(left, right, binaryOperator); // Numeric type checking
|
||||||
|
if(binaryOperator.isStrictBooleanOperator()) ParserUtil.checkBooleanOperation(left, right, binaryOperator); // Boolean type checking
|
||||||
switch(binaryOperator.getType()) {
|
switch(binaryOperator.getType()) {
|
||||||
case ADDITION_OPERATOR:
|
case ADDITION_OPERATOR:
|
||||||
if(left.returnType().equals(Returnable.ReturnType.NUMBER) && right.returnType().equals(Returnable.ReturnType.NUMBER)) {
|
if(left.returnType().equals(Returnable.ReturnType.NUMBER) && right.returnType().equals(Returnable.ReturnType.NUMBER)) {
|
||||||
@@ -226,62 +233,48 @@ public class Parser {
|
|||||||
throw new UnsupportedOperationException("Unsupported variable type: " + type);
|
throw new UnsupportedOperationException("Unsupported variable type: " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private Block parseBlock(List<Token> tokens, Map<String, Variable<?>> superVars) throws ParseException {
|
private Block parseBlock(List<Token> tokens, Map<String, Variable<?>> superVars) throws ParseException {
|
||||||
List<Item<?>> parsedItems = new GlueList<>();
|
List<Item<?>> parsedItems = new GlueList<>();
|
||||||
|
|
||||||
Map<String, Variable<?>> parsedVariables = new HashMap<>(superVars); // New hashmap as to not mutate parent scope's declarations.
|
Map<String, Variable<?>> parsedVariables = new HashMap<>(superVars); // New hashmap as to not mutate parent scope's declarations.
|
||||||
|
|
||||||
Token first = tokens.get(0);
|
Token first = tokens.get(0);
|
||||||
ParserUtil.checkType(tokens.get(0), Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE);
|
|
||||||
|
|
||||||
main:
|
|
||||||
while(tokens.size() > 0) {
|
while(tokens.size() > 0) {
|
||||||
Token token = tokens.get(0);
|
Token token = tokens.get(0);
|
||||||
ParserUtil.checkType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.BLOCK_END, Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE);
|
if(token.getType().equals(Token.Type.BLOCK_END)) break; // Stop parsing at block end.
|
||||||
switch(token.getType()) {
|
|
||||||
case IF_STATEMENT:
|
|
||||||
case WHILE_LOOP:
|
|
||||||
parsedItems.add(parseKeyword(tokens, parsedVariables));
|
|
||||||
if(tokens.isEmpty()) break;
|
|
||||||
ParserUtil.checkType(tokens.get(0), Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.BLOCK_END);
|
|
||||||
break;
|
|
||||||
case IDENTIFIER:
|
|
||||||
if(parsedVariables.containsKey(token.getContent())) {
|
|
||||||
Variable<?> variable = parsedVariables.get(token.getContent());
|
|
||||||
|
|
||||||
parsedItems.add(parseAssignment(variable, tokens, parsedVariables));
|
ParserUtil.checkType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE);
|
||||||
} 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;
|
|
||||||
case NUMBER_VARIABLE:
|
|
||||||
case BOOLEAN_VARIABLE:
|
|
||||||
case STRING_VARIABLE:
|
|
||||||
Variable<?> temp;
|
|
||||||
if(token.getType().equals(Token.Type.NUMBER_VARIABLE))
|
|
||||||
temp = parseVariableDeclaration(tokens, Returnable.ReturnType.NUMBER);
|
|
||||||
else if(token.getType().equals(Token.Type.STRING_VARIABLE))
|
|
||||||
temp = parseVariableDeclaration(tokens, Returnable.ReturnType.STRING);
|
|
||||||
else temp = parseVariableDeclaration(tokens, Returnable.ReturnType.BOOLEAN);
|
|
||||||
Token name = tokens.get(1);
|
|
||||||
|
|
||||||
ParserUtil.checkType(name, Token.Type.IDENTIFIER); // Name must be an identifier.
|
if(token.isLoopLike()) { // Parse loop-like tokens (if, while, etc)
|
||||||
|
parsedItems.add(parseLoopLike(tokens, parsedVariables));
|
||||||
|
} else if(token.isIdentifier()) { // Parse identifiers
|
||||||
|
if(parsedVariables.containsKey(token.getContent())) { // Assume variable assignment
|
||||||
|
Variable<?> variable = parsedVariables.get(token.getContent());
|
||||||
|
parsedItems.add(parseAssignment(variable, tokens, parsedVariables));
|
||||||
|
} else parsedItems.add(parseFunction(tokens, true, parsedVariables));
|
||||||
|
} else if(token.isVariableDeclaration()) {
|
||||||
|
Variable<?> temp;
|
||||||
|
if(token.getType().equals(Token.Type.NUMBER_VARIABLE))
|
||||||
|
temp = parseVariableDeclaration(tokens, Returnable.ReturnType.NUMBER);
|
||||||
|
else if(token.getType().equals(Token.Type.STRING_VARIABLE))
|
||||||
|
temp = parseVariableDeclaration(tokens, Returnable.ReturnType.STRING);
|
||||||
|
else temp = parseVariableDeclaration(tokens, Returnable.ReturnType.BOOLEAN);
|
||||||
|
Token name = tokens.get(1);
|
||||||
|
|
||||||
if(functions.containsKey(name.getContent()) || parsedVariables.containsKey(name.getContent()))
|
ParserUtil.checkType(name, Token.Type.IDENTIFIER); // Name must be an identifier.
|
||||||
throw new ParseException(name.getContent() + " is already defined in this scope: " + name.getPosition());
|
|
||||||
|
|
||||||
parsedVariables.put(name.getContent(), temp);
|
if(functions.containsKey(name.getContent()) || parsedVariables.containsKey(name.getContent()))
|
||||||
|
throw new ParseException(name.getContent() + " is already defined in this scope: " + name.getPosition());
|
||||||
|
|
||||||
ParserUtil.checkType(tokens.remove(0), Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE);
|
parsedVariables.put(name.getContent(), temp);
|
||||||
|
|
||||||
parsedItems.add(parseAssignment(temp, tokens, parsedVariables));
|
ParserUtil.checkType(tokens.remove(0), Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE);
|
||||||
ParserUtil.checkType(tokens.remove(0), Token.Type.STATEMENT_END);
|
|
||||||
break;
|
parsedItems.add(parseAssignment(temp, tokens, parsedVariables));
|
||||||
case BLOCK_END:
|
} else throw new UnsupportedOperationException("Unexpected token " + token.getType() + ": " + token.getPosition());
|
||||||
tokens.remove(0); // Remove block end.
|
|
||||||
break main;
|
if(!tokens.isEmpty()) ParserUtil.checkType(tokens.remove(0), Token.Type.STATEMENT_END, Token.Type.BLOCK_END);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return new Block(parsedItems, first.getPosition());
|
return new Block(parsedItems, first.getPosition());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,21 @@ public class Token {
|
|||||||
|| 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLoopLike() {
|
||||||
|
return type.equals(Type.IF_STATEMENT)
|
||||||
|
|| type.equals(Type.WHILE_LOOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIdentifier() {
|
||||||
|
return type.equals(Type.IDENTIFIER);
|
||||||
|
}
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
/**
|
/**
|
||||||
* Function identifier or language keyword
|
* Function identifier or language keyword
|
||||||
@@ -170,15 +185,4 @@ public class Token {
|
|||||||
IF_STATEMENT,
|
IF_STATEMENT,
|
||||||
WHILE_LOOP
|
WHILE_LOOP
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Group {
|
|
||||||
KEYWORD(Type.IF_STATEMENT, Type.WHILE_LOOP, Type.BOOLEAN_VARIABLE, Type.STRING_VARIABLE, Type.NUMBER_VARIABLE),
|
|
||||||
IDENTIFIER(Type.IDENTIFIER),
|
|
||||||
BINARY_OPERATOR(Type.BOOLEAN_AND, Type.BOOLEAN_OR, Type.ADDITION_OPERATOR, Type.MULTIPLICATION_OPERATOR, Type.SUBTRACTION_OPERATOR, Type.DIVISION_OPERATOR, Type.GREATER_THAN_OPERATOR, Type.GREATER_THAN_OR_EQUALS_OPERATOR, Type.LESS_THAN_OPERATOR, Type.LESS_THAN_OR_EQUALS_OPERATOR, Type.EQUALS_OPERATOR, Type.NOT_EQUALS_OPERATOR);
|
|
||||||
private final Type[] types;
|
|
||||||
|
|
||||||
Group(Type... types) {
|
|
||||||
this.types = types;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user