All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dragome.compiler.ast.Block Maven / Gradle / Ivy

There is a newer version: 0.96-beta4
Show newest version
package com.dragome.compiler.ast;

import org.w3c.dom.DOMException;

import com.dragome.compiler.generators.AbstractVisitor;
import com.dragome.compiler.utils.Log;

public class Block extends ASTNode
{

	public static int TAG= 0;

	private String label;

	private ASTNode firstChild= null;

	private ASTNode lastChild= null;

	private int childCount= 0;

	public Block()
	{
		super();
	}

	public Block(int theBeginIndex)
	{
		setBeginIndex(theBeginIndex);
	}

	public Block(int theBeginIndex, int theEndIndex)
	{
		this(theBeginIndex);
		setRange(theBeginIndex, theEndIndex);
	}

	public int getTargetPc()
	{
		if (lastChild instanceof Jump)
		{
			return ((Jump) lastChild).getTargetIndex();
		}
		return Integer.MAX_VALUE;
	}

	public int getTargetIndex()
	{
		return beginIndex;
	}

	public void setBeginIndex(int theBeginIndex)
	{
		super.setBeginIndex(theBeginIndex);
	}

	public void visit(AbstractVisitor visitor)
	{
		visitor.visit(this);
	}

	public void appendChildren(ASTNode begin, ASTNode end)
	{
		if (begin == null || end == null)
		{
			throw new RuntimeException("Illegal null parameters");
		}
		if (begin.getParentBlock() != null)
			(begin.getParentBlock()).removeChildren(begin, end);

		if (firstChild == null)
		{
			setFirstChildInternal(begin);
		}
		else
		{
			ASTNode prev= getLastChild();
			prev.setNextSibling(begin);
			begin.setPreviousSibling(prev);
		}
		setLastChildInternal(end);

		ASTNode node= begin;
		while (node != null)
		{
			node.setParentNode(this);
			childCount++;
			if (node == end)
				break;
			node= node.getNextSibling();
		}
	}

	public void appendChildren(Block sourceBlock)
	{
		if (sourceBlock.getChildCount() > 0)
		{
			appendChildren(sourceBlock.getFirstChild(), sourceBlock.getLastChild());
		}
	}

	public ASTNode setChildAt(int index, ASTNode newChild)
	{
		if (index == childCount)
		{
			appendChild(newChild);
			return null;
		}
		else if (index < 0 || index > childCount)
		{
			throw new RuntimeException("Index " + index + " out of range [0, " + childCount + "]");
		}

		return replaceChild(newChild, getChildAt(index));
	}

	public ASTNode getChildAt(int index)
	{
		if (childCount == 0)
		{
			throw new RuntimeException("Requested child at index " + index + ", but block has no children");
		}
		if (index < 0 || index >= childCount)
		{
			throw new RuntimeException("Index " + index + " out of range [0, " + (childCount - 1) + "]");
		}

		if (index == childCount - 1)
		{
			return getLastChild();
		}

		ASTNode node= getFirstChild();
		int i= 0;
		while (i < index)
		{
			i++;
			node= node.getNextSibling();
		}

		return node;
	}

	public ASTNode appendChild(ASTNode newChild)
	{
		Log.getLogger().debug("Appending " + newChild + " to " + this);

		unlink(newChild);

		if (firstChild == null)
		{
			newChild.setPreviousSibling(null);
			setFirstChildInternal(newChild);
		}
		else
		{
			ASTNode prev= getLastChild();
			prev.setNextSibling(newChild);
			newChild.setPreviousSibling(prev);
		}
		setLastChildInternal(newChild);
		newChild.setParentNode(this);
		childCount++;

		return newChild;
	}

	public ASTNode replaceChild(ASTNode newChild, ASTNode oldChild)
	{
		Log.getLogger().debug("Replacing " + oldChild + " by " + newChild + " in " + this);
		if (oldChild.getParentNode() != this)
		{
			throw new DOMException(DOMException.NOT_FOUND_ERR, "Node " + oldChild + " is not a child of " + this);
		}
		unlink(newChild);
		if (oldChild.getPreviousSibling() != null)
		{
			oldChild.getPreviousSibling().setNextSibling(newChild);
		}
		if (oldChild.getNextSibling() != null)
		{
			oldChild.getNextSibling().setPreviousSibling(newChild);
		}
		newChild.setPreviousSibling(oldChild.getPreviousSibling());
		newChild.setNextSibling(oldChild.getNextSibling());
		newChild.setParentNode(this);
		if (getFirstChild() == oldChild)
		{
			setFirstChildInternal(newChild);
		}
		if (getLastChild() == oldChild)
		{
			setLastChildInternal(newChild);
		}
		oldChild.setPreviousSibling(null);
		oldChild.setNextSibling(null);
		oldChild.setParentNode(null);
		return oldChild;
	}

