Search in sources :

Example 36 with ConfigCompileException

use of com.laytonsmith.core.exceptions.ConfigCompileException in project CommandHelper by EngineHub.

the class Script method checkAmbiguous.

public void checkAmbiguous(List<Script> scripts) throws ConfigCompileException {
    List<Construct> thisCommand = this.cleft;
    for (Script script : scripts) {
        List<Construct> thatCommand = script.cleft;
        if (thatCommand == null) {
            // It hasn't been compiled yet.
            return;
        }
        if (this.cleft == script.cleft) {
            // Of course this command is going to match its own signature.
            continue;
        }
        matchScope: {
            for (int k = 0; k < thisCommand.size(); k++) {
                Construct c1 = thisCommand.get(k);
                if (k < thatCommand.size()) {
                    Construct c2 = thatCommand.get(k);
                    // the same argument position.
                    if (c1.getCType() == c2.getCType() && (c1.getCType() == ConstructType.STRING || c1.getCType() == ConstructType.COMMAND)) {
                        if (c1.nval() != c2.nval() && (c1.nval() == null || !c1.nval().equals(c2.nval()))) {
                            break matchScope;
                        }
                    }
                } else {
                    // after the last Construct in thatCommand.
                    if (!(c1 instanceof Variable) || (c1 instanceof Variable && !((Variable) c1).isOptional())) {
                        break matchScope;
                    } else {
                        // There is no need to loop over later Constructs, the commands are ambigous.
                        break;
                    }
                }
            }
            if (thatCommand.size() > thisCommand.size()) {
                // thisCommand is shorter than thatCommand.
                // Commands are not ambigous if thatCommand contains a non-variable or a non-optional variable
                // after the last Construct in thisCommand.
                Construct c2 = thatCommand.get(thisCommand.size());
                if (!(c2 instanceof Variable) || (c2 instanceof Variable && !((Variable) c2).isOptional())) {
                    break matchScope;
                }
            }
            // The signature of thisCommand and thatCommand are ambigous. Throw a compile exception.
            String commandThis = "";
            for (Construct c : thisCommand) {
                commandThis += c.val() + " ";
            }
            String commandThat = "";
            for (Construct c : thatCommand) {
                commandThat += c.val() + " ";
            }
            script.compilerError = true;
            this.compilerError = true;
            throw new ConfigCompileException("The command " + commandThis.trim() + " is ambiguous because it " + "matches the signature of " + commandThat.trim() + " defined at " + thatCommand.get(0).getTarget(), thisCommand.get(0).getTarget());
        }
    }
}
Also used : IVariable(com.laytonsmith.core.constructs.IVariable) Variable(com.laytonsmith.core.constructs.Variable) Construct(com.laytonsmith.core.constructs.Construct) CString(com.laytonsmith.core.constructs.CString) ConfigCompileException(com.laytonsmith.core.exceptions.ConfigCompileException) ProfilePoint(com.laytonsmith.core.profiler.ProfilePoint)

Example 37 with ConfigCompileException

use of com.laytonsmith.core.exceptions.ConfigCompileException in project CommandHelper by EngineHub.

the class Script method verifyLeft.

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<>();
    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 (Token aTempLeft : tempLeft) {
        if (aTempLeft.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) || t.type.equals(TType.STRING))) {
                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.isAtomicLit() && 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.isAtomicLit()) {
                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;
        }
    }
    return true;
}
Also used : IVariable(com.laytonsmith.core.constructs.IVariable) Variable(com.laytonsmith.core.constructs.Variable) ArrayList(java.util.ArrayList) Token(com.laytonsmith.core.constructs.Token) CString(com.laytonsmith.core.constructs.CString) ConfigCompileException(com.laytonsmith.core.exceptions.ConfigCompileException) ProfilePoint(com.laytonsmith.core.profiler.ProfilePoint)

Aggregations

ConfigCompileException (com.laytonsmith.core.exceptions.ConfigCompileException)37 ParseTree (com.laytonsmith.core.ParseTree)16 CFunction (com.laytonsmith.core.constructs.CFunction)14 ArrayList (java.util.ArrayList)13 ConfigCompileGroupException (com.laytonsmith.core.exceptions.ConfigCompileGroupException)12 CString (com.laytonsmith.core.constructs.CString)11 Construct (com.laytonsmith.core.constructs.Construct)8 Token (com.laytonsmith.core.constructs.Token)8 IVariable (com.laytonsmith.core.constructs.IVariable)7 Target (com.laytonsmith.core.constructs.Target)6 GlobalEnv (com.laytonsmith.core.environments.GlobalEnv)6 Function (com.laytonsmith.core.functions.Function)6 Variable (com.laytonsmith.core.constructs.Variable)5 CommandHelperEnvironment (com.laytonsmith.core.environments.CommandHelperEnvironment)5 Environment (com.laytonsmith.core.environments.Environment)5 ConfigRuntimeException (com.laytonsmith.core.exceptions.ConfigRuntimeException)5 FunctionBase (com.laytonsmith.core.functions.FunctionBase)5 File (java.io.File)5 List (java.util.List)5 FunctionList (com.laytonsmith.core.functions.FunctionList)4