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