org.codehaus.groovy.syntax.Reduction Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of groovy-all Show documentation
Show all versions of groovy-all Show documentation
Groovy: A powerful, dynamic language for the JVM
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.codehaus.groovy.syntax;
import org.codehaus.groovy.GroovyBugError;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
/**
* A syntax reduction, produced by the Parser
.
*
* @see antlr.Parser
* @see Token
* @see CSTNode
* @see Types
*
* @author bob mcwhirter
* @author Chris Poirier
*/
public class Reduction extends CSTNode
{
public static final Reduction EMPTY = new Reduction();
//---------------------------------------------------------------------------
// INITIALIZATION AND SUCH
private List elements = null; // The set of child nodes
private boolean marked = false; // Used for completion marking by some parts of the parser
/**
* Initializes the Reduction
with the specified root.
*/
public Reduction( Token root )
{
elements = new ArrayList();
set( 0, root );
}
/**
* Initializes the Reduction
to empty.
*/
private Reduction()
{
elements = Collections.EMPTY_LIST;
}
/**
* Creates a new Reduction
with Token.NULL
* as it's root.
*/
public static Reduction newContainer()
{
return new Reduction( Token.NULL );
}
//---------------------------------------------------------------------------
// MEMBER ACCESS
/**
* Returns true if the node is completely empty (no root, even).
*/
public boolean isEmpty()
{
return size() == 0;
}
/**
* Returns the number of elements in the node.
*/
public int size()
{
return elements.size();
}
/**
* Returns the specified element, or null.
*/
public CSTNode get( int index )
{
CSTNode element = null;
if( index < size() )
{
element = (CSTNode)elements.get( index );
}
return element;
}
/**
* Returns the root of the node, the Token that indicates it's
* type. Returns null if there is no root (usually only if the
* node is a placeholder of some kind -- see isEmpty()).
*/
public Token getRoot()
{
if( size() > 0 )
{
return (Token)elements.get(0);
}
else
{
return null;
}
}
/**
* Marks the node a complete expression.
*/
public void markAsExpression()
{
marked = true;
}
/**
* Returns true if the node is a complete expression.
*/
public boolean isAnExpression()
{
if( isA(Types.COMPLEX_EXPRESSION) )
{
return true;
}
return marked;
}
//---------------------------------------------------------------------------
// OPERATIONS
/**
* Adds an element to the node.
*/
public CSTNode add( CSTNode element )
{
return set( size(), element );
}
/**
* Sets an element in at the specified index.
*/
public CSTNode set( int index, CSTNode element )
{
if( elements == null )
{
throw new GroovyBugError( "attempt to set() on a EMPTY Reduction" );
}
if( index == 0 && !(element instanceof Token) )
{
//
// It's not the greatest of design that the interface allows this, but it
// is a tradeoff with convenience, and the convenience is more important.
throw new GroovyBugError( "attempt to set() a non-Token as root of a Reduction" );
}
//
// Fill slots with nulls, if necessary.
int count = elements.size();
if( index >= count )
{
for( int i = count; i <= index; i++ )
{
elements.add( null );
}
}
//
// Then set in the element.
elements.set( index, element );
return element;
}
/**
* Removes a node from the Reduction
. You cannot remove
* the root node (index 0).
*/
public CSTNode remove( int index )
{
if( index < 1 )
{
throw new GroovyBugError( "attempt to remove() root node of Reduction" );
}
return (CSTNode)elements.remove( index );
}
/**
* Creates a Reduction
from this node. Returns self if the
* node is already a Reduction
.
*/
public Reduction asReduction()
{
return this;
}
}