comparison src/main/gov/nasa/jpf/util/script/StringExpander.java @ 0:61d41facf527

initial v8 import (history reset)
author Peter Mehlitz <Peter.C.Mehlitz@nasa.gov>
date Fri, 23 Jan 2015 10:14:01 -0800
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:61d41facf527
1 /*
2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
4 * All rights reserved.
5 *
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0.
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 package gov.nasa.jpf.util.script;
19
20
21 import java.util.LinkedList;
22 import java.util.List;
23
24 /**
25 * utility class to expand regular expression like strings. We support
26 * alternatives "<..|..>" and character categories "[.. X-Z ..]". Alternatives
27 * can be nested, char categories can include '-' ranges
28 *
29 * e.g. "a<B|X[0-1]Y>z" => aBz, aX0Yz, aX1Yz
30 *
31 * <2do> this is awfully connected to ESParser - we should really make it more generic
32 * (this is the reason why it was moved from the general gov.nasa.jpf.util to
33 * this package)
34 */
35 public class StringExpander {
36
37 public static final char META_CHAR = '`'; // starts a symbol
38
39 public static final char ALT_START_CHAR = '<';
40 public static final char ALT_END_CHAR = '>';
41 public static final char ALT_CHAR = '|';
42
43 public static final char CAT_START_CHAR = '[';
44 public static final char CAT_END_CHAR = ']';
45 public static final char CAT_CHAR = '-';
46
47 static class Exception extends RuntimeException {
48 Exception(String details){
49 super(details);
50 }
51 }
52
53 static class Token {
54 String value;
55
56 Token (String value){
57 this.value = value;
58 }
59 int length() {
60 return value.length();
61 }
62 boolean isSymbol() {
63 return false;
64 }
65 @Override
66 public String toString(){
67 return value;
68 }
69
70 }
71 static class Symbol extends Token {
72 Symbol (String s){
73 super(s);
74 }
75 @Override
76 boolean isSymbol(){
77 return true;
78 }
79 }
80
81 // our symbol tokens
82 static final Symbol CAT_START = new Symbol("CAT_START");
83 static final Symbol CAT_END = new Symbol("CAT_END");
84
85 static final Symbol ALT_START = new Symbol("ALT_START");
86 static final Symbol ALT_END = new Symbol("ALT_END");
87 static final Symbol ALT = new Symbol("ALT");
88 static final Symbol EOS = new Symbol("END");
89
90 final String src;
91 final int len;
92
93 Token token;
94 int pos;
95
96 /**
97 // a quoted symbol char version - doesn't look nice, but is more general
98 void nextToken () {
99
100 int i = pos;
101 int len = this.len;
102
103 if (i>=len){
104 token = EOS;
105
106 } else {
107 if (src.charAt(i) == META_CHAR){ // symbol
108 char c = src.charAt(++i);
109 switch (c){
110 case CAT_START_CHAR: token = CAT_START; break;
111 case CAT_END_CHAR: token = CAT_END; break;
112
113 case ALT_START_CHAR: token = ALT_START; break;
114 case ALT_CHAR: token = ALT; break;
115 case ALT_END_CHAR: token = ALT_END; break;
116 default:
117 error("illegal symbol: " + c);
118 }
119 pos += 2;
120
121 } else { // string literal
122 int j = i + 1;
123 for (; j < len && src.charAt(j) != META_CHAR; j++);
124 pos = j;
125 token = new Token(src.substring(i, j));
126 }
127 }
128 }
129 **/
130
131 private boolean isMetaChar(char c){
132 return ((c == CAT_START_CHAR) || (c == CAT_END_CHAR) ||
133 (c == ALT_START_CHAR) || (c == ALT_END_CHAR) || (c == ALT_CHAR));
134
135 }
136
137 void nextToken() {
138 int i = pos;
139 int len = this.len;
140
141 if (i>=len){
142 token = EOS;
143
144 } else {
145 char c = src.charAt(i);
146 switch (c){
147 case CAT_START_CHAR: token = CAT_START; pos++; break;
148 case CAT_END_CHAR: token = CAT_END; pos++; break;
149
150 case ALT_START_CHAR: token = ALT_START; pos++; break;
151 case ALT_CHAR: token = ALT; pos++; break;
152 case ALT_END_CHAR: token = ALT_END; pos++; break;
153
154 default:
155 int j = i + 1;
156 for (; j < len && !isMetaChar(src.charAt(j)); j++);
157 pos = j;
158 token = new Token(src.substring(i, j));
159 }
160 }
161 }
162
163 boolean match (Symbol sym){
164 if (token == sym){
165 nextToken();
166 return true;
167 } else {
168 return false;
169 }
170 }
171
172 public StringExpander (String src){
173 this.src = src;
174 this.len = src.length();
175 this.pos = 0;
176 }
177
178 List<String> addSeq (List<String> list, List<String> seq){
179 List<String> result = new LinkedList<String>();
180
181 if (list != null && list.size() > 0){
182 result.addAll(list);
183 }
184 result.addAll(seq);
185
186 return result;
187 }
188
189 List<String> addLiteral (List<String> list, String s){
190 List<String> result = new LinkedList<String>();
191
192 if (list == null || list.size() == 0){
193 result.add(s);
194
195 } else {
196 for (String e : list) {
197 result.add(e + s);
198 }
199 }
200
201 return result;
202 }
203
204 List<String> addAlt (List<String> list, List<String>alt){
205 List<String> result = new LinkedList<String>();
206
207 if (list == null || list.size() == 0){
208 result.addAll(alt);
209
210 } else {
211 for (String e : list) {
212 for (String p : alt) {
213 result.add(e + p);
214 }
215 }
216 }
217
218 return result;
219 }
220
221 List<String> addCat (List<String> list, char[] cat){
222 List<String> result = new LinkedList<String>();
223
224 if (list == null || list.size() == 0){
225 for (char c : cat){
226 result.add(Character.toString(c));
227 }
228
229 } else {
230 for (String e : list) {
231 for (char c : cat){
232 result.add(e + c);
233 }
234 }
235 }
236
237 return result;
238 }
239
240 void error (String msg){
241 throw new Exception(msg);
242 }
243
244 protected char[] createCategory(String cat){
245 char[] s = cat.toCharArray();
246 int l1 = s.length-1;
247 char[] d = s;
248
249
250 for (int i=0, j=0; i<s.length; i++){
251 char c = s[i];
252 if ((c == CAT_CHAR) && (i>0) && (i<l1)){
253 char c0 = s[i-1];
254 char c1 = s[i+1];
255 int n = c1 - c0;
256
257 int len = j + n + (s.length-i-2);
258 char[] dNew = new char[len];
259 System.arraycopy(d, 0, dNew, 0, j);
260 d = dNew;
261
262 for (int k=c0+1; k<=c1; k++){
263 d[j++] = (char)k;
264 }
265 i++;
266
267 } else {
268 d[j++] = c;
269 }
270 }
271
272 return d;
273 }
274
275 // seq := {LIT | cat | alt}*
276 // cat := `[ LIT `]
277 // alt := `< spec {`| spec}* `>
278
279 public List<String> expand() {
280 return seq();
281 }
282
283 List<String> seq() {
284 List<String> result = null;
285
286 for (nextToken(); token != EOS; ){
287 if (!token.isSymbol()){
288 result = addLiteral( result,token.value);
289 nextToken();
290
291 } else if (token == ALT_START){
292 result = addAlt( result, alt());
293
294 } else if (token == CAT_START){
295 result = addCat( result, cat());
296
297 } else {
298 break;
299 }
300 }
301
302 return result;
303 }
304
305
306 List<String> alt() {
307 List<String> result = null;
308
309 assert token == ALT_START;
310
311 do {
312 result = addSeq(result, seq());
313 } while (token == ALT);
314
315 if (!match(ALT_END)){
316 error("unterminated alternative");
317 }
318 return result;
319 }
320
321 char[] cat() {
322 char[] set = null;
323
324 assert token == CAT_START;
325
326 nextToken();
327 if (!token.isSymbol()){
328 set = createCategory(token.value);
329 nextToken();
330 }
331
332 if (!match(CAT_END)){
333 error("unterminated category");
334 }
335 return set;
336 }
337
338
339 public static void main (String[] args) {
340 //String a = "<B[0-3]C>";
341 String a = args[0];
342 System.out.println(a);
343
344 StringExpander ex = new StringExpander(a);
345
346 /**
347 for (ex.nextToken(); ex.token != EOS; ex.nextToken()){
348 System.out.println(ex.token);
349 }
350 **/
351 /**/
352 for (String s : ex.expand()) {
353 System.out.println(s);
354 }
355 /**/
356 /**
357 System.out.println(new String(ex.createCategory(args[0])));
358 **/
359 }
360 }