blob: 73752caa02a618f810c34b036d0aeca67d053c40 [file] [log] [blame]
/*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package jdk.nashorn.internal.runtime.regexp.joni;
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
import jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.StringNode;
import jdk.nashorn.internal.runtime.regexp.joni.constants.NodeType;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
import jdk.nashorn.internal.runtime.regexp.joni.exception.SyntaxException;
abstract class Compiler implements ErrorMessages {
protected final Analyser analyser;
protected final Regex regex;
protected Compiler(final Analyser analyser) {
this.analyser = analyser;
this.regex = analyser.regex;
}
final void compile() {
prepare();
compileTree(analyser.root);
finish();
}
protected abstract void prepare();
protected abstract void finish();
protected abstract void compileAltNode(ConsAltNode node);
private void compileStringRawNode(final StringNode sn) {
if (sn.length() <= 0) {
return;
}
addCompileString(sn.chars, sn.p, sn.length(), false);
}
private void compileStringNode(final StringNode node) {
final StringNode sn = node;
if (sn.length() <= 0) {
return;
}
final boolean ambig = sn.isAmbig();
int p, prev;
p = prev = sn.p;
final int end = sn.end;
final char[] chars = sn.chars;
p++;
int slen = 1;
while (p < end) {
slen++;
p++;
}
addCompileString(chars, prev, slen, ambig);
}
protected abstract void addCompileString(char[] chars, int p, int strLength, boolean ignoreCase);
protected abstract void compileCClassNode(CClassNode node);
protected abstract void compileAnyCharNode();
protected abstract void compileBackrefNode(BackRefNode node);
protected abstract void compileNonCECQuantifierNode(QuantifierNode node);
protected abstract void compileOptionNode(EncloseNode node);
protected abstract void compileEncloseNode(EncloseNode node);
protected abstract void compileAnchorNode(AnchorNode node);
protected final void compileTree(final Node node) {
switch (node.getType()) {
case NodeType.LIST:
ConsAltNode lin = (ConsAltNode)node;
do {
compileTree(lin.car);
} while ((lin = lin.cdr) != null);
break;
case NodeType.ALT:
compileAltNode((ConsAltNode)node);
break;
case NodeType.STR:
final StringNode sn = (StringNode)node;
if (sn.isRaw()) {
compileStringRawNode(sn);
} else {
compileStringNode(sn);
}
break;
case NodeType.CCLASS:
compileCClassNode((CClassNode)node);
break;
case NodeType.CANY:
compileAnyCharNode();
break;
case NodeType.BREF:
compileBackrefNode((BackRefNode)node);
break;
case NodeType.QTFR:
compileNonCECQuantifierNode((QuantifierNode)node);
break;
case NodeType.ENCLOSE:
final EncloseNode enode = (EncloseNode)node;
if (enode.isOption()) {
compileOptionNode(enode);
} else {
compileEncloseNode(enode);
}
break;
case NodeType.ANCHOR:
compileAnchorNode((AnchorNode)node);
break;
default:
// undefined node type
newInternalException(ERR_PARSER_BUG);
} // switch
}
protected final void compileTreeNTimes(final Node node, final int n) {
for (int i=0; i<n; i++) {
compileTree(node);
}
}
protected void newSyntaxException(final String message) {
throw new SyntaxException(message);
}
protected void newInternalException(final String message) {
throw new InternalException(message);
}
}