use of io.github.wysohn.triggerreactor.core.script.parser.Node in project TriggerReactor by wysohn.
the class ParserTest method testPlaceholder.
@Test
public void testPlaceholder() throws Exception {
Charset charset = Charset.forName("UTF-8");
String text = "" + "x = 10;" + "#MESSAGE $placeholdertest:0:x:5:true;";
Lexer lexer = new Lexer(text, charset);
Parser parser = new Parser(lexer);
Node root = parser.parse();
Queue<Node> queue = new LinkedList<Node>();
serializeNode(queue, root);
assertEquals(new Node(new Token(Type.THIS, "<This>")), queue.poll());
assertEquals(new Node(new Token(Type.ID, "x")), queue.poll());
assertEquals(new Node(new Token(Type.OPERATOR, ".")), queue.poll());
assertEquals(new Node(new Token(Type.INTEGER, "10")), queue.poll());
assertEquals(new Node(new Token(Type.OPERATOR, "=")), queue.poll());
assertEquals(new Node(new Token(Type.INTEGER, "0")), queue.poll());
assertEquals(new Node(new Token(Type.THIS, "<This>")), queue.poll());
assertEquals(new Node(new Token(Type.ID, "x")), queue.poll());
assertEquals(new Node(new Token(Type.OPERATOR, ".")), queue.poll());
assertEquals(new Node(new Token(Type.INTEGER, "5")), queue.poll());
assertEquals(new Node(new Token(Type.BOOLEAN, "true")), queue.poll());
assertEquals(new Node(new Token(Type.PLACEHOLDER, "placeholdertest")), queue.poll());
assertEquals(new Node(new Token(Type.EXECUTOR, "MESSAGE")), queue.poll());
assertEquals(new Node(new Token(Type.ROOT, "<ROOT>")), queue.poll());
assertEquals(0, queue.size());
}
use of io.github.wysohn.triggerreactor.core.script.parser.Node in project TriggerReactor by wysohn.
the class ParserTest method testParam.
@Test
public void testParam() throws IOException, LexerException, ParserException {
Charset charset = Charset.forName("UTF-8");
String text = "#SOUND player.getLocation() \"LEVEL_UP\" 1.0 1.0";
Lexer lexer = new Lexer(text, charset);
Parser parser = new Parser(lexer);
Node root = parser.parse();
Queue<Node> queue = new LinkedList<Node>();
serializeNode(queue, root);
assertEquals(new Node(new Token(Type.THIS, "<This>")), queue.poll());
assertEquals(new Node(new Token(Type.ID, "player")), queue.poll());
assertEquals(new Node(new Token(Type.OPERATOR, ".")), queue.poll());
assertEquals(new Node(new Token(Type.CALL, "getLocation")), queue.poll());
assertEquals(new Node(new Token(Type.OPERATOR, ".")), queue.poll());
assertEquals(new Node(new Token(Type.STRING, "LEVEL_UP")), queue.poll());
assertEquals(new Node(new Token(Type.DECIMAL, "1.0")), queue.poll());
assertEquals(new Node(new Token(Type.DECIMAL, "1.0")), queue.poll());
assertEquals(new Node(new Token(Type.EXECUTOR, "SOUND")), queue.poll());
assertEquals(new Node(new Token(Type.ROOT, "<ROOT>")), queue.poll());
assertEquals(0, queue.size());
}
use of io.github.wysohn.triggerreactor.core.script.parser.Node in project TriggerReactor by wysohn.
the class JavaPluginBridge method createInterrupter.
@Override
public ProcessInterrupter createInterrupter(Object e, Interpreter interpreter, Map<UUID, Long> cooldowns) {
return new ProcessInterrupter() {
@Override
public boolean onNodeProcess(Node node) {
if (interpreter.isCooldown() && e instanceof PlayerEvent) {
Player player = ((PlayerEvent) e).getPlayer();
UUID uuid = player.getUniqueId();
cooldowns.put(uuid, interpreter.getCooldownEnd());
}
return false;
}
@Override
public boolean onCommand(Object context, String command, Object[] args) {
if ("CALL".equals(command)) {
if (args.length < 1)
throw new RuntimeException("Need parameter [String] or [String, boolean]");
if (args[0] instanceof String) {
Trigger trigger = getNamedTriggerManager().getTriggerForName((String) args[0]);
if (trigger == null)
throw new RuntimeException("No trigger found for Named Trigger " + args[0]);
if (args.length > 1 && args[1] instanceof Boolean) {
trigger.setSync((boolean) args[1]);
} else {
trigger.setSync(true);
}
if (trigger.isSync()) {
trigger.activate(e, interpreter.getVars());
} else {
// use snapshot to avoid concurrent modification
trigger.activate(e, new HashMap<>(interpreter.getVars()));
}
return true;
} else {
throw new RuntimeException("Parameter type not match; it should be a String." + " Make sure to put double quotes, if you provided String literal.");
}
} else if ("CANCELEVENT".equals(command)) {
if (!interpreter.isSync())
throw new RuntimeException("CANCELEVENT is illegal in async mode!");
if (context instanceof Cancellable) {
((Cancellable) context).setCancelled(true);
return true;
} else {
throw new RuntimeException(context + " is not a Cancellable event!");
}
}
return false;
}
};
}
use of io.github.wysohn.triggerreactor.core.script.parser.Node in project TriggerReactor by wysohn.
the class Interpreter method start.
// Check if stopFlag is on before pop Token from stack.
private void start(Node node) throws InterpreterException {
if (stopFlag)
return;
// IF children -- [0] : condition , [1] : true body , [2] : false body(may not exist)
if ("ELSEIF".equals(node.getToken().value) || "IF".equals(node.getToken().value)) {
// [0] condition
start(node.getChildren().get(0));
if (stopFlag)
return;
Token resultToken = stack.pop();
if (isVariable(resultToken)) {
resultToken = unwrapVariable(resultToken);
}
if (resultToken.type == Type.NULLVALUE) {
// null check failed
if (node.getChildren().size() > 2) {
start(node.getChildren().get(2));
}
} else {
// normal IF statement
if (resultToken.isBoolean()) {
boolean result = (boolean) resultToken.value;
if (result) {
// [1] true body
start(node.getChildren().get(1));
} else if (node.getChildren().size() > 2) {
// [2] false body
start(node.getChildren().get(2));
}
} else if (resultToken.isInt()) {
int value = resultToken.toInt();
if (value != 0) {
start(node.getChildren().get(1));
} else if (node.getChildren().size() > 2) {
start(node.getChildren().get(2));
}
} else if (resultToken.isDouble()) {
double value = resultToken.toDouble();
if (value != 0.0) {
start(node.getChildren().get(1));
} else if (node.getChildren().size() > 2) {
start(node.getChildren().get(2));
}
} else if (resultToken.value != null) {
// always true if not null
start(node.getChildren().get(1));
} else {
throw new InterpreterException("Unexpected token for IF statement! -- " + resultToken);
}
}
} else if ("WHILE".equals(node.getToken().value)) {
Token resultToken = null;
do {
start(node.getChildren().get(0));
resultToken = stack.pop();
if (resultToken == null)
throw new InterpreterException("Could not find conditon for WHILE statement!");
if (isVariable(resultToken)) {
resultToken = unwrapVariable(resultToken);
}
if (!(resultToken.value instanceof Boolean))
throw new InterpreterException("Unexpected token for WHILE statement! -- " + resultToken);
if ((boolean) resultToken.value) {
start(node.getChildren().get(1));
} else {
break;
}
} while (!stopFlag);
} else if ("FOR".equals(node.getToken().value)) {
start(node.getChildren().get(0));
if (stopFlag)
return;
Token idToken = stack.pop();
if (idToken == null)
throw new InterpreterException("Iteration variable for FOR statement not found!");
if (node.getChildren().get(1).getToken().type != Type.ITERATOR)
throw new InterpreterException("Expected <ITERATOR> but found " + node.getChildren().get(1).getToken());
Node iterNode = node.getChildren().get(1);
if (iterNode.getChildren().size() == 1) {
start(iterNode.getChildren().get(0));
if (stopFlag)
return;
Token valueToken = stack.pop();
if (isVariable(valueToken)) {
valueToken = unwrapVariable(valueToken);
}
if (!valueToken.isIterable())
throw new InterpreterException(valueToken + " is not iterable!");
if (valueToken.isArray()) {
for (int i = 0; i < Array.getLength(valueToken.value); i++) {
Object obj = Array.get(valueToken.value, i);
if (stopFlag)
break;
assignValue(idToken, parseValue(obj));
start(node.getChildren().get(2));
}
} else {
for (Object obj : (Iterable<?>) valueToken.value) {
if (stopFlag)
break;
assignValue(idToken, parseValue(obj));
start(node.getChildren().get(2));
}
}
} else if (iterNode.getChildren().size() == 2) {
Node initNode = iterNode.getChildren().get(0);
if (initNode.getToken().type != Type.INTEGER)
throw new InterpreterException("Init value must be an Integer value! -- " + initNode);
start(initNode);
if (stopFlag)
return;
Token initToken = stack.pop();
Node limitNode = iterNode.getChildren().get(1);
start(limitNode);
if (stopFlag)
return;
Token limitToken = stack.pop();
if (isVariable(limitToken)) {
limitToken = unwrapVariable(limitToken);
}
if (limitToken.type != Type.INTEGER)
throw new InterpreterException("Limit value must be an Integer value! -- " + limitToken);
for (int i = initToken.toInt(); !stopFlag && i < limitToken.toInt(); i++) {
assignValue(idToken, new Token(Type.INTEGER, i));
start(node.getChildren().get(2));
}
} else {
throw new InterpreterException("Number of <ITERATOR> must be 1 or 2!");
}
} else {
for (int i = 0; i < node.getChildren().size(); i++) {
Node child = node.getChildren().get(i);
start(child);
// experimental
if (i == 0) {
if ("&&".equals(node.getToken().value)) {
Token leftBool = stack.pop();
if (isVariable(leftBool)) {
leftBool = unwrapVariable(leftBool);
}
stack.push(leftBool);
if (!leftBool.isBoolean())
throw new InterpreterException("Left of && operator should be Boolean but was " + leftBool);
boolean result = leftBool.toBoolean();
if (!result) {
// false anyway
return;
}
} else if ("||".equals(node.getToken().value)) {
Token leftBool = stack.pop();
if (isVariable(leftBool)) {
leftBool = unwrapVariable(leftBool);
}
stack.push(leftBool);
if (!leftBool.isBoolean())
throw new InterpreterException("Left of || operator should be Boolean but was " + leftBool);
boolean result = leftBool.toBoolean();
if (result) {
// true anyway
return;
}
}
}
}
}
Integer result = interpret(node);
if (result != null) {
switch(result) {
case Executor.STOP:
stopFlag = true;
return;
case Executor.WAIT:
waitFlag = true;
synchronized (this) {
while (waitFlag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
break;
default:
throw new InterpreterException(result + " is not a valid return code!");
}
}
}
use of io.github.wysohn.triggerreactor.core.script.parser.Node in project TriggerReactor by wysohn.
the class Interpreter method startWithContextAndInterrupter.
/**
* Start interpretation.
* @param context The context that can be used by Executors. This is usually Event object for Bukkit plugin.
* @param interupter gives the caller to interrupt the execution
* @throws InterpreterException
*/
public void startWithContextAndInterrupter(Object context, ProcessInterrupter interrupter) throws InterpreterException {
this.context = context;
this.interrupter = interrupter;
Node child = null;
try {
for (int i = 0; i < root.getChildren().size(); i++) start(child = root.getChildren().get(i));
} catch (InterpreterException e) {
throw new InterpreterException("While interpreting " + child, e);
}
}
Aggregations