Mercurial > hg > Members > kono > jpf-core
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/gov/nasa/jpf/util/script/StringExpander.java Fri Jan 23 10:14:01 2015 -0800 @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2014, United States Government, as represented by the + * Administrator of the National Aeronautics and Space Administration. + * All rights reserved. + * + * The Java Pathfinder core (jpf-core) platform is licensed under the + * Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package gov.nasa.jpf.util.script; + + +import java.util.LinkedList; +import java.util.List; + +/** + * utility class to expand regular expression like strings. We support + * alternatives "<..|..>" and character categories "[.. X-Z ..]". Alternatives + * can be nested, char categories can include '-' ranges + * + * e.g. "a<B|X[0-1]Y>z" => aBz, aX0Yz, aX1Yz + * + * <2do> this is awfully connected to ESParser - we should really make it more generic + * (this is the reason why it was moved from the general gov.nasa.jpf.util to + * this package) + */ +public class StringExpander { + + public static final char META_CHAR = '`'; // starts a symbol + + public static final char ALT_START_CHAR = '<'; + public static final char ALT_END_CHAR = '>'; + public static final char ALT_CHAR = '|'; + + public static final char CAT_START_CHAR = '['; + public static final char CAT_END_CHAR = ']'; + public static final char CAT_CHAR = '-'; + + static class Exception extends RuntimeException { + Exception(String details){ + super(details); + } + } + + static class Token { + String value; + + Token (String value){ + this.value = value; + } + int length() { + return value.length(); + } + boolean isSymbol() { + return false; + } + @Override + public String toString(){ + return value; + } + + } + static class Symbol extends Token { + Symbol (String s){ + super(s); + } + @Override + boolean isSymbol(){ + return true; + } + } + + // our symbol tokens + static final Symbol CAT_START = new Symbol("CAT_START"); + static final Symbol CAT_END = new Symbol("CAT_END"); + + static final Symbol ALT_START = new Symbol("ALT_START"); + static final Symbol ALT_END = new Symbol("ALT_END"); + static final Symbol ALT = new Symbol("ALT"); + static final Symbol EOS = new Symbol("END"); + + final String src; + final int len; + + Token token; + int pos; + +/** + // a quoted symbol char version - doesn't look nice, but is more general + void nextToken () { + + int i = pos; + int len = this.len; + + if (i>=len){ + token = EOS; + + } else { + if (src.charAt(i) == META_CHAR){ // symbol + char c = src.charAt(++i); + switch (c){ + case CAT_START_CHAR: token = CAT_START; break; + case CAT_END_CHAR: token = CAT_END; break; + + case ALT_START_CHAR: token = ALT_START; break; + case ALT_CHAR: token = ALT; break; + case ALT_END_CHAR: token = ALT_END; break; + default: + error("illegal symbol: " + c); + } + pos += 2; + + } else { // string literal + int j = i + 1; + for (; j < len && src.charAt(j) != META_CHAR; j++); + pos = j; + token = new Token(src.substring(i, j)); + } + } + } +**/ + + private boolean isMetaChar(char c){ + return ((c == CAT_START_CHAR) || (c == CAT_END_CHAR) || + (c == ALT_START_CHAR) || (c == ALT_END_CHAR) || (c == ALT_CHAR)); + + } + + void nextToken() { + int i = pos; + int len = this.len; + + if (i>=len){ + token = EOS; + + } else { + char c = src.charAt(i); + switch (c){ + case CAT_START_CHAR: token = CAT_START; pos++; break; + case CAT_END_CHAR: token = CAT_END; pos++; break; + + case ALT_START_CHAR: token = ALT_START; pos++; break; + case ALT_CHAR: token = ALT; pos++; break; + case ALT_END_CHAR: token = ALT_END; pos++; break; + + default: + int j = i + 1; + for (; j < len && !isMetaChar(src.charAt(j)); j++); + pos = j; + token = new Token(src.substring(i, j)); + } + } + } + + boolean match (Symbol sym){ + if (token == sym){ + nextToken(); + return true; + } else { + return false; + } + } + + public StringExpander (String src){ + this.src = src; + this.len = src.length(); + this.pos = 0; + } + + List<String> addSeq (List<String> list, List<String> seq){ + List<String> result = new LinkedList<String>(); + + if (list != null && list.size() > 0){ + result.addAll(list); + } + result.addAll(seq); + + return result; + } + + List<String> addLiteral (List<String> list, String s){ + List<String> result = new LinkedList<String>(); + + if (list == null || list.size() == 0){ + result.add(s); + + } else { + for (String e : list) { + result.add(e + s); + } + } + + return result; + } + + List<String> addAlt (List<String> list, List<String>alt){ + List<String> result = new LinkedList<String>(); + + if (list == null || list.size() == 0){ + result.addAll(alt); + + } else { + for (String e : list) { + for (String p : alt) { + result.add(e + p); + } + } + } + + return result; + } + + List<String> addCat (List<String> list, char[] cat){ + List<String> result = new LinkedList<String>(); + + if (list == null || list.size() == 0){ + for (char c : cat){ + result.add(Character.toString(c)); + } + + } else { + for (String e : list) { + for (char c : cat){ + result.add(e + c); + } + } + } + + return result; + } + + void error (String msg){ + throw new Exception(msg); + } + + protected char[] createCategory(String cat){ + char[] s = cat.toCharArray(); + int l1 = s.length-1; + char[] d = s; + + + for (int i=0, j=0; i<s.length; i++){ + char c = s[i]; + if ((c == CAT_CHAR) && (i>0) && (i<l1)){ + char c0 = s[i-1]; + char c1 = s[i+1]; + int n = c1 - c0; + + int len = j + n + (s.length-i-2); + char[] dNew = new char[len]; + System.arraycopy(d, 0, dNew, 0, j); + d = dNew; + + for (int k=c0+1; k<=c1; k++){ + d[j++] = (char)k; + } + i++; + + } else { + d[j++] = c; + } + } + + return d; + } + + // seq := {LIT | cat | alt}* + // cat := `[ LIT `] + // alt := `< spec {`| spec}* `> + + public List<String> expand() { + return seq(); + } + + List<String> seq() { + List<String> result = null; + + for (nextToken(); token != EOS; ){ + if (!token.isSymbol()){ + result = addLiteral( result,token.value); + nextToken(); + + } else if (token == ALT_START){ + result = addAlt( result, alt()); + + } else if (token == CAT_START){ + result = addCat( result, cat()); + + } else { + break; + } + } + + return result; + } + + + List<String> alt() { + List<String> result = null; + + assert token == ALT_START; + + do { + result = addSeq(result, seq()); + } while (token == ALT); + + if (!match(ALT_END)){ + error("unterminated alternative"); + } + return result; + } + + char[] cat() { + char[] set = null; + + assert token == CAT_START; + + nextToken(); + if (!token.isSymbol()){ + set = createCategory(token.value); + nextToken(); + } + + if (!match(CAT_END)){ + error("unterminated category"); + } + return set; + } + + + public static void main (String[] args) { + //String a = "<B[0-3]C>"; + String a = args[0]; + System.out.println(a); + + StringExpander ex = new StringExpander(a); + +/** + for (ex.nextToken(); ex.token != EOS; ex.nextToken()){ + System.out.println(ex.token); + } +**/ +/**/ + for (String s : ex.expand()) { + System.out.println(s); + } +/**/ +/** + System.out.println(new String(ex.createCategory(args[0]))); +**/ + } +}