1 /*
   2  * Permission is hereby granted, free of charge, to any person obtaining a copy of
   3  * this software and associated documentation files (the "Software"), to deal in
   4  * the Software without restriction, including without limitation the rights to
   5  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
   6  * of the Software, and to permit persons to whom the Software is furnished to do
   7  * so, subject to the following conditions:
   8  *
   9  * The above copyright notice and this permission notice shall be included in all
  10  * copies or substantial portions of the Software.
  11  *
  12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  18  * SOFTWARE.
  19  */
  20 package jdk.nashorn.internal.runtime.regexp.joni;
  21 
  22 import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
  23 import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
  24 import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
  25 import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
  26 import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
  27 import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
  28 import jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode;
  29 import jdk.nashorn.internal.runtime.regexp.joni.ast.StringNode;
  30 import jdk.nashorn.internal.runtime.regexp.joni.constants.NodeType;
  31 import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
  32 import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
  33 import jdk.nashorn.internal.runtime.regexp.joni.exception.SyntaxException;
  34 
  35 abstract class Compiler implements ErrorMessages {
  36     protected final Analyser analyser;
  37     protected final Regex regex;
  38 
  39     protected Compiler(final Analyser analyser) {
  40         this.analyser = analyser;
  41         this.regex = analyser.regex;
  42     }
  43 
  44     final void compile() {
  45         prepare();
  46         compileTree(analyser.root);
  47         finish();
  48     }
  49 
  50     protected abstract void prepare();
  51     protected abstract void finish();
  52 
  53     protected abstract void compileAltNode(ConsAltNode node);
  54 
  55     private void compileStringRawNode(final StringNode sn) {
  56         if (sn.length() <= 0) {
  57             return;
  58         }
  59         addCompileString(sn.chars, sn.p, sn.length(), false);
  60     }
  61 
  62     private void compileStringNode(final StringNode node) {
  63         final StringNode sn = node;
  64         if (sn.length() <= 0) {
  65             return;
  66         }
  67 
  68         final boolean ambig = sn.isAmbig();
  69 
  70         int p, prev;
  71         p = prev = sn.p;
  72         final int end = sn.end;
  73         final char[] chars = sn.chars;
  74         p++;
  75         int slen = 1;
  76 
  77         while (p < end) {
  78             slen++;
  79             p++;
  80         }
  81         addCompileString(chars, prev, slen, ambig);
  82     }
  83 
  84     protected abstract void addCompileString(char[] chars, int p, int strLength, boolean ignoreCase);
  85 
  86     protected abstract void compileCClassNode(CClassNode node);
  87     protected abstract void compileAnyCharNode();
  88     protected abstract void compileBackrefNode(BackRefNode node);
  89     protected abstract void compileNonCECQuantifierNode(QuantifierNode node);
  90     protected abstract void compileOptionNode(EncloseNode node);
  91     protected abstract void compileEncloseNode(EncloseNode node);
  92     protected abstract void compileAnchorNode(AnchorNode node);
  93 
  94     protected final void compileTree(final Node node) {
  95         switch (node.getType()) {
  96         case NodeType.LIST:
  97             ConsAltNode lin = (ConsAltNode)node;
  98             do {
  99                 compileTree(lin.car);
 100             } while ((lin = lin.cdr) != null);
 101             break;
 102 
 103         case NodeType.ALT:
 104             compileAltNode((ConsAltNode)node);
 105             break;
 106 
 107         case NodeType.STR:
 108             final StringNode sn = (StringNode)node;
 109             if (sn.isRaw()) {
 110                 compileStringRawNode(sn);
 111             } else {
 112                 compileStringNode(sn);
 113             }
 114             break;
 115 
 116         case NodeType.CCLASS:
 117             compileCClassNode((CClassNode)node);
 118             break;
 119 
 120         case NodeType.CANY:
 121             compileAnyCharNode();
 122             break;
 123 
 124         case NodeType.BREF:
 125             compileBackrefNode((BackRefNode)node);
 126             break;
 127 
 128         case NodeType.QTFR:
 129             compileNonCECQuantifierNode((QuantifierNode)node);
 130             break;
 131 
 132         case NodeType.ENCLOSE:
 133             final EncloseNode enode = (EncloseNode)node;
 134             if (enode.isOption()) {
 135                 compileOptionNode(enode);
 136             } else {
 137                 compileEncloseNode(enode);
 138             }
 139             break;
 140 
 141         case NodeType.ANCHOR:
 142             compileAnchorNode((AnchorNode)node);
 143             break;
 144 
 145         default:
 146             // undefined node type
 147             newInternalException(ERR_PARSER_BUG);
 148         } // switch
 149     }
 150 
 151     protected final void compileTreeNTimes(final Node node, final int n) {
 152         for (int i=0; i<n; i++) {
 153             compileTree(node);
 154         }
 155     }
 156 
 157     protected void newSyntaxException(final String message) {
 158         throw new SyntaxException(message);
 159     }
 160 
 161     protected void newInternalException(final String message) {
 162         throw new InternalException(message);
 163     }
 164 }