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 | 43512 | jjdelcerro | 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 | 43521 | jjdelcerro | private SymbolTable symbolTable = null; |
17 | private Double accuracy; |
||
18 | private Code currentCode;
|
||
19 | 43512 | jjdelcerro | |
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 | 43521 | jjdelcerro | 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 | 43512 | jjdelcerro | 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 | 43521 | jjdelcerro | if( caller.args() != null ) { |
64 | 43519 | jjdelcerro | for( Code arg : caller.args() ) {
|
65 | linkCode(arg); |
||
66 | } |
||
67 | 43512 | jjdelcerro | } |
68 | } |
||
69 | } |
||
70 | |||
71 | private Object runCode(Code code) throws Exception { |
||
72 | 43521 | jjdelcerro | this.currentCode = code;
|
73 | 43512 | jjdelcerro | 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 | 43521 | jjdelcerro | 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 | 43512 | jjdelcerro | } |
128 | 43521 | jjdelcerro | } catch (Exception ex) { |
129 | String argsstr = "???"; |
||
130 | try {
|
||
131 | argsstr = args.toString(); |
||
132 | } catch(Exception ex2) { |
||
133 | // Ignore.
|
||
134 | 43512 | jjdelcerro | } |
135 | 43521 | jjdelcerro | throw new RuntimeException("Problems calling function '"+function.name()+"' with args ("+argsstr+").", ex); |
136 | 43512 | jjdelcerro | } |
137 | } |
||
138 | 43521 | jjdelcerro | this.currentCode = null; |
139 | 43512 | jjdelcerro | return value;
|
140 | } |
||
141 | 43521 | jjdelcerro | |
142 | @Override
|
||
143 | public Code getCurrentCode() {
|
||
144 | return this.currentCode; |
||
145 | } |
||
146 | 43512 | jjdelcerro | } |