1 /* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.nashorn.internal.runtime.regexp; 27 28 import java.util.regex.MatchResult; 29 import jdk.nashorn.internal.runtime.BitVector; 30 import jdk.nashorn.internal.runtime.ECMAErrors; 31 import jdk.nashorn.internal.runtime.ParserException; 32 33 /** 34 * This is the base class for representing a parsed regular expression. 35 * 36 * Instances of this class are created by a {@link RegExpFactory}. 37 */ 38 public abstract class RegExp { 39 40 /** Pattern string. */ 41 private final String source; 42 43 /** Global search flag for this regexp.*/ 44 private boolean global; 45 46 /** Case insensitive flag for this regexp */ 47 private boolean ignoreCase; 48 49 /** Multi-line flag for this regexp */ 50 private boolean multiline; 51 52 /** BitVector that keeps track of groups in negative lookahead */ 53 protected BitVector groupsInNegativeLookahead; 54 55 /** 56 * Constructor. 57 * 58 * @param source the source string 59 * @param flags the flags string 60 */ 61 protected RegExp(final String source, final String flags) { 62 this.source = source.length() == 0 ? "(?:)" : source; 63 for (int i = 0; i < flags.length(); i++) { 64 final char ch = flags.charAt(i); 65 switch (ch) { 66 case 'g': 67 if (this.global) { 68 throwParserException("repeated.flag", "g"); 69 } 70 this.global = true; 71 break; 72 case 'i': 73 if (this.ignoreCase) { 74 throwParserException("repeated.flag", "i"); 75 } 76 this.ignoreCase = true; 77 break; 78 case 'm': 79 if (this.multiline) { 80 throwParserException("repeated.flag", "m"); 81 } 82 this.multiline = true; 83 break; 84 default: 85 throwParserException("unsupported.flag", Character.toString(ch)); 86 } 87 } 88 } 89 90 /** 91 * Get the source pattern of this regular expression. 92 * 93 * @return the source string 94 */ 95 public String getSource() { 96 return source; 97 } 98 99 /** 100 * Set the global flag of this regular expression to {@code global}. 101 * 102 * @param global the new global flag 103 */ 104 public void setGlobal(final boolean global) { 105 this.global = global; 106 } 107 108 /** 109 * Get the global flag of this regular expression. 110 * 111 * @return the global flag 112 */ 113 public boolean isGlobal() { 114 return global; 115 } 116 117 /** 118 * Get the ignore-case flag of this regular expression. 119 * 120 * @return the ignore-case flag 121 */ 122 public boolean isIgnoreCase() { 123 return ignoreCase; 124 } 125 126 /** 127 * Get the multiline flag of this regular expression. 128 * 129 * @return the multiline flag 130 */ 131 public boolean isMultiline() { 132 return multiline; 133 } 134 135 /** 136 * Get a bitset indicating which of the groups in this regular expression are inside a negative lookahead. 137 * 138 * @return the groups-in-negative-lookahead bitset 139 */ 140 public BitVector getGroupsInNegativeLookahead() { 141 return groupsInNegativeLookahead; 142 } 143 144 /** 145 * Match this regular expression against {@code str}, starting at index {@code start} 146 * and return a {@link MatchResult} with the result. 147 * 148 * @param str the string 149 * @return the matcher 150 */ 151 public abstract RegExpMatcher match(String str); 152 153 /** 154 * Throw a regexp parser exception. 155 * 156 * @param key the message key 157 * @param str string argument 158 * @throws jdk.nashorn.internal.runtime.ParserException unconditionally 159 */ 160 protected static void throwParserException(final String key, final String str) throws ParserException { 161 throw new ParserException(ECMAErrors.getMessage("parser.error.regex." + key, str)); 162 } 163 }