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

History | View | Annotate | Download (6.5 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.Stack;
10
import org.gvsig.expressionevaluator.ExpressionRuntimeException;
11
import org.gvsig.expressionevaluator.ExpressionSyntaxException;
12
import org.gvsig.expressionevaluator.I18N;
13
import org.gvsig.tools.lang.Cloneable;
14

    
15
public abstract class AbstractLexicalAnalyzer implements LexicalAnalyzer {
16

    
17
    protected class DefaultToken implements Token {
18

    
19
        private int type;
20
        private String literal;
21
        private Object value;
22

    
23
        public DefaultToken() {
24
        }
25

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

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

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

    
46
        @Override
47
        public int getType() {
48
            return type;
49
        }
50

    
51
        @Override
52
        public Object getValue() {
53
            return value;
54
        }
55

    
56
        @Override
57
        public String getLiteral() {
58
            return literal;
59
        }
60

    
61
        public void setLiteral(String literal) {
62
            this.literal = literal;
63
        }
64

    
65
    }
66

    
67
    protected class Buffer implements Cloneable {
68

    
69
        StringBuilder builder;
70

    
71
        public Buffer() {
72
            this.builder = new StringBuilder();
73
        }
74

    
75
        @Override
76
        public Buffer clone() throws CloneNotSupportedException {
77
            Buffer other = (Buffer) super.clone();
78
            other.builder = new StringBuilder(builder);
79
            return other;
80
        }
81

    
82
        public void clear() {
83
            builder.delete(0, builder.length());
84
        }
85

    
86
        public void add(char ch) {
87
            builder.append(ch);
88
        }
89

    
90
        public int length() {
91
            return this.builder.length();
92
        }
93

    
94
        @Override
95
        public String toString() {
96
            return this.builder.toString();
97
        }
98
    }
99

    
100
    protected static final char EOF = 0;
101

    
102
    private NumberFormat nf;
103
    private ParsePosition nfPos;
104
    private Stack<Integer> states;
105
    private String source;
106
    private int position;
107

    
108
    protected Buffer buffer;
109
    protected Token token;
110
    protected Map<String, Integer> tokens;
111

    
112
    public AbstractLexicalAnalyzer(String source) {
113
        this.position = 0;
114
        this.source = source;
115
        this.states = new Stack<>();
116
        this.buffer = new Buffer();
117
        this.token = this.createToken();
118

    
119
        this.nf = NumberFormat.getInstance(Locale.UK);
120
        this.nfPos = new ParsePosition(0);
121

    
122
        this.tokens = new HashMap<>();
123
    }
124

    
125
    public AbstractLexicalAnalyzer() {
126
        this(null);
127
    }
128

    
129
    protected Token createToken() {
130
        return new DefaultToken();
131
    }
132
    
133
    @Override
134
    public LexicalAnalyzer clone() throws CloneNotSupportedException {
135
        AbstractLexicalAnalyzer other = (AbstractLexicalAnalyzer) super.clone();
136
        other.nf = NumberFormat.getInstance(Locale.UK);
137
        other.nfPos = new ParsePosition(0);
138
        other.buffer = buffer.clone();
139
        other.token = token.clone();
140
        other.states = new Stack<>();
141
        other.states.addAll(states);
142
        other.tokens = new HashMap<>(tokens);
143
        return other;
144
    }
145

    
146
    @Override
147
    public void setSource(String source) {
148
        this.source = source;
149
        this.position = 0;
150
    }
151

    
152
    @Override
153
    public String getSource() {
154
        return this.source;
155
    }
156

    
157
    @Override
158
    public Token next() {
159
        return getToken();
160
    }
161

    
162
    @Override
163
    public Token look() {
164
        push_state();
165
        try {
166
            return getToken();
167
        } finally {
168
            pop_state();
169
        }
170
    }
171

    
172
    abstract protected Token getToken();
173

    
174
    protected void push_state() {
175
        this.states.push(position);
176
    }
177

    
178
    protected void pop_state() {
179
        position = this.states.pop();
180
    }
181

    
182
    @Override
183
    public int getPosition() {
184
        return position;
185
    }
186

    
187
    public boolean isEOF() {
188
        return this.position >= this.source.length();
189
    }
190

    
191
    protected void skipblanks() {
192
        if (isEOF()) {
193
            return;
194
        }
195
        char ch = getch();
196
        while (ch != EOF && Character.isSpaceChar(ch)) {
197
            ch = getch();
198
        }
199
        ungetch();
200
    }
201

    
202
    protected char lookch() {
203
        if (this.position >= this.source.length()) {
204
            return EOF;
205
        }
206
        return this.source.charAt(this.position);
207
    }
208

    
209
    protected char getch() {
210
        if (this.position >= this.source.length()) {
211
            return EOF;
212
        }
213
        return this.source.charAt(this.position++);
214
    }
215

    
216
    protected void ungetch() {
217
        this.position--;
218
        if (this.position < 0) {
219
            this.position = 0;
220
        }
221
    }
222

    
223
    protected void parseString() {
224
        buffer.clear();
225
        char ch = getch();
226
        while (true) {
227
            if (ch == EOF) {
228
                throw new ExpressionSyntaxException(I18N.End_of_string_was_expected_and_end_of_source_was_found(), this);
229
            }
230
            if (ch == '\'') {
231
                ch = getch();
232
                if (ch == EOF) {
233
                    break;
234
                }
235
                if (ch != '\'') {
236
                    ungetch();
237
                    break;
238
                }
239
            }
240
            buffer.add(ch);
241
            ch = getch();
242
        }
243
        token.set(Token.STRING_LITERAL, buffer.toString());
244
    }
245

    
246
    protected void parseNumber() {
247
        this.nfPos.setIndex(this.position);
248
        Number n = nf.parse(source, this.nfPos);
249
        if (this.nfPos.getIndex() == this.position) {
250
            throw new ExpressionRuntimeException(I18N.Expected_a_number_at_position_XpositionX(this.nfPos.getIndex()));
251
        }
252
        String literal = source.substring(this.position, this.nfPos.getIndex());
253
        this.position = this.nfPos.getIndex();
254
        if (n instanceof Long || n instanceof Integer) {
255
            token.set(Token.INTEGER_LITERAL, literal, n);
256
        } else {
257
            token.set(Token.FLOATING_POINT_LITERAL, literal, n);
258
        }
259
    }
260
}