private boolean compileLeft() { cleft = new ArrayList<Construct>(); if (label != null && label.startsWith("!")) { if (label.length() > 1) { label = label.substring(1); } nolog = true; } for (int i = 0; i < left.size(); i++) { Token t = left.get(i); if (t.value.startsWith("/")) { cleft.add(new Command(t.val(), t.target)); } else if (t.type == Token.TType.VARIABLE) { cleft.add(new Variable(t.val(), null, t.target)); } else if (t.type.equals(TType.FINAL_VAR)) { Variable v = new Variable(t.val(), null, t.target); v.setFinal(true); cleft.add(v); } else if (t.type.equals(TType.LSQUARE_BRACKET)) { if (i + 2 < left.size() && left.get(i + 2).type.equals(TType.OPT_VAR_ASSIGN)) { Variable v = new Variable(left.get(i + 1).val(), left.get(i + 3).val(), t.target); v.setOptional(true); if (left.get(i + 1).type.equals(TType.FINAL_VAR)) { v.setFinal(true); } cleft.add(v); i += 4; } else { t = left.get(i + 1); Variable v = new Variable(t.val(), null, t.target); v.setOptional(true); if (t.val().equals("$")) { v.setFinal(true); } cleft.add(v); i += 2; } } else { cleft.add(new CString(t.val(), t.getTarget())); } } return true; }
public void run(final List<Variable> vars, Environment myEnv, final MethodScriptComplete done) { // Some things, such as the label are determined at compile time this.CurrentEnv = myEnv; this.CurrentEnv.getEnv(GlobalEnv.class).SetLabel(this.label); MCCommandSender p = myEnv.getEnv(CommandHelperEnvironment.class).GetCommandSender(); if (!hasBeenCompiled || compilerError) { Target target = Target.UNKNOWN; if (left.size() >= 1) { try { target = new Target(left.get(0).line_num, left.get(0).file, left.get(0).column); } catch (NullPointerException e) { // Oh well, we tried to get more information } } throw new ConfigRuntimeException( "Unable to run command, script not yet compiled, or a compiler error occured for that command." + " To see the compile error, run /reloadaliases", null, target); } if (p instanceof MCPlayer) { if (CurrentEnv.getEnv(GlobalEnv.class).GetLabel() != null) { PermissionsResolver perms = CurrentEnv.getEnv(GlobalEnv.class).GetPermissionsResolver(); String[] groups = CurrentEnv.getEnv(GlobalEnv.class).GetLabel().split("/"); for (String group : groups) { if (group.startsWith("-") && perms.inGroup(((MCPlayer) p).getName(), group.substring(1))) { // negative permission throw new ConfigRuntimeException( "You do not have permission to use that command", ExceptionType.InsufficientPermissionException, Target.UNKNOWN); } else if (perms.inGroup(((MCPlayer) p).getName(), group)) { // They do have permission. break; } } } } try { for (ParseTree rootNode : cright) { for (Construct tempNode : rootNode.getAllData()) { if (tempNode instanceof Variable) { if (left_vars == null) { throw new ConfigRuntimeException( "$variables may not be used in this context. Only @variables may be.", null, tempNode.getTarget()); } ((Variable) tempNode) .setVal( new CString( Static.resolveDollarVar( left_vars.get(((Variable) tempNode).getName()), vars) .toString(), tempNode.getTarget())); } } MethodScriptCompiler.registerAutoIncludes(CurrentEnv, this); MethodScriptCompiler.execute(rootNode, CurrentEnv, done, this); } } catch (ConfigRuntimeException ex) { // We don't know how to handle this really, so let's pass it up the chain. throw ex; } catch (CancelCommandException e) { // p.sendMessage(e.getMessage()); // The message in the exception is actually empty } catch (LoopBreakException e) { if (p != null) { p.sendMessage("The break() function must be used inside a for() or foreach() loop"); } System.out.println("The break() function must be used inside a for() or foreach() loop"); } catch (LoopContinueException e) { if (p != null) { p.sendMessage("The continue() function must be used inside a for() or foreach() loop"); } System.out.println("The continue() function must be used inside a for() or foreach() loop"); } catch (FunctionReturnException e) { if (myEnv.getEnv(CommandHelperEnvironment.class).GetEvent() != null) { // Oh, we're running in an event handler. Those know how to catch it too. throw e; } if (p != null) { p.sendMessage("The return() function must be used inside a procedure."); } System.out.println("The return() function must be used inside a procedure."); } catch (Throwable t) { System.out.println("An unexpected exception occured during the execution of a script."); t.printStackTrace(); if (p != null) { p.sendMessage( "An unexpected exception occured during the execution of your script. Please check the console for more information."); } } if (done != null) { done.done(null); } }
private boolean verifyLeft() throws ConfigCompileException { boolean inside_opt_var = false; boolean after_no_def_opt_var = false; String lastVar = null; // Go through our token list and readjust non-spaced symbols. Any time we combine a symbol, // the token becomes a string List<Token> tempLeft = new ArrayList<Token>(); for (int i = 0; i < left.size(); i++) { Token t = left.get(i); if (i == 0 && t.type == TType.NEWLINE) { continue; } if (t.type.isSymbol() && left.size() - 1 > i && left.get(i + 1).type != TType.WHITESPACE) { StringBuilder b = new StringBuilder(); b.append(t.value); i++; Token m = left.get(i); while (m.type.isSymbol() && m.type != TType.WHITESPACE) { b.append(m.value); i++; m = left.get(i); } if (m.type != TType.WHITESPACE && m.type != TType.LABEL) { b.append(m.value); } t = new Token(TType.STRING, b.toString(), t.target); if (m.type == TType.LABEL) { tempLeft.add(t); tempLeft.add(m); continue; } } // Go ahead and toString the other symbols too if (t.type.isSymbol()) { t = new Token(TType.STRING, t.value, t.target); } if (t.type != TType.WHITESPACE) { tempLeft.add(t); } } // Look through and concatenate all tokens before the label, if such exists. boolean hasLabel = false; for (int i = 0; i < tempLeft.size(); i++) { if (tempLeft.get(i).type == TType.LABEL) { hasLabel = true; break; } } if (hasLabel) { StringBuilder b = new StringBuilder(); int count = 0; while (tempLeft.get(count).type != TType.LABEL) { b.append(tempLeft.get(count).val()); count++; } tempLeft.set(0, new Token(TType.STRING, b.toString(), Target.UNKNOWN)); for (int i = 0; i < count - 1; i++) { tempLeft.remove(1); } } left = tempLeft; for (int j = 0; j < left.size(); j++) { Token t = left.get(j); // Token prev_token = j - 2 >= 0?c.tokens.get(j - 2):new Token(TType.UNKNOWN, "", t.line_num); Token last_token = j - 1 >= 0 ? left.get(j - 1) : new Token(TType.UNKNOWN, "", t.getTarget()); Token next_token = j + 1 < left.size() ? left.get(j + 1) : new Token(TType.UNKNOWN, "", t.getTarget()); Token after_token = j + 2 < left.size() ? left.get(j + 2) : new Token(TType.UNKNOWN, "", t.getTarget()); if (j == 0) { if (next_token.type == TType.LABEL) { this.label = t.val(); j--; left.remove(0); left.remove(0); continue; } } if (t.type == TType.LABEL) { continue; } if (t.type.equals(TType.FINAL_VAR) && left.size() - j >= 5) { throw new ConfigCompileException( "FINAL_VAR must be the last argument in the alias", t.target); } if (t.type.equals(TType.VARIABLE) || t.type.equals(TType.FINAL_VAR)) { Variable v = new Variable(t.val(), null, t.target); lastVar = t.val(); v.setOptional(last_token.type.equals(TType.LSQUARE_BRACKET)); left_vars.put(t.val(), v); if (v.isOptional()) { after_no_def_opt_var = true; } else { v.setDefault(""); } } // We're looking for a command up front if (j == 0 && !t.value.startsWith("/")) { if (!(next_token.type == TType.LABEL && after_token.type == TType.COMMAND)) { throw new ConfigCompileException( "Expected command (/command) at start of alias." + " Instead, found " + t.type + " (" + t.val() + ")", t.target); } } if (last_token.type.equals(TType.LSQUARE_BRACKET)) { inside_opt_var = true; if (!(t.type.equals(TType.FINAL_VAR) || t.type.equals(TType.VARIABLE))) { throw new ConfigCompileException( "Unexpected " + t.type.toString() + " (" + t.val() + "), was expecting" + " a $variable", t.target); } } if (after_no_def_opt_var && !inside_opt_var) { if (t.type.equals(TType.VARIABLE) || t.type.equals(TType.FINAL_VAR)) { throw new ConfigCompileException( "You cannot have anything other than optional arguments after your" + " first optional argument.", t.target); } } if (!t.type.equals(TType.LSQUARE_BRACKET) && !t.type.equals(TType.OPT_VAR_ASSIGN) && !t.type.equals(TType.RSQUARE_BRACKET) && !t.type.equals(TType.VARIABLE) && !t.type.equals(TType.LIT) && !t.type.equals(TType.COMMAND) && !t.type.equals(TType.FINAL_VAR)) { if (j - 1 > 0 && !( /*t.type.equals(TType.STRING) &&*/ left.get(j - 1).type.equals(TType.OPT_VAR_ASSIGN))) { throw new ConfigCompileException("Unexpected " + t.type + " (" + t.val() + ")", t.target); } } if (last_token.type.equals(TType.COMMAND)) { if (!(t.type.equals(TType.VARIABLE) || t.type.equals(TType.LSQUARE_BRACKET) || t.type.equals(TType.FINAL_VAR) || t.type.equals(TType.LIT))) { throw new ConfigCompileException( "Unexpected " + t.type + " (" + t.val() + ") after command", t.target); } } if (inside_opt_var && t.type.equals(TType.OPT_VAR_ASSIGN)) { if (!((next_token.type.equals(TType.STRING) || next_token.type.equals(TType.LIT)) && after_token.type.equals(TType.RSQUARE_BRACKET) || (next_token.type.equals(TType.RSQUARE_BRACKET)))) { throw new ConfigCompileException("Unexpected token in optional variable", t.target); } else if (next_token.type.equals(TType.STRING) || next_token.type.equals(TType.LIT)) { left_vars.get(lastVar).setDefault(next_token.val()); } } if (t.type.equals(TType.RSQUARE_BRACKET)) { if (!inside_opt_var) { throw new ConfigCompileException("Unexpected " + t.type.toString(), t.target); } inside_opt_var = false; // if (last_token.type.equals(TType.VARIABLE) // || last_token.type.equals(TType.FINAL_VAR)) { // after_no_def_opt_var = true; // } } } return true; }
public boolean match(String command) { if (cleft == null) { // The compilation error happened during the signature declaration, so // we can't match it, nor can we even tell if it's what they intended for us to run. return false; } boolean case_sensitive = Prefs.CaseSensitive(); String[] cmds = command.split(" "); List<String> args = new ArrayList(Arrays.asList(cmds)); boolean isAMatch = true; StringBuilder lastVar = new StringBuilder(); int lastJ = 0; try { for (int j = 0; j < cleft.size(); j++) { if (!isAMatch) { break; } lastJ = j; Construct c = cleft.get(j); String arg = args.get(j); if (c.getCType() != ConstructType.VARIABLE) { if (case_sensitive && !c.val().equals(arg) || !case_sensitive && !c.val().equalsIgnoreCase(arg)) { isAMatch = false; continue; } } else { // It's a variable. If it's optional, the rest of them are optional too, so as long as the // size of // args isn't greater than the size of cleft, it's a match if (((Variable) c).isOptional()) { if (args.size() <= cleft.size()) { return true; } else { Construct fin = cleft.get(cleft.size() - 1); if (fin instanceof Variable) { if (((Variable) fin).isFinal()) { return true; } } return false; } } } if (j == cleft.size() - 1) { if (cleft.get(j).getCType() == ConstructType.VARIABLE) { Variable lv = (Variable) cleft.get(j); if (lv.isFinal()) { for (int a = j; a < args.size(); a++) { if (lastVar.length() == 0) { lastVar.append(args.get(a)); } else { lastVar.append(" ").append(args.get(a)); } } } } } } } catch (IndexOutOfBoundsException e) { if (cleft.get(lastJ).getCType() != ConstructType.VARIABLE || cleft.get(lastJ).getCType() == ConstructType.VARIABLE && !((Variable) cleft.get(lastJ)).isOptional()) { isAMatch = false; } } boolean lastIsFinal = false; if (cleft.get(cleft.size() - 1) instanceof Variable) { Variable v = (Variable) cleft.get(cleft.size() - 1); if (v.isFinal()) { lastIsFinal = true; } } if ((cleft.get(lastJ) instanceof Variable && ((Variable) cleft.get(lastJ)).isOptional())) { return true; } if (cleft.size() != cmds.length && !lastIsFinal) { isAMatch = false; } // ArrayList<Variable> vars = new ArrayList<Variable>(); // Variable v = null; // for (int j = 0; j < cleft.size(); j++) { // try { // if (cleft.get(j).getCType() == ConstructType.VARIABLE) { // if (((Variable) cleft.get(j)).getName().equals("$")) { // v = new Variable(((Variable) cleft.get(j)).getName(), // lastVar.toString(), Target.UNKNOWN); // } else { // v = new Variable(((Variable) cleft.get(j)).getName(), // args.get(j), Target.UNKNOWN); // } // } // } catch (IndexOutOfBoundsException e) { // v = new Variable(((Variable) cleft.get(j)).getName(), // ((Variable) cleft.get(j)).getDefault(), Target.UNKNOWN); // } // if (v != null) { // vars.add(v); // } // } return isAMatch; }