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;
}