Sat, 09 Nov 2019 20:29:44 +0800
Merge
1 /*
2 * Copyright (c) 2010, 2019, 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 */
26 package jdk.nashorn.internal.runtime.regexp;
28 import static java.util.regex.Pattern.CASE_INSENSITIVE;
29 import static java.util.regex.Pattern.MULTILINE;
30 import static java.util.regex.Pattern.UNICODE_CASE;
32 import java.util.regex.Matcher;
33 import java.util.regex.Pattern;
34 import java.util.regex.PatternSyntaxException;
35 import jdk.nashorn.internal.runtime.ParserException;
37 /**
38 * Default regular expression implementation based on java.util.regex package.
39 *
40 * Note that this class is not thread-safe as it stores the current match result
41 * and the string being matched in instance fields.
42 */
43 public class JdkRegExp extends RegExp {
45 /** Java regexp pattern to use for match. We compile to one of these */
46 private Pattern pattern;
48 /**
49 * Construct a Regular expression from the given {@code source} and {@code flags} strings.
50 *
51 * @param source RegExp source string
52 * @param flags RegExp flag string
53 * @throws ParserException if flags is invalid or source string has syntax error.
54 */
55 public JdkRegExp(final String source, final String flags) throws ParserException {
56 super(source, flags);
58 int intFlags = 0;
60 if (isIgnoreCase()) {
61 intFlags |= CASE_INSENSITIVE | UNICODE_CASE;
62 }
63 if (isMultiline()) {
64 intFlags |= MULTILINE;
65 }
67 try {
68 RegExpScanner parsed;
70 try {
71 parsed = RegExpScanner.scan(source);
72 } catch (final PatternSyntaxException e) {
73 // refine the exception with a better syntax error, if this
74 // passes, just rethrow what we have
75 Pattern.compile(source, intFlags);
76 throw e;
77 }
79 if (parsed != null) {
80 this.pattern = Pattern.compile(parsed.getJavaPattern(), intFlags);
81 this.groupsInNegativeLookahead = parsed.getGroupsInNegativeLookahead();
82 }
83 } catch (final PatternSyntaxException e2) {
84 throwParserException("syntax", e2.getMessage());
85 } catch (StackOverflowError e3) {
86 throw new RuntimeException(e3);
87 }
88 }
90 @Override
91 public RegExpMatcher match(final String str) {
92 if (pattern == null) {
93 return null; // never matches or similar, e.g. a[]
94 }
96 return new DefaultMatcher(str);
97 }
99 class DefaultMatcher implements RegExpMatcher {
100 final String input;
101 final Matcher defaultMatcher;
103 DefaultMatcher(final String input) {
104 this.input = input;
105 this.defaultMatcher = pattern.matcher(input);
106 }
108 @Override
109 public boolean search(final int start) {
110 return defaultMatcher.find(start);
111 }
113 @Override
114 public String getInput() {
115 return input;
116 }
118 @Override
119 public int start() {
120 return defaultMatcher.start();
121 }
123 @Override
124 public int start(final int group) {
125 return defaultMatcher.start(group);
126 }
128 @Override
129 public int end() {
130 return defaultMatcher.end();
131 }
133 @Override
134 public int end(final int group) {
135 return defaultMatcher.end(group);
136 }
138 @Override
139 public String group() {
140 return defaultMatcher.group();
141 }
143 @Override
144 public String group(final int group) {
145 return defaultMatcher.group(group);
146 }
148 @Override
149 public int groupCount() {
150 return defaultMatcher.groupCount();
151 }
152 }
154 }