1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21package proguard.util; 22 23import java.util.List; 24 25/** 26 * This StringParser can create StringMatcher instances for regular expressions. 27 * The regular expressions are either presented as a list, or they are 28 * interpreted as comma-separated lists, optionally prefixed with '!' negators. 29 * If an entry with a negator matches, a negative match is returned, without 30 * considering any subsequent entries in the list. The creation of StringMatcher 31 * instances for the entries is delegated to the given StringParser. 32 * 33 * @author Eric Lafortune 34 */ 35public class ListParser implements StringParser 36{ 37 private final StringParser stringParser; 38 39 40 /** 41 * Creates a new ListParser that parses individual elements in the 42 * comma-separated list with the given StringParser. 43 */ 44 public ListParser(StringParser stringParser) 45 { 46 this.stringParser = stringParser; 47 } 48 49 50 // Implementations for StringParser. 51 52 public StringMatcher parse(String regularExpression) 53 { 54 // Does the regular expression contain a ',' list separator? 55 return parse(ListUtil.commaSeparatedList(regularExpression)); 56 } 57 58 59 /** 60 * Creates a StringMatcher for the given regular expression, which can 61 * be a list of optionally negated simple entries. 62 * <p> 63 * An empty list results in a StringMatcher that matches any string. 64 */ 65 public StringMatcher parse(List regularExpressions) 66 { 67 StringMatcher listMatcher = null; 68 69 // Loop over all simple regular expressions, backward, creating a 70 // linked list of matchers. 71 for (int index = regularExpressions.size()-1; index >=0; index--) 72 { 73 String regularExpression = (String)regularExpressions.get(index); 74 75 StringMatcher entryMatcher = parseEntry(regularExpression); 76 77 // Prepend the entry matcher. 78 listMatcher = 79 listMatcher == null ? 80 (StringMatcher)entryMatcher : 81 isNegated(regularExpression) ? 82 (StringMatcher)new AndMatcher(entryMatcher, listMatcher) : 83 (StringMatcher)new OrMatcher(entryMatcher, listMatcher); 84 } 85 86 return listMatcher != null ? listMatcher : new ConstantMatcher(true); 87 } 88 89 90 // Small utility methods. 91 92 /** 93 * Creates a StringMatcher for the given regular expression, which is a 94 * an optionally negated simple expression. 95 */ 96 private StringMatcher parseEntry(String regularExpression) 97 { 98 // Wrap the matcher if the regular expression starts with a '!' negator. 99 return isNegated(regularExpression) ? 100 new NotMatcher(stringParser.parse(regularExpression.substring(1))) : 101 stringParser.parse(regularExpression); 102 } 103 104 105 /** 106 * Returns whether the given simple regular expression is negated. 107 */ 108 private boolean isNegated(String regularExpression) 109 { 110 return regularExpression.length() > 0 && 111 regularExpression.charAt(0) == '!'; 112 } 113 114 115 /** 116 * A main method for testing name matching. 117 */ 118 public static void main(String[] args) 119 { 120 try 121 { 122 System.out.println("Regular expression ["+args[0]+"]"); 123 ListParser parser = new ListParser(new NameParser()); 124 StringMatcher matcher = parser.parse(args[0]); 125 for (int index = 1; index < args.length; index++) 126 { 127 String string = args[index]; 128 System.out.print("String ["+string+"]"); 129 System.out.println(" -> match = "+matcher.matches(args[index])); 130 } 131 } 132 catch (Exception ex) 133 { 134 ex.printStackTrace(); 135 } 136 } 137} 138