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.CTypeNode;
  26 import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
  27 import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
  28 import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
  29 import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
  30 import jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode;
  31 import jdk.nashorn.internal.runtime.regexp.joni.ast.StringNode;
  32 import jdk.nashorn.internal.runtime.regexp.joni.constants.NodeType;
  33 import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
  34 import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
  35 import jdk.nashorn.internal.runtime.regexp.joni.exception.SyntaxException;
  36 
  37 abstract class Compiler implements ErrorMessages {
  38     protected final Analyser analyser;
  39     protected final Regex regex;
  40 
  41     protected Compiler(Analyser analyser) {
  42         this.analyser = analyser;
  43         this.regex = analyser.regex;
  44     }
  45 
  46     final void compile() {
  47         prepare();
  48         compileTree(analyser.root);
  49         finish();
  50     }
  51 
  52     protected abstract void prepare();
  53     protected abstract void finish();
  54 
  55     protected abstract void compileAltNode(ConsAltNode node);
  56 
  57     private void compileStringRawNode(StringNode sn) {
  58         if (sn.length() <= 0) return;
  59         addCompileString(sn.chars, sn.p, 1 /*sb*/, sn.length(), false);
  60     }
  61 
  62     private void compileStringNode(StringNode node) {
  63         StringNode sn = node;
  64         if (sn.length() <= 0) return;
  65 
  66         boolean ambig = sn.isAmbig();
  67 
  68         int p, prev;
  69         p = prev = sn.p;
  70         int end = sn.end;
  71         char[] chars = sn.chars;
  72         p++;
  73         int slen = 1;
  74 
  75         while (p < end) {
  76             slen++;
  77             p++;
  78         }
  79         addCompileString(chars, prev, 1, slen, ambig);
  80     }
  81 
  82     protected abstract void addCompileString(char[] chars, int p, int mbLength, int strLength, boolean ignoreCase);
  83 
  84     protected abstract void compileCClassNode(CClassNode node);
  85     protected abstract void compileCTypeNode(CTypeNode node);
  86     protected abstract void compileAnyCharNode();
  87     protected abstract void compileCallNode(CallNode node);
  88     protected abstract void compileBackrefNode(BackRefNode node);
  89     protected abstract void compileCECQuantifierNode(QuantifierNode node);
  90     protected abstract void compileNonCECQuantifierNode(QuantifierNode node);
  91     protected abstract void compileOptionNode(EncloseNode node);
  92     protected abstract void compileEncloseNode(EncloseNode node);
  93     protected abstract void compileAnchorNode(AnchorNode node);
  94 
  95     protected final void compileTree(Node node) {
  96         switch (node.getType()) {
  97         case NodeType.LIST:
  98             ConsAltNode lin = (ConsAltNode)node;
  99             do {
 100                 compileTree(lin.car);
 101             } while ((lin = lin.cdr) != null);
 102             break;
 103 
 104         case NodeType.ALT:
 105             compileAltNode((ConsAltNode)node);
 106             break;
 107 
 108         case NodeType.STR:
 109             StringNode sn = (StringNode)node;
 110             if (sn.isRaw()) {
 111                 compileStringRawNode(sn);
 112             } else {
 113                 compileStringNode(sn);
 114             }
 115             break;
 116 
 117         case NodeType.CCLASS:
 118             compileCClassNode((CClassNode)node);
 119             break;
 120 
 121         case NodeType.CTYPE:
 122             compileCTypeNode((CTypeNode)node);
 123             break;
 124 
 125         case NodeType.CANY:
 126             compileAnyCharNode();
 127             break;
 128 
 129         case NodeType.BREF:
 130             compileBackrefNode((BackRefNode)node);
 131             break;
 132 
 133         case NodeType.CALL:
 134             if (Config.USE_SUBEXP_CALL) {
 135                 compileCallNode((CallNode)node);
 136                 break;
 137             } // USE_SUBEXP_CALL
 138             break;
 139 
 140         case NodeType.QTFR:
 141             if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
 142                 compileCECQuantifierNode((QuantifierNode)node);
 143             } else {
 144                 compileNonCECQuantifierNode((QuantifierNode)node);
 145             }
 146             break;
 147 
 148         case NodeType.ENCLOSE:
 149             EncloseNode enode = (EncloseNode)node;
 150             if (enode.isOption()) {
 151                 compileOptionNode(enode);
 152             } else {
 153                 compileEncloseNode(enode);
 154             }
 155             break;
 156 
 157         case NodeType.ANCHOR:
 158             compileAnchorNode((AnchorNode)node);
 159             break;
 160 
 161         default:
 162             // undefined node type
 163             newInternalException(ERR_PARSER_BUG);
 164         } // switch
 165     }
 166 
 167     protected final void compileTreeNTimes(Node node, int n) {
 168         for (int i=0; i<n; i++) compileTree(node);
 169     }
 170 
 171     protected void newSyntaxException(String message) {
 172         throw new SyntaxException(message);
 173     }
 174 
 175     protected void newInternalException(String message) {
 176         throw new InternalException(message);
 177     }
 178 }