	public ASTNode removeChild(ASTNode oldChild)
	{
		Log.getLogger().debug("Removing " + oldChild + " from " + this);
		removeChildren(oldChild, oldChild);

		oldChild.setPreviousSibling(null);
		oldChild.setNextSibling(null);
		return oldChild;
	}

	private void removeChildren(ASTNode begin, ASTNode end)
	{
		if (begin == null || end == null)
			throw new RuntimeException("Illegal null parameters");
		ASTNode node= begin;
		while (node != null)
		{
			if (node.getParentNode() != this)
			{
				throw new DOMException(DOMException.NOT_FOUND_ERR, "Node " + node + " is not a child of " + this);
			}
			node.setParentNode(null);
			childCount--;
			if (node == end)
				break;
			node= node.getNextSibling();
		}

		if (node != end)
		{
			throw new RuntimeException("Node " + end + " is not a right-sibling of " + begin);
		}

		if (begin.getPreviousSibling() != null)
		{
			begin.getPreviousSibling().setNextSibling(end.getNextSibling());
		}
		if (end.getNextSibling() != null)
		{
			end.getNextSibling().setPreviousSibling(begin.getPreviousSibling());
		}
		if (getFirstChild() == begin)
		{
			setFirstChildInternal(end.getNextSibling());
		}
		if (getLastChild() == end)
		{
			setLastChildInternal(begin.getPreviousSibling());
		}
	}

	public void removeChildren()
	{
		if (getFirstChild() != null)
		{
			removeChildren(getFirstChild(), getLastChild());
		}
	}

	public int getChildCount()
	{
		return childCount;
	}

	public ASTNode insertBefore(ASTNode newChild, ASTNode refChild)
	{
		if (refChild == null)
		{
			return appendChild(newChild);
		}

		Log.getLogger().debug("Inserting " + newChild + " before " + refChild + " in " + this);

		if (refChild.getParentNode() != this)
		{
			throw new DOMException(DOMException.NOT_FOUND_ERR, "Reference " + refChild + " is not a child of " + this);
		}

		unlink(newChild);

		if (refChild.getPreviousSibling() != null)
		{
			refChild.getPreviousSibling().setNextSibling(newChild);
		}
		newChild.setPreviousSibling(refChild.getPreviousSibling());
		newChild.setNextSibling(refChild);
		newChild.setParentNode(this);
		childCount++;

		refChild.setPreviousSibling(newChild);

		if (getFirstChild() == refChild)
		{
			setFirstChildInternal(newChild);
		}

		return newChild;
	}

	public void addStatements(java.util.List statements)
	{
		for (int i= 0; i < statements.size(); i++)
		{
			appendChild((ASTNode) statements.get(i));
		}
	}

	public ASTNode getFirstChild()
	{
		return firstChild;
	}

	public ASTNode getLastChild()
	{
		return lastChild;
	}

	private void setFirstChildInternal(ASTNode newFirstChild)
	{
		firstChild= newFirstChild;
		if (firstChild != null)
		{
			firstChild.setPreviousSibling(null);
			beginIndex= Math.min(beginIndex, firstChild.getBeginIndex());
		}
	}

	private void setLastChildInternal(ASTNode newLastChild)
	{
		lastChild= newLastChild;
		if (lastChild != null)
		{
			lastChild.setNextSibling(null);
			endIndex= Math.max(endIndex, lastChild.getEndIndex());
		}
	}

	private void unlink(ASTNode node)
	{
		if (node.getParentBlock() != null)
		{
			node.getParentBlock().removeChild(node);
		}
	}

	public String getLabel()
	{
		if (label == null)
			throw new RuntimeException("Statement is not labeled");
		return label;
	}

	public void setLabel(String theLabel)
	{
		label= theLabel;
	}

	public boolean isLabeled()
	{
		return label != null;
	}

	public String setLabeled()
	{
		if (label == null)
			label= "L" + (++TAG);
		return label;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy