src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java

Sat, 09 Nov 2019 20:29:44 +0800

author
aoqi
date
Sat, 09 Nov 2019 20:29:44 +0800
changeset 2511
52348a92adca
parent 1205
4112748288bb
parent 2510
fba077f48da2
permissions
-rw-r--r--

Merge

hannesw@115 1 /*
hannesw@2510 2 * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
hannesw@115 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
hannesw@115 4 *
hannesw@115 5 * This code is free software; you can redistribute it and/or modify it
hannesw@115 6 * under the terms of the GNU General Public License version 2 only, as
hannesw@115 7 * published by the Free Software Foundation. Oracle designates this
hannesw@115 8 * particular file as subject to the "Classpath" exception as provided
hannesw@115 9 * by Oracle in the LICENSE file that accompanied this code.
hannesw@115 10 *
hannesw@115 11 * This code is distributed in the hope that it will be useful, but WITHOUT
hannesw@115 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
hannesw@115 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
hannesw@115 14 * version 2 for more details (a copy is included in the LICENSE file that
hannesw@115 15 * accompanied this code).
hannesw@115 16 *
hannesw@115 17 * You should have received a copy of the GNU General Public License version
hannesw@115 18 * 2 along with this work; if not, write to the Free Software Foundation,
hannesw@115 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
hannesw@115 20 *
hannesw@115 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
hannesw@115 22 * or visit www.oracle.com if you need additional information or have any
hannesw@115 23 * questions.
hannesw@115 24 */
hannesw@115 25
hannesw@115 26 package jdk.nashorn.internal.runtime.regexp;
hannesw@115 27
attila@962 28 import java.util.regex.Pattern;
attila@962 29 import java.util.regex.PatternSyntaxException;
hannesw@115 30 import jdk.nashorn.internal.runtime.ParserException;
hannesw@115 31 import jdk.nashorn.internal.runtime.regexp.joni.Matcher;
hannesw@115 32 import jdk.nashorn.internal.runtime.regexp.joni.Option;
hannesw@115 33 import jdk.nashorn.internal.runtime.regexp.joni.Regex;
hannesw@115 34 import jdk.nashorn.internal.runtime.regexp.joni.Region;
hannesw@115 35 import jdk.nashorn.internal.runtime.regexp.joni.Syntax;
hannesw@115 36 import jdk.nashorn.internal.runtime.regexp.joni.exception.JOniException;
hannesw@115 37
hannesw@115 38 /**
hannesw@115 39 * Regular expression implementation based on the Joni engine from the JRuby project.
hannesw@115 40 */
hannesw@115 41 public class JoniRegExp extends RegExp {
hannesw@115 42
hannesw@115 43 /** Compiled Joni Regex */
hannesw@115 44 private Regex regex;
hannesw@115 45
hannesw@115 46 /**
hannesw@115 47 * Construct a Regular expression from the given {@code pattern} and {@code flags} strings.
hannesw@115 48 *
hannesw@115 49 * @param pattern RegExp pattern string
hannesw@115 50 * @param flags RegExp flag string
hannesw@115 51 * @throws ParserException if flags is invalid or pattern string has syntax error.
hannesw@115 52 */
hannesw@115 53 public JoniRegExp(final String pattern, final String flags) throws ParserException {
hannesw@115 54 super(pattern, flags);
hannesw@115 55
hannesw@115 56 int option = Option.SINGLELINE;
hannesw@115 57
hannesw@115 58 if (this.isIgnoreCase()) {
hannesw@115 59 option |= Option.IGNORECASE;
hannesw@115 60 }
hannesw@115 61 if (this.isMultiline()) {
hannesw@115 62 option &= ~Option.SINGLELINE;
hannesw@115 63 option |= Option.NEGATE_SINGLELINE;
hannesw@115 64 }
hannesw@115 65
hannesw@115 66 try {
hannesw@115 67 RegExpScanner parsed;
hannesw@115 68
hannesw@115 69 try {
hannesw@115 70 parsed = RegExpScanner.scan(pattern);
hannesw@115 71 } catch (final PatternSyntaxException e) {
hannesw@115 72 // refine the exception with a better syntax error, if this
hannesw@115 73 // passes, just rethrow what we have
hannesw@115 74 Pattern.compile(pattern, 0);
hannesw@115 75 throw e;
hannesw@115 76 }
hannesw@115 77
hannesw@115 78 if (parsed != null) {
attila@962 79 final char[] javaPattern = parsed.getJavaPattern().toCharArray();
hannesw@115 80 this.regex = new Regex(javaPattern, 0, javaPattern.length, option, Syntax.JAVASCRIPT);
hannesw@115 81 this.groupsInNegativeLookahead = parsed.getGroupsInNegativeLookahead();
hannesw@115 82 }
hannesw@447 83 } catch (final PatternSyntaxException | JOniException e2) {
hannesw@115 84 throwParserException("syntax", e2.getMessage());
hannesw@2510 85 } catch (StackOverflowError e3) {
hannesw@2510 86 throw new RuntimeException(e3);
hannesw@115 87 }
hannesw@115 88 }
hannesw@115 89
hannesw@115 90 @Override
hannesw@115 91 public RegExpMatcher match(final String input) {
hannesw@115 92 if (regex == null) {
hannesw@115 93 return null;
hannesw@115 94 }
hannesw@115 95
hannesw@846 96 return new JoniMatcher(input);
hannesw@115 97 }
hannesw@115 98
hannesw@115 99 /**
hannesw@115 100 * RegExp Factory class for Joni regexp engine.
hannesw@115 101 */
hannesw@115 102 public static class Factory extends RegExpFactory {
hannesw@115 103
hannesw@115 104 @Override
hannesw@273 105 public RegExp compile(final String pattern, final String flags) throws ParserException {
hannesw@115 106 return new JoniRegExp(pattern, flags);
hannesw@115 107 }
hannesw@115 108
hannesw@115 109 }
hannesw@115 110
hannesw@115 111 class JoniMatcher implements RegExpMatcher {
hannesw@115 112 final String input;
lagergren@247 113 final Matcher joniMatcher;
hannesw@115 114
hannesw@115 115 JoniMatcher(final String input) {
hannesw@115 116 this.input = input;
lagergren@247 117 this.joniMatcher = regex.matcher(input.toCharArray());
hannesw@115 118 }
hannesw@115 119
hannesw@115 120 @Override
hannesw@115 121 public boolean search(final int start) {
lagergren@247 122 return joniMatcher.search(start, input.length(), Option.NONE) > -1;
hannesw@115 123 }
hannesw@115 124
hannesw@115 125 @Override
hannesw@115 126 public String getInput() {
hannesw@115 127 return input;
hannesw@115 128 }
hannesw@115 129
hannesw@115 130 @Override
hannesw@115 131 public int start() {
lagergren@247 132 return joniMatcher.getBegin();
hannesw@115 133 }
hannesw@115 134
hannesw@115 135 @Override
hannesw@115 136 public int start(final int group) {
lagergren@247 137 return group == 0 ? start() : joniMatcher.getRegion().beg[group];
hannesw@115 138 }
hannesw@115 139
hannesw@115 140 @Override
hannesw@115 141 public int end() {
lagergren@247 142 return joniMatcher.getEnd();
hannesw@115 143 }
hannesw@115 144
hannesw@115 145 @Override
hannesw@115 146 public int end(final int group) {
lagergren@247 147 return group == 0 ? end() : joniMatcher.getRegion().end[group];
hannesw@115 148 }
hannesw@115 149
hannesw@115 150 @Override
hannesw@115 151 public String group() {
lagergren@247 152 return input.substring(joniMatcher.getBegin(), joniMatcher.getEnd());
hannesw@115 153 }
hannesw@115 154
hannesw@115 155 @Override
hannesw@115 156 public String group(final int group) {
hannesw@115 157 if (group == 0) {
hannesw@115 158 return group();
hannesw@115 159 }
lagergren@247 160 final Region region = joniMatcher.getRegion();
hannesw@115 161 return input.substring(region.beg[group], region.end[group]);
hannesw@115 162 }
hannesw@115 163
hannesw@115 164 @Override
hannesw@115 165 public int groupCount() {
lagergren@247 166 final Region region = joniMatcher.getRegion();
hannesw@115 167 return region == null ? 0 : region.numRegs - 1;
hannesw@115 168 }
hannesw@115 169 }
hannesw@115 170 }

mercurial