From f28401aecc2ae517893db3933352633529269215 Mon Sep 17 00:00:00 2001 From: TomyLobo Date: Fri, 28 Oct 2011 20:34:48 +0200 Subject: [PATCH] Moved the sub-processors into a new class, ParserProcessors. --- .../worldedit/expression/parser/Parser.java | 288 +---------------- .../expression/parser/ParserProcessors.java | 295 ++++++++++++++++++ 2 files changed, 297 insertions(+), 286 deletions(-) create mode 100644 src/main/java/com/sk89q/worldedit/expression/parser/ParserProcessors.java diff --git a/src/main/java/com/sk89q/worldedit/expression/parser/Parser.java b/src/main/java/com/sk89q/worldedit/expression/parser/Parser.java index 95f96725f..80ba6871b 100644 --- a/src/main/java/com/sk89q/worldedit/expression/parser/Parser.java +++ b/src/main/java/com/sk89q/worldedit/expression/parser/Parser.java @@ -20,9 +20,6 @@ package com.sk89q.worldedit.expression.parser; import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -36,8 +33,6 @@ import com.sk89q.worldedit.expression.lexer.tokens.Token; import com.sk89q.worldedit.expression.runtime.Constant; import com.sk89q.worldedit.expression.runtime.Functions; import com.sk89q.worldedit.expression.runtime.Invokable; -import com.sk89q.worldedit.expression.runtime.Operators; -import com.sk89q.worldedit.expression.runtime.Sequence; public class Parser { private final class NullToken extends Token { @@ -145,292 +140,13 @@ public class Parser { } if (isStatement) { - return processStatement(halfProcessed); + return ParserProcessors.processStatement(halfProcessed); } else { - // process binary operators - return processExpression(halfProcessed); + return ParserProcessors.processExpression(halfProcessed); } } - private static Invokable processStatement(LinkedList input) throws ParserException { - LinkedList lhs = new LinkedList(); - LinkedList rhs = new LinkedList(); - boolean semicolonFound = false; - - for (Identifiable identifiable : input) { - if (semicolonFound) { - rhs.addLast(identifiable); - } - else { - if (identifiable.id() == ';') { - semicolonFound = true; - } - else { - lhs.addLast(identifiable); - } - } - } - - if (rhs.isEmpty()) { - if (lhs.isEmpty()) { - return new Sequence(semicolonFound ? input.get(0).getPosition() : -1); - } - - return processExpression(lhs); - } - else if (lhs.isEmpty()) { - return processStatement(rhs); - } - else { - assert(semicolonFound); - - Invokable lhsInvokable = processExpression(lhs); - Invokable rhsInvokable = processStatement(rhs); - - return new Sequence(lhsInvokable.getPosition(), lhsInvokable, rhsInvokable); - } - } - - private static Invokable processExpression(LinkedList input) throws ParserException { - return processBinaryOpsRA(input, binaryOpMapsRA.length - 1); - } - - private static final Map[] binaryOpMapsLA; - private static final Map[] binaryOpMapsRA; - - private static final Map unaryOpMap = new HashMap(); - static { - final Object[][][] binaryOpsLA = { - { - { "^", "pow" }, - { "**", "pow" }, - }, - { - { "*", "mul" }, - { "/", "div" }, - { "%", "mod" }, - }, - { - { "+", "add" }, - { "-", "sub" }, - }, - { - { "<<", "shl" }, - { ">>", "shr" }, - }, - { - { "<", "lth" }, - { ">", "gth" }, - { "<=", "leq" }, - { ">=", "geq" }, - }, - { - { "==", "equ" }, - { "!=", "neq" }, - { "~=", "near" }, - }, - { - { "&&", "and" }, - }, - { - { "||", "or" }, - }, - }; - final Object[][][] binaryOpsRA = { - { - { "=", "ass" }, - { "+=", "aadd" }, - { "-=", "asub" }, - { "*=", "amul" }, - { "/=", "adiv" }, - { "%=", "amod" }, - { "^=", "aexp" }, - }, - }; - - @SuppressWarnings("unchecked") - final Map[] lBinaryOpMapsLA = binaryOpMapsLA = new Map[binaryOpsLA.length]; - for (int i = 0; i < binaryOpsLA.length; ++i) { - final Object[][] a = binaryOpsLA[i]; - switch (a.length) { - case 0: - lBinaryOpMapsLA[i] = Collections.emptyMap(); - break; - - case 1: - final Object[] first = a[0]; - lBinaryOpMapsLA[i] = Collections.singletonMap((String) first[0], (String) first[1]); - break; - - default: - Map m = lBinaryOpMapsLA[i] = new HashMap(); - for (int j = 0; j < a.length; ++j) { - final Object[] element = a[j]; - m.put((String) element[0], (String) element[1]); - } - } - } - - @SuppressWarnings("unchecked") - final Map[] lBinaryOpMapsRA = binaryOpMapsRA = new Map[binaryOpsRA.length]; - for (int i = 0; i < binaryOpsRA.length; ++i) { - final Object[][] a = binaryOpsRA[i]; - switch (a.length) { - case 0: - lBinaryOpMapsRA[i] = Collections.emptyMap(); - break; - - case 1: - final Object[] first = a[0]; - lBinaryOpMapsRA[i] = Collections.singletonMap((String) first[0], (String) first[1]); - break; - - default: - Map m = lBinaryOpMapsRA[i] = new HashMap(); - for (int j = 0; j < a.length; ++j) { - final Object[] element = a[j]; - m.put((String) element[0], (String) element[1]); - } - } - } - - unaryOpMap.put("-", "neg"); - unaryOpMap.put("!", "not"); - unaryOpMap.put("~", "inv"); - unaryOpMap.put("++", "inc"); - unaryOpMap.put("--", "dec"); - } - - private static Invokable processBinaryOpsLA(LinkedList input, int level) throws ParserException { - if (level < 0) { - return processUnaryOps(input); - } - - LinkedList lhs = new LinkedList(); - LinkedList rhs = new LinkedList(); - String operator = null; - - for (Iterator it = input.descendingIterator(); it.hasNext();) { - Identifiable identifiable = it.next(); - if (operator == null) { - rhs.addFirst(identifiable); - - if (!(identifiable instanceof OperatorToken)) { - continue; - } - - operator = binaryOpMapsLA[level].get(((OperatorToken) identifiable).operator); - if (operator == null) { - continue; - } - - rhs.removeFirst(); - } - else { - lhs.addFirst(identifiable); - } - } - - Invokable rhsInvokable = processBinaryOpsLA(rhs, level - 1); - if (operator == null) return rhsInvokable; - - Invokable lhsInvokable = processBinaryOpsLA(lhs, level); - - try { - return Operators.getOperator(input.get(0).getPosition(), operator, lhsInvokable, rhsInvokable); - } - catch (NoSuchMethodException e) { - final Token operatorToken = (Token) input.get(lhs.size()); - throw new ParserException(operatorToken.getPosition(), "Couldn't find operator '" + operator + "'"); - } - } - - private static Invokable processBinaryOpsRA(LinkedList input, int level) throws ParserException { - if (level < 0) { - return processTernaryOps(input); - } - - LinkedList lhs = new LinkedList(); - LinkedList rhs = new LinkedList(); - String operator = null; - - for (Identifiable identifiable : input) { - if (operator == null) { - lhs.addLast(identifiable); - - if (!(identifiable instanceof OperatorToken)) { - continue; - } - - operator = binaryOpMapsRA[level].get(((OperatorToken) identifiable).operator); - if (operator == null) { - continue; - } - - lhs.removeLast(); - } - else { - rhs.addLast(identifiable); - } - } - - Invokable lhsInvokable = processBinaryOpsRA(lhs, level - 1); - if (operator == null) return lhsInvokable; - - Invokable rhsInvokable = processBinaryOpsRA(rhs, level); - - try { - return Operators.getOperator(input.get(0).getPosition(), operator, lhsInvokable, rhsInvokable); - } - catch (NoSuchMethodException e) { - final Token operatorToken = (Token) input.get(lhs.size()); - throw new ParserException(operatorToken.getPosition(), "Couldn't find operator '" + operator + "'"); - } - } - - private static Invokable processTernaryOps(LinkedList input) throws ParserException { - return processBinaryOpsLA(input, binaryOpMapsLA.length - 1); - } - - private static Invokable processUnaryOps(LinkedList input) throws ParserException { - if (input.isEmpty()) { - throw new ParserException(-1, "Expression missing."); - } - - Invokable ret = (Invokable) input.removeLast(); - while (!input.isEmpty()) { - final Identifiable last = input.removeLast(); - final int lastPosition = last.getPosition(); - if (last instanceof PrefixOperator) { - final String operator = ((PrefixOperator) last).operator; - if (operator.equals("+")) { - continue; - } - - String opName = unaryOpMap.get(operator); - if (opName != null) { - try { - ret = Operators.getOperator(lastPosition, opName, ret); - continue; - } - catch (NoSuchMethodException e) { - throw new ParserException(lastPosition, "No such prefix operator: " + operator); - } - } - } - if (last instanceof Token) { - throw new ParserException(lastPosition, "Extra token found in expression: " + last); - } - else if (last instanceof Invokable) { - throw new ParserException(lastPosition, "Extra expression found: " + last); - } - else { - throw new ParserException(lastPosition, "Extra element found: " + last); - } - } - return ret; - } private Token peek() { if (position >= tokens.size()) { diff --git a/src/main/java/com/sk89q/worldedit/expression/parser/ParserProcessors.java b/src/main/java/com/sk89q/worldedit/expression/parser/ParserProcessors.java new file mode 100644 index 000000000..1bd20228e --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/expression/parser/ParserProcessors.java @@ -0,0 +1,295 @@ +package com.sk89q.worldedit.expression.parser; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; + +import com.sk89q.worldedit.expression.Identifiable; +import com.sk89q.worldedit.expression.lexer.tokens.OperatorToken; +import com.sk89q.worldedit.expression.lexer.tokens.Token; +import com.sk89q.worldedit.expression.runtime.Invokable; +import com.sk89q.worldedit.expression.runtime.Operators; +import com.sk89q.worldedit.expression.runtime.Sequence; + +public final class ParserProcessors { + static Invokable processStatement(LinkedList input) throws ParserException { + LinkedList lhs = new LinkedList(); + LinkedList rhs = new LinkedList(); + boolean semicolonFound = false; + + for (Identifiable identifiable : input) { + if (semicolonFound) { + rhs.addLast(identifiable); + } + else { + if (identifiable.id() == ';') { + semicolonFound = true; + } + else { + lhs.addLast(identifiable); + } + } + } + + if (rhs.isEmpty()) { + if (lhs.isEmpty()) { + return new Sequence(semicolonFound ? input.get(0).getPosition() : -1); + } + + return processExpression(lhs); + } + else if (lhs.isEmpty()) { + return processStatement(rhs); + } + else { + assert(semicolonFound); + + Invokable lhsInvokable = processExpression(lhs); + Invokable rhsInvokable = processStatement(rhs); + + return new Sequence(lhsInvokable.getPosition(), lhsInvokable, rhsInvokable); + } + } + + static Invokable processExpression(LinkedList input) throws ParserException { + return processBinaryOpsRA(input, binaryOpMapsRA.length - 1); + } + + private static final Map[] binaryOpMapsLA; + private static final Map[] binaryOpMapsRA; + + private static final Map unaryOpMap = new HashMap(); + static { + final Object[][][] binaryOpsLA = { + { + { "^", "pow" }, + { "**", "pow" }, + }, + { + { "*", "mul" }, + { "/", "div" }, + { "%", "mod" }, + }, + { + { "+", "add" }, + { "-", "sub" }, + }, + { + { "<<", "shl" }, + { ">>", "shr" }, + }, + { + { "<", "lth" }, + { ">", "gth" }, + { "<=", "leq" }, + { ">=", "geq" }, + }, + { + { "==", "equ" }, + { "!=", "neq" }, + { "~=", "near" }, + }, + { + { "&&", "and" }, + }, + { + { "||", "or" }, + }, + }; + final Object[][][] binaryOpsRA = { + { + { "=", "ass" }, + { "+=", "aadd" }, + { "-=", "asub" }, + { "*=", "amul" }, + { "/=", "adiv" }, + { "%=", "amod" }, + { "^=", "aexp" }, + }, + }; + + @SuppressWarnings("unchecked") + final Map[] lBinaryOpMapsLA = binaryOpMapsLA = new Map[binaryOpsLA.length]; + for (int i = 0; i < binaryOpsLA.length; ++i) { + final Object[][] a = binaryOpsLA[i]; + switch (a.length) { + case 0: + lBinaryOpMapsLA[i] = Collections.emptyMap(); + break; + + case 1: + final Object[] first = a[0]; + lBinaryOpMapsLA[i] = Collections.singletonMap((String) first[0], (String) first[1]); + break; + + default: + Map m = lBinaryOpMapsLA[i] = new HashMap(); + for (int j = 0; j < a.length; ++j) { + final Object[] element = a[j]; + m.put((String) element[0], (String) element[1]); + } + } + } + + @SuppressWarnings("unchecked") + final Map[] lBinaryOpMapsRA = binaryOpMapsRA = new Map[binaryOpsRA.length]; + for (int i = 0; i < binaryOpsRA.length; ++i) { + final Object[][] a = binaryOpsRA[i]; + switch (a.length) { + case 0: + lBinaryOpMapsRA[i] = Collections.emptyMap(); + break; + + case 1: + final Object[] first = a[0]; + lBinaryOpMapsRA[i] = Collections.singletonMap((String) first[0], (String) first[1]); + break; + + default: + Map m = lBinaryOpMapsRA[i] = new HashMap(); + for (int j = 0; j < a.length; ++j) { + final Object[] element = a[j]; + m.put((String) element[0], (String) element[1]); + } + } + } + + unaryOpMap.put("-", "neg"); + unaryOpMap.put("!", "not"); + unaryOpMap.put("~", "inv"); + unaryOpMap.put("++", "inc"); + unaryOpMap.put("--", "dec"); + } + + private static Invokable processBinaryOpsLA(LinkedList input, int level) throws ParserException { + if (level < 0) { + return processUnaryOps(input); + } + + LinkedList lhs = new LinkedList(); + LinkedList rhs = new LinkedList(); + String operator = null; + + for (Iterator it = input.descendingIterator(); it.hasNext();) { + Identifiable identifiable = it.next(); + if (operator == null) { + rhs.addFirst(identifiable); + + if (!(identifiable instanceof OperatorToken)) { + continue; + } + + operator = binaryOpMapsLA[level].get(((OperatorToken) identifiable).operator); + if (operator == null) { + continue; + } + + rhs.removeFirst(); + } + else { + lhs.addFirst(identifiable); + } + } + + Invokable rhsInvokable = processBinaryOpsLA(rhs, level - 1); + if (operator == null) return rhsInvokable; + + Invokable lhsInvokable = processBinaryOpsLA(lhs, level); + + try { + return Operators.getOperator(input.get(0).getPosition(), operator, lhsInvokable, rhsInvokable); + } + catch (NoSuchMethodException e) { + final Token operatorToken = (Token) input.get(lhs.size()); + throw new ParserException(operatorToken.getPosition(), "Couldn't find operator '" + operator + "'"); + } + } + + private static Invokable processBinaryOpsRA(LinkedList input, int level) throws ParserException { + if (level < 0) { + return processTernaryOps(input); + } + + LinkedList lhs = new LinkedList(); + LinkedList rhs = new LinkedList(); + String operator = null; + + for (Identifiable identifiable : input) { + if (operator == null) { + lhs.addLast(identifiable); + + if (!(identifiable instanceof OperatorToken)) { + continue; + } + + operator = binaryOpMapsRA[level].get(((OperatorToken) identifiable).operator); + if (operator == null) { + continue; + } + + lhs.removeLast(); + } + else { + rhs.addLast(identifiable); + } + } + + Invokable lhsInvokable = processBinaryOpsRA(lhs, level - 1); + if (operator == null) return lhsInvokable; + + Invokable rhsInvokable = processBinaryOpsRA(rhs, level); + + try { + return Operators.getOperator(input.get(0).getPosition(), operator, lhsInvokable, rhsInvokable); + } + catch (NoSuchMethodException e) { + final Token operatorToken = (Token) input.get(lhs.size()); + throw new ParserException(operatorToken.getPosition(), "Couldn't find operator '" + operator + "'"); + } + } + + private static Invokable processTernaryOps(LinkedList input) throws ParserException { + return processBinaryOpsLA(input, binaryOpMapsLA.length - 1); + } + + private static Invokable processUnaryOps(LinkedList input) throws ParserException { + if (input.isEmpty()) { + throw new ParserException(-1, "Expression missing."); + } + + Invokable ret = (Invokable) input.removeLast(); + while (!input.isEmpty()) { + final Identifiable last = input.removeLast(); + final int lastPosition = last.getPosition(); + if (last instanceof PrefixOperator) { + final String operator = ((PrefixOperator) last).operator; + if (operator.equals("+")) { + continue; + } + + String opName = unaryOpMap.get(operator); + if (opName != null) { + try { + ret = Operators.getOperator(lastPosition, opName, ret); + continue; + } + catch (NoSuchMethodException e) { + throw new ParserException(lastPosition, "No such prefix operator: " + operator); + } + } + } + if (last instanceof Token) { + throw new ParserException(lastPosition, "Extra token found in expression: " + last); + } + else if (last instanceof Invokable) { + throw new ParserException(lastPosition, "Extra expression found: " + last); + } + else { + throw new ParserException(lastPosition, "Extra element found: " + last); + } + } + return ret; + } +}