001package jmri.jmrit.logixng.util.parser;
002
003import jmri.JmriException;
004import jmri.jmrit.logixng.SymbolTable;
005import jmri.util.TypeConversionUtil;
006
007/**
008 * A parsed expression
009 */
010public class ExpressionNodeIncreaseDecreaseOperator implements ExpressionNode {
011
012    private final ExpressionNode _exprNode;
013    private final Operator _operator;
014    
015    
016    public ExpressionNodeIncreaseDecreaseOperator(TokenType tokenType, ExpressionNode exprNode, boolean before) {
017        _exprNode = exprNode;
018        
019        if (_exprNode == null) {
020            throw new IllegalArgumentException("exprNode must not be null for operators ++ and --");
021        }
022        
023        if (! _exprNode.canBeAssigned()) {
024            throw new IllegalArgumentException("exprNode must assignable");
025        }
026        
027        // Verify that the token is of the correct type
028        switch (tokenType) {
029            case INCREMENT:
030                _operator = before ? Operator.PRE_INCREMENT : Operator.POST_INCREMENT;
031                break;
032            case DECREMENT:
033                _operator = before ? Operator.PRE_DECREMENT : Operator.POST_DECREMENT;
034                break;
035            default:
036                throw new IllegalArgumentException("Unknown arithmetic operator: "+tokenType.name());
037        }
038    }
039    
040    
041    @Override
042    public Object calculate(SymbolTable symbolTable) throws JmriException {
043        
044        Object value = _exprNode.calculate(symbolTable);
045        
046        if (TypeConversionUtil.isIntegerNumber(value)) {
047            long v = ((Number)value).longValue();
048            long result;
049            
050            switch (_operator) {
051                case PRE_INCREMENT:  result = ++v; break;
052                case PRE_DECREMENT:  result = --v; break;
053                case POST_INCREMENT: result = v++; break;
054                case POST_DECREMENT: result = v--; break;
055                default:
056                    throw new CalculateException("Unknown operator: "+_operator.name());
057            }
058            _exprNode.assignValue(symbolTable, v);
059            return result;
060        } else {
061            throw new CalculateException(Bundle.getMessage("ArithmeticNotIntegerNumberError", value));
062        }
063    }
064    
065    
066    /** {@inheritDoc} */
067    @Override
068    public String getDefinitionString() {
069        String leftOperStr = "";
070        String rightOperStr = "";
071        switch (_operator) {
072            case PRE_INCREMENT:
073                leftOperStr = "++";
074                break;
075                
076            case PRE_DECREMENT:
077                leftOperStr = "--";
078                break;
079                
080            case POST_INCREMENT:
081                rightOperStr = "++";
082                break;
083                
084            case POST_DECREMENT:
085                rightOperStr = "--";
086                break;
087                
088            default:
089                throw new UnsupportedOperationException("Unknown operator: "+_operator.name());
090        }
091        
092        String exprNodeString = _exprNode != null ? _exprNode.getDefinitionString() : "null";
093        return leftOperStr + "("+exprNodeString+")" + rightOperStr;
094    }
095    
096    
097    
098    private enum Operator {
099        PRE_INCREMENT,
100        PRE_DECREMENT,
101        POST_INCREMENT,
102        POST_DECREMENT,
103    }
104    
105}