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

Thu, 16 May 2013 19:52:39 +0200

author
hannesw
date
Thu, 16 May 2013 19:52:39 +0200
changeset 273
98798a6336de
parent 247
5a3f7867e19c
child 447
7503f30c1355
permissions
-rw-r--r--

8012359: Increase code coverage in Joni
Reviewed-by: jlaskey, lagergren

hannesw@115 1 /*
hannesw@115 2 * Copyright (c) 2010, 2013, 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
hannesw@115 28 import jdk.nashorn.internal.runtime.ParserException;
hannesw@115 29 import jdk.nashorn.internal.runtime.regexp.joni.Matcher;
hannesw@115 30 import jdk.nashorn.internal.runtime.regexp.joni.Option;
hannesw@115 31 import jdk.nashorn.internal.runtime.regexp.joni.Regex;
hannesw@115 32 import jdk.nashorn.internal.runtime.regexp.joni.Region;
hannesw@115 33 import jdk.nashorn.internal.runtime.regexp.joni.Syntax;
hannesw@115 34 import jdk.nashorn.internal.runtime.regexp.joni.exception.JOniException;
hannesw@115 35
hannesw@115 36 import java.util.regex.Pattern;
hannesw@115 37 import java.util.regex.PatternSyntaxException;
hannesw@115 38
hannesw@115 39 /**
hannesw@115 40 * Regular expression implementation based on the Joni engine from the JRuby project.
hannesw@115 41 */
hannesw@115 42 public class JoniRegExp extends RegExp {
hannesw@115 43
hannesw@115 44 /** Compiled Joni Regex */
hannesw@115 45 private Regex regex;
hannesw@115 46
hannesw@115 47 /** Matcher */
hannesw@115 48 private RegExpMatcher matcher;
hannesw@115 49
hannesw@115 50 /**
hannesw@115 51 * Construct a Regular expression from the given {@code pattern} and {@code flags} strings.
hannesw@115 52 *
hannesw@115 53 * @param pattern RegExp pattern string
hannesw@115 54 * @param flags RegExp flag string
hannesw@115 55 * @throws ParserException if flags is invalid or pattern string has syntax error.
hannesw@115 56 */
hannesw@115 57 public JoniRegExp(final String pattern, final String flags) throws ParserException {
hannesw@115 58 super(pattern, flags);
hannesw@115 59
hannesw@115 60 int option = Option.SINGLELINE;
hannesw@115 61
hannesw@115 62 if (this.isIgnoreCase()) {
hannesw@115 63 option |= Option.IGNORECASE;
hannesw@115 64 }
hannesw@115 65 if (this.isMultiline()) {
hannesw@115 66 option &= ~Option.SINGLELINE;
hannesw@115 67 option |= Option.NEGATE_SINGLELINE;
hannesw@115 68 }
hannesw@115 69
hannesw@115 70 try {
hannesw@115 71 RegExpScanner parsed;
hannesw@115 72
hannesw@115 73 try {
hannesw@115 74 parsed = RegExpScanner.scan(pattern);
hannesw@115 75 } catch (final PatternSyntaxException e) {
hannesw@115 76 // refine the exception with a better syntax error, if this
hannesw@115 77 // passes, just rethrow what we have
hannesw@115 78 Pattern.compile(pattern, 0);
hannesw@115 79 throw e;
hannesw@115 80 }
hannesw@115 81
hannesw@115 82 if (parsed != null) {
hannesw@115 83 char[] javaPattern = parsed.getJavaPattern().toCharArray();
hannesw@115 84 this.regex = new Regex(javaPattern, 0, javaPattern.length, option, Syntax.JAVASCRIPT);
hannesw@115 85 this.groupsInNegativeLookahead = parsed.getGroupsInNegativeLookahead();
hannesw@115 86 }
hannesw@115 87 } catch (final PatternSyntaxException e2) {
hannesw@115 88 throwParserException("syntax", e2.getMessage());
hannesw@115 89 } catch (JOniException e2) {
hannesw@115 90 throwParserException("syntax", e2.getMessage());
hannesw@115 91 }
hannesw@115 92 }
hannesw@115 93
hannesw@115 94 @Override
hannesw@115 95 public RegExpMatcher match(final String input) {
hannesw@115 96 if (regex == null) {
hannesw@115 97 return null;
hannesw@115 98 }
hannesw@115 99
lagergren@139 100 RegExpMatcher currentMatcher = this.matcher;
hannesw@115 101
lagergren@139 102 if (currentMatcher == null || input != currentMatcher.getInput()) {
lagergren@139 103 currentMatcher = new JoniMatcher(input);
lagergren@139 104 this.matcher = currentMatcher;
hannesw@115 105 }
hannesw@115 106
lagergren@139 107 return currentMatcher;
hannesw@115 108 }
hannesw@115 109
hannesw@115 110 /**
hannesw@115 111 * RegExp Factory class for Joni regexp engine.
hannesw@115 112 */
hannesw@115 113 public static class Factory extends RegExpFactory {
hannesw@115 114
hannesw@115 115 @Override
hannesw@273 116 public RegExp compile(final String pattern, final String flags) throws ParserException {
hannesw@115 117 return new JoniRegExp(pattern, flags);
hannesw@115 118 }
hannesw@115 119
hannesw@115 120 }
hannesw@115 121
hannesw@115 122 class JoniMatcher implements RegExpMatcher {
hannesw@115 123 final String input;
lagergren@247 124 final Matcher joniMatcher;
hannesw@115 125
hannesw@115 126 JoniMatcher(final String input) {
hannesw@115 127 this.input = input;
lagergren@247 128 this.joniMatcher = regex.matcher(input.toCharArray());
hannesw@115 129 }
hannesw@115 130
hannesw@115 131 @Override
hannesw@115 132 public boolean search(final int start) {
lagergren@247 133 return joniMatcher.search(start, input.length(), Option.NONE) > -1;
hannesw@115 134 }
hannesw@115 135
hannesw@115 136 @Override
hannesw@115 137 public String getInput() {
hannesw@115 138 return input;
hannesw@115 139 }
hannesw@115 140
hannesw@115 141 @Override
hannesw@115 142 public int start() {
lagergren@247 143 return joniMatcher.getBegin();
hannesw@115 144 }
hannesw@115 145
hannesw@115 146 @Override
hannesw@115 147 public int start(final int group) {
lagergren@247 148 return group == 0 ? start() : joniMatcher.getRegion().beg[group];
hannesw@115 149 }
hannesw@115 150
hannesw@115 151 @Override
hannesw@115 152 public int end() {
lagergren@247 153 return joniMatcher.getEnd();
hannesw@115 154 }
hannesw@115 155
hannesw@115 156 @Override
hannesw@115 157 public int end(final int group) {
lagergren@247 158 return group == 0 ? end() : joniMatcher.getRegion().end[group];
hannesw@115 159 }
hannesw@115 160
hannesw@115 161 @Override
hannesw@115 162 public String group() {
lagergren@247 163 return input.substring(joniMatcher.getBegin(), joniMatcher.getEnd());
hannesw@115 164 }
hannesw@115 165
hannesw@115 166 @Override
hannesw@115 167 public String group(final int group) {
hannesw@115 168 if (group == 0) {
hannesw@115 169 return group();
hannesw@115 170 }
lagergren@247 171 final Region region = joniMatcher.getRegion();
hannesw@115 172 return input.substring(region.beg[group], region.end[group]);
hannesw@115 173 }
hannesw@115 174
hannesw@115 175 @Override
hannesw@115 176 public int groupCount() {
lagergren@247 177 final Region region = joniMatcher.getRegion();
hannesw@115 178 return region == null ? 0 : region.numRegs - 1;
hannesw@115 179 }
hannesw@115 180 }
hannesw@115 181 }

mercurial