Commit 555dc5dd authored by Ticxo's avatar Ticxo
Browse files

Directly move everything to this repo

parent 2ff9eb39
package com.bedrockk.molang.ast.binaryop;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.ast.BinaryOpExpression;
import com.bedrockk.molang.runtime.MoLangEnvironment;
import com.bedrockk.molang.runtime.MoScope;
import com.bedrockk.molang.runtime.value.DoubleValue;
import com.bedrockk.molang.runtime.value.MoValue;
public class SmallerOrEqualExpression extends BinaryOpExpression {
public SmallerOrEqualExpression(Expression left, Expression right) {
super(left, right);
}
@Override
public String getSigil() {
return "<=";
}
@Override
public MoValue evaluate(MoScope scope, MoLangEnvironment environment) {
return new DoubleValue(left.evaluate(scope, environment).asDouble() <= right.evaluate(scope, environment).asDouble());
}
}
package com.bedrockk.molang.parser;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.parser.tokenizer.Token;
public interface InfixParselet {
Expression parse(MoLangParser parser, Token token, Expression leftExpr);
default Precedence getPrecedence() {
return Precedence.ANYTHING;
}
}
package com.bedrockk.molang.parser;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.parser.parselet.*;
import com.bedrockk.molang.parser.tokenizer.Token;
import com.bedrockk.molang.parser.tokenizer.TokenIterator;
import com.bedrockk.molang.parser.tokenizer.TokenType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class MoLangParser {
private final static Map<TokenType, PrefixParselet> prefixParselets = new HashMap<>();
private final static Map<TokenType, InfixParselet> infixParselets = new HashMap<>();
private final TokenIterator tokenIterator;
private final List<Token> readTokens = new ArrayList<>();
static {
prefixParselets.put(TokenType.NAME, new NameParselet());
prefixParselets.put(TokenType.STRING, new StringParselet());
prefixParselets.put(TokenType.NUMBER, new NumberParselet());
prefixParselets.put(TokenType.TRUE, new BooleanParselet());
prefixParselets.put(TokenType.FALSE, new BooleanParselet());
prefixParselets.put(TokenType.RETURN, new ReturnParselet());
prefixParselets.put(TokenType.CONTINUE, new ContinueParselet());
prefixParselets.put(TokenType.BREAK, new BreakParselet());
prefixParselets.put(TokenType.LOOP, new LoopParselet());
prefixParselets.put(TokenType.FOR_EACH, new ForEachParselet());
prefixParselets.put(TokenType.THIS, new ThisParselet());
prefixParselets.put(TokenType.BRACKET_LEFT, new GroupParselet());
prefixParselets.put(TokenType.CURLY_BRACKET_LEFT, new BracketScopeParselet());
prefixParselets.put(TokenType.MINUS, new UnaryMinusParselet());
prefixParselets.put(TokenType.PLUS, new UnaryPlusParselet());
prefixParselets.put(TokenType.BANG, new BooleanNotParselet());
infixParselets.put(TokenType.QUESTION, new TernaryParselet());
infixParselets.put(TokenType.ARRAY_LEFT, new ArrayAccessParselet());
infixParselets.put(TokenType.PLUS, new GenericBinaryOpParselet(Precedence.SUM));
infixParselets.put(TokenType.MINUS, new GenericBinaryOpParselet(Precedence.SUM));
infixParselets.put(TokenType.SLASH, new GenericBinaryOpParselet(Precedence.PRODUCT));
infixParselets.put(TokenType.ASTERISK, new GenericBinaryOpParselet(Precedence.PRODUCT));
infixParselets.put(TokenType.EQUALS, new GenericBinaryOpParselet(Precedence.COMPARE));
infixParselets.put(TokenType.NOT_EQUALS, new GenericBinaryOpParselet(Precedence.COMPARE));
infixParselets.put(TokenType.GREATER, new GenericBinaryOpParselet(Precedence.COMPARE));
infixParselets.put(TokenType.GREATER_OR_EQUALS, new GenericBinaryOpParselet(Precedence.COMPARE));
infixParselets.put(TokenType.SMALLER, new GenericBinaryOpParselet(Precedence.COMPARE));
infixParselets.put(TokenType.SMALLER_OR_EQUALS, new GenericBinaryOpParselet(Precedence.COMPARE));
infixParselets.put(TokenType.AND, new GenericBinaryOpParselet(Precedence.AND));
infixParselets.put(TokenType.OR, new GenericBinaryOpParselet(Precedence.OR));
infixParselets.put(TokenType.COALESCE, new GenericBinaryOpParselet(Precedence.COALESCE));
infixParselets.put(TokenType.ARROW, new GenericBinaryOpParselet(Precedence.ARROW));
infixParselets.put(TokenType.ASSIGN, new AssignParselet());
}
public MoLangParser(TokenIterator iterator) {
this.tokenIterator = iterator;
}
public List<Expression> parse() {
List<Expression> exprs = new ArrayList<>();
do {
Expression expr = parseExpression();
if (expr != null) {
exprs.add(expr);
} else {
break;
}
} while (matchToken(TokenType.SEMICOLON));
return exprs;
}
public Expression parseExpression() {
return parseExpression(Precedence.ANYTHING);
}
public Expression parseExpression(Precedence precedence) {
Token token = consumeToken();
if (token.getType().equals(TokenType.EOF)) {
return null;
}
PrefixParselet parselet = prefixParselets.get(token.getType());
if (parselet == null) {
throw new RuntimeException("Cannot parse " + token.getType().name() + " expression");
}
Expression expr = parselet.parse(this, token);
initExpr(expr, token);
return parseInfixExpression(expr, precedence);
}
private Expression parseInfixExpression(Expression left, Precedence precedence) {
Token token;
while (precedence.ordinal() < getPrecedence().ordinal()) {
token = consumeToken();
left = infixParselets.get(token.getType()).parse(this, token, left);
initExpr(left, token);
}
return left;
}
private void initExpr(Expression expression, Token token) {
expression.getAttributes().put("position", token.getPosition());
}
private Precedence getPrecedence() {
Token token = readToken();
if (token != null) {
InfixParselet parselet = infixParselets.get(token.getType());
if (parselet != null) {
return parselet.getPrecedence();
}
}
return Precedence.ANYTHING;
}
public List<Expression> parseArgs() {
List<Expression> args = new ArrayList<>();
if (matchToken(TokenType.BRACKET_LEFT)) {
if (!matchToken(TokenType.BRACKET_RIGHT)) { // check for empty groups
do {
args.add(parseExpression());
} while (matchToken(TokenType.COMMA));
consumeToken(TokenType.BRACKET_RIGHT);
}
}
return args;
}
public String fixNameShortcut(String name) {
String[] splits = name.split("\\.");
switch (splits[0]) {
case "q" -> splits[0] = "query";
case "v" -> splits[0] = "variable";
case "t" -> splits[0] = "temp";
case "c" -> splits[0] = "context";
}
return String.join(".", splits);
}
public String getNameHead(String name) {
return name.split("\\.")[0];
}
public Token consumeToken() {
return consumeToken(null);
}
public Token consumeToken(TokenType expectedType) {
tokenIterator.step();
Token token = readToken();
if (expectedType != null) {
if (!token.getType().equals(expectedType)) {
throw new RuntimeException("Expected token " + expectedType.name() + " and " + token.getType().name() + " given");
}
}
return readTokens.remove(0);
}
public boolean matchToken(TokenType expectedType) {
return matchToken(expectedType, true);
}
public boolean matchToken(TokenType expectedType, boolean consume) {
Token token = readToken();
if (token == null || !token.getType().equals(expectedType)) {
return false;
} else {
if (consume) {
consumeToken();
}
return true;
}
}
private Token readToken() {
return readToken(0);
}
private Token readToken(int distance) {
while (distance >= readTokens.size()) {
readTokens.add(tokenIterator.next());
}
return readTokens.get(distance);
}
}
package com.bedrockk.molang.parser;
public enum Precedence {
ANYTHING,
SCOPE,
ASSIGNMENT,
CONDITIONAL,
ARRAY_ACCESS,
COALESCE,
AND,
OR,
COMPARE,
SUM,
PRODUCT,
PREFIX,
ARROW
}
package com.bedrockk.molang.parser;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.parser.tokenizer.Token;
public interface PrefixParselet {
Expression parse(MoLangParser parser, Token token);
}
package com.bedrockk.molang.parser.parselet;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.ast.ArrayAccessExpression;
import com.bedrockk.molang.parser.InfixParselet;
import com.bedrockk.molang.parser.MoLangParser;
import com.bedrockk.molang.parser.Precedence;
import com.bedrockk.molang.parser.tokenizer.Token;
import com.bedrockk.molang.parser.tokenizer.TokenType;
public class ArrayAccessParselet implements InfixParselet {
@Override
public Expression parse(MoLangParser parser, Token token, Expression leftExpr) {
Expression index = parser.parseExpression(getPrecedence());
parser.consumeToken(TokenType.ARRAY_RIGHT);
return new ArrayAccessExpression(leftExpr, index);
}
@Override
public Precedence getPrecedence() {
return Precedence.ARRAY_ACCESS;
}
}
package com.bedrockk.molang.parser.parselet;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.ast.AssignExpression;
import com.bedrockk.molang.parser.InfixParselet;
import com.bedrockk.molang.parser.MoLangParser;
import com.bedrockk.molang.parser.Precedence;
import com.bedrockk.molang.parser.tokenizer.Token;
public class AssignParselet implements InfixParselet {
@Override
public Expression parse(MoLangParser parser, Token token, Expression leftExpr) {
return new AssignExpression(leftExpr, parser.parseExpression(getPrecedence()));
}
@Override
public Precedence getPrecedence() {
return Precedence.ASSIGNMENT;
}
}
package com.bedrockk.molang.parser.parselet;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.ast.BooleanNotExpression;
import com.bedrockk.molang.parser.MoLangParser;
import com.bedrockk.molang.parser.Precedence;
import com.bedrockk.molang.parser.PrefixParselet;
import com.bedrockk.molang.parser.tokenizer.Token;
public class BooleanNotParselet implements PrefixParselet {
@Override
public Expression parse(MoLangParser parser, Token token) {
return new BooleanNotExpression(parser.parseExpression(Precedence.PREFIX));
}
}
package com.bedrockk.molang.parser.parselet;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.ast.BooleanExpression;
import com.bedrockk.molang.parser.MoLangParser;
import com.bedrockk.molang.parser.PrefixParselet;
import com.bedrockk.molang.parser.tokenizer.Token;
public class BooleanParselet implements PrefixParselet {
@Override
public Expression parse(MoLangParser parser, Token token) {
return new BooleanExpression(Boolean.parseBoolean(token.getText()));
}
}
package com.bedrockk.molang.parser.parselet;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.ast.StatementExpression;
import com.bedrockk.molang.parser.MoLangParser;
import com.bedrockk.molang.parser.Precedence;
import com.bedrockk.molang.parser.PrefixParselet;
import com.bedrockk.molang.parser.tokenizer.Token;
import com.bedrockk.molang.parser.tokenizer.TokenType;
import java.util.ArrayList;
import java.util.List;
public class BracketScopeParselet implements PrefixParselet {
@Override
public Expression parse(MoLangParser parser, Token token) {
List<Expression> exprs = new ArrayList<>();
if (!parser.matchToken(TokenType.CURLY_BRACKET_RIGHT)) {
do {
if (parser.matchToken(TokenType.CURLY_BRACKET_RIGHT, false)) {
break;
}
exprs.add(parser.parseExpression(Precedence.SCOPE));
} while (parser.matchToken(TokenType.SEMICOLON));
parser.consumeToken(TokenType.CURLY_BRACKET_RIGHT);
}
return new StatementExpression(exprs.toArray(new Expression[0]));
}
}
package com.bedrockk.molang.parser.parselet;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.ast.BreakExpression;
import com.bedrockk.molang.parser.MoLangParser;
import com.bedrockk.molang.parser.PrefixParselet;
import com.bedrockk.molang.parser.tokenizer.Token;
public class BreakParselet implements PrefixParselet {
@Override
public Expression parse(MoLangParser parser, Token token) {
return new BreakExpression();
}
}
package com.bedrockk.molang.parser.parselet;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.ast.ContinueExpression;
import com.bedrockk.molang.parser.MoLangParser;
import com.bedrockk.molang.parser.PrefixParselet;
import com.bedrockk.molang.parser.tokenizer.Token;
public class ContinueParselet implements PrefixParselet {
@Override
public Expression parse(MoLangParser parser, Token token) {
return new ContinueExpression();
}
}
package com.bedrockk.molang.parser.parselet;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.ast.ForEachExpression;
import com.bedrockk.molang.parser.MoLangParser;
import com.bedrockk.molang.parser.PrefixParselet;
import com.bedrockk.molang.parser.tokenizer.Token;
import java.util.List;
public class ForEachParselet implements PrefixParselet {
@Override
public Expression parse(MoLangParser parser, Token token) {
List<Expression> args = parser.parseArgs();
if (args.size() != 3) {
throw new RuntimeException("ForEach: Expected 3 argument, " + args.size() + " argument given");
} else {
return new ForEachExpression(args.get(0), args.get(1), args.get(2));
}
}
}
package com.bedrockk.molang.parser.parselet;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.ast.binaryop.*;
import com.bedrockk.molang.parser.InfixParselet;
import com.bedrockk.molang.parser.MoLangParser;
import com.bedrockk.molang.parser.Precedence;
import com.bedrockk.molang.parser.tokenizer.Token;
import lombok.Value;
@Value
public class GenericBinaryOpParselet implements InfixParselet {
Precedence precedence;
@Override
public Expression parse(MoLangParser parser, Token token, Expression leftExpr) {
Expression rightExpr = parser.parseExpression(getPrecedence());
switch (token.getType()) {
case ARROW:
return new ArrowExpression(leftExpr, rightExpr);
case AND:
return new BooleanAndExpression(leftExpr, rightExpr);
case OR:
return new BooleanOrExpression(leftExpr, rightExpr);
case COALESCE:
return new CoalesceExpression(leftExpr, rightExpr);
case SLASH:
return new DivideExpression(leftExpr, rightExpr);
case EQUALS:
return new EqualExpression(leftExpr, rightExpr);
case GREATER:
return new GreaterExpression(leftExpr, rightExpr);
case GREATER_OR_EQUALS:
return new GreaterOrEqualExpression(leftExpr, rightExpr);
case MINUS:
return new MinusExpression(leftExpr, rightExpr);
case NOT_EQUALS:
return new NotEqualExpression(leftExpr, rightExpr);
case PLUS:
return new PlusExpression(leftExpr, rightExpr);
case ASTERISK:
return new PowExpression(leftExpr, rightExpr);
case SMALLER:
return new SmallerExpression(leftExpr, rightExpr);
case SMALLER_OR_EQUALS:
return new SmallerOrEqualExpression(leftExpr, rightExpr);
}
return null;
}
@Override
public Precedence getPrecedence() {
return precedence;
}
}
package com.bedrockk.molang.parser.parselet;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.parser.MoLangParser;
import com.bedrockk.molang.parser.PrefixParselet;
import com.bedrockk.molang.parser.tokenizer.Token;
import com.bedrockk.molang.parser.tokenizer.TokenType;
public class GroupParselet implements PrefixParselet {
@Override
public Expression parse(MoLangParser parser, Token token) {
// this only for conditions
Expression expr = parser.parseExpression();
parser.consumeToken(TokenType.BRACKET_RIGHT);
return expr;
}
}
package com.bedrockk.molang.parser.parselet;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.ast.LoopExpression;
import com.bedrockk.molang.parser.MoLangParser;
import com.bedrockk.molang.parser.PrefixParselet;
import com.bedrockk.molang.parser.tokenizer.Token;
import java.util.List;
public class LoopParselet implements PrefixParselet {
@Override
public Expression parse(MoLangParser parser, Token token) {
List<Expression> args = parser.parseArgs();
if (args.size() != 2) {
throw new RuntimeException("Loop: Expected 2 argument, " + args.size() + " argument given");
} else {
return new LoopExpression(args.get(0), args.get(1));
}
}
}
package com.bedrockk.molang.parser.parselet;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.ast.FuncCallExpression;
import com.bedrockk.molang.ast.NameExpression;
import com.bedrockk.molang.parser.MoLangParser;
import com.bedrockk.molang.parser.PrefixParselet;
import com.bedrockk.molang.parser.tokenizer.Token;
import java.util.List;
public class NameParselet implements PrefixParselet {
@Override
public Expression parse(MoLangParser parser, Token token) {
List<Expression> args = parser.parseArgs();
String name = parser.fixNameShortcut(token.getText());
Expression nameExpr = new NameExpression(name);
if (args.size() > 0 || parser.getNameHead(name).equals("query") || parser.getNameHead(name).equals("math")){
return new FuncCallExpression(nameExpr, args.toArray(new Expression[0]));
}
return nameExpr;
}
}
package com.bedrockk.molang.parser.parselet;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.ast.NumberExpression;
import com.bedrockk.molang.parser.MoLangParser;
import com.bedrockk.molang.parser.PrefixParselet;
import com.bedrockk.molang.parser.tokenizer.Token;
public class NumberParselet implements PrefixParselet {
@Override
public Expression parse(MoLangParser parser, Token token) {
return new NumberExpression(Double.parseDouble(token.getText()));
}
}
package com.bedrockk.molang.parser.parselet;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.ast.ReturnExpression;
import com.bedrockk.molang.parser.MoLangParser;
import com.bedrockk.molang.parser.PrefixParselet;
import com.bedrockk.molang.parser.tokenizer.Token;
public class ReturnParselet implements PrefixParselet {
@Override
public Expression parse(MoLangParser parser, Token token) {
return new ReturnExpression(parser.parseExpression());
}
}
package com.bedrockk.molang.parser.parselet;
import com.bedrockk.molang.Expression;
import com.bedrockk.molang.ast.StringExpression;
import com.bedrockk.molang.parser.MoLangParser;
import com.bedrockk.molang.parser.PrefixParselet;
import com.bedrockk.molang.parser.tokenizer.Token;
public class StringParselet implements PrefixParselet {
@Override
public Expression parse(MoLangParser parser, Token token) {
return new StringExpression(token.getText());
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment