source: josm/trunk/src/org/openstreetmap/josm/actions/search/PushbackTokenizer.java@ 3385

Last change on this file since 3385 was 3385, checked in by jttt, 14 years ago

Fix warnings

  • Property svn:eol-style set to native
File size: 6.2 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.actions.search;
3
4import static org.openstreetmap.josm.tools.I18n.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.io.IOException;
8import java.io.Reader;
9import java.util.Arrays;
10import java.util.List;
11
12import org.openstreetmap.josm.actions.search.SearchCompiler.ParseError;
13
14public class PushbackTokenizer {
15
16 public static class Range {
17 private final long start;
18 private final long end;
19
20 public Range(long start, long end) {
21 this.start = start;
22 this.end = end;
23 }
24
25 public long getStart() {
26 return start;
27 }
28
29 public long getEnd() {
30 return end;
31 }
32 }
33
34 private final Reader search;
35
36 private Token currentToken;
37 private String currentText;
38 private Long currentNumber;
39 private Long currentRange;
40 private int c;
41
42 public PushbackTokenizer(Reader search) {
43 this.search = search;
44 getChar();
45 }
46
47 public enum Token {
48 NOT(marktr("<not>")), OR(marktr("<or>")), LEFT_PARENT(marktr("<left parent>")),
49 RIGHT_PARENT(marktr("<right parent>")), COLON(marktr("<colon>")), EQUALS(marktr("<equals>")),
50 KEY(marktr("<key>")), QUESTION_MARK(marktr("<question mark>")),
51 EOF(marktr("<end-of-file>"));
52
53 private Token(String name) {
54 this.name = name;
55 }
56
57 private final String name;
58
59 @Override
60 public String toString() {
61 return tr(name);
62 }
63 }
64
65
66 private void getChar() {
67 try {
68 c = search.read();
69 } catch (IOException e) {
70 throw new RuntimeException(e.getMessage(), e);
71 }
72 }
73
74 private long getNumber() {
75 long result = 0;
76 while (Character.isDigit(c)) {
77 result = result * 10 + (c - '0');
78 getChar();
79 }
80 return result;
81 }
82
83 private static final List<Character> specialChars = Arrays.asList(new Character[] {'"', ':', '(', ')', '|', '=', '?'});
84 private static final List<Character> specialCharsQuoted = Arrays.asList(new Character[] {'"'});
85
86 private String getString(boolean quoted) {
87 List<Character> sChars = quoted ? specialCharsQuoted : specialChars;
88 StringBuilder s = new StringBuilder();
89 boolean escape = false;
90 while (c != -1 && (escape || (!sChars.contains((char)c) && (quoted || !Character.isWhitespace(c))))) {
91 if (c == '\\' && !escape) {
92 escape = true;
93 } else {
94 s.append((char)c);
95 escape = false;
96 }
97 getChar();
98 }
99 return s.toString();
100 }
101
102 private String getString() {
103 return getString(false);
104 }
105
106 /**
107 * The token returned is <code>null</code> or starts with an identifier character:
108 * - for an '-'. This will be the only character
109 * : for an key. The value is the next token
110 * | for "OR"
111 * ' ' for anything else.
112 * @return The next token in the stream.
113 */
114 public Token nextToken() {
115 if (currentToken != null) {
116 Token result = currentToken;
117 currentToken = null;
118 return result;
119 }
120
121 while (Character.isWhitespace(c)) {
122 getChar();
123 }
124 switch (c) {
125 case -1:
126 getChar();
127 return Token.EOF;
128 case ':':
129 getChar();
130 return Token.COLON;
131 case '=':
132 getChar();
133 return Token.EQUALS;
134 case '(':
135 getChar();
136 return Token.LEFT_PARENT;
137 case ')':
138 getChar();
139 return Token.RIGHT_PARENT;
140 case '|':
141 getChar();
142 return Token.OR;
143 case '?':
144 getChar();
145 return Token.QUESTION_MARK;
146 case '"':
147 getChar();
148 currentText = getString(true);
149 getChar();
150 return Token.KEY;
151 default:
152 String prefix = "";
153 if (c == '-') {
154 getChar();
155 if (!Character.isDigit(c))
156 return Token.NOT;
157 prefix = "-";
158 }
159 currentText = prefix + getString();
160 if ("or".equals(currentText))
161 return Token.OR;
162 try {
163 currentNumber = Long.parseLong(currentText);
164 } catch (NumberFormatException e) {
165 currentNumber = null;
166 }
167 int pos = currentText.indexOf('-', 1);
168 if (pos > 0) {
169 try {
170 currentNumber = Long.parseLong(currentText.substring(0, pos));
171 currentRange = Long.parseLong(currentText.substring(pos + 1));
172 } catch (NumberFormatException e) {
173 currentNumber = null;
174 currentRange = null;
175 }
176 }
177 return Token.KEY;
178 }
179 }
180
181 public boolean readIfEqual(Token token) {
182 Token nextTok = nextToken();
183 if (nextTok == null ? token == null : nextTok == token)
184 return true;
185 currentToken = nextTok;
186 return false;
187 }
188
189 public String readTextOrNumber() {
190 Token nextTok = nextToken();
191 if (nextTok == Token.KEY)
192 return currentText;
193 currentToken = nextTok;
194 return null;
195 }
196
197 public long readNumber(String errorMessage) throws ParseError {
198 if ((nextToken() == Token.KEY) && (currentNumber != null))
199 return currentNumber;
200 else
201 throw new ParseError(errorMessage);
202 }
203
204 public long getReadNumber() {
205 return (currentNumber != null) ? currentNumber : 0;
206 }
207
208 public Range readRange(String errorMessage) throws ParseError {
209 if ((nextToken() == Token.KEY) && (currentNumber != null)) {
210 if (currentRange == null)
211 return new Range(currentNumber, currentNumber);
212 else
213 return new Range(currentNumber, currentRange);
214 } else
215 throw new ParseError(errorMessage);
216 }
217
218 public String getText() {
219 return currentText;
220 }
221}
Note: See TracBrowser for help on using the repository browser.