/* * Copyright (c) 2013-2017 Cinchapi Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.cinchapi.concourse.lang.ast; import java.util.Collection; import java.util.Collections; import java.util.List; import javax.annotation.concurrent.Immutable; import com.cinchapi.concourse.lang.Symbol; import com.google.common.base.Objects; import com.google.common.collect.Lists; /** * An {@link AST} is a generic abstract syntax tree that can be used to * represent a statement in the language. * <p> * Each {@link AST} contains a single {@link Symbol} and any number of * {@link #children} nodes. If the tree contains no children, it is considered a * "leaf". This property can be checked by the {@link #isLeaf()} method. * </p> * * @author Jeff Nelson */ @Immutable public abstract class AST { /** * The list of this AST's children in order from left to right. */ private final List<AST> children = Lists.newArrayList(); /** * The symbol that is held in this {@link AST}. */ private final Symbol symbol; /** * Construct a new instance. * * @param children */ protected AST(Symbol symbol, AST... children) { this.symbol = symbol; for (AST child : children) { this.children.add(child); } } @Override public boolean equals(Object obj) { if(obj.getClass() == this.getClass()) { return Objects.equal(symbol, ((AST) obj).symbol) && Objects.equal(children, ((AST) obj).children); } return false; } /** * Return the {@link Symbol} that is contained in this {@link AST} node. * * @return the symbol */ public Symbol getSymbol() { return symbol; } @Override public int hashCode() { return Objects.hashCode(symbol, children); } /** * Return {@code true} if this {@link AST} has no children and is therefore * considered a leaf node. * * @return {@code true} if this AST is considered a leaf node */ public boolean isLeaf() { return children.isEmpty(); } /** * Return an list of this {@link AST}'s children. The list will * contain the children of this node from left to right. * * @return an iterator for the children */ protected Collection<AST> children() { return Collections.unmodifiableList(children); } }