public String toString(Token t) {
   if (t.getKind().hasPayload()) {
     return t.stringValue();
   } else {
     return t.kind.toString().toLowerCase();
   }
 }
 /**
  * Eat an identifier, possibly qualified (meaning that it is dotted). TODO AndyC Could create
  * complete identifiers (a.b.c) here rather than a sequence of them? (a, b, c)
  */
 private SpelNodeImpl eatPossiblyQualifiedId() {
   LinkedList<SpelNodeImpl> qualifiedIdPieces = new LinkedList<SpelNodeImpl>();
   Token node = peekToken();
   while (isValidQualifiedId(node)) {
     nextToken();
     if (node.kind != TokenKind.DOT) {
       qualifiedIdPieces.add(new Identifier(node.stringValue(), toPos(node)));
     }
     node = peekToken();
   }
   if (qualifiedIdPieces.isEmpty()) {
     if (node == null) {
       raiseInternalException(expressionString.length(), SpelMessage.OOD);
     }
     raiseInternalException(
         node.startpos,
         SpelMessage.NOT_EXPECTED_TOKEN,
         "qualified ID",
         node.getKind().toString().toLowerCase());
   }
   int pos =
       toPos(
           qualifiedIdPieces.getFirst().getStartPosition(),
           qualifiedIdPieces.getLast().getEndPosition());
   return new QualifiedIdentifier(
       pos, qualifiedIdPieces.toArray(new SpelNodeImpl[qualifiedIdPieces.size()]));
 }
 private Token eatToken(TokenKind expectedKind) {
   Token t = nextToken();
   if (t == null) {
     raiseInternalException(expressionString.length(), SpelMessage.OOD);
   }
   if (t.kind != expectedKind) {
     raiseInternalException(
         t.startpos,
         SpelMessage.NOT_EXPECTED_TOKEN,
         expectedKind.toString().toLowerCase(),
         t.getKind().toString().toLowerCase());
   }
   return t;
 }
 // powerExpr  : unaryExpression (POWER^ unaryExpression)? (INC || DEC) ;
 private SpelNodeImpl eatPowerIncDecExpression() {
   SpelNodeImpl expr = eatUnaryExpression();
   if (peekToken(TokenKind.POWER)) {
     Token t = nextToken(); // consume POWER
     SpelNodeImpl rhExpr = eatUnaryExpression();
     checkRightOperand(t, rhExpr);
     return new OperatorPower(toPos(t), expr, rhExpr);
   } else if (expr != null && peekToken(TokenKind.INC, TokenKind.DEC)) {
     Token t = nextToken(); // consume INC/DEC
     if (t.getKind() == TokenKind.INC) {
       return new OpInc(toPos(t), true, expr);
     } else {
       return new OpDec(toPos(t), true, expr);
     }
   }
   return expr;
 }
 // unaryExpression: (PLUS^ | MINUS^ | BANG^ | INC^ | DEC^) unaryExpression | primaryExpression ;
 private SpelNodeImpl eatUnaryExpression() {
   if (peekToken(TokenKind.PLUS, TokenKind.MINUS, TokenKind.NOT)) {
     Token t = nextToken();
     SpelNodeImpl expr = eatUnaryExpression();
     if (t.kind == TokenKind.NOT) {
       return new OperatorNot(toPos(t), expr);
     } else if (t.kind == TokenKind.PLUS) {
       return new OpPlus(toPos(t), expr);
     } else {
       Assert.isTrue(t.kind == TokenKind.MINUS);
       return new OpMinus(toPos(t), expr);
     }
   } else if (peekToken(TokenKind.INC, TokenKind.DEC)) {
     Token t = nextToken();
     SpelNodeImpl expr = eatUnaryExpression();
     if (t.getKind() == TokenKind.INC) {
       return new OpInc(toPos(t), false, expr);
     } else {
       return new OpDec(toPos(t), false, expr);
     }
   } else {
     return eatPrimaryExpression();
   }
 }