private List shuntingYard()

in gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Expression.java [1080:1158]


    private List<Token> shuntingYard(String expression) {
        List<Token> outputQueue = new ArrayList<>();
        Stack<Token> stack = new Stack<>();

        Tokenizer tokenizer = new Tokenizer(expression);

        String previousToken = null;
        while (tokenizer.hasNext()) {
            String token = tokenizer.next();
            if (token.charAt(0) == '"') {
                StringBuilder sb = new StringBuilder();
                boolean escaped = false;
                for (int i = 1; i < token.length() - 1; i++) {
                    char ch = token.charAt(i);
                    if (escaped || ch != '\\') {
                        sb.append(ch);
                    } else {
                        escaped = true;
                    }
                }
                outputQueue.add(new Constant(sb.toString()));
            } else if (isNumber(token)) {
                outputQueue.add(new Constant(toBigDecimal(token)));
            } else if (constants.containsKey(token)) {
                outputQueue.add(new Constant(constants.get(token)));
            } else if (functions.containsKey(token.toUpperCase())) {
                stack.push(functions.get(token.toUpperCase()));
            } else if (Character.isLetter(token.charAt(0))) {
                outputQueue.add(new Variable(token));
            } else if (",".equals(token)) {
                while (!stack.isEmpty() && !(stack.peek() instanceof LeftParen)) {
                    outputQueue.add(stack.pop());
                }
                if (stack.isEmpty()) {
                    outputQueue.add(new Comma());
                }
            } else if (operators.containsKey(token)) {
                Operator o1 = operators.get(token);
                Token token2 = stack.isEmpty() ? null : stack.peek();
                while (token2 instanceof Operator
                        && ((o1.isLeftAssoc() && o1.getPrecedence() <= ((Operator) token2).getPrecedence())
                          || (o1.getPrecedence() < ((Operator) token2).getPrecedence()))) {
                    outputQueue.add(stack.pop());
                    token2 = stack.isEmpty() ? null : stack.peek();
                }
                stack.push(o1);
            } else if ("(".equals(token)) {
                if (previousToken != null) {
                    if (isNumber(previousToken)) {
                        throw new ExpressionException("Missing operator at character position " + tokenizer.getPos());
                    }
                }
                stack.push(new LeftParen());
            } else if (")".equals(token)) {
                while (!stack.isEmpty() && !(stack.peek() instanceof LeftParen)) {
                    outputQueue.add(stack.pop());
                }
                if (stack.isEmpty()) {
                    throw new RuntimeException("Mismatched parentheses");
                }
                stack.pop();
                if (!stack.isEmpty() && stack.peek() instanceof Function) {
                    outputQueue.add(stack.pop());
                }
            }
            previousToken = token;
        }
        while (!stack.isEmpty()) {
            Token element = stack.pop();
            if (element instanceof LeftParen) {
                throw new RuntimeException("Mismatched parentheses");
            }
            if (!(element instanceof Operator)) {
                throw new RuntimeException("Unknown operator or function: " + element);
            }
            outputQueue.add(element);
        }
        return outputQueue;
    }