gt:                         StringBuilder stringBuilder = new StringBuilder();
context: /*
   * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  
  package com.sun.javafx.fxml.expression;
  
  import java.io.IOException;
  import java.io.PushbackReader;
  import java.io.Reader;
  import java.io.StringReader;
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Map;
  
  import com.sun.javafx.fxml.BeanAdapter;
  import static com.sun.javafx.fxml.expression.Operator.*;
  
  /**
   * Abstract base class for expressions. Also provides static methods for
   * creating arithmetic and logical expressions as well as accessing namespace
   * values by key path.
   */
  public abstract class Expression<T> {
      // Expression parser class
      private static class Parser {
          public static class Token {
              public Token(TokenType type, Object value) {
                  this.type = type;
                  this.value = value;
              }
  
              public final TokenType type;
              public final Object value;
  
              @Override
              public String toString() {
                  return value.toString();
              }
          }
  
          public enum TokenType {
              LITERAL,
              VARIABLE,
              FUNCTION,
              UNARY_OPERATOR,
              BINARY_OPERATOR,
              BEGIN_GROUP,
              END_GROUP
          }
  
          private int c = -1;
          private char[] pushbackBuffer = new char[PUSHBACK_BUFFER_SIZE];
  
          private static final int PUSHBACK_BUFFER_SIZE = 6;
  
          public Expression parse(Reader reader) throws IOException {
              LinkedList<Token> tokens = tokenize(new PushbackReader(reader, PUSHBACK_BUFFER_SIZE));
  
              LinkedList<Expression> stack = new LinkedList<Expression>();
  
              for (Token token : tokens) {
                  Expression<?> expression;
                  switch (token.type) {
                      case LITERAL: {
                          expression = new LiteralExpression(token.value);
                          break;
                      }
  
                      case VARIABLE: {
                          expression = new VariableExpression((KeyPath)token.value);
                          break;
                      }
  
                      case FUNCTION: {
                          // TODO Create a new FunctionExpression type; this
                          // class will have a property of type Method that
                          // refers to a method defined by the "scope context"
                          // (e.g. an FXML document controller), which must be
                          // set prior to evaluating the expression; it will
                          // also have a list of argument Expressions
                          expression = null;
                          break;
                      }
  
                      case UNARY_OPERATOR: {
                          Operator operator = (Operator)token.value;
                          Expression operand = stack.pop();
  
                          switch(operator) {
                              case NEGATE:
                                  expression = negate(operand);
                                  break;
                              case NOT:
                                  expression = not(operand);
                                  break;
                              default:
                                  throw new UnsupportedOperationException();
  
                          }
  
                          break;
                      }
  
                      case BINARY_OPERATOR: {
                          Operator operator = (Operator)token.value;
                          Expression right = stack.pop();
                          Expression left = stack.pop();
  
                          switch(operator) {
                              case ADD:
                                  expression = add(left, right);
                                  break;
                              case SUBTRACT:
                                  expression = subtract(left, right);
                                  break;
                              case MULTIPLY:
                                  expression = multiply(left, right);
                                  break;
                              case DIVIDE:
                                  expression = divide(left, right);
                                  break;
                              case MODULO:
                                  expression = modulo(left, right);
                                  break;
                              case GREATER_THAN:
                                  expression = greaterThan(left, right);
                                  break;
                              case GREATER_THAN_OR_EQUAL_TO:
                                  expression = greaterThanOrEqualTo(left, right);
                                  break;
                              case LESS_THAN:
                                  expression = lessThan(left, right);
                                  break;
                              case LESS_THAN_OR_EQUAL_TO:
                                  expression = lessThanOrEqualTo(left, right);
                                  break;
                              case EQUAL_TO:
                                  expression = equalTo(left, right);
                                  break;
                              case NOT_EQUAL_TO:
                                  expression = notEqualTo(left, right);
                                  break;
                              case AND:
                                  expression = and(left, right);
                                  break;
                              case OR:
                                  expression = or(left, right);
                                  break;
                              default:
                                  throw new UnsupportedOperationException();
                          }
  
                          break;
                      }
  
                      default: {
                          throw new UnsupportedOperationException();
                      }
                  }
  
                  stack.push(expression);
              }
  
              if (stack.size() != 1) {
                  throw new IllegalArgumentException("Invalid expression.");
              }
  
              return stack.peek();
          }
  
          private LinkedList<Token> tokenize(PushbackReader reader) throws IOException {
              // Read the string into a postfix list of tokens
              LinkedList<Token> tokens = new LinkedList<Token>();
              LinkedList<Token> stack = new LinkedList<Token>();
  
              c = reader.read();
              boolean unary = true;
  
              while (c != -1) {
                  // Skip whitespace
                  while (c != -1 && Character.isWhitespace(c)) {
                      c = reader.read();
                  }
  
                  if (c != -1) {
                      Token token;
  
                      if (c == 'n') {
                          if (readKeyword(reader, NULL_KEYWORD)) {
                              token = new Token(TokenType.LITERAL, null);
                          } else {
                              token = new Token(TokenType.VARIABLE, KeyPath.parse(reader));
                              c = reader.read();
                          }
                      } else if (c == '"' || c == '\'') {
  