mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-06-17 22:31:52 +00:00
Simplify code
This commit is contained in:
+13
-13
@@ -83,17 +83,17 @@ public class Lexer {
|
|||||||
|
|
||||||
// Check if operator token
|
// Check if operator token
|
||||||
if(reader.matchesString("==", true))
|
if(reader.matchesString("==", true))
|
||||||
return new Token("==", TokenType.EQUALS_OPERATOR, reader.getPosition());
|
return new Token("==", TokenType.EQUALS_EQUALS, reader.getPosition());
|
||||||
if(reader.matchesString("!=", true))
|
if(reader.matchesString("!=", true))
|
||||||
return new Token("!=", TokenType.NOT_EQUALS_OPERATOR, reader.getPosition());
|
return new Token("!=", TokenType.BANG_EQUALS, reader.getPosition());
|
||||||
if(reader.matchesString(">=", true))
|
if(reader.matchesString(">=", true))
|
||||||
return new Token(">=", TokenType.GREATER_THAN_OR_EQUALS_OPERATOR, reader.getPosition());
|
return new Token(">=", TokenType.GREATER_EQUAL, reader.getPosition());
|
||||||
if(reader.matchesString("<=", true))
|
if(reader.matchesString("<=", true))
|
||||||
return new Token("<=", TokenType.LESS_THAN_OR_EQUALS_OPERATOR, reader.getPosition());
|
return new Token("<=", TokenType.LESS_EQUALS, reader.getPosition());
|
||||||
if(reader.matchesString(">", true))
|
if(reader.matchesString(">", true))
|
||||||
return new Token(">", TokenType.GREATER_THAN_OPERATOR, reader.getPosition());
|
return new Token(">", TokenType.GREATER, reader.getPosition());
|
||||||
if(reader.matchesString("<", true))
|
if(reader.matchesString("<", true))
|
||||||
return new Token("<", TokenType.LESS_THAN_OPERATOR, reader.getPosition());
|
return new Token("<", TokenType.LESS, reader.getPosition());
|
||||||
|
|
||||||
// Check if logical operator
|
// Check if logical operator
|
||||||
if(reader.matchesString("||", true))
|
if(reader.matchesString("||", true))
|
||||||
@@ -131,9 +131,9 @@ public class Lexer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(reader.current().is('('))
|
if(reader.current().is('('))
|
||||||
return new Token(reader.consume().toString(), TokenType.GROUP_BEGIN, reader.getPosition());
|
return new Token(reader.consume().toString(), TokenType.OPEN_PAREN, reader.getPosition());
|
||||||
if(reader.current().is(')'))
|
if(reader.current().is(')'))
|
||||||
return new Token(reader.consume().toString(), TokenType.GROUP_END, reader.getPosition());
|
return new Token(reader.consume().toString(), TokenType.CLOSE_PAREN, reader.getPosition());
|
||||||
if(reader.current().is(';'))
|
if(reader.current().is(';'))
|
||||||
return new Token(reader.consume().toString(), TokenType.STATEMENT_END, reader.getPosition());
|
return new Token(reader.consume().toString(), TokenType.STATEMENT_END, reader.getPosition());
|
||||||
if(reader.current().is(','))
|
if(reader.current().is(','))
|
||||||
@@ -153,19 +153,19 @@ public class Lexer {
|
|||||||
if(reader.current().is('='))
|
if(reader.current().is('='))
|
||||||
return new Token(reader.consume().toString(), TokenType.ASSIGNMENT, reader.getPosition());
|
return new Token(reader.consume().toString(), TokenType.ASSIGNMENT, reader.getPosition());
|
||||||
if(reader.current().is('+'))
|
if(reader.current().is('+'))
|
||||||
return new Token(reader.consume().toString(), TokenType.ADDITION_OPERATOR, reader.getPosition());
|
return new Token(reader.consume().toString(), TokenType.PLUS, reader.getPosition());
|
||||||
if(reader.current().is('-'))
|
if(reader.current().is('-'))
|
||||||
return new Token(reader.consume().toString(), TokenType.SUBTRACTION_OPERATOR,
|
return new Token(reader.consume().toString(), TokenType.MINUS,
|
||||||
reader.getPosition());
|
reader.getPosition());
|
||||||
if(reader.current().is('*'))
|
if(reader.current().is('*'))
|
||||||
return new Token(reader.consume().toString(), TokenType.MULTIPLICATION_OPERATOR,
|
return new Token(reader.consume().toString(), TokenType.STAR,
|
||||||
reader.getPosition());
|
reader.getPosition());
|
||||||
if(reader.current().is('/'))
|
if(reader.current().is('/'))
|
||||||
return new Token(reader.consume().toString(), TokenType.DIVISION_OPERATOR, reader.getPosition());
|
return new Token(reader.consume().toString(), TokenType.FORWARD_SLASH, reader.getPosition());
|
||||||
if(reader.current().is('%'))
|
if(reader.current().is('%'))
|
||||||
return new Token(reader.consume().toString(), TokenType.MODULO_OPERATOR, reader.getPosition());
|
return new Token(reader.consume().toString(), TokenType.MODULO_OPERATOR, reader.getPosition());
|
||||||
if(reader.current().is('!'))
|
if(reader.current().is('!'))
|
||||||
return new Token(reader.consume().toString(), TokenType.BOOLEAN_NOT, reader.getPosition());
|
return new Token(reader.consume().toString(), TokenType.BANG, reader.getPosition());
|
||||||
|
|
||||||
// Read word
|
// Read word
|
||||||
StringBuilder token = new StringBuilder();
|
StringBuilder token = new StringBuilder();
|
||||||
|
|||||||
+30
-30
@@ -44,29 +44,29 @@ public class Token {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBinaryOperator() {
|
public boolean isBinaryOperator() {
|
||||||
return type.equals(TokenType.ADDITION_OPERATOR)
|
return type.equals(TokenType.PLUS)
|
||||||
|| type.equals(TokenType.SUBTRACTION_OPERATOR)
|
|| type.equals(TokenType.MINUS)
|
||||||
|| type.equals(TokenType.MULTIPLICATION_OPERATOR)
|
|| type.equals(TokenType.STAR)
|
||||||
|| type.equals(TokenType.DIVISION_OPERATOR)
|
|| type.equals(TokenType.FORWARD_SLASH)
|
||||||
|| type.equals(TokenType.EQUALS_OPERATOR)
|
|| type.equals(TokenType.EQUALS_EQUALS)
|
||||||
|| type.equals(TokenType.NOT_EQUALS_OPERATOR)
|
|| type.equals(TokenType.BANG_EQUALS)
|
||||||
|| type.equals(TokenType.LESS_THAN_OPERATOR)
|
|| type.equals(TokenType.LESS)
|
||||||
|| type.equals(TokenType.GREATER_THAN_OPERATOR)
|
|| type.equals(TokenType.GREATER)
|
||||||
|| type.equals(TokenType.LESS_THAN_OR_EQUALS_OPERATOR)
|
|| type.equals(TokenType.LESS_EQUALS)
|
||||||
|| type.equals(TokenType.GREATER_THAN_OR_EQUALS_OPERATOR)
|
|| type.equals(TokenType.GREATER_EQUAL)
|
||||||
|| type.equals(TokenType.BOOLEAN_OR)
|
|| type.equals(TokenType.BOOLEAN_OR)
|
||||||
|| type.equals(TokenType.BOOLEAN_AND)
|
|| type.equals(TokenType.BOOLEAN_AND)
|
||||||
|| type.equals(TokenType.MODULO_OPERATOR);
|
|| type.equals(TokenType.MODULO_OPERATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStrictNumericOperator() {
|
public boolean isStrictNumericOperator() {
|
||||||
return type.equals(TokenType.SUBTRACTION_OPERATOR)
|
return type.equals(TokenType.MINUS)
|
||||||
|| type.equals(TokenType.MULTIPLICATION_OPERATOR)
|
|| type.equals(TokenType.STAR)
|
||||||
|| type.equals(TokenType.DIVISION_OPERATOR)
|
|| type.equals(TokenType.FORWARD_SLASH)
|
||||||
|| type.equals(TokenType.GREATER_THAN_OPERATOR)
|
|| type.equals(TokenType.GREATER)
|
||||||
|| type.equals(TokenType.LESS_THAN_OPERATOR)
|
|| type.equals(TokenType.LESS)
|
||||||
|| type.equals(TokenType.LESS_THAN_OR_EQUALS_OPERATOR)
|
|| type.equals(TokenType.LESS_EQUALS)
|
||||||
|| type.equals(TokenType.GREATER_THAN_OR_EQUALS_OPERATOR)
|
|| type.equals(TokenType.GREATER_EQUAL)
|
||||||
|| type.equals(TokenType.MODULO_OPERATOR);
|
|| type.equals(TokenType.MODULO_OPERATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,11 +108,11 @@ public class Token {
|
|||||||
/**
|
/**
|
||||||
* Beginning of group
|
* Beginning of group
|
||||||
*/
|
*/
|
||||||
GROUP_BEGIN,
|
OPEN_PAREN,
|
||||||
/**
|
/**
|
||||||
* Ending of group
|
* Ending of group
|
||||||
*/
|
*/
|
||||||
GROUP_END,
|
CLOSE_PAREN,
|
||||||
/**
|
/**
|
||||||
* End of statement
|
* End of statement
|
||||||
*/
|
*/
|
||||||
@@ -136,43 +136,43 @@ public class Token {
|
|||||||
/**
|
/**
|
||||||
* Boolean equals operator
|
* Boolean equals operator
|
||||||
*/
|
*/
|
||||||
EQUALS_OPERATOR,
|
EQUALS_EQUALS,
|
||||||
/**
|
/**
|
||||||
* Boolean not equals operator
|
* Boolean not equals operator
|
||||||
*/
|
*/
|
||||||
NOT_EQUALS_OPERATOR,
|
BANG_EQUALS,
|
||||||
/**
|
/**
|
||||||
* Boolean greater than operator
|
* Boolean greater than operator
|
||||||
*/
|
*/
|
||||||
GREATER_THAN_OPERATOR,
|
GREATER,
|
||||||
/**
|
/**
|
||||||
* Boolean less than operator
|
* Boolean less than operator
|
||||||
*/
|
*/
|
||||||
LESS_THAN_OPERATOR,
|
LESS,
|
||||||
/**
|
/**
|
||||||
* Boolean greater than or equal to operator
|
* Boolean greater than or equal to operator
|
||||||
*/
|
*/
|
||||||
GREATER_THAN_OR_EQUALS_OPERATOR,
|
GREATER_EQUAL,
|
||||||
/**
|
/**
|
||||||
* Boolean less than or equal to operator
|
* Boolean less than or equal to operator
|
||||||
*/
|
*/
|
||||||
LESS_THAN_OR_EQUALS_OPERATOR,
|
LESS_EQUALS,
|
||||||
/**
|
/**
|
||||||
* Addition/concatenation operator
|
* Addition/concatenation operator
|
||||||
*/
|
*/
|
||||||
ADDITION_OPERATOR,
|
PLUS,
|
||||||
/**
|
/**
|
||||||
* Subtraction operator
|
* Subtraction operator
|
||||||
*/
|
*/
|
||||||
SUBTRACTION_OPERATOR,
|
MINUS,
|
||||||
/**
|
/**
|
||||||
* Multiplication operator
|
* Multiplication operator
|
||||||
*/
|
*/
|
||||||
MULTIPLICATION_OPERATOR,
|
STAR,
|
||||||
/**
|
/**
|
||||||
* Division operator
|
* Division operator
|
||||||
*/
|
*/
|
||||||
DIVISION_OPERATOR,
|
FORWARD_SLASH,
|
||||||
/**
|
/**
|
||||||
* Modulo operator.
|
* Modulo operator.
|
||||||
*/
|
*/
|
||||||
@@ -180,7 +180,7 @@ public class Token {
|
|||||||
/**
|
/**
|
||||||
* Boolean not operator
|
* Boolean not operator
|
||||||
*/
|
*/
|
||||||
BOOLEAN_NOT,
|
BANG,
|
||||||
/**
|
/**
|
||||||
* Boolean or
|
* Boolean or
|
||||||
*/
|
*/
|
||||||
|
|||||||
+87
-87
@@ -63,11 +63,12 @@ import com.dfsek.terra.api.util.generic.pair.Pair;
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class Parser {
|
public class Parser {
|
||||||
private final String source;
|
|
||||||
private final List<String> ignoredFunctions = new ArrayList<>();
|
private final List<String> ignoredFunctions = new ArrayList<>();
|
||||||
|
|
||||||
public Parser(String source) {
|
private final Lexer lexer;
|
||||||
this.source = source;
|
|
||||||
|
public Parser(Lexer lexer) {
|
||||||
|
this.lexer = lexer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,30 +79,30 @@ public class Parser {
|
|||||||
* @throws ParseException If parsing fails.
|
* @throws ParseException If parsing fails.
|
||||||
*/
|
*/
|
||||||
public Executable parse(ScopeBuilder scopeBuilder) {
|
public Executable parse(ScopeBuilder scopeBuilder) {
|
||||||
return new Executable(parseBlock(new Lexer(source), scopeBuilder, ReturnType.VOID), scopeBuilder);
|
return new Executable(parseBlock(scopeBuilder, ReturnType.VOID), scopeBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WhileKeyword parseWhileLoop(Lexer lexer, ScopeBuilder scopeBuilder) {
|
private WhileKeyword parseWhileLoop(ScopeBuilder scopeBuilder) {
|
||||||
SourcePosition start = lexer.consume().getPosition();
|
SourcePosition start = lexer.consume().getPosition();
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.GROUP_BEGIN);
|
ParserUtil.ensureType(lexer.consume(), TokenType.OPEN_PAREN);
|
||||||
scopeBuilder = scopeBuilder.innerLoopScope();
|
scopeBuilder = scopeBuilder.innerLoopScope();
|
||||||
Expression<?> condition = parseExpression(lexer, true, scopeBuilder);
|
Expression<?> condition = parseExpression(true, scopeBuilder);
|
||||||
ParserUtil.ensureReturnType(condition, Expression.ReturnType.BOOLEAN);
|
ParserUtil.ensureReturnType(condition, Expression.ReturnType.BOOLEAN);
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.GROUP_END);
|
ParserUtil.ensureType(lexer.consume(), TokenType.CLOSE_PAREN);
|
||||||
return new WhileKeyword(parseStatementBlock(lexer, scopeBuilder, ReturnType.VOID), (Expression<Boolean>) condition,
|
return new WhileKeyword(parseStatementBlock(scopeBuilder, ReturnType.VOID), (Expression<Boolean>) condition,
|
||||||
start); // While loop
|
start); // While loop
|
||||||
}
|
}
|
||||||
|
|
||||||
private IfKeyword parseIfStatement(Lexer lexer, ScopeBuilder scopeBuilder) {
|
private IfKeyword parseIfStatement(ScopeBuilder scopeBuilder) {
|
||||||
SourcePosition start = lexer.consume().getPosition();
|
SourcePosition start = lexer.consume().getPosition();
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.GROUP_BEGIN);
|
ParserUtil.ensureType(lexer.consume(), TokenType.OPEN_PAREN);
|
||||||
Expression<?> condition = parseExpression(lexer, true, scopeBuilder);
|
Expression<?> condition = parseExpression(true, scopeBuilder);
|
||||||
ParserUtil.ensureReturnType(condition, Expression.ReturnType.BOOLEAN);
|
ParserUtil.ensureReturnType(condition, Expression.ReturnType.BOOLEAN);
|
||||||
|
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.GROUP_END);
|
ParserUtil.ensureType(lexer.consume(), TokenType.CLOSE_PAREN);
|
||||||
|
|
||||||
Block elseBlock = null;
|
Block elseBlock = null;
|
||||||
Block statement = parseStatementBlock(lexer, scopeBuilder, ReturnType.VOID);
|
Block statement = parseStatementBlock(scopeBuilder, ReturnType.VOID);
|
||||||
|
|
||||||
List<Pair<Expression<Boolean>, Block>> elseIf = new ArrayList<>();
|
List<Pair<Expression<Boolean>, Block>> elseIf = new ArrayList<>();
|
||||||
|
|
||||||
@@ -109,11 +110,11 @@ public class Parser {
|
|||||||
lexer.consume(); // Consume else.
|
lexer.consume(); // Consume else.
|
||||||
if(lexer.current().isType(TokenType.IF_STATEMENT)) {
|
if(lexer.current().isType(TokenType.IF_STATEMENT)) {
|
||||||
lexer.consume(); // Consume if.
|
lexer.consume(); // Consume if.
|
||||||
Expression<?> elseCondition = parseExpression(lexer, true, scopeBuilder);
|
Expression<?> elseCondition = parseExpression(true, scopeBuilder);
|
||||||
ParserUtil.ensureReturnType(elseCondition, Expression.ReturnType.BOOLEAN);
|
ParserUtil.ensureReturnType(elseCondition, Expression.ReturnType.BOOLEAN);
|
||||||
elseIf.add(Pair.of((Expression<Boolean>) elseCondition, parseStatementBlock(lexer, scopeBuilder, ReturnType.VOID)));
|
elseIf.add(Pair.of((Expression<Boolean>) elseCondition, parseStatementBlock(scopeBuilder, ReturnType.VOID)));
|
||||||
} else {
|
} else {
|
||||||
elseBlock = parseStatementBlock(lexer, scopeBuilder, ReturnType.VOID);
|
elseBlock = parseStatementBlock(scopeBuilder, ReturnType.VOID);
|
||||||
break; // Else must be last.
|
break; // Else must be last.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,10 +122,10 @@ public class Parser {
|
|||||||
return new IfKeyword(statement, (Expression<Boolean>) condition, elseIf, elseBlock, start); // If statement
|
return new IfKeyword(statement, (Expression<Boolean>) condition, elseIf, elseBlock, start); // If statement
|
||||||
}
|
}
|
||||||
|
|
||||||
private Block parseStatementBlock(Lexer lexer, ScopeBuilder scopeBuilder, ReturnType blockReturnType) {
|
private Block parseStatementBlock(ScopeBuilder scopeBuilder, ReturnType blockReturnType) {
|
||||||
if(lexer.current().isType(TokenType.BLOCK_BEGIN)) {
|
if(lexer.current().isType(TokenType.BLOCK_BEGIN)) {
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.BLOCK_BEGIN);
|
ParserUtil.ensureType(lexer.consume(), TokenType.BLOCK_BEGIN);
|
||||||
Block block = parseBlock(lexer, scopeBuilder, blockReturnType);
|
Block block = parseBlock(scopeBuilder, blockReturnType);
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.BLOCK_END);
|
ParserUtil.ensureType(lexer.consume(), TokenType.BLOCK_END);
|
||||||
return block;
|
return block;
|
||||||
} else {
|
} else {
|
||||||
@@ -133,61 +134,61 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ForKeyword parseForLoop(Lexer lexer, ScopeBuilder scopeBuilder) {
|
private ForKeyword parseForLoop(ScopeBuilder scopeBuilder) {
|
||||||
SourcePosition start = lexer.consume().getPosition();
|
SourcePosition start = lexer.consume().getPosition();
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.GROUP_BEGIN);
|
ParserUtil.ensureType(lexer.consume(), TokenType.OPEN_PAREN);
|
||||||
scopeBuilder = scopeBuilder.innerLoopScope(); // new scope
|
scopeBuilder = scopeBuilder.innerLoopScope(); // new scope
|
||||||
Token f = lexer.current();
|
Token f = lexer.current();
|
||||||
ParserUtil.ensureType(f, TokenType.TYPE_NUMBER, TokenType.TYPE_STRING, TokenType.TYPE_BOOLEAN, TokenType.IDENTIFIER);
|
ParserUtil.ensureType(f, TokenType.TYPE_NUMBER, TokenType.TYPE_STRING, TokenType.TYPE_BOOLEAN, TokenType.IDENTIFIER);
|
||||||
Expression<?> initializer;
|
Expression<?> initializer;
|
||||||
if(f.isVariableDeclaration()) {
|
if(f.isVariableDeclaration()) {
|
||||||
Expression<?> forVar = parseDeclaration(lexer, scopeBuilder);
|
Expression<?> forVar = parseDeclaration(scopeBuilder);
|
||||||
Token name = lexer.current();
|
Token name = lexer.current();
|
||||||
if(scopeBuilder.containsFunction(name.getContent()) || scopeBuilder.contains(name.getContent()))
|
if(scopeBuilder.containsFunction(name.getContent()) || scopeBuilder.contains(name.getContent()))
|
||||||
throw new ParseException(name.getContent() + " is already defined in this scope", name.getPosition());
|
throw new ParseException(name.getContent() + " is already defined in this scope", name.getPosition());
|
||||||
initializer = forVar;
|
initializer = forVar;
|
||||||
} else initializer = parseExpression(lexer, true, scopeBuilder);
|
} else initializer = parseExpression(true, scopeBuilder);
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.STATEMENT_END);
|
ParserUtil.ensureType(lexer.consume(), TokenType.STATEMENT_END);
|
||||||
Expression<?> conditional = parseExpression(lexer, true, scopeBuilder);
|
Expression<?> conditional = parseExpression(true, scopeBuilder);
|
||||||
ParserUtil.ensureReturnType(conditional, Expression.ReturnType.BOOLEAN);
|
ParserUtil.ensureReturnType(conditional, Expression.ReturnType.BOOLEAN);
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.STATEMENT_END);
|
ParserUtil.ensureType(lexer.consume(), TokenType.STATEMENT_END);
|
||||||
|
|
||||||
Expression<?> incrementer;
|
Expression<?> incrementer;
|
||||||
Token token = lexer.current();
|
Token token = lexer.current();
|
||||||
if(scopeBuilder.contains(token.getContent())) { // Assume variable assignment
|
if(scopeBuilder.contains(token.getContent())) { // Assume variable assignment
|
||||||
incrementer = parseAssignment(lexer, scopeBuilder);
|
incrementer = parseAssignment(scopeBuilder);
|
||||||
} else incrementer = parseFunctionInvocation(lexer, true, scopeBuilder);
|
} else incrementer = parseFunctionInvocation(true, scopeBuilder);
|
||||||
|
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.GROUP_END);
|
ParserUtil.ensureType(lexer.consume(), TokenType.CLOSE_PAREN);
|
||||||
|
|
||||||
return new ForKeyword(parseStatementBlock(lexer, scopeBuilder, ReturnType.VOID), initializer, (Expression<Boolean>) conditional,
|
return new ForKeyword(parseStatementBlock(scopeBuilder, ReturnType.VOID), initializer, (Expression<Boolean>) conditional,
|
||||||
incrementer,
|
incrementer,
|
||||||
start);
|
start);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Expression<?> parseExpression(Lexer lexer, boolean full, ScopeBuilder scopeBuilder) {
|
private Expression<?> parseExpression(boolean full, ScopeBuilder scopeBuilder) {
|
||||||
boolean booleanInverted = false; // Check for boolean not operator
|
boolean booleanInverted = false; // Check for boolean not operator
|
||||||
boolean negate = false;
|
boolean negate = false;
|
||||||
if(lexer.current().isType(TokenType.BOOLEAN_NOT)) {
|
if(lexer.current().isType(TokenType.BANG)) {
|
||||||
booleanInverted = true;
|
booleanInverted = true;
|
||||||
lexer.consume();
|
lexer.consume();
|
||||||
} else if(lexer.current().isType(TokenType.SUBTRACTION_OPERATOR)) {
|
} else if(lexer.current().isType(TokenType.MINUS)) {
|
||||||
negate = true;
|
negate = true;
|
||||||
lexer.consume();
|
lexer.consume();
|
||||||
}
|
}
|
||||||
|
|
||||||
Token id = lexer.current();
|
Token id = lexer.current();
|
||||||
|
|
||||||
ParserUtil.ensureType(id, TokenType.IDENTIFIER, TokenType.BOOLEAN, TokenType.STRING, TokenType.NUMBER, TokenType.GROUP_BEGIN);
|
ParserUtil.ensureType(id, TokenType.IDENTIFIER, TokenType.BOOLEAN, TokenType.STRING, TokenType.NUMBER, TokenType.OPEN_PAREN);
|
||||||
|
|
||||||
Expression<?> expression;
|
Expression<?> expression;
|
||||||
if(id.isConstant()) {
|
if(id.isConstant()) {
|
||||||
expression = parseConstantExpression(lexer);
|
expression = parseConstantExpression(lexer);
|
||||||
} else if(id.isType(TokenType.GROUP_BEGIN)) { // Parse grouped expression
|
} else if(id.isType(TokenType.OPEN_PAREN)) { // Parse grouped expression
|
||||||
expression = parseExpressionGroup(lexer, scopeBuilder);
|
expression = parseExpressionGroup(scopeBuilder);
|
||||||
} else {
|
} else {
|
||||||
if(scopeBuilder.containsFunction(id.getContent()))
|
if(scopeBuilder.containsFunction(id.getContent()))
|
||||||
expression = parseFunctionInvocation(lexer, false, scopeBuilder);
|
expression = parseFunctionInvocation(false, scopeBuilder);
|
||||||
else if(scopeBuilder.contains(id.getContent())) {
|
else if(scopeBuilder.contains(id.getContent())) {
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.IDENTIFIER);
|
ParserUtil.ensureType(lexer.consume(), TokenType.IDENTIFIER);
|
||||||
String varId = id.getContent();
|
String varId = id.getContent();
|
||||||
@@ -211,7 +212,7 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(full && lexer.current().isBinaryOperator()) { // Parse binary operations
|
if(full && lexer.current().isBinaryOperator()) { // Parse binary operations
|
||||||
return parseBinaryOperation(expression, lexer, scopeBuilder);
|
return parseBinaryOperation(expression, scopeBuilder);
|
||||||
}
|
}
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
@@ -231,27 +232,26 @@ public class Parser {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private Expression<?> parseExpressionGroup(Lexer lexer, ScopeBuilder scopeBuilder) {
|
private Expression<?> parseExpressionGroup(ScopeBuilder scopeBuilder) {
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.GROUP_BEGIN);
|
ParserUtil.ensureType(lexer.consume(), TokenType.OPEN_PAREN);
|
||||||
Expression<?> expression = parseExpression(lexer, true, scopeBuilder); // Parse inside of group as a separate expression
|
Expression<?> expression = parseExpression(true, scopeBuilder); // Parse inside of group as a separate expression
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.GROUP_END);
|
ParserUtil.ensureType(lexer.consume(), TokenType.CLOSE_PAREN);
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BinaryOperation<?, ?> parseBinaryOperation(Expression<?> left, Lexer lexer,
|
private BinaryOperation<?, ?> parseBinaryOperation(Expression<?> left, ScopeBuilder scopeBuilder) {
|
||||||
ScopeBuilder scopeBuilder) {
|
|
||||||
Token binaryOperator = lexer.consume();
|
Token binaryOperator = lexer.consume();
|
||||||
ParserUtil.checkBinaryOperator(binaryOperator);
|
ParserUtil.checkBinaryOperator(binaryOperator);
|
||||||
|
|
||||||
Expression<?> right = parseExpression(lexer, false, scopeBuilder);
|
Expression<?> right = parseExpression(false, scopeBuilder);
|
||||||
|
|
||||||
Token other = lexer.current();
|
Token other = lexer.current();
|
||||||
|
|
||||||
if(ParserUtil.hasPrecedence(binaryOperator.getType(), other.getType()))
|
if(ParserUtil.hasPrecedence(binaryOperator.getType(), other.getType()))
|
||||||
return assemble(left, parseBinaryOperation(right, lexer, scopeBuilder), binaryOperator);
|
return assemble(left, parseBinaryOperation(right, scopeBuilder), binaryOperator);
|
||||||
|
|
||||||
if(other.isBinaryOperator())
|
if(other.isBinaryOperator())
|
||||||
return parseBinaryOperation(assemble(left, right, binaryOperator), lexer, scopeBuilder);
|
return parseBinaryOperation(assemble(left, right, binaryOperator), scopeBuilder);
|
||||||
|
|
||||||
return assemble(left, right, binaryOperator);
|
return assemble(left, right, binaryOperator);
|
||||||
}
|
}
|
||||||
@@ -261,29 +261,29 @@ public class Parser {
|
|||||||
ParserUtil.checkArithmeticOperation(left, right, binaryOperator); // Numeric type checking
|
ParserUtil.checkArithmeticOperation(left, right, binaryOperator); // Numeric type checking
|
||||||
if(binaryOperator.isStrictBooleanOperator()) ParserUtil.checkBooleanOperation(left, right, binaryOperator); // Boolean type checking
|
if(binaryOperator.isStrictBooleanOperator()) ParserUtil.checkBooleanOperation(left, right, binaryOperator); // Boolean type checking
|
||||||
switch(binaryOperator.getType()) {
|
switch(binaryOperator.getType()) {
|
||||||
case ADDITION_OPERATOR:
|
case PLUS:
|
||||||
if(left.returnType().equals(Expression.ReturnType.NUMBER) && right.returnType().equals(Expression.ReturnType.NUMBER)) {
|
if(left.returnType().equals(Expression.ReturnType.NUMBER) && right.returnType().equals(Expression.ReturnType.NUMBER)) {
|
||||||
return new NumberAdditionOperation((Expression<Number>) left, (Expression<Number>) right, binaryOperator.getPosition());
|
return new NumberAdditionOperation((Expression<Number>) left, (Expression<Number>) right, binaryOperator.getPosition());
|
||||||
}
|
}
|
||||||
return new ConcatenationOperation((Expression<Object>) left, (Expression<Object>) right, binaryOperator.getPosition());
|
return new ConcatenationOperation((Expression<Object>) left, (Expression<Object>) right, binaryOperator.getPosition());
|
||||||
case SUBTRACTION_OPERATOR:
|
case MINUS:
|
||||||
return new SubtractionOperation((Expression<Number>) left, (Expression<Number>) right, binaryOperator.getPosition());
|
return new SubtractionOperation((Expression<Number>) left, (Expression<Number>) right, binaryOperator.getPosition());
|
||||||
case MULTIPLICATION_OPERATOR:
|
case STAR:
|
||||||
return new MultiplicationOperation((Expression<Number>) left, (Expression<Number>) right, binaryOperator.getPosition());
|
return new MultiplicationOperation((Expression<Number>) left, (Expression<Number>) right, binaryOperator.getPosition());
|
||||||
case DIVISION_OPERATOR:
|
case FORWARD_SLASH:
|
||||||
return new DivisionOperation((Expression<Number>) left, (Expression<Number>) right, binaryOperator.getPosition());
|
return new DivisionOperation((Expression<Number>) left, (Expression<Number>) right, binaryOperator.getPosition());
|
||||||
case EQUALS_OPERATOR:
|
case EQUALS_EQUALS:
|
||||||
return new EqualsStatement((Expression<Object>) left, (Expression<Object>) right, binaryOperator.getPosition());
|
return new EqualsStatement((Expression<Object>) left, (Expression<Object>) right, binaryOperator.getPosition());
|
||||||
case NOT_EQUALS_OPERATOR:
|
case BANG_EQUALS:
|
||||||
return new NotEqualsStatement((Expression<Object>) left, (Expression<Object>) right, binaryOperator.getPosition());
|
return new NotEqualsStatement((Expression<Object>) left, (Expression<Object>) right, binaryOperator.getPosition());
|
||||||
case GREATER_THAN_OPERATOR:
|
case GREATER:
|
||||||
return new GreaterThanStatement((Expression<Number>) left, (Expression<Number>) right, binaryOperator.getPosition());
|
return new GreaterThanStatement((Expression<Number>) left, (Expression<Number>) right, binaryOperator.getPosition());
|
||||||
case LESS_THAN_OPERATOR:
|
case LESS:
|
||||||
return new LessThanStatement((Expression<Number>) left, (Expression<Number>) right, binaryOperator.getPosition());
|
return new LessThanStatement((Expression<Number>) left, (Expression<Number>) right, binaryOperator.getPosition());
|
||||||
case GREATER_THAN_OR_EQUALS_OPERATOR:
|
case GREATER_EQUAL:
|
||||||
return new GreaterOrEqualsThanStatement((Expression<Number>) left, (Expression<Number>) right,
|
return new GreaterOrEqualsThanStatement((Expression<Number>) left, (Expression<Number>) right,
|
||||||
binaryOperator.getPosition());
|
binaryOperator.getPosition());
|
||||||
case LESS_THAN_OR_EQUALS_OPERATOR:
|
case LESS_EQUALS:
|
||||||
return new LessThanOrEqualsStatement((Expression<Number>) left, (Expression<Number>) right, binaryOperator.getPosition());
|
return new LessThanOrEqualsStatement((Expression<Number>) left, (Expression<Number>) right, binaryOperator.getPosition());
|
||||||
case BOOLEAN_AND:
|
case BOOLEAN_AND:
|
||||||
return new BooleanAndOperation((Expression<Boolean>) left, (Expression<Boolean>) right, binaryOperator.getPosition());
|
return new BooleanAndOperation((Expression<Boolean>) left, (Expression<Boolean>) right, binaryOperator.getPosition());
|
||||||
@@ -296,30 +296,30 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Expression<?> parseDeclaration(Lexer lexer, ScopeBuilder scopeBuilder) {
|
private Expression<?> parseDeclaration(ScopeBuilder scopeBuilder) {
|
||||||
Token type = lexer.consume();
|
Token type = lexer.consume();
|
||||||
|
|
||||||
Token identifier = lexer.consume();
|
Token identifier = lexer.consume();
|
||||||
ParserUtil.ensureType(identifier, TokenType.IDENTIFIER);
|
ParserUtil.ensureType(identifier, TokenType.IDENTIFIER);
|
||||||
|
|
||||||
Token declarationType = lexer.consume();
|
Token declarationType = lexer.consume();
|
||||||
ParserUtil.ensureType(declarationType, TokenType.ASSIGNMENT, TokenType.GROUP_BEGIN);
|
ParserUtil.ensureType(declarationType, TokenType.ASSIGNMENT, TokenType.OPEN_PAREN);
|
||||||
|
|
||||||
return switch(declarationType.getType()) {
|
return switch(declarationType.getType()) {
|
||||||
case ASSIGNMENT -> parseVariableDeclaration(lexer, scopeBuilder, type, identifier);
|
case ASSIGNMENT -> parseVariableDeclaration(scopeBuilder, type, identifier);
|
||||||
case GROUP_BEGIN -> parseFunctionDeclaration(lexer, scopeBuilder, type, identifier);
|
case OPEN_PAREN -> parseFunctionDeclaration(scopeBuilder, type, identifier);
|
||||||
default -> throw new ParseException("Illegal type for declaration: " + type, declarationType.getPosition());
|
default -> throw new ParseException("Illegal type for declaration: " + type, declarationType.getPosition());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Expression<?> parseVariableDeclaration(Lexer lexer, ScopeBuilder scopeBuilder, Token type, Token identifier) {
|
private Expression<?> parseVariableDeclaration(ScopeBuilder scopeBuilder, Token type, Token identifier) {
|
||||||
ParserUtil.ensureType(type, TokenType.TYPE_STRING, TokenType.TYPE_BOOLEAN, TokenType.TYPE_NUMBER);
|
ParserUtil.ensureType(type, TokenType.TYPE_STRING, TokenType.TYPE_BOOLEAN, TokenType.TYPE_NUMBER);
|
||||||
|
|
||||||
if(scopeBuilder.contains(identifier.getContent()))
|
if(scopeBuilder.contains(identifier.getContent()))
|
||||||
throw new ParseException(identifier.getContent() + " is already defined in this scope", identifier.getPosition());
|
throw new ParseException(identifier.getContent() + " is already defined in this scope", identifier.getPosition());
|
||||||
|
|
||||||
Expression<?> value = parseExpression(lexer, true, scopeBuilder);
|
Expression<?> value = parseExpression(true, scopeBuilder);
|
||||||
ParserUtil.ensureReturnType(value, ParserUtil.getVariableReturnType(type));
|
ParserUtil.ensureReturnType(value, ParserUtil.getVariableReturnType(type));
|
||||||
|
|
||||||
String variableName = identifier.getContent();
|
String variableName = identifier.getContent();
|
||||||
@@ -334,7 +334,7 @@ public class Parser {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private Expression<?> parseFunctionDeclaration(Lexer lexer, ScopeBuilder scopeBuilder, Token type, Token identifier) {
|
private Expression<?> parseFunctionDeclaration(ScopeBuilder scopeBuilder, Token type, Token identifier) {
|
||||||
ParserUtil.ensureType(type, TokenType.TYPE_STRING, TokenType.TYPE_BOOLEAN, TokenType.TYPE_NUMBER, TokenType.TYPE_VOID);
|
ParserUtil.ensureType(type, TokenType.TYPE_STRING, TokenType.TYPE_BOOLEAN, TokenType.TYPE_NUMBER, TokenType.TYPE_VOID);
|
||||||
|
|
||||||
if(scopeBuilder.contains(identifier.getContent()))
|
if(scopeBuilder.contains(identifier.getContent()))
|
||||||
@@ -345,7 +345,7 @@ public class Parser {
|
|||||||
ScopeBuilder functionBodyScope = scopeBuilder.functionScope();
|
ScopeBuilder functionBodyScope = scopeBuilder.functionScope();
|
||||||
|
|
||||||
// Declare argument names into function body scope
|
// Declare argument names into function body scope
|
||||||
List<Pair<Integer, ReturnType>> argumentInfo = getFunctionArgumentsDeclaration(lexer).stream().map(
|
List<Pair<Integer, ReturnType>> argumentInfo = getFunctionArgumentsDeclaration().stream().map(
|
||||||
arg -> Pair.of(switch(arg.getRight()) {
|
arg -> Pair.of(switch(arg.getRight()) {
|
||||||
case NUMBER -> functionBodyScope.declareNum(arg.getLeft());
|
case NUMBER -> functionBodyScope.declareNum(arg.getLeft());
|
||||||
case BOOLEAN -> functionBodyScope.declareBool(arg.getLeft());
|
case BOOLEAN -> functionBodyScope.declareBool(arg.getLeft());
|
||||||
@@ -353,7 +353,7 @@ public class Parser {
|
|||||||
default -> throw new IllegalArgumentException("Unsupported argument type: " + arg.getRight());
|
default -> throw new IllegalArgumentException("Unsupported argument type: " + arg.getRight());
|
||||||
}, arg.getRight())).toList();
|
}, arg.getRight())).toList();
|
||||||
|
|
||||||
Block body = parseStatementBlock(lexer, functionBodyScope, returnType);
|
Block body = parseStatementBlock(functionBodyScope, returnType);
|
||||||
|
|
||||||
FunctionBuilder<?> functionBuilder = new UserDefinedFunctionBuilder<>(returnType, argumentInfo, body, functionBodyScope);
|
FunctionBuilder<?> functionBuilder = new UserDefinedFunctionBuilder<>(returnType, argumentInfo, body, functionBodyScope);
|
||||||
|
|
||||||
@@ -361,9 +361,9 @@ public class Parser {
|
|||||||
return Expression.NOOP;
|
return Expression.NOOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Pair<String, ReturnType>> getFunctionArgumentsDeclaration(Lexer lexer) {
|
private List<Pair<String, ReturnType>> getFunctionArgumentsDeclaration() {
|
||||||
List<Pair<String, ReturnType>> arguments = new ArrayList<>();
|
List<Pair<String, ReturnType>> arguments = new ArrayList<>();
|
||||||
while(lexer.current().getType() != TokenType.GROUP_END) {
|
while(lexer.current().getType() != TokenType.CLOSE_PAREN) {
|
||||||
// Parse argument type
|
// Parse argument type
|
||||||
Token typeToken = lexer.consume();
|
Token typeToken = lexer.consume();
|
||||||
ParserUtil.ensureType(typeToken, TokenType.TYPE_BOOLEAN, TokenType.TYPE_STRING, TokenType.TYPE_NUMBER);
|
ParserUtil.ensureType(typeToken, TokenType.TYPE_BOOLEAN, TokenType.TYPE_STRING, TokenType.TYPE_NUMBER);
|
||||||
@@ -379,11 +379,11 @@ public class Parser {
|
|||||||
// Consume separator if present, trailing separators are allowed
|
// Consume separator if present, trailing separators are allowed
|
||||||
if(lexer.current().isType(TokenType.SEPARATOR)) lexer.consume();
|
if(lexer.current().isType(TokenType.SEPARATOR)) lexer.consume();
|
||||||
}
|
}
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.GROUP_END);
|
ParserUtil.ensureType(lexer.consume(), TokenType.CLOSE_PAREN);
|
||||||
return arguments;
|
return arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Block parseBlock(Lexer lexer, ScopeBuilder scopeBuilder, ReturnType blockReturnType) {
|
private Block parseBlock(ScopeBuilder scopeBuilder, ReturnType blockReturnType) {
|
||||||
List<Expression<?>> expressions = new ArrayList<>();
|
List<Expression<?>> expressions = new ArrayList<>();
|
||||||
scopeBuilder = scopeBuilder.innerScope();
|
scopeBuilder = scopeBuilder.innerScope();
|
||||||
SourcePosition startPosition = lexer.current().getPosition();
|
SourcePosition startPosition = lexer.current().getPosition();
|
||||||
@@ -428,15 +428,15 @@ public class Parser {
|
|||||||
TokenType.FAIL);
|
TokenType.FAIL);
|
||||||
|
|
||||||
Expression<?> expression = switch(token.getType()) {
|
Expression<?> expression = switch(token.getType()) {
|
||||||
case FOR_LOOP -> parseForLoop(lexer, scopeBuilder);
|
case FOR_LOOP -> parseForLoop(scopeBuilder);
|
||||||
case IF_STATEMENT -> parseIfStatement(lexer, scopeBuilder);
|
case IF_STATEMENT -> parseIfStatement(scopeBuilder);
|
||||||
case WHILE_LOOP -> parseWhileLoop(lexer, scopeBuilder);
|
case WHILE_LOOP -> parseWhileLoop(scopeBuilder);
|
||||||
case IDENTIFIER -> {
|
case IDENTIFIER -> {
|
||||||
if(scopeBuilder.contains(token.getContent())) yield parseAssignment(lexer, scopeBuilder); // Assume variable assignment
|
if(scopeBuilder.contains(token.getContent())) yield parseAssignment(scopeBuilder); // Assume variable assignment
|
||||||
else yield parseFunctionInvocation(lexer, true, scopeBuilder);
|
else yield parseFunctionInvocation(true, scopeBuilder);
|
||||||
}
|
}
|
||||||
case TYPE_NUMBER, TYPE_STRING, TYPE_BOOLEAN, TYPE_VOID -> parseDeclaration(lexer, scopeBuilder);
|
case TYPE_NUMBER, TYPE_STRING, TYPE_BOOLEAN, TYPE_VOID -> parseDeclaration(scopeBuilder);
|
||||||
case RETURN -> parseReturn(lexer, scopeBuilder);
|
case RETURN -> parseReturn(scopeBuilder);
|
||||||
case BREAK -> new BreakKeyword(lexer.consume().getPosition());
|
case BREAK -> new BreakKeyword(lexer.consume().getPosition());
|
||||||
case CONTINUE -> new ContinueKeyword(lexer.consume().getPosition());
|
case CONTINUE -> new ContinueKeyword(lexer.consume().getPosition());
|
||||||
case FAIL -> new FailKeyword(lexer.consume().getPosition());
|
case FAIL -> new FailKeyword(lexer.consume().getPosition());
|
||||||
@@ -446,24 +446,24 @@ public class Parser {
|
|||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ReturnKeyword parseReturn(Lexer lexer, ScopeBuilder scopeBuilder) {
|
private ReturnKeyword parseReturn(ScopeBuilder scopeBuilder) {
|
||||||
Token returnToken = lexer.consume();
|
Token returnToken = lexer.consume();
|
||||||
ParserUtil.ensureType(returnToken, TokenType.RETURN);
|
ParserUtil.ensureType(returnToken, TokenType.RETURN);
|
||||||
Expression<?> data = null;
|
Expression<?> data = null;
|
||||||
if(!lexer.current().isType(TokenType.STATEMENT_END)) {
|
if(!lexer.current().isType(TokenType.STATEMENT_END)) {
|
||||||
data = parseExpression(lexer, true, scopeBuilder);
|
data = parseExpression(true, scopeBuilder);
|
||||||
}
|
}
|
||||||
return new ReturnKeyword(data, returnToken.getPosition());
|
return new ReturnKeyword(data, returnToken.getPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
private VariableAssignmentNode<?> parseAssignment(Lexer lexer, ScopeBuilder scopeBuilder) {
|
private VariableAssignmentNode<?> parseAssignment(ScopeBuilder scopeBuilder) {
|
||||||
Token identifier = lexer.consume();
|
Token identifier = lexer.consume();
|
||||||
|
|
||||||
ParserUtil.ensureType(identifier, TokenType.IDENTIFIER);
|
ParserUtil.ensureType(identifier, TokenType.IDENTIFIER);
|
||||||
|
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.ASSIGNMENT);
|
ParserUtil.ensureType(lexer.consume(), TokenType.ASSIGNMENT);
|
||||||
|
|
||||||
Expression<?> value = parseExpression(lexer, true, scopeBuilder);
|
Expression<?> value = parseExpression(true, scopeBuilder);
|
||||||
|
|
||||||
String id = identifier.getContent();
|
String id = identifier.getContent();
|
||||||
|
|
||||||
@@ -479,18 +479,18 @@ public class Parser {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private Expression<?> parseFunctionInvocation(Lexer lexer, boolean fullStatement, ScopeBuilder scopeBuilder) {
|
private Expression<?> parseFunctionInvocation(boolean fullStatement, ScopeBuilder scopeBuilder) {
|
||||||
Token identifier = lexer.consume();
|
Token identifier = lexer.consume();
|
||||||
ParserUtil.ensureType(identifier, TokenType.IDENTIFIER); // First token must be identifier
|
ParserUtil.ensureType(identifier, TokenType.IDENTIFIER); // First token must be identifier
|
||||||
|
|
||||||
if(!scopeBuilder.containsFunction(identifier.getContent()))
|
if(!scopeBuilder.containsFunction(identifier.getContent()))
|
||||||
throw new ParseException("Function \"" + identifier.getContent() + "\" is not defined in this scope", identifier.getPosition());
|
throw new ParseException("Function \"" + identifier.getContent() + "\" is not defined in this scope", identifier.getPosition());
|
||||||
|
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.GROUP_BEGIN); // Second is body begin
|
ParserUtil.ensureType(lexer.consume(), TokenType.OPEN_PAREN); // Second is body begin
|
||||||
|
|
||||||
List<Expression<?>> args = getFunctionArgs(lexer, scopeBuilder); // Extract arguments, consume the rest.
|
List<Expression<?>> args = getFunctionArgs(scopeBuilder); // Extract arguments, consume the rest.
|
||||||
|
|
||||||
ParserUtil.ensureType(lexer.consume(), TokenType.GROUP_END); // Remove body end
|
ParserUtil.ensureType(lexer.consume(), TokenType.CLOSE_PAREN); // Remove body end
|
||||||
|
|
||||||
if(fullStatement) ParserUtil.ensureType(lexer.current(), TokenType.STATEMENT_END);
|
if(fullStatement) ParserUtil.ensureType(lexer.current(), TokenType.STATEMENT_END);
|
||||||
|
|
||||||
@@ -516,12 +516,12 @@ public class Parser {
|
|||||||
throw new UnsupportedOperationException("Unsupported function: " + identifier.getContent());
|
throw new UnsupportedOperationException("Unsupported function: " + identifier.getContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Expression<?>> getFunctionArgs(Lexer lexer, ScopeBuilder scopeBuilder) {
|
private List<Expression<?>> getFunctionArgs(ScopeBuilder scopeBuilder) {
|
||||||
List<Expression<?>> args = new ArrayList<>();
|
List<Expression<?>> args = new ArrayList<>();
|
||||||
|
|
||||||
while(!lexer.current().isType(TokenType.GROUP_END)) {
|
while(!lexer.current().isType(TokenType.CLOSE_PAREN)) {
|
||||||
args.add(parseExpression(lexer, true, scopeBuilder));
|
args.add(parseExpression(true, scopeBuilder));
|
||||||
ParserUtil.ensureType(lexer.current(), TokenType.SEPARATOR, TokenType.GROUP_END);
|
ParserUtil.ensureType(lexer.current(), TokenType.SEPARATOR, TokenType.CLOSE_PAREN);
|
||||||
if(lexer.current().isType(TokenType.SEPARATOR)) lexer.consume();
|
if(lexer.current().isType(TokenType.SEPARATOR)) lexer.consume();
|
||||||
}
|
}
|
||||||
return args;
|
return args;
|
||||||
|
|||||||
+10
-10
@@ -21,21 +21,21 @@ import com.dfsek.terra.addons.terrascript.parser.lang.Expression;
|
|||||||
public class ParserUtil {
|
public class ParserUtil {
|
||||||
|
|
||||||
private static final Map<TokenType, Map<TokenType, Boolean>> PRECEDENCE = new HashMap<>(); // If second has precedence, true.
|
private static final Map<TokenType, Map<TokenType, Boolean>> PRECEDENCE = new HashMap<>(); // If second has precedence, true.
|
||||||
private static final List<TokenType> ARITHMETIC = Arrays.asList(TokenType.ADDITION_OPERATOR, TokenType.SUBTRACTION_OPERATOR,
|
private static final List<TokenType> ARITHMETIC = Arrays.asList(TokenType.PLUS, TokenType.MINUS,
|
||||||
TokenType.MULTIPLICATION_OPERATOR, TokenType.DIVISION_OPERATOR,
|
TokenType.STAR, TokenType.FORWARD_SLASH,
|
||||||
TokenType.MODULO_OPERATOR);
|
TokenType.MODULO_OPERATOR);
|
||||||
private static final List<TokenType> COMPARISON = Arrays.asList(TokenType.EQUALS_OPERATOR, TokenType.NOT_EQUALS_OPERATOR,
|
private static final List<TokenType> COMPARISON = Arrays.asList(TokenType.EQUALS_EQUALS, TokenType.BANG_EQUALS,
|
||||||
TokenType.LESS_THAN_OPERATOR, TokenType.LESS_THAN_OR_EQUALS_OPERATOR,
|
TokenType.LESS, TokenType.LESS_EQUALS,
|
||||||
TokenType.GREATER_THAN_OPERATOR,
|
TokenType.GREATER,
|
||||||
TokenType.GREATER_THAN_OR_EQUALS_OPERATOR);
|
TokenType.GREATER_EQUAL);
|
||||||
|
|
||||||
static { // Setup precedence
|
static { // Setup precedence
|
||||||
Map<TokenType, Boolean> add = new HashMap<>(); // Addition/subtraction before Multiplication/division.
|
Map<TokenType, Boolean> add = new HashMap<>(); // Addition/subtraction before Multiplication/division.
|
||||||
add.put(TokenType.MULTIPLICATION_OPERATOR, true);
|
add.put(TokenType.STAR, true);
|
||||||
add.put(TokenType.DIVISION_OPERATOR, true);
|
add.put(TokenType.FORWARD_SLASH, true);
|
||||||
|
|
||||||
PRECEDENCE.put(TokenType.ADDITION_OPERATOR, add);
|
PRECEDENCE.put(TokenType.PLUS, add);
|
||||||
PRECEDENCE.put(TokenType.SUBTRACTION_OPERATOR, add);
|
PRECEDENCE.put(TokenType.MINUS, add);
|
||||||
|
|
||||||
Map<TokenType, Boolean> numericBoolean = new HashMap<>();
|
Map<TokenType, Boolean> numericBoolean = new HashMap<>();
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
package com.dfsek.terra.addons.terrascript.script;
|
package com.dfsek.terra.addons.terrascript.script;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.terrascript.lexer.Lexer;
|
||||||
|
|
||||||
import net.jafama.FastMath;
|
import net.jafama.FastMath;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -62,18 +64,18 @@ public class StructureScript implements Structure, Keyed<StructureScript> {
|
|||||||
public StructureScript(InputStream source, RegistryKey id, Platform platform, Registry<Structure> structureRegistry,
|
public StructureScript(InputStream source, RegistryKey id, Platform platform, Registry<Structure> structureRegistry,
|
||||||
Registry<LootTable> lootRegistry,
|
Registry<LootTable> lootRegistry,
|
||||||
Registry<FunctionBuilder> functionRegistry) {
|
Registry<FunctionBuilder> functionRegistry) {
|
||||||
Parser parser;
|
Lexer lexer;
|
||||||
try {
|
try {
|
||||||
parser = new Parser(IOUtils.toString(source, Charset.defaultCharset()));
|
lexer = new Lexer(IOUtils.toString(source, Charset.defaultCharset()));
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
Parser parser = new Parser(lexer);
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.profile = "terrascript_direct:" + id;
|
this.profile = "terrascript_direct:" + id;
|
||||||
|
|
||||||
ScopeBuilder scope = new ScopeBuilder();
|
ScopeBuilder scope = new ScopeBuilder();
|
||||||
|
|
||||||
//noinspection unchecked
|
|
||||||
functionRegistry.forEach((key, function) -> scope.registerFunction(key.getID(), function)); // Register registry functions.
|
functionRegistry.forEach((key, function) -> scope.registerFunction(key.getID(), function)); // Register registry functions.
|
||||||
|
|
||||||
scope
|
scope
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
package structure;
|
package structure;
|
||||||
|
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.terrascript.lexer.Lexer;
|
||||||
import com.dfsek.terra.addons.terrascript.parser.lang.Scope.ScopeBuilder;
|
import com.dfsek.terra.addons.terrascript.parser.lang.Scope.ScopeBuilder;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
@@ -32,8 +33,8 @@ import com.dfsek.terra.addons.terrascript.lexer.SourcePosition;
|
|||||||
public class ParserTest {
|
public class ParserTest {
|
||||||
@Test
|
@Test
|
||||||
public void parse() throws IOException, ParseException {
|
public void parse() throws IOException, ParseException {
|
||||||
Parser parser = new Parser(
|
Lexer lexer = new Lexer(IOUtils.toString(Objects.requireNonNull(getClass().getResourceAsStream("/test.tesf")), Charset.defaultCharset()));
|
||||||
IOUtils.toString(Objects.requireNonNull(getClass().getResourceAsStream("/test.tesf")), Charset.defaultCharset()));
|
Parser parser = new Parser(lexer);
|
||||||
|
|
||||||
ScopeBuilder scope = new ScopeBuilder();
|
ScopeBuilder scope = new ScopeBuilder();
|
||||||
scope.registerFunction("test", new FunctionBuilder<Test1>() {
|
scope.registerFunction("test", new FunctionBuilder<Test1>() {
|
||||||
|
|||||||
Reference in New Issue
Block a user