Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.expressionevaluator / org.gvsig.expressionevaluator.lib / org.gvsig.expressionevaluator.lib.api / src / main / java / org / gvsig / expressionevaluator / spi / AbstractLexicalAnalyzer.java @ 44210

History | View | Annotate | Download (8.04 KB)

1
package org.gvsig.expressionevaluator.spi;
2

    
3
import org.gvsig.expressionevaluator.LexicalAnalyzer;
4
import java.text.NumberFormat;
5
import java.text.ParsePosition;
6
import java.util.HashMap;
7
import java.util.Locale;
8
import java.util.Map;
9
import java.util.Objects;
10
import java.util.Stack;
11
import org.apache.commons.lang3.StringUtils;
12
import org.gvsig.expressionevaluator.ExpressionRuntimeException;
13
import org.gvsig.expressionevaluator.ExpressionSyntaxException;
14
import org.gvsig.expressionevaluator.I18N;
15
import org.gvsig.tools.lang.Cloneable;
16

    
17
public abstract class AbstractLexicalAnalyzer implements LexicalAnalyzer {
18

    
19
    protected class DefaultToken implements Token {
20

    
21
        private int type;
22
        private String literal;
23
        private Object value;
24

    
25
        public DefaultToken() {
26
        }
27

    
28
        @Override
29
        public Token clone() throws CloneNotSupportedException {
30
            // We will assume that the properties of the class are immutable, so 
31
            // it would suffice to call the super class.
32
            DefaultToken other = (DefaultToken) super.clone();
33
            return other;
34
        }
35

    
36
        @Override
37
        public void set(int type, String literal) {
38
            this.set(type, literal, literal);
39
        }
40

    
41
        @Override
42
        public void set(int type, String literal, Object value) {
43
            this.literal = literal;
44
            this.type = type;
45
            this.value = value;
46
        }
47

    
48
        @Override
49
        public int getType() {
50
            return type;
51
        }
52

    
53
        @Override
54
        public Object getValue() {
55
            return value;
56
        }
57

    
58
        @Override
59
        public String getLiteral() {
60
            return literal;
61
        }
62

    
63
        public void setLiteral(String literal) {
64
            this.literal = literal;
65
        }
66

    
67
        @Override
68
        public boolean is(String... values) {
69
            for (String theValue : values) {
70
                if( StringUtils.isBlank(literal) ) {
71
                    if( StringUtils.isBlank(theValue) ) {
72
                        return true;
73
                    }
74
                    continue;
75
                }
76
                if( StringUtils.isBlank(theValue) ) {
77
                    continue;
78
                }
79
                if( theValue.trim().equalsIgnoreCase(this.literal.trim()) ) {
80
                    return true;
81
                }
82
            }
83
            return false;
84
        }
85

    
86
        @Override
87
        public String toString() {
88
            return String.format("{%d,%s,%s}", this.type, Objects.toString(this.literal), Objects.toString(value));
89
        }
90
        
91
    }
92

    
93
    protected class Buffer implements Cloneable {
94

    
95
        StringBuilder builder;
96

    
97
        public Buffer() {
98
            this.builder = new StringBuilder();
99
        }
100

    
101
        @Override
102
        public Buffer clone() throws CloneNotSupportedException {
103
            Buffer other = (Buffer) super.clone();
104
            other.builder = new StringBuilder(builder);
105
            return other;
106
        }
107

    
108
        public void clear() {
109
            builder.delete(0, builder.length());
110
        }
111

    
112
        public void add(char ch) {
113
            builder.append(ch);
114
        }
115

    
116
        public int length() {
117
            return this.builder.length();
118
        }
119

    
120
        @Override
121
        public String toString() {
122
            return this.builder.toString();
123
        }
124
    }
125

    
126
    protected static final char EOF = 0;
127

    
128
    private NumberFormat nf;
129
    private ParsePosition nfPos;
130
    private Stack<Integer> states;
131
    private String source;
132
    private int position;
133

    
134
    protected Buffer buffer;
135
    protected Token token;
136
    protected Map<String, Integer> tokens;
137
    protected boolean useBracketsForIdentifiers;
138
            
139
    public AbstractLexicalAnalyzer(String source) {
140
        this.useBracketsForIdentifiers = false;
141
        this.position = 0;
142
        this.source = source;
143
        this.states = new Stack<>();
144
        this.buffer = new Buffer();
145
        this.token = this.createToken();
146

    
147
        this.nf = NumberFormat.getInstance(Locale.UK);
148
        this.nf.setGroupingUsed(false);
149
        
150
        this.nfPos = new ParsePosition(0);
151

    
152
        this.tokens = new HashMap<>();
153
    }
154

    
155
    public AbstractLexicalAnalyzer() {
156
        this(null);
157
    }
158

    
159
    protected Token createToken() {
160
        return new DefaultToken();
161
    }
162
    
163
    @Override
164
    public LexicalAnalyzer clone() throws CloneNotSupportedException {
165
        AbstractLexicalAnalyzer other = (AbstractLexicalAnalyzer) super.clone();
166
        other.nf = NumberFormat.getInstance(Locale.UK);
167
        other.nfPos = new ParsePosition(0);
168
        other.buffer = buffer.clone();
169
        other.token = token.clone();
170
        other.states = new Stack<>();
171
        other.states.addAll(states);
172
        other.tokens = new HashMap<>(tokens);
173
        return other;
174
    }
175

    
176
    @Override
177
    public void setSource(String source) {
178
        this.source = source;
179
        this.position = 0;
180
    }
181

    
182
    @Override
183
    public String getSource() {
184
        return this.source;
185
    }
186

    
187
    @Override
188
    public Token next() {
189
        return getToken();
190
    }
191

    
192
    @Override
193
    public Token look() {
194
        push_state();
195
        try {
196
            return getToken();
197
        } finally {
198
            pop_state();
199
        }
200
    }
201

    
202
    abstract protected Token getToken();
203

    
204
    protected void push_state() {
205
        this.states.push(position);
206
    }
207

    
208
    protected void pop_state() {
209
        position = this.states.pop();
210
    }
211

    
212
    @Override
213
    public int getPosition() {
214
        return position;
215
    }
216

    
217
    public boolean isEOF() {
218
        return this.position >= this.source.length();
219
    }
220

    
221
    protected void skipblanks() {
222
        if (isEOF()) {
223
            return;
224
        }
225
        char ch = getch();
226
        while (ch != EOF && Character.isWhitespace(ch)) {
227
            ch = getch();
228
        }
229
        ungetch();
230
    }
231

    
232
    protected char lookch() {
233
        if (this.position >= this.source.length()) {
234
            return EOF;
235
        }
236
        return this.source.charAt(this.position);
237
    }
238

    
239
    protected char getch() {
240
        if (this.position >= this.source.length()) {
241
            return EOF;
242
        }
243
        return this.source.charAt(this.position++);
244
    }
245

    
246
    protected void ungetch() {
247
        this.position--;
248
        if (this.position < 0) {
249
            this.position = 0;
250
        }
251
    }
252

    
253
    protected void parseString() {
254
        buffer.clear();
255
        char ch = getch();
256
        while (true) {
257
            if (ch == EOF) {
258
                throw new ExpressionSyntaxException(I18N.End_of_string_was_expected_and_end_of_source_was_found(), this);
259
            }
260
            if (ch == '\'') {
261
                ch = getch();
262
                if (ch == EOF) {
263
                    break;
264
                }
265
                if (ch != '\'') {
266
                    ungetch();
267
                    break;
268
                }
269
            }
270
            buffer.add(ch);
271
            ch = getch();
272
        }
273
        token.set(Token.STRING_LITERAL, buffer.toString());
274
    }
275

    
276
    protected void parseNumber() {
277
        this.nfPos.setIndex(this.position);
278
        Number n = nf.parse(source, this.nfPos);
279
        if (this.nfPos.getIndex() == this.position) {
280
            throw new ExpressionRuntimeException(I18N.Expected_a_number_at_position_XpositionX(this.nfPos.getIndex()));
281
        }
282
        String literal = source.substring(this.position, this.nfPos.getIndex());
283
        this.position = this.nfPos.getIndex();
284
        if( n instanceof Long ) {
285
            long l = ((Long)n);
286
            if( l>Integer.MIN_VALUE && l<Integer.MAX_VALUE ) {
287
                token.set(Token.INTEGER_LITERAL, literal, (int)l);
288
            } else {
289
                token.set(Token.INTEGER_LITERAL, literal, n);
290
            }
291
        } else if( n instanceof Integer) {
292
            token.set(Token.INTEGER_LITERAL, literal, n);
293
        } else {
294
            token.set(Token.FLOATING_POINT_LITERAL, literal, n);
295
        }
296
    }
297
    
298
    public void setUseBracketsForIdentifiers(boolean useBracketsForIdentifiers) {
299
        this.useBracketsForIdentifiers = useBracketsForIdentifiers;
300
    }
301
    
302
    public boolean getUseBracketsForIdentifiers() {
303
        return this.useBracketsForIdentifiers;
304
    }
305
}