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 @ 44145

History | View | Annotate | Download (7.99 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.nfPos = new ParsePosition(0);
149

    
150
        this.tokens = new HashMap<>();
151
    }
152

    
153
    public AbstractLexicalAnalyzer() {
154
        this(null);
155
    }
156

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

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

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

    
185
    @Override
186
    public Token next() {
187
        return getToken();
188
    }
189

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

    
200
    abstract protected Token getToken();
201

    
202
    protected void push_state() {
203
        this.states.push(position);
204
    }
205

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

    
210
    @Override
211
    public int getPosition() {
212
        return position;
213
    }
214

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

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

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

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

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

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

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