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:
newInternalException(ERR_PARSER_BUG);
}
}
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);
}
}