From 9c971b50670ddb5e62b52a80b8473a68ffec0d9d Mon Sep 17 00:00:00 2001 From: PseudoKnight Date: Wed, 11 Dec 2024 00:24:04 -0800 Subject: [PATCH] Improve early detection of errant symbols Checks binary operators for unexpected adjacent symbols during auto concat rewrite. Does adjacent symbol token detection in aliases too. This was limited to when inPureMScript, skipping the right side of aliases. --- .../core/MethodScriptCompiler.java | 29 ++-- .../laytonsmith/core/functions/Compiler.java | 138 ++++++------------ 2 files changed, 58 insertions(+), 109 deletions(-) diff --git a/src/main/java/com/laytonsmith/core/MethodScriptCompiler.java b/src/main/java/com/laytonsmith/core/MethodScriptCompiler.java index 72df3e386..9f54b4391 100644 --- a/src/main/java/com/laytonsmith/core/MethodScriptCompiler.java +++ b/src/main/java/com/laytonsmith/core/MethodScriptCompiler.java @@ -946,25 +946,22 @@ public static TokenStream lex(String script, Environment env, File file, } } - // Skip this check if we're not in pure mscript. - if(inPureMScript) { - if(it.hasNext()) { - Token next = it.next(); // Select 'next' -->. - it.previous(); // Select 'next' <--. - it.previous(); // Select 't' <--. - if(t.type.isSymbol() && !t.type.isUnary() && !next.type.isUnary()) { - if(it.hasPrevious()) { - Token prev1 = it.previous(); // Select 'prev1' <--. - if(prev1.type.equals(TType.FUNC_START) || prev1.type.equals(TType.COMMA) - || next.type.equals(TType.FUNC_END) || next.type.equals(TType.COMMA) - || prev1.type.isSymbol() || next.type.isSymbol()) { - throw new ConfigCompileException("Unexpected symbol (" + t.val() + ")", t.getTarget()); - } - it.next(); // Select 'prev1' -->. + if(it.hasNext()) { + Token next = it.next(); // Select 'next' -->. + it.previous(); // Select 'next' <--. + it.previous(); // Select 't' <--. + if(t.type.isSymbol() && !t.type.isUnary() && !next.type.isUnary()) { + if(it.hasPrevious()) { + Token prev1 = it.previous(); // Select 'prev1' <--. + if(prev1.type.equals(TType.FUNC_START) || prev1.type.equals(TType.COMMA) + || next.type.equals(TType.FUNC_END) || next.type.equals(TType.COMMA) + || prev1.type.isSymbol() || next.type.isSymbol()) { + throw new ConfigCompileException("Unexpected symbol token (" + t.val() + ")", t.getTarget()); } + it.next(); // Select 'prev1' -->. } - it.next(); // Select 't' -->. } + it.next(); // Select 't' -->. } } diff --git a/src/main/java/com/laytonsmith/core/functions/Compiler.java b/src/main/java/com/laytonsmith/core/functions/Compiler.java index 4c837d05e..8e553e1f7 100644 --- a/src/main/java/com/laytonsmith/core/functions/Compiler.java +++ b/src/main/java/com/laytonsmith/core/functions/Compiler.java @@ -330,136 +330,69 @@ public static ParseTree rewrite(List list, boolean returnSConcat, //Exponential for(int i = 0; i < list.size() - 1; i++) { ParseTree next = list.get(i + 1); - if(next.getData() instanceof CSymbol) { - if(((CSymbol) next.getData()).isExponential()) { - ParseTree conversion = new ParseTree(new CFunction(((CSymbol) next.getData()).convert(), next.getTarget()), next.getFileOptions()); - conversion.addChild(list.get(i)); - conversion.addChild(list.get(i + 2)); - list.set(i, conversion); - list.remove(i + 1); - list.remove(i + 1); - i--; - } + if(next.getData() instanceof CSymbol sy && sy.isExponential()) { + rewriteBinaryOperator(list, sy, i--); } } - //Multiplicative for(int i = 0; i < list.size() - 1; i++) { ParseTree next = list.get(i + 1); - if(next.getData() instanceof CSymbol) { - CSymbol nextData = (CSymbol) next.getData(); - if(nextData.isMultaplicative() && !nextData.isAssignment()) { - ParseTree conversion = new ParseTree(new CFunction(((CSymbol) next.getData()).convert(), next.getTarget()), next.getFileOptions()); - conversion.addChild(list.get(i)); - conversion.addChild(list.get(i + 2)); - list.set(i, conversion); - list.remove(i + 1); - list.remove(i + 1); - i--; - } + if(next.getData() instanceof CSymbol sy && sy.isMultaplicative() && !sy.isAssignment()) { + rewriteBinaryOperator(list, sy, i--); } } //Additive for(int i = 0; i < list.size() - 1; i++) { ParseTree next = list.get(i + 1); - if(next.getData() instanceof CSymbol && ((CSymbol) next.getData()).isAdditive() && !((CSymbol) next.getData()).isAssignment()) { - ParseTree conversion = new ParseTree(new CFunction(((CSymbol) next.getData()).convert(), next.getTarget()), next.getFileOptions()); - conversion.addChild(list.get(i)); - conversion.addChild(list.get(i + 2)); - list.set(i, conversion); - list.remove(i + 1); - list.remove(i + 1); - i--; + if(next.getData() instanceof CSymbol sy && sy.isAdditive() && !sy.isAssignment()) { + rewriteBinaryOperator(list, sy, i--); } } //relational for(int i = 0; i < list.size() - 1; i++) { - ParseTree node = list.get(i + 1); - if(node.getData() instanceof CSymbol && ((CSymbol) node.getData()).isRelational()) { - CSymbol sy = (CSymbol) node.getData(); - ParseTree conversion = new ParseTree(new CFunction(sy.convert(), node.getTarget()), node.getFileOptions()); - conversion.addChild(list.get(i)); - conversion.addChild(list.get(i + 2)); - list.set(i, conversion); - list.remove(i + 1); - list.remove(i + 1); - i--; + ParseTree next = list.get(i + 1); + if(next.getData() instanceof CSymbol sy && sy.isRelational()) { + rewriteBinaryOperator(list, sy, i--); } } //equality for(int i = 0; i < list.size() - 1; i++) { - ParseTree node = list.get(i + 1); - if(node.getData() instanceof CSymbol && ((CSymbol) node.getData()).isEquality()) { - CSymbol sy = (CSymbol) node.getData(); - ParseTree conversion = new ParseTree(new CFunction(sy.convert(), node.getTarget()), node.getFileOptions()); - conversion.addChild(list.get(i)); - conversion.addChild(list.get(i + 2)); - list.set(i, conversion); - list.remove(i + 1); - list.remove(i + 1); - i--; + ParseTree next = list.get(i + 1); + if(next.getData() instanceof CSymbol sy && sy.isEquality()) { + rewriteBinaryOperator(list, sy, i--); } } // default and for(int i = 0; i < list.size() - 1; i++) { - ParseTree node = list.get(i + 1); - if(node.getData() instanceof CSymbol && ((CSymbol) node.getData()).isDefaultAnd()) { - CSymbol sy = (CSymbol) node.getData(); - ParseTree conversion = new ParseTree(new CFunction(sy.convert(), node.getTarget()), node.getFileOptions()); - conversion.addChild(list.get(i)); - conversion.addChild(list.get(i + 2)); - list.set(i, conversion); - list.remove(i + 1); - list.remove(i + 1); - i--; + ParseTree next = list.get(i + 1); + if(next.getData() instanceof CSymbol sy && sy.isDefaultAnd()) { + rewriteBinaryOperator(list, sy, i--); } } - // default or for(int i = 0; i < list.size() - 1; i++) { - ParseTree node = list.get(i + 1); - if(node.getData() instanceof CSymbol && ((CSymbol) node.getData()).isDefaultOr()) { - CSymbol sy = (CSymbol) node.getData(); - ParseTree conversion = new ParseTree(new CFunction(sy.convert(), node.getTarget()), node.getFileOptions()); - conversion.addChild(list.get(i)); - conversion.addChild(list.get(i + 2)); - list.set(i, conversion); - list.remove(i + 1); - list.remove(i + 1); - i--; + ParseTree next = list.get(i + 1); + if(next.getData() instanceof CSymbol sy && sy.isDefaultOr()) { + rewriteBinaryOperator(list, sy, i--); } } - //logical and for(int i = 0; i < list.size() - 1; i++) { - ParseTree node = list.get(i + 1); - if(node.getData() instanceof CSymbol && ((CSymbol) node.getData()).isLogicalAnd()) { - CSymbol sy = (CSymbol) node.getData(); - ParseTree conversion = new ParseTree(new CFunction(sy.convert(), node.getTarget()), node.getFileOptions()); - conversion.addChild(list.get(i)); - conversion.addChild(list.get(i + 2)); - list.set(i, conversion); - list.remove(i + 1); - list.remove(i + 1); - i--; + ParseTree next = list.get(i + 1); + if(next.getData() instanceof CSymbol sy && sy.isLogicalAnd()) { + rewriteBinaryOperator(list, sy, i--); } } //logical or for(int i = 0; i < list.size() - 1; i++) { - ParseTree node = list.get(i + 1); - if(node.getData() instanceof CSymbol && ((CSymbol) node.getData()).isLogicalOr()) { - CSymbol sy = (CSymbol) node.getData(); - ParseTree conversion = new ParseTree(new CFunction(sy.convert(), node.getTarget()), node.getFileOptions()); - conversion.addChild(list.get(i)); - conversion.addChild(list.get(i + 2)); - list.set(i, conversion); - list.remove(i + 1); - list.remove(i + 1); - i--; + ParseTree next = list.get(i + 1); + if(next.getData() instanceof CSymbol sy && sy.isLogicalOr()) { + rewriteBinaryOperator(list, sy, i--); } } } catch (IndexOutOfBoundsException e) { - throw new ConfigCompileException("Unexpected symbol (" + list.get(list.size() - 1).getData().val() + "). Did you forget to quote your symbols?", list.get(list.size() - 1).getTarget()); + throw new ConfigCompileException("Unexpected symbol (" + list.get(list.size() - 1).getData().val() + ")", + list.get(list.size() - 1).getTarget()); } } @@ -630,6 +563,25 @@ public static ParseTree rewrite(List list, boolean returnSConcat, } } + private static void rewriteBinaryOperator(List list, CSymbol symbol, int leftIndex) throws ConfigCompileException { + ParseTree left = list.get(leftIndex); + if(left.getData() instanceof CSymbol) { + throw new ConfigCompileException("Unexpected symbol (" + left.getData().val() + ") before binary operator (" + + list.get(leftIndex + 1).getData().val() + ")", left.getTarget()); + } + ParseTree right = list.get(leftIndex + 2); + if(right.getData() instanceof CSymbol) { + throw new ConfigCompileException("Unexpected symbol (" + right.getData().val() + ") after binary operator (" + + list.get(leftIndex + 1).getData().val() + ")", right.getTarget()); + } + ParseTree conversion = new ParseTree(new CFunction(symbol.convert(), symbol.getTarget()), left.getFileOptions()); + conversion.addChild(left); + conversion.addChild(right); + list.set(leftIndex, conversion); + list.remove(leftIndex + 1); + list.remove(leftIndex + 1); + } + private static void rewriteParenthesis(List list) throws ConfigCompileException { for(int listInd = list.size() - 1; listInd >= 1; listInd--) { Stack executes = new Stack<>();