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 java.util.Set;
  23 import jdk.nashorn.internal.runtime.regexp.joni.WarnCallback;
  24 import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
  25 import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
  26 
  27 @SuppressWarnings("javadoc")
  28 public final class ConsAltNode extends Node {
  29     public Node car;
  30     public ConsAltNode cdr;
  31     private int type;           // List or Alt
  32 
  33     private ConsAltNode(final Node car, final ConsAltNode cdr, final int type) {
  34         this.car = car;
  35         if (car != null) {
  36             car.parent = this;
  37         }
  38         this.cdr = cdr;
  39         if (cdr != null) {
  40             cdr.parent = this;
  41         }
  42 
  43         this.type = type;
  44     }
  45 
  46     public static ConsAltNode newAltNode(final Node left, final ConsAltNode right) {
  47         return new ConsAltNode(left, right, ALT);
  48     }
  49 
  50     public static ConsAltNode newListNode(final Node left, final ConsAltNode right) {
  51         return new ConsAltNode(left, right, LIST);
  52     }
  53 
  54     public static ConsAltNode listAdd(final ConsAltNode listp, final Node x) {
  55         final ConsAltNode n = newListNode(x, null);
  56         ConsAltNode list = listp;
  57 
  58         if (list != null) {
  59             while (list.cdr != null) {
  60                 list = list.cdr;
  61             }
  62             list.setCdr(n);
  63         }
  64         return n;
  65     }
  66 
  67     public void toListNode() {
  68         type = LIST;
  69     }
  70 
  71     public void toAltNode() {
  72         type = ALT;
  73     }
  74 
  75     @Override
  76     public int getType() {
  77         return type;
  78     }
  79 
  80     @Override
  81     protected void setChild(final Node newChild) {
  82         car = newChild;
  83     }
  84 
  85     @Override
  86     protected Node getChild() {
  87         return car;
  88     }
  89 
  90     @Override
  91     public void swap(final Node with) {
  92         if (cdr != null) {
  93             cdr.parent = with;
  94             if (with instanceof ConsAltNode) {
  95                 final ConsAltNode withCan = (ConsAltNode)with;
  96                 withCan.cdr.parent = this;
  97                 final ConsAltNode tmp = cdr;
  98                 cdr = withCan.cdr;
  99                 withCan.cdr = tmp;
 100             }
 101         }
 102         super.swap(with);
 103     }
 104 
 105     @Override
 106     public void verifyTree(final Set<Node> set, final WarnCallback warnings) {
 107         if (!set.contains(this)) {
 108             set.add(this);
 109             if (car != null) {
 110                 if (car.parent != this) {
 111                     warnings.warn("broken list car: " + this.getAddressName() + " -> " +  car.getAddressName());
 112                 }
 113                 car.verifyTree(set,warnings);
 114             }
 115             if (cdr != null) {
 116                 if (cdr.parent != this) {
 117                     warnings.warn("broken list cdr: " + this.getAddressName() + " -> " +  cdr.getAddressName());
 118                 }
 119                 cdr.verifyTree(set,warnings);
 120             }
 121         }
 122     }
 123 
 124     public Node setCar(final Node ca) {
 125         car = ca;
 126         ca.parent = this;
 127         return car;
 128     }
 129 
 130     public ConsAltNode setCdr(final ConsAltNode cd) {
 131         cdr = cd;
 132         cd.parent = this;
 133         return cdr;
 134     }
 135 
 136     @Override
 137     public String getName() {
 138         switch (type) {
 139         case ALT:
 140             return "Alt";
 141         case LIST:
 142             return "List";
 143         default:
 144             throw new InternalException(ErrorMessages.ERR_PARSER_BUG);
 145         }
 146     }
 147 
 148     @Override
 149     public String toString(final int level) {
 150         final StringBuilder value = new StringBuilder();
 151         value.append("\n  car: ").append(pad(car, level + 1));
 152         value.append("\n  cdr: ").append(cdr == null ? "NULL" : cdr.toString());
 153 
 154         return value.toString();
 155     }
 156 
 157 }