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 / AbstractLexicalAnalyzer.java @ 43809

History | View | Annotate | Download (4.83 KB)

1
package org.gvsig.expressionevaluator.impl;
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.tools.lang.Cloneable;
11

    
12
public abstract class AbstractLexicalAnalyzer implements LexicalAnalyzer {
13

    
14
    protected class Buffer implements Cloneable {
15

    
16
        StringBuilder builder;
17

    
18
        public Buffer() {
19
            this.builder = new StringBuilder();
20
        }
21

    
22
        @Override
23
        public Buffer clone() throws CloneNotSupportedException {
24
            Buffer other = (Buffer) super.clone(); 
25
            other.builder = new StringBuilder(builder);
26
            return other;
27
        }
28

    
29
        public void clear() {
30
            builder.delete(0, builder.length());
31
        }
32

    
33
        public void add(char ch) {
34
            builder.append(ch);
35
        }
36

    
37
        public int length() {
38
            return this.builder.length();
39
        }
40

    
41
        @Override
42
        public String toString() {
43
            return this.builder.toString();
44
        }
45
    }
46

    
47
    protected static final char EOF = 0;
48
    
49
    private NumberFormat nf;
50
    private ParsePosition nfPos;
51
    private Stack<Integer> states;
52
    private String source;
53
    private int position;
54

    
55
    protected Buffer buffer;
56
    protected DefaultToken token;
57
    protected Map<String, Integer> tokens;
58

    
59
    public AbstractLexicalAnalyzer(String source) {
60
        this.position = 0;
61
        this.source = source;
62
        this.states = new Stack<>();
63
        this.buffer = new Buffer();
64
        this.token = new DefaultToken();
65

    
66
        this.nf = NumberFormat.getInstance(Locale.UK);
67
        this.nfPos = new ParsePosition(0);
68

    
69
        this.tokens = new HashMap<>();
70
    }
71

    
72
    public AbstractLexicalAnalyzer() {
73
        this(null);
74
    }
75

    
76
    @Override
77
    public LexicalAnalyzer clone() throws CloneNotSupportedException {
78
        AbstractLexicalAnalyzer other = (AbstractLexicalAnalyzer) super.clone();
79
        other.nf = NumberFormat.getInstance(Locale.UK);
80
        other.nfPos = new ParsePosition(0);
81
        other.buffer = buffer.clone();
82
        other.token = (DefaultToken) token.clone();
83
        other.states = new Stack<>();
84
        other.states.addAll(states);
85
        other.tokens = new HashMap<>(tokens);
86
        return other;
87
    }
88
    
89
    @Override
90
    public void setSource(String source) {
91
        this.source = source;
92
        this.position = 0;
93
    }
94
    
95
    @Override
96
    public Token next() {
97
        return getToken();
98
    }
99

    
100
    @Override
101
    public Token look() {
102
        push_state();
103
        try {
104
            return getToken();
105
        } finally {
106
            pop_state();
107
        }
108
    }
109

    
110
    abstract protected Token getToken();
111

    
112
    protected void push_state() {
113
        this.states.push(position);
114
    }
115

    
116
    protected void pop_state() {
117
        position = this.states.pop();
118
    }
119

    
120
    protected int getPosition() {
121
        return position;
122
    }
123

    
124
    protected boolean isEOF() {
125
        return this.position >= this.source.length();
126
    }
127
    
128
    protected void skipblanks() {
129
        if( isEOF() ) {
130
            return;
131
        }
132
        char ch = getch();
133
        while( ch != EOF && Character.isSpaceChar(ch) ) {
134
            ch = getch();
135
        }
136
        ungetch();
137
    }
138

    
139
    protected char getch() {
140
        if( this.position+1 > this.source.length() ) {
141
            return EOF;
142
        }
143
        return this.source.charAt(this.position++);
144
    }
145

    
146
    protected void ungetch() {
147
        this.position--;
148
        if( this.position < 0 ) {
149
            this.position = 0;
150
        }
151
    }
152

    
153
    protected void parseString() {
154
        buffer.clear();
155
        char ch = getch();
156
        while( true ) {
157
            if( ch == EOF ) {
158
                throw new RuntimeException("Found end of source and expected end of string");
159
            }
160
            if( ch == '\'' ) {
161
                ch = getch();
162
                if( ch==EOF ) {
163
                    break;
164
                }
165
                if( ch != '\'' ) {
166
                    ungetch();
167
                    break;
168
                }
169
            }
170
            buffer.add(ch);
171
            ch = getch();
172
        }
173
        token.set(Token.STRING_LITERAL, buffer.toString());
174
    }
175

    
176
    protected void parseNumber() {
177
        this.nfPos.setIndex(this.position);
178
        Number n = nf.parse(source, this.nfPos);
179
        if( this.nfPos.getIndex() == this.position ) {
180
            throw new RuntimeException("Expected a number at position " + this.nfPos.getIndex() + ".");
181
        }
182
        String literal = source.substring(this.position, this.nfPos.getIndex());
183
        this.position = this.nfPos.getIndex();
184
        if( n instanceof Long || n instanceof Integer ) {
185
            token.set(Token.INTEGER_LITERAL, literal, n);
186
        } else {
187
            token.set(Token.FLOATING_POINT_LITERAL, literal, n);
188
        }
189
    }
190
}