Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.expressionevaluator / org.gvsig.expressionevaluator.lib / org.gvsig.expressionevaluator.lib.impl / src / main / java / org / gvsig / expressionevaluator / impl / DefaultInterpreter.java @ 43521

History | View | Annotate | Download (4.92 KB)

1
package org.gvsig.expressionevaluator.impl;
2

    
3
import org.gvsig.expressionevaluator.SymbolTable;
4
import org.gvsig.expressionevaluator.Interpreter;
5
import org.gvsig.expressionevaluator.Code;
6
import org.gvsig.expressionevaluator.Code.Constant;
7
import org.gvsig.expressionevaluator.Code.Identifier;
8
import org.gvsig.expressionevaluator.Code.Caller;
9
import org.gvsig.expressionevaluator.Code.Caller.Arguments;
10
import org.gvsig.expressionevaluator.Function;
11
import org.gvsig.expressionevaluator.impl.function.operator.BinaryOperator;
12
import org.gvsig.expressionevaluator.impl.function.operator.UnaryOperator;
13

    
14
public class DefaultInterpreter implements Interpreter {
15

    
16
    private SymbolTable symbolTable = null;
17
    private Double accuracy;
18
    private Code currentCode;
19

    
20
    public DefaultInterpreter() {
21
        this.symbolTable = SQLSymbolTable.getInstance();
22
    }
23

    
24
    @Override
25
    public void setSymbolTable(SymbolTable symbolTable) {
26
        this.symbolTable = symbolTable;
27
    }
28

    
29
    @Override
30
    public SymbolTable getSymbolTable() {
31
        return this.symbolTable;
32
    }
33
    @Override
34
    public Double getAccuracy() {
35
        return this.accuracy;
36
    }
37
    
38
    @Override
39
    public void setAccuracy(Double accuracy) {
40
        this.accuracy = accuracy;
41
    }
42
    
43
    @Override
44
    public Object run(Code code) {
45
        try {
46
            return this.runCode(code);
47
        } catch (Exception ex) {
48
            throw new RuntimeException(ex);
49
        }
50
    }
51

    
52
    @Override
53
    public void link(Code code) {
54
        linkCode(code);
55
    }
56

    
57
    private void linkCode(Code code) {
58
        if( code instanceof Caller ) {
59
            Caller caller = (Caller) code;
60
            if( caller.function() == null ) {
61
                caller.function(this.symbolTable.function(caller.name()));
62
            }
63
            if( caller.args() != null ) {
64
                for( Code arg : caller.args() ) {
65
                    linkCode(arg);
66
                }
67
            }
68
        }
69
    }
70

    
71
    private Object runCode(Code code) throws Exception {
72
        this.currentCode = code;
73
        Object value = null;
74
        switch( code.code() ) {
75
        case Code.CONSTANT:
76
            value = ((Constant) code).value();
77
            break;
78

    
79
        case Code.IDENTIFIER:
80
            String name = ((Identifier) code).name();
81
            if( !symbolTable.exists(name) ) {
82
                throw new RuntimeException("Variable '" + name + "' not found.");
83
            }
84
            value = symbolTable.value(name);
85
            break;
86

    
87
        case Code.CALLER:
88
            Caller caller = (Caller) code;
89
            Function function = caller.function();
90
            if( function == null ) {
91
                function = this.symbolTable.function(caller.name());
92
                if( function == null ) {
93
                    throw new RuntimeException("Function '" + caller.name() + "' not found.");
94
                }
95
                caller.function(function);
96
            }
97
            Arguments args = caller.args();
98
            try {
99
                switch( caller.type() ) {
100
                case Caller.UNARY_OPERATOR:
101
                    if( args == null || args.count() != 1 ) {
102
                        throw new RuntimeException("Number of argument mistmatch, expected 1 got " + args.count() + ".");
103
                    }
104
                    value = ((UnaryOperator) function).call(this, runCode(args.get(0)));
105
                    break;
106

    
107
                case Caller.BINARY_OPERATOR:
108
                    if( args == null || args.count() != 2 ) {
109
                        throw new RuntimeException("Number of argument mistmatch, expected 2 got " + args.count() + ".");
110
                    }
111
                    value = ((BinaryOperator) function).call(this, runCode(args.get(0)), runCode(args.get(1)));
112
                    break;
113

    
114
                case Caller.FUNCTION:
115
                    int argc = (args == null) ? 0 : args.count();
116
                    if( !function.argc().contains(argc) ) {
117
                        throw new RuntimeException("Number of argument mistmatch, expected " + function.argc() + " got " + argc + ".");
118
                    }
119
                    Object[] argvalues = new Object[argc];
120
                    if( args != null ) {
121
                        int i = 0;
122
                        for( Code arg : args ) {
123
                            argvalues[i++] = runCode(arg);
124
                        }
125
                    }
126
                    value = function.call(this, argvalues);
127
                }
128
            } catch (Exception ex) {
129
                String argsstr = "???";
130
                try {
131
                    argsstr = args.toString();
132
                } catch(Exception ex2) {
133
                    // Ignore.
134
                }
135
                throw new RuntimeException("Problems calling function '"+function.name()+"' with args ("+argsstr+").", ex);
136
            }
137
        }
138
        this.currentCode = null;
139
        return value;
140
    }
141

    
142
    @Override
143
    public Code getCurrentCode() {
144
        return this.currentCode;
145
    }
146
}