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.ast;
  21 
  22 import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;
  23 import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
  24 import jdk.nashorn.internal.runtime.regexp.joni.exception.ValueException;
  25 
  26 public final class BackRefNode extends StateNode {
  27     //private static int NODE_BACKREFS_SIZE = 6;
  28 
  29     //int state;
  30     public int backNum;
  31     public int back[];
  32 
  33     public int nestLevel;
  34 
  35     public BackRefNode(int backNum, int[]backRefs, boolean byName, ScanEnvironment env) {
  36         this.backNum = backNum;
  37         if (byName) setNameRef();
  38 
  39         for (int i=0; i<backNum; i++) {
  40             if (backRefs[i] <= env.numMem && env.memNodes[backRefs[i]] == null) {
  41                 setRecursion(); /* /...(\1).../ */
  42                 break;
  43             }
  44         }
  45 
  46         back = new int[backNum];
  47         System.arraycopy(backRefs, 0, back, 0, backNum); // shall we really dup it ???
  48     }
  49 
  50     // #ifdef USE_BACKREF_AT_LEVEL
  51     public BackRefNode(int backNum, int[]backRefs, boolean byName, boolean existLevel, int nestLevel, ScanEnvironment env) {
  52         this(backNum, backRefs, byName, env);
  53 
  54         if (existLevel) {
  55             //state |= NST_NEST_LEVEL;
  56             setNestLevel();
  57             this.nestLevel = nestLevel;
  58         }
  59     }
  60 
  61     @Override
  62     public int getType() {
  63         return BREF;
  64     }
  65 
  66     @Override
  67     public String getName() {
  68         return "Back Ref";
  69     }
  70 
  71     @Override
  72     public String toString(int level) {
  73         StringBuilder value = new StringBuilder(super.toString(level));
  74         value.append("\n  backNum: " + backNum);
  75         String backs = "";
  76         for (int i=0; i<back.length; i++) backs += back[i] + ", ";
  77         value.append("\n  back: " + backs);
  78         value.append("\n  nextLevel: " + nestLevel);
  79         return value.toString();
  80     }
  81 
  82     public void renumber(int[]map) {
  83         if (!isNameRef()) throw new ValueException(ErrorMessages.ERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED);
  84 
  85         int oldNum = backNum;
  86 
  87         int pos = 0;
  88         for (int i=0; i<oldNum; i++) {
  89             int n = map[back[i]];
  90             if (n > 0) {
  91                 back[pos] = n;
  92                 pos++;
  93             }
  94         }
  95         backNum = pos;
  96     }
  97 
  98 